@@ -138,6 +138,7 @@ let s:NODE_CURLYNAMEPART = 90
138138let s: NODE_CURLYNAMEEXPR = 91
139139let s: NODE_LAMBDA = 92
140140let s: NODE_BLOB = 93
141+ let s: NODE_CONST = 94
141142
142143let s: TOKEN_EOF = 1
143144let 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)
15341538endfunction
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+
15361575function ! 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)
18671906endfunction
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+
18691924function ! 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
19161971endfunction
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+
19182007function ! s: VimLParser .ends_excmds (c )
19192008 return a: c == # ' ' || a: c == # ' |' || a: c == # ' "' || a: c == # ' <EOF>' || a: c == # ' <EOL>'
19202009endfunction
@@ -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 )
44354528endfunction
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+
44374546function ! s: Compiler .compile_unlet (node)
44384547 let list = map (a: node .list , ' self.compile(v:val)' )
44394548 call self .out (' (unlet %s)' , join (list , ' ' ))
0 commit comments