Skip to content

Commit a57c52d

Browse files
committed
implement HeredocExpr
1 parent def642b commit a57c52d

File tree

4 files changed

+66
-3
lines changed

4 files changed

+66
-3
lines changed

ast/node.go

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -517,7 +517,7 @@ type Ident struct {
517517
func (i *Ident) Pos() Pos { return i.NamePos }
518518

519519
// LambdaExpr node represents lambda.
520-
// vimlparsr: LAMBDA .rlist .left
520+
// vimlparser: LAMBDA .rlist .left
521521
// { Params -> Expr }
522522
type LambdaExpr struct {
523523
Lcurlybrace Pos // position of "{"
@@ -528,14 +528,25 @@ type LambdaExpr struct {
528528
func (i *LambdaExpr) Pos() Pos { return i.Lcurlybrace }
529529

530530
// ParenExpr node represents a parenthesized expression.
531-
// vimlparsr: PARENEXPR .value
531+
// vimlparser: PARENEXPR .value
532532
type ParenExpr struct {
533533
Lparen Pos // position of "("
534534
X Expr // parenthesized expression
535535
}
536536

537537
func (i *ParenExpr) Pos() Pos { return i.Lparen }
538538

539+
// HeredocExpr node represents a heredoc expression.
540+
// vimlparser: HEREDOC .rlist .op .body
541+
type HeredocExpr struct {
542+
OpPos Pos // position of "=<<"
543+
Flags []Expr // modifiers [trim]; or nil
544+
EndMarker string // {endmarker}
545+
Body []Expr // body
546+
}
547+
548+
func (i *HeredocExpr) Pos() Pos { return i.OpPos }
549+
539550
// stmtNode() ensures that only ExComamnd and Comment nodes can be assigned to
540551
// an Statement.
541552
//
@@ -588,3 +599,4 @@ func (*CurlyNameExpr) exprNode() {}
588599
func (*Ident) exprNode() {}
589600
func (*LambdaExpr) exprNode() {}
590601
func (*ParenExpr) exprNode() {}
602+
func (*HeredocExpr) exprNode() {}

ast/walk.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,10 @@ func Walk(v Visitor, node Node) {
201201
case *ParenExpr:
202202
Walk(v, n.X)
203203

204+
case *HeredocExpr:
205+
walkExprList(v, n.Flags)
206+
walkExprList(v, n.Body)
207+
204208
default:
205209
panic(fmt.Sprintf("ast.Walk: unexpected node type %T", n))
206210
}

compiler/compiler.go

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,28 @@ func (c *Compiler) compileExpr(node ast.Expr) string {
440440
params = append(params, p.Name)
441441
}
442442
return fmt.Sprintf("(lambda (%s) %s)", strings.Join(params, " "), c.compileExpr(n.Expr))
443+
case *ast.HeredocExpr:
444+
var flags string
445+
if len(n.Flags) == 0 {
446+
flags = "(list)"
447+
} else {
448+
xs := make([]string, len(n.Flags))
449+
for i, f := range n.Flags {
450+
xs[i] = `"` + c.compileExpr(f) + `"`
451+
}
452+
flags = fmt.Sprintf("(list %s)", strings.Join(xs, " "))
453+
}
454+
var body string
455+
if len(n.Body) == 0 {
456+
body = "(list)"
457+
} else {
458+
xs := make([]string, len(n.Body))
459+
for i, p := range n.Body {
460+
xs[i] = `"` + escape(c.compileExpr(p), "\n\t\r") + `"`
461+
}
462+
body = fmt.Sprintf("(list %s)", strings.Join(xs, " "))
463+
}
464+
return fmt.Sprintf(`(heredoc %s "%s" %s)`, flags, n.EndMarker, body)
443465
case *ast.ParenExpr:
444466
return c.compileExpr(n.X)
445467
}
@@ -450,7 +472,16 @@ func escape(s string, chars string) string {
450472
r := ""
451473
for _, c := range s {
452474
if strings.IndexRune(chars, c) != -1 {
453-
r += `\` + string(c)
475+
switch c {
476+
case '\n':
477+
r += `\n`
478+
case '\t':
479+
r += `\t`
480+
case '\r':
481+
r += `\r`
482+
default:
483+
r += `\` + string(c)
484+
}
454485
} else {
455486
r += string(c)
456487
}

go/export.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -453,6 +453,14 @@ func newAstNode(n *VimNode, filename string) ast.Node {
453453
Value: n.value.(string),
454454
}
455455

456+
case NODE_HEREDOC:
457+
return &ast.HeredocExpr{
458+
OpPos: pos,
459+
Flags: newRlist(*n, filename),
460+
EndMarker: n.op,
461+
Body: newBodyExprs(*n, filename),
462+
}
463+
456464
case NODE_PARENEXPR:
457465
n := n.value.(*VimNode)
458466
return &ast.ParenExpr{
@@ -535,6 +543,14 @@ func newBody(n VimNode, filename string) []ast.Statement {
535543
return body
536544
}
537545

546+
func newBodyExprs(n VimNode, filename string) []ast.Expr {
547+
body := make([]ast.Expr, len(n.body))
548+
for i, node := range n.body {
549+
body[i] = newExprNode(node, filename)
550+
}
551+
return body
552+
}
553+
538554
func newIdents(n VimNode, filename string) []*ast.Ident {
539555
var idents []*ast.Ident
540556
if n.rlist != nil {

0 commit comments

Comments
 (0)