Last active
December 13, 2015 19:59
-
-
Save ynkdir/4966998 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
" PROTOTYPE WORK IN PROGRESS | |
" (function) | |
" (delfunction) | |
" (return) | |
" (call) | |
" (let) | |
" (unlet) | |
" (lockvar) | |
" (unlockvar) | |
" (if) | |
" (while) | |
" (for) | |
" (continue) | |
" (break) | |
" (try) | |
" (throw) | |
" (echo) | |
" (echon) | |
" (echohl) | |
" (echomsg) | |
" (echoerr) | |
" (execute) | |
function! s:decho(msg, hl) | |
execute 'echohl ' . a:hl | |
echo a:msg | |
echohl None | |
endfunction | |
let s:NIL = {} | |
let s:VimLParser = {} | |
function s:VimLParser.new(...) | |
let obj = copy(self) | |
call call(obj.__init__, a:000, obj) | |
return obj | |
endfunction | |
function s:VimLParser.__init__() | |
endfunction | |
function s:VimLParser.node(type, value) | |
return {'type': a:type, 'value': a:value} | |
endfunction | |
function s:VimLParser.push_context(type, value) | |
let ctx = {'type': a:type, 'value': a:value, 'body': []} | |
call insert(self.stack, ctx, 0) | |
endfunction | |
function s:VimLParser.pop_context() | |
return remove(self.stack, 0) | |
endfunction | |
function s:VimLParser.find_context(pat) | |
let i = 0 | |
for ctx in self.stack | |
if ctx.type =~ a:pat | |
return i | |
endif | |
let i += 1 | |
endfor | |
return -1 | |
endfunction | |
function s:VimLParser.add_node(node) | |
call add(self.stack[0].body, a:node) | |
endfunction | |
function s:VimLParser.parse(lines) | |
let self.stack = [] | |
call self.push_context('TOPLEVEL', []) | |
let self.reader = s:StringReader.new(join(a:lines, "\n")) | |
while self.reader.peek() != '' | |
call s:decho(printf('%d: %s', self.reader.getpos()[1], self.reader.peekline()), 'Comment') | |
call self.parse_one_cmd() | |
endwhile | |
let ctx = self.pop_context() | |
return self.node('TOPLEVEL', ctx.body) | |
endfunction | |
function s:VimLParser.parse_one_cmd() | |
let self.ea = {} | |
let self.ea.forceit = 0 | |
let self.ea.addr_count = 0 | |
let self.ea.line1 = 0 | |
let self.ea.line2 = 0 | |
let self.ea.flags = 0 | |
let self.ea.do_ecmd_cmd = '' | |
let self.ea.do_ecmd_lnum = 0 | |
let self.ea.append = 0 | |
let self.ea.usefilter = 0 | |
let self.ea.amount = 0 | |
let self.ea.regname = 0 | |
let self.ea.regname = 0 | |
let self.ea.force_bin = 0 | |
let self.ea.read_edit = 0 | |
let self.ea.force_ff = 0 | |
let self.ea.force_enc = 0 | |
let self.ea.bad_char = 0 | |
let self.ea.linepos = [] | |
let self.ea.cmdpos = [] | |
let self.ea.argpos = [] | |
let self.ea.cmd = {} | |
let self.ea.modifiers = [] | |
let self.ea.range = [] | |
if self.reader.peek(2) == '#!' | |
call self.parse_hashbang() | |
return | |
endif | |
call self.skip_white_and_colon() | |
if self.reader.peek() =~ '^$\|\n' | |
call self.reader.readline() | |
return | |
endif | |
if self.reader.peek() == '"' | |
call self.parse_comment() | |
return | |
endif | |
let self.ea.linepos = self.reader.getpos() | |
call self.parse_command_modifiers() | |
call self.parse_range() | |
call self.parse_command() | |
endfunction | |
" FIXME: | |
function s:VimLParser.parse_command_modifiers() | |
let modifiers = [] | |
while 1 | |
let pos = self.reader.getpos() | |
if self.reader.peek() =~ '\d' | |
let d = self.read_digits() | |
call self.skip_white() | |
else | |
let d = '' | |
endif | |
let k = self.read_alpha() | |
let c = self.reader.peek() | |
call self.skip_white() | |
if k =~# '^abo\%[veleft]$' | |
call add(modifiers, {'name': 'aboveleft'}) | |
elseif k =~# '^bel\%[owright]$' | |
call add(modifiers, {'name': 'belowright'}) | |
elseif k =~# '^bro\%[wse]$' | |
call add(modifiers, {'name': 'browse'}) | |
elseif k =~# '^bo\%[tright]$' | |
call add(modifiers, {'name': 'botright'}) | |
elseif k =~# '^conf\%[irm]$' | |
call add(modifiers, {'name': 'confirm'}) | |
elseif k =~# '^kee\%[pmarks]$' | |
call add(modifiers, {'name': 'keepmarks'}) | |
elseif k =~# '^keepa\%[lt]$' | |
call add(modifiers, {'name': 'keepalt'}) | |
elseif k =~# '^keepj\%[umps]$' | |
call add(modifiers, {'name': 'keepjumps'}) | |
elseif k =~# '^hid\%[e]$' | |
if self.ends_excmds(c) | |
break | |
endif | |
call add(modifiers, {'name': 'hide'}) | |
elseif k =~# '^loc\%[kmarks]$' | |
call add(modifiers, {'name': 'lockmarks'}) | |
elseif k =~# '^lefta\%[bove]$' | |
call add(modifiers, {'name': 'leftabove'}) | |
elseif k =~# '^noa\%[utocmd]$' | |
call add(modifiers, {'name': 'noautocmd'}) | |
elseif k =~# '^rightb\%[elow]$' | |
call add(modifiers, {'name': 'rightbelow'}) | |
elseif k =~# '^san\%[dbox]$' | |
call add(modifiers, {'name': 'sandbox'}) | |
elseif k =~# '^sil\%[ent]$' | |
if c == '!' | |
call add(modifiers, {'name': 'silent', 'bang': 1}) | |
else | |
call add(modifiers, {'name': 'silent', 'bang': 0}) | |
endif | |
elseif k =~# '^tab$' | |
if d != '' | |
call add(modifiers, {'name': 'tab', 'count': str2nr(d, 10)}) | |
else | |
call add(modifiers, {'name': 'tab'}) | |
endif | |
elseif k =~# '^to\%[pleft]$' | |
call add(modifiers, {'name': 'topleft'}) | |
elseif k =~# '^uns\%[ilent]$' | |
call add(modifiers, {'name': 'unsilent'}) | |
elseif k =~# '^vert\%[ical]$' | |
call add(modifiers, {'name': 'vertical'}) | |
elseif k =~# '^verb\%[ose]$' | |
if d != '' | |
call add(modifiers, {'name': 'verbose', 'count': str2nr(d, 10)}) | |
else | |
call add(modifiers, {'name': 'verbose', 'count': 1}) | |
endif | |
else | |
call self.reader.setpos(pos) | |
break | |
endif | |
endwhile | |
let self.ea.modifiers = modifiers | |
endfunction | |
" FIXME: | |
function s:VimLParser.parse_range() | |
let tokens = [] | |
while 1 | |
while 1 | |
call self.skip_white() | |
let c = self.reader.peek() | |
if c == '' | |
break | |
endif | |
if c == '.' | |
call add(tokens, self.reader.get()) | |
elseif c == '$' | |
call add(tokens, self.reader.get()) | |
elseif c == "'" | |
call self.reader.get() | |
let c = self.reader.get() | |
if c == '' | |
break | |
endif | |
call add(tokens, "'" . c) | |
elseif c == '/' | |
call add(tokens, self.parse_pattern()) | |
elseif c == '?' | |
call add(tokens, self.parse_pattern()) | |
elseif c == '\' | |
call self.reader.get() | |
let c = self.reader.get() | |
if c == '&' || c == '?' || c == '/' | |
call add(tokens, '\' . c) | |
else | |
throw 'VimLParser: E10: \\ should be followed by /, ? or &' | |
endif | |
elseif c =~ '\d' | |
call add(tokens, self.read_digits()) | |
endif | |
while 1 | |
call self.skip_white() | |
if self.reader.peek() == '' | |
break | |
endif | |
let n = self.read_integer() | |
if n == '' | |
break | |
endif | |
call add(tokens, n) | |
endwhile | |
if self.reader.peek() !~ '[/?]' | |
break | |
endif | |
endwhile | |
if self.reader.peek() == '%' | |
call add(tokens, self.reader.get()) | |
elseif self.reader.peek() == '*' " && &cpoptions !~ '\*' | |
call add(tokens, self.reader.get()) | |
endif | |
if self.reader.peek() == ';' | |
call add(tokens, self.reader.get()) | |
continue | |
elseif self.reader.peek() == ',' | |
call add(tokens, self.reader.get()) | |
continue | |
endif | |
break | |
endwhile | |
let self.ea.tokens = tokens | |
endfunction | |
" FIXME: | |
function s:VimLParser.parse_pattern() | |
let pattern = self.reader.peek() | |
let inbracket = 0 | |
let delimiter = self.reader.get() | |
while 1 | |
let c = self.reader.get() | |
if c == '' | |
throw 'VimLParser: E682: Invalid search pattern or delimiter' | |
endif | |
let pattern .= c | |
if c == delimiter && inbracket == 0 | |
break | |
elseif c == '\' | |
if self.reader.peek() == '' | |
throw 'VimLParser: E682: Invalid search pattern or delimiter' | |
endif | |
let pattern .= self.reader.get() | |
elseif c == '[' | |
let inbracket += 1 | |
elseif c == ']' | |
let inbracket -= 1 | |
endif | |
endwhile | |
return pattern | |
endfunction | |
function s:VimLParser.parse_command() | |
call self.skip_white_and_colon() | |
if self.reader.peek() =~ '^$\|\n' | |
return | |
elseif self.reader.peek() == '"' | |
call self.parse_comment() | |
return | |
endif | |
let self.ea.cmdpos = self.reader.getpos() | |
let line = self.reader.peekline() | |
let self.ea.cmd = self.find_command() | |
if self.ea.cmd == s:NIL | |
throw printf('VimLParser: E492: Not an editor command: %s', line) | |
endif | |
if self.reader.peek() == '!' && self.ea.cmd.name !~ '\v^%(substitute|smagic|snomagic)$' | |
call self.reader.get() | |
let self.ea.forceit = 1 | |
else | |
let self.ea.forceit = 0 | |
endif | |
if self.ea.cmd.flags !~ '\<BANG\>' && self.ea.forceit | |
throw 'VimLParser: E477: No ! allowed' | |
endif | |
if self.ea.cmd.name != '!' | |
call self.skip_white() | |
endif | |
let self.ea.argpos = self.reader.getpos() | |
if self.ea.cmd.flags =~ '\<ARGOPT\>' | |
call self.parse_argopt() | |
endif | |
if self.ea.cmd.name =~ '\v^%(write|update)$' | |
if self.reader.peek() == '>' | |
call self.reader.get() | |
if self.reader.peek() == '>' | |
throw 'VimLParser: E494: Use w or w>>' | |
endif | |
call self.skip_white() | |
let self.ea.append = 1 | |
elseif self.reader.peek() == '!' && self.ea.cmd.name == 'write' | |
call self.reader.get() | |
let self.ea.usefilter = 1 | |
endif | |
endif | |
if self.ea.cmd.name == 'read' | |
if self.ea.forceit | |
let self.ea.usefilter = 1 | |
let self.ea.forceit = 0 | |
elseif self.reader.peek() == '!' | |
call self.reader.get() | |
let self.ea.usefilter = 1 | |
endif | |
endif | |
if self.ea.cmd.name =~ '^[<>]$' | |
let self.ea.amount = 1 | |
while self.reader.peek() == self.ea.cmd.name | |
call self.reader.get() | |
let self.ea.amount += 1 | |
endwhile | |
call self.skip_white() | |
endif | |
if self.ea.cmd.flags =~ '\<EDITCMD\>' && !self.ea.usefilter | |
call self.parse_argcmd() | |
endif | |
call self[self.ea.cmd.parser]() | |
endfunction | |
function s:VimLParser.find_command() | |
call self.skip_white_and_colon() | |
if self.reader.peek() =~ '^$\|\n' | |
call self.reader.readline() | |
return s:NIL | |
elseif self.reader.peek() == '"' | |
call self.parse_comment() | |
return s:NIL | |
endif | |
let c = self.reader.peek() | |
if c == 'k' | |
call self.reader.get() | |
let name = 'k' | |
elseif c == 's' && self.reader.peek(5) =~ '\v^s%(c[^sr][^i][^p]|g|i[^mlg]|I|r[^e])' | |
call self.reader.get() | |
let name = 'substitute' | |
elseif c =~ '[@*!=><&~#]' | |
call self.reader.get() | |
let name = c | |
elseif self.reader.peek(2) == 'py' | |
let name = self.read_alnum() | |
else | |
let pos = self.reader.getpos() | |
let name = self.read_alpha() | |
if name != 'del' && name =~# '\v^d%[elete][lp]$' | |
call self.reader.setpos(pos) | |
let name = self.reader.get(len(name) - 1) | |
endif | |
endif | |
let cmd = s:NIL | |
for x in self.builtin_commands | |
if name =~# x.pat | |
let cmd = x | |
break | |
endif | |
endfor | |
" FIXME: user defined command | |
if (cmd == s:NIL || cmd.name == 'Print') && name =~ '^[A-Z]' | |
let name .= self.read_alnum() | |
let cmd = {'name': name, 'flags': 'USERCMD', 'parser': 'parse_cmd_usercmd'} | |
endif | |
return cmd | |
endfunction | |
" TODO: | |
function s:VimLParser.parse_hashbang() | |
call self.reader.readline() | |
endfunction | |
" TODO: | |
function s:VimLParser.parse_comment() | |
call self.reader.readline() | |
endfunction | |
" TODO: | |
function s:VimLParser.parse_argopt() | |
endfunction | |
" TODO: | |
function s:VimLParser.parse_argcmd() | |
endfunction | |
" TODO: | |
function s:VimLParser.parse_cmd_common() | |
if self.ea.cmd.flags =~ '\<TRLBAR\>' && !self.ea.usefilter | |
let end = self.separate_nextcmd() | |
elseif self.ea.cmd.name =~ '^\(!\|global\|vglobal\)$' || self.ea.usefilter | |
while self.reader.peek() !~ '^$\|\n' | |
call self.reader.get() | |
endwhile | |
let end = self.reader.getpos() | |
call self.reader.get() | |
else | |
while 1 | |
let end = self.reader.getpos() | |
if self.reader.get() =~ '^$\|\n' | |
break | |
endif | |
endwhile | |
endif | |
let cmdstr = self.reader.getstr(self.ea.linepos, end) | |
let expr = self.node('STRING', '"' . escape(cmdstr, '\"') . '"') | |
call s:decho(['EXECUTE', self.ea.cmd.name, cmdstr], 'None') | |
let node = self.node('EXECUTE', [expr]) | |
call self.add_node(node) | |
endfunction | |
function s:VimLParser.separate_nextcmd() | |
call self.skip_vimgrep_pat() | |
let pc = '' | |
while 1 | |
let end = self.reader.getpos() | |
let c = self.reader.peek() | |
if c == '' | |
break | |
elseif c == "\<C-V>" | |
call self.reader.get() | |
let c = self.reader.get() | |
if c == '' | |
break | |
endif | |
elseif self.reader.peek(2) == '`=' && self.ea.cmd.flags =~ '\<XFILE\>' | |
call self.reader.get(2) | |
call self.parse_expr() | |
let c = self.reader.get() | |
if c != '`' | |
throw printf('VimLParser: unexpected character: %s', c) | |
endif | |
elseif c == '|' || c == "\n" || | |
\ (c == '"' && self.ea.cmd.flags !~ '\<NOTRLCOM\>' | |
\ && ((self.ea.cmd.name != '@' && self.ea.cmd.name != '*') | |
\ || self.reader.getpos() != self.ea.argpos) | |
\ && (self.ea.cmd.name != 'redir' | |
\ || self.reader.getpos()[0] != self.ea.argpos[0] + 1 || pc != '@')) | |
if c == '|' && self.ea.cmd.flags !~ '\<USECTRLV\>' && pc == '\' | |
call self.reader.get() | |
else | |
call self.reader.get() | |
break | |
endif | |
else | |
call self.reader.get() | |
endif | |
let pc = c | |
endwhile | |
return end | |
endfunction | |
" FIXME | |
function s:VimLParser.skip_vimgrep_pat() | |
endfunction | |
" FIXME | |
function s:VimLParser.parse_cmd_usercmd() | |
return self.parse_cmd_common() | |
endfunction | |
function s:VimLParser.parse_cmd_function() | |
let pos = self.reader.getpos() | |
call self.skip_white() | |
let c = self.reader.peek() | |
" :function | |
if self.ends_excmds(c) | |
call self.reader.setpos(pos) | |
return self.parse_cmd_common() | |
endif | |
" :function /pattern | |
if c == '/' | |
call self.reader.setpos(pos) | |
return self.parse_cmd_common() | |
endif | |
let name = self.parse_lvalue() | |
call self.skip_white() | |
" :function {name} | |
if self.reader.peek() != '(' | |
call self.reader.setpos(pos) | |
return self.parse_cmd_common() | |
endif | |
" :function[!] {name}([arguments]) [range] [abort] [dict] | |
call self.reader.get() | |
let args = [] | |
let c = self.reader.peek() | |
if c == ')' | |
call self.reader.get() | |
else | |
while 1 | |
call self.skip_white() | |
if self.reader.peek() =~ '\h' | |
let arg = self.readx('\w') | |
call add(args, arg) | |
call self.skip_white() | |
let c = self.reader.peek() | |
if c == ',' | |
call self.reader.get() | |
continue | |
elseif c == ')' | |
call self.reader.get() | |
break | |
else | |
throw printf('VimLParser: unexpected characters: %s', c) | |
endif | |
elseif self.reader.peek(3) == '...' | |
call self.reader.get(3) | |
call add(args, '...') | |
call self.skip_white() | |
let c = self.reader.peek() | |
if c == ')' | |
call self.reader.get() | |
break | |
else | |
throw printf('VimLParser: unexpected characters: %s', c) | |
endif | |
else | |
throw printf('VimLParser: unexpected characters: %s', c) | |
endif | |
endwhile | |
endif | |
let attr = {'range': 0, 'abort': 0, 'dict': 0} | |
while 1 | |
call self.skip_white() | |
let key = self.read_alpha() | |
if key == '' | |
break | |
elseif key == 'range' | |
let attr.range = 1 | |
elseif key == 'abort' | |
let attr.abort = 1 | |
elseif key == 'dict' | |
let attr.dict = 1 | |
else | |
throw printf('VimLParser: unexpected token: %s', key) | |
endif | |
endwhile | |
call self.skip_trail() | |
call s:decho(['function', name, args], 'None') | |
call self.push_context('function', [name, args]) | |
endfunction | |
function s:VimLParser.parse_cmd_endfunction() | |
if self.find_context('^function$') != 0 | |
throw 'VimLParser: E193: :endfunction not inside a function' | |
endif | |
call self.skip_trail() | |
call s:decho(['endfunction'], 'None') | |
let ctx = self.pop_context() | |
let [name, args] = ctx.value | |
let node = self.node('FUNCTION', [name, args, ctx.body]) | |
call self.add_node(node) | |
endfunction | |
function s:VimLParser.parse_cmd_delfunction() | |
let name = self.parse_lvalue() | |
call self.skip_trail() | |
call s:decho(['delfunction', name], 'None') | |
let node = self.node('DELFUNCTION', name) | |
call self.add_node(node) | |
endfunction | |
function s:VimLParser.parse_cmd_return() | |
if self.find_context('^function$') == -1 | |
throw 'VimLParser: E133: :return not inside a function' | |
endif | |
call self.skip_white() | |
let c = self.reader.peek() | |
if self.ends_excmds(c) | |
let arg = s:NIL | |
else | |
let arg = self.parse_expr() | |
endif | |
call self.skip_trail() | |
call s:decho(['return', arg], 'None') | |
let node = self.node('RETURN', arg) | |
call self.add_node(node) | |
endfunction | |
function s:VimLParser.parse_cmd_call() | |
call self.skip_white() | |
let c = self.reader.peek() | |
if self.ends_excmds(c) | |
throw printf('VimLParser: call error: %s', c) | |
endif | |
let expr = self.parse_expr() | |
if expr.type != 'CALL' | |
throw printf('VimLParser: call error: %s', expr.type) | |
endif | |
let [name, args] = expr.value | |
call self.skip_trail() | |
call s:decho(['call', expr], 'None') | |
let node = self.node('EXCALL', [name, args]) | |
call self.add_node(node) | |
endfunction | |
function s:VimLParser.parse_cmd_let() | |
let pos = self.reader.getpos() | |
call self.skip_white() | |
" :let | |
if self.ends_excmds(self.reader.peek()) | |
call self.reader.setpos(pos) | |
return self.parse_cmd_common() | |
endif | |
let lhs = self.parse_letlhs() | |
call self.skip_white() | |
let s1 = self.reader.peek(1) | |
let s2 = self.reader.peek(2) | |
" :let {var-name} .. | |
if self.ends_excmds(s1) || (s2 != '+=' && s2 != '-=' && s2 != '.=' && s1 != '=') | |
call self.reader.setpos(pos) | |
return self.parse_cmd_common() | |
endif | |
" :let lhs op rhs | |
if s2 == '+=' || s2 == '-=' || s2 == '.=' | |
call self.reader.get(2) | |
let op = s2 | |
elseif s1 == '=' | |
call self.reader.get(1) | |
let op = s1 | |
else | |
throw 'NOT REACHED' | |
endif | |
let rhs = self.parse_expr() | |
call self.skip_trail() | |
call s:decho(['let', lhs, op, rhs], 'None') | |
let node = self.node('LET', [lhs, op, rhs]) | |
call self.add_node(node) | |
endfunction | |
function s:VimLParser.parse_cmd_unlet() | |
let args = [] | |
let node = self.parse_lvalue() | |
call add(args, node) | |
while 1 | |
call self.skip_white() | |
if self.ends_excmds(self.reader.peek()) | |
break | |
endif | |
let node = self.parse_lvalue() | |
call add(args, node) | |
endwhile | |
call self.skip_trail() | |
call s:decho(['unlet', args], 'None') | |
let node = self.node('UNLET', args) | |
call self.add_node(node) | |
endfunction | |
function s:VimLParser.parse_cmd_lockvar() | |
let args = [] | |
let depth = 2 | |
call self.skip_white() | |
if self.reader.peek() =~ '\d' | |
let d = self.read_digits() | |
let depth = str2nr(depth, 10) | |
endif | |
let node = self.parse_lvalue() | |
call add(args, node) | |
while 1 | |
call self.skip_white() | |
if self.ends_excmds(self.reader.peek()) | |
break | |
endif | |
let node = self.parse_lvalue() | |
call add(args, node) | |
endwhile | |
call self.skip_trail() | |
call s:decho(['lockvar', depth, args], 'None') | |
let self.node = self.node('LOCKVAR', [depth, args]) | |
call self.add_node(node) | |
endfunction | |
function s:VimLParser.parse_cmd_unlockvar() | |
let args = [] | |
let depth = 2 | |
call self.skip_white() | |
if self.reader.peek() =~ '\d' | |
let d = self.read_digits() | |
let depth = str2nr(depth, 10) | |
endif | |
let node = self.parse_lvalue() | |
call add(args, node) | |
while 1 | |
call self.skip_white() | |
if self.ends_excmds(self.reader.peek()) | |
break | |
endif | |
let node = self.parse_lvalue() | |
call add(args, node) | |
endwhile | |
call self.skip_trail() | |
call s:decho(['unlockvar', depth, args], 'None') | |
let node = self.node('UNLOCKVAR', [depth, args]) | |
call self.add_node(node) | |
endfunction | |
function s:VimLParser.parse_cmd_if() | |
let cond = self.parse_expr() | |
call self.skip_trail() | |
call s:decho(['if', cond], 'None') | |
let clauses = [[cond, []]] | |
call self.push_context('if', clauses) | |
endfunction | |
function s:VimLParser.parse_cmd_elseif() | |
if self.find_context('^\(if\|elseif\)$') != 0 | |
throw 'VimLParser: E582: :elseif without :if' | |
endif | |
let cond = self.parse_expr() | |
call self.skip_trail() | |
call s:decho(['elseif', cond], 'None') | |
let ctx = self.pop_context() | |
let clauses = ctx.value | |
let clauses[-1][1] = ctx.body | |
call add(clauses, [cond, []]) | |
call self.push_context('elseif', clauses) | |
endfunction | |
function s:VimLParser.parse_cmd_else() | |
if self.find_context('^\(if\|elseif\)$') != 0 | |
throw 'VimLParser: E581: :else without :if' | |
endif | |
call self.skip_trail() | |
call s:decho(['else'], 'None') | |
let ctx = self.pop_context() | |
let clauses = ctx.value | |
let clauses[-1][1] = ctx.body | |
call add(clauses, [s:NIL, []]) | |
call self.push_context('else', clauses) | |
endfunction | |
function s:VimLParser.parse_cmd_endif() | |
if self.find_context('^\(if\|elseif\|else\)$') != 0 | |
throw 'VimLParser: E580: :endif without :if' | |
endif | |
call self.skip_trail() | |
call s:decho(['endif'], 'None') | |
let ctx = self.pop_context() | |
let clauses = ctx.value | |
let clauses[-1][1] = ctx.body | |
let node = self.node('IF', clauses) | |
call self.add_node(node) | |
endfunction | |
function s:VimLParser.parse_cmd_while() | |
let cond = self.parse_expr() | |
call self.skip_trail() | |
call s:decho(['while', cond], 'None') | |
call self.push_context('while', cond) | |
endfunction | |
function s:VimLParser.parse_cmd_endwhile() | |
if self.find_context('^while$') == -1 | |
throw 'VimLParser: E588: :endwhile without :while' | |
endif | |
call self.skip_trail() | |
call s:decho(['endwhile'], 'None') | |
let ctx = self.pop_context() | |
let cond = ctx.value | |
let node = self.node('WHILE', [cond, ctx.body]) | |
call self.add_node(node) | |
endfunction | |
function s:VimLParser.parse_cmd_for() | |
let var = self.parse_letlhs() | |
call self.skip_white() | |
if self.read_alpha() != 'in' | |
throw 'VimLParser: Missing "in" after :for' | |
endif | |
let list = self.parse_expr() | |
call self.skip_trail() | |
call s:decho(['for', var, list], 'None') | |
call self.push_context('for', [var, list]) | |
endfunction | |
function s:VimLParser.parse_cmd_endfor() | |
if self.find_context('^for$') == -1 | |
throw 'VimLParser: E588: :endfor without :for' | |
endif | |
call self.skip_trail() | |
call s:decho(['endfor'], 'None') | |
let ctx = self.pop_context() | |
let [var, list] = ctx.value | |
let node = self.node('FOR', [var, list, ctx.body]) | |
call self.add_node(node) | |
endfunction | |
function s:VimLParser.parse_cmd_continue() | |
if self.find_context('^\(while\|for\)$') == -1 | |
throw 'VimLParser: E586: :continue without :while or :for' | |
endif | |
call self.skip_trail() | |
call s:decho(['continue'], 'None') | |
let node = self.node('CONTINUE', s:NIL) | |
call self.add_node(node) | |
endfunction | |
function s:VimLParser.parse_cmd_break() | |
if self.find_context('^\(while\|for\)$') == -1 | |
throw 'VimLParser: E587: :break without :while or :for' | |
endif | |
call self.skip_trail() | |
call s:decho(['break'], 'None') | |
let node = self.node('BREAK', s:NIL) | |
call self.add_node(node) | |
endfunction | |
function s:VimLParser.parse_cmd_try() | |
call self.skip_trail() | |
call s:decho(['try'], 'None') | |
let [body, _catch, _finally] = [[], [], s:NIL] | |
call self.push_context('try', [body, _catch, _finally]) | |
endfunction | |
function s:VimLParser.parse_cmd_catch() | |
if self.find_context('^finally$') == 0 | |
throw 'VimLParser: E604: :catch after :finally' | |
elseif self.find_context('^\(try\|catch\)$') != 0 | |
throw 'VimLParser: E603: :catch without :try' | |
endif | |
call self.skip_white() | |
if self.ends_excmds(self.reader.peek()) | |
let pattern = s:NIL | |
else | |
let pattern = self.parse_pattern() | |
endif | |
call self.skip_trail() | |
call s:decho(['catch', pattern], 'None') | |
let ctx = self.pop_context() | |
let [body, _catch, _finally] = ctx.value | |
if ctx.type == 'try' | |
let body = ctx.body | |
else | |
let _catch[-1][1] = ctx.body | |
endif | |
call add(_catch, [pattern, []]) | |
call self.push_context('catch', [body, _catch, _finally]) | |
endfunction | |
function s:VimLParser.parse_cmd_finally() | |
if self.find_context('^\(try\|catch\)$') != 0 | |
throw 'VimLParser: E606: :finally without :try' | |
endif | |
call self.skip_trail() | |
call s:decho(['finally'], 'None') | |
let ctx = self.pop_context() | |
let [body, _catch, _finally] = ctx.value | |
if ctx.type == 'try' | |
let body = ctx.body | |
else | |
let _catch[-1][1] = ctx.body | |
endif | |
call self.push_context('finally', [body, _catch, _finally]) | |
endfunction | |
function s:VimLParser.parse_cmd_endtry() | |
if self.find_context('^\(try\|catch\|finally\)$') != 0 | |
throw 'VimLParser: E602: :endtry without :try' | |
endif | |
call self.skip_trail() | |
call s:decho(['endtry'], 'None') | |
let ctx = self.pop_context() | |
let [body, _catch, _finally] = ctx.value | |
if ctx.type == 'try' | |
let body = ctx.body | |
elseif ctx.type == 'catch' | |
let _catch[-1][1] = ctx.body | |
else | |
let _finally = ctx.body | |
endif | |
let node = self.node('TRY', [body, _catch, _finally]) | |
call self.add_node(node) | |
endfunction | |
function s:VimLParser.parse_cmd_throw() | |
let expr1 = self.parse_expr() | |
call self.skip_trail() | |
call s:decho(['throw', expr1], 'None') | |
let node = self.node('THROW', expr1) | |
call self.add_node(node) | |
endfunction | |
function s:VimLParser.parse_cmd_echo() | |
let args = self.parse_exprlist() | |
call self.skip_trail() | |
call s:decho(['echo', args], 'None') | |
let node = self.node('ECHO', args) | |
call self.add_node(node) | |
endfunction | |
function s:VimLParser.parse_cmd_echon() | |
let args = self.parse_exprlist() | |
call self.skip_trail() | |
call s:decho(['echon', args], 'None') | |
let node = self.node('ECHON', args) | |
call self.add_node(node) | |
endfunction | |
function s:VimLParser.parse_cmd_echohl() | |
let name = '' | |
while !self.ends_excmds(self.reader.peek()) | |
let name .= self.reader.get() | |
endwhile | |
call self.skip_trail() | |
call s:decho(['echohl', name], 'None') | |
let node = self.node('ECHOHL', name) | |
call self.add_node(node) | |
endfunction | |
function s:VimLParser.parse_cmd_echomsg() | |
let args = self.parse_exprlist() | |
call self.skip_trail() | |
call s:decho(['echomsg', args], 'None') | |
let node = self.node('ECHOMSG', args) | |
call self.add_node(node) | |
endfunction | |
function s:VimLParser.parse_cmd_echoerr() | |
let args = self.parse_exprlist() | |
call self.skip_trail() | |
call s:decho(['echoerr', args], 'None') | |
let node = self.node('ECHOERR', args) | |
call self.add_node(node) | |
endfunction | |
function s:VimLParser.parse_cmd_execute() | |
let args = self.parse_exprlist() | |
call self.skip_trail() | |
call s:decho(['execute', args], 'None') | |
let node = self.node('EXECUTE', args) | |
call self.add_node(node) | |
endfunction | |
function s:VimLParser.parse_expr() | |
return s:ExprParser.new(s:ExprTokenizer.new(self.reader)).parse() | |
endfunction | |
function s:VimLParser.parse_exprlist() | |
let args = [] | |
let node = self.parse_expr() | |
call add(args, node) | |
while 1 | |
call self.skip_white() | |
let c = self.reader.peek() | |
if c != '"' && self.ends_excmds(c) | |
break | |
endif | |
let node = self.parse_expr() | |
call add(args, node) | |
endwhile | |
return args | |
endfunction | |
" FIXME: | |
function s:VimLParser.parse_lvalue() | |
let p = s:LvalueParser.new(s:ExprTokenizer.new(self.reader)) | |
let node = p.parse() | |
if node.type =~ '\v^%(IDENTIFIER|INDEX|DOT|OPTION|ENV|REG)$' | |
return node | |
endif | |
throw printf('VimLParser: lvalue error: %s', node.value) | |
endfunction | |
" FIXME: | |
function s:VimLParser.parse_letlhs() | |
let values = {'args': [], 'rest': s:NIL} | |
let tokenizer = s:ExprTokenizer.new(self.reader) | |
if tokenizer.peek().type == 'LBRA' | |
call tokenizer.get() | |
while 1 | |
let node = self.parse_lvalue() | |
call add(values.args, node) | |
if tokenizer.peek().type == 'RBRA' | |
call tokenizer.get() | |
break | |
elseif tokenizer.peek().type == 'COMMA' | |
call tokenizer.get() | |
continue | |
elseif tokenizer.peek().type == 'SEMICOLON' | |
call tokenizer.get() | |
let node = self.parse_lvalue() | |
let values.rest = node | |
let token = tokenizer.peek() | |
if token.type == 'RBRA' | |
call tokenizer.get() | |
break | |
else | |
throw printf('VimLParser: E475 Invalid argument: %s', token.value) | |
endif | |
else | |
throw printf('VimLParser: E475 Invalid argument: %s', token.value) | |
endif | |
endwhile | |
else | |
let node = self.parse_lvalue() | |
call add(values.args, node) | |
endif | |
return values | |
endfunction | |
function s:VimLParser.readx(pat) | |
let r = '' | |
while self.reader.peek() =~ a:pat | |
let r .= self.reader.get() | |
endwhile | |
return r | |
endfunction | |
function s:VimLParser.read_alpha() | |
return self.readx('\a') | |
endfunction | |
function s:VimLParser.read_digits() | |
return self.readx('\d') | |
endfunction | |
function s:VimLParser.read_integer() | |
if self.reader.peek() =~ '[-+]' | |
let c = self.reader.get() | |
else | |
let c = '' | |
endif | |
return c . self.read_digits() | |
endfunction | |
function s:VimLParser.read_alnum() | |
return self.readx('[0-9a-zA-Z]') | |
endfunction | |
function s:VimLParser.skip_white() | |
call self.readx('\s') | |
endfunction | |
function s:VimLParser.skip_white_and_colon() | |
call self.readx(':\|\s') | |
endfunction | |
function s:VimLParser.skip_trail() | |
call self.skip_white() | |
let c = self.reader.peek() | |
if c == '' | |
" pass | |
elseif c == "\n" || c == '"' | |
call self.reader.readline() | |
elseif c == '|' | |
call self.reader.get() | |
else | |
throw printf('VimLParser: E488: Trailing characters: %s', c) | |
endif | |
endfunction | |
function s:VimLParser.ends_excmds(c) | |
return a:c == '' || a:c == '|' || a:c == '"' || a:c == "\n" | |
endfunction | |
let s:VimLParser.builtin_commands = [ | |
\ {'name': 'append', 'pat': '^a\%[ppend]$', 'flags': 'BANG|RANGE|ZEROR|TRLBAR|CMDWIN|MODIFY', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'abbreviate', 'pat': '^ab\%[breviate]$', 'flags': 'EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'abclear', 'pat': '^abc\%[lear]$', 'flags': 'EXTRA|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'aboveleft', 'pat': '^abo\%[veleft]$', 'flags': 'NEEDARG|EXTRA|NOTRLCOM', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'all', 'pat': '^al\%[l]$', 'flags': 'BANG|RANGE|NOTADR|COUNT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'amenu', 'pat': '^am\%[enu]$', 'flags': 'RANGE|NOTADR|ZEROR|EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'anoremenu', 'pat': '^an\%[oremenu]$', 'flags': 'RANGE|NOTADR|ZEROR|EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'args', 'pat': '^ar\%[gs]$', 'flags': 'BANG|FILES|EDITCMD|ARGOPT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'argadd', 'pat': '^arga\%[dd]$', 'flags': 'BANG|NEEDARG|RANGE|NOTADR|ZEROR|FILES|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'argdelete', 'pat': '^argd\%[elete]$', 'flags': 'BANG|RANGE|NOTADR|FILES|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'argedit', 'pat': '^arge\%[dit]$', 'flags': 'BANG|NEEDARG|EXTRA|NOTRLCOM', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'argdo', 'pat': '^argdo$', 'flags': 'BANG|NEEDARG|RANGE|NOTADR|FILE1|EDITCMD|ARGOPT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'argglobal', 'pat': '^argg\%[lobal]$', 'flags': 'BANG|FILES|EDITCMD|ARGOPT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'arglocal', 'pat': '^argl\%[ocal]$', 'flags': 'BANG|FILES|EDITCMD|ARGOPT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'argument', 'pat': '^argu\%[ment]$', 'flags': 'BANG|RANGE|NOTADR|COUNT|EXTRA|EDITCMD|ARGOPT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'ascii', 'pat': '^as\%[cii]$', 'flags': 'TRLBAR|SBOXOK|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'autocmd', 'pat': '^au\%[tocmd]$', 'flags': 'BANG|EXTRA|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'augroup', 'pat': '^aug\%[roup]$', 'flags': 'BANG|WORD1|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'aunmenu', 'pat': '^aun\%[menu]$', 'flags': 'EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'buffer', 'pat': '^b\%[uffer]$', 'flags': 'BANG|RANGE|NOTADR|BUFNAME|BUFUNL|COUNT|EXTRA|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'bNext', 'pat': '^bN\%[ext]$', 'flags': 'BANG|RANGE|NOTADR|COUNT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'ball', 'pat': '^ba\%[ll]$', 'flags': 'RANGE|NOTADR|COUNT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'badd', 'pat': '^bad\%[d]$', 'flags': 'NEEDARG|FILE1|EDITCMD|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'bdelete', 'pat': '^bd\%[elete]$', 'flags': 'BANG|RANGE|NOTADR|BUFNAME|COUNT|EXTRA|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'behave', 'pat': '^be\%[have]$', 'flags': 'NEEDARG|WORD1|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'belowright', 'pat': '^bel\%[owright]$', 'flags': 'NEEDARG|EXTRA|NOTRLCOM', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'bfirst', 'pat': '^bf\%[irst]$', 'flags': 'BANG|RANGE|NOTADR|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'blast', 'pat': '^bl\%[ast]$', 'flags': 'BANG|RANGE|NOTADR|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'bmodified', 'pat': '^bm\%[odified]$', 'flags': 'BANG|RANGE|NOTADR|COUNT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'bnext', 'pat': '^bn\%[ext]$', 'flags': 'BANG|RANGE|NOTADR|COUNT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'botright', 'pat': '^bo\%[tright]$', 'flags': 'NEEDARG|EXTRA|NOTRLCOM', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'bprevious', 'pat': '^bp\%[revious]$', 'flags': 'BANG|RANGE|NOTADR|COUNT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'brewind', 'pat': '^br\%[ewind]$', 'flags': 'BANG|RANGE|NOTADR|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'break', 'pat': '^brea\%[k]$', 'flags': 'TRLBAR|SBOXOK|CMDWIN', 'parser': 'parse_cmd_break'}, | |
\ {'name': 'breakadd', 'pat': '^breaka\%[dd]$', 'flags': 'EXTRA|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'breakdel', 'pat': '^breakd\%[el]$', 'flags': 'EXTRA|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'breaklist', 'pat': '^breakl\%[ist]$', 'flags': 'EXTRA|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'browse', 'pat': '^bro\%[wse]$', 'flags': 'NEEDARG|EXTRA|NOTRLCOM|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'bufdo', 'pat': '^bufdo$', 'flags': 'BANG|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'buffers', 'pat': '^buffers$', 'flags': 'BANG|NEEDARG|EXTRA|NOTRLCOM', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'bunload', 'pat': '^bun\%[load]$', 'flags': 'BANG|RANGE|NOTADR|BUFNAME|COUNT|EXTRA|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'bwipeout', 'pat': '^bw\%[ipeout]$', 'flags': 'BANG|RANGE|NOTADR|BUFNAME|BUFUNL|COUNT|EXTRA|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'change', 'pat': '^c\%[hange]$', 'flags': 'BANG|WHOLEFOLD|RANGE|COUNT|TRLBAR|CMDWIN|MODIFY', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'cNext', 'pat': '^cN\%[ext]$', 'flags': 'RANGE|NOTADR|COUNT|TRLBAR|BANG', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'cNfile', 'pat': '^cNf\%[ile]$', 'flags': 'RANGE|NOTADR|COUNT|TRLBAR|BANG', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'cabbrev', 'pat': '^ca\%[bbrev]$', 'flags': 'EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'cabclear', 'pat': '^cabc\%[lear]$', 'flags': 'EXTRA|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'caddbuffer', 'pat': '^caddb\%[uffer]$', 'flags': 'RANGE|NOTADR|WORD1|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'caddexpr', 'pat': '^cad\%[dexpr]$', 'flags': 'NEEDARG|WORD1|NOTRLCOM|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'caddfile', 'pat': '^caddf\%[ile]$', 'flags': 'TRLBAR|FILE1', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'call', 'pat': '^cal\%[l]$', 'flags': 'RANGE|NEEDARG|EXTRA|NOTRLCOM|SBOXOK|CMDWIN', 'parser': 'parse_cmd_call'}, | |
\ {'name': 'catch', 'pat': '^cat\%[ch]$', 'flags': 'EXTRA|SBOXOK|CMDWIN', 'parser': 'parse_cmd_catch'}, | |
\ {'name': 'cbuffer', 'pat': '^cb\%[uffer]$', 'flags': 'BANG|RANGE|NOTADR|WORD1|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'cc', 'pat': '^cc$', 'flags': 'RANGE|NOTADR|COUNT|TRLBAR|BANG', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'cclose', 'pat': '^ccl\%[ose]$', 'flags': 'RANGE|NOTADR|COUNT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'cd', 'pat': '^cd$', 'flags': 'BANG|FILE1|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'center', 'pat': '^ce\%[nter]$', 'flags': 'TRLBAR|RANGE|WHOLEFOLD|EXTRA|CMDWIN|MODIFY', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'cexpr', 'pat': '^cex\%[pr]$', 'flags': 'NEEDARG|WORD1|NOTRLCOM|TRLBAR|BANG', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'cfile', 'pat': '^cf\%[ile]$', 'flags': 'TRLBAR|FILE1|BANG', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'cfirst', 'pat': '^cfir\%[st]$', 'flags': 'RANGE|NOTADR|COUNT|TRLBAR|BANG', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'cgetbuffer', 'pat': '^cgetb\%[uffer]$', 'flags': 'TRLBAR|FILE1', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'cgetexpr', 'pat': '^cgete\%[xpr]$', 'flags': 'RANGE|NOTADR|WORD1|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'cgetfile', 'pat': '^cg\%[etfile]$', 'flags': 'NEEDARG|WORD1|NOTRLCOM|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'changes', 'pat': '^cha\%[nges]$', 'flags': 'BANG|FILE1|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'chdir', 'pat': '^chd\%[ir]$', 'flags': 'TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'checkpath', 'pat': '^che\%[ckpath]$', 'flags': 'TRLBAR|BANG|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'checktime', 'pat': '^checkt\%[ime]$', 'flags': 'RANGE|NOTADR|BUFNAME|COUNT|EXTRA|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'clist', 'pat': '^cl\%[ist]$', 'flags': 'BANG|EXTRA|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'clast', 'pat': '^cla\%[st]$', 'flags': 'RANGE|NOTADR|COUNT|TRLBAR|BANG', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'close', 'pat': '^clo\%[se]$', 'flags': 'BANG|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'cmap', 'pat': '^cm\%[ap]$', 'flags': 'EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'cmapclear', 'pat': '^cmapc\%[lear]$', 'flags': 'EXTRA|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'cmenu', 'pat': '^cme\%[nu]$', 'flags': 'RANGE|NOTADR|ZEROR|EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'cnext', 'pat': '^cn\%[ext]$', 'flags': 'RANGE|NOTADR|COUNT|TRLBAR|BANG', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'cnewer', 'pat': '^cnew\%[er]$', 'flags': 'RANGE|NOTADR|COUNT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'cnfile', 'pat': '^cnf\%[ile]$', 'flags': 'RANGE|NOTADR|COUNT|TRLBAR|BANG', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'cnoremap', 'pat': '^cno\%[remap]$', 'flags': 'EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'cnoreabbrev', 'pat': '^cnorea\%[bbrev]$', 'flags': 'EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'cnoremenu', 'pat': '^cnoreme\%[nu]$', 'flags': 'RANGE|NOTADR|ZEROR|EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'copy', 'pat': '^co\%[py]$', 'flags': 'RANGE|WHOLEFOLD|EXTRA|TRLBAR|CMDWIN|MODIFY', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'colder', 'pat': '^col\%[der]$', 'flags': 'RANGE|NOTADR|COUNT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'colorscheme', 'pat': '^colo\%[rscheme]$', 'flags': 'WORD1|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'command', 'pat': '^com\%[mand]$', 'flags': 'EXTRA|BANG|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'comclear', 'pat': '^comc\%[lear]$', 'flags': 'TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'compiler', 'pat': '^comp\%[iler]$', 'flags': 'BANG|TRLBAR|WORD1|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'continue', 'pat': '^con\%[tinue]$', 'flags': 'TRLBAR|SBOXOK|CMDWIN', 'parser': 'parse_cmd_continue'}, | |
\ {'name': 'confirm', 'pat': '^conf\%[irm]$', 'flags': 'NEEDARG|EXTRA|NOTRLCOM|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'copen', 'pat': '^cope\%[n]$', 'flags': 'RANGE|NOTADR|COUNT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'cprevious', 'pat': '^cp\%[revious]$', 'flags': 'RANGE|NOTADR|COUNT|TRLBAR|BANG', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'cpfile', 'pat': '^cpf\%[ile]$', 'flags': 'RANGE|NOTADR|COUNT|TRLBAR|BANG', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'cquit', 'pat': '^cq\%[uit]$', 'flags': 'TRLBAR|BANG', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'crewind', 'pat': '^cr\%[ewind]$', 'flags': 'RANGE|NOTADR|COUNT|TRLBAR|BANG', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'cscope', 'pat': '^cs\%[cope]$', 'flags': 'EXTRA|NOTRLCOM|XFILE', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'cstag', 'pat': '^cst\%[ag]$', 'flags': 'BANG|TRLBAR|WORD1', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'cunmap', 'pat': '^cu\%[nmap]$', 'flags': 'EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'cunabbrev', 'pat': '^cuna\%[bbrev]$', 'flags': 'EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'cunmenu', 'pat': '^cunme\%[nu]$', 'flags': 'EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'cwindow', 'pat': '^cw\%[indow]$', 'flags': 'RANGE|NOTADR|COUNT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'delete', 'pat': '^d\%[elete]$', 'flags': 'RANGE|WHOLEFOLD|REGSTR|COUNT|TRLBAR|CMDWIN|MODIFY', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'delmarks', 'pat': '^delm\%[arks]$', 'flags': 'BANG|EXTRA|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'debug', 'pat': '^deb\%[ug]$', 'flags': 'NEEDARG|EXTRA|NOTRLCOM|SBOXOK|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'debuggreedy', 'pat': '^debugg\%[reedy]$', 'flags': 'RANGE|NOTADR|ZEROR|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'delcommand', 'pat': '^delc\%[ommand]$', 'flags': 'NEEDARG|WORD1|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'delfunction', 'pat': '^delf\%[unction]$', 'flags': 'NEEDARG|WORD1|CMDWIN', 'parser': 'parse_cmd_delfunction'}, | |
\ {'name': 'diffupdate', 'pat': '^dif\%[fupdate]$', 'flags': 'EXTRA|NOTRLCOM|TRLBAR|SBOXOK|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'diffget', 'pat': '^diffg\%[et]$', 'flags': 'BANG|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'diffoff', 'pat': '^diffo\%[ff]$', 'flags': 'RANGE|EXTRA|TRLBAR|MODIFY', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'diffpatch', 'pat': '^diffp\%[atch]$', 'flags': 'BANG|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'diffput', 'pat': '^diffpu\%[t]$', 'flags': 'EXTRA|FILE1|TRLBAR|MODIFY', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'diffsplit', 'pat': '^diffs\%[plit]$', 'flags': 'RANGE|EXTRA|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'diffthis', 'pat': '^diffthis$', 'flags': 'EXTRA|FILE1|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'digraphs', 'pat': '^dig\%[raphs]$', 'flags': 'TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'display', 'pat': '^di\%[splay]$', 'flags': 'EXTRA|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'djump', 'pat': '^dj\%[ump]$', 'flags': 'BANG|RANGE|DFLALL|WHOLEFOLD|EXTRA', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'dlist', 'pat': '^dl\%[ist]$', 'flags': 'BANG|RANGE|DFLALL|WHOLEFOLD|EXTRA|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'doautocmd', 'pat': '^do\%[autocmd]$', 'flags': 'EXTRA|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'doautoall', 'pat': '^doautoa\%[ll]$', 'flags': 'EXTRA|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'drop', 'pat': '^dr\%[op]$', 'flags': 'FILES|EDITCMD|NEEDARG|ARGOPT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'dsearch', 'pat': '^ds\%[earch]$', 'flags': 'BANG|RANGE|DFLALL|WHOLEFOLD|EXTRA|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'dsplit', 'pat': '^dsp\%[lit]$', 'flags': 'BANG|RANGE|DFLALL|WHOLEFOLD|EXTRA', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'edit', 'pat': '^e\%[dit]$', 'flags': 'BANG|FILE1|EDITCMD|ARGOPT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'earlier', 'pat': '^ea\%[rlier]$', 'flags': 'TRLBAR|EXTRA|NOSPC|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'echo', 'pat': '^ec\%[ho]$', 'flags': 'EXTRA|NOTRLCOM|SBOXOK|CMDWIN', 'parser': 'parse_cmd_echo'}, | |
\ {'name': 'echoerr', 'pat': '^echoe\%[rr]$', 'flags': 'EXTRA|NOTRLCOM|SBOXOK|CMDWIN', 'parser': 'parse_cmd_echoerr'}, | |
\ {'name': 'echohl', 'pat': '^echoh\%[l]$', 'flags': 'EXTRA|TRLBAR|SBOXOK|CMDWIN', 'parser': 'parse_cmd_echohl'}, | |
\ {'name': 'echomsg', 'pat': '^echom\%[sg]$', 'flags': 'EXTRA|NOTRLCOM|SBOXOK|CMDWIN', 'parser': 'parse_cmd_echomsg'}, | |
\ {'name': 'echon', 'pat': '^echon$', 'flags': 'EXTRA|NOTRLCOM|SBOXOK|CMDWIN', 'parser': 'parse_cmd_echon'}, | |
\ {'name': 'else', 'pat': '^el\%[se]$', 'flags': 'TRLBAR|SBOXOK|CMDWIN', 'parser': 'parse_cmd_else'}, | |
\ {'name': 'elseif', 'pat': '^elsei\%[f]$', 'flags': 'EXTRA|NOTRLCOM|SBOXOK|CMDWIN', 'parser': 'parse_cmd_elseif'}, | |
\ {'name': 'emenu', 'pat': '^em\%[enu]$', 'flags': 'NEEDARG|EXTRA|TRLBAR|NOTRLCOM|RANGE|NOTADR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'endif', 'pat': '^en\%[dif]$', 'flags': 'TRLBAR|SBOXOK|CMDWIN', 'parser': 'parse_cmd_endif'}, | |
\ {'name': 'endfor', 'pat': '^endfo\%[r]$', 'flags': 'TRLBAR|CMDWIN', 'parser': 'parse_cmd_endfor'}, | |
\ {'name': 'endfunction', 'pat': '^endf\%[unction]$', 'flags': 'TRLBAR|SBOXOK|CMDWIN', 'parser': 'parse_cmd_endfunction'}, | |
\ {'name': 'endtry', 'pat': '^endt\%[ry]$', 'flags': 'TRLBAR|SBOXOK|CMDWIN', 'parser': 'parse_cmd_endtry'}, | |
\ {'name': 'endwhile', 'pat': '^endw\%[hile]$', 'flags': 'TRLBAR|SBOXOK|CMDWIN', 'parser': 'parse_cmd_endwhile'}, | |
\ {'name': 'enew', 'pat': '^ene\%[w]$', 'flags': 'BANG|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'ex', 'pat': '^ex$', 'flags': 'BANG|FILE1|EDITCMD|ARGOPT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'execute', 'pat': '^exe\%[cute]$', 'flags': 'EXTRA|NOTRLCOM|SBOXOK|CMDWIN', 'parser': 'parse_cmd_execute'}, | |
\ {'name': 'exit', 'pat': '^exi\%[t]$', 'flags': 'RANGE|WHOLEFOLD|BANG|FILE1|ARGOPT|DFLALL|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'exusage', 'pat': '^exu\%[sage]$', 'flags': 'TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'file', 'pat': '^f\%[ile]$', 'flags': 'RANGE|NOTADR|ZEROR|BANG|FILE1|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'files', 'pat': '^files$', 'flags': 'BANG|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'filetype', 'pat': '^filet\%[ype]$', 'flags': 'EXTRA|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'find', 'pat': '^fin\%[d]$', 'flags': 'RANGE|NOTADR|BANG|FILE1|EDITCMD|ARGOPT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'finally', 'pat': '^fina\%[lly]$', 'flags': 'TRLBAR|SBOXOK|CMDWIN', 'parser': 'parse_cmd_finally'}, | |
\ {'name': 'finish', 'pat': '^fini\%[sh]$', 'flags': 'TRLBAR|SBOXOK|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'first', 'pat': '^fir\%[st]$', 'flags': 'EXTRA|BANG|EDITCMD|ARGOPT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'fixdel', 'pat': '^fix\%[del]$', 'flags': 'TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'fold', 'pat': '^fo\%[ld]$', 'flags': 'RANGE|WHOLEFOLD|TRLBAR|SBOXOK|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'foldclose', 'pat': '^foldc\%[lose]$', 'flags': 'RANGE|BANG|WHOLEFOLD|TRLBAR|SBOXOK|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'folddoopen', 'pat': '^foldd\%[oopen]$', 'flags': 'RANGE|DFLALL|NEEDARG|EXTRA|NOTRLCOM', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'folddoclosed', 'pat': '^folddoc\%[losed]$', 'flags': 'RANGE|DFLALL|NEEDARG|EXTRA|NOTRLCOM', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'foldopen', 'pat': '^foldo\%[pen]$', 'flags': 'RANGE|BANG|WHOLEFOLD|TRLBAR|SBOXOK|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'for', 'pat': '^for$', 'flags': 'EXTRA|NOTRLCOM|SBOXOK|CMDWIN', 'parser': 'parse_cmd_for'}, | |
\ {'name': 'function', 'pat': '^fu\%[nction]$', 'flags': 'EXTRA|BANG|CMDWIN', 'parser': 'parse_cmd_function'}, | |
\ {'name': 'global', 'pat': '^g\%[lobal]$', 'flags': 'RANGE|WHOLEFOLD|BANG|EXTRA|DFLALL|SBOXOK|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'goto', 'pat': '^go\%[to]$', 'flags': 'RANGE|NOTADR|COUNT|TRLBAR|SBOXOK|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'grep', 'pat': '^gr\%[ep]$', 'flags': 'RANGE|NOTADR|BANG|NEEDARG|EXTRA|NOTRLCOM|TRLBAR|XFILE', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'grepadd', 'pat': '^grepa\%[dd]$', 'flags': 'RANGE|NOTADR|BANG|NEEDARG|EXTRA|NOTRLCOM|TRLBAR|XFILE', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'gui', 'pat': '^gu\%[i]$', 'flags': 'BANG|FILES|EDITCMD|ARGOPT|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'gvim', 'pat': '^gv\%[im]$', 'flags': 'BANG|FILES|EDITCMD|ARGOPT|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'hardcopy', 'pat': '^ha\%[rdcopy]$', 'flags': 'BANG|EXTRA|NOTRLCOM', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'help', 'pat': '^h\%[elp]$', 'flags': 'EXTRA|NOTRLCOM', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'helpfind', 'pat': '^helpf\%[ind]$', 'flags': 'EXTRA|NOTRLCOM|NEEDARG', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'helpgrep', 'pat': '^helpg\%[rep]$', 'flags': 'NEEDARG|FILES|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'helptags', 'pat': '^helpt\%[ags]$', 'flags': 'RANGE|COUNT|EXTRA|TRLBAR|DFLALL|BANG', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'highlight', 'pat': '^hi\%[ghlight]$', 'flags': 'BANG|EXTRA|TRLBAR|SBOXOK|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'hide', 'pat': '^hid\%[e]$', 'flags': 'BANG|EXTRA|NOTRLCOM', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'history', 'pat': '^his\%[tory]$', 'flags': 'EXTRA|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'insert', 'pat': '^i\%[nsert]$', 'flags': 'BANG|RANGE|TRLBAR|CMDWIN|MODIFY', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'iabbrev', 'pat': '^ia\%[bbrev]$', 'flags': 'EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'iabclear', 'pat': '^iabc\%[lear]$', 'flags': 'EXTRA|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'if', 'pat': '^if$', 'flags': 'EXTRA|NOTRLCOM|SBOXOK|CMDWIN', 'parser': 'parse_cmd_if'}, | |
\ {'name': 'ijump', 'pat': '^ij\%[ump]$', 'flags': 'BANG|RANGE|DFLALL|WHOLEFOLD|EXTRA', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'ilist', 'pat': '^il\%[ist]$', 'flags': 'BANG|RANGE|DFLALL|WHOLEFOLD|EXTRA|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'imap', 'pat': '^im\%[ap]$', 'flags': 'EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'imapclear', 'pat': '^imapc\%[lear]$', 'flags': 'EXTRA|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'imenu', 'pat': '^ime\%[nu]$', 'flags': 'RANGE|NOTADR|ZEROR|EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'inoremap', 'pat': '^ino\%[remap]$', 'flags': 'EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'inoreabbrev', 'pat': '^inorea\%[bbrev]$', 'flags': 'EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'inoremenu', 'pat': '^inoreme\%[nu]$', 'flags': 'RANGE|NOTADR|ZEROR|EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'intro', 'pat': '^int\%[ro]$', 'flags': 'TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'isearch', 'pat': '^is\%[earch]$', 'flags': 'BANG|RANGE|DFLALL|WHOLEFOLD|EXTRA|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'isplit', 'pat': '^isp\%[lit]$', 'flags': 'BANG|RANGE|DFLALL|WHOLEFOLD|EXTRA', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'iunmap', 'pat': '^iu\%[nmap]$', 'flags': 'EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'iunabbrev', 'pat': '^iuna\%[bbrev]$', 'flags': 'EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'iunmenu', 'pat': '^iunme\%[nu]$', 'flags': 'EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'join', 'pat': '^j\%[oin]$', 'flags': 'BANG|RANGE|WHOLEFOLD|COUNT|EXFLAGS|TRLBAR|CMDWIN|MODIFY', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'jumps', 'pat': '^ju\%[mps]$', 'flags': 'TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'k', 'pat': '^k$', 'flags': 'RANGE|WORD1|TRLBAR|SBOXOK|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'keepalt', 'pat': '^keepa\%[lt]$', 'flags': 'NEEDARG|EXTRA|NOTRLCOM', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'keepmarks', 'pat': '^kee\%[pmarks]$', 'flags': 'NEEDARG|EXTRA|NOTRLCOM', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'keepjumps', 'pat': '^keepj\%[umps]$', 'flags': 'NEEDARG|EXTRA|NOTRLCOM', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'lNext', 'pat': '^lN\%[ext]$', 'flags': 'RANGE|WHOLEFOLD|COUNT|EXFLAGS|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'lNfile', 'pat': '^lNf\%[ile]$', 'flags': 'RANGE|NOTADR|COUNT|TRLBAR|BANG', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'list', 'pat': '^l\%[ist]$', 'flags': 'RANGE|NOTADR|COUNT|TRLBAR|BANG', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'laddexpr', 'pat': '^lad\%[dexpr]$', 'flags': 'EXTRA|BANG|EDITCMD|ARGOPT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'laddbuffer', 'pat': '^laddb\%[uffer]$', 'flags': 'EXTRA|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'laddfile', 'pat': '^laddf\%[ile]$', 'flags': 'NEEDARG|WORD1|NOTRLCOM|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'last', 'pat': '^la\%[st]$', 'flags': 'RANGE|NOTADR|WORD1|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'language', 'pat': '^lan\%[guage]$', 'flags': 'TRLBAR|FILE1', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'later', 'pat': '^lat\%[er]$', 'flags': 'TRLBAR|EXTRA|NOSPC|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'lbuffer', 'pat': '^lb\%[uffer]$', 'flags': 'BANG|RANGE|NOTADR|WORD1|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'lcd', 'pat': '^lc\%[d]$', 'flags': 'BANG|FILE1|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'lchdir', 'pat': '^lch\%[dir]$', 'flags': 'BANG|FILE1|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'lclose', 'pat': '^lcl\%[ose]$', 'flags': 'RANGE|NOTADR|COUNT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'lcscope', 'pat': '^lcs\%[cope]$', 'flags': 'EXTRA|NOTRLCOM|XFILE', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'left', 'pat': '^le\%[ft]$', 'flags': 'TRLBAR|RANGE|WHOLEFOLD|EXTRA|CMDWIN|MODIFY', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'leftabove', 'pat': '^lefta\%[bove]$', 'flags': 'NEEDARG|EXTRA|NOTRLCOM', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'let', 'pat': '^let$', 'flags': 'EXTRA|NOTRLCOM|SBOXOK|CMDWIN', 'parser': 'parse_cmd_let'}, | |
\ {'name': 'lexpr', 'pat': '^lex\%[pr]$', 'flags': 'NEEDARG|WORD1|NOTRLCOM|TRLBAR|BANG', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'lfile', 'pat': '^lf\%[ile]$', 'flags': 'TRLBAR|FILE1|BANG', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'lfirst', 'pat': '^lfir\%[st]$', 'flags': 'RANGE|NOTADR|COUNT|TRLBAR|BANG', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'lgetbuffer', 'pat': '^lgetb\%[uffer]$', 'flags': 'TRLBAR|FILE1', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'lgetexpr', 'pat': '^lgete\%[xpr]$', 'flags': 'RANGE|NOTADR|WORD1|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'lgetfile', 'pat': '^lg\%[etfile]$', 'flags': 'NEEDARG|WORD1|NOTRLCOM|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'lgrep', 'pat': '^lgr\%[ep]$', 'flags': 'RANGE|NOTADR|BANG|NEEDARG|EXTRA|NOTRLCOM|TRLBAR|XFILE', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'lgrepadd', 'pat': '^lgrepa\%[dd]$', 'flags': 'RANGE|NOTADR|BANG|NEEDARG|EXTRA|NOTRLCOM|TRLBAR|XFILE', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'lhelpgrep', 'pat': '^lh\%[elpgrep]$', 'flags': 'EXTRA|NOTRLCOM|NEEDARG', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'll', 'pat': '^ll$', 'flags': 'RANGE|NOTADR|COUNT|TRLBAR|BANG', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'llast', 'pat': '^lla\%[st]$', 'flags': 'RANGE|NOTADR|COUNT|TRLBAR|BANG', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'llist', 'pat': '^lli\%[st]$', 'flags': 'BANG|EXTRA|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'lmake', 'pat': '^lmak\%[e]$', 'flags': 'EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'lmap', 'pat': '^lm\%[ap]$', 'flags': 'EXTRA|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'lmapclear', 'pat': '^lmapc\%[lear]$', 'flags': 'BANG|EXTRA|NOTRLCOM|TRLBAR|XFILE', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'lnext', 'pat': '^lne\%[xt]$', 'flags': 'EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'lnewer', 'pat': '^lnew\%[er]$', 'flags': 'RANGE|NOTADR|COUNT|TRLBAR|BANG', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'lnfile', 'pat': '^lnf\%[ile]$', 'flags': 'RANGE|NOTADR|COUNT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'lnoremap', 'pat': '^ln\%[oremap]$', 'flags': 'RANGE|NOTADR|COUNT|TRLBAR|BANG', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'loadkeymap', 'pat': '^loadk\%[eymap]$', 'flags': 'FILE1|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'loadview', 'pat': '^lo\%[adview]$', 'flags': 'CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'lockmarks', 'pat': '^loc\%[kmarks]$', 'flags': 'NEEDARG|EXTRA|NOTRLCOM', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'lockvar', 'pat': '^lockv\%[ar]$', 'flags': 'BANG|EXTRA|NEEDARG|SBOXOK|CMDWIN', 'parser': 'parse_cmd_lockvar'}, | |
\ {'name': 'lolder', 'pat': '^lol\%[der]$', 'flags': 'RANGE|NOTADR|COUNT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'lopen', 'pat': '^lope\%[n]$', 'flags': 'RANGE|NOTADR|COUNT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'lprevious', 'pat': '^lp\%[revious]$', 'flags': 'RANGE|NOTADR|COUNT|TRLBAR|BANG', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'lpfile', 'pat': '^lpf\%[ile]$', 'flags': 'RANGE|NOTADR|COUNT|TRLBAR|BANG', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'lrewind', 'pat': '^lr\%[ewind]$', 'flags': 'RANGE|NOTADR|COUNT|TRLBAR|BANG', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'ls', 'pat': '^ls$', 'flags': 'NOTADR|TRLBAR|BANG|WORD1', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'ltag', 'pat': '^lt\%[ag]$', 'flags': 'RANGE|EXTRA|NEEDARG|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'lunmap', 'pat': '^lu\%[nmap]$', 'flags': 'RANGE|DFLALL|EXTRA|NEEDARG|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'lua', 'pat': '^lua$', 'flags': 'RANGE|FILE1|NEEDARG|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'luado', 'pat': '^luad\%[o]$', 'flags': 'EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'luafile', 'pat': '^luaf\%[ile]$', 'flags': 'RANGE|NOTADR|BANG|NEEDARG|EXTRA|NOTRLCOM|TRLBAR|XFILE', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'lvimgrep', 'pat': '^lv\%[imgrep]$', 'flags': 'RANGE|NOTADR|BANG|NEEDARG|EXTRA|NOTRLCOM|TRLBAR|XFILE', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'lvimgrepadd', 'pat': '^lvimgrepa\%[dd]$', 'flags': 'RANGE|NOTADR|COUNT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'lwindow', 'pat': '^lw\%[indow]$', 'flags': 'BANG|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'move', 'pat': '^m\%[ove]$', 'flags': 'RANGE|WHOLEFOLD|EXTRA|TRLBAR|CMDWIN|MODIFY', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'mark', 'pat': '^ma\%[rk]$', 'flags': 'RANGE|WORD1|TRLBAR|SBOXOK|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'make', 'pat': '^mak\%[e]$', 'flags': 'BANG|EXTRA|NOTRLCOM|TRLBAR|XFILE', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'map', 'pat': '^map$', 'flags': 'BANG|EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'mapclear', 'pat': '^mapc\%[lear]$', 'flags': 'EXTRA|BANG|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'marks', 'pat': '^marks$', 'flags': 'EXTRA|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'match', 'pat': '^mat\%[ch]$', 'flags': 'RANGE|NOTADR|EXTRA|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'menu', 'pat': '^me\%[nu]$', 'flags': 'RANGE|NOTADR|ZEROR|BANG|EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'menutranslate', 'pat': '^menut\%[ranslate]$', 'flags': 'EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'messages', 'pat': '^mes\%[sages]$', 'flags': 'TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'mkexrc', 'pat': '^mk\%[exrc]$', 'flags': 'BANG|FILE1|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'mksession', 'pat': '^mks\%[ession]$', 'flags': 'BANG|FILE1|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'mkspell', 'pat': '^mksp\%[ell]$', 'flags': 'BANG|NEEDARG|EXTRA|NOTRLCOM|TRLBAR|XFILE', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'mkvimrc', 'pat': '^mkv\%[imrc]$', 'flags': 'BANG|FILE1|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'mkview', 'pat': '^mkvie\%[w]$', 'flags': 'BANG|FILE1|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'mode', 'pat': '^mod\%[e]$', 'flags': 'WORD1|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'mzscheme', 'pat': '^mz\%[scheme]$', 'flags': 'RANGE|EXTRA|DFLALL|NEEDARG|CMDWIN|SBOXOK', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'mzfile', 'pat': '^mzf\%[ile]$', 'flags': 'RANGE|FILE1|NEEDARG|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'nbclose', 'pat': '^nbc\%[lose]$', 'flags': 'RANGE|NOTADR|BANG|FILES|EDITCMD|ARGOPT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'nbkey', 'pat': '^nb\%[key]$', 'flags': 'EXTRA|NOTADR|NEEDARG', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'nbstart', 'pat': '^nbs\%[art]$', 'flags': 'TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'next', 'pat': '^n\%[ext]$', 'flags': 'WORD1|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'new', 'pat': '^new$', 'flags': 'BANG|FILE1|RANGE|NOTADR|EDITCMD|ARGOPT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'nmap', 'pat': '^nm\%[ap]$', 'flags': 'EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'nmapclear', 'pat': '^nmapc\%[lear]$', 'flags': 'EXTRA|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'nmenu', 'pat': '^nme\%[nu]$', 'flags': 'RANGE|NOTADR|ZEROR|EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'nnoremap', 'pat': '^nn\%[oremap]$', 'flags': 'EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'nnoremenu', 'pat': '^nnoreme\%[nu]$', 'flags': 'RANGE|NOTADR|ZEROR|EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'noautocmd', 'pat': '^noa\%[utocmd]$', 'flags': 'BANG|EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'noremap', 'pat': '^no\%[remap]$', 'flags': 'NEEDARG|EXTRA|NOTRLCOM', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'nohlsearch', 'pat': '^noh\%[lsearch]$', 'flags': 'TRLBAR|SBOXOK|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'noreabbrev', 'pat': '^norea\%[bbrev]$', 'flags': 'EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'noremenu', 'pat': '^noreme\%[nu]$', 'flags': 'RANGE|NOTADR|ZEROR|BANG|EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'normal', 'pat': '^norm\%[al]$', 'flags': 'RANGE|BANG|EXTRA|NEEDARG|NOTRLCOM|USECTRLV|SBOXOK|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'number', 'pat': '^nu\%[mber]$', 'flags': 'RANGE|WHOLEFOLD|COUNT|EXFLAGS|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'nunmap', 'pat': '^nun\%[map]$', 'flags': 'EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'nunmenu', 'pat': '^nunme\%[nu]$', 'flags': 'EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'oldfiles', 'pat': '^ol\%[dfiles]$', 'flags': 'RANGE|BANG|EXTRA', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'open', 'pat': '^o\%[pen]$', 'flags': 'BANG|TRLBAR|SBOXOK|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'omap', 'pat': '^om\%[ap]$', 'flags': 'EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'omapclear', 'pat': '^omapc\%[lear]$', 'flags': 'EXTRA|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'omenu', 'pat': '^ome\%[nu]$', 'flags': 'RANGE|NOTADR|ZEROR|EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'only', 'pat': '^on\%[ly]$', 'flags': 'BANG|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'onoremap', 'pat': '^ono\%[remap]$', 'flags': 'EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'onoremenu', 'pat': '^onoreme\%[nu]$', 'flags': 'RANGE|NOTADR|ZEROR|EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'options', 'pat': '^opt\%[ions]$', 'flags': 'TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'ounmap', 'pat': '^ou\%[nmap]$', 'flags': 'EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'ounmenu', 'pat': '^ounme\%[nu]$', 'flags': 'EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'ownsyntax', 'pat': '^ow\%[nsyntax]$', 'flags': 'EXTRA|NOTRLCOM|SBOXOK|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'pclose', 'pat': '^pc\%[lose]$', 'flags': 'RANGE|WHOLEFOLD|COUNT|EXFLAGS|TRLBAR|CMDWIN|SBOXOK', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'pedit', 'pat': '^ped\%[it]$', 'flags': 'BANG|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'perl', 'pat': '^pe\%[rl]$', 'flags': 'RANGE|EXTRA|DFLALL|NEEDARG|SBOXOK|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'print', 'pat': '^p\%[rint]$', 'flags': 'RANGE|EXTRA|DFLALL|NEEDARG|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'profdel', 'pat': '^profd\%[el]$', 'flags': 'BANG|FILE1|EDITCMD|ARGOPT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'profile', 'pat': '^prof\%[ile]$', 'flags': 'RANGE|NOTADR|BANG|COUNT|TRLBAR|ZEROR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'promptfind', 'pat': '^pro\%[mptfind]$', 'flags': 'NEEDARG|EXTRA|BANG|TRLBAR|NOTRLCOM|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'promptrepl', 'pat': '^promptr\%[epl]$', 'flags': 'RANGE|NOTADR|BANG|COUNT|TRLBAR|ZEROR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'perldo', 'pat': '^perld\%[o]$', 'flags': 'TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'pop', 'pat': '^po\%[p]$', 'flags': 'EXTRA|RANGE|NOTADR|COUNT|BANG|EDITCMD|ARGOPT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'popup', 'pat': '^pop\%[up]$', 'flags': 'EXTRA|NOTRLCOM|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'ppop', 'pat': '^pp\%[op]$', 'flags': 'EXTRA|NOTRLCOM|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'preserve', 'pat': '^pre\%[serve]$', 'flags': 'BANG|EXTRA|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'previous', 'pat': '^prev\%[ious]$', 'flags': 'EXTRA|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'psearch', 'pat': '^ps\%[earch]$', 'flags': 'BANG|RANGE|WHOLEFOLD|DFLALL|EXTRA', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'ptag', 'pat': '^pt\%[ag]$', 'flags': 'RANGE|NOTADR|BANG|WORD1|TRLBAR|ZEROR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'ptNext', 'pat': '^ptN\%[ext]$', 'flags': 'RANGE|NOTADR|BANG|TRLBAR|ZEROR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'ptfirst', 'pat': '^ptf\%[irst]$', 'flags': 'RANGE|NOTADR|BANG|TRLBAR|ZEROR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'ptjump', 'pat': '^ptj\%[ump]$', 'flags': 'BANG|TRLBAR|WORD1', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'ptlast', 'pat': '^ptl\%[ast]$', 'flags': 'BANG|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'ptnext', 'pat': '^ptn\%[ext]$', 'flags': 'RANGE|NOTADR|BANG|TRLBAR|ZEROR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'ptprevious', 'pat': '^ptp\%[revious]$', 'flags': 'RANGE|NOTADR|BANG|TRLBAR|ZEROR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'ptrewind', 'pat': '^ptr\%[ewind]$', 'flags': 'RANGE|NOTADR|BANG|TRLBAR|ZEROR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'ptselect', 'pat': '^pts\%[elect]$', 'flags': 'BANG|TRLBAR|WORD1', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'put', 'pat': '^pu\%[t]$', 'flags': 'RANGE|WHOLEFOLD|BANG|REGSTR|TRLBAR|ZEROR|CMDWIN|MODIFY', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'pwd', 'pat': '^pw\%[d]$', 'flags': 'TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'py3', 'pat': '^py3$', 'flags': 'RANGE|EXTRA|NEEDARG|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'python3', 'pat': '^python3$', 'flags': 'RANGE|FILE1|NEEDARG|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'py3file', 'pat': '^py3f\%[ile]$', 'flags': 'RANGE|EXTRA|NEEDARG|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'python', 'pat': '^py\%[thon]$', 'flags': 'RANGE|EXTRA|NEEDARG|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'pyfile', 'pat': '^pyf\%[ile]$', 'flags': 'RANGE|FILE1|NEEDARG|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'quit', 'pat': '^q\%[uit]$', 'flags': 'BANG|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'quitall', 'pat': '^quita\%[ll]$', 'flags': 'BANG|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'qall', 'pat': '^qa\%[ll]$', 'flags': 'BANG|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'read', 'pat': '^r\%[ead]$', 'flags': 'BANG|RANGE|WHOLEFOLD|FILE1|ARGOPT|TRLBAR|ZEROR|CMDWIN|MODIFY', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'recover', 'pat': '^rec\%[over]$', 'flags': 'BANG|FILE1|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'redo', 'pat': '^red\%[o]$', 'flags': 'TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'redir', 'pat': '^redi\%[r]$', 'flags': 'BANG|FILES|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'redraw', 'pat': '^redr\%[aw]$', 'flags': 'BANG|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'redrawstatus', 'pat': '^redraws\%[tatus]$', 'flags': 'BANG|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'registers', 'pat': '^reg\%[isters]$', 'flags': 'EXTRA|NOTRLCOM|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'resize', 'pat': '^res\%[ize]$', 'flags': 'RANGE|NOTADR|TRLBAR|WORD1', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'retab', 'pat': '^ret\%[ab]$', 'flags': 'TRLBAR|RANGE|WHOLEFOLD|DFLALL|BANG|WORD1|CMDWIN|MODIFY', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'return', 'pat': '^retu\%[rn]$', 'flags': 'EXTRA|NOTRLCOM|SBOXOK|CMDWIN', 'parser': 'parse_cmd_return'}, | |
\ {'name': 'rewind', 'pat': '^rew\%[ind]$', 'flags': 'EXTRA|BANG|EDITCMD|ARGOPT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'right', 'pat': '^ri\%[ght]$', 'flags': 'TRLBAR|RANGE|WHOLEFOLD|EXTRA|CMDWIN|MODIFY', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'rightbelow', 'pat': '^rightb\%[elow]$', 'flags': 'NEEDARG|EXTRA|NOTRLCOM', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'ruby', 'pat': '^rub\%[y]$', 'flags': 'BANG|NEEDARG|FILES|TRLBAR|SBOXOK|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'rubydo', 'pat': '^rubyd\%[o]$', 'flags': 'RANGE|EXTRA|NEEDARG|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'rubyfile', 'pat': '^rubyf\%[ile]$', 'flags': 'RANGE|DFLALL|EXTRA|NEEDARG|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'rundo', 'pat': '^rund\%[o]$', 'flags': 'RANGE|FILE1|NEEDARG|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'runtime', 'pat': '^ru\%[ntime]$', 'flags': 'NEEDARG|FILE1', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'rviminfo', 'pat': '^rv\%[iminfo]$', 'flags': 'BANG|FILE1|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'substitute', 'pat': '^s\%[ubstitute]$', 'flags': 'RANGE|WHOLEFOLD|EXTRA|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'sNext', 'pat': '^sN\%[ext]$', 'flags': 'EXTRA|RANGE|NOTADR|COUNT|BANG|EDITCMD|ARGOPT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'sandbox', 'pat': '^san\%[dbox]$', 'flags': 'BANG|RANGE|NOTADR|COUNT|EXTRA|EDITCMD|ARGOPT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'sargument', 'pat': '^sa\%[rgument]$', 'flags': 'BANG|RANGE|NOTADR|COUNT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'sall', 'pat': '^sal\%[l]$', 'flags': 'NEEDARG|EXTRA|NOTRLCOM', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'saveas', 'pat': '^sav\%[eas]$', 'flags': 'BANG|DFLALL|FILE1|ARGOPT|CMDWIN|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'sbuffer', 'pat': '^sb\%[uffer]$', 'flags': 'BANG|RANGE|NOTADR|BUFNAME|BUFUNL|COUNT|EXTRA|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'sbNext', 'pat': '^sbN\%[ext]$', 'flags': 'RANGE|NOTADR|COUNT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'sball', 'pat': '^sba\%[ll]$', 'flags': 'RANGE|NOTADR|COUNT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'sbfirst', 'pat': '^sbf\%[irst]$', 'flags': 'TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'sblast', 'pat': '^sbl\%[ast]$', 'flags': 'TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'sbmodified', 'pat': '^sbm\%[odified]$', 'flags': 'RANGE|NOTADR|COUNT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'sbnext', 'pat': '^sbn\%[ext]$', 'flags': 'RANGE|NOTADR|COUNT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'sbprevious', 'pat': '^sbp\%[revious]$', 'flags': 'RANGE|NOTADR|COUNT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'sbrewind', 'pat': '^sbr\%[ewind]$', 'flags': 'TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'scriptnames', 'pat': '^scrip\%[tnames]$', 'flags': 'TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'scriptencoding', 'pat': '^scripte\%[ncoding]', 'flags': 'WORD1|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'scscope', 'pat': '^scs\%[cope]$', 'flags': 'EXTRA|NOTRLCOM', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'set', 'pat': '^se\%[t]$', 'flags': 'TRLBAR|EXTRA|CMDWIN|SBOXOK', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'setfiletype', 'pat': '^setf\%[iletype]$', 'flags': 'TRLBAR|EXTRA|NEEDARG|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'setglobal', 'pat': '^setg\%[lobal]$', 'flags': 'TRLBAR|EXTRA|CMDWIN|SBOXOK', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'setlocal', 'pat': '^setl\%[ocal]$', 'flags': 'TRLBAR|EXTRA|CMDWIN|SBOXOK', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'sfind', 'pat': '^sf\%[ind]$', 'flags': 'BANG|FILE1|RANGE|NOTADR|EDITCMD|ARGOPT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'sfirst', 'pat': '^sfir\%[st]$', 'flags': 'EXTRA|BANG|EDITCMD|ARGOPT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'shell', 'pat': '^sh\%[ell]$', 'flags': 'TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'simalt', 'pat': '^sim\%[alt]$', 'flags': 'NEEDARG|WORD1|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'sign', 'pat': '^sig\%[n]$', 'flags': 'NEEDARG|RANGE|NOTADR|EXTRA|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'silent', 'pat': '^sil\%[ent]$', 'flags': 'NEEDARG|EXTRA|BANG|NOTRLCOM|SBOXOK|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'sleep', 'pat': '^sl\%[eep]$', 'flags': 'RANGE|NOTADR|COUNT|EXTRA|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'slast', 'pat': '^sla\%[st]$', 'flags': 'EXTRA|BANG|EDITCMD|ARGOPT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'smagic', 'pat': '^sm\%[agic]$', 'flags': 'RANGE|WHOLEFOLD|EXTRA|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'smap', 'pat': '^sma\%[p]$', 'flags': 'EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'smapclear', 'pat': '^smapc\%[lear]$', 'flags': 'EXTRA|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'smenu', 'pat': '^sme\%[nu]$', 'flags': 'RANGE|NOTADR|ZEROR|EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'snext', 'pat': '^sn\%[ext]$', 'flags': 'RANGE|NOTADR|BANG|FILES|EDITCMD|ARGOPT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'sniff', 'pat': '^sni\%[ff]$', 'flags': 'EXTRA|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'snomagic', 'pat': '^sno\%[magic]$', 'flags': 'RANGE|WHOLEFOLD|EXTRA|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'snoremap', 'pat': '^snor\%[emap]$', 'flags': 'EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'snoremenu', 'pat': '^snoreme\%[nu]$', 'flags': 'RANGE|NOTADR|ZEROR|EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'sort', 'pat': '^sor\%[t]$', 'flags': 'BANG|FILE1|TRLBAR|SBOXOK|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'source', 'pat': '^so\%[urce]$', 'flags': 'RANGE|DFLALL|WHOLEFOLD|BANG|EXTRA|NOTRLCOM|MODIFY', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'spelldump', 'pat': '^spelld\%[ump]$', 'flags': 'BANG|FILE1|RANGE|NOTADR|EDITCMD|ARGOPT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'spellgood', 'pat': '^spe\%[llgood]$', 'flags': 'BANG|RANGE|NOTADR|NEEDARG|EXTRA|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'spellinfo', 'pat': '^spelli\%[nfo]$', 'flags': 'BANG|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'spellrepall', 'pat': '^spellr\%[epall]$', 'flags': 'TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'spellundo', 'pat': '^spellu\%[ndo]$', 'flags': 'TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'spellwrong', 'pat': '^spellw\%[rong]$', 'flags': 'BANG|RANGE|NOTADR|NEEDARG|EXTRA|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'split', 'pat': '^sp\%[lit]$', 'flags': 'BANG|RANGE|NOTADR|NEEDARG|EXTRA|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'sprevious', 'pat': '^spr\%[evious]$', 'flags': 'EXTRA|RANGE|NOTADR|COUNT|BANG|EDITCMD|ARGOPT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'srewind', 'pat': '^sre\%[wind]$', 'flags': 'EXTRA|BANG|EDITCMD|ARGOPT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'stop', 'pat': '^st\%[op]$', 'flags': 'TRLBAR|BANG|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'stag', 'pat': '^sta\%[g]$', 'flags': 'RANGE|NOTADR|BANG|WORD1|TRLBAR|ZEROR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'startinsert', 'pat': '^star\%[tinsert]$', 'flags': 'BANG|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'startgreplace', 'pat': '^startg\%[replace]$', 'flags': 'BANG|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'startreplace', 'pat': '^startr\%[eplace]$', 'flags': 'BANG|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'stopinsert', 'pat': '^stopi\%[nsert]$', 'flags': 'BANG|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'stjump', 'pat': '^stj\%[ump]$', 'flags': 'BANG|TRLBAR|WORD1', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'stselect', 'pat': '^sts\%[elect]$', 'flags': 'BANG|TRLBAR|WORD1', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'sunhide', 'pat': '^sun\%[hide]$', 'flags': 'RANGE|NOTADR|COUNT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'sunmap', 'pat': '^sunm\%[ap]$', 'flags': 'EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'sunmenu', 'pat': '^sunme\%[nu]$', 'flags': 'EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'suspend', 'pat': '^sus\%[pend]$', 'flags': 'TRLBAR|BANG|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'sview', 'pat': '^sv\%[iew]$', 'flags': 'BANG|FILE1|RANGE|NOTADR|EDITCMD|ARGOPT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'swapname', 'pat': '^sw\%[apname]$', 'flags': 'TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'syntax', 'pat': '^sy\%[ntax]$', 'flags': 'EXTRA|NOTRLCOM|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'syncbind', 'pat': '^sync\%[bind]$', 'flags': 'TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 't', 'pat': '^t$', 'flags': 'RANGE|WHOLEFOLD|EXTRA|TRLBAR|CMDWIN|MODIFY', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'tNext', 'pat': '^tN\%[ext]$', 'flags': 'RANGE|NOTADR|BANG|TRLBAR|ZEROR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'tabNext', 'pat': '^tabN\%[ext]$', 'flags': 'RANGE|NOTADR|BANG|WORD1|TRLBAR|ZEROR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'tabclose', 'pat': '^tabc\%[lose]$', 'flags': 'TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'tabdo', 'pat': '^tabdo$', 'flags': 'NEEDARG|EXTRA|NOTRLCOM', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'tabedit', 'pat': '^tabe\%[dit]$', 'flags': 'RANGE|NOTADR|COUNT|BANG|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'tabfind', 'pat': '^tabf\%[ind]$', 'flags': 'NEEDARG|EXTRA|NOTRLCOM', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'tabfirst', 'pat': '^tabfir\%[st]$', 'flags': 'BANG|FILE1|RANGE|NOTADR|ZEROR|EDITCMD|ARGOPT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'tablast', 'pat': '^tabl\%[ast]$', 'flags': 'BANG|FILE1|RANGE|NOTADR|ZEROR|EDITCMD|ARGOPT|NEEDARG|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'tabmove', 'pat': '^tabm\%[ove]$', 'flags': 'TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'tabnew', 'pat': '^tabnew$', 'flags': 'RANGE|NOTADR|ZEROR|EXTRA|NOSPC|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'tabnext', 'pat': '^tabn\%[ext]$', 'flags': 'TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'tabonly', 'pat': '^tabo\%[nly]$', 'flags': 'RANGE|NOTADR|COUNT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'tabprevious', 'pat': '^tabp\%[revious]$', 'flags': 'BANG|FILE1|RANGE|NOTADR|ZEROR|EDITCMD|ARGOPT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'tabrewind', 'pat': '^tabr\%[ewind]$', 'flags': 'BANG|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'tabs', 'pat': '^tabs$', 'flags': 'RANGE|NOTADR|COUNT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'tab', 'pat': '^tab$', 'flags': 'RANGE|NOTADR|COUNT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'tag', 'pat': '^ta\%[g]$', 'flags': 'TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'tags', 'pat': '^tags$', 'flags': 'TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'tcl', 'pat': '^tc\%[l]$', 'flags': 'RANGE|EXTRA|NEEDARG|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'tcldo', 'pat': '^tcld\%[o]$', 'flags': 'RANGE|DFLALL|EXTRA|NEEDARG|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'tclfile', 'pat': '^tclf\%[ile]$', 'flags': 'RANGE|FILE1|NEEDARG|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'tearoff', 'pat': '^te\%[aroff]$', 'flags': 'NEEDARG|EXTRA|TRLBAR|NOTRLCOM|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'tfirst', 'pat': '^tf\%[irst]$', 'flags': 'RANGE|NOTADR|BANG|TRLBAR|ZEROR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'throw', 'pat': '^th\%[row]$', 'flags': 'EXTRA|NEEDARG|SBOXOK|CMDWIN', 'parser': 'parse_cmd_throw'}, | |
\ {'name': 'tjump', 'pat': '^tj\%[ump]$', 'flags': 'BANG|TRLBAR|WORD1', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'tlast', 'pat': '^tl\%[ast]$', 'flags': 'BANG|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'tmenu', 'pat': '^tm\%[enu]$', 'flags': 'RANGE|NOTADR|ZEROR|EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'tnext', 'pat': '^tn\%[ext]$', 'flags': 'RANGE|NOTADR|BANG|TRLBAR|ZEROR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'topleft', 'pat': '^to\%[pleft]$', 'flags': 'NEEDARG|EXTRA|NOTRLCOM', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'tprevious', 'pat': '^tp\%[revious]$', 'flags': 'RANGE|NOTADR|BANG|TRLBAR|ZEROR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'trewind', 'pat': '^tr\%[ewind]$', 'flags': 'RANGE|NOTADR|BANG|TRLBAR|ZEROR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'try', 'pat': '^try$', 'flags': 'TRLBAR|SBOXOK|CMDWIN', 'parser': 'parse_cmd_try'}, | |
\ {'name': 'tselect', 'pat': '^ts\%[elect]$', 'flags': 'BANG|TRLBAR|WORD1', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'tunmenu', 'pat': '^tu\%[nmenu]$', 'flags': 'EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'undo', 'pat': '^u\%[ndo]$', 'flags': 'RANGE|NOTADR|COUNT|ZEROR|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'undojoin', 'pat': '^undoj\%[oin]$', 'flags': 'TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'undolist', 'pat': '^undol\%[ist]$', 'flags': 'TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'unabbreviate', 'pat': '^una\%[bbreviate]$', 'flags': 'EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'unhide', 'pat': '^unh\%[ide]$', 'flags': 'RANGE|NOTADR|COUNT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'unlet', 'pat': '^unl\%[et]$', 'flags': 'BANG|EXTRA|NEEDARG|SBOXOK|CMDWIN', 'parser': 'parse_cmd_unlet'}, | |
\ {'name': 'unlockvar', 'pat': '^unlo\%[ckvar]$', 'flags': 'BANG|EXTRA|NEEDARG|SBOXOK|CMDWIN', 'parser': 'parse_cmd_unlockvar'}, | |
\ {'name': 'unmap', 'pat': '^unm\%[ap]$', 'flags': 'BANG|EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'unmenu', 'pat': '^unme\%[nu]$', 'flags': 'BANG|EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'unsilent', 'pat': '^uns\%[ilent]$', 'flags': 'NEEDARG|EXTRA|NOTRLCOM|SBOXOK|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'update', 'pat': '^up\%[date]$', 'flags': 'RANGE|WHOLEFOLD|BANG|FILE1|ARGOPT|DFLALL|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'vglobal', 'pat': '^v\%[global]$', 'flags': 'RANGE|WHOLEFOLD|EXTRA|DFLALL|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'version', 'pat': '^ve\%[rsion]$', 'flags': 'EXTRA|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'verbose', 'pat': '^verb\%[ose]$', 'flags': 'NEEDARG|RANGE|NOTADR|EXTRA|NOTRLCOM|SBOXOK|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'vertical', 'pat': '^vert\%[ical]$', 'flags': 'NEEDARG|EXTRA|NOTRLCOM', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'vimgrep', 'pat': '^vim\%[grep]$', 'flags': 'BANG|FILE1|EDITCMD|ARGOPT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'vimgrepadd', 'pat': '^vimgrepa\%[dd]$', 'flags': 'BANG|FILE1|EDITCMD|ARGOPT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'visual', 'pat': '^vi\%[sual]$', 'flags': 'RANGE|NOTADR|BANG|NEEDARG|EXTRA|NOTRLCOM|TRLBAR|XFILE', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'viusage', 'pat': '^viu\%[sage]$', 'flags': 'RANGE|NOTADR|BANG|NEEDARG|EXTRA|NOTRLCOM|TRLBAR|XFILE', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'view', 'pat': '^vie\%[w]$', 'flags': 'TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'vmap', 'pat': '^vm\%[ap]$', 'flags': 'EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'vmapclear', 'pat': '^vmapc\%[lear]$', 'flags': 'EXTRA|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'vmenu', 'pat': '^vme\%[nu]$', 'flags': 'RANGE|NOTADR|ZEROR|EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'vnew', 'pat': '^vne\%[w]$', 'flags': 'EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'vnoremap', 'pat': '^vn\%[oremap]$', 'flags': 'BANG|FILE1|RANGE|NOTADR|EDITCMD|ARGOPT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'vnoremenu', 'pat': '^vnoreme\%[nu]$', 'flags': 'RANGE|NOTADR|ZEROR|EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'vsplit', 'pat': '^vs\%[plit]$', 'flags': 'BANG|FILE1|RANGE|NOTADR|EDITCMD|ARGOPT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'vunmap', 'pat': '^vu\%[nmap]$', 'flags': 'EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'vunmenu', 'pat': '^vunme\%[nu]$', 'flags': 'EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'windo', 'pat': '^windo$', 'flags': 'RANGE|WHOLEFOLD|BANG|FILE1|ARGOPT|DFLALL|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'write', 'pat': '^w\%[rite]$', 'flags': 'RANGE|WHOLEFOLD|NOTADR|BANG|FILE1|ARGOPT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'wNext', 'pat': '^wN\%[ext]$', 'flags': 'BANG|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'wall', 'pat': '^wa\%[ll]$', 'flags': 'EXTRA|NOTRLCOM|SBOXOK|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'while', 'pat': '^wh\%[ile]$', 'flags': 'EXTRA|NEEDARG|TRLBAR', 'parser': 'parse_cmd_while'}, | |
\ {'name': 'winsize', 'pat': '^wi\%[nsize]$', 'flags': 'NEEDARG|WORD1|RANGE|NOTADR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'wincmd', 'pat': '^winc\%[md]$', 'flags': 'BANG|NEEDARG|EXTRA|NOTRLCOM', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'winpos', 'pat': '^winp\%[os]$', 'flags': 'EXTRA|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'wnext', 'pat': '^wn\%[ext]$', 'flags': 'RANGE|NOTADR|BANG|FILE1|ARGOPT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'wprevious', 'pat': '^wp\%[revious]$', 'flags': 'RANGE|NOTADR|BANG|FILE1|ARGOPT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'wq', 'pat': '^wq$', 'flags': 'RANGE|WHOLEFOLD|BANG|FILE1|ARGOPT|DFLALL|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'wqall', 'pat': '^wqa\%[ll]$', 'flags': 'BANG|FILE1|ARGOPT|DFLALL|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'wsverb', 'pat': '^ws\%[verb]$', 'flags': 'EXTRA|NOTADR|NEEDARG', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'wundo', 'pat': '^wu\%[ndo]$', 'flags': 'BANG|NEEDARG|FILE1', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'wviminfo', 'pat': '^wv\%[iminfo]$', 'flags': 'BANG|FILE1|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'xit', 'pat': '^x\%[it]$', 'flags': 'RANGE|WHOLEFOLD|BANG|FILE1|ARGOPT|DFLALL|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'xall', 'pat': '^xa\%[ll]$', 'flags': 'BANG|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'xmapclear', 'pat': '^xmapc\%[lear]$', 'flags': 'EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'xmap', 'pat': '^xm\%[ap]$', 'flags': 'EXTRA|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'xmenu', 'pat': '^xme\%[nu]$', 'flags': 'RANGE|NOTADR|ZEROR|EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'xnoremap', 'pat': '^xn\%[oremap]$', 'flags': 'EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'xnoremenu', 'pat': '^xnoreme\%[nu]$', 'flags': 'RANGE|NOTADR|ZEROR|EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'xunmap', 'pat': '^xu\%[nmap]$', 'flags': 'EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'xunmenu', 'pat': '^xunme\%[nu]$', 'flags': 'EXTRA|TRLBAR|NOTRLCOM|USECTRLV|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'yank', 'pat': '^y\%[ank]$', 'flags': 'RANGE|WHOLEFOLD|REGSTR|COUNT|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'z', 'pat': '^z$', 'flags': 'RANGE|WHOLEFOLD|EXTRA|EXFLAGS|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': '!', 'pat': '^!$', 'flags': 'RANGE|WHOLEFOLD|BANG|FILES|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': '#', 'pat': '^#$', 'flags': 'RANGE|WHOLEFOLD|COUNT|EXFLAGS|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': '&', 'pat': '^&$', 'flags': 'RANGE|WHOLEFOLD|EXTRA|CMDWIN|MODIFY', 'parser': 'parse_cmd_common'}, | |
\ {'name': '*', 'pat': '^*$', 'flags': 'RANGE|WHOLEFOLD|EXTRA|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': '<', 'pat': '^<$', 'flags': 'RANGE|WHOLEFOLD|COUNT|EXFLAGS|TRLBAR|CMDWIN|MODIFY', 'parser': 'parse_cmd_common'}, | |
\ {'name': '=', 'pat': '^=$', 'flags': 'RANGE|TRLBAR|DFLALL|EXFLAGS|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': '>', 'pat': '^>$', 'flags': 'RANGE|WHOLEFOLD|COUNT|EXFLAGS|TRLBAR|CMDWIN|MODIFY', 'parser': 'parse_cmd_common'}, | |
\ {'name': '@', 'pat': '^@$', 'flags': 'RANGE|WHOLEFOLD|EXTRA|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'Next', 'pat': '^N\%[ext]$', 'flags': 'EXTRA|RANGE|NOTADR|COUNT|BANG|EDITCMD|ARGOPT|TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'Print', 'pat': '^P\%[rint]$', 'flags': 'RANGE|WHOLEFOLD|COUNT|EXFLAGS|TRLBAR|CMDWIN', 'parser': 'parse_cmd_common'}, | |
\ {'name': 'X', 'pat': '^X$', 'flags': 'TRLBAR', 'parser': 'parse_cmd_common'}, | |
\ {'name': '~', 'pat': '^\~$', 'flags': 'RANGE|WHOLEFOLD|EXTRA|CMDWIN|MODIFY', 'parser': 'parse_cmd_common'}, | |
\] | |
let s:ExprTokenizer = {} | |
function s:ExprTokenizer.new(...) | |
let obj = copy(self) | |
call call(obj.__init__, a:000, obj) | |
return obj | |
endfunction | |
function s:ExprTokenizer.__init__(reader) | |
let self.reader = a:reader | |
endfunction | |
function s:ExprTokenizer.token(type, value) | |
return {'type': a:type, 'value': a:value} | |
endfunction | |
function s:ExprTokenizer.peek() | |
let pos = self.reader.getpos() | |
let r = self.get() | |
call self.reader.setpos(pos) | |
return r | |
endfunction | |
function s:ExprTokenizer.get() | |
while 1 | |
let r = self.get_keepspace() | |
if r.type != 'SPACE' | |
return r | |
endif | |
endwhile | |
endfunction | |
function s:ExprTokenizer.peek_keepspace() | |
let pos = self.reader.getpos() | |
let r = self.get_keepspace() | |
call self.reader.setpos(pos) | |
return r | |
endfunction | |
function s:ExprTokenizer.get_keepspace() | |
while 1 | |
let s = self.reader.peek(10) | |
if s == '' | |
return self.token('EOF', 'EOF') | |
elseif s =~ '^\s' | |
let s = '' | |
while self.reader.peek() =~ '\s' | |
let s .= self.reader.get() | |
endwhile | |
return self.token('SPACE', s) | |
elseif s =~ '\v^%(\r\n|\r|\n)' | |
let s = self.reader.get() | |
if s == "\r" && self.reader.peek() == "\n" | |
let s .= self.reader.get() | |
endif | |
return self.token('NEWLINE', s) | |
elseif s =~ '^\d' | |
let s = '' | |
while self.reader.peek() =~ '\d' | |
let s .= self.reader.get() | |
endwhile | |
if self.reader.peek(2) =~ '\.\d' | |
let s .= self.reader.get() | |
while self.reader.peek() =~ '\d' | |
let s .= self.reader.get() | |
endwhile | |
endif | |
return self.token('NUMBER', s) | |
elseif s =~# '^is#' | |
call self.reader.get(3) | |
return self.token('ISH', 'is#') | |
elseif s=~# '^is?' | |
call self.reader.get(3) | |
return self.token('ISQ', 'is?') | |
elseif s =~# '^isnot#' | |
call self.reader.get(6) | |
return self.token('ISNOTH', 'is#') | |
elseif s =~# '^isnot?' | |
call self.reader.get(6) | |
return self.token('ISNOTQ', 'is?') | |
elseif s =~# '^is\>' | |
call self.reader.get(2) | |
return self.token('IS', 'is') | |
elseif s =~# '^isnot\>' | |
call self.reader.get(5) | |
return self.token('ISNOT', 'isnot') | |
elseif s =~ '^\h' | |
let s = self.reader.get() | |
while self.reader.peek() =~ '\w\|[:#]' | |
let s .= self.reader.get() | |
endwhile | |
return self.token('IDENTIFIER', s) | |
elseif s =~ '^==?' | |
call self.reader.get(3) | |
return self.token('EQEQQ', '==?') | |
elseif s =~ '^==#' | |
call self.reader.get(3) | |
return self.token('EQEQH', '==#') | |
elseif s =~ '^!=?' | |
call self.reader.get(3) | |
return self.token('NOTEQQ', '!=?') | |
elseif s =~ '^!=#' | |
call self.reader.get(3) | |
return self.token('NOTEQH', '!=#') | |
elseif s =~ '^>=?' | |
call self.reader.get(3) | |
return self.token('GTEQQ', '>=?') | |
elseif s =~ '^>=#' | |
call self.reader.get(3) | |
return self.token('GTEQH', '>=#') | |
elseif s =~ '^<=?' | |
call self.reader.get(3) | |
return self.token('LTEQQ', '<=?') | |
elseif s =~ '^<=#' | |
call self.reader.get(3) | |
return self.token('LTEQH', '<=#') | |
elseif s =~ '^=\~?' | |
call self.reader.get(3) | |
return self.token('EQTILDQ', '=\~?') | |
elseif s =~ '^=\~#' | |
call self.reader.get(3) | |
return self.token('EQTILDH', '=\~#') | |
elseif s =~ '^!\~?' | |
call self.reader.get(3) | |
return self.token('NOTTILDQ', '!\~?') | |
elseif s =~ '^!\~#' | |
call self.reader.get(3) | |
return self.token('NOTTILDH', '!\~#') | |
elseif s =~ '^>?' | |
call self.reader.get(2) | |
return self.token('GTQ', '>?') | |
elseif s =~ '^>#' | |
call self.reader.get(2) | |
return self.token('GTH', '>#') | |
elseif s =~ '^<?' | |
call self.reader.get(2) | |
return self.token('LTQ', '<?') | |
elseif s =~ '^<#' | |
call self.reader.get(2) | |
return self.token('LTH', '<#') | |
elseif s =~ '^||' | |
call self.reader.get(2) | |
return self.token('OROR', '||') | |
elseif s =~ '^&&' | |
call self.reader.get(2) | |
return self.token('ANDAND', '&&') | |
elseif s =~ '^==' | |
call self.reader.get(2) | |
return self.token('EQEQ', '==') | |
elseif s =~ '^!=' | |
call self.reader.get(2) | |
return self.token('NOTEQ', '!=') | |
elseif s =~ '^>=' | |
call self.reader.get(2) | |
return self.token('GTEQ', '>=') | |
elseif s =~ '^<=' | |
call self.reader.get(2) | |
return self.token('LTEQ', '<=') | |
elseif s =~ '^=\~' | |
call self.reader.get(2) | |
return self.token('EQTILD', '=\~') | |
elseif s =~ '^!\~' | |
call self.reader.get(2) | |
return self.token('NOTTILD', '!\~') | |
elseif s =~ '^>' | |
call self.reader.get(1) | |
return self.token('GT', '>') | |
elseif s =~ '^<' | |
call self.reader.get(1) | |
return self.token('LT', '<') | |
elseif s =~ '^+' | |
call self.reader.get(1) | |
return self.token('PLUS', '+') | |
elseif s =~ '^-' | |
call self.reader.get(1) | |
return self.token('MINUS', '-') | |
elseif s =~ '^\.' | |
call self.reader.get(1) | |
return self.token('DOT', '.') | |
elseif s =~ '^*' | |
call self.reader.get(1) | |
return self.token('STAR', '*') | |
elseif s =~ '^/' | |
call self.reader.get(1) | |
return self.token('SLASH', '/') | |
elseif s =~ '^%' | |
call self.reader.get(1) | |
return self.token('PER', '%') | |
elseif s =~ '^!' | |
call self.reader.get(1) | |
return self.token('NOT', '!') | |
elseif s =~ '^?' | |
call self.reader.get(1) | |
return self.token('QUESTION', '?') | |
elseif s =~ '^:' | |
call self.reader.get(1) | |
return self.token('COLON', ':') | |
elseif s =~ '^(' | |
call self.reader.get(1) | |
return self.token('LPAR', '(') | |
elseif s =~ '^)' | |
call self.reader.get(1) | |
return self.token('RPAR', ')') | |
elseif s =~ '^[' | |
call self.reader.get(1) | |
return self.token('LBRA', '[') | |
elseif s =~ '^]' | |
call self.reader.get(1) | |
return self.token('RBRA', ']') | |
elseif s =~ '^{' | |
call self.reader.get(1) | |
return self.token('LBPAR', '{') | |
elseif s =~ '^}' | |
call self.reader.get(1) | |
return self.token('RBPAR', '}') | |
elseif s =~ '^,' | |
call self.reader.get(1) | |
return self.token('COMMA', ',') | |
elseif s =~ "^'" | |
call self.reader.get(1) | |
return self.token('SQUOTE', "'") | |
elseif s =~ '^"' | |
call self.reader.get(1) | |
return self.token('DQUOTE', '"') | |
elseif s =~ '^\$\w\+' | |
let s = self.reader.get() | |
while self.reader.peek() =~ '\w' | |
let s .= self.reader.get() | |
endwhile | |
return self.token('ENV', s) | |
elseif s =~ '^@\a' | |
return self.token('REG', self.reader.get(2)) | |
elseif s =~ '^&\(g:\|l:\|\w\w\)' | |
let s = self.reader.get(3) | |
while self.reader.peek() =~ '\w' | |
let s .= self.reader.get() | |
endwhile | |
return self.token('OPTION', s) | |
elseif s =~ '^=' | |
call self.reader.get(1) | |
return self.token('EQ', '=') | |
elseif s =~ '^|' | |
call self.reader.get(1) | |
return self.token('OR', '|') | |
elseif s =~ '^;' | |
call self.reader.get(1) | |
return self.token('SEMICOLON', ';') | |
else | |
throw printf('ExprTokenizer: %s', s) | |
endif | |
endwhile | |
endfunction | |
function s:ExprTokenizer.get_sstring() | |
let s = '' | |
while self.reader.peek() =~ '\s' | |
call self.reader.get() | |
endwhile | |
let c = self.reader.get() | |
if c != "'" | |
throw printf('ExprTokenizer: unexpected character: %s', c) | |
endif | |
while 1 | |
let c = self.reader.get() | |
if c == '' || c == "\n" | |
throw 'ExprTokenizer: unexpected EOL' | |
elseif c == "'" | |
if self.reader.peek() == "'" | |
let s .= c | |
else | |
break | |
endif | |
else | |
let s .= c | |
endif | |
endwhile | |
return s | |
endfunction | |
function s:ExprTokenizer.get_dstring() | |
let s = '' | |
while self.reader.peek() =~ '\s' | |
call self.reader.get() | |
endwhile | |
let c = self.reader.get() | |
if c != '"' | |
throw printf('ExprTokenizer: unexpected character: %s', c) | |
endif | |
while 1 | |
let c = self.reader.get() | |
if c == '' || c == "\n" | |
throw 'ExprTokenizer: unexpectd EOL' | |
elseif c == '"' | |
break | |
elseif c == '\' | |
let s .= c | |
let c = self.reader.get() | |
if c == '' || c == "\n" | |
throw 'ExprTokenizer: unexpected EOL' | |
endif | |
let s .= c | |
else | |
let s .= c | |
endif | |
endwhile | |
return s | |
endfunction | |
let s:ExprParser = {} | |
function s:ExprParser.new(...) | |
let obj = copy(self) | |
call call(obj.__init__, a:000, obj) | |
return obj | |
endfunction | |
function s:ExprParser.__init__(tokenizer) | |
let self.tokenizer = a:tokenizer | |
endfunction | |
function s:ExprParser.node(type, value) | |
return {'type': a:type, 'value': a:value} | |
endfunction | |
function s:ExprParser.parse() | |
return self.parse_expr1() | |
endfunction | |
" expr1: expr2 ? expr1 : expr1 | |
function s:ExprParser.parse_expr1() | |
let lhs = self.parse_expr2() | |
let token = self.tokenizer.peek() | |
if token.type == 'QUESTION' | |
call self.tokenizer.get() | |
let t = self.parse_expr1() | |
let token = self.tokenizer.peek() | |
if token.type != 'COLON' | |
throw printf('ExprParser: unexpected token: %s', token.value) | |
endif | |
call self.tokenizer.get() | |
let e = self.parse_expr1() | |
let lhs = self.node('CONDEXP', [lhs, t, e]) | |
endif | |
return lhs | |
endfunction | |
" expr2: expr3 || expr3 .. | |
function s:ExprParser.parse_expr2() | |
let lhs = self.parse_expr3() | |
let token = self.tokenizer.peek() | |
while token.type == 'OROR' | |
call self.tokenizer.get() | |
let rhs = self.parse_expr3() | |
let lhs = self.node('LOGOR', [lhs, rhs]) | |
let token = self.tokenizer.peek() | |
endwhile | |
return lhs | |
endfunction | |
" expr3: expr4 && expr4 | |
function s:ExprParser.parse_expr3() | |
let lhs = self.parse_expr4() | |
let token = self.tokenizer.peek() | |
while token.type == 'ANDAND' | |
call self.tokenizer.get() | |
let rhs = self.parse_expr4() | |
let lhs = self.node('LOGAND', [lhs, rhs]) | |
let token = self.tokenizer.peek() | |
endwhile | |
return lhs | |
endfunction | |
" expr4: expr5 == expr5 | |
" expr5 != expr5 | |
" expr5 > expr5 | |
" expr5 >= expr5 | |
" expr5 < expr5 | |
" expr5 <= expr5 | |
" expr5 =~ expr5 | |
" expr5 !~ expr5 | |
" | |
" expr5 ==? expr5 | |
" expr5 ==# expr5 | |
" etc. | |
" | |
" expr5 is expr5 | |
" expr5 isnot expr5 | |
function s:ExprParser.parse_expr4() | |
let lhs = self.parse_expr5() | |
let token = self.tokenizer.peek() | |
if token.type == 'EQEQQ' | |
call self.tokenizer.get() | |
let rhs = self.parse_expr5() | |
let lhs = self.node('EQEQQ', [lhs, rhs]) | |
elseif token.type == 'EQEQH' | |
call self.tokenizer.get() | |
let rhs = self.parse_expr5() | |
let lhs = self.node('EQEQH', [lhs, rhs]) | |
elseif token.type == 'NOTEQQ' | |
call self.tokenizer.get() | |
let rhs = self.parse_expr5() | |
let lhs = self.node('NOTEQQ', [lhs, rhs]) | |
elseif token.type == 'NOTEQH' | |
call self.tokenizer.get() | |
let rhs = self.parse_expr5() | |
let lhs = self.node('NOTEQH', [lhs, rhs]) | |
elseif token.type == 'GTEQQ' | |
call self.tokenizer.get() | |
let rhs = self.parse_expr5() | |
let lhs = self.node('GTEQQ', [lhs, rhs]) | |
elseif token.type == 'GTEQH' | |
call self.tokenizer.get() | |
let rhs = self.parse_expr5() | |
let lhs = self.node('GTEQH', [lhs, rhs]) | |
elseif token.type == 'LTEQQ' | |
call self.tokenizer.get() | |
let rhs = self.parse_expr5() | |
let lhs = self.node('LTEQQ', [lhs, rhs]) | |
elseif token.type == 'LTEQH' | |
call self.tokenizer.get() | |
let rhs = self.parse_expr5() | |
let lhs = self.node('LTEQH', [lhs, rhs]) | |
elseif token.type == 'EQTILDQ' | |
call self.tokenizer.get() | |
let rhs = self.parse_expr5() | |
let lhs = self.node('EQTILDQ', [lhs, rhs]) | |
elseif token.type == 'EQTILDH' | |
call self.tokenizer.get() | |
let rhs = self.parse_expr5() | |
let lhs = self.node('EQTILDH', [lhs, rhs]) | |
elseif token.type == 'NOTTILDQ' | |
call self.tokenizer.get() | |
let rhs = self.parse_expr5() | |
let lhs = self.node('NOTTILDQ', [lhs, rhs]) | |
elseif token.type == 'NOTTILDH' | |
call self.tokenizer.get() | |
let rhs = self.parse_expr5() | |
let lhs = self.node('NOTTILDH', [lhs, rhs]) | |
elseif token.type == 'GTQ' | |
call self.tokenizer.get() | |
let rhs = self.parse_expr5() | |
let lhs = self.node('GTQ', [lhs, rhs]) | |
elseif token.type == 'GTH' | |
call self.tokenizer.get() | |
let rhs = self.parse_expr5() | |
let lhs = self.node('GTH', [lhs, rhs]) | |
elseif token.type == 'LTQ' | |
call self.tokenizer.get() | |
let rhs = self.parse_expr5() | |
let lhs = self.node('LTQ', [lhs, rhs]) | |
elseif token.type == 'LTH' | |
call self.tokenizer.get() | |
let rhs = self.parse_expr5() | |
let lhs = self.node('LTH', [lhs, rhs]) | |
elseif token.type == 'EQEQ' | |
call self.tokenizer.get() | |
let rhs = self.parse_expr5() | |
let lhs = self.node('EQEQ', [lhs, rhs]) | |
elseif token.type == 'NOTEQ' | |
call self.tokenizer.get() | |
let rhs = self.parse_expr5() | |
let lhs = self.node('NOTEQ', [lhs, rhs]) | |
elseif token.type == 'GTEQ' | |
call self.tokenizer.get() | |
let rhs = self.parse_expr5() | |
let lhs = self.node('GTEQ', [lhs, rhs]) | |
elseif token.type == 'LTEQ' | |
call self.tokenizer.get() | |
let rhs = self.parse_expr5() | |
let lhs = self.node('LTEQ', [lhs, rhs]) | |
elseif token.type == 'EQTILD' | |
call self.tokenizer.get() | |
let rhs = self.parse_expr5() | |
let lhs = self.node('EQTILD', [lhs, rhs]) | |
elseif token.type == 'NOTTILD' | |
call self.tokenizer.get() | |
let rhs = self.parse_expr5() | |
let lhs = self.node('NOTTILD', [lhs, rhs]) | |
elseif token.type == 'GT' | |
call self.tokenizer.get() | |
let rhs = self.parse_expr5() | |
let lhs = self.node('GT', [lhs, rhs]) | |
elseif token.type == 'LT' | |
call self.tokenizer.get() | |
let rhs = self.parse_expr5() | |
let lhs = self.node('LT', [lhs, rhs]) | |
elseif token.type == 'ISH' | |
call self.tokenizer.get() | |
let rhs = self.parse_expr5() | |
let lhs = self.node('ISH', [lhs, rhs]) | |
elseif token.type == 'ISQ' | |
call self.tokenizer.get() | |
let rhs = self.parse_expr5() | |
let lhs = self.node('ISQ', [lhs, rhs]) | |
elseif token.type == 'ISNOTH' | |
call self.tokenizer.get() | |
let rhs = self.parse_expr5() | |
let lhs = self.node('ISNOTH', [lhs, rhs]) | |
elseif token.type == 'ISNOTQ' | |
call self.tokenizer.get() | |
let rhs = self.parse_expr5() | |
let lhs = self.node('ISNOTQ', [lhs, rhs]) | |
elseif token.type == 'IS' | |
call self.tokenizer.get() | |
let rhs = self.parse_expr5() | |
let lhs = self.node('IS', [lhs, rhs]) | |
elseif token.type == 'ISNOT' | |
call self.tokenizer.get() | |
let rhs = self.parse_expr5() | |
let lhs = self.node('ISNOT', [lhs, rhs]) | |
endif | |
return lhs | |
endfunction | |
" expr5: expr6 + expr6 .. | |
" expr6 - expr6 .. | |
" expr6 . expr6 .. | |
function s:ExprParser.parse_expr5() | |
let lhs = self.parse_expr6() | |
while 1 | |
let token = self.tokenizer.peek() | |
if token.type == 'PLUS' | |
call self.tokenizer.get() | |
let rhs = self.parse_expr6() | |
let lhs = self.node('ADD', [lhs,rhs]) | |
continue | |
elseif token.type == 'MINUS' | |
call self.tokenizer.get() | |
let rhs = self.parse_expr6() | |
let lhs = self.node('SUB', [lhs, rhs]) | |
continue | |
elseif token.type == 'DOT' | |
call self.tokenizer.get() | |
let rhs = self.parse_expr6() | |
let lhs = self.node('CONCAT', [lhs, rhs]) | |
continue | |
endif | |
break | |
endwhile | |
return lhs | |
endfunction | |
" expr6: expr7 * expr7 .. | |
" expr7 / expr7 .. | |
" expr7 % expr7 .. | |
function s:ExprParser.parse_expr6() | |
let lhs = self.parse_expr7() | |
while 1 | |
let token = self.tokenizer.peek() | |
if token.type == 'STAR' | |
call self.tokenizer.get() | |
let rhs = self.parse_expr7() | |
let lhs = self.node('MUL', [lhs, rhs]) | |
continue | |
elseif token.type == 'SLASH' | |
call self.tokenizer.get() | |
let rhs = self.parse_expr7() | |
let lhs = self.node('DIV', [lhs, rhs]) | |
continue | |
elseif token.type == 'PER' | |
call self.tokenizer.get() | |
let rhs = self.parse_expr7() | |
let lhs = self.node('MOD', [lhs, rhs]) | |
continue | |
endif | |
break | |
endwhile | |
return lhs | |
endfunction | |
" expr7: ! expr7 | |
" - expr7 | |
" + expr7 | |
function s:ExprParser.parse_expr7() | |
let token = self.tokenizer.peek() | |
if token.type == 'NOT' | |
call self.tokenizer.get() | |
let e = self.parse_expr7() | |
return self.node('NOT', e) | |
elseif token.type == 'PLUS' | |
call self.tokenizer.get() | |
let e = self.parse_expr7() | |
return self.node('PLUS', e) | |
elseif token.type == 'MINUS' | |
call self.tokenizer.get() | |
let e = self.parse_expr7() | |
return self.node('MINUS', e) | |
else | |
return self.parse_expr8() | |
endif | |
endfunction | |
" expr8: expr8[expr1] | |
" expr8[expr1 : expr1] | |
" expr8.name | |
" expr8(expr1, ...) | |
function s:ExprParser.parse_expr8() | |
let lhs = self.parse_expr9() | |
while 1 | |
let token = self.tokenizer.peek() | |
let token2 = self.tokenizer.peek_keepspace() | |
if token.type == 'LBRA' | |
call self.tokenizer.get() | |
let token = self.tokenizer.peek() | |
if token.type == 'COLON' | |
call self.tokenizer.get() | |
let e1 = s:NIL | |
else | |
let e1 = self.parse_expr1() | |
endif | |
let token = self.tokenizer.peek() | |
if token.type == 'RBRA' | |
call self.tokenizer.get() | |
if e1 == s:NIL | |
let e2 = s:NIL | |
let lhs = self.node('SLICE', [lhs, e1, e2]) | |
else | |
let lhs = self.node('INDEX', [lhs, e1]) | |
endif | |
elseif token.type == 'COLON' | |
call self.tokenizer.get() | |
let token = self.tokenizer.peek() | |
if token.type == 'COLON' | |
call self.tokenizer.get() | |
let e2 = s:NIL | |
else | |
let e2 = self.parse_expr1() | |
endif | |
let token = self.tokenizer.peek() | |
if token.type == 'RBRA' | |
call self.tokenizer.get() | |
let lhs = self.node('SLICE', [lhs, e1, e2]) | |
else | |
throw printf('ExprParser: unexpected token: %s', token.value) | |
endif | |
else | |
throw printf('ExprParser: unexpected token: %s', token.value) | |
endif | |
continue | |
elseif token.type == 'LPAR' | |
call self.tokenizer.get() | |
let args = [] | |
let token = self.tokenizer.peek() | |
if token.type == 'RPAR' | |
call self.tokenizer.get() | |
else | |
while 1 | |
let node = self.parse_expr1() | |
call add(args, node) | |
let token = self.tokenizer.peek() | |
if token.type == 'COMMA' | |
call self.tokenizer.get() | |
continue | |
elseif token.type == 'RPAR' | |
call self.tokenizer.get() | |
break | |
else | |
throw printf('ExprParser: unexpected token: %s', token.value) | |
endif | |
endwhile | |
endif | |
let lhs = self.node('CALL', [lhs, args]) | |
continue | |
elseif token2.type == 'DOT' | |
" INDEX or CONCAT | |
let pos = self.tokenizer.reader.getpos() | |
call self.tokenizer.get() | |
let token2 = self.tokenizer.peek_keepspace() | |
if token2.type == 'IDENTIFIER' | |
call self.tokenizer.get() | |
let node = self.node('IDENTIFIER', token2.value) | |
let lhs = self.node('DOT', [lhs, node]) | |
continue | |
endif | |
call self.tokenizer.reader.setpos(pos) | |
" to be CONCAT | |
break | |
endif | |
break | |
endwhile | |
return lhs | |
endfunction | |
" expr9: number | |
" "string" | |
" 'string' | |
" [expr1, ...] | |
" {expr1: expr1, ...} | |
" &option | |
" (expr1) | |
" variable | |
" var{ria}ble | |
" $VAR | |
" @r | |
" function(expr1, ...) | |
" func{ti}on(expr1, ...) | |
function s:ExprParser.parse_expr9() | |
let token = self.tokenizer.peek() | |
if token.type == 'NUMBER' | |
call self.tokenizer.get() | |
return self.node('NUMBER', token.value) | |
elseif token.type == 'DQUOTE' | |
let e = self.tokenizer.get_dstring() | |
return self.node('STRING', '"' . e . '"') | |
elseif token.type == 'SQUOTE' | |
let e = self.tokenizer.get_sstring() | |
return self.node('STRING', "'" . e . "'") | |
elseif token.type == 'LBRA' | |
call self.tokenizer.get() | |
let list = [] | |
let token = self.tokenizer.peek() | |
if token.type == 'RBRA' | |
call self.tokenizer.get() | |
else | |
while 1 | |
let node = self.parse_expr1() | |
call add(list, node) | |
let token = self.tokenizer.peek() | |
if token.type == 'COMMA' | |
call self.tokenizer.get() | |
if self.tokenizer.peek().type == 'RBRA' | |
call self.tokenizer.get() | |
break | |
endif | |
continue | |
elseif token.type == 'RBRA' | |
call self.tokenizer.get() | |
break | |
else | |
throw printf('ExprParser: unexpected token: %s', token.value) | |
endif | |
endwhile | |
endif | |
return self.node('LIST', list) | |
elseif token.type == 'LBPAR' | |
call self.tokenizer.get() | |
let token = self.tokenizer.peek() | |
let dict = [] | |
if token.type == 'RBPAR' | |
call self.tokenizer.get() | |
else | |
while 1 | |
let key = self.parse_expr1() | |
let token = self.tokenizer.get() | |
if token.type != 'COLON' | |
throw printf('ExprParser: unexpected token: %s', token.value) | |
endif | |
let val = self.parse_expr1() | |
call add(dict, [key, val]) | |
let token = self.tokenizer.peek() | |
if token.type == 'COMMA' | |
call self.tokenizer.get() | |
if self.tokenizer.peek().type == 'LBPAR' | |
call self.tokenizer.get() | |
break | |
endif | |
continue | |
elseif token.type == 'RBPAR' | |
call self.tokenizer.get() | |
break | |
else | |
throw printf('ExprParser: unexpected token: %s', token.value) | |
endif | |
endwhile | |
endif | |
return self.node('DICT', dict) | |
elseif token.type == 'LPAR' | |
call self.tokenizer.get() | |
let e = self.parse_expr1() | |
let token = self.tokenizer.get() | |
if token.type == 'RPAR' | |
return e | |
else | |
throw printf('ExprParser: unexpected token: %s', token.value) | |
endif | |
elseif token.type == 'OPTION' | |
call self.tokenizer.get() | |
return self.node('OPTION', token.value) | |
elseif token.type == 'IDENTIFIER' | |
call self.tokenizer.get() | |
return self.node('IDENTIFIER', token.value) | |
elseif token.type == 'ENV' | |
call self.tokenizer.get() | |
return self.node('ENV', token.value) | |
elseif token.type == 'REG' | |
call self.tokenizer.get() | |
return self.node('REG', token.value) | |
else | |
throw printf('ExprParser: unexpected token: %s', token.value) | |
endif | |
endfunction | |
let s:LvalueParser = {} | |
function s:LvalueParser.new(...) | |
let obj = copy(self) | |
call call(obj.__init__, a:000, obj) | |
return obj | |
endfunction | |
function s:LvalueParser.__init__(tokenizer) | |
let self.tokenizer = a:tokenizer | |
endfunction | |
function s:LvalueParser.node(type, value) | |
return {'type': a:type, 'value': a:value} | |
endfunction | |
function s:LvalueParser.parse() | |
return self.parse_expr8() | |
endfunction | |
" expr8: expr8[expr1] | |
" expr8[expr1 : expr1] | |
" expr8.name | |
function s:LvalueParser.parse_expr8() | |
let p = s:ExprParser.new(self.tokenizer) | |
let lhs = self.parse_expr9() | |
while 1 | |
let token = self.tokenizer.peek() | |
let token2 = self.tokenizer.peek_keepspace() | |
if token.type == 'LBRA' | |
call self.tokenizer.get() | |
let token = self.tokenizer.peek() | |
if token.type == 'COLON' | |
call self.tokenizer.get() | |
let e1 = s:NIL | |
else | |
let e1 = p.parse_expr1() | |
endif | |
let token = self.tokenizer.peek() | |
if token.type == 'RBRA' | |
call self.tokenizer.get() | |
if e1 == s:NIL | |
let e2 = s:NIL | |
let lhs = self.node('SLICE', [lhs, e1, e2]) | |
else | |
let lhs = self.node('INDEX', [lhs, e1]) | |
endif | |
elseif token.type == 'COLON' | |
call self.tokenizer.get() | |
let token = self.tokenizer.peek() | |
if token.type == 'COLON' | |
call self.tokenizer.get() | |
let e2 = s:NIL | |
else | |
let e2 = p.parse_expr1() | |
endif | |
let token = self.tokenizer.peek() | |
if token.type == 'RBRA' | |
call self.tokenizer.get() | |
let lhs = self.node('SLICE', [lhs, e1, e2]) | |
else | |
throw printf('LvalueParser: unexpected token: %s', token.value) | |
endif | |
else | |
throw printf('LvalueParser: unexpected token: %s', token.value) | |
endif | |
continue | |
elseif token2.type == 'DOT' | |
" INDEX or CONCAT | |
let pos = self.tokenizer.reader.getpos() | |
call self.tokenizer.get() | |
let token2 = self.tokenizer.peek_keepspace() | |
if token2.type == 'IDENTIFIER' | |
call self.tokenizer.get() | |
let node = self.node('IDENTIFIER', token2.value) | |
let lhs = self.node('DOT', [lhs, node]) | |
continue | |
endif | |
call self.tokenizer.reader.setpos(pos) | |
" to be CONCAT | |
break | |
endif | |
break | |
endwhile | |
return lhs | |
endfunction | |
" expr9: &option | |
" variable | |
" var{ria}ble | |
" $VAR | |
" @r | |
function s:LvalueParser.parse_expr9() | |
let token = self.tokenizer.peek() | |
if token.type == 'OPTION' | |
call self.tokenizer.get() | |
return self.node('OPTION', token.value) | |
elseif token.type == 'IDENTIFIER' | |
call self.tokenizer.get() | |
return self.node('IDENTIFIER', token.value) | |
elseif token.type == 'ENV' | |
call self.tokenizer.get() | |
return self.node('ENV', token.value) | |
elseif token.type == 'REG' | |
call self.tokenizer.get() | |
return self.node('REG', token.value) | |
else | |
throw printf('LvalueParser: unexpected token: %s', token.value) | |
endif | |
endfunction | |
let s:StringReader = {} | |
function s:StringReader.new(...) | |
let obj = copy(self) | |
call call(obj.__init__, a:000, obj) | |
return obj | |
endfunction | |
function s:StringReader.__init__(str) | |
let self.buf = split(a:str, '\zs') | |
let self.i = 0 | |
let self.lnum = 1 | |
let self.col = 1 | |
endfunction | |
function s:StringReader.peek(...) | |
let n = get(a:000, 0, 1) | |
let pos = self.getpos() | |
let r = self.get(n) | |
call self.setpos(pos) | |
return r | |
endfunction | |
function s:StringReader.get(...) | |
let n = get(a:000, 0, 1) | |
let r = '' | |
while n > 0 && self.i < len(self.buf) | |
let c = self.buf[self.i] | |
if c == "\n" | |
let self.lnum += 1 | |
let [i, col] = self.find_line_continuation(self.i + 1) | |
if i != -1 | |
let self.i = i | |
let self.col = col | |
continue | |
endif | |
let self.col = 0 | |
endif | |
let r .= c | |
let self.i += 1 | |
let self.col += 1 | |
let n -= 1 | |
endwhile | |
return r | |
endfunction | |
function s:StringReader.find_line_continuation(start) | |
let [i, col] = [a:start, 1] | |
while i < len(self.buf) && self.buf[i] =~ '\s' | |
let i += 1 | |
let col += 1 | |
endwhile | |
if i < len(self.buf) && self.buf[i] == '\' | |
return [i + 1, col + 1] | |
endif | |
return [-1, 0] | |
endfunction | |
function s:StringReader.peekline() | |
let pos = self.getpos() | |
let r = self.readline() | |
call self.setpos(pos) | |
return r | |
endfunction | |
function s:StringReader.readline() | |
let r = '' | |
while 1 | |
let c = self.get() | |
if c == '' || c == "\n" | |
break | |
endif | |
let r .= c | |
endwhile | |
return r | |
endfunction | |
function s:StringReader.getstr(begin, end) | |
return join(self.buf[a:begin[0] : a:end[0] - 1], '') | |
endfunction | |
function s:StringReader.getpos() | |
return [self.i, self.lnum, self.col] | |
endfunction | |
function s:StringReader.setpos(pos) | |
let [self.i, self.lnum, self.col] = a:pos | |
endfunction | |
let s:Compiler = {} | |
function s:Compiler.new(...) | |
let obj = copy(self) | |
call call(obj.__init__, a:000, obj) | |
return obj | |
endfunction | |
function s:Compiler.__init__() | |
let self.indent = '' | |
let self.lines = [] | |
endfunction | |
function s:Compiler.out(line) | |
call add(self.lines, self.indent . a:line) | |
endfunction | |
function s:Compiler.incindent() | |
let self.indent .= ' ' | |
endfunction | |
function s:Compiler.decindent() | |
let self.indent = matchstr(self.indent, '.*\ze $') | |
endfunction | |
function s:Compiler.compile(ast) | |
if a:ast.type == 'TOPLEVEL' | |
return self.compile_toplevel(a:ast) | |
elseif a:ast.type == 'FUNCTION' | |
return self.compile_function(a:ast) | |
elseif a:ast.type == 'DELFUNCTION' | |
return self.compile_delfunction(a:ast) | |
elseif a:ast.type == 'RETURN' | |
return self.compile_return(a:ast) | |
elseif a:ast.type == 'EXCALL' | |
return self.compile_excall(a:ast) | |
elseif a:ast.type == 'LET' | |
return self.compile_let(a:ast) | |
elseif a:ast.type == 'UNLET' | |
return self.compile_unlet(a:ast) | |
elseif a:ast.type == 'LOCKVAR' | |
return self.compile_lockvar(a:ast) | |
elseif a:ast.type == 'UNLOCKVAR' | |
return self.compile_unlockvar(a:ast) | |
elseif a:ast.type == 'IF' | |
return self.compile_if(a:ast) | |
elseif a:ast.type == 'WHILE' | |
return self.compile_while(a:ast) | |
elseif a:ast.type == 'FOR' | |
return self.compile_for(a:ast) | |
elseif a:ast.type == 'CONTINUE' | |
return self.compile_continue(a:ast) | |
elseif a:ast.type == 'BREAK' | |
return self.compile_break(a:ast) | |
elseif a:ast.type == 'TRY' | |
return self.compile_try(a:ast) | |
elseif a:ast.type == 'THROW' | |
return self.compile_throw(a:ast) | |
elseif a:ast.type == 'ECHO' | |
return self.compile_echo(a:ast) | |
elseif a:ast.type == 'ECHON' | |
return self.compile_echon(a:ast) | |
elseif a:ast.type == 'ECHOHL' | |
return self.compile_echohl(a:ast) | |
elseif a:ast.type == 'ECHOMSG' | |
return self.compile_echomsg(a:ast) | |
elseif a:ast.type == 'ECHOERR' | |
return self.compile_echoerr(a:ast) | |
elseif a:ast.type == 'EXECUTE' | |
return self.compile_execute(a:ast) | |
elseif a:ast.type == 'CONDEXP' | |
return self.compile_condexp(a:ast) | |
elseif a:ast.type == 'LOGOR' | |
return self.compile_logor(a:ast) | |
elseif a:ast.type == 'LOGAND' | |
return self.compile_logand(a:ast) | |
elseif a:ast.type == 'EQEQQ' | |
return self.compile_eqeqq(a:ast) | |
elseif a:ast.type == 'EQEQH' | |
return self.compile_eqeqh(a:ast) | |
elseif a:ast.type == 'NOTEQQ' | |
return self.compile_noteqq(a:ast) | |
elseif a:ast.type == 'NOTEQH' | |
return self.compile_noteqh(a:ast) | |
elseif a:ast.type == 'GTEQQ' | |
return self.compile_gteqq(a:ast) | |
elseif a:ast.type == 'GTEQH' | |
return self.compile_gteqh(a:ast) | |
elseif a:ast.type == 'LTEQQ' | |
return self.compile_lteqq(a:ast) | |
elseif a:ast.type == 'LTEQH' | |
return self.compile_lteqh(a:ast) | |
elseif a:ast.type == 'EQTILDQ' | |
return self.compile_eqtildq(a:ast) | |
elseif a:ast.type == 'EQTILDH' | |
return self.compile_eqtildh(a:ast) | |
elseif a:ast.type == 'NOTTILDQ' | |
return self.compile_nottildq(a:ast) | |
elseif a:ast.type == 'NOTTILDH' | |
return self.compile_nottildh(a:ast) | |
elseif a:ast.type == 'GTQ' | |
return self.compile_gtq(a:ast) | |
elseif a:ast.type == 'GTH' | |
return self.compile_gth(a:ast) | |
elseif a:ast.type == 'LTQ' | |
return self.compile_ltq(a:ast) | |
elseif a:ast.type == 'LTH' | |
return self.compile_lth(a:ast) | |
elseif a:ast.type == 'EQEQ' | |
return self.compile_eqeq(a:ast) | |
elseif a:ast.type == 'NOTEQ' | |
return self.compile_noteq(a:ast) | |
elseif a:ast.type == 'GTEQ' | |
return self.compile_gteq(a:ast) | |
elseif a:ast.type == 'LTEQ' | |
return self.compile_lteq(a:ast) | |
elseif a:ast.type == 'EQTILD' | |
return self.compile_eqtild(a:ast) | |
elseif a:ast.type == 'NOTTILD' | |
return self.compile_nottild(a:ast) | |
elseif a:ast.type == 'GT' | |
return self.compile_gt(a:ast) | |
elseif a:ast.type == 'LT' | |
return self.compile_lt(a:ast) | |
elseif a:ast.type == 'ISQ' | |
return self.compile_isq(a:ast) | |
elseif a:ast.type == 'ISH' | |
return self.compile_ish(a:ast) | |
elseif a:ast.type == 'ISNOTQ' | |
return self.compile_isnotq(a:ast) | |
elseif a:ast.type == 'ISNOTH' | |
return self.compile_isnoth(a:ast) | |
elseif a:ast.type == 'IS' | |
return self.compile_is(a:ast) | |
elseif a:ast.type == 'ISNOT' | |
return self.compile_isnot(a:ast) | |
elseif a:ast.type == 'ADD' | |
return self.compile_add(a:ast) | |
elseif a:ast.type == 'SUB' | |
return self.compile_sub(a:ast) | |
elseif a:ast.type == 'CONCAT' | |
return self.compile_concat(a:ast) | |
elseif a:ast.type == 'MUL' | |
return self.compile_mul(a:ast) | |
elseif a:ast.type == 'DIV' | |
return self.compile_div(a:ast) | |
elseif a:ast.type == 'MOD' | |
return self.compile_mod(a:ast) | |
elseif a:ast.type == 'NOT' | |
return self.compile_not(a:ast) | |
elseif a:ast.type == 'PLUS' | |
return self.compile_plus(a:ast) | |
elseif a:ast.type == 'MINUS' | |
return self.compile_minus(a:ast) | |
elseif a:ast.type == 'INDEX' | |
return self.compile_index(a:ast) | |
elseif a:ast.type == 'SLICE' | |
return self.compile_slice(a:ast) | |
elseif a:ast.type == 'DOT' | |
return self.compile_dot(a:ast) | |
elseif a:ast.type == 'CALL' | |
return self.compile_call(a:ast) | |
elseif a:ast.type == 'NUMBER' | |
return self.compile_number(a:ast) | |
elseif a:ast.type == 'STRING' | |
return self.compile_string(a:ast) | |
elseif a:ast.type == 'LIST' | |
return self.compile_list(a:ast) | |
elseif a:ast.type == 'DICT' | |
return self.compile_dict(a:ast) | |
elseif a:ast.type == 'OPTION' | |
return self.compile_option(a:ast) | |
elseif a:ast.type == 'IDENTIFIER' | |
return self.compile_identifier(a:ast) | |
elseif a:ast.type == 'ENV' | |
return self.compile_env(a:ast) | |
elseif a:ast.type == 'REG' | |
return self.compile_reg(a:ast) | |
else | |
throw printf('Compiler: unknown node: %s', string(a:ast)) | |
endif | |
endfunction | |
function s:Compiler.compile_body(body) | |
call self.incindent() | |
for node in a:body | |
call self.compile(node) | |
endfor | |
call self.decindent() | |
endfunction | |
function s:Compiler.compile_toplevel(ast) | |
let body = a:ast.value | |
call self.compile_body(body) | |
endfunction | |
function s:Compiler.compile_function(ast) | |
let [_name, args, body] = a:ast.value | |
let name = self.compile(_name) | |
call self.out(printf('(function %s (%s)', name, join(args, ' '))) | |
call self.compile_body(body) | |
call self.out(')') | |
endfunction | |
function s:Compiler.compile_delfunction(ast) | |
let _name = a:ast.value | |
let name = self.compile(_name) | |
call self.out(printf('(delfunction %s)', name)) | |
endfunction | |
function s:Compiler.compile_return(ast) | |
let _arg = a:ast.value | |
if _arg is s:NIL | |
call self.out('(return)') | |
else | |
let arg = self.compile(_arg) | |
call self.out(printf('(return %s)', arg)) | |
endif | |
endfunction | |
function s:Compiler.compile_excall(ast) | |
let [_name, args] = a:ast.value | |
let name = self.compile(_name) | |
call map(args, 'self.compile(v:val)') | |
call self.out(printf('(call %s %s)', name, join(args, ' '))) | |
endfunction | |
function s:Compiler.compile_let(ast) | |
let [lhs, op, _rhs] = a:ast.value | |
let args = join(map(copy(lhs.args), 'self.compile(v:val)'), ' ') | |
if lhs.rest isnot s:NIL | |
let args = ' . ' . self.compile(lhs.rest) | |
endif | |
let rhs = self.compile(_rhs) | |
call self.out(printf('(let %s %s %s)', op, args, rhs)) | |
endfunction | |
function s:Compiler.compile_unlet(ast) | |
let args = a:ast.value | |
call map(args, 'self.compile(v:val)') | |
call self.out(printf('(unlet %s)', join(args, ' '))) | |
endfunction | |
function s:Compiler.compile_lockvar(ast) | |
let [depth, args] = a:ast.value | |
call map(args, 'self.compile(v:val)') | |
call self.out(printf('(lockvar %s %s)', depth, join(args, ' '))) | |
endfunction | |
function s:Compiler.compile_unlockvar(ast) | |
let [depth, args] = a:ast.value | |
call map(args, 'self.compile(v:val)') | |
call self.out(printf('(unlockvar %s %s)', depth, join(args, ' '))) | |
endfunction | |
function s:Compiler.compile_if(ast) | |
let clauses = a:ast.value | |
for i in range(len(clauses)) | |
let [cond, body] = clauses[i] | |
if i == 0 | |
call self.out(printf('(if %s (', self.compile(cond))) | |
call self.compile_body(body) | |
call self.out(')') | |
elseif cond isnot s:NIL | |
call self.out(printf('(elseif %s (', self.compile(cond))) | |
call self.compile_body(body) | |
call self.out('))') | |
else | |
call self.out('(else (') | |
call self.compile_body(body) | |
call self.out('))') | |
endif | |
endfor | |
call self.out(')') | |
endfunction | |
function s:Compiler.compile_while(ast) | |
let [cond, body] = a:ast.value | |
call self.out(printf('(while %s', self.compile(cond))) | |
call self.compile_body(body) | |
call self.out(')') | |
endfunction | |
function s:Compiler.compile_for(ast) | |
let [lhs, _rhs, body] = a:ast.value | |
let args = join(map(copy(lhs.args), 'self.compile(v:val)'), ' ') | |
if lhs.rest isnot s:NIL | |
let args = ' . ' . self.compile(lhs.rest) | |
endif | |
let rhs = self.compile(_rhs) | |
call self.out(printf('(for (%s) in %s', args, rhs)) | |
call self.compile_body(body) | |
call self.out(')') | |
endfunction | |
function s:Compiler.compile_continue(ast) | |
call self.out('(continue)') | |
endfunction | |
function s:Compiler.compile_break(ast) | |
call self.out('(break)') | |
endfunction | |
function s:Compiler.compile_try(ast) | |
call self.out('(try)') | |
endfunction | |
function s:Compiler.compile_throw(ast) | |
let expr1 = a:ast.value | |
call self.out(printf('(throw %s)', self.compile(expr1))) | |
endfunction | |
function s:Compiler.compile_echo(ast) | |
let args = a:ast.value | |
call map(args, 'self.compile(v:val)') | |
call self.out(printf('(echo %s)', join(args, ' '))) | |
endfunction | |
function s:Compiler.compile_echon(ast) | |
let args = a:ast.value | |
call map(args, 'self.compile(v:val)') | |
call self.out(printf('(echon %s)', join(args, ' '))) | |
endfunction | |
function s:Compiler.compile_echohl(ast) | |
let name = a:ast.value | |
call self.out(printf('(echohl %s)', name)) | |
endfunction | |
function s:Compiler.compile_echomsg(ast) | |
let args = a:ast.value | |
call map(args, 'self.compile(v:val)') | |
call self.out(printf('(echomsg %s)', join(args, ' '))) | |
endfunction | |
function s:Compiler.compile_echoerr(ast) | |
let args = a:ast.value | |
call map(args, 'self.compile(v:val)') | |
call self.out(printf('(echoerr %s)', join(args, ' '))) | |
endfunction | |
function s:Compiler.compile_execute(ast) | |
let args = a:ast.value | |
call map(args, 'self.compile(v:val)') | |
call self.out(printf('(execute %s)', join(args, ' '))) | |
endfunction | |
function s:Compiler.compile_condexp(ast) | |
let [cond, t, e] = a:ast.value | |
return printf('(?: %s %s %s)', self.compile(cond), self.compile(t), self.compile(e)) | |
endfunction | |
function s:Compiler.compile_logor(ast) | |
let [lhs, rhs] = a:ast.value | |
return printf('(|| %s %s)', self.compile(lhs), self.compile(rhs)) | |
endfunction | |
function s:Compiler.compile_logand(ast) | |
let [lhs, rhs] = a:ast.value | |
return printf('(&& %s %s)', self.compile(lhs), self.compile(rhs)) | |
endfunction | |
function s:Compiler.compile_eqeqq(ast) | |
let [lhs, rhs] = a:ast.value | |
return printf('(==? %s %s)', self.compile(lhs), self.compile(rhs)) | |
endfunction | |
function s:Compiler.compile_eqeqh(ast) | |
let [lhs, rhs] = a:ast.value | |
return printf('(==# %s %s)', self.compile(lhs), self.compile(rhs)) | |
endfunction | |
function s:Compiler.compile_noteqq(ast) | |
let [lhs, rhs] = a:ast.value | |
return printf('(!=? %s %s)', self.compile(lhs), self.compile(rhs)) | |
endfunction | |
function s:Compiler.compile_noteqh(ast) | |
let [lhs, rhs] = a:ast.value | |
return printf('(!=# %s %s)', self.compile(lhs), self.compile(rhs)) | |
endfunction | |
function s:Compiler.compile_gteqq(ast) | |
let [lhs, rhs] = a:ast.value | |
return printf('(>=? %s %s)', self.compile(lhs), self.compile(rhs)) | |
endfunction | |
function s:Compiler.compile_gteqh(ast) | |
let [lhs, rhs] = a:ast.value | |
return printf('(>=# %s %s)', self.compile(lhs), self.compile(rhs)) | |
endfunction | |
function s:Compiler.compile_lteqq(ast) | |
let [lhs, rhs] = a:ast.value | |
return printf('(<=? %s %s)', self.compile(lhs), self.compile(rhs)) | |
endfunction | |
function s:Compiler.compile_lteqh(ast) | |
let [lhs, rhs] = a:ast.value | |
return printf('(<=# %s %s)', self.compile(lhs), self.compile(rhs)) | |
endfunction | |
function s:Compiler.compile_eqtildq(ast) | |
let [lhs, rhs] = a:ast.value | |
return printf('(=~? %s %s)', self.compile(lhs), self.compile(rhs)) | |
endfunction | |
function s:Compiler.compile_eqtildh(ast) | |
let [lhs, rhs] = a:ast.value | |
return printf('(=~# %s %s)', self.compile(lhs), self.compile(rhs)) | |
endfunction | |
function s:Compiler.compile_nottildq(ast) | |
let [lhs, rhs] = a:ast.value | |
return printf('(!~? %s %s)', self.compile(lhs), self.compile(rhs)) | |
endfunction | |
function s:Compiler.compile_nottildh(ast) | |
let [lhs, rhs] = a:ast.value | |
return printf('(!~# %s %s)', self.compile(lhs), self.compile(rhs)) | |
endfunction | |
function s:Compiler.compile_gtq(ast) | |
let [lhs, rhs] = a:ast.value | |
return printf('(>? %s %s)', self.compile(lhs), self.compile(rhs)) | |
endfunction | |
function s:Compiler.compile_gth(ast) | |
let [lhs, rhs] = a:ast.value | |
return printf('(># %s %s)', self.compile(lhs), self.compile(rhs)) | |
endfunction | |
function s:Compiler.compile_ltq(ast) | |
let [lhs, rhs] = a:ast.value | |
return printf('(<? %s %s)', self.compile(lhs), self.compile(rhs)) | |
endfunction | |
function s:Compiler.compile_lth(ast) | |
let [lhs, rhs] = a:ast.value | |
return printf('(<# %s %s)', self.compile(lhs), self.compile(rhs)) | |
endfunction | |
function s:Compiler.compile_eqeq(ast) | |
let [lhs, rhs] = a:ast.value | |
return printf('(== %s %s)', self.compile(lhs), self.compile(rhs)) | |
endfunction | |
function s:Compiler.compile_noteq(ast) | |
let [lhs, rhs] = a:ast.value | |
return printf('(!= %s %s)', self.compile(lhs), self.compile(rhs)) | |
endfunction | |
function s:Compiler.compile_gteq(ast) | |
let [lhs, rhs] = a:ast.value | |
return printf('(>= %s %s)', self.compile(lhs), self.compile(rhs)) | |
endfunction | |
function s:Compiler.compile_lteq(ast) | |
let [lhs, rhs] = a:ast.value | |
return printf('(<= %s %s)', self.compile(lhs), self.compile(rhs)) | |
endfunction | |
function s:Compiler.compile_eqtild(ast) | |
let [lhs, rhs] = a:ast.value | |
return printf('(=~ %s %s)', self.compile(lhs), self.compile(rhs)) | |
endfunction | |
function s:Compiler.compile_nottild(ast) | |
let [lhs, rhs] = a:ast.value | |
return printf('(!~ %s %s)', self.compile(lhs), self.compile(rhs)) | |
endfunction | |
function s:Compiler.compile_gt(ast) | |
let [lhs, rhs] = a:ast.value | |
return printf('(> %s %s)', self.compile(lhs), self.compile(rhs)) | |
endfunction | |
function s:Compiler.compile_lt(ast) | |
let [lhs, rhs] = a:ast.value | |
return printf('(< %s %s)', self.compile(lhs), self.compile(rhs)) | |
endfunction | |
function s:Compiler.compile_isq(ast) | |
let [lhs, rhs] = a:ast.value | |
return printf('(is? %s %s)', self.compile(lhs), self.compile(rhs)) | |
endfunction | |
function s:Compiler.compile_ish(ast) | |
let [lhs, rhs] = a:ast.value | |
return printf('(is# %s %s)', self.compile(lhs), self.compile(rhs)) | |
endfunction | |
function s:Compiler.compile_isnotq(ast) | |
let [lhs, rhs] = a:ast.value | |
return printf('(isnot? %s %s)', self.compile(lhs), self.compile(rhs)) | |
endfunction | |
function s:Compiler.compile_isnoth(ast) | |
let [lhs, rhs] = a:ast.value | |
return printf('(isnot# %s %s)', self.compile(lhs), self.compile(rhs)) | |
endfunction | |
function s:Compiler.compile_is(ast) | |
let [lhs, rhs] = a:ast.value | |
return printf('(is %s %s)', self.compile(lhs), self.compile(rhs)) | |
endfunction | |
function s:Compiler.compile_isnot(ast) | |
let [lhs, rhs] = a:ast.value | |
return printf('(isnot %s %s)', self.compile(lhs), self.compile(rhs)) | |
endfunction | |
function s:Compiler.compile_add(ast) | |
let [lhs, rhs] = a:ast.value | |
return printf('(+ %s %s)', self.compile(lhs), self.compile(rhs)) | |
endfunction | |
function s:Compiler.compile_sub(ast) | |
let [lhs, rhs] = a:ast.value | |
return printf('(- %s %s)', self.compile(lhs), self.compile(rhs)) | |
endfunction | |
function s:Compiler.compile_concat(ast) | |
let [lhs, rhs] = a:ast.value | |
return printf('(concat %s %s)', self.compile(lhs), self.compile(rhs)) | |
endfunction | |
function s:Compiler.compile_mul(ast) | |
let [lhs, rhs] = a:ast.value | |
return printf('(* %s %s)', self.compile(lhs), self.compile(rhs)) | |
endfunction | |
function s:Compiler.compile_div(ast) | |
let [lhs, rhs] = a:ast.value | |
return printf('(/ %s %s)', self.compile(lhs), self.compile(rhs)) | |
endfunction | |
function s:Compiler.compile_mod(ast) | |
let [lhs, rhs] = a:ast.value | |
return printf('(% %s %s)', self.compile(lhs), self.compile(rhs)) | |
endfunction | |
function s:Compiler.compile_not(ast) | |
let lhs = a:ast.value | |
return printf('(! %s)', self.compile(lhs)) | |
endfunction | |
function s:Compiler.compile_plus(ast) | |
let lhs = a:ast.value | |
return printf('(+ %s)', self.compile(lhs)) | |
endfunction | |
function s:Compiler.compile_minus(ast) | |
let lhs = a:ast.value | |
return printf('(- %s)', self.compile(lhs)) | |
endfunction | |
function s:Compiler.compile_index(ast) | |
let [v, s1] = a:ast.value | |
return printf('(index %s %s)', self.compile(v), self.compile(s1)) | |
endfunction | |
function s:Compiler.compile_slice(ast) | |
let [v, s1, s2] = a:ast.value | |
return printf('(slice %s %s %s)', self.compile(v), self.compile(s1), self.compile(s2)) | |
endfunction | |
function s:Compiler.compile_dot(ast) | |
let [lhs, rhs] = a:ast.value | |
return printf('(dot %s %s)', self.compile(lhs), self.compile(rhs)) | |
endfunction | |
function s:Compiler.compile_call(ast) | |
let [lhs, args] = a:ast.value | |
call map(args, 'self.compile(v:val)') | |
return printf('(%s %s)', self.compile(lhs), join(args, ' ')) | |
endfunction | |
function s:Compiler.compile_number(ast) | |
let v = a:ast.value | |
return v | |
endfunction | |
function s:Compiler.compile_string(ast) | |
let v = a:ast.value | |
return v | |
endfunction | |
function s:Compiler.compile_list(ast) | |
let list = a:ast.value | |
call map(list, 'self.compile(v:val)') | |
return printf('(list %s)', join(list, ' ')) | |
endfunction | |
function s:Compiler.compile_dict(ast) | |
let dict = a:ast.value | |
call map(dict, '"(" . self.compile(v:val[0]) . " " . self.compile(v:val[1]) . ")"') | |
return printf('(dict %s)', join(dict, ' ')) | |
endfunction | |
function s:Compiler.compile_option(ast) | |
let v = a:ast.value | |
return v | |
endfunction | |
function s:Compiler.compile_identifier(ast) | |
let v = a:ast.value | |
return v | |
endfunction | |
function s:Compiler.compile_env(ast) | |
let v = a:ast.value | |
return v | |
endfunction | |
function s:Compiler.compile_reg(ast) | |
let v = a:ast.value | |
return v | |
endfunction | |
function! X() | |
return s: | |
endfunction | |
"call X().VimLParser.new().parse(readfile('vimlparser.vim')) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment