Skip to content

Commit 2d1b538

Browse files
committed
Add heredoc
1 parent 045da67 commit 2d1b538

File tree

3 files changed

+67
-1
lines changed

3 files changed

+67
-1
lines changed

autoload/vimlparser.vim

Lines changed: 62 additions & 1 deletion
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_HEREDOC = 94
141142

142143
let s:TOKEN_EOF = 1
143144
let s:TOKEN_EOL = 2
@@ -207,6 +208,7 @@ let s:TOKEN_ARROW = 65
207208
let s:TOKEN_BLOB = 66
208209
let s:TOKEN_LITCOPEN = 67
209210
let s:TOKEN_DOTDOT = 68
211+
let s:TOKEN_HEREDOC = 69
210212

211213
let 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
410413
function! s:Node(type)
411414
return {'type': a:type}
412415
endfunction
@@ -1483,6 +1486,42 @@ function! s:VimLParser.parse_cmd_call()
14831486
call self.add_node(node)
14841487
endfunction
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+
14861525
function! 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))
48284877
endfunction
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
48314892
let s:RegexpParser = {}
48324893

test/test_heredoc.ok

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
(let a (heredoc () "EOS" "hello\n world\n")))

test/test_heredoc.vim

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
let a =<< EOS
2+
hello
3+
world
4+
EOS

0 commit comments

Comments
 (0)