Merge pull request #5804 from hashicorp/dep-update-hil
deps: Update github.com/hashicorp/hil
This commit is contained in:
commit
9cb08cb229
|
@ -738,11 +738,11 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/hashicorp/hil",
|
"ImportPath": "github.com/hashicorp/hil",
|
||||||
"Rev": "1586b586f59cfa528a751d4a62be88910d34e6e9"
|
"Rev": "59cce4313fb7be2d9064afbdb3cacd76737cfa3c"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/hashicorp/hil/ast",
|
"ImportPath": "github.com/hashicorp/hil/ast",
|
||||||
"Rev": "1586b586f59cfa528a751d4a62be88910d34e6e9"
|
"Rev": "59cce4313fb7be2d9064afbdb3cacd76737cfa3c"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"ImportPath": "github.com/hashicorp/logutils",
|
"ImportPath": "github.com/hashicorp/logutils",
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
version: "build-{branch}-{build}"
|
||||||
|
image: Visual Studio 2015
|
||||||
|
clone_folder: c:\gopath\src\github.com\hashicorp\hil
|
||||||
|
environment:
|
||||||
|
GOPATH: c:\gopath
|
||||||
|
init:
|
||||||
|
- git config --global core.autocrlf true
|
||||||
|
install:
|
||||||
|
- cmd: >-
|
||||||
|
echo %Path%
|
||||||
|
|
||||||
|
go version
|
||||||
|
|
||||||
|
go env
|
||||||
|
|
||||||
|
go get -d -v -t ./...
|
||||||
|
build_script:
|
||||||
|
- cmd: go test -v ./...
|
|
@ -53,4 +53,5 @@ const (
|
||||||
TypeInt
|
TypeInt
|
||||||
TypeFloat
|
TypeFloat
|
||||||
TypeList
|
TypeList
|
||||||
|
TypeMap
|
||||||
)
|
)
|
||||||
|
|
|
@ -34,33 +34,39 @@ func (n *Index) Type(s Scope) (Type, error) {
|
||||||
if !ok {
|
if !ok {
|
||||||
return TypeInvalid, fmt.Errorf("unknown variable accessed: %s", variableAccess.Name)
|
return TypeInvalid, fmt.Errorf("unknown variable accessed: %s", variableAccess.Name)
|
||||||
}
|
}
|
||||||
if variable.Type != TypeList {
|
|
||||||
|
switch variable.Type {
|
||||||
|
case TypeList:
|
||||||
|
return n.typeList(variable, variableAccess.Name)
|
||||||
|
case TypeMap:
|
||||||
|
return n.typeMap(variable, variableAccess.Name)
|
||||||
|
default:
|
||||||
return TypeInvalid, fmt.Errorf("invalid index operation into non-indexable type: %s", variable.Type)
|
return TypeInvalid, fmt.Errorf("invalid index operation into non-indexable type: %s", variable.Type)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *Index) typeList(variable Variable, variableName string) (Type, error) {
|
||||||
|
// We assume type checking has already determined that this is a list
|
||||||
list := variable.Value.([]Variable)
|
list := variable.Value.([]Variable)
|
||||||
|
|
||||||
// Ensure that the types of the list elements are homogenous
|
return VariableListElementTypesAreHomogenous(variableName, list)
|
||||||
listTypes := make(map[Type]struct{})
|
}
|
||||||
for _, v := range list {
|
|
||||||
if _, ok := listTypes[v.Type]; ok {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
listTypes[v.Type] = struct{}{}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(listTypes) != 1 {
|
func (n *Index) typeMap(variable Variable, variableName string) (Type, error) {
|
||||||
typesFound := make([]string, len(listTypes))
|
// We assume type checking has already determined that this is a map
|
||||||
i := 0
|
vmap := variable.Value.(map[string]Variable)
|
||||||
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
|
return VariableMapValueTypesAreHomogenous(variableName, vmap)
|
||||||
|
}
|
||||||
|
|
||||||
|
func reportTypes(typesFound map[Type]struct{}) string {
|
||||||
|
stringTypes := make([]string, len(typesFound))
|
||||||
|
i := 0
|
||||||
|
for k, _ := range typesFound {
|
||||||
|
stringTypes[0] = k.String()
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
return strings.Join(stringTypes, ", ")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *Index) GoString() string {
|
func (n *Index) GoString() string {
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
package ast
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func VariableListElementTypesAreHomogenous(variableName string, list []Variable) (Type, error) {
|
||||||
|
listTypes := make(map[Type]struct{})
|
||||||
|
for _, v := range list {
|
||||||
|
if _, ok := listTypes[v.Type]; ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
listTypes[v.Type] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(listTypes) != 1 && len(list) != 0 {
|
||||||
|
return TypeInvalid, fmt.Errorf("list %q does not have homogenous types. found %s", variableName, reportTypes(listTypes))
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(list) > 0 {
|
||||||
|
return list[0].Type, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return TypeInvalid, fmt.Errorf("list %q does not have any elements so cannot determine type.", variableName)
|
||||||
|
}
|
||||||
|
|
||||||
|
func VariableMapValueTypesAreHomogenous(variableName string, vmap map[string]Variable) (Type, error) {
|
||||||
|
valueTypes := make(map[Type]struct{})
|
||||||
|
for _, v := range vmap {
|
||||||
|
if _, ok := valueTypes[v.Type]; ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
valueTypes[v.Type] = struct{}{}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(valueTypes) != 1 && len(vmap) != 0 {
|
||||||
|
return TypeInvalid, fmt.Errorf("map %q does not have homogenous value types. found %s", variableName, reportTypes(valueTypes))
|
||||||
|
}
|
||||||
|
|
||||||
|
// For loop here is an easy way to get a single key, we return immediately.
|
||||||
|
for _, v := range vmap {
|
||||||
|
return v.Type, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// This means the map is empty
|
||||||
|
return TypeInvalid, fmt.Errorf("map %q does not have any elements so cannot determine type.", variableName)
|
||||||
|
}
|
|
@ -241,7 +241,13 @@ func (tc *typeCheckConcat) TypeCheck(v *TypeCheck) (ast.Node, error) {
|
||||||
types[len(n.Exprs)-1-i] = v.StackPop()
|
types[len(n.Exprs)-1-i] = v.StackPop()
|
||||||
}
|
}
|
||||||
|
|
||||||
// All concat args must be strings, so validate that
|
// If there is only one argument and it is a list, we evaluate to a list
|
||||||
|
if len(types) == 1 && types[0] == ast.TypeList {
|
||||||
|
v.StackPush(ast.TypeList)
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, all concat args must be strings, so validate that
|
||||||
for i, t := range types {
|
for i, t := range types {
|
||||||
if t != ast.TypeString {
|
if t != ast.TypeString {
|
||||||
cn := v.ImplicitConversion(t, ast.TypeString, n.Exprs[i])
|
cn := v.ImplicitConversion(t, ast.TypeString, n.Exprs[i])
|
||||||
|
@ -251,7 +257,7 @@ func (tc *typeCheckConcat) TypeCheck(v *TypeCheck) (ast.Node, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, fmt.Errorf(
|
return nil, fmt.Errorf(
|
||||||
"output of an HIL expression must be a string (argument %d is %s)", i+1, t)
|
"output of an HIL expression must be a string, or a single list (argument %d is %s)", i+1, t)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -293,15 +299,6 @@ type typeCheckIndex struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tc *typeCheckIndex) TypeCheck(v *TypeCheck) (ast.Node, error) {
|
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
|
// Ensure we have a VariableAccess as the target
|
||||||
varAccessNode, ok := tc.n.Target.(*ast.VariableAccess)
|
varAccessNode, ok := tc.n.Target.(*ast.VariableAccess)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -313,28 +310,40 @@ func (tc *typeCheckIndex) TypeCheck(v *TypeCheck) (ast.Node, error) {
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("unknown variable accessed: %s", varAccessNode.Name)
|
return nil, fmt.Errorf("unknown variable accessed: %s", varAccessNode.Name)
|
||||||
}
|
}
|
||||||
if variable.Type != ast.TypeList {
|
|
||||||
|
keyType, err := tc.n.Key.Type(v.Scope)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
switch variable.Type {
|
||||||
|
case ast.TypeList:
|
||||||
|
if keyType != ast.TypeInt {
|
||||||
|
return nil, fmt.Errorf("key of an index must be an int, was %s", keyType)
|
||||||
|
}
|
||||||
|
|
||||||
|
valType, err := ast.VariableListElementTypesAreHomogenous(varAccessNode.Name, variable.Value.([]ast.Variable))
|
||||||
|
if err != nil {
|
||||||
|
return tc.n, err
|
||||||
|
}
|
||||||
|
|
||||||
|
v.StackPush(valType)
|
||||||
|
return tc.n, nil
|
||||||
|
case ast.TypeMap:
|
||||||
|
if keyType != ast.TypeString {
|
||||||
|
return nil, fmt.Errorf("key of an index must be a string, was %s", keyType)
|
||||||
|
}
|
||||||
|
|
||||||
|
valType, err := ast.VariableMapValueTypesAreHomogenous(varAccessNode.Name, variable.Value.(map[string]ast.Variable))
|
||||||
|
if err != nil {
|
||||||
|
return tc.n, err
|
||||||
|
}
|
||||||
|
|
||||||
|
v.StackPush(valType)
|
||||||
|
return tc.n, nil
|
||||||
|
default:
|
||||||
return nil, fmt.Errorf("invalid index operation into non-indexable type: %s", variable.Type)
|
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(
|
||||||
|
|
|
@ -200,16 +200,35 @@ func (v *evalIndex) Eval(scope ast.Scope, stack *ast.Stack) (interface{}, ast.Ty
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, ast.TypeInvalid, err
|
return nil, ast.TypeInvalid, err
|
||||||
}
|
}
|
||||||
|
|
||||||
key, keyType, err := evalKey.Eval(scope, stack)
|
key, keyType, err := evalKey.Eval(scope, stack)
|
||||||
|
if err != nil {
|
||||||
// Last sanity check
|
return nil, ast.TypeInvalid, err
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
variableName := v.Index.Target.(*ast.VariableAccess).Name
|
||||||
|
|
||||||
|
switch targetType {
|
||||||
|
case ast.TypeList:
|
||||||
|
if keyType != ast.TypeInt {
|
||||||
|
return nil, ast.TypeInvalid, fmt.Errorf("key for indexing list %q must be an int, is %s", variableName, keyType)
|
||||||
|
}
|
||||||
|
|
||||||
|
return v.evalListIndex(variableName, target, key)
|
||||||
|
case ast.TypeMap:
|
||||||
|
if keyType != ast.TypeString {
|
||||||
|
return nil, ast.TypeInvalid, fmt.Errorf("key for indexing map %q must be a string, is %s", variableName, keyType)
|
||||||
|
}
|
||||||
|
|
||||||
|
return v.evalMapIndex(variableName, target, key)
|
||||||
|
default:
|
||||||
|
return nil, ast.TypeInvalid, fmt.Errorf("target %q for indexing must be ast.TypeList or ast.TypeMap, is %s", variableName, targetType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (v *evalIndex) evalListIndex(variableName string, target interface{}, key interface{}) (interface{}, ast.Type, error) {
|
||||||
|
// We assume type checking was already done and we can assume that target
|
||||||
|
// is a list and key is an int
|
||||||
list, ok := target.([]ast.Variable)
|
list, ok := target.([]ast.Variable)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, ast.TypeInvalid, fmt.Errorf("cannot cast target to []Variable")
|
return nil, ast.TypeInvalid, fmt.Errorf("cannot cast target to []Variable")
|
||||||
|
@ -225,7 +244,7 @@ func (v *evalIndex) Eval(scope ast.Scope, stack *ast.Stack) (interface{}, ast.Ty
|
||||||
}
|
}
|
||||||
|
|
||||||
if keyInt < 0 || len(list) < keyInt+1 {
|
if keyInt < 0 || len(list) < keyInt+1 {
|
||||||
return nil, ast.TypeInvalid, fmt.Errorf("index %d out of range (max %d)", keyInt, len(list))
|
return nil, ast.TypeInvalid, fmt.Errorf("index %d out of range for list %s (max %d)", keyInt, variableName, len(list))
|
||||||
}
|
}
|
||||||
|
|
||||||
returnVal := list[keyInt].Value
|
returnVal := list[keyInt].Value
|
||||||
|
@ -234,6 +253,31 @@ func (v *evalIndex) Eval(scope ast.Scope, stack *ast.Stack) (interface{}, ast.Ty
|
||||||
return returnVal, returnType, nil
|
return returnVal, returnType, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (v *evalIndex) evalMapIndex(variableName string, target interface{}, key interface{}) (interface{}, ast.Type, error) {
|
||||||
|
// We assume type checking was already done and we can assume that target
|
||||||
|
// is a map and key is a string
|
||||||
|
vmap, ok := target.(map[string]ast.Variable)
|
||||||
|
if !ok {
|
||||||
|
return nil, ast.TypeInvalid, fmt.Errorf("cannot cast target to map[string]Variable")
|
||||||
|
}
|
||||||
|
|
||||||
|
keyString, ok := key.(string)
|
||||||
|
if !ok {
|
||||||
|
return nil, ast.TypeInvalid, fmt.Errorf("cannot cast key to string")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(vmap) == 0 {
|
||||||
|
return nil, ast.TypeInvalid, fmt.Errorf("map is empty")
|
||||||
|
}
|
||||||
|
|
||||||
|
value, ok := vmap[keyString]
|
||||||
|
if !ok {
|
||||||
|
return nil, ast.TypeInvalid, fmt.Errorf("key %q does not exist in map %s", keyString, variableName)
|
||||||
|
}
|
||||||
|
|
||||||
|
return value.Value, value.Type, 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) {
|
||||||
|
@ -244,6 +288,12 @@ func (v *evalConcat) Eval(s ast.Scope, stack *ast.Stack) (interface{}, ast.Type,
|
||||||
nodes = append(nodes, stack.Pop().(*ast.LiteralNode))
|
nodes = append(nodes, stack.Pop().(*ast.LiteralNode))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Special case the single list
|
||||||
|
if len(nodes) == 1 && nodes[0].Typex == ast.TypeList {
|
||||||
|
return nodes[0].Value, ast.TypeList, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise concatenate the strings
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
for i := len(nodes) - 1; i >= 0; i-- {
|
for i := len(nodes) - 1; i >= 0; i-- {
|
||||||
buf.WriteString(nodes[i].Value.(string))
|
buf.WriteString(nodes[i].Value.(string))
|
||||||
|
|
|
@ -55,7 +55,7 @@ var parserStatenames = [...]string{}
|
||||||
|
|
||||||
const parserEofCode = 1
|
const parserEofCode = 1
|
||||||
const parserErrCode = 2
|
const parserErrCode = 2
|
||||||
const parserMaxDepth = 200
|
const parserInitialStackSize = 16
|
||||||
|
|
||||||
//line lang.y:196
|
//line lang.y:196
|
||||||
|
|
||||||
|
@ -157,18 +157,17 @@ type parserParser interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
type parserParserImpl struct {
|
type parserParserImpl struct {
|
||||||
lookahead func() int
|
lval parserSymType
|
||||||
|
stack [parserInitialStackSize]parserSymType
|
||||||
|
char int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *parserParserImpl) Lookahead() int {
|
func (p *parserParserImpl) Lookahead() int {
|
||||||
return p.lookahead()
|
return p.char
|
||||||
}
|
}
|
||||||
|
|
||||||
func parserNewParser() parserParser {
|
func parserNewParser() parserParser {
|
||||||
p := &parserParserImpl{
|
return &parserParserImpl{}
|
||||||
lookahead: func() int { return -1 },
|
|
||||||
}
|
|
||||||
return p
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const parserFlag = -1000
|
const parserFlag = -1000
|
||||||
|
@ -296,22 +295,20 @@ func parserParse(parserlex parserLexer) int {
|
||||||
|
|
||||||
func (parserrcvr *parserParserImpl) Parse(parserlex parserLexer) int {
|
func (parserrcvr *parserParserImpl) Parse(parserlex parserLexer) int {
|
||||||
var parsern int
|
var parsern int
|
||||||
var parserlval parserSymType
|
|
||||||
var parserVAL parserSymType
|
var parserVAL parserSymType
|
||||||
var parserDollar []parserSymType
|
var parserDollar []parserSymType
|
||||||
_ = parserDollar // silence set and not used
|
_ = parserDollar // silence set and not used
|
||||||
parserS := make([]parserSymType, parserMaxDepth)
|
parserS := parserrcvr.stack[:]
|
||||||
|
|
||||||
Nerrs := 0 /* number of errors */
|
Nerrs := 0 /* number of errors */
|
||||||
Errflag := 0 /* error recovery flag */
|
Errflag := 0 /* error recovery flag */
|
||||||
parserstate := 0
|
parserstate := 0
|
||||||
parserchar := -1
|
parserrcvr.char = -1
|
||||||
parsertoken := -1 // parserchar translated into internal numbering
|
parsertoken := -1 // parserrcvr.char translated into internal numbering
|
||||||
parserrcvr.lookahead = func() int { return parserchar }
|
|
||||||
defer func() {
|
defer func() {
|
||||||
// Make sure we report no lookahead when not parsing.
|
// Make sure we report no lookahead when not parsing.
|
||||||
parserstate = -1
|
parserstate = -1
|
||||||
parserchar = -1
|
parserrcvr.char = -1
|
||||||
parsertoken = -1
|
parsertoken = -1
|
||||||
}()
|
}()
|
||||||
parserp := -1
|
parserp := -1
|
||||||
|
@ -343,8 +340,8 @@ parsernewstate:
|
||||||
if parsern <= parserFlag {
|
if parsern <= parserFlag {
|
||||||
goto parserdefault /* simple state */
|
goto parserdefault /* simple state */
|
||||||
}
|
}
|
||||||
if parserchar < 0 {
|
if parserrcvr.char < 0 {
|
||||||
parserchar, parsertoken = parserlex1(parserlex, &parserlval)
|
parserrcvr.char, parsertoken = parserlex1(parserlex, &parserrcvr.lval)
|
||||||
}
|
}
|
||||||
parsern += parsertoken
|
parsern += parsertoken
|
||||||
if parsern < 0 || parsern >= parserLast {
|
if parsern < 0 || parsern >= parserLast {
|
||||||
|
@ -352,9 +349,9 @@ parsernewstate:
|
||||||
}
|
}
|
||||||
parsern = parserAct[parsern]
|
parsern = parserAct[parsern]
|
||||||
if parserChk[parsern] == parsertoken { /* valid shift */
|
if parserChk[parsern] == parsertoken { /* valid shift */
|
||||||
parserchar = -1
|
parserrcvr.char = -1
|
||||||
parsertoken = -1
|
parsertoken = -1
|
||||||
parserVAL = parserlval
|
parserVAL = parserrcvr.lval
|
||||||
parserstate = parsern
|
parserstate = parsern
|
||||||
if Errflag > 0 {
|
if Errflag > 0 {
|
||||||
Errflag--
|
Errflag--
|
||||||
|
@ -366,8 +363,8 @@ parserdefault:
|
||||||
/* default state action */
|
/* default state action */
|
||||||
parsern = parserDef[parserstate]
|
parsern = parserDef[parserstate]
|
||||||
if parsern == -2 {
|
if parsern == -2 {
|
||||||
if parserchar < 0 {
|
if parserrcvr.char < 0 {
|
||||||
parserchar, parsertoken = parserlex1(parserlex, &parserlval)
|
parserrcvr.char, parsertoken = parserlex1(parserlex, &parserrcvr.lval)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* look through exception table */
|
/* look through exception table */
|
||||||
|
@ -430,7 +427,7 @@ parserdefault:
|
||||||
if parsertoken == parserEofCode {
|
if parsertoken == parserEofCode {
|
||||||
goto ret1
|
goto ret1
|
||||||
}
|
}
|
||||||
parserchar = -1
|
parserrcvr.char = -1
|
||||||
parsertoken = -1
|
parsertoken = -1
|
||||||
goto parsernewstate /* try again in the same state */
|
goto parsernewstate /* try again in the same state */
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue