@@ -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_HEREDOC = 94
141142
142143let s: TOKEN_EOF = 1
143144let s: TOKEN_EOL = 2
@@ -207,6 +208,7 @@ let s:TOKEN_ARROW = 65
207208let s: TOKEN_BLOB = 66
208209let s: TOKEN_LITCOPEN = 67
209210let s: TOKEN_DOTDOT = 68
211+ let s: TOKEN_HEREDOC = 69
210212
211213let s: MAX_FUNC_ARGS = 20
212214
@@ -407,6 +409,7 @@ endfunction
407409" CURLYNAMEPART .value
408410" CURLYNAMEEXPR .value
409411" LAMBDA .rlist .left
412+ " HEREDOC .rlist .op .value
410413function ! s: Node (type )
411414 return {' type' : a: type }
412415endfunction
@@ -1483,6 +1486,42 @@ function! s:VimLParser.parse_cmd_call()
14831486 call self .add_node (node)
14841487endfunction
14851488
1489+ function ! s: VimLParser .parse_heredoc ()
1490+ let node = s: Node (s: NODE_HEREDOC )
1491+ let node.pos = self .ea .cmdpos
1492+ let node.op = ' '
1493+ let node.rlist = []
1494+ let node.str = ' '
1495+
1496+ let words = []
1497+ while s: TRUE
1498+ call self .reader.skip_white ()
1499+ let key = self .reader.read_alpha ()
1500+ if key == ' '
1501+ break
1502+ endif
1503+ call add (words, key )
1504+ endwhile
1505+ if empty (words)
1506+ call self .reader.seek_set (pos)
1507+ call self .parse_cmd_common ()
1508+ return
1509+ endif
1510+ let node.rlist = words[:-2 ]
1511+ let node.op = words[-1 ]
1512+ let lines = []
1513+ call self .parse_trail ()
1514+ while self .reader.peek () !=# ' <EOF>'
1515+ let line = self .reader.readline ()
1516+ if line == # node.op
1517+ let node.str = join (lines , " \n " ) . " \n "
1518+ return node
1519+ endif
1520+ call add (lines , line )
1521+ endwhile
1522+ return s: NIL
1523+ endfunction
1524+
14861525function ! s: VimLParser .parse_cmd_let ()
14871526 let pos = self .reader.tell ()
14881527 call self .reader.skip_white ()
@@ -1501,10 +1540,12 @@ function! s:VimLParser.parse_cmd_let()
15011540 " TODO check scriptversion?
15021541 if s2 == # ' ..'
15031542 let s2 = self .reader.peekn (3 )
1543+ elseif s2 == # ' =<'
1544+ let s2 = self .reader.peekn (3 )
15041545 endif
15051546
15061547 " :let {var-name} ..
1507- if self .ends_excmds (s1) || (s2 !=# ' +=' && s2 !=# ' -=' && s2 !=# ' .=' && s2 !=# ' ..=' && s2 !=# ' *=' && s2 !=# ' /=' && s2 !=# ' %=' && s1 !=# ' =' )
1548+ if self .ends_excmds (s1) || (s2 !=# ' +=' && s2 !=# ' -=' && s2 !=# ' .=' && s2 !=# ' ..=' && s2 !=# ' *=' && s2 !=# ' /=' && s2 !=# ' %=' && s2 !=# ' =<< ' && s1 !=# ' =' )
15081549 call self .reader.seek_set (pos)
15091550 call self .parse_cmd_common ()
15101551 return
@@ -1522,6 +1563,12 @@ function! s:VimLParser.parse_cmd_let()
15221563 if s2 == # ' +=' || s2 == # ' -=' || s2 == # ' .=' || s2 == # ' ..=' || s2 == # ' *=' || s2 == # ' /=' || s2 == # ' %='
15231564 call self .reader.getn (len (s2))
15241565 let node.op = s2
1566+ elseif s2 == # ' =<<'
1567+ call self .reader.getn (len (s2))
1568+ call self .reader.skip_white ()
1569+ let node.right = self .parse_heredoc ()
1570+ call self .add_node (node)
1571+ return
15251572 elseif s1 == # ' ='
15261573 call self .reader.getn (1 )
15271574 let node.op = s1
@@ -4360,6 +4407,8 @@ function! s:Compiler.compile(node)
43604407 return self .compile_curlynameexpr (a: node )
43614408 elseif a: node .type == s: NODE_LAMBDA
43624409 return self .compile_lambda (a: node )
4410+ elseif a: node .type == s: NODE_HEREDOC
4411+ return self .compile_heredoc (a: node )
43634412 else
43644413 throw printf (' Compiler: unknown node: %s' , string (a: node ))
43654414 endif
@@ -4827,6 +4876,18 @@ function! s:Compiler.compile_lambda(node)
48274876 return printf (' (lambda (%s) %s)' , join (rlist, ' ' ), self .compile (a: node .left ))
48284877endfunction
48294878
4879+ function ! s: escape_string (str)
4880+ let str = ' "' . escape (a: str , ' \"' ) . ' "'
4881+ let str = substitute (str, " \r " , ' \\r' , ' g' )
4882+ let str = substitute (str, " \n " , ' \\n' , ' g' )
4883+ let str = substitute (str, " \t " , ' \\t' , ' g' )
4884+ return str
4885+ endfunction
4886+
4887+ function ! s: Compiler .compile_heredoc (node)
4888+ return printf (' (heredoc (%s) "%s" %s))' , join (a: node .rlist, ' ' ), a: node .op , s: escape_string (a: node .str))
4889+ endfunction
4890+
48304891" TODO: under construction
48314892let s: RegexpParser = {}
48324893
0 commit comments