Commits

ZyX_I committed 11fa476

@/fwc: Implemented actions

Comments (0)

Files changed (5)

plugin/frawor/fwc/compiler.vim

             \    'nmatch': 'no matches found for %s',
             \   'notfail': '`not'' check failed',
             \     'isnot': 'expected %s, but got %s',
+            \       'anf': '`%s'' is not a valid action',
         \}, '"Error while processing check %s for %s: ".v:val'))
 let s:_messages._types=['number', 'string', 'function reference', 'list',
             \           'dictionary']
             endif
             if arg[0] is 'actions' || arg[0] is 'prefixes'
                 if get(get(arg, 1, []), 0, '') is 'matcher'
-                    let sq[arg[0].'matcher']=remove(arg, 1)[1:]
+                    let sq[arg[0].'matcher']=remove(arg, 1)
                 endif
                 call extend(sq[arg[0]], filter(map(arg[1:], 'v:val[1:]'),
                             \                  '!empty(v:val)'))
                 let hasa=1
             endif
             if len(action)>1
-                let [namin, namax]=s:F.getlenrange(action[1])
+                let [namin, namax]=s:F.getlenrange(action[-1])
                 if namin<amin || !minset
                     let minset=1
                     let amin=namin
     return self
 endfunction
 "▶1 compileadesc   :: adescr[, idx[, purgemax]] + self → self + self
+let s:actdefmatcher=['matcher', ['intfunc', 'start', 0, 0]]
 function s:compiler.compileadesc(adescr, ...)
     let purgemax=get(a:000, 1, 0)
-    if !self.o.only
+    "▶2 Length checks
+    if !empty(self.subs)
         if !has_key(a:adescr, 'minimum')
             call s:F.getlenrange(a:adescr)
         endif
             let a:adescr.checkedfor=1
         endif
     endif
+    "▲2
     if !empty(self.subs)
         let nextsub=copy(self.subs[-1])
     endif
+    "▶2 `arg' key
     if has_key(a:adescr, 'arg')
         let i=0
         for arg in a:adescr.arg
             let nextsub=copy(self.subs[-1])
         endif
     endif
+    "▶2 Quit if no more keys are present or if we are checking the only argument
     if empty(self.subs) || empty(a:adescr)
                 \|| !(has_key(a:adescr, 'optional')
                 \  || has_key(a:adescr, 'next')
                 \  || has_key(a:adescr, 'actions'))
         return self
     endif
+    "▲2
     let addedsavemsgs=0
     let caidxstr=self.getlvarid('caidx')
     let caidx=[caidxstr]
+    let oldsub=s:F.getsub(nextsub)
+    if oldsub isnot caidxstr
+        call self.let(caidxstr, oldsub)
+    endif
+    let self.subs[-1]=copy(caidx)
+    "▶2 `optinal' key
     if has_key(a:adescr, 'optional')
-        call self.let(caidxstr, s:F.getsub(nextsub))
-        let self.subs[-1]=copy(caidx)
         unlet nextsub
         let nextsub=copy(caidx)
         let lopt=len(a:adescr.optional)
             endfor
         endif
     endif
+    "▶2 `prefixes' key
     if has_key(a:adescr, 'prefixes')
         " TODO
     endif
+    "▶2 `next' key
     if has_key(a:adescr, 'next')
-        let oldsub=s:F.getsub(nextsub)
-        if oldsub isnot caidxstr
-            call self.let(caidxstr, oldsub)
-        endif
-        let self.subs[-1]=copy(caidx)
         unlet nextsub
         let nextsub=copy(caidx)
         if has_key(a:adescr, 'actions')
             call self.catch(s:cfreg).popms().up()
         endif
     endif
+    "▶2 `actions' key
     if has_key(a:adescr, 'actions')
-        " TODO
+        unlet nextsub
+        let nextsub=copy(caidx)
+        let actionstr=self.getlvarid('action')
+        let actid=printf('%x', self.vids.actions)
+        let self.vids.actions+=1
+        if !has_key(self.vars, 'actions')
+            let self.vars.actions={}
+        endif
+        let actions=filter(copy(a:adescr.actions), 'v:val[0] isnot 0')
+        let noact=get(filter(copy(a:adescr.actions), 'v:val[0] is 0'), 0, 0)
+        let self.vars.actions[actid]=map(copy(actions), 'v:val[0]')
+        if noact isnot 0
+            call self.try().pushms('throw')
+        endif
+        let idx=get(a:000, 0, '').'(actions)'
+        if !self.o.onlystrings
+            call self.addtypecond([type('')], idx)
+        endif
+        let curargstr=self.argstr()
+        call self.let(actionstr, self.getmatcher(get(a:adescr, 'actionsmatcher',
+                    \                                s:actdefmatcher),
+                    \                            '@%@.actions.'.actid,
+                    \                            curargstr))
+                    \.nextthrow(actionstr.' is 0', 'anf', idx, curargstr)
+                    \.let(curargstr, actionstr)
+        unlet curargstr
+        call self.incsub()
+        let astartsub=copy(self.subs[-1])
+        for action in actions
+            call self.addif(actionstr.' is '.string(action[0]))
+            if len(action)>1
+                call self.compileadesc(action[1], idx.'.'.s:F.string(action[0]))
+            endif
+            call self.let(caidxstr, s:F.getsub(self.subs[-1]))
+                        \.up()
+            let self.subs[-1]=copy(astartsub)
+        endfor
+        if noact isnot 0
+            call self.popms().catch(s:cfreg)
+            call self.incsub(-1)
+            if len(noact)>1
+                call self.compileadesc(noact[1], idx.'.nullact')
+                            \.let(caidxstr, s:F.getsub(self.subs[-1]))
+            endif
+            let self.subs[-1]=copy(astartsub)
+            call self.up().up()
+        endif
+        let self.subs[-1]=copy(caidx)
     endif
+    "▶2 Check for processed argument length
     " XXX a:0 is checked here
     if !a:0 && type(self.subs[-1])==type([])
         let largsstr=self.getlargsstr()
         call self.addif(proclen.' isnot '.largsstr)
                     \.addthrow('lennmatch', 0, proclen, largsstr)
     endif
+    "▶2 addrestmsgs
     if addedsavemsgs
         call self.addrestmsgs()
     endif
+    "▲2
     return self
 endfunction
 "▶1 compilestr     :: vars, String, type, doreturn → [String]
                 \   'type': a:type,
                 \   'subs': [],
                 \   'vars': a:vars,
-                \   'vids': {},
+                \   'vids': {'actions': 0},
                 \'argbase': '@@@',
                 \  'preva': [],
                 \   'msgs': {'savevars': [],

plugin/frawor/fwc/intfuncs.vim

 " Checks whether {argument} is either 0 or 1
 function s:r.bool.check(desc, idx, type)
     let curargstr=self.argstr()
-    return self.nextthrow('index([0, 1], '.curargstr.')==-1',
+    if !has_key(self.vars, 'bool')
+        let self.vars.bool=((self.o.onlystrings)?(["0", "1"]):([0, 1]))
+    endif
+    return self.nextthrow('index(@%@.bool, '.curargstr.')==-1',
                 \         'nbool', a:idx, 'string('.curargstr.')')
 endfunction
 " Transforms {argument} to 0 if it is empty and to 1 otherwise

plugin/frawor/fwc/parser.vim

     return self.conclose()
 endfunction
 "▶1 scanpref   :: &self
-" Input: ({prefdescr} ( "-" | {arg} ) )* "}"?
+" Input: {omtchr} ({prefdescr} ( "-" | {arg} ) )* "}"?
 "        {prefdescr} :: {prefopts}? ( {str} | {wordchar}+ )
 "         {prefopts} :: ( "?" | "!" | "*" | "+" {digit}+ )* ( ":" {var} )?
-" Output: context(prefixes, context(String, {prefopts}[, {var}][, {arg}+]))
+" Output: context(prefixes[, {matcher}], {prefix}*)
+"           {prefix} :: context(prefix, String, {prefopts}[, {var}][, {arg}+])
 "         {prefopts} :: { "alt": Bool, "list": Bool, "opt": Bool,
 "                         "argnum": UInt }
 let s:defprefopts={'alt': 0, 'list': 0, 'opt': 0, 'argnum': 1}
 function s:parser.scanpref()
-    call self.addcon('prefixes')
-    let c=self.readc()
-    if c is '~'
-        call self.getmatcher()
-    else
-        call self.ungetc(c)
-    endif
+    call self.addcon('prefixes').getomtchr()
     let prevlen=-1
     while self.len && prevlen!=self.len
         let prevlen=self.len
     return self.conclose()
 endfunction
 "▶1 scanact    :: &self
-" Input: "~" {matcher} ( {actdescr} ( "-" | "(" {arg}* ")"? | {arg} ) )* ">"?
+" Input: {omtchr} ( {actdescr} ( "-" | "(" {arg}* ")"? | {arg} ) )* ">"?
 "        {actdescr} :: {str}
 "                    | {wordchar}+
 " Output: context(actions[, {matcher}],
-"                 (context(action, 0|String|{arg}, {arg}*))
+"                 (context(action, 0|String|{arg}, {arg}*))*)
 function s:parser.scanact()
-    call self.addcon('actions')
-    let c=self.readc()
-    if c is '~'
-        call self.getmatcher()
-    else
-        call self.ungetc(c)
-    endif
+    call self.addcon('actions').getomtchr()
     let hasaction=0
     let prevlen=-1
     while self.len && prevlen!=self.len
 plugin/frawor/fwc/compiler:nbool
 plugin/frawor/fwc/compiler:nreg
 plugin/frawor/fwc/compiler:nbool
+::: Section <Actions>
+plugin/frawor/fwc/compiler:invlen
+plugin/frawor/fwc/compiler:invlen
+plugin/frawor/fwc/compiler:invlen
+plugin/frawor/fwc/compiler:invlen
+plugin/frawor/fwc/compiler:anf
+plugin/frawor/fwc/compiler:anf
+plugin/frawor/fwc/compiler:nreg
+plugin/frawor/fwc/compiler:anf
+plugin/frawor/fwc/compiler:invlen
+plugin/frawor/fwc/compiler:anf
 <<< messages

test/fwctests.dat

 ['[isreg]+bool',                         'check'], [1, 0],       1
 ['[isreg]+bool',                         'check'], [],           1
 ['[isreg]+bool',                         'check'], [''],         1
+#▶1 Actions
+['<abc (bool) def (bool bool) ghi (isreg)>', 'filter'], ['a', 2],  ['abc', 1]
+['<abc (bool) def (bool bool) ghi (isreg)>', 'filter'], ['d', 2],  0
+['<abc (bool) def (bool bool) ghi (isreg)>', 'filter'], ['g', ''], ['ghi', '']
+['<abc (bool) def (bool bool) - (isreg)>',   'filter'], ['a', 2],  ['abc', 1]
+['<abc (bool) def (bool bool) - (isreg)>',   'filter'], ['d', 2],  0
+['<abc (bool) def (bool bool) - (isreg)>',   'filter'], ['g', ''], 0
+['<abc (bool) def (bool bool) - (isreg)>',   'filter'], ['g'],     ['g']
+['<abc (bool) def (bool bool) - (isreg)>',   'filter'], ['\v('],   0
+['<abc (bool) def (bool bool) - (isreg)>',   'filter'], ['b', ''], 0
+['<~smart abc (bool)>',                      'filter'], ['b', ''], ['abc', 0]
 # vim: cms=#%s fmr=▶,▲
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.