Merge pull request #5348 from hashicorp/update-hil
dependencies: Update github.com/hashicorp/hil
This commit is contained in:
commit
3ea72e8b4c
|
@ -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",
|
||||||
|
|
|
@ -1 +1,3 @@
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
.idea
|
||||||
|
*.iml
|
||||||
|
|
|
@ -52,4 +52,5 @@ const (
|
||||||
TypeString
|
TypeString
|
||||||
TypeInt
|
TypeInt
|
||||||
TypeFloat
|
TypeFloat
|
||||||
|
TypeList
|
||||||
)
|
)
|
||||||
|
|
|
@ -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)
|
||||||
|
}
|
|
@ -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.
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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:
|
||||||
{
|
{
|
||||||
|
|
|
@ -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 '+':
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue