github.com/arvindram03/terraform@v0.3.7-0.20150212015210-408f838db36d/config/lang/lang.y (about) 1 // This is the yacc input for creating the parser for interpolation 2 // expressions in Go. To build it, just run `go generate` on this 3 // package, as the lexer has the go generate pragma within it. 4 5 %{ 6 package lang 7 8 import ( 9 "github.com/hashicorp/terraform/config/lang/ast" 10 ) 11 12 %} 13 14 %union { 15 node ast.Node 16 nodeList []ast.Node 17 str string 18 token *parserToken 19 } 20 21 %token <str> PROGRAM_BRACKET_LEFT PROGRAM_BRACKET_RIGHT 22 %token <str> PROGRAM_STRING_START PROGRAM_STRING_END 23 %token <str> PAREN_LEFT PAREN_RIGHT COMMA 24 25 %token <token> IDENTIFIER INTEGER FLOAT STRING 26 27 %type <node> expr interpolation literal literalModeTop literalModeValue 28 %type <nodeList> args 29 30 %% 31 32 top: 33 { 34 parserResult = &ast.LiteralNode{ 35 Value: "", 36 Typex: ast.TypeString, 37 Posx: ast.Pos{Column: 1, Line: 1}, 38 } 39 } 40 | literalModeTop 41 { 42 parserResult = $1 43 44 // We want to make sure that the top value is always a Concat 45 // so that the return value is always a string type from an 46 // interpolation. 47 // 48 // The logic for checking for a LiteralNode is a little annoying 49 // because functionally the AST is the same, but we do that because 50 // it makes for an easy literal check later (to check if a string 51 // has any interpolations). 52 if _, ok := $1.(*ast.Concat); !ok { 53 if n, ok := $1.(*ast.LiteralNode); !ok || n.Typex != ast.TypeString { 54 parserResult = &ast.Concat{ 55 Exprs: []ast.Node{$1}, 56 Posx: $1.Pos(), 57 } 58 } 59 } 60 } 61 62 literalModeTop: 63 literalModeValue 64 { 65 $$ = $1 66 } 67 | literalModeTop literalModeValue 68 { 69 var result []ast.Node 70 if c, ok := $1.(*ast.Concat); ok { 71 result = append(c.Exprs, $2) 72 } else { 73 result = []ast.Node{$1, $2} 74 } 75 76 $$ = &ast.Concat{ 77 Exprs: result, 78 Posx: result[0].Pos(), 79 } 80 } 81 82 literalModeValue: 83 literal 84 { 85 $$ = $1 86 } 87 | interpolation 88 { 89 $$ = $1 90 } 91 92 interpolation: 93 PROGRAM_BRACKET_LEFT expr PROGRAM_BRACKET_RIGHT 94 { 95 $$ = $2 96 } 97 98 expr: 99 literalModeTop 100 { 101 $$ = $1 102 } 103 | INTEGER 104 { 105 $$ = &ast.LiteralNode{ 106 Value: $1.Value.(int), 107 Typex: ast.TypeInt, 108 Posx: $1.Pos, 109 } 110 } 111 | FLOAT 112 { 113 $$ = &ast.LiteralNode{ 114 Value: $1.Value.(float64), 115 Typex: ast.TypeFloat, 116 Posx: $1.Pos, 117 } 118 } 119 | IDENTIFIER 120 { 121 $$ = &ast.VariableAccess{Name: $1.Value.(string), Posx: $1.Pos} 122 } 123 | IDENTIFIER PAREN_LEFT args PAREN_RIGHT 124 { 125 $$ = &ast.Call{Func: $1.Value.(string), Args: $3, Posx: $1.Pos} 126 } 127 128 args: 129 { 130 $$ = nil 131 } 132 | args COMMA expr 133 { 134 $$ = append($1, $3) 135 } 136 | expr 137 { 138 $$ = append($$, $1) 139 } 140 141 literal: 142 STRING 143 { 144 $$ = &ast.LiteralNode{ 145 Value: $1.Value.(string), 146 Typex: ast.TypeString, 147 Posx: $1.Pos, 148 } 149 } 150 151 %%