Skip to content

Commit fb05bed

Browse files
committed
support :const
1 parent bc0d350 commit fb05bed

File tree

3 files changed

+115
-0
lines changed

3 files changed

+115
-0
lines changed

autoload/vimlparser.vim

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ let s:NODE_CURLYNAMEPART = 90
138138
let s:NODE_CURLYNAMEEXPR = 91
139139
let s:NODE_LAMBDA = 92
140140
let s:NODE_BLOB = 93
141+
let s:NODE_CONST = 94
141142

142143
let s:TOKEN_EOF = 1
143144
let s:TOKEN_EOL = 2
@@ -324,6 +325,7 @@ endfunction
324325
" RETURN .ea .left
325326
" EXCALL .ea .left
326327
" LET .ea .op .left .list .rest .right
328+
" CONST .ea .op .left .list .rest .right
327329
" UNLET .ea .list
328330
" LOCKVAR .ea .depth .list
329331
" UNLOCKVAR .ea .depth .list
@@ -860,6 +862,8 @@ function! s:VimLParser._parse_command(parser) abort
860862
call self.parse_cmd_insert()
861863
elseif a:parser ==# 'parse_cmd_let'
862864
call self.parse_cmd_let()
865+
elseif a:parser ==# 'parse_cmd_const'
866+
call self.parse_cmd_const()
863867
elseif a:parser ==# 'parse_cmd_loadkeymap'
864868
call self.parse_cmd_loadkeymap()
865869
elseif a:parser ==# 'parse_cmd_lockvar'
@@ -1533,6 +1537,41 @@ function! s:VimLParser.parse_cmd_let()
15331537
call self.add_node(node)
15341538
endfunction
15351539

1540+
function! s:VimLParser.parse_cmd_const()
1541+
let pos = self.reader.tell()
1542+
call self.reader.skip_white()
1543+
1544+
" :const
1545+
if self.ends_excmds(self.reader.peek())
1546+
call self.reader.seek_set(pos)
1547+
call self.parse_cmd_common()
1548+
return
1549+
endif
1550+
1551+
let lhs = self.parse_constlhs()
1552+
call self.reader.skip_white()
1553+
let s1 = self.reader.peekn(1)
1554+
1555+
" :const {var-name}
1556+
if self.ends_excmds(s1) || s1 !=# '='
1557+
call self.reader.seek_set(pos)
1558+
call self.parse_cmd_common()
1559+
return
1560+
endif
1561+
1562+
" :const left op right
1563+
let node = s:Node(s:NODE_CONST)
1564+
let node.pos = self.ea.cmdpos
1565+
let node.ea = self.ea
1566+
call self.reader.getn(1)
1567+
let node.op = s1
1568+
let node.left = lhs.left
1569+
let node.list = lhs.list
1570+
let node.rest = lhs.rest
1571+
let node.right = self.parse_expr()
1572+
call self.add_node(node)
1573+
endfunction
1574+
15361575
function! s:VimLParser.parse_cmd_unlet()
15371576
let node = s:Node(s:NODE_UNLET)
15381577
let node.pos = self.ea.cmdpos
@@ -1866,6 +1905,22 @@ function! s:VimLParser.parse_lvalue()
18661905
throw s:Err('Invalid Expression', node.pos)
18671906
endfunction
18681907

1908+
" TODO: merge with s:VimLParser.parse_lvalue()
1909+
function! s:VimLParser.parse_constlvalue()
1910+
let p = s:LvalueParser.new(self.reader)
1911+
let node = p.parse()
1912+
if node.type == s:NODE_IDENTIFIER
1913+
if !s:isvarname(node.value)
1914+
throw s:Err(printf('E461: Illegal variable name: %s', node.value), node.pos)
1915+
endif
1916+
endif
1917+
if node.type == s:NODE_IDENTIFIER || node.type == s:NODE_CURLYNAME
1918+
return node
1919+
endif
1920+
throw s:Err('Invalid Expression', node.pos)
1921+
endfunction
1922+
1923+
18691924
function! s:VimLParser.parse_lvaluelist()
18701925
let list = []
18711926
let node = self.parse_expr()
@@ -1915,6 +1970,40 @@ function! s:VimLParser.parse_letlhs()
19151970
return lhs
19161971
endfunction
19171972

1973+
" TODO: merge with s:VimLParser.parse_letlhs() ?
1974+
function! s:VimLParser.parse_constlhs()
1975+
let lhs = {'left': s:NIL, 'list': s:NIL, 'rest': s:NIL}
1976+
let tokenizer = s:ExprTokenizer.new(self.reader)
1977+
if tokenizer.peek().type == s:TOKEN_SQOPEN
1978+
call tokenizer.get()
1979+
let lhs.list = []
1980+
while s:TRUE
1981+
let node = self.parse_lvalue()
1982+
call add(lhs.list, node)
1983+
let token = tokenizer.get()
1984+
if token.type == s:TOKEN_SQCLOSE
1985+
break
1986+
elseif token.type == s:TOKEN_COMMA
1987+
continue
1988+
elseif token.type == s:TOKEN_SEMICOLON
1989+
let node = self.parse_lvalue()
1990+
let lhs.rest = node
1991+
let token = tokenizer.get()
1992+
if token.type == s:TOKEN_SQCLOSE
1993+
break
1994+
else
1995+
throw s:Err(printf('E475 Invalid argument: %s', token.value), token.pos)
1996+
endif
1997+
else
1998+
throw s:Err(printf('E475 Invalid argument: %s', token.value), token.pos)
1999+
endif
2000+
endwhile
2001+
else
2002+
let lhs.left = self.parse_constlvalue()
2003+
endif
2004+
return lhs
2005+
endfunction
2006+
19182007
function! s:VimLParser.ends_excmds(c)
19192008
return a:c ==# '' || a:c ==# '|' || a:c ==# '"' || a:c ==# '<EOF>' || a:c ==# '<EOL>'
19202009
endfunction
@@ -2193,6 +2282,7 @@ let s:VimLParser.builtin_commands = [
21932282
\ {'name': 'left', 'minlen': 2, 'flags': 'TRLBAR|RANGE|WHOLEFOLD|EXTRA|CMDWIN|MODIFY', 'parser': 'parse_cmd_common'},
21942283
\ {'name': 'leftabove', 'minlen': 5, 'flags': 'NEEDARG|EXTRA|NOTRLCOM', 'parser': 'parse_cmd_common'},
21952284
\ {'name': 'let', 'minlen': 3, 'flags': 'EXTRA|NOTRLCOM|SBOXOK|CMDWIN', 'parser': 'parse_cmd_let'},
2285+
\ {'name': 'const', 'minlen': 4, 'flags': 'EXTRA|NOTRLCOM|SBOXOK|CMDWIN', 'parser': 'parse_cmd_const'},
21962286
\ {'name': 'lexpr', 'minlen': 3, 'flags': 'NEEDARG|WORD1|NOTRLCOM|TRLBAR|BANG', 'parser': 'parse_cmd_common'},
21972287
\ {'name': 'lfile', 'minlen': 2, 'flags': 'TRLBAR|FILE1|BANG', 'parser': 'parse_cmd_common'},
21982288
\ {'name': 'lfirst', 'minlen': 4, 'flags': 'RANGE|NOTADR|COUNT|TRLBAR|BANG', 'parser': 'parse_cmd_common'},
@@ -4195,6 +4285,9 @@ function! s:Compiler.compile(node)
41954285
elseif a:node.type == s:NODE_LET
41964286
call self.compile_let(a:node)
41974287
return s:NIL
4288+
elseif a:node.type == s:NODE_CONST
4289+
call self.compile_const(a:node)
4290+
return s:NIL
41984291
elseif a:node.type == s:NODE_UNLET
41994292
call self.compile_unlet(a:node)
42004293
return s:NIL
@@ -4434,6 +4527,22 @@ function! s:Compiler.compile_let(node)
44344527
call self.out('(let %s %s %s)', a:node.op, left, right)
44354528
endfunction
44364529

4530+
" TODO: merge with s:Compiler.compile_let() ?
4531+
function! s:Compiler.compile_const(node)
4532+
let left = ''
4533+
if a:node.left isnot s:NIL
4534+
let left = self.compile(a:node.left)
4535+
else
4536+
let left = join(map(a:node.list, 'self.compile(v:val)'), ' ')
4537+
if a:node.rest isnot s:NIL
4538+
let left .= ' . ' . self.compile(a:node.rest)
4539+
endif
4540+
let left = '(' . left . ')'
4541+
endif
4542+
let right = self.compile(a:node.right)
4543+
call self.out('(const %s %s %s)', a:node.op, left, right)
4544+
endfunction
4545+
44374546
function! s:Compiler.compile_unlet(node)
44384547
let list = map(a:node.list, 'self.compile(v:val)')
44394548
call self.out('(unlet %s)', join(list, ' '))

test/test1.ok

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,3 +53,6 @@
5353
(let %= a 5)
5454
(let ..= a 'foo')
5555
(echo (concat (concat 'foo' 'bar') 'baz'))
56+
(const = a 1)
57+
(const = (a b) (list 1 2))
58+
(const = (a b . c) (list 1 2 3))

test/test1.vim

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,3 +58,6 @@ let a /= 4
5858
let a %= 5
5959
let a ..= 'foo'
6060
echo ('foo' .. 'bar')..'baz'
61+
const a = 1
62+
const [a, b] = [1, 2]
63+
const [a, b; c] = [1, 2, 3]

0 commit comments

Comments
 (0)