@@ -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_HEREDOC = 94
141
142
142
143
let s: TOKEN_EOF = 1
143
144
let s: TOKEN_EOL = 2
@@ -207,6 +208,7 @@ let s:TOKEN_ARROW = 65
207
208
let s: TOKEN_BLOB = 66
208
209
let s: TOKEN_LITCOPEN = 67
209
210
let s: TOKEN_DOTDOT = 68
211
+ let s: TOKEN_HEREDOC = 69
210
212
211
213
let s: MAX_FUNC_ARGS = 20
212
214
@@ -407,6 +409,7 @@ endfunction
407
409
" CURLYNAMEPART .value
408
410
" CURLYNAMEEXPR .value
409
411
" LAMBDA .rlist .left
412
+ " HEREDOC .rlist .op .value
410
413
function ! s: Node (type )
411
414
return {' type' : a: type }
412
415
endfunction
@@ -1483,6 +1486,42 @@ function! s:VimLParser.parse_cmd_call()
1483
1486
call self .add_node (node)
1484
1487
endfunction
1485
1488
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
+
1486
1525
function ! s: VimLParser .parse_cmd_let ()
1487
1526
let pos = self .reader.tell ()
1488
1527
call self .reader.skip_white ()
@@ -1501,10 +1540,12 @@ function! s:VimLParser.parse_cmd_let()
1501
1540
" TODO check scriptversion?
1502
1541
if s2 == # ' ..'
1503
1542
let s2 = self .reader.peekn (3 )
1543
+ elseif s2 == # ' =<'
1544
+ let s2 = self .reader.peekn (3 )
1504
1545
endif
1505
1546
1506
1547
" :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 !=# ' =' )
1508
1549
call self .reader.seek_set (pos)
1509
1550
call self .parse_cmd_common ()
1510
1551
return
@@ -1522,6 +1563,12 @@ function! s:VimLParser.parse_cmd_let()
1522
1563
if s2 == # ' +=' || s2 == # ' -=' || s2 == # ' .=' || s2 == # ' ..=' || s2 == # ' *=' || s2 == # ' /=' || s2 == # ' %='
1523
1564
call self .reader.getn (len (s2))
1524
1565
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
1525
1572
elseif s1 == # ' ='
1526
1573
call self .reader.getn (1 )
1527
1574
let node.op = s1
@@ -4360,6 +4407,8 @@ function! s:Compiler.compile(node)
4360
4407
return self .compile_curlynameexpr (a: node )
4361
4408
elseif a: node .type == s: NODE_LAMBDA
4362
4409
return self .compile_lambda (a: node )
4410
+ elseif a: node .type == s: NODE_HEREDOC
4411
+ return self .compile_heredoc (a: node )
4363
4412
else
4364
4413
throw printf (' Compiler: unknown node: %s' , string (a: node ))
4365
4414
endif
@@ -4827,6 +4876,18 @@ function! s:Compiler.compile_lambda(node)
4827
4876
return printf (' (lambda (%s) %s)' , join (rlist, ' ' ), self .compile (a: node .left ))
4828
4877
endfunction
4829
4878
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
+
4830
4891
" TODO: under construction
4831
4892
let s: RegexpParser = {}
4832
4893
0 commit comments