@@ -138,6 +138,7 @@ let s:NODE_CURLYNAMEPART = 90
138
138
let s: NODE_CURLYNAMEEXPR = 91
139
139
let s: NODE_LAMBDA = 92
140
140
let s: NODE_BLOB = 93
141
+ let s: NODE_CONST = 94
141
142
142
143
let s: TOKEN_EOF = 1
143
144
let s: TOKEN_EOL = 2
@@ -324,6 +325,7 @@ endfunction
324
325
" RETURN .ea .left
325
326
" EXCALL .ea .left
326
327
" LET .ea .op .left .list .rest .right
328
+ " CONST .ea .op .left .list .rest .right
327
329
" UNLET .ea .list
328
330
" LOCKVAR .ea .depth .list
329
331
" UNLOCKVAR .ea .depth .list
@@ -860,6 +862,8 @@ function! s:VimLParser._parse_command(parser) abort
860
862
call self .parse_cmd_insert ()
861
863
elseif a: parser == # ' parse_cmd_let'
862
864
call self .parse_cmd_let ()
865
+ elseif a: parser == # ' parse_cmd_const'
866
+ call self .parse_cmd_const ()
863
867
elseif a: parser == # ' parse_cmd_loadkeymap'
864
868
call self .parse_cmd_loadkeymap ()
865
869
elseif a: parser == # ' parse_cmd_lockvar'
@@ -1533,6 +1537,41 @@ function! s:VimLParser.parse_cmd_let()
1533
1537
call self .add_node (node)
1534
1538
endfunction
1535
1539
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
+
1536
1575
function ! s: VimLParser .parse_cmd_unlet ()
1537
1576
let node = s: Node (s: NODE_UNLET )
1538
1577
let node.pos = self .ea .cmdpos
@@ -1866,6 +1905,22 @@ function! s:VimLParser.parse_lvalue()
1866
1905
throw s: Err (' Invalid Expression' , node.pos)
1867
1906
endfunction
1868
1907
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
+
1869
1924
function ! s: VimLParser .parse_lvaluelist ()
1870
1925
let list = []
1871
1926
let node = self .parse_expr ()
@@ -1915,6 +1970,40 @@ function! s:VimLParser.parse_letlhs()
1915
1970
return lhs
1916
1971
endfunction
1917
1972
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
+
1918
2007
function ! s: VimLParser .ends_excmds (c )
1919
2008
return a: c == # ' ' || a: c == # ' |' || a: c == # ' "' || a: c == # ' <EOF>' || a: c == # ' <EOL>'
1920
2009
endfunction
@@ -2193,6 +2282,7 @@ let s:VimLParser.builtin_commands = [
2193
2282
\ {' name' : ' left' , ' minlen' : 2 , ' flags' : ' TRLBAR|RANGE|WHOLEFOLD|EXTRA|CMDWIN|MODIFY' , ' parser' : ' parse_cmd_common' },
2194
2283
\ {' name' : ' leftabove' , ' minlen' : 5 , ' flags' : ' NEEDARG|EXTRA|NOTRLCOM' , ' parser' : ' parse_cmd_common' },
2195
2284
\ {' 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' },
2196
2286
\ {' name' : ' lexpr' , ' minlen' : 3 , ' flags' : ' NEEDARG|WORD1|NOTRLCOM|TRLBAR|BANG' , ' parser' : ' parse_cmd_common' },
2197
2287
\ {' name' : ' lfile' , ' minlen' : 2 , ' flags' : ' TRLBAR|FILE1|BANG' , ' parser' : ' parse_cmd_common' },
2198
2288
\ {' name' : ' lfirst' , ' minlen' : 4 , ' flags' : ' RANGE|NOTADR|COUNT|TRLBAR|BANG' , ' parser' : ' parse_cmd_common' },
@@ -4195,6 +4285,9 @@ function! s:Compiler.compile(node)
4195
4285
elseif a: node .type == s: NODE_LET
4196
4286
call self .compile_let (a: node )
4197
4287
return s: NIL
4288
+ elseif a: node .type == s: NODE_CONST
4289
+ call self .compile_const (a: node )
4290
+ return s: NIL
4198
4291
elseif a: node .type == s: NODE_UNLET
4199
4292
call self .compile_unlet (a: node )
4200
4293
return s: NIL
@@ -4434,6 +4527,22 @@ function! s:Compiler.compile_let(node)
4434
4527
call self .out (' (let %s %s %s)' , a: node .op , left , right )
4435
4528
endfunction
4436
4529
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
+
4437
4546
function ! s: Compiler .compile_unlet (node)
4438
4547
let list = map (a: node .list , ' self.compile(v:val)' )
4439
4548
call self .out (' (unlet %s)' , join (list , ' ' ))
0 commit comments