1. ZyX_I
  2. frawor

Commits

ZyX_I  committed e44b675

@/fwc: Added partial prefixes implementation (untested)

  • Participants
  • Parent commits db2c931
  • Branches default

Comments (0)

Files changed (2)

File plugin/frawor/fwc/compiler.vim

View file
             \   'notfail': '`not'' check failed',
             \     'isnot': 'expected %s, but got %s',
             \       'anf': '`%s'' is not a valid action',
+            \       'pnf': 'prefix not found',
         \}, '"Error while processing check %s for %s: ".v:val'))
 let s:_messages._types=['number', 'string', 'function reference', 'list',
             \           'dictionary']
     for sub in a:subscripts
         let tsub=type(sub)
         if tsub==type('')
-            if sub=~#'^\w\+$'
-                let r.='.'.sub
-            else
-                let r.='['.s:F.string(sub).']'
-            endif
+            let r.=((sub=~#'\W')?('['.s:F.string(sub).']'):
+                        \        ('.'.sub))
         elseif tsub==type(0)
             let r.='['.sub.']'
         elseif tsub==type([])
     endif
     return self
 endfunction
+"▶1 getfunstatvar  :: varname, varinit + self → varstr + self
+function s:compiler.getfunstatvar(name, init)
+    let id=printf('%x', self.vids[a:name])
+    let self.vids[a:name]+=1
+    if !has_key(self.vars, a:name)
+        let self.vars[a:name]={}
+    endif
+    let self.vars[a:name][id]=a:init
+    return '@%@'.self.getsubs([a:name, id])
+endfunction
 "▶1 compileadesc   :: adescr[, idx[, purgemax]] + self → self + self
 let s:actdefmatcher=['matcher', ['intfunc', 'start', 0, 0]]
+let s:prefdefmatcher=s:actdefmatcher
 function s:compiler.compileadesc(adescr, ...)
     let purgemax=get(a:000, 1, 0)
     "▶2 Length checks
     endif
     "▶2 `prefixes' key
     if has_key(a:adescr, 'prefixes')
+        unlet nextsub
+        let nextsub=copy(caidx)
+        let preflist=[]
+        let plstr=self.getfunstatvar('prefixes', preflist)
+        let prefdictstr=self.getlvarid('prefdict')
+        let base=self.argstr(0, self.subs[:-2])
+        let addtry=(has_key(a:adescr, 'next') || has_key(a:adescr, 'actions'))
+        if addtry
+            if !addedsavemsgs
+                call self.addsavemsgs()
+                let addedsavemsgs=1
+            endif
+            call self.try().pushms('throw')
+        endif
+        let dstr=self.getlvarid('d')
+        let astr=dstr.'.arg'
+        let idx=get(a:000, 0, '').'(prefixes)'
+        call self.let(prefdictstr, '{}')
+                    \.let(dstr, '{}')
+                    \.call('insert('.base.', '.prefdictstr.', '.
+                    \                s:F.getsub(nextsub).')')
+                    \.increment(caidxstr)
+        let defaults=filter(copy(a:adescr.prefixes),
+                    \       'exists("v:val[2][0]") && v:val[2][0] isnot "arg"')
+        let haslist=!empty(filter(copy(a:adescr.prefixes), 'v:val[1].list'))
+        for [prefix, prefopts, defval; dummylist] in defaults
+            call self.let(prefdictstr.self.getsubs([prefix]),
+                        \ self.getvar(defval))
+        endfor
+        call self.while('len('.base.')>'.caidxstr)
+        if !self.o.onlystrings
+            call self.addtypecond([type('')], idx)
+        endif
+        if haslist
+            " TODO
+        endif
+        call self.let(astr, self.getmatcher(get(a:adescr, 'prefixesmatcher',
+                    \                           s:prefdefmatcher), plstr,
+                    \                       'remove('.base.', '.caidxstr.')'))
+                    \.nextthrow(astr.' is 0', 'pnf', idx)
+        for [prefix, prefopts; args] in a:adescr.prefixes
+            call add(preflist, prefix)
+            if prefopts.alt
+                call add(preflist, 'no'.prefix)
+            endif
+            let prefstr=prefdictstr.self.getsubs([prefix])
+            if !empty(args) && args[0][0] isnot 'arg'
+                call remove(args, 0)
+            endif
+            call self.addif(astr.' is '.s:F.string(prefix))
+            " TODO prefopts.list
+            for i in range(1, prefopts.argnum)
+                call self.compilearg(args[i-1], idx.s:F.string(prefix))
+                            \.incsub()
+            endfor
+            if !prefopts.list && prefopts.argnum==1
+                call self.let(prefstr, 'remove('.base.', '.caidxstr.')')
+            elseif prefopts.argnum>0
+                call self.let(prefstr, 'remove('.base.', '.caidxstr.', '.
+                            \                  caidxstr.'+'.(prefopts.argnum-1).
+                            \                ')')
+            else
+                call self.let(prefstr, 1)
+            endif
+            let self.subs[-1]=copy(caidx)
+            call self.up()
+            if prefopts.alt
+                call self.addif(astr.' is '.s:F.string('no'.prefix))
+                            \.let(prefstr, 0)
+                            \.up()
+            endif
+        endfor
+        call self.up()
+        if addtry
+            call self.addrestmsgs(1).catch(s:cfreg).popms()
+                        \.if('has_key('.dstr.', "arg")')
+                            \.call('insert('.base.', '.astr.')')
+                        \.up().up()
+        endif
         " TODO
     endif
     "▶2 `next' key
                     \.increment(caidxstr)
                     \.up()
         if has_key(a:adescr, 'actions')
-            call self.catch(s:cfreg).popms().up()
+            call self.addrestmsgs(1).catch(s:cfreg).popms().up()
         endif
     endif
     "▶2 `actions' key
         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]')
+        let fsastr=self.getfunstatvar('actions', map(copy(actions), 'v:val[0]'))
         if noact isnot 0
             call self.try().pushms('throw')
         endif
         let curargstr=self.argstr()
         call self.let(actionstr, self.getmatcher(get(a:adescr, 'actionsmatcher',
                     \                                s:actdefmatcher),
-                    \                            '@%@.actions.'.actid,
-                    \                            curargstr))
+                    \                            fsastr, curargstr))
                     \.nextthrow(actionstr.' is 0', 'anf', idx, curargstr)
                     \.let(curargstr, actionstr)
         unlet curargstr
                 \   'type': a:type,
                 \   'subs': [],
                 \   'vars': a:vars,
-                \   'vids': {'actions': 0},
+                \   'vids': {'actions': 0, 'prefixes': 0},
                 \'argbase': '@@@',
                 \  'preva': [],
                 \   'msgs': {'savevars': [],

File plugin/frawor/fwc/parser.vim

View file
     return self.conclose()
 endfunction
 "▶1 scanpref   :: &self
-" Input: {omtchr} ({prefdescr} ( "-" | {arg} ) )* "}"?
+" Input: {omtchr} ({prefdescr} ( "-" | {arg} )* )* "}"?
 "        {prefdescr} :: {prefopts}? ( {str} | {wordchar}+ )
 "         {prefopts} :: ( "?" | "!" | "*" | "+" {digit}+ )* ( ":" {var} )?
 " Output: context(prefixes[, {matcher}], {prefix}*)
-"           {prefix} :: context(prefix, String, {prefopts}[, {var}][, {arg}+])
+"           {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}