Merge pull request #5348 from hashicorp/update-hil

dependencies: Update github.com/hashicorp/hil
This commit is contained in:
James Nugent 2016-02-26 15:03:16 -05:00
commit 3ea72e8b4c
12 changed files with 374 additions and 100 deletions

4
Godeps/Godeps.json generated
View File

@ -666,11 +666,11 @@
}, },
{ {
"ImportPath": "github.com/hashicorp/hil", "ImportPath": "github.com/hashicorp/hil",
"Rev": "42518c6f01625b5e6948a6a0e6a0792df126c548" "Rev": "0457360d54ca4d081a769eaa1617e0462153fd70"
}, },
{ {
"ImportPath": "github.com/hashicorp/hil/ast", "ImportPath": "github.com/hashicorp/hil/ast",
"Rev": "42518c6f01625b5e6948a6a0e6a0792df126c548" "Rev": "0457360d54ca4d081a769eaa1617e0462153fd70"
}, },
{ {
"ImportPath": "github.com/hashicorp/logutils", "ImportPath": "github.com/hashicorp/logutils",

View File

@ -1 +1,3 @@
.DS_Store .DS_Store
.idea
*.iml

View File

@ -52,4 +52,5 @@ const (
TypeString TypeString
TypeInt TypeInt
TypeFloat TypeFloat
TypeList
) )

68
vendor/github.com/hashicorp/hil/ast/index.go generated vendored Normal file
View File

@ -0,0 +1,68 @@
package ast
import (
"fmt"
"strings"
)
// Index represents an indexing operation into another data structure
type Index struct {
Target Node
Key Node
Posx Pos
}
func (n *Index) Accept(v Visitor) Node {
return v(n)
}
func (n *Index) Pos() Pos {
return n.Posx
}
func (n *Index) String() string {
return fmt.Sprintf("Index(%s, %s)", n.Target, n.Key)
}
func (n *Index) Type(s Scope) (Type, error) {
variableAccess, ok := n.Target.(*VariableAccess)
if !ok {
return TypeInvalid, fmt.Errorf("target is not a variable")
}
variable, ok := s.LookupVar(variableAccess.Name)
if !ok {
return TypeInvalid, fmt.Errorf("unknown variable accessed: %s", variableAccess.Name)
}
if variable.Type != TypeList {
return TypeInvalid, fmt.Errorf("invalid index operation into non-indexable type: %s", variable.Type)
}
list := variable.Value.([]Variable)
// Ensure that the types of the list elements are homogenous
listTypes := make(map[Type]struct{})
for _, v := range list {
if _, ok := listTypes[v.Type]; ok {
continue
}
listTypes[v.Type] = struct{}{}
}
if len(listTypes) != 1 {
typesFound := make([]string, len(listTypes))
i := 0
for k, _ := range listTypes {
typesFound[0] = k.String()
i++
}
types := strings.Join(typesFound, ", ")
return TypeInvalid, fmt.Errorf("list %q does not have homogenous types. found %s", variableAccess.Name, types)
}
return list[0].Type, nil
}
func (n *Index) GoString() string {
return fmt.Sprintf("*%#v", *n)
}

View File

@ -1,5 +1,10 @@
package ast package ast
import (
"fmt"
"reflect"
)
// Scope is the interface used to look up variables and functions while // Scope is the interface used to look up variables and functions while
// evaluating. How these functions/variables are defined are up to the caller. // evaluating. How these functions/variables are defined are up to the caller.
type Scope interface { type Scope interface {
@ -14,6 +19,26 @@ type Variable struct {
Type Type Type Type
} }
// NewVariable creates a new Variable for the given value. This will
// attempt to infer the correct type. If it can't, an error will be returned.
func NewVariable(v interface{}) (result Variable, err error) {
switch v := reflect.ValueOf(v); v.Kind() {
case reflect.String:
result.Type = TypeString
default:
err = fmt.Errorf("Unknown type: %s", v.Kind())
}
result.Value = v
return
}
// String implements Stringer on Variable, displaying the type and value
// of the Variable.
func (v Variable) String() string {
return fmt.Sprintf("{Variable (%s): %+v}", v.Type, v.Value)
}
// Function defines a function that can be executed by the engine. // Function defines a function that can be executed by the engine.
// The type checker will validate that the proper types will be called // The type checker will validate that the proper types will be called
// to the callback. // to the callback.

View File

@ -10,6 +10,7 @@ const (
_Type_name_2 = "TypeString" _Type_name_2 = "TypeString"
_Type_name_3 = "TypeInt" _Type_name_3 = "TypeInt"
_Type_name_4 = "TypeFloat" _Type_name_4 = "TypeFloat"
_Type_name_5 = "TypeList"
) )
var ( var (
@ -18,6 +19,7 @@ var (
_Type_index_2 = [...]uint8{0, 10} _Type_index_2 = [...]uint8{0, 10}
_Type_index_3 = [...]uint8{0, 7} _Type_index_3 = [...]uint8{0, 7}
_Type_index_4 = [...]uint8{0, 9} _Type_index_4 = [...]uint8{0, 9}
_Type_index_5 = [...]uint8{0, 8}
) )
func (i Type) String() string { func (i Type) String() string {
@ -32,6 +34,8 @@ func (i Type) String() string {
return _Type_name_3 return _Type_name_3
case i == 16: case i == 16:
return _Type_name_4 return _Type_name_4
case i == 32:
return _Type_name_5
default: default:
return fmt.Sprintf("Type(%d)", i) return fmt.Sprintf("Type(%d)", i)
} }

View File

@ -61,6 +61,9 @@ func (v *TypeCheck) visit(raw ast.Node) ast.Node {
case *ast.Call: case *ast.Call:
tc := &typeCheckCall{n} tc := &typeCheckCall{n}
result, err = tc.TypeCheck(v) result, err = tc.TypeCheck(v)
case *ast.Index:
tc := &typeCheckIndex{n}
result, err = tc.TypeCheck(v)
case *ast.Concat: case *ast.Concat:
tc := &typeCheckConcat{n} tc := &typeCheckConcat{n}
result, err = tc.TypeCheck(v) result, err = tc.TypeCheck(v)
@ -285,6 +288,55 @@ func (tc *typeCheckVariableAccess) TypeCheck(v *TypeCheck) (ast.Node, error) {
return tc.n, nil return tc.n, nil
} }
type typeCheckIndex struct {
n *ast.Index
}
func (tc *typeCheckIndex) TypeCheck(v *TypeCheck) (ast.Node, error) {
value, err := tc.n.Key.Type(v.Scope)
if err != nil {
return nil, err
}
if value != ast.TypeInt {
return nil, fmt.Errorf("key of an index must be an int, was %s", value)
}
// Ensure we have a VariableAccess as the target
varAccessNode, ok := tc.n.Target.(*ast.VariableAccess)
if !ok {
return nil, fmt.Errorf("target of an index must be a VariableAccess node, was %T", tc.n.Target)
}
// Get the variable
variable, ok := v.Scope.LookupVar(varAccessNode.Name)
if !ok {
return nil, fmt.Errorf("unknown variable accessed: %s", varAccessNode.Name)
}
if variable.Type != ast.TypeList {
return nil, fmt.Errorf("invalid index operation into non-indexable type: %s", variable.Type)
}
list := variable.Value.([]ast.Variable)
// Ensure that the types of the list elements are homogenous
listTypes := make(map[ast.Type]struct{})
for _, v := range list {
if _, ok := listTypes[v.Type]; ok {
continue
}
listTypes[v.Type] = struct{}{}
}
if len(listTypes) != 1 {
return nil, fmt.Errorf("list %q does not have homogenous types (%s)", varAccessNode.Name)
}
// This is the type since the list is homogenous in type
v.StackPush(list[0].Type)
return tc.n, nil
}
func (v *TypeCheck) ImplicitConversion( func (v *TypeCheck) ImplicitConversion(
actual ast.Type, expected ast.Type, n ast.Node) ast.Node { actual ast.Type, expected ast.Type, n ast.Node) ast.Node {
if v.Implicit == nil { if v.Implicit == nil {

View File

@ -140,6 +140,8 @@ func (v *evalVisitor) visit(raw ast.Node) ast.Node {
// types as well as any other EvalNode implementations. // types as well as any other EvalNode implementations.
func evalNode(raw ast.Node) (EvalNode, error) { func evalNode(raw ast.Node) (EvalNode, error) {
switch n := raw.(type) { switch n := raw.(type) {
case *ast.Index:
return &evalIndex{n}, nil
case *ast.Call: case *ast.Call:
return &evalCall{n}, nil return &evalCall{n}, nil
case *ast.Concat: case *ast.Concat:
@ -184,6 +186,53 @@ func (v *evalCall) Eval(s ast.Scope, stack *ast.Stack) (interface{}, ast.Type, e
return result, function.ReturnType, nil return result, function.ReturnType, nil
} }
type evalIndex struct{ *ast.Index }
func (v *evalIndex) Eval(scope ast.Scope, stack *ast.Stack) (interface{}, ast.Type, error) {
evalVarAccess, err := evalNode(v.Target)
if err != nil {
return nil, ast.TypeInvalid, err
}
target, targetType, err := evalVarAccess.Eval(scope, stack)
evalKey, err := evalNode(v.Key)
if err != nil {
return nil, ast.TypeInvalid, err
}
key, keyType, err := evalKey.Eval(scope, stack)
// Last sanity check
if targetType != ast.TypeList {
return nil, ast.TypeInvalid, fmt.Errorf("target for indexing must be ast.TypeList, is %s", targetType)
}
if keyType != ast.TypeInt {
return nil, ast.TypeInvalid, fmt.Errorf("key for indexing must be ast.TypeInt, is %s", keyType)
}
list, ok := target.([]ast.Variable)
if !ok {
return nil, ast.TypeInvalid, fmt.Errorf("cannot cast target to []Variable")
}
keyInt, ok := key.(int)
if !ok {
return nil, ast.TypeInvalid, fmt.Errorf("cannot cast key to int")
}
if len(list) == 0 {
return nil, ast.TypeInvalid, fmt.Errorf("list is empty")
}
if keyInt < 0 || len(list) < keyInt+1 {
return nil, ast.TypeInvalid, fmt.Errorf("index %d out of range (max %d)", keyInt, len(list))
}
returnVal := list[keyInt].Value
returnType := list[keyInt].Type
return returnVal, returnType, nil
}
type evalConcat struct{ *ast.Concat } type evalConcat struct{ *ast.Concat }
func (v *evalConcat) Eval(s ast.Scope, stack *ast.Stack) (interface{}, ast.Type, error) { func (v *evalConcat) Eval(s ast.Scope, stack *ast.Stack) (interface{}, ast.Type, error) {

View File

@ -21,6 +21,7 @@ import (
%token <str> PROGRAM_BRACKET_LEFT PROGRAM_BRACKET_RIGHT %token <str> PROGRAM_BRACKET_LEFT PROGRAM_BRACKET_RIGHT
%token <str> PROGRAM_STRING_START PROGRAM_STRING_END %token <str> PROGRAM_STRING_START PROGRAM_STRING_END
%token <str> PAREN_LEFT PAREN_RIGHT COMMA %token <str> PAREN_LEFT PAREN_RIGHT COMMA
%token <str> SQUARE_BRACKET_LEFT SQUARE_BRACKET_RIGHT
%token <token> ARITH_OP IDENTIFIER INTEGER FLOAT STRING %token <token> ARITH_OP IDENTIFIER INTEGER FLOAT STRING
@ -157,6 +158,17 @@ expr:
{ {
$$ = &ast.Call{Func: $1.Value.(string), Args: $3, Posx: $1.Pos} $$ = &ast.Call{Func: $1.Value.(string), Args: $3, Posx: $1.Pos}
} }
| IDENTIFIER SQUARE_BRACKET_LEFT expr SQUARE_BRACKET_RIGHT
{
$$ = &ast.Index{
Target: &ast.VariableAccess{
Name: $1.Value.(string),
Posx: $1.Pos,
},
Key: $3,
Posx: $1.Pos,
}
}
args: args:
{ {

View File

@ -166,6 +166,10 @@ func (x *parserLex) lexModeInterpolation(yylval *parserSymType) int {
return PAREN_LEFT return PAREN_LEFT
case ')': case ')':
return PAREN_RIGHT return PAREN_RIGHT
case '[':
return SQUARE_BRACKET_LEFT
case ']':
return SQUARE_BRACKET_RIGHT
case ',': case ',':
return COMMA return COMMA
case '+': case '+':

114
vendor/github.com/hashicorp/hil/y.go generated vendored
View File

@ -24,11 +24,13 @@ const PROGRAM_STRING_END = 57349
const PAREN_LEFT = 57350 const PAREN_LEFT = 57350
const PAREN_RIGHT = 57351 const PAREN_RIGHT = 57351
const COMMA = 57352 const COMMA = 57352
const ARITH_OP = 57353 const SQUARE_BRACKET_LEFT = 57353
const IDENTIFIER = 57354 const SQUARE_BRACKET_RIGHT = 57354
const INTEGER = 57355 const ARITH_OP = 57355
const FLOAT = 57356 const IDENTIFIER = 57356
const STRING = 57357 const INTEGER = 57357
const FLOAT = 57358
const STRING = 57359
var parserToknames = [...]string{ var parserToknames = [...]string{
"$end", "$end",
@ -41,6 +43,8 @@ var parserToknames = [...]string{
"PAREN_LEFT", "PAREN_LEFT",
"PAREN_RIGHT", "PAREN_RIGHT",
"COMMA", "COMMA",
"SQUARE_BRACKET_LEFT",
"SQUARE_BRACKET_RIGHT",
"ARITH_OP", "ARITH_OP",
"IDENTIFIER", "IDENTIFIER",
"INTEGER", "INTEGER",
@ -53,7 +57,7 @@ const parserEofCode = 1
const parserErrCode = 2 const parserErrCode = 2
const parserMaxDepth = 200 const parserMaxDepth = 200
//line lang.y:184 //line lang.y:196
//line yacctab:1 //line yacctab:1
var parserExca = [...]int{ var parserExca = [...]int{
@ -62,52 +66,57 @@ var parserExca = [...]int{
-2, 0, -2, 0,
} }
const parserNprod = 20 const parserNprod = 21
const parserPrivate = 57344 const parserPrivate = 57344
var parserTokenNames []string var parserTokenNames []string
var parserStates []string var parserStates []string
const parserLast = 34 const parserLast = 37
var parserAct = [...]int{ var parserAct = [...]int{
9, 7, 3, 16, 22, 8, 17, 17, 20, 17, 9, 7, 29, 17, 23, 16, 17, 3, 17, 20,
1, 18, 6, 23, 8, 19, 25, 26, 21, 11, 8, 18, 21, 17, 6, 19, 27, 28, 22, 8,
2, 24, 7, 4, 5, 0, 10, 27, 0, 14, 1, 25, 26, 7, 11, 2, 24, 10, 4, 30,
15, 12, 13, 6, 5, 0, 14, 15, 12, 13, 6,
} }
var parserPact = [...]int{ var parserPact = [...]int{
-3, -1000, -3, -1000, -1000, -1000, -1000, 18, -1000, -2, -3, -1000, -3, -1000, -1000, -1000, -1000, 19, -1000, 0,
18, -3, -1000, -1000, 18, 0, -1000, 18, -5, -1000, 19, -3, -1000, -1000, 19, 1, -1000, 19, -5, -1000,
18, -1000, -1000, 7, -4, -1000, 18, -4, 19, 19, -1000, -1000, 7, -7, -10, -1000, 19, -1000,
-7,
} }
var parserPgo = [...]int{ var parserPgo = [...]int{
0, 0, 24, 23, 19, 2, 13, 10, 0, 0, 30, 28, 24, 7, 26, 20,
} }
var parserR1 = [...]int{ var parserR1 = [...]int{
0, 7, 7, 4, 4, 5, 5, 2, 1, 1, 0, 7, 7, 4, 4, 5, 5, 2, 1, 1,
1, 1, 1, 1, 1, 1, 6, 6, 6, 3, 1, 1, 1, 1, 1, 1, 1, 6, 6, 6,
3,
} }
var parserR2 = [...]int{ var parserR2 = [...]int{
0, 0, 1, 1, 2, 1, 1, 3, 3, 1, 0, 0, 1, 1, 2, 1, 1, 3, 3, 1,
1, 1, 2, 3, 1, 4, 0, 3, 1, 1, 1, 1, 2, 3, 1, 4, 4, 0, 3, 1,
1,
} }
var parserChk = [...]int{ var parserChk = [...]int{
-1000, -7, -4, -5, -3, -2, 15, 4, -5, -1, -1000, -7, -4, -5, -3, -2, 17, 4, -5, -1,
8, -4, 13, 14, 11, 12, 5, 11, -1, -1, 8, -4, 15, 16, 13, 14, 5, 13, -1, -1,
8, -1, 9, -6, -1, 9, 10, -1, 8, 11, -1, 9, -6, -1, -1, 9, 10, 12,
-1,
} }
var parserDef = [...]int{ var parserDef = [...]int{
1, -2, 2, 3, 5, 6, 19, 0, 4, 0, 1, -2, 2, 3, 5, 6, 20, 0, 4, 0,
0, 9, 10, 11, 0, 14, 7, 0, 0, 12, 0, 9, 10, 11, 0, 14, 7, 0, 0, 12,
16, 13, 8, 0, 18, 15, 0, 17, 17, 0, 13, 8, 0, 19, 0, 15, 0, 16,
18,
} }
var parserTok1 = [...]int{ var parserTok1 = [...]int{
@ -116,7 +125,7 @@ var parserTok1 = [...]int{
var parserTok2 = [...]int{ var parserTok2 = [...]int{
2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11,
12, 13, 14, 15, 12, 13, 14, 15, 16, 17,
} }
var parserTok3 = [...]int{ var parserTok3 = [...]int{
0, 0,
@ -464,7 +473,7 @@ parserdefault:
case 1: case 1:
parserDollar = parserS[parserpt-0 : parserpt+1] parserDollar = parserS[parserpt-0 : parserpt+1]
//line lang.y:35 //line lang.y:36
{ {
parserResult = &ast.LiteralNode{ parserResult = &ast.LiteralNode{
Value: "", Value: "",
@ -474,7 +483,7 @@ parserdefault:
} }
case 2: case 2:
parserDollar = parserS[parserpt-1 : parserpt+1] parserDollar = parserS[parserpt-1 : parserpt+1]
//line lang.y:43 //line lang.y:44
{ {
parserResult = parserDollar[1].node parserResult = parserDollar[1].node
@ -497,13 +506,13 @@ parserdefault:
} }
case 3: case 3:
parserDollar = parserS[parserpt-1 : parserpt+1] parserDollar = parserS[parserpt-1 : parserpt+1]
//line lang.y:66 //line lang.y:67
{ {
parserVAL.node = parserDollar[1].node parserVAL.node = parserDollar[1].node
} }
case 4: case 4:
parserDollar = parserS[parserpt-2 : parserpt+1] parserDollar = parserS[parserpt-2 : parserpt+1]
//line lang.y:70 //line lang.y:71
{ {
var result []ast.Node var result []ast.Node
if c, ok := parserDollar[1].node.(*ast.Concat); ok { if c, ok := parserDollar[1].node.(*ast.Concat); ok {
@ -519,37 +528,37 @@ parserdefault:
} }
case 5: case 5:
parserDollar = parserS[parserpt-1 : parserpt+1] parserDollar = parserS[parserpt-1 : parserpt+1]
//line lang.y:86 //line lang.y:87
{ {
parserVAL.node = parserDollar[1].node parserVAL.node = parserDollar[1].node
} }
case 6: case 6:
parserDollar = parserS[parserpt-1 : parserpt+1] parserDollar = parserS[parserpt-1 : parserpt+1]
//line lang.y:90 //line lang.y:91
{ {
parserVAL.node = parserDollar[1].node parserVAL.node = parserDollar[1].node
} }
case 7: case 7:
parserDollar = parserS[parserpt-3 : parserpt+1] parserDollar = parserS[parserpt-3 : parserpt+1]
//line lang.y:96 //line lang.y:97
{ {
parserVAL.node = parserDollar[2].node parserVAL.node = parserDollar[2].node
} }
case 8: case 8:
parserDollar = parserS[parserpt-3 : parserpt+1] parserDollar = parserS[parserpt-3 : parserpt+1]
//line lang.y:102 //line lang.y:103
{ {
parserVAL.node = parserDollar[2].node parserVAL.node = parserDollar[2].node
} }
case 9: case 9:
parserDollar = parserS[parserpt-1 : parserpt+1] parserDollar = parserS[parserpt-1 : parserpt+1]
//line lang.y:106 //line lang.y:107
{ {
parserVAL.node = parserDollar[1].node parserVAL.node = parserDollar[1].node
} }
case 10: case 10:
parserDollar = parserS[parserpt-1 : parserpt+1] parserDollar = parserS[parserpt-1 : parserpt+1]
//line lang.y:110 //line lang.y:111
{ {
parserVAL.node = &ast.LiteralNode{ parserVAL.node = &ast.LiteralNode{
Value: parserDollar[1].token.Value.(int), Value: parserDollar[1].token.Value.(int),
@ -559,7 +568,7 @@ parserdefault:
} }
case 11: case 11:
parserDollar = parserS[parserpt-1 : parserpt+1] parserDollar = parserS[parserpt-1 : parserpt+1]
//line lang.y:118 //line lang.y:119
{ {
parserVAL.node = &ast.LiteralNode{ parserVAL.node = &ast.LiteralNode{
Value: parserDollar[1].token.Value.(float64), Value: parserDollar[1].token.Value.(float64),
@ -569,7 +578,7 @@ parserdefault:
} }
case 12: case 12:
parserDollar = parserS[parserpt-2 : parserpt+1] parserDollar = parserS[parserpt-2 : parserpt+1]
//line lang.y:126 //line lang.y:127
{ {
// This is REALLY jank. We assume that a singular ARITH_OP // This is REALLY jank. We assume that a singular ARITH_OP
// means 0 ARITH_OP expr, which... is weird. We don't want to // means 0 ARITH_OP expr, which... is weird. We don't want to
@ -590,7 +599,7 @@ parserdefault:
} }
case 13: case 13:
parserDollar = parserS[parserpt-3 : parserpt+1] parserDollar = parserS[parserpt-3 : parserpt+1]
//line lang.y:145 //line lang.y:146
{ {
parserVAL.node = &ast.Arithmetic{ parserVAL.node = &ast.Arithmetic{
Op: parserDollar[2].token.Value.(ast.ArithmeticOp), Op: parserDollar[2].token.Value.(ast.ArithmeticOp),
@ -600,37 +609,50 @@ parserdefault:
} }
case 14: case 14:
parserDollar = parserS[parserpt-1 : parserpt+1] parserDollar = parserS[parserpt-1 : parserpt+1]
//line lang.y:153 //line lang.y:154
{ {
parserVAL.node = &ast.VariableAccess{Name: parserDollar[1].token.Value.(string), Posx: parserDollar[1].token.Pos} parserVAL.node = &ast.VariableAccess{Name: parserDollar[1].token.Value.(string), Posx: parserDollar[1].token.Pos}
} }
case 15: case 15:
parserDollar = parserS[parserpt-4 : parserpt+1] parserDollar = parserS[parserpt-4 : parserpt+1]
//line lang.y:157 //line lang.y:158
{ {
parserVAL.node = &ast.Call{Func: parserDollar[1].token.Value.(string), Args: parserDollar[3].nodeList, Posx: parserDollar[1].token.Pos} parserVAL.node = &ast.Call{Func: parserDollar[1].token.Value.(string), Args: parserDollar[3].nodeList, Posx: parserDollar[1].token.Pos}
} }
case 16: case 16:
parserDollar = parserS[parserpt-0 : parserpt+1] parserDollar = parserS[parserpt-4 : parserpt+1]
//line lang.y:162 //line lang.y:162
{
parserVAL.node = &ast.Index{
Target: &ast.VariableAccess{
Name: parserDollar[1].token.Value.(string),
Posx: parserDollar[1].token.Pos,
},
Key: parserDollar[3].node,
Posx: parserDollar[1].token.Pos,
}
}
case 17:
parserDollar = parserS[parserpt-0 : parserpt+1]
//line lang.y:174
{ {
parserVAL.nodeList = nil parserVAL.nodeList = nil
} }
case 17: case 18:
parserDollar = parserS[parserpt-3 : parserpt+1] parserDollar = parserS[parserpt-3 : parserpt+1]
//line lang.y:166 //line lang.y:178
{ {
parserVAL.nodeList = append(parserDollar[1].nodeList, parserDollar[3].node) parserVAL.nodeList = append(parserDollar[1].nodeList, parserDollar[3].node)
} }
case 18: case 19:
parserDollar = parserS[parserpt-1 : parserpt+1] parserDollar = parserS[parserpt-1 : parserpt+1]
//line lang.y:170 //line lang.y:182
{ {
parserVAL.nodeList = append(parserVAL.nodeList, parserDollar[1].node) parserVAL.nodeList = append(parserVAL.nodeList, parserDollar[1].node)
} }
case 19: case 20:
parserDollar = parserS[parserpt-1 : parserpt+1] parserDollar = parserS[parserpt-1 : parserpt+1]
//line lang.y:176 //line lang.y:188
{ {
parserVAL.node = &ast.LiteralNode{ parserVAL.node = &ast.LiteralNode{
Value: parserDollar[1].token.Value.(string), Value: parserDollar[1].token.Value.(string),

View File

@ -5,7 +5,7 @@ state 0
PROGRAM_BRACKET_LEFT shift 7 PROGRAM_BRACKET_LEFT shift 7
STRING shift 6 STRING shift 6
. reduce 1 (src line 34) . reduce 1 (src line 35)
interpolation goto 5 interpolation goto 5
literal goto 4 literal goto 4
@ -26,7 +26,7 @@ state 2
PROGRAM_BRACKET_LEFT shift 7 PROGRAM_BRACKET_LEFT shift 7
STRING shift 6 STRING shift 6
. reduce 2 (src line 42) . reduce 2 (src line 43)
interpolation goto 5 interpolation goto 5
literal goto 4 literal goto 4
@ -35,25 +35,25 @@ state 2
state 3 state 3
literalModeTop: literalModeValue. (3) literalModeTop: literalModeValue. (3)
. reduce 3 (src line 64) . reduce 3 (src line 65)
state 4 state 4
literalModeValue: literal. (5) literalModeValue: literal. (5)
. reduce 5 (src line 84) . reduce 5 (src line 85)
state 5 state 5
literalModeValue: interpolation. (6) literalModeValue: interpolation. (6)
. reduce 6 (src line 89) . reduce 6 (src line 90)
state 6 state 6
literal: STRING. (19) literal: STRING. (20)
. reduce 19 (src line 174) . reduce 20 (src line 186)
state 7 state 7
@ -77,7 +77,7 @@ state 7
state 8 state 8
literalModeTop: literalModeTop literalModeValue. (4) literalModeTop: literalModeTop literalModeValue. (4)
. reduce 4 (src line 69) . reduce 4 (src line 70)
state 9 state 9
@ -113,7 +113,7 @@ state 11
PROGRAM_BRACKET_LEFT shift 7 PROGRAM_BRACKET_LEFT shift 7
STRING shift 6 STRING shift 6
. reduce 9 (src line 105) . reduce 9 (src line 106)
interpolation goto 5 interpolation goto 5
literal goto 4 literal goto 4
@ -122,13 +122,13 @@ state 11
state 12 state 12
expr: INTEGER. (10) expr: INTEGER. (10)
. reduce 10 (src line 109) . reduce 10 (src line 110)
state 13 state 13
expr: FLOAT. (11) expr: FLOAT. (11)
. reduce 11 (src line 117) . reduce 11 (src line 118)
state 14 state 14
@ -152,15 +152,17 @@ state 14
state 15 state 15
expr: IDENTIFIER. (14) expr: IDENTIFIER. (14)
expr: IDENTIFIER.PAREN_LEFT args PAREN_RIGHT expr: IDENTIFIER.PAREN_LEFT args PAREN_RIGHT
expr: IDENTIFIER.SQUARE_BRACKET_LEFT expr SQUARE_BRACKET_RIGHT
PAREN_LEFT shift 20 PAREN_LEFT shift 20
. reduce 14 (src line 152) SQUARE_BRACKET_LEFT shift 21
. reduce 14 (src line 153)
state 16 state 16
interpolation: PROGRAM_BRACKET_LEFT expr PROGRAM_BRACKET_RIGHT. (7) interpolation: PROGRAM_BRACKET_LEFT expr PROGRAM_BRACKET_RIGHT. (7)
. reduce 7 (src line 94) . reduce 7 (src line 95)
state 17 state 17
@ -175,7 +177,7 @@ state 17
STRING shift 6 STRING shift 6
. error . error
expr goto 21 expr goto 22
interpolation goto 5 interpolation goto 5
literal goto 4 literal goto 4
literalModeTop goto 11 literalModeTop goto 11
@ -185,7 +187,7 @@ state 18
expr: PAREN_LEFT expr.PAREN_RIGHT expr: PAREN_LEFT expr.PAREN_RIGHT
expr: expr.ARITH_OP expr expr: expr.ARITH_OP expr
PAREN_RIGHT shift 22 PAREN_RIGHT shift 23
ARITH_OP shift 17 ARITH_OP shift 17
. error . error
@ -194,12 +196,12 @@ state 19
expr: ARITH_OP expr. (12) expr: ARITH_OP expr. (12)
expr: expr.ARITH_OP expr expr: expr.ARITH_OP expr
. reduce 12 (src line 125) . reduce 12 (src line 126)
state 20 state 20
expr: IDENTIFIER PAREN_LEFT.args PAREN_RIGHT expr: IDENTIFIER PAREN_LEFT.args PAREN_RIGHT
args: . (16) args: . (17)
PROGRAM_BRACKET_LEFT shift 7 PROGRAM_BRACKET_LEFT shift 7
PAREN_LEFT shift 10 PAREN_LEFT shift 10
@ -208,52 +210,79 @@ state 20
INTEGER shift 12 INTEGER shift 12
FLOAT shift 13 FLOAT shift 13
STRING shift 6 STRING shift 6
. reduce 16 (src line 161) . reduce 17 (src line 173)
expr goto 24 expr goto 25
interpolation goto 5 interpolation goto 5
literal goto 4 literal goto 4
literalModeTop goto 11 literalModeTop goto 11
literalModeValue goto 3 literalModeValue goto 3
args goto 23 args goto 24
state 21 state 21
expr: IDENTIFIER SQUARE_BRACKET_LEFT.expr SQUARE_BRACKET_RIGHT
PROGRAM_BRACKET_LEFT shift 7
PAREN_LEFT shift 10
ARITH_OP shift 14
IDENTIFIER shift 15
INTEGER shift 12
FLOAT shift 13
STRING shift 6
. error
expr goto 26
interpolation goto 5
literal goto 4
literalModeTop goto 11
literalModeValue goto 3
state 22
expr: expr.ARITH_OP expr expr: expr.ARITH_OP expr
expr: expr ARITH_OP expr. (13) expr: expr ARITH_OP expr. (13)
. reduce 13 (src line 144) . reduce 13 (src line 145)
state 22
expr: PAREN_LEFT expr PAREN_RIGHT. (8)
. reduce 8 (src line 100)
state 23 state 23
expr: IDENTIFIER PAREN_LEFT args.PAREN_RIGHT expr: PAREN_LEFT expr PAREN_RIGHT. (8)
args: args.COMMA expr
PAREN_RIGHT shift 25 . reduce 8 (src line 101)
COMMA shift 26
. error
state 24 state 24
expr: expr.ARITH_OP expr expr: IDENTIFIER PAREN_LEFT args.PAREN_RIGHT
args: expr. (18) args: args.COMMA expr
ARITH_OP shift 17 PAREN_RIGHT shift 27
. reduce 18 (src line 169) COMMA shift 28
. error
state 25 state 25
expr: IDENTIFIER PAREN_LEFT args PAREN_RIGHT. (15) expr: expr.ARITH_OP expr
args: expr. (19)
. reduce 15 (src line 156) ARITH_OP shift 17
. reduce 19 (src line 181)
state 26 state 26
expr: expr.ARITH_OP expr
expr: IDENTIFIER SQUARE_BRACKET_LEFT expr.SQUARE_BRACKET_RIGHT
SQUARE_BRACKET_RIGHT shift 29
ARITH_OP shift 17
. error
state 27
expr: IDENTIFIER PAREN_LEFT args PAREN_RIGHT. (15)
. reduce 15 (src line 157)
state 28
args: args COMMA.expr args: args COMMA.expr
PROGRAM_BRACKET_LEFT shift 7 PROGRAM_BRACKET_LEFT shift 7
@ -265,29 +294,35 @@ state 26
STRING shift 6 STRING shift 6
. error . error
expr goto 27 expr goto 30
interpolation goto 5 interpolation goto 5
literal goto 4 literal goto 4
literalModeTop goto 11 literalModeTop goto 11
literalModeValue goto 3 literalModeValue goto 3
state 27 state 29
expr: IDENTIFIER SQUARE_BRACKET_LEFT expr SQUARE_BRACKET_RIGHT. (16)
. reduce 16 (src line 161)
state 30
expr: expr.ARITH_OP expr expr: expr.ARITH_OP expr
args: args COMMA expr. (17) args: args COMMA expr. (18)
ARITH_OP shift 17 ARITH_OP shift 17
. reduce 17 (src line 165) . reduce 18 (src line 177)
15 terminals, 8 nonterminals 17 terminals, 8 nonterminals
20 grammar rules, 28/2000 states 21 grammar rules, 31/2000 states
0 shift/reduce, 0 reduce/reduce conflicts reported 0 shift/reduce, 0 reduce/reduce conflicts reported
57 working sets used 57 working sets used
memory: parser 40/30000 memory: parser 45/30000
23 extra closures 26 extra closures
57 shift entries, 1 exceptions 67 shift entries, 1 exceptions
15 goto entries 16 goto entries
27 entries saved by goto default 31 entries saved by goto default
Optimizer space used: output 34/30000 Optimizer space used: output 37/30000
34 table entries, 2 zero 37 table entries, 1 zero
maximum spread: 15, maximum offset: 26 maximum spread: 17, maximum offset: 28