diff --git a/pkg/engine/runtimev2/utils.go b/pkg/engine/runtimev2/utils.go new file mode 100644 index 0000000..28e4234 --- /dev/null +++ b/pkg/engine/runtimev2/utils.go @@ -0,0 +1 @@ +package runtimev2 diff --git a/pkg/engine/vm/insn.go b/pkg/engine/vm/insn.go new file mode 100644 index 0000000..fae1dd3 --- /dev/null +++ b/pkg/engine/vm/insn.go @@ -0,0 +1,39 @@ +package vm + +type OPCode int + +const ( + OP_NOP OPCode = iota + + OP_ST + OP_LD + + OP_ADD + OP_SUB + OP_MUL + OP_DIV + OP_MOD + OP_UNM // unary minus + + OP_AND + OP_OR + OP_NOT + + OP_EQ + OP_NEQ + OP_LT + OP_LTE + OP_GT + OP_GTE + OP_LEN + + OP_GET + OP_SET + OP_APPEND + + OP_JMP + OP_JMP_IF + + OP_CALL + OP_RET +) diff --git a/pkg/engine/vm/utils.go b/pkg/engine/vm/utils.go new file mode 100644 index 0000000..830a8f6 --- /dev/null +++ b/pkg/engine/vm/utils.go @@ -0,0 +1 @@ +package vm diff --git a/pkg/v2/ast/ast.go b/pkg/v2/ast/ast.go new file mode 100644 index 0000000..c848fe3 --- /dev/null +++ b/pkg/v2/ast/ast.go @@ -0,0 +1,46 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the MIT License. +// This product includes software developed at Guance Cloud (https://www.guance.com/). +// Copyright 2021-present Guance, Inc. + +// Package ast pipeline ast node +package ast + +import ( + "fmt" + "sort" + "strings" +) + +type Stmts []Node + +type KwArgs map[string]Node + +type FuncArgList []Node + +func (e KwArgs) String() string { + keys := []string{} + for k := range e { + keys = append(keys, k) + } + sort.Strings(keys) + + arr := []string{} + for _, key := range keys { + arr = append(arr, fmt.Sprintf("%s = %s", key, e[key])) + } + return strings.Join(arr, ", ") +} + +func (e Stmts) String() string { + arr := []string{} + for i, x := range e { + arr = append(arr, x.String()) + _ = i + } + return strings.Join(arr, "\n") +} + +type Node interface { + String() string +} diff --git a/pkg/v2/ast/dtype.go b/pkg/v2/ast/dtype.go new file mode 100644 index 0000000..7f37569 --- /dev/null +++ b/pkg/v2/ast/dtype.go @@ -0,0 +1,185 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the MIT License. +// This product includes software developed at Guance Cloud (https://www.guance.com/). +// Copyright 2021-present Guance, Inc. + +package ast + +import ( + "bytes" + + "github.com/GuanceCloud/platypus/pkg/token" +) + +type DType uint + +func (t DType) String() string { + switch t { + case Invalid: + return "invalid" + case Bool: + return "bool" + case Int: + return "int" + case Float: + return "float" + case String: + return "str" + case List: + return "list" + case Map: + return "map" + case Func: + return "func" + case Class: + return "class" + } + return "" +} + +const ( + Invalid DType = iota + + Any // any + + Bool + Int // int64 + Float // float64 + String // string + + List + Map + + Class + + Func +) + +func AllTyp() []DType { + return []DType{Bool, Int, Float, String, List, Map, Class, Func} +} + +type TypeNode interface { + IsType() + String() string +} + +type TypeID struct { + Name Node +} + +func (*TypeID) IsType() {} +func (t *TypeID) String() string { + return t.Name.String() +} + +type FnParam struct { + Name Node + DType Node + Varb bool + DefaultVal Node +} + +func (p *FnParam) String() string { + s := p.Name.String() + if p.DType != nil { + if p.Varb { + s += ": ..." + p.DType.String() + } else { + s += ": " + p.DType.String() + } + } else if p.Varb { + s += ": ..." + } + if p.DefaultVal != nil { + s += " = " + p.DefaultVal.String() + } + return s +} + +type TypeAny struct{} + +func (*TypeAny) IsType() {} + +func (t *TypeAny) String() string { + return "any" +} + +type TypeFn struct { + Params []FnParam + Results []Node +} + +func (*TypeFn) IsType() {} + +func (t *TypeFn) String() string { + return "fn " + t.string() +} + +func (t *TypeFn) string() string { + b := bytes.NewBuffer([]byte{}) + b.WriteString("(") + for i, p := range t.Params { + b.WriteString(p.String()) + if i < len(t.Params)-1 { + b.WriteString(", ") + } + } + b.WriteString(")") + if len(t.Results) > 0 { + b.WriteString(" -> ") + } + + if len(t.Results) > 1 { + b.WriteString("(") + } + for i, r := range t.Results { + b.WriteString(r.String()) + if i < len(t.Results)-1 { + b.WriteString(", ") + } + } + if len(t.Results) > 1 { + b.WriteString(")") + } + + return b.String() +} + +type TypeClass struct { + Fields []Node + Methods []Node +} + +func (*TypeClass) IsType() {} + +type TypeMap struct { + KeyType Node + ValueType Node +} + +func (t *TypeMap) String() string { + return "map" +} +func (*TypeMap) IsType() {} + +type TypeList struct { + VType Node +} + +func (t *TypeList) String() string { + return "list" +} + +func (*TypeList) IsType() {} + +type TypeBasic struct { + Pos token.LnColPos + DType DType +} + +func (*TypeBasic) IsType() {} + +func (t *TypeBasic) String() string { + return t.DType.String() +} diff --git a/pkg/v2/ast/expr.go b/pkg/v2/ast/expr.go new file mode 100644 index 0000000..a44d596 --- /dev/null +++ b/pkg/v2/ast/expr.go @@ -0,0 +1,375 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the MIT License. +// This product includes software developed at Guance Cloud (https://www.guance.com/). +// Copyright 2021-present Guance, Inc. + +package ast + +import ( + "fmt" + "regexp" + "strings" + + "github.com/GuanceCloud/grok" + "github.com/GuanceCloud/platypus/pkg/token" +) + +type Op string + +const ( + ADD Op = "+" + SUB Op = "-" + MUL Op = "*" + DIV Op = "/" + MOD Op = "%" + + // XOR Op = "^" + // ~~~ POW Op = "^" ~~~. + + EQEQ Op = "==" + NEQ Op = "!=" + LTE Op = "<=" + LT Op = "<" + GTE Op = ">=" + GT Op = ">" + + AND Op = "&&" + OR Op = "||" + NOT Op = "!" + + EQ Op = "=" + ADDEQ Op = "+=" + SUBEQ Op = "-=" + MULEQ Op = "*=" + DIVEQ Op = "/=" + MODEQ Op = "%=" + + IN Op = "in" +) + +type Identifier struct { + Name string + Start token.LnColPos +} + +func (e *Identifier) IsExpr() bool { + return true +} + +func (e *Identifier) String() string { + return e.Name +} + +type StringLiteral struct { + Val string + Start token.LnColPos +} + +func (e *StringLiteral) IsExpr() bool { + return true +} + +func (e *StringLiteral) String() string { + return fmt.Sprintf("'%s'", e.Val) +} + +// type NumberLiteral struct { +// IsInt bool +// Float float64 +// Int int64 +// Start token.FilePos +// End token.FilePos +// } + +type IntegerLiteral struct { + Val int64 + Start token.LnColPos +} + +func (e *IntegerLiteral) String() string { + return fmt.Sprintf("%d", e.Val) +} + +func (e *IntegerLiteral) IsExpr() bool { + return true +} + +type FloatLiteral struct { + Val float64 + Start token.LnColPos +} + +func (e *FloatLiteral) String() string { + return fmt.Sprintf("%f", e.Val) +} + +func (e *FloatLiteral) IsExpr() bool { + return true +} + +type BoolLiteral struct { + Val bool + Start token.LnColPos +} + +func (e *BoolLiteral) String() string { + return fmt.Sprintf("%v", e.Val) +} + +type NilLiteral struct { + Start token.LnColPos +} + +func (e *NilLiteral) IsExpr() bool { + return true +} + +func (e *NilLiteral) String() string { + return "nil" +} + +type DataType struct { + Identifier Node +} + +type composeLiteral struct { +} + +type MapLiteral struct { + KeyValeList [][2]Node // key,value list + LBrace token.LnColPos + RBrace token.LnColPos +} + +func (e *MapLiteral) IsExpr() bool { + return true +} + +func (e *MapLiteral) String() string { + v := "{" + for i, item := range e.KeyValeList { + if i == 0 { + v += item[0].String() + ": " + item[1].String() + } else { + v += ", " + item[0].String() + ": " + item[1].String() + } + } + return v + "}" +} + +type ListLiteral struct { + List []Node + LBracket token.LnColPos + RBracket token.LnColPos +} + +func (e *ListLiteral) IsExpr() bool { + return true +} + +func (e *ListLiteral) String() string { + arr := []string{} + for _, x := range e.List { + arr = append(arr, x.String()) + } + return "[" + strings.Join(arr, ", ") + "]" +} + +type UnaryExpr struct { + Op Op + RHS Node + OpPos token.LnColPos +} + +func (e *UnaryExpr) IsExpr() bool { + return true +} + +func (e *UnaryExpr) String() string { + return fmt.Sprintf("%s%s", e.Op, e.RHS.String()) +} + +type ConditionalExpr struct { + Op Op + LHS, RHS Node + OpPos token.LnColPos +} + +func (e *ConditionalExpr) IsExpr() bool { + return true +} + +func (e *ConditionalExpr) String() string { + return fmt.Sprintf("%s %s %s", e.LHS.String(), e.Op, e.RHS.String()) +} + +type InExpr struct { + Op Op + LHS, RHS Node + OpPos token.LnColPos +} + +func (e *InExpr) IsExpr() bool { + return true +} + +func (e *InExpr) String() string { + return fmt.Sprintf("%s %s %s", e.LHS.String(), e.Op, e.RHS.String()) +} + +type ArithmeticExpr struct { + Op Op + LHS, RHS Node + OpPos token.LnColPos +} + +func (e *ArithmeticExpr) IsExpr() bool { + return true +} + +func (e *ArithmeticExpr) String() string { + return fmt.Sprintf("%s %s %s", e.LHS.String(), e.Op, e.RHS.String()) +} + +type AttrExpr struct { + Obj Node + Attr Node + Start token.LnColPos +} + +func (e *AttrExpr) IsExpr() bool { + return true +} + +func (e *AttrExpr) String() string { + if e.Attr != nil { + if e.Obj == nil { + return e.Attr.String() + } + return e.Obj.String() + "." + e.Attr.String() + } else { + return e.Obj.String() + } +} + +type IndexExpr struct { + Obj Node + Index Node + + Dot token.LnColPos + LBracket token.LnColPos + RBracket token.LnColPos +} + +func (e *IndexExpr) IsExpr() bool { + return true +} + +func (e *IndexExpr) String() string { + x := "" + if e.Obj != nil { + x = e.Obj.String() + } else { + x = "." + } + x += fmt.Sprintf("[%s]", e.Index.String()) + return x +} + +type ParenExpr struct { + Param Node + LParen token.LnColPos + RParen token.LnColPos +} + +func (e *ParenExpr) IsExpr() bool { + return true +} + +func (e *ParenExpr) String() string { + return fmt.Sprintf("(%s)", e.Param.String()) +} + +type CallExpr struct { + LParen token.LnColPos + RParen token.LnColPos + + Obj Node + + Param []Node + ParamNormalized []Node + + PrivateData interface{} + + Grok *grok.GrokRegexp + Re *regexp.Regexp +} + +func (e *CallExpr) IsExpr() bool { + return true +} + +func (e *CallExpr) String() string { + arr := []string{} + for _, n := range e.Param { + arr = append(arr, n.String()) + } + return fmt.Sprintf("%s(%s)", strings.ToLower(e.Obj.String()), strings.Join(arr, ", ")) +} + +type SliceExpr struct { + Obj Node + + Start Node + End Node + Step Node + + LBracket token.LnColPos + RBracket token.LnColPos +} + +func (e *SliceExpr) IsExpr() bool { + return true +} + +func (e *SliceExpr) String() string { + var startStr, endStr, stepStr string + if e.Start != nil { + startStr = e.Start.String() + } + if e.End != nil { + endStr = e.End.String() + } + if e.Step != nil { + stepStr = ":" + e.Step.String() + } + + return fmt.Sprintf("%s[%s:%s%s]", e.Obj.String(), startStr, endStr, stepStr) +} + +type AssignmentStmt struct { + LHS, RHS []Node + Op Op + OpPos token.LnColPos +} + +func (e *AssignmentStmt) IsExpr() bool { + return true +} + +func (e *AssignmentStmt) String() string { + var l []string + for _, lhs := range e.LHS { + l = append(l, lhs.String()) + } + var r []string + for _, rhs := range e.RHS { + r = append(r, rhs.String()) + } + + return fmt.Sprintf("%s %s %s", + strings.Join(l, ", "), + e.Op, + strings.Join(r, ", "), + ) +} diff --git a/pkg/v2/ast/misc.go b/pkg/v2/ast/misc.go new file mode 100644 index 0000000..9f69942 --- /dev/null +++ b/pkg/v2/ast/misc.go @@ -0,0 +1,17 @@ +package ast + +type CommaExpr struct { + List []*Node +} + +func (e *CommaExpr) Append(n *Node) { + e.List = append(e.List, n) +} + +type FnCallParams struct { + List []*Node +} + +func (c *FnCallParams) Append(n *Node) { + c.List = append(c.List, n) +} diff --git a/pkg/v2/ast/stmt.go b/pkg/v2/ast/stmt.go new file mode 100644 index 0000000..fc415e0 --- /dev/null +++ b/pkg/v2/ast/stmt.go @@ -0,0 +1,222 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the MIT License. +// This product includes software developed at Guance Cloud (https://www.guance.com/). +// Copyright 2021-present Guance, Inc. + +package ast + +import ( + "strings" + + "github.com/GuanceCloud/platypus/pkg/token" +) + +type IfelseStmt struct { + IfList IfList + Else *BlockStmt + + Label int + + ElsePos token.LnColPos +} + +func (e *IfelseStmt) IsExpr() bool { + return false +} + +func (e *IfelseStmt) String() string { + arr := []string{e.IfList.String()} + if e.Else != nil && len(e.Else.Stmts) != 0 { + arr = append(arr, "else", "{", e.Else.String(), "}") + } + return strings.Join(arr, " ") +} + +// IfList index [0] is IF, [1..end] is ELIF. +type IfList []*IfStmtElem + +func (e IfList) String() string { + if len(e) == 0 { + return "" + } + arr := []string{"if", e[0].String()} + for i := 1; i < len(e); i++ { + arr = append(arr, "elif", e[i].String()) + } + return strings.Join(arr, " ") +} + +type IfStmtElem struct { + Condition Node + Block *BlockStmt + + Start token.LnColPos +} + +func (e *IfStmtElem) String() string { + arr := []string{e.Condition.String(), "{", e.Block.String(), "}"} + return strings.Join(arr, " ") +} + +type BreakStmt struct { + Start token.LnColPos +} + +func (e *BreakStmt) String() string { + return "break" +} + +type ContinueStmt struct { + Start token.LnColPos +} + +func (e *ContinueStmt) String() string { + return "continue" +} + +type ForInStmt struct { + InExpr Node + Body *BlockStmt + + Label int + SymTb int + + ForPos token.LnColPos +} + +func (e *ForInStmt) String() string { + return "for in stmt" +} + +type ForStmt struct { + // init + Init Node + + // step1: -> step2 or break + Cond Node + + // step3: -> step1 + Loop Node + + // step2: -> step3 + Body *BlockStmt + + Label int + SymTb int + + ForPos token.LnColPos +} + +func (e *ForStmt) String() string { + return "for stmt" +} + +type BlockStmt struct { + LBracePos token.LnColPos + RBracePos token.LnColPos + + Label int + Table int + + Stmts Stmts +} + +func (block *BlockStmt) String() string { + var arr []string + for _, x := range block.Stmts { + arr = append(arr, x.String()) + } + return strings.Join(arr, "\n") +} + +type ReturnStmt struct { + ReturnPos token.LnColPos + Exprs []Node +} + +func (r *ReturnStmt) String() string { + var params []string + for _, x := range r.Exprs { + params = append(params, x.String()) + } + if len(params) > 0 { + return "return " + strings.Join(params, ", ") + } + return "return" +} + +type FnDefStmt struct { + FnPos token.LnColPos + LParen, RParen token.LnColPos + + RetPos token.LnColPos + RetLParen, RetRParen token.LnColPos + + Name Node + + Label int + Table int + + FnType *TypeFn + + Block *BlockStmt +} + +func (f *FnDefStmt) String() string { + s := f.Block.String() + if len(s) > 0 { + return "fn " + f.FnType.string() + "{\n" + s + "\n}" + } else { + return "fn " + f.FnType.string() + "{\n}" + } +} + +type LetStmt struct { + LetPos token.LnColPos + Name *Identifier + Type Node + Value Node +} + +func (v *LetStmt) String() string { + s := "let " + v.Name.String() + if v.Type != nil { + s += ": " + v.Type.String() + " " + } + if v.Value != nil { + s += "= " + v.Value.String() + } + return s +} + +type ConstDefStmt struct { + ConstPos token.LnColPos + Name Node + Value Node +} + +func (c *ConstDefStmt) String() string { + return "const " + c.Name.String() + " = " + c.Value.String() +} + +type ImportStmt struct { + ImportPos token.LnColPos + AsPos token.LnColPos + + Name []*Identifier + AsName *Identifier +} + +func (i *ImportStmt) String() string { + var pkgNames []string + for _, x := range i.Name { + pkgNames = append(pkgNames, x.String()) + } + + s := "import " + strings.Join(pkgNames, ", ") + if i.AsName != nil { + s += " as " + i.AsName.String() + } + + return s +} diff --git a/pkg/v2/ast/x_test.go b/pkg/v2/ast/x_test.go new file mode 100644 index 0000000..cc7c9e3 --- /dev/null +++ b/pkg/v2/ast/x_test.go @@ -0,0 +1,11 @@ +package ast + +import "testing" + +func TestXxx(t *testing.T) { + var b, ax int + ax, (b) = 1, 1 + t.Log(ax) + _ = b + _ = ax +} diff --git a/pkg/v2/compile/compile.go b/pkg/v2/compile/compile.go new file mode 100644 index 0000000..f5b1ff7 --- /dev/null +++ b/pkg/v2/compile/compile.go @@ -0,0 +1,34 @@ +package compile + +import ( + "github.com/GuanceCloud/platypus/pkg/v2/ast" + "github.com/GuanceCloud/platypus/pkg/v2/ir" +) + +type Insns struct { + Insns []*ir.Insn +} + +func NewInsns() *Insns { + return &Insns{ + Insns: make([]*ir.Insn, 0), + } +} + +func Compile(stmts []ast.Node) *Insns { + ins := NewInsns() + + for _, node := range stmts { + switch n := node.(type) { + case *ast.LetStmt: + _ = n + } + + } + + return ins +} + +func (insns *Insns) CompileIfStmt(stmt *ast.IfelseStmt) { + +} diff --git a/pkg/v2/compile/compile_test.go b/pkg/v2/compile/compile_test.go new file mode 100644 index 0000000..af4b81c --- /dev/null +++ b/pkg/v2/compile/compile_test.go @@ -0,0 +1,34 @@ +package compile + +import ( + "testing" + + "github.com/GuanceCloud/platypus/pkg/v2/parser" +) + +const ( + sp = ` +let a = 2 +fn abc(a: int, b: float, c: ...) -> (bool, str) { + return 1, "" +} +let abcd: any = 2 + +abc(a, x) + +` +) + +func TestCompile(t *testing.T) { + stmts, err := parser.ParsePipeline("main.p", sp) + if err != nil { + t.Error(err) + } + ctx := NewContext() + err = BuildSyms(ctx, stmts) + if err != nil { + t.Error(err) + } + + t.Log(ctx) +} diff --git a/pkg/v2/compile/pre.go b/pkg/v2/compile/pre.go new file mode 100644 index 0000000..2aafc34 --- /dev/null +++ b/pkg/v2/compile/pre.go @@ -0,0 +1,281 @@ +package compile + +import ( + "fmt" + + "github.com/GuanceCloud/platypus/pkg/v2/ast" + "github.com/GuanceCloud/platypus/pkg/v2/sym" +) + +func BuildSyms(ctx *CContext, stmts ast.Stmts) error { + for _, stmt := range stmts { + if err := LStmt(ctx, stmt); err != nil { + return err + } + } + + return nil +} + +func LStmt(ctx *CContext, node ast.Node) error { + switch v := node.(type) { + case *ast.AssignmentStmt: + return LAssign(ctx, v) + case *ast.LetStmt: + return LLetDef(ctx, v) + case *ast.FnDefStmt: + return LFuncDefStmt(ctx, v) + case *ast.IfelseStmt: + return LIf(ctx, v) + case *ast.ForInStmt: + case *ast.ForStmt: + return LFor(ctx, v) + case *ast.BlockStmt: + return LBlock(ctx, v) + case *ast.ParenExpr: + return LStmt(ctx, v.Param) + default: + } + + return nil +} + +func LLetDef(ctx *CContext, stmt *ast.LetStmt) error { + name := stmt.Name.Name + _, ok := ctx.Tb.GetCur(name) + if ok { + return fmt.Errorf("sym exists") + } + + var tp sym.Type = &sym.TypAny{} + + if stmt.Type != nil { + switch v := stmt.Type.(type) { + case *ast.TypeMap: + tp = &sym.TypMap{ + Key: &sym.TypString{}, + Value: &sym.TypAny{}, + } + case *ast.TypeList: + tp = &sym.TypList{ + Elem: &sym.TypAny{}, + } + case *ast.TypeBasic: + switch v.DType { + case ast.Int: + tp = sym.Int + case ast.Float: + tp = sym.Float + case ast.Bool: + tp = sym.Bool + case ast.String: + tp = sym.Str + case ast.Any: + tp = sym.Any + } + case *ast.TypeAny: + tp = sym.Any + default: + return fmt.Errorf("unsuppored type") + } + } else { + tp = sym.Any + } + + if !ctx.Tb.Define(name, &sym.Sym{ + Name: name, + Type: tp, + }) { + return fmt.Errorf("sym exists") + } + + return nil +} + +func LBlock(ctx *CContext, stmt *ast.BlockStmt) error { + ctx = NewChildContext(ctx) + stmt.Label = ctx.Lb.Insert() + stmt.Table = ctx.Tb.ScopeID() + + return BuildSyms(ctx, stmt.Stmts) +} + +func LAssign(ctx *CContext, stmt *ast.AssignmentStmt) error { + + lhs := stmt.LHS + rhs := stmt.RHS + + for i := range rhs { + if err := LStmt(ctx, rhs[i]); err != nil { + return err + } + } + + for i := range lhs { + node := getNode(lhs[i]) + switch node := node.(type) { + case *ast.Identifier: + name := node.Name + if _, ok := ctx.Tb.GetCur(name); !ok { + ctx.Tb.Define(name, &sym.Sym{ + Name: name, + Type: &sym.TypAny{}, + }) + } + case *ast.IndexExpr: + if err := LStmt(ctx, rhs[i]); err != nil { + return err + } + case *ast.AttrExpr: + if err := LStmt(ctx, rhs[i]); err != nil { + return err + } + default: + return fmt.Errorf("unsuppored lhs type") + } + } + + return nil +} + +func LIf(ctx *CContext, stmt *ast.IfelseStmt) error { + for _, v := range stmt.IfList { + if err := LStmt(ctx, v.Block); err != nil { + return err + } + } + + if stmt.Else != nil { + if err := LStmt(ctx, stmt.Else); err != nil { + return err + } + } + + return nil +} + +func LForIn(ctx *CContext, stmt *ast.ForInStmt) error { + ctx = NewChildContext(ctx) + stmt.SymTb = ctx.Tb.ScopeID() + stmt.Label = ctx.Lb.Insert() + + inExpr := stmt.InExpr + if v, ok := inExpr.(*ast.InExpr); ok { + if lhs, ok := v.LHS.(*ast.Identifier); ok { + ctx.Tb.Define(lhs.Name, &sym.Sym{ + Name: lhs.Name, + Type: &sym.TypAny{}, + }) + } + } else { + return fmt.Errorf("not in expr") + } + + newCtx := NewChildContext(ctx) + if stmt.Body != nil { + if err := LStmt(newCtx, stmt.Body); err != nil { + return err + } + } + + return nil +} + +func LFor(ctx *CContext, stmt *ast.ForStmt) error { + ctx = NewChildContext(ctx) + stmt.SymTb = ctx.Tb.ScopeID() + stmt.Label = ctx.Lb.Insert() + + if err := LStmt(ctx, stmt.Init); err != nil { + return err + } + if err := LStmt(ctx, stmt.Cond); err != nil { + return err + } + + if err := LStmt(ctx, stmt.Body); err != nil { + return err + } + + return nil +} + +func LFuncDefStmt(ctx *CContext, stmt *ast.FnDefStmt) error { + nameNode, ok := getNode(stmt.Name).(*ast.Identifier) + if !ok { + return fmt.Errorf("unsuppored node type") + } + + name := nameNode.String() + + fn := sym.TypFunc{} + + newCtx := NewChildContext(ctx) + stmt.Label = ctx.Lb.Insert() + stmt.Table = ctx.Tb.ScopeID() + for _, v := range stmt.FnType.Params { + p := &sym.Param{} + if v.DType != nil { + typ, err := getType(getNode(v.DType)) + if err != nil { + return err + } + p.Type = typ + } else { + p.Type = sym.Any + } + p.IsVarb = v.Varb + fn.Params = append(fn.Params, p) + if name, ok := v.Name.(*ast.Identifier); ok { + newCtx.Tb.Define(name.String(), &sym.Sym{ + Name: name.String(), + Type: p.Type, + }) + } else { + return fmt.Errorf("unsupported node type") + } + } + + for _, v := range stmt.FnType.Results { + typ, err := getType(getNode(v)) + if err != nil { + return err + } + fn.Returns = append(fn.Returns, typ) + } + + ctx.Tb.Define(name, &sym.Sym{ + Name: name, + Type: fn, + }) + + return LStmt(newCtx, stmt.Block) +} + +func getType(node ast.Node) (sym.Type, error) { + switch v := node.(type) { + case *ast.TypeBasic: + switch v.DType { + case ast.Any: + return sym.Any, nil + case ast.Int: + return sym.Int, nil + case ast.Bool: + return sym.Bool, nil + case ast.Float: + return sym.Float, nil + case ast.String: + return sym.Str, nil + default: + return nil, fmt.Errorf("unsupported type") + } + case *ast.TypeList: + return sym.NewListTyp(sym.Any), nil + case *ast.TypeMap: + return sym.NewMapTyp(), nil + case *ast.TypeAny: + return sym.Any, nil + default: + return nil, fmt.Errorf("unsupported type") + } +} diff --git a/pkg/v2/compile/utils.go b/pkg/v2/compile/utils.go new file mode 100644 index 0000000..91a592d --- /dev/null +++ b/pkg/v2/compile/utils.go @@ -0,0 +1,48 @@ +package compile + +import ( + "github.com/GuanceCloud/platypus/pkg/v2/ast" + "github.com/GuanceCloud/platypus/pkg/v2/sym" +) + +func getNode(node ast.Node) ast.Node { + if v, ok := node.(*ast.ParenExpr); ok { + return getNode(v.Param) + } + return node +} + +type CContext struct { + Tb *sym.Tables + Lb *Labels +} + +type Labels struct { + Pos int + Lb map[int]any +} + +func (lb *Labels) Insert() int { + lb.Pos++ + return lb.Pos +} + +func NewLBs() *Labels { + return &Labels{ + Lb: map[int]any{}, + } +} + +func NewContext() *CContext { + return &CContext{ + Tb: sym.NewTabels(), + Lb: NewLBs(), + } +} + +func NewChildContext(ctx *CContext) *CContext { + return &CContext{ + Tb: ctx.Tb.NextScope(), + Lb: ctx.Lb, + } +} diff --git a/pkg/v2/ir/insn.go b/pkg/v2/ir/insn.go new file mode 100644 index 0000000..6980309 --- /dev/null +++ b/pkg/v2/ir/insn.go @@ -0,0 +1,73 @@ +package ir + +import "github.com/GuanceCloud/platypus/pkg/ast" + +type DebugInfo struct{} + +type OP uint8 + +func (op OP) String() string { + return "" +} + +const ( + OP_NOP OP = iota + OP_ADD // + + OP_SUB // - + OP_MUL // * + OP_DIV // / + OP_MOD // % + OP_EQEQ // == + OP_NE // != + OP_LT // < + OP_LE // <= + OP_GT // > + OP_GE // >= + OP_AND // && + OP_OR // || + OP_NOT // ! + OP_NEG // - + OP_ASSIGN // = + OP_APPEND // append + OP_LEN // len + OP_IGET // index_get + OP_ISET // index_set + OP_CALL // call + OP_RET // ret + OP_JMP // jmp + + OP_LOAD // load + OP_STORE // store + + OP_LOADG // load global + OP_STOREG // store global +) + +type Insn struct { + Op OP + Args Args +} + +type Args struct { + Arg1 *Value + Arg2 *Value + Arg3 *Value +} + +type Value struct { + Val any + DType ast.DType +} + +func (v *Value) Value() any { + return v.Val +} + +func (v *Value) Set(val any, typ ast.DType) { + v.Val = val + v.DType = typ +} + +func (v *Value) Type() ast.DType { + return v.DType +} diff --git a/pkg/v2/ir/ir.go b/pkg/v2/ir/ir.go new file mode 100644 index 0000000..0d58835 --- /dev/null +++ b/pkg/v2/ir/ir.go @@ -0,0 +1 @@ +package ir diff --git a/pkg/v2/parser/Makefile b/pkg/v2/parser/Makefile new file mode 100644 index 0000000..8f836f4 --- /dev/null +++ b/pkg/v2/parser/Makefile @@ -0,0 +1,2 @@ +all: + goyacc -o gram_y.go gram.y diff --git a/pkg/v2/parser/errs.go b/pkg/v2/parser/errs.go new file mode 100644 index 0000000..d8bf55b --- /dev/null +++ b/pkg/v2/parser/errs.go @@ -0,0 +1,49 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the MIT License. +// This product includes software developed at Guance Cloud (https://www.guance.com/). +// Copyright 2021-present Guance, Inc. + +package parser + +import ( + "fmt" + "strings" + + "github.com/GuanceCloud/platypus/pkg/token" +) + +type ParseErrors []ParseError + +type ParseError struct { + Pos *PositionRange + Err error + Query string +} + +func (e *ParseError) Error() string { + if e.Pos == nil { + return fmt.Sprintf("%s", e.Err) + } + + var posStr string + if ln, col, err := token.LnCol(e.Query, e.Pos.Start); err != nil { + posStr = err.Error() + } else { + posStr = fmt.Sprintf("%d:%d", ln, col) + } + + return fmt.Sprintf("%s parse error: %s", posStr, e.Err) +} + +// Error impl Error() interface. +func (errs ParseErrors) Error() string { + var errArray []string + for _, err := range errs { + errStr := err.Error() + if errStr != "" { + errArray = append(errArray, errStr) + } + } + + return strings.Join(errArray, "\n") +} diff --git a/pkg/v2/parser/gram.y b/pkg/v2/parser/gram.y new file mode 100644 index 0000000..1f8d558 --- /dev/null +++ b/pkg/v2/parser/gram.y @@ -0,0 +1,839 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the MIT License. +// This product includes software developed at Guance Cloud (https://www.guance.com/). +// Copyright 2021-present Guance, Inc. + +%{ +package parser + +import ( + ast "github.com/GuanceCloud/platypus/pkg/v2/ast" +) + +%} + +%union { + aststmts ast.Stmts + astblock *ast.BlockStmt + + classbody any + + ifitem *ast.IfStmtElem + iflist []*ast.IfStmtElem + node ast.Node + nodes []ast.Node + map_nodes [][2]ast.Node + item Item + + fnparam ast.FnParam + fnparams []ast.FnParam +} + +%token SEMICOLON COMMA COMMENT EOF ERROR ID NUMBER + LEFT_PAREN LEFT_BRACKET LEFT_BRACE RIGHT_BRACE + RIGHT_PAREN RIGHT_BRACKET STRING QUOTED_STRING MULTILINE_STRING + COLON EOL + +// operator +%token operatorsStart +%token + ADD SUB MUL DIV MOD + EQ + GTE GT LT LTE NEQ EQEQ + ADD_EQ SUB_EQ DIV_EQ MUL_EQ MOD_EQ + AND OR NOT + DOT +%token operatorsEnd + +// keywords +%token keywordsStart +%token +TRUE FALSE CLASS +NIL NULL IF ELIF ELSE +STR INT FLOAT BOOL LIST MAP ANY +FOR IN WHILE BREAK CONTINUE RETURN SWITCH CASE GOTO +FN LET VAR VAR_ARG FN_RET IMPORT AS TYPE +NEW MAKE INTERFACE CONST +%token keywordsEnd + +// start symbols for parser +%token startSymbolsStart +%token START_STMTS +%token startSymbolsEnd + +//////////////////////////////////////////////////// +// grammar rules +//////////////////////////////////////////////////// +/* %type + unary_op */ + + +%type + stmt_block + empty_block + + +%type + stmts + stmts_list + +%type + if_elem + elif_elem + +%type + if_elif_list + +%type + function_args + exprs + pkg_name + fn_ret_types_multi + +%type + expr_colon_expr + +%type + stmt + assignment_stmt + for_in_stmt + for_stmt + continue_stmt + break_stmt + ifelse_stmt + call_expr + named_arg + +%type + identifier + unary_expr + conditional_expr + arithmeticExpr + paren_expr + index_expr + attr_expr + in_expr + expr + map_literal + value_stmt + expr_or_empty + list_literal + basic_literal + for_init_elem + for_loop_elem + slice_expr + data_type + let_stmt + const_def_stmt + fn_def_stmt + import_stmt + return_stmt + //columnref + +%type + +%type + fn_def_param + +%type + fn_def_params + +%start start + +// operator listed with increasing precedence +%right EQ SUB_EQ ADD_EQ MUL_EQ DIV_EQ MOD_EQ +%left OR +%left AND +%left IN +%left GTE GT NEQ EQEQ LTE LT +%left ADD SUB +%left MUL DIV MOD +%right NOT UMINUS +%left LEFT_PAREN RIGHT_PAREN DOT LEFT_BRACKET RIGHT_BRACKET +%% + +sep: SEMICOLON +| EOL +| sep SEMICOLON +| sep EOL +; + +sem: SEMICOLON +| sem EOL +| sem SEMICOLON +; + +EOLS: EOL +| EOLS EOL +; + +EOLS_SPACE: EOLS +| +; + +start: START_STMTS stmts +{ + yylex.(*parser).parseResult = $2 +} +| START_STMTS EOLS +{ + yylex.(*parser).parseResult = ast.Stmts{} +} +| START_STMTS EOLS stmts +{ + yylex.(*parser).parseResult = $3 +} +| start EOF +| error +{ + yylex.(*parser).unexpected("", "") +} +; + +/* +stmts and exprs +*/ + +stmts: stmts_list stmt +{ + s := $1 + s = append(s, $2) + $$ = s +} +| stmts_list +| stmt +{ + $$ = ast.Stmts{$1} +} +; + +stmts_list: stmt sep +{ + $$ = ast.Stmts{$1} +} +| sem +{ + $$ = ast.Stmts{} +} +| stmts_list stmt sep +{ + s := $1 + s = append(s, $2) + $$ = s +} +; + +stmt: ifelse_stmt +| for_in_stmt +| for_stmt +| continue_stmt +| break_stmt +| value_stmt +| let_stmt +| const_def_stmt +| fn_def_stmt +| import_stmt +| return_stmt +| assignment_stmt +; + + +value_stmt: expr +; + +/* expression */ +expr: identifier +| basic_literal +| list_literal +| map_literal +| paren_expr +| unary_expr +| conditional_expr +| arithmeticExpr +| attr_expr +| index_expr +| slice_expr +| in_expr +| call_expr +; + + +/* +type +*/ + +data_type: INT +{ + $$ = yylex.(*parser).newBuiltinType($1) +} +| FLOAT +{ + $$ = yylex.(*parser).newBuiltinType($1) +} +| STR +{ + $$ = yylex.(*parser).newBuiltinType($1) +} +| BOOL +{ + $$ = yylex.(*parser).newBuiltinType($1) +} +| ANY +{ + $$ = yylex.(*parser).newBuiltinType($1) +} +; + + +const_def_stmt: CONST identifier EQ expr +{ + $$ = yylex.(*parser).newConstDefStmt($1, $2, $4) +} +; + + +let_stmt: LET identifier COLON data_type EQ expr +{ + $$ = yylex.(*parser).newLetStmt($1, $2, $4, $6) +} +| LET identifier COLON data_type +{ + $$ = yylex.(*parser).newLetStmt($1, $2, $4, nil) +} +| LET identifier +{ + $$ = yylex.(*parser).newLetStmt($1, $2, nil, nil) +} +| LET identifier EQ expr +{ + $$ = yylex.(*parser).newLetStmt($1, $2, nil, nil) +} +; + + +/* +stmt +*/ + + +pkg_name: identifier +{ + $$ = []ast.Node{$1} +} +| pkg_name DOT identifier +{ + $$ = append($$, $3) +} +; + +import_stmt: IMPORT pkg_name +{ + $$ = yylex.(*parser).newImportStmt($1, $2, nil) +} +| IMPORT pkg_name AS identifier +{ + $$ = yylex.(*parser).newImportStmt($1, $2, $4) +} +; + + +fn_def_param: identifier +{ + $$ = yylex.(*parser).newFnParam($1, nil, nil) +} +| identifier COLON data_type +{ + $$ = yylex.(*parser).newFnParam($1, $3, nil) +} +| identifier COLON VAR_ARG data_type +{ + $$ = yylex.(*parser).newFnParam($1, $4, nil, true) +} +| identifier COLON VAR_ARG +{ + $$ = yylex.(*parser).newFnParam($1, nil, nil, true) +} +| identifier EQ expr +{ + $$ = yylex.(*parser).newFnParam($1, nil, $3) +} +| identifier COLON data_type EQ expr +{ + $$ = yylex.(*parser).newFnParam($1, $3, $5) +} +; + + +return_stmt: RETURN +{ + $$ = yylex.(*parser).newReturnStmt($1, nil) +} +| RETURN exprs +{ + $$ = yylex.(*parser).newReturnStmt($1, $2) +} +; + + +fn_def_params: fn_def_param +{ + $$ = []ast.FnParam{$1} +} +| fn_def_params COMMA fn_def_param +{ + $$ = append($$, $3) +} +; + + +fn_ret_types_multi: data_type +{ + $$ = []ast.Node{$1} +} +| fn_ret_types_multi COMMA data_type +{ + $$ = append($$, $3) +} +; + + + +fn_def_stmt: FN identifier LEFT_PAREN RIGHT_PAREN stmt_block +{ + $$ = yylex.(*parser).newFnDefStmt($1, $2, nil, nil, $5) +} +| FN identifier LEFT_PAREN RIGHT_PAREN FN_RET data_type stmt_block +{ + $$ = yylex.(*parser).newFnDefStmt($1, $2, nil, []ast.Node{$6}, $7) +} +| FN identifier LEFT_PAREN RIGHT_PAREN FN_RET LEFT_PAREN fn_ret_types_multi RIGHT_PAREN stmt_block +{ + $$ = yylex.(*parser).newFnDefStmt($1, $2, nil, $7, $9) +} +| FN identifier LEFT_PAREN fn_def_params RIGHT_PAREN stmt_block +{ + $$ = yylex.(*parser).newFnDefStmt($1, $2, $4, nil, $6) +} +| FN identifier LEFT_PAREN fn_def_params RIGHT_PAREN FN_RET data_type stmt_block +{ + $$ = yylex.(*parser).newFnDefStmt($1, $2, $4, []ast.Node{$7}, $8) +} +| FN identifier LEFT_PAREN fn_def_params RIGHT_PAREN FN_RET LEFT_PAREN fn_ret_types_multi RIGHT_PAREN stmt_block +{ + $$ = yylex.(*parser).newFnDefStmt($1, $2, $4, $8, $10) +} +; + +exprs: expr +{ + $$ = []ast.Node{$1} +} +| exprs COMMA expr +{ + $$ = append($1, $3) +} +; + + +assignment_stmt: exprs EQ exprs +{ + $$ = yylex.(*parser).newAssignmentStmt( + $1, $3, $2) +} +| expr ADD_EQ expr +{ + $$ = yylex.(*parser).newAssignmentStmt( + []ast.Node{$1}, []ast.Node{$3}, $2) +} +| expr SUB_EQ expr +{ + $$ = yylex.(*parser).newAssignmentStmt( + []ast.Node{$1}, []ast.Node{$3}, $2) +} +| expr MUL_EQ expr +{ + $$ = yylex.(*parser).newAssignmentStmt( + []ast.Node{$1}, []ast.Node{$3}, $2) +} +| expr DIV_EQ expr +{ + $$ = yylex.(*parser).newAssignmentStmt( + []ast.Node{$1}, []ast.Node{$3}, $2) +} +| expr MOD_EQ expr +{ + $$ = yylex.(*parser).newAssignmentStmt( + []ast.Node{$1}, []ast.Node{$3}, $2) +} +; + + +break_stmt: BREAK +{ + $$ = yylex.(*parser).newBreakStmt($1.Pos) +} +; + + +continue_stmt: CONTINUE +{ + $$ = yylex.(*parser).newContinueStmt($1.Pos) +} +; + +/* + for identifier IN identifier + for identifier IN list_init + for identifier IN string +*/ +for_in_stmt : FOR in_expr stmt_block +{ + $$ = yylex.(*parser).newForInStmt($1, $2, $3) +} +; + + +/* + for init ; cond expr; loop { stmts } + for init ; cond expr; { stmts } + for ; cond expr; loop { stmts } + for ; cond expr; { stmts } +*/ + +for_init_elem: expr | assignment_stmt | let_stmt +; + +for_loop_elem: expr | assignment_stmt ; + +for_stmt : FOR for_init_elem SEMICOLON expr SEMICOLON for_loop_elem stmt_block +{ + $$ = yylex.(*parser).newForStmt($1, $2, $4, $6, $7) +} +| FOR for_init_elem SEMICOLON expr SEMICOLON stmt_block +{ + $$ = yylex.(*parser).newForStmt($1, $2, $4, nil, $6) +} +| FOR for_init_elem SEMICOLON SEMICOLON for_loop_elem stmt_block +{ + $$ = yylex.(*parser).newForStmt($1, $2, nil, $5, $6) +} +| FOR for_init_elem SEMICOLON SEMICOLON stmt_block +{ + $$ = yylex.(*parser).newForStmt($1, $2, nil, nil, $5) +} +| FOR SEMICOLON expr SEMICOLON for_loop_elem stmt_block +{ + $$ = yylex.(*parser).newForStmt($1, $3, nil, $5, $6) +} +| FOR SEMICOLON expr SEMICOLON stmt_block +{ + $$ = yylex.(*parser).newForStmt($1, $3, nil, nil, $5) +} +| FOR SEMICOLON SEMICOLON for_loop_elem stmt_block +{ + $$ = yylex.(*parser).newForStmt($1, nil, nil, $4, $5) +} +| FOR SEMICOLON SEMICOLON stmt_block +{ + $$ = yylex.(*parser).newForStmt($1, nil, nil, nil, $4) +} +; + + +ifelse_stmt: if_elif_list +{ + $$ = yylex.(*parser).newIfElifStmt($1) +} +| if_elif_list ELSE stmt_block +{ + $$ = yylex.(*parser).newIfElifelseStmt($1, $2, $3) +} +; + +if_elem: IF expr stmt_block +{ + $$ = yylex.(*parser).newIfElem($1, $2, $3) +} +; + +if_elif_list: if_elem +{ + $$ = []*ast.IfStmtElem{$1} +} +| if_elif_list elif_elem +{ + $$ = append($1, $2) +} +; + +elif_elem: ELIF expr stmt_block +{ + $$ = yylex.(*parser).newIfElem($1, $2, $3) +} +; + + +stmt_block: empty_block +| LEFT_BRACE stmts RIGHT_BRACE +{ + $$ = yylex.(*parser).newBlockStmt($1, $3, $2) +} +; + + +empty_block : LEFT_BRACE RIGHT_BRACE +{ + $$ = yylex.(*parser).newBlockStmt($1, $2, nil) +} +; + + +/* +expr +*/ + +in_expr: expr IN expr +{ + $$ = yylex.(*parser).newInExpr($1, $3, $2) +} +; + +function_args: function_args COMMA expr +{ + $$ = append($$, $3) +} +| function_args COMMA named_arg +{ + $$ = append($$, $3) +} +| named_arg +{ + $$ = []ast.Node{$1} +} +| expr +{ + $$ = []ast.Node{$1} +} +; + +named_arg: identifier EQ expr +{ + $$ = yylex.(*parser).newAssignmentStmt([]ast.Node{$1}, []ast.Node{$3}, $2) +} +; + + +call_expr: expr LEFT_PAREN function_args EOLS_SPACE RIGHT_PAREN +{ + $$ = yylex.(*parser).newCallExpr($2, $5, $1, $3) +} +| expr LEFT_PAREN function_args COMMA RIGHT_PAREN +{ + $$ = yylex.(*parser).newCallExpr($2, $5, $1, $3) +} +| expr LEFT_PAREN RIGHT_PAREN +{ + $$ = yylex.(*parser).newCallExpr($2, $3, $1, nil) +} +; + +unary_expr: ADD expr %prec UMINUS +{ + $$ = yylex.(*parser).newUnaryExpr($1, $2) +} +| SUB expr %prec UMINUS +{ + $$ = yylex.(*parser).newUnaryExpr($1, $2) +} +| NOT expr +{ + $$ = yylex.(*parser).newUnaryExpr($1, $2) +} +; + +conditional_expr: expr GTE expr +{ + $$ = yylex.(*parser).newConditionalExpr($1, $3, $2) +} +| expr GT expr +{ + $$ = yylex.(*parser).newConditionalExpr($1, $3, $2) +} +| expr OR expr +{ + $$ = yylex.(*parser).newConditionalExpr($1, $3, $2) +} +| expr AND expr +{ + $$ = yylex.(*parser).newConditionalExpr($1, $3, $2) +} +| expr LT expr +{ + $$ = yylex.(*parser).newConditionalExpr($1, $3, $2) +} +| expr LTE expr +{ + $$ = yylex.(*parser).newConditionalExpr($1, $3, $2) +} +| expr NEQ expr +{ + $$ = yylex.(*parser).newConditionalExpr($1, $3, $2) +} +| expr EQEQ expr +{ + $$ = yylex.(*parser).newConditionalExpr($1, $3, $2) +} +; + + +arithmeticExpr: expr ADD expr +{ + $$ = yylex.(*parser).newArithmeticExpr($1, $3, $2) +} +| expr SUB expr +{ + $$ = yylex.(*parser).newArithmeticExpr($1, $3, $2) +} +| expr MUL expr +{ + $$ = yylex.(*parser).newArithmeticExpr($1, $3, $2) +} +| expr DIV expr +{ + $$ = yylex.(*parser).newArithmeticExpr($1, $3, $2) +} +| expr MOD expr +{ + $$ = yylex.(*parser).newArithmeticExpr($1, $3, $2) +} +; + + +paren_expr: LEFT_PAREN expr EOLS_SPACE RIGHT_PAREN +{ + $$ = yylex.(*parser).newParenExpr($1, $4, $2) +} +; + + +index_expr: expr LEFT_BRACKET expr EOLS_SPACE RIGHT_BRACKET +{ + $$ = yylex.(*parser).newIndexExpr($2, $5, $1, $3) +} +| DOT LEFT_BRACKET expr EOLS_SPACE RIGHT_BRACKET // 特殊处理,兼容旧版 +{ + $$ = yylex.(*parser).newIndexExpr($2, $5, nil, $3, $1) +} +; + + +attr_expr: expr DOT expr +{ + $$ = yylex.(*parser).newAttrExpr($1, $3) +} +; + + +expr_or_empty: expr +{ + $$ = $1 +} +| EOLS_SPACE +{ + $$ = nil +} +; + + +slice_expr: expr LEFT_BRACKET expr_or_empty COLON expr_or_empty COLON expr_or_empty RIGHT_BRACKET +{ + $$ = yylex.(*parser).newSliceExpr($2, $8, $1, $3, $5, $7) +} +| expr LEFT_BRACKET expr_or_empty COLON expr_or_empty RIGHT_BRACKET +{ + $$ = yylex.(*parser).newSliceExpr($2, $6, $1, $3, $5, nil) +} +; + + + + +list_literal : LEFT_BRACKET exprs EOLS_SPACE RIGHT_BRACKET +{ + $$ = yylex.(*parser).newListLiteral($1, $4, $2) +} +| LEFT_BRACKET exprs COMMA RIGHT_BRACKET +{ + $$ = yylex.(*parser).newListLiteral($1, $4, $2) +} +| LEFT_BRACKET RIGHT_BRACKET +{ + $$ = yylex.(*parser).newListLiteral($1, $2, nil)} +; + + +expr_colon_expr: expr COLON expr +{ + $$ = [][2]ast.Node{[2]ast.Node{$1, $3}} +} +| expr_colon_expr COMMA expr COLON expr +{ + $$ = append($$, [2]ast.Node{$3, $5}) +} +; + +map_literal : LEFT_BRACE RIGHT_BRACE +{ + $$ = yylex.(*parser).newMapLiteral($1, $2, nil) +} +| LEFT_BRACE expr_colon_expr EOLS_SPACE RIGHT_BRACE +{ + $$ = yylex.(*parser).newMapLiteral($1, $4, $2) +} +; + + +identifier: ID +{ + $$ = yylex.(*parser).newIdentifierLiteral($1) +} +| QUOTED_STRING +{ + $1.Val = yylex.(*parser).unquoteString($1.Val) + $$ = yylex.(*parser).newIdentifierLiteral($1) +} +; + +basic_literal: NUMBER +{ + $$ = yylex.(*parser).newNumberLiteral($1) +} +| TRUE +{ + $$ = yylex.(*parser).newBoolLiteral($1.Pos, true) +} +| FALSE +{ + $$ = yylex.(*parser).newBoolLiteral($1.Pos, false) +} +| STRING +{ + $1.Val = yylex.(*parser).unquoteString($1.Val) + $$ = yylex.(*parser).newStringLiteral($1) +} +| MULTILINE_STRING +{ + $1.Val = yylex.(*parser).unquoteMultilineString($1.Val) + $$ = yylex.(*parser).newStringLiteral($1) +} +| NIL +{ + $$ = yylex.(*parser).newNilLiteral($1.Pos) +} +| NULL +{ + $$ = yylex.(*parser).newNilLiteral($1.Pos) +} +; + +%% diff --git a/pkg/v2/parser/gram_y.go b/pkg/v2/parser/gram_y.go new file mode 100644 index 0000000..ffdd3c9 --- /dev/null +++ b/pkg/v2/parser/gram_y.go @@ -0,0 +1,1601 @@ +// Code generated by goyacc -o gram_y.go gram.y. DO NOT EDIT. + +//line gram.y:7 +package parser + +import __yyfmt__ "fmt" + +//line gram.y:7 + +import ( + ast "github.com/GuanceCloud/platypus/pkg/v2/ast" +) + +//line gram.y:15 +type yySymType struct { + yys int + aststmts ast.Stmts + astblock *ast.BlockStmt + + classbody any + + ifitem *ast.IfStmtElem + iflist []*ast.IfStmtElem + node ast.Node + nodes []ast.Node + map_nodes [][2]ast.Node + item Item + + fnparam ast.FnParam + fnparams []ast.FnParam +} + +const SEMICOLON = 57346 +const COMMA = 57347 +const COMMENT = 57348 +const EOF = 57349 +const ERROR = 57350 +const ID = 57351 +const NUMBER = 57352 +const LEFT_PAREN = 57353 +const LEFT_BRACKET = 57354 +const LEFT_BRACE = 57355 +const RIGHT_BRACE = 57356 +const RIGHT_PAREN = 57357 +const RIGHT_BRACKET = 57358 +const STRING = 57359 +const QUOTED_STRING = 57360 +const MULTILINE_STRING = 57361 +const COLON = 57362 +const EOL = 57363 +const operatorsStart = 57364 +const ADD = 57365 +const SUB = 57366 +const MUL = 57367 +const DIV = 57368 +const MOD = 57369 +const EQ = 57370 +const GTE = 57371 +const GT = 57372 +const LT = 57373 +const LTE = 57374 +const NEQ = 57375 +const EQEQ = 57376 +const ADD_EQ = 57377 +const SUB_EQ = 57378 +const DIV_EQ = 57379 +const MUL_EQ = 57380 +const MOD_EQ = 57381 +const AND = 57382 +const OR = 57383 +const NOT = 57384 +const DOT = 57385 +const operatorsEnd = 57386 +const keywordsStart = 57387 +const TRUE = 57388 +const FALSE = 57389 +const CLASS = 57390 +const NIL = 57391 +const NULL = 57392 +const IF = 57393 +const ELIF = 57394 +const ELSE = 57395 +const STR = 57396 +const INT = 57397 +const FLOAT = 57398 +const BOOL = 57399 +const LIST = 57400 +const MAP = 57401 +const ANY = 57402 +const FOR = 57403 +const IN = 57404 +const WHILE = 57405 +const BREAK = 57406 +const CONTINUE = 57407 +const RETURN = 57408 +const SWITCH = 57409 +const CASE = 57410 +const GOTO = 57411 +const FN = 57412 +const LET = 57413 +const VAR = 57414 +const VAR_ARG = 57415 +const FN_RET = 57416 +const IMPORT = 57417 +const AS = 57418 +const TYPE = 57419 +const NEW = 57420 +const MAKE = 57421 +const INTERFACE = 57422 +const CONST = 57423 +const keywordsEnd = 57424 +const startSymbolsStart = 57425 +const START_STMTS = 57426 +const startSymbolsEnd = 57427 +const UMINUS = 57428 + +var yyToknames = [...]string{ + "$end", + "error", + "$unk", + "SEMICOLON", + "COMMA", + "COMMENT", + "EOF", + "ERROR", + "ID", + "NUMBER", + "LEFT_PAREN", + "LEFT_BRACKET", + "LEFT_BRACE", + "RIGHT_BRACE", + "RIGHT_PAREN", + "RIGHT_BRACKET", + "STRING", + "QUOTED_STRING", + "MULTILINE_STRING", + "COLON", + "EOL", + "operatorsStart", + "ADD", + "SUB", + "MUL", + "DIV", + "MOD", + "EQ", + "GTE", + "GT", + "LT", + "LTE", + "NEQ", + "EQEQ", + "ADD_EQ", + "SUB_EQ", + "DIV_EQ", + "MUL_EQ", + "MOD_EQ", + "AND", + "OR", + "NOT", + "DOT", + "operatorsEnd", + "keywordsStart", + "TRUE", + "FALSE", + "CLASS", + "NIL", + "NULL", + "IF", + "ELIF", + "ELSE", + "STR", + "INT", + "FLOAT", + "BOOL", + "LIST", + "MAP", + "ANY", + "FOR", + "IN", + "WHILE", + "BREAK", + "CONTINUE", + "RETURN", + "SWITCH", + "CASE", + "GOTO", + "FN", + "LET", + "VAR", + "VAR_ARG", + "FN_RET", + "IMPORT", + "AS", + "TYPE", + "NEW", + "MAKE", + "INTERFACE", + "CONST", + "keywordsEnd", + "startSymbolsStart", + "START_STMTS", + "startSymbolsEnd", + "UMINUS", +} + +var yyStatenames = [...]string{} + +const yyEofCode = 1 +const yyErrCode = 2 +const yyInitialStackSize = 16 + +//line gram.y:839 + +//line yacctab:1 +var yyExca = [...]int16{ + -1, 1, + 1, -1, + -2, 0, + -1, 28, + 5, 81, + 28, 81, + -2, 35, + -1, 80, + 4, 92, + -2, 81, + -1, 160, + 20, 143, + -2, 11, + -1, 189, + 13, 95, + -2, 81, + -1, 225, + 1, 113, + 4, 113, + 7, 113, + 14, 113, + 21, 113, + -2, 152, + -1, 226, + 5, 81, + 28, 81, + -2, 35, +} + +const yyPrivate = 57344 + +const yyLast = 1323 + +var yyAct = [...]int16{ + 28, 161, 263, 22, 169, 69, 207, 240, 144, 112, + 34, 130, 130, 187, 264, 241, 200, 198, 199, 201, + 267, 162, 202, 165, 3, 235, 80, 76, 74, 81, + 194, 166, 113, 167, 111, 257, 36, 170, 128, 200, + 198, 199, 201, 192, 110, 202, 89, 103, 249, 17, + 114, 66, 248, 47, 126, 269, 196, 243, 232, 9, + 111, 119, 120, 121, 122, 123, 105, 106, 107, 109, + 115, 127, 255, 237, 125, 82, 212, 131, 104, 77, + 134, 230, 216, 218, 136, 137, 138, 139, 140, 141, + 145, 147, 148, 149, 150, 151, 152, 153, 154, 155, + 156, 157, 158, 159, 160, 164, 2, 176, 214, 130, + 50, 266, 174, 171, 111, 124, 132, 89, 103, 51, + 168, 70, 4, 9, 172, 180, 146, 73, 9, 98, + 99, 100, 101, 102, 184, 270, 189, 175, 71, 190, + 177, 50, 179, 112, 72, 277, 133, 205, 270, 104, + 51, 238, 10, 173, 200, 198, 199, 201, 271, 181, + 202, 239, 5, 8, 193, 252, 67, 203, 204, 163, + 183, 68, 6, 1, 188, 171, 206, 213, 21, 215, + 197, 20, 195, 19, 18, 46, 189, 189, 78, 190, + 190, 37, 226, 227, 38, 231, 16, 234, 233, 220, + 222, 228, 217, 89, 103, 208, 209, 210, 200, 198, + 199, 201, 39, 44, 202, 45, 40, 100, 101, 102, + 189, 43, 42, 190, 221, 223, 224, 41, 48, 146, + 11, 15, 14, 244, 13, 104, 250, 12, 118, 108, + 142, 24, 258, 259, 236, 253, 75, 35, 7, 234, + 261, 129, 251, 0, 0, 256, 0, 0, 245, 246, + 0, 247, 0, 0, 0, 0, 0, 0, 274, 273, + 265, 0, 268, 0, 0, 208, 0, 0, 254, 0, + 0, 0, 0, 260, 0, 275, 23, 0, 0, 0, + 262, 50, 52, 61, 59, 60, 225, 0, 0, 55, + 51, 56, 0, 0, 272, 62, 63, 0, 0, 0, + 276, 0, 0, 0, 0, 0, 278, 0, 0, 0, + 0, 0, 0, 0, 64, 65, 0, 0, 53, 54, + 0, 57, 58, 49, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 25, 0, 0, 27, 26, 33, 0, + 0, 0, 31, 29, 0, 0, 0, 32, 0, 23, + 0, 0, 0, 30, 50, 52, 61, 59, 60, 182, + 0, 0, 55, 51, 56, 0, 0, 0, 62, 63, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 64, 65, 0, + 0, 53, 54, 0, 57, 58, 49, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 25, 0, 0, 27, + 26, 33, 0, 0, 0, 31, 29, 0, 0, 0, + 32, 0, 23, 0, 0, 0, 30, 50, 52, 61, + 59, 60, 0, 0, 0, 55, 51, 56, 0, 66, + 0, 62, 63, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 64, 65, 0, 0, 53, 54, 0, 57, 58, 49, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, + 0, 0, 27, 26, 33, 0, 0, 0, 31, 29, + 0, 0, 0, 32, 0, 23, 0, 0, 0, 30, + 50, 52, 61, 59, 60, 0, 0, 0, 55, 51, + 56, 0, 9, 0, 62, 63, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 64, 65, 0, 0, 53, 54, 0, + 57, 58, 49, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 25, 0, 0, 27, 26, 33, 0, 0, + 0, 31, 29, 0, 0, 0, 32, 50, 52, 61, + 59, 60, 30, 0, 0, 55, 51, 56, 0, 0, + 0, 62, 63, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 64, 65, 0, 0, 53, 54, 0, 57, 58, 49, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, + 0, 0, 27, 26, 33, 0, 0, 0, 31, 29, + 0, 0, 0, 32, 0, 79, 0, 0, 0, 30, + 50, 52, 61, 59, 60, 0, 0, 0, 55, 51, + 56, 0, 0, 0, 62, 63, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 64, 65, 0, 0, 53, 54, 0, + 57, 58, 0, 0, 0, 89, 103, 0, 0, 0, + 0, 0, 0, 0, 178, 0, 0, 98, 99, 100, + 101, 102, 29, 90, 91, 94, 95, 96, 97, 83, + 84, 86, 85, 87, 93, 92, 0, 104, 0, 89, + 103, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 98, 99, 100, 101, 102, 88, 90, 91, 94, + 95, 96, 97, 83, 84, 86, 85, 87, 93, 92, + 0, 104, 0, 89, 103, 0, 0, 0, 0, 0, + 0, 0, 242, 0, 0, 98, 99, 100, 101, 102, + 88, 90, 91, 94, 95, 96, 97, 0, 0, 0, + 219, 0, 93, 92, 0, 104, 0, 89, 103, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 98, + 99, 100, 101, 102, 88, 90, 91, 94, 95, 96, + 97, 89, 103, 0, 0, 0, 93, 92, 0, 104, + 0, 9, 0, 98, 99, 100, 101, 102, 186, 90, + 91, 94, 95, 96, 97, 89, 103, 0, 88, 0, + 93, 92, 0, 104, 0, 0, 0, 98, 99, 100, + 101, 102, 0, 90, 91, 94, 95, 96, 97, 89, + 103, 130, 88, 0, 93, 92, 0, 104, 0, 0, + 0, 98, 99, 100, 101, 102, 0, 90, 91, 94, + 95, 96, 97, 89, 103, 0, 88, 0, 93, 92, + 0, 104, 178, 0, 0, 98, 99, 100, 101, 102, + 0, 90, 91, 94, 95, 96, 97, 89, 103, 0, + 88, 0, 93, 92, 0, 104, 0, 0, 0, 98, + 99, 100, 101, 102, 0, 90, 91, 94, 95, 96, + 97, 89, 103, 0, 88, 0, 93, 92, 0, 104, + 0, 0, 0, 98, 99, 100, 101, 102, 0, 90, + 91, 94, 95, 96, 97, 89, 103, 0, 88, 0, + 93, 0, 0, 104, 0, 0, 0, 98, 99, 100, + 101, 102, 0, 90, 91, 94, 95, 96, 97, 0, + 0, 0, 88, 0, 0, 0, 0, 104, 50, 52, + 61, 59, 60, 0, 0, 0, 55, 51, 56, 0, + 9, 0, 62, 63, 0, 0, 88, 0, 0, 50, + 52, 61, 59, 60, 0, 229, 0, 55, 51, 56, + 0, 64, 65, 62, 63, 53, 54, 0, 57, 58, + 50, 52, 61, 59, 60, 0, 0, 211, 55, 51, + 56, 0, 64, 65, 62, 63, 53, 54, 0, 57, + 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 64, 65, 0, 0, 53, 54, 185, + 57, 58, 0, 0, 50, 52, 61, 59, 60, 0, + 0, 0, 55, 51, 56, 0, 0, 0, 62, 63, + 50, 52, 61, 59, 60, 0, 143, 0, 55, 51, + 56, 0, 0, 0, 62, 63, 0, 64, 65, 0, + 0, 53, 54, 0, 57, 58, 0, 0, 0, 0, + 0, 0, 0, 64, 65, 0, 0, 53, 54, 135, + 57, 58, 0, 0, 50, 52, 61, 59, 60, 0, + 0, 0, 55, 51, 56, 0, 0, 0, 62, 63, + 50, 52, 61, 59, 60, 117, 0, 0, 55, 51, + 56, 0, 0, 0, 62, 63, 0, 64, 65, 0, + 0, 53, 54, 0, 57, 58, 0, 0, 0, 0, + 0, 0, 0, 64, 65, 0, 0, 53, 54, 0, + 57, 58, 50, 52, 61, 59, 60, 0, 0, 116, + 55, 51, 56, 0, 0, 0, 62, 63, 50, 52, + 61, 59, 60, 0, 0, 0, 55, 51, 56, 0, + 0, 0, 62, 63, 0, 64, 65, 0, 0, 53, + 54, 0, 57, 58, 0, 0, 0, 0, 0, 0, + 0, 64, 65, 0, 0, 53, 54, 0, 57, 58, + 50, 52, 61, 59, 191, 0, 0, 0, 55, 51, + 56, 0, 0, 0, 62, 63, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 89, 103, 0, 64, 65, 0, 0, 53, 54, 0, + 57, 58, 98, 99, 100, 101, 102, 0, 90, 91, + 94, 95, 96, 97, 0, 0, 0, 0, 0, 0, + 0, 0, 104, +} + +var yyPact = [...]int16{ + 22, 115, 501, -1000, -1000, -1000, 428, 568, 117, -1000, + 123, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -25, 641, -1000, -1000, 718, 101, + 101, 101, 101, 1209, 4, -1000, -1000, -1000, -1000, -1000, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 1209, + -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, -1000, 1193, + 1151, 1209, 1209, 1209, 1209, 103, -1000, -1000, 117, 50, + -1000, -1000, -1000, -1000, 96, -1000, 1209, 96, 142, 1135, + 718, -1000, -1000, 1209, 1209, 1209, 1209, 1209, 1209, 1091, + 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, 1209, + 1209, 1209, 1209, 989, 1209, 3, 5, 109, -39, -1000, + 138, 906, 1209, 1209, 858, 107, -1000, -1000, 102, 882, + 810, 35, 35, 35, 1209, 50, -1000, -1000, -1000, -1000, + 355, 858, -1000, 1075, 834, 1251, 906, 906, 906, 906, + 906, 1279, 38, -1000, -1000, 906, 2, 106, 106, 930, + 954, 106, 106, 106, 106, 192, 192, 35, 35, 35, + 810, 36, -1000, 30, -1000, -15, 1209, 1209, 132, 101, + 101, 906, 138, -1000, 1031, 60, 1209, 94, 1209, 67, + 810, 69, -1000, -1000, 786, 1251, 1251, 96, -1000, 718, + -1000, 282, 1010, 66, 1209, 42, 989, -3, -1000, -1000, + -1000, -1000, -1000, 906, 906, -1, 146, -1000, -13, -1000, + -1000, -1000, -1000, 752, -1000, 906, -1000, 41, -1000, 1251, + 96, -1000, 96, -1000, -1000, -1000, 684, 906, -1000, -1000, + -1000, 906, -1000, 32, 906, 1209, -1000, 154, 101, -2, + -38, 1209, 1209, -1000, 96, -1000, -1000, -1000, 989, -1000, + 906, 96, -15, -1000, -1000, 100, -8, -15, 906, 906, + -1000, 39, -1000, 143, -1000, 96, -15, 1209, -1000, -1000, + -15, 96, -1000, 130, 906, -1000, -1000, 96, -1000, +} + +var yyPgo = [...]uint8{ + 0, 38, 251, 159, 248, 247, 246, 241, 240, 10, + 239, 2, 238, 163, 3, 237, 234, 232, 231, 230, + 228, 8, 36, 227, 222, 221, 216, 215, 213, 53, + 0, 212, 196, 1, 194, 191, 188, 13, 185, 14, + 49, 184, 183, 181, 178, 6, 176, 173, 5, 152, + 169, 21, +} + +var yyR1 = [...]int8{ + 0, 48, 48, 48, 48, 49, 49, 49, 50, 50, + 51, 51, 47, 47, 47, 47, 47, 3, 3, 3, + 4, 4, 4, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 32, 30, 30, 30, 30, + 30, 30, 30, 30, 30, 30, 30, 30, 30, 39, + 39, 39, 39, 39, 41, 40, 40, 40, 40, 10, + 10, 43, 43, 45, 45, 45, 45, 45, 45, 44, + 44, 46, 46, 11, 11, 42, 42, 42, 42, 42, + 42, 9, 9, 14, 14, 14, 14, 14, 14, 18, + 17, 15, 36, 36, 36, 37, 37, 16, 16, 16, + 16, 16, 16, 16, 16, 19, 19, 5, 7, 7, + 6, 1, 1, 2, 29, 8, 8, 8, 8, 21, + 20, 20, 20, 23, 23, 23, 24, 24, 24, 24, + 24, 24, 24, 24, 25, 25, 25, 25, 25, 26, + 27, 27, 28, 33, 33, 38, 38, 34, 34, 34, + 12, 12, 31, 31, 22, 22, 35, 35, 35, 35, + 35, 35, 35, +} + +var yyR2 = [...]int8{ + 0, 1, 1, 2, 2, 1, 2, 2, 1, 2, + 1, 0, 2, 2, 3, 2, 1, 2, 1, 1, + 2, 1, 3, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 4, 6, 4, 2, 4, 1, + 3, 2, 4, 1, 3, 4, 3, 3, 5, 1, + 2, 1, 3, 1, 3, 5, 7, 9, 6, 8, + 10, 1, 3, 3, 3, 3, 3, 3, 3, 1, + 1, 3, 1, 1, 1, 1, 1, 7, 6, 6, + 5, 6, 5, 5, 4, 1, 3, 3, 1, 2, + 3, 1, 3, 2, 3, 3, 3, 1, 1, 3, + 5, 5, 3, 2, 2, 2, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, + 5, 5, 3, 1, 1, 8, 6, 4, 4, 2, + 3, 5, 2, 4, 1, 1, 1, 1, 1, 1, + 1, 1, 1, +} + +var yyChk = [...]int16{ + -1000, -47, 84, 2, 7, -3, -50, -4, -13, 21, + -49, -19, -15, -16, -17, -18, -32, -40, -41, -42, + -43, -44, -14, 4, -7, 61, 65, 64, -30, 71, + 81, 70, 75, 66, -9, -5, -22, -35, -34, -31, + -26, -23, -24, -25, -28, -27, -38, -29, -20, 51, + 9, 18, 10, 46, 47, 17, 19, 49, 50, 12, + 13, 11, 23, 24, 42, 43, 21, -3, -13, -48, + 4, 21, 21, 4, 53, -6, 52, -29, -36, 4, + -30, -14, -40, 35, 36, 38, 37, 39, 62, 11, + 29, 30, 41, 40, 31, 32, 33, 34, 23, 24, + 25, 26, 27, 12, 43, -22, -22, -22, -10, -22, + -9, -30, 5, 28, -30, -9, 16, 14, -12, -30, + -30, -30, -30, -30, 12, -48, 4, 21, -1, -2, + 13, -30, -1, 4, -30, 4, -30, -30, -30, -30, + -30, -30, -8, 15, -21, -30, -22, -30, -30, -30, + -30, -30, -30, -30, -30, -30, -30, -30, -30, -30, + -30, -33, -51, -50, -30, 20, 28, 28, 11, 43, + 76, -30, -9, -1, 5, -51, 5, -51, 20, -51, + -30, -3, 14, -1, -30, 4, 4, -37, -1, -30, + -14, 13, 5, -51, 28, -51, 20, -39, 55, 56, + 54, 57, 60, -30, -30, 15, -46, -45, -22, -22, + -22, 16, 16, -30, 14, -30, 15, -51, 14, 4, + -37, -1, -37, -1, -1, 14, -30, -30, -21, 15, + 15, -30, 16, -33, -30, 28, -1, 74, 5, 15, + 20, 28, 20, 16, -37, -1, -1, -1, 20, 16, + -30, -39, 11, -45, -1, 74, -39, 73, -30, -30, + -1, -33, -1, -11, -39, -39, 11, 28, -39, 16, + 5, 15, -1, -11, -30, -39, -1, 15, -1, +} + +var yyDef = [...]int16{ + 0, -2, 0, 16, 15, 12, 13, 18, 19, 8, + 21, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 5, 105, 0, 90, 89, -2, 0, + 0, 0, 0, 69, 0, 108, 36, 37, 38, 39, + 40, 41, 42, 43, 44, 45, 46, 47, 48, 0, + 154, 155, 156, 157, 158, 159, 160, 161, 162, 0, + 0, 0, 0, 0, 0, 0, 9, 14, 17, 20, + 1, 2, 6, 7, 0, 109, 0, 47, 0, 0, + -2, 93, 94, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 11, 0, 57, 0, 0, 61, 59, + 70, 81, 0, 0, 0, 11, 149, 152, 11, 0, + 11, 123, 124, 125, 0, 22, 3, 4, 106, 111, + 0, 0, 91, 0, 0, 0, 84, 85, 86, 87, + 88, 114, 11, 122, 117, 118, 36, 126, 127, 128, + 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, + -2, 0, 144, 10, 142, 0, 0, 0, 0, 0, + 0, 82, 83, 107, 0, 0, 0, 0, 0, 0, + 11, 0, 113, 110, 0, 0, 0, 0, 104, -2, + 96, 0, 0, 0, 0, 0, 11, 56, 49, 50, + 51, 52, 53, 58, 54, 0, 0, 71, 63, 60, + 62, 148, 147, 0, 153, 150, 139, 0, 112, 0, + 0, 100, 0, 102, 103, -2, -2, 115, 116, 121, + 120, 119, 140, 0, 143, 0, 75, 0, 0, 0, + 0, 0, 0, 141, 0, 98, 99, 101, 11, 146, + 55, 0, 0, 72, 78, 0, 64, 66, 67, 151, + 97, 0, 76, 0, 73, 0, 0, 0, 65, 145, + 0, 0, 79, 0, 68, 74, 77, 0, 80, +} + +var yyTok1 = [...]int8{ + 1, +} + +var yyTok2 = [...]int8{ + 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, + 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, + 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, + 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, + 82, 83, 84, 85, 86, +} + +var yyTok3 = [...]int8{ + 0, +} + +var yyErrorMessages = [...]struct { + state int + token int + msg string +}{} + +//line yaccpar:1 + +/* parser for yacc output */ + +var ( + yyDebug = 0 + yyErrorVerbose = false +) + +type yyLexer interface { + Lex(lval *yySymType) int + Error(s string) +} + +type yyParser interface { + Parse(yyLexer) int + Lookahead() int +} + +type yyParserImpl struct { + lval yySymType + stack [yyInitialStackSize]yySymType + char int +} + +func (p *yyParserImpl) Lookahead() int { + return p.char +} + +func yyNewParser() yyParser { + return &yyParserImpl{} +} + +const yyFlag = -1000 + +func yyTokname(c int) string { + if c >= 1 && c-1 < len(yyToknames) { + if yyToknames[c-1] != "" { + return yyToknames[c-1] + } + } + return __yyfmt__.Sprintf("tok-%v", c) +} + +func yyStatname(s int) string { + if s >= 0 && s < len(yyStatenames) { + if yyStatenames[s] != "" { + return yyStatenames[s] + } + } + return __yyfmt__.Sprintf("state-%v", s) +} + +func yyErrorMessage(state, lookAhead int) string { + const TOKSTART = 4 + + if !yyErrorVerbose { + return "syntax error" + } + + for _, e := range yyErrorMessages { + if e.state == state && e.token == lookAhead { + return "syntax error: " + e.msg + } + } + + res := "syntax error: unexpected " + yyTokname(lookAhead) + + // To match Bison, suggest at most four expected tokens. + expected := make([]int, 0, 4) + + // Look for shiftable tokens. + base := int(yyPact[state]) + for tok := TOKSTART; tok-1 < len(yyToknames); tok++ { + if n := base + tok; n >= 0 && n < yyLast && int(yyChk[int(yyAct[n])]) == tok { + if len(expected) == cap(expected) { + return res + } + expected = append(expected, tok) + } + } + + if yyDef[state] == -2 { + i := 0 + for yyExca[i] != -1 || int(yyExca[i+1]) != state { + i += 2 + } + + // Look for tokens that we accept or reduce. + for i += 2; yyExca[i] >= 0; i += 2 { + tok := int(yyExca[i]) + if tok < TOKSTART || yyExca[i+1] == 0 { + continue + } + if len(expected) == cap(expected) { + return res + } + expected = append(expected, tok) + } + + // If the default action is to accept or reduce, give up. + if yyExca[i+1] != 0 { + return res + } + } + + for i, tok := range expected { + if i == 0 { + res += ", expecting " + } else { + res += " or " + } + res += yyTokname(tok) + } + return res +} + +func yylex1(lex yyLexer, lval *yySymType) (char, token int) { + token = 0 + char = lex.Lex(lval) + if char <= 0 { + token = int(yyTok1[0]) + goto out + } + if char < len(yyTok1) { + token = int(yyTok1[char]) + goto out + } + if char >= yyPrivate { + if char < yyPrivate+len(yyTok2) { + token = int(yyTok2[char-yyPrivate]) + goto out + } + } + for i := 0; i < len(yyTok3); i += 2 { + token = int(yyTok3[i+0]) + if token == char { + token = int(yyTok3[i+1]) + goto out + } + } + +out: + if token == 0 { + token = int(yyTok2[1]) /* unknown char */ + } + if yyDebug >= 3 { + __yyfmt__.Printf("lex %s(%d)\n", yyTokname(token), uint(char)) + } + return char, token +} + +func yyParse(yylex yyLexer) int { + return yyNewParser().Parse(yylex) +} + +func (yyrcvr *yyParserImpl) Parse(yylex yyLexer) int { + var yyn int + var yyVAL yySymType + var yyDollar []yySymType + _ = yyDollar // silence set and not used + yyS := yyrcvr.stack[:] + + Nerrs := 0 /* number of errors */ + Errflag := 0 /* error recovery flag */ + yystate := 0 + yyrcvr.char = -1 + yytoken := -1 // yyrcvr.char translated into internal numbering + defer func() { + // Make sure we report no lookahead when not parsing. + yystate = -1 + yyrcvr.char = -1 + yytoken = -1 + }() + yyp := -1 + goto yystack + +ret0: + return 0 + +ret1: + return 1 + +yystack: + /* put a state and value onto the stack */ + if yyDebug >= 4 { + __yyfmt__.Printf("char %v in %v\n", yyTokname(yytoken), yyStatname(yystate)) + } + + yyp++ + if yyp >= len(yyS) { + nyys := make([]yySymType, len(yyS)*2) + copy(nyys, yyS) + yyS = nyys + } + yyS[yyp] = yyVAL + yyS[yyp].yys = yystate + +yynewstate: + yyn = int(yyPact[yystate]) + if yyn <= yyFlag { + goto yydefault /* simple state */ + } + if yyrcvr.char < 0 { + yyrcvr.char, yytoken = yylex1(yylex, &yyrcvr.lval) + } + yyn += yytoken + if yyn < 0 || yyn >= yyLast { + goto yydefault + } + yyn = int(yyAct[yyn]) + if int(yyChk[yyn]) == yytoken { /* valid shift */ + yyrcvr.char = -1 + yytoken = -1 + yyVAL = yyrcvr.lval + yystate = yyn + if Errflag > 0 { + Errflag-- + } + goto yystack + } + +yydefault: + /* default state action */ + yyn = int(yyDef[yystate]) + if yyn == -2 { + if yyrcvr.char < 0 { + yyrcvr.char, yytoken = yylex1(yylex, &yyrcvr.lval) + } + + /* look through exception table */ + xi := 0 + for { + if yyExca[xi+0] == -1 && int(yyExca[xi+1]) == yystate { + break + } + xi += 2 + } + for xi += 2; ; xi += 2 { + yyn = int(yyExca[xi+0]) + if yyn < 0 || yyn == yytoken { + break + } + } + yyn = int(yyExca[xi+1]) + if yyn < 0 { + goto ret0 + } + } + if yyn == 0 { + /* error ... attempt to resume parsing */ + switch Errflag { + case 0: /* brand new error */ + yylex.Error(yyErrorMessage(yystate, yytoken)) + Nerrs++ + if yyDebug >= 1 { + __yyfmt__.Printf("%s", yyStatname(yystate)) + __yyfmt__.Printf(" saw %s\n", yyTokname(yytoken)) + } + fallthrough + + case 1, 2: /* incompletely recovered error ... try again */ + Errflag = 3 + + /* find a state where "error" is a legal shift action */ + for yyp >= 0 { + yyn = int(yyPact[yyS[yyp].yys]) + yyErrCode + if yyn >= 0 && yyn < yyLast { + yystate = int(yyAct[yyn]) /* simulate a shift of "error" */ + if int(yyChk[yystate]) == yyErrCode { + goto yystack + } + } + + /* the current p has no shift on "error", pop stack */ + if yyDebug >= 2 { + __yyfmt__.Printf("error recovery pops state %d\n", yyS[yyp].yys) + } + yyp-- + } + /* there is no state on the stack with an error shift ... abort */ + goto ret1 + + case 3: /* no shift yet; clobber input char */ + if yyDebug >= 2 { + __yyfmt__.Printf("error recovery discards %s\n", yyTokname(yytoken)) + } + if yytoken == yyEofCode { + goto ret1 + } + yyrcvr.char = -1 + yytoken = -1 + goto yynewstate /* try again in the same state */ + } + } + + /* reduction by production yyn */ + if yyDebug >= 2 { + __yyfmt__.Printf("reduce %v in:\n\t%v\n", yyn, yyStatname(yystate)) + } + + yynt := yyn + yypt := yyp + _ = yypt // guard against "declared and not used" + + yyp -= int(yyR2[yyn]) + // yyp is now the index of $0. Perform the default action. Iff the + // reduced production is ε, $1 is possibly out of range. + if yyp+1 >= len(yyS) { + nyys := make([]yySymType, len(yyS)*2) + copy(nyys, yyS) + yyS = nyys + } + yyVAL = yyS[yyp+1] + + /* consult goto table to find next state */ + yyn = int(yyR1[yyn]) + yyg := int(yyPgo[yyn]) + yyj := yyg + yyS[yyp].yys + 1 + + if yyj >= yyLast { + yystate = int(yyAct[yyg]) + } else { + yystate = int(yyAct[yyj]) + if int(yyChk[yystate]) != -yyn { + yystate = int(yyAct[yyg]) + } + } + // dummy call; replaced with literal code + switch yynt { + + case 12: + yyDollar = yyS[yypt-2 : yypt+1] +//line gram.y:175 + { + yylex.(*parser).parseResult = yyDollar[2].aststmts + } + case 13: + yyDollar = yyS[yypt-2 : yypt+1] +//line gram.y:179 + { + yylex.(*parser).parseResult = ast.Stmts{} + } + case 14: + yyDollar = yyS[yypt-3 : yypt+1] +//line gram.y:183 + { + yylex.(*parser).parseResult = yyDollar[3].aststmts + } + case 16: + yyDollar = yyS[yypt-1 : yypt+1] +//line gram.y:188 + { + yylex.(*parser).unexpected("", "") + } + case 17: + yyDollar = yyS[yypt-2 : yypt+1] +//line gram.y:198 + { + s := yyDollar[1].aststmts + s = append(s, yyDollar[2].node) + yyVAL.aststmts = s + } + case 19: + yyDollar = yyS[yypt-1 : yypt+1] +//line gram.y:205 + { + yyVAL.aststmts = ast.Stmts{yyDollar[1].node} + } + case 20: + yyDollar = yyS[yypt-2 : yypt+1] +//line gram.y:211 + { + yyVAL.aststmts = ast.Stmts{yyDollar[1].node} + } + case 21: + yyDollar = yyS[yypt-1 : yypt+1] +//line gram.y:215 + { + yyVAL.aststmts = ast.Stmts{} + } + case 22: + yyDollar = yyS[yypt-3 : yypt+1] +//line gram.y:219 + { + s := yyDollar[1].aststmts + s = append(s, yyDollar[2].node) + yyVAL.aststmts = s + } + case 49: + yyDollar = yyS[yypt-1 : yypt+1] +//line gram.y:266 + { + yyVAL.node = yylex.(*parser).newBuiltinType(yyDollar[1].item) + } + case 50: + yyDollar = yyS[yypt-1 : yypt+1] +//line gram.y:270 + { + yyVAL.node = yylex.(*parser).newBuiltinType(yyDollar[1].item) + } + case 51: + yyDollar = yyS[yypt-1 : yypt+1] +//line gram.y:274 + { + yyVAL.node = yylex.(*parser).newBuiltinType(yyDollar[1].item) + } + case 52: + yyDollar = yyS[yypt-1 : yypt+1] +//line gram.y:278 + { + yyVAL.node = yylex.(*parser).newBuiltinType(yyDollar[1].item) + } + case 53: + yyDollar = yyS[yypt-1 : yypt+1] +//line gram.y:282 + { + yyVAL.node = yylex.(*parser).newBuiltinType(yyDollar[1].item) + } + case 54: + yyDollar = yyS[yypt-4 : yypt+1] +//line gram.y:289 + { + yyVAL.node = yylex.(*parser).newConstDefStmt(yyDollar[1].item, yyDollar[2].node, yyDollar[4].node) + } + case 55: + yyDollar = yyS[yypt-6 : yypt+1] +//line gram.y:296 + { + yyVAL.node = yylex.(*parser).newLetStmt(yyDollar[1].item, yyDollar[2].node, yyDollar[4].node, yyDollar[6].node) + } + case 56: + yyDollar = yyS[yypt-4 : yypt+1] +//line gram.y:300 + { + yyVAL.node = yylex.(*parser).newLetStmt(yyDollar[1].item, yyDollar[2].node, yyDollar[4].node, nil) + } + case 57: + yyDollar = yyS[yypt-2 : yypt+1] +//line gram.y:304 + { + yyVAL.node = yylex.(*parser).newLetStmt(yyDollar[1].item, yyDollar[2].node, nil, nil) + } + case 58: + yyDollar = yyS[yypt-4 : yypt+1] +//line gram.y:308 + { + yyVAL.node = yylex.(*parser).newLetStmt(yyDollar[1].item, yyDollar[2].node, nil, nil) + } + case 59: + yyDollar = yyS[yypt-1 : yypt+1] +//line gram.y:320 + { + yyVAL.nodes = []ast.Node{yyDollar[1].node} + } + case 60: + yyDollar = yyS[yypt-3 : yypt+1] +//line gram.y:324 + { + yyVAL.nodes = append(yyVAL.nodes, yyDollar[3].node) + } + case 61: + yyDollar = yyS[yypt-2 : yypt+1] +//line gram.y:330 + { + yyVAL.node = yylex.(*parser).newImportStmt(yyDollar[1].item, yyDollar[2].nodes, nil) + } + case 62: + yyDollar = yyS[yypt-4 : yypt+1] +//line gram.y:334 + { + yyVAL.node = yylex.(*parser).newImportStmt(yyDollar[1].item, yyDollar[2].nodes, yyDollar[4].node) + } + case 63: + yyDollar = yyS[yypt-1 : yypt+1] +//line gram.y:341 + { + yyVAL.fnparam = yylex.(*parser).newFnParam(yyDollar[1].node, nil, nil) + } + case 64: + yyDollar = yyS[yypt-3 : yypt+1] +//line gram.y:345 + { + yyVAL.fnparam = yylex.(*parser).newFnParam(yyDollar[1].node, yyDollar[3].node, nil) + } + case 65: + yyDollar = yyS[yypt-4 : yypt+1] +//line gram.y:349 + { + yyVAL.fnparam = yylex.(*parser).newFnParam(yyDollar[1].node, yyDollar[4].node, nil, true) + } + case 66: + yyDollar = yyS[yypt-3 : yypt+1] +//line gram.y:353 + { + yyVAL.fnparam = yylex.(*parser).newFnParam(yyDollar[1].node, nil, nil, true) + } + case 67: + yyDollar = yyS[yypt-3 : yypt+1] +//line gram.y:357 + { + yyVAL.fnparam = yylex.(*parser).newFnParam(yyDollar[1].node, nil, yyDollar[3].node) + } + case 68: + yyDollar = yyS[yypt-5 : yypt+1] +//line gram.y:361 + { + yyVAL.fnparam = yylex.(*parser).newFnParam(yyDollar[1].node, yyDollar[3].node, yyDollar[5].node) + } + case 69: + yyDollar = yyS[yypt-1 : yypt+1] +//line gram.y:368 + { + yyVAL.node = yylex.(*parser).newReturnStmt(yyDollar[1].item, nil) + } + case 70: + yyDollar = yyS[yypt-2 : yypt+1] +//line gram.y:372 + { + yyVAL.node = yylex.(*parser).newReturnStmt(yyDollar[1].item, yyDollar[2].nodes) + } + case 71: + yyDollar = yyS[yypt-1 : yypt+1] +//line gram.y:379 + { + yyVAL.fnparams = []ast.FnParam{yyDollar[1].fnparam} + } + case 72: + yyDollar = yyS[yypt-3 : yypt+1] +//line gram.y:383 + { + yyVAL.fnparams = append(yyVAL.fnparams, yyDollar[3].fnparam) + } + case 73: + yyDollar = yyS[yypt-1 : yypt+1] +//line gram.y:390 + { + yyVAL.nodes = []ast.Node{yyDollar[1].node} + } + case 74: + yyDollar = yyS[yypt-3 : yypt+1] +//line gram.y:394 + { + yyVAL.nodes = append(yyVAL.nodes, yyDollar[3].node) + } + case 75: + yyDollar = yyS[yypt-5 : yypt+1] +//line gram.y:402 + { + yyVAL.node = yylex.(*parser).newFnDefStmt(yyDollar[1].item, yyDollar[2].node, nil, nil, yyDollar[5].astblock) + } + case 76: + yyDollar = yyS[yypt-7 : yypt+1] +//line gram.y:406 + { + yyVAL.node = yylex.(*parser).newFnDefStmt(yyDollar[1].item, yyDollar[2].node, nil, []ast.Node{yyDollar[6].node}, yyDollar[7].astblock) + } + case 77: + yyDollar = yyS[yypt-9 : yypt+1] +//line gram.y:410 + { + yyVAL.node = yylex.(*parser).newFnDefStmt(yyDollar[1].item, yyDollar[2].node, nil, yyDollar[7].nodes, yyDollar[9].astblock) + } + case 78: + yyDollar = yyS[yypt-6 : yypt+1] +//line gram.y:414 + { + yyVAL.node = yylex.(*parser).newFnDefStmt(yyDollar[1].item, yyDollar[2].node, yyDollar[4].fnparams, nil, yyDollar[6].astblock) + } + case 79: + yyDollar = yyS[yypt-8 : yypt+1] +//line gram.y:418 + { + yyVAL.node = yylex.(*parser).newFnDefStmt(yyDollar[1].item, yyDollar[2].node, yyDollar[4].fnparams, []ast.Node{yyDollar[7].node}, yyDollar[8].astblock) + } + case 80: + yyDollar = yyS[yypt-10 : yypt+1] +//line gram.y:422 + { + yyVAL.node = yylex.(*parser).newFnDefStmt(yyDollar[1].item, yyDollar[2].node, yyDollar[4].fnparams, yyDollar[8].nodes, yyDollar[10].astblock) + } + case 81: + yyDollar = yyS[yypt-1 : yypt+1] +//line gram.y:428 + { + yyVAL.nodes = []ast.Node{yyDollar[1].node} + } + case 82: + yyDollar = yyS[yypt-3 : yypt+1] +//line gram.y:432 + { + yyVAL.nodes = append(yyDollar[1].nodes, yyDollar[3].node) + } + case 83: + yyDollar = yyS[yypt-3 : yypt+1] +//line gram.y:439 + { + yyVAL.node = yylex.(*parser).newAssignmentStmt( + yyDollar[1].nodes, yyDollar[3].nodes, yyDollar[2].item) + } + case 84: + yyDollar = yyS[yypt-3 : yypt+1] +//line gram.y:444 + { + yyVAL.node = yylex.(*parser).newAssignmentStmt( + []ast.Node{yyDollar[1].node}, []ast.Node{yyDollar[3].node}, yyDollar[2].item) + } + case 85: + yyDollar = yyS[yypt-3 : yypt+1] +//line gram.y:449 + { + yyVAL.node = yylex.(*parser).newAssignmentStmt( + []ast.Node{yyDollar[1].node}, []ast.Node{yyDollar[3].node}, yyDollar[2].item) + } + case 86: + yyDollar = yyS[yypt-3 : yypt+1] +//line gram.y:454 + { + yyVAL.node = yylex.(*parser).newAssignmentStmt( + []ast.Node{yyDollar[1].node}, []ast.Node{yyDollar[3].node}, yyDollar[2].item) + } + case 87: + yyDollar = yyS[yypt-3 : yypt+1] +//line gram.y:459 + { + yyVAL.node = yylex.(*parser).newAssignmentStmt( + []ast.Node{yyDollar[1].node}, []ast.Node{yyDollar[3].node}, yyDollar[2].item) + } + case 88: + yyDollar = yyS[yypt-3 : yypt+1] +//line gram.y:464 + { + yyVAL.node = yylex.(*parser).newAssignmentStmt( + []ast.Node{yyDollar[1].node}, []ast.Node{yyDollar[3].node}, yyDollar[2].item) + } + case 89: + yyDollar = yyS[yypt-1 : yypt+1] +//line gram.y:472 + { + yyVAL.node = yylex.(*parser).newBreakStmt(yyDollar[1].item.Pos) + } + case 90: + yyDollar = yyS[yypt-1 : yypt+1] +//line gram.y:479 + { + yyVAL.node = yylex.(*parser).newContinueStmt(yyDollar[1].item.Pos) + } + case 91: + yyDollar = yyS[yypt-3 : yypt+1] +//line gram.y:490 + { + yyVAL.node = yylex.(*parser).newForInStmt(yyDollar[1].item, yyDollar[2].node, yyDollar[3].astblock) + } + case 97: + yyDollar = yyS[yypt-7 : yypt+1] +//line gram.y:509 + { + yyVAL.node = yylex.(*parser).newForStmt(yyDollar[1].item, yyDollar[2].node, yyDollar[4].node, yyDollar[6].node, yyDollar[7].astblock) + } + case 98: + yyDollar = yyS[yypt-6 : yypt+1] +//line gram.y:513 + { + yyVAL.node = yylex.(*parser).newForStmt(yyDollar[1].item, yyDollar[2].node, yyDollar[4].node, nil, yyDollar[6].astblock) + } + case 99: + yyDollar = yyS[yypt-6 : yypt+1] +//line gram.y:517 + { + yyVAL.node = yylex.(*parser).newForStmt(yyDollar[1].item, yyDollar[2].node, nil, yyDollar[5].node, yyDollar[6].astblock) + } + case 100: + yyDollar = yyS[yypt-5 : yypt+1] +//line gram.y:521 + { + yyVAL.node = yylex.(*parser).newForStmt(yyDollar[1].item, yyDollar[2].node, nil, nil, yyDollar[5].astblock) + } + case 101: + yyDollar = yyS[yypt-6 : yypt+1] +//line gram.y:525 + { + yyVAL.node = yylex.(*parser).newForStmt(yyDollar[1].item, yyDollar[3].node, nil, yyDollar[5].node, yyDollar[6].astblock) + } + case 102: + yyDollar = yyS[yypt-5 : yypt+1] +//line gram.y:529 + { + yyVAL.node = yylex.(*parser).newForStmt(yyDollar[1].item, yyDollar[3].node, nil, nil, yyDollar[5].astblock) + } + case 103: + yyDollar = yyS[yypt-5 : yypt+1] +//line gram.y:533 + { + yyVAL.node = yylex.(*parser).newForStmt(yyDollar[1].item, nil, nil, yyDollar[4].node, yyDollar[5].astblock) + } + case 104: + yyDollar = yyS[yypt-4 : yypt+1] +//line gram.y:537 + { + yyVAL.node = yylex.(*parser).newForStmt(yyDollar[1].item, nil, nil, nil, yyDollar[4].astblock) + } + case 105: + yyDollar = yyS[yypt-1 : yypt+1] +//line gram.y:544 + { + yyVAL.node = yylex.(*parser).newIfElifStmt(yyDollar[1].iflist) + } + case 106: + yyDollar = yyS[yypt-3 : yypt+1] +//line gram.y:548 + { + yyVAL.node = yylex.(*parser).newIfElifelseStmt(yyDollar[1].iflist, yyDollar[2].item, yyDollar[3].astblock) + } + case 107: + yyDollar = yyS[yypt-3 : yypt+1] +//line gram.y:554 + { + yyVAL.ifitem = yylex.(*parser).newIfElem(yyDollar[1].item, yyDollar[2].node, yyDollar[3].astblock) + } + case 108: + yyDollar = yyS[yypt-1 : yypt+1] +//line gram.y:560 + { + yyVAL.iflist = []*ast.IfStmtElem{yyDollar[1].ifitem} + } + case 109: + yyDollar = yyS[yypt-2 : yypt+1] +//line gram.y:564 + { + yyVAL.iflist = append(yyDollar[1].iflist, yyDollar[2].ifitem) + } + case 110: + yyDollar = yyS[yypt-3 : yypt+1] +//line gram.y:570 + { + yyVAL.ifitem = yylex.(*parser).newIfElem(yyDollar[1].item, yyDollar[2].node, yyDollar[3].astblock) + } + case 112: + yyDollar = yyS[yypt-3 : yypt+1] +//line gram.y:578 + { + yyVAL.astblock = yylex.(*parser).newBlockStmt(yyDollar[1].item, yyDollar[3].item, yyDollar[2].aststmts) + } + case 113: + yyDollar = yyS[yypt-2 : yypt+1] +//line gram.y:585 + { + yyVAL.astblock = yylex.(*parser).newBlockStmt(yyDollar[1].item, yyDollar[2].item, nil) + } + case 114: + yyDollar = yyS[yypt-3 : yypt+1] +//line gram.y:596 + { + yyVAL.node = yylex.(*parser).newInExpr(yyDollar[1].node, yyDollar[3].node, yyDollar[2].item) + } + case 115: + yyDollar = yyS[yypt-3 : yypt+1] +//line gram.y:602 + { + yyVAL.nodes = append(yyVAL.nodes, yyDollar[3].node) + } + case 116: + yyDollar = yyS[yypt-3 : yypt+1] +//line gram.y:606 + { + yyVAL.nodes = append(yyVAL.nodes, yyDollar[3].node) + } + case 117: + yyDollar = yyS[yypt-1 : yypt+1] +//line gram.y:610 + { + yyVAL.nodes = []ast.Node{yyDollar[1].node} + } + case 118: + yyDollar = yyS[yypt-1 : yypt+1] +//line gram.y:614 + { + yyVAL.nodes = []ast.Node{yyDollar[1].node} + } + case 119: + yyDollar = yyS[yypt-3 : yypt+1] +//line gram.y:620 + { + yyVAL.node = yylex.(*parser).newAssignmentStmt([]ast.Node{yyDollar[1].node}, []ast.Node{yyDollar[3].node}, yyDollar[2].item) + } + case 120: + yyDollar = yyS[yypt-5 : yypt+1] +//line gram.y:627 + { + yyVAL.node = yylex.(*parser).newCallExpr(yyDollar[2].item, yyDollar[5].item, yyDollar[1].node, yyDollar[3].nodes) + } + case 121: + yyDollar = yyS[yypt-5 : yypt+1] +//line gram.y:631 + { + yyVAL.node = yylex.(*parser).newCallExpr(yyDollar[2].item, yyDollar[5].item, yyDollar[1].node, yyDollar[3].nodes) + } + case 122: + yyDollar = yyS[yypt-3 : yypt+1] +//line gram.y:635 + { + yyVAL.node = yylex.(*parser).newCallExpr(yyDollar[2].item, yyDollar[3].item, yyDollar[1].node, nil) + } + case 123: + yyDollar = yyS[yypt-2 : yypt+1] +//line gram.y:641 + { + yyVAL.node = yylex.(*parser).newUnaryExpr(yyDollar[1].item, yyDollar[2].node) + } + case 124: + yyDollar = yyS[yypt-2 : yypt+1] +//line gram.y:645 + { + yyVAL.node = yylex.(*parser).newUnaryExpr(yyDollar[1].item, yyDollar[2].node) + } + case 125: + yyDollar = yyS[yypt-2 : yypt+1] +//line gram.y:649 + { + yyVAL.node = yylex.(*parser).newUnaryExpr(yyDollar[1].item, yyDollar[2].node) + } + case 126: + yyDollar = yyS[yypt-3 : yypt+1] +//line gram.y:655 + { + yyVAL.node = yylex.(*parser).newConditionalExpr(yyDollar[1].node, yyDollar[3].node, yyDollar[2].item) + } + case 127: + yyDollar = yyS[yypt-3 : yypt+1] +//line gram.y:659 + { + yyVAL.node = yylex.(*parser).newConditionalExpr(yyDollar[1].node, yyDollar[3].node, yyDollar[2].item) + } + case 128: + yyDollar = yyS[yypt-3 : yypt+1] +//line gram.y:663 + { + yyVAL.node = yylex.(*parser).newConditionalExpr(yyDollar[1].node, yyDollar[3].node, yyDollar[2].item) + } + case 129: + yyDollar = yyS[yypt-3 : yypt+1] +//line gram.y:667 + { + yyVAL.node = yylex.(*parser).newConditionalExpr(yyDollar[1].node, yyDollar[3].node, yyDollar[2].item) + } + case 130: + yyDollar = yyS[yypt-3 : yypt+1] +//line gram.y:671 + { + yyVAL.node = yylex.(*parser).newConditionalExpr(yyDollar[1].node, yyDollar[3].node, yyDollar[2].item) + } + case 131: + yyDollar = yyS[yypt-3 : yypt+1] +//line gram.y:675 + { + yyVAL.node = yylex.(*parser).newConditionalExpr(yyDollar[1].node, yyDollar[3].node, yyDollar[2].item) + } + case 132: + yyDollar = yyS[yypt-3 : yypt+1] +//line gram.y:679 + { + yyVAL.node = yylex.(*parser).newConditionalExpr(yyDollar[1].node, yyDollar[3].node, yyDollar[2].item) + } + case 133: + yyDollar = yyS[yypt-3 : yypt+1] +//line gram.y:683 + { + yyVAL.node = yylex.(*parser).newConditionalExpr(yyDollar[1].node, yyDollar[3].node, yyDollar[2].item) + } + case 134: + yyDollar = yyS[yypt-3 : yypt+1] +//line gram.y:690 + { + yyVAL.node = yylex.(*parser).newArithmeticExpr(yyDollar[1].node, yyDollar[3].node, yyDollar[2].item) + } + case 135: + yyDollar = yyS[yypt-3 : yypt+1] +//line gram.y:694 + { + yyVAL.node = yylex.(*parser).newArithmeticExpr(yyDollar[1].node, yyDollar[3].node, yyDollar[2].item) + } + case 136: + yyDollar = yyS[yypt-3 : yypt+1] +//line gram.y:698 + { + yyVAL.node = yylex.(*parser).newArithmeticExpr(yyDollar[1].node, yyDollar[3].node, yyDollar[2].item) + } + case 137: + yyDollar = yyS[yypt-3 : yypt+1] +//line gram.y:702 + { + yyVAL.node = yylex.(*parser).newArithmeticExpr(yyDollar[1].node, yyDollar[3].node, yyDollar[2].item) + } + case 138: + yyDollar = yyS[yypt-3 : yypt+1] +//line gram.y:706 + { + yyVAL.node = yylex.(*parser).newArithmeticExpr(yyDollar[1].node, yyDollar[3].node, yyDollar[2].item) + } + case 139: + yyDollar = yyS[yypt-4 : yypt+1] +//line gram.y:713 + { + yyVAL.node = yylex.(*parser).newParenExpr(yyDollar[1].item, yyDollar[4].item, yyDollar[2].node) + } + case 140: + yyDollar = yyS[yypt-5 : yypt+1] +//line gram.y:720 + { + yyVAL.node = yylex.(*parser).newIndexExpr(yyDollar[2].item, yyDollar[5].item, yyDollar[1].node, yyDollar[3].node) + } + case 141: + yyDollar = yyS[yypt-5 : yypt+1] +//line gram.y:724 + { + yyVAL.node = yylex.(*parser).newIndexExpr(yyDollar[2].item, yyDollar[5].item, nil, yyDollar[3].node, yyDollar[1].item) + } + case 142: + yyDollar = yyS[yypt-3 : yypt+1] +//line gram.y:731 + { + yyVAL.node = yylex.(*parser).newAttrExpr(yyDollar[1].node, yyDollar[3].node) + } + case 143: + yyDollar = yyS[yypt-1 : yypt+1] +//line gram.y:738 + { + yyVAL.node = yyDollar[1].node + } + case 144: + yyDollar = yyS[yypt-1 : yypt+1] +//line gram.y:742 + { + yyVAL.node = nil + } + case 145: + yyDollar = yyS[yypt-8 : yypt+1] +//line gram.y:749 + { + yyVAL.node = yylex.(*parser).newSliceExpr(yyDollar[2].item, yyDollar[8].item, yyDollar[1].node, yyDollar[3].node, yyDollar[5].node, yyDollar[7].node) + } + case 146: + yyDollar = yyS[yypt-6 : yypt+1] +//line gram.y:753 + { + yyVAL.node = yylex.(*parser).newSliceExpr(yyDollar[2].item, yyDollar[6].item, yyDollar[1].node, yyDollar[3].node, yyDollar[5].node, nil) + } + case 147: + yyDollar = yyS[yypt-4 : yypt+1] +//line gram.y:762 + { + yyVAL.node = yylex.(*parser).newListLiteral(yyDollar[1].item, yyDollar[4].item, yyDollar[2].nodes) + } + case 148: + yyDollar = yyS[yypt-4 : yypt+1] +//line gram.y:766 + { + yyVAL.node = yylex.(*parser).newListLiteral(yyDollar[1].item, yyDollar[4].item, yyDollar[2].nodes) + } + case 149: + yyDollar = yyS[yypt-2 : yypt+1] +//line gram.y:770 + { + yyVAL.node = yylex.(*parser).newListLiteral(yyDollar[1].item, yyDollar[2].item, nil) + } + case 150: + yyDollar = yyS[yypt-3 : yypt+1] +//line gram.y:776 + { + yyVAL.map_nodes = [][2]ast.Node{[2]ast.Node{yyDollar[1].node, yyDollar[3].node}} + } + case 151: + yyDollar = yyS[yypt-5 : yypt+1] +//line gram.y:780 + { + yyVAL.map_nodes = append(yyVAL.map_nodes, [2]ast.Node{yyDollar[3].node, yyDollar[5].node}) + } + case 152: + yyDollar = yyS[yypt-2 : yypt+1] +//line gram.y:786 + { + yyVAL.node = yylex.(*parser).newMapLiteral(yyDollar[1].item, yyDollar[2].item, nil) + } + case 153: + yyDollar = yyS[yypt-4 : yypt+1] +//line gram.y:790 + { + yyVAL.node = yylex.(*parser).newMapLiteral(yyDollar[1].item, yyDollar[4].item, yyDollar[2].map_nodes) + } + case 154: + yyDollar = yyS[yypt-1 : yypt+1] +//line gram.y:797 + { + yyVAL.node = yylex.(*parser).newIdentifierLiteral(yyDollar[1].item) + } + case 155: + yyDollar = yyS[yypt-1 : yypt+1] +//line gram.y:801 + { + yyDollar[1].item.Val = yylex.(*parser).unquoteString(yyDollar[1].item.Val) + yyVAL.node = yylex.(*parser).newIdentifierLiteral(yyDollar[1].item) + } + case 156: + yyDollar = yyS[yypt-1 : yypt+1] +//line gram.y:808 + { + yyVAL.node = yylex.(*parser).newNumberLiteral(yyDollar[1].item) + } + case 157: + yyDollar = yyS[yypt-1 : yypt+1] +//line gram.y:812 + { + yyVAL.node = yylex.(*parser).newBoolLiteral(yyDollar[1].item.Pos, true) + } + case 158: + yyDollar = yyS[yypt-1 : yypt+1] +//line gram.y:816 + { + yyVAL.node = yylex.(*parser).newBoolLiteral(yyDollar[1].item.Pos, false) + } + case 159: + yyDollar = yyS[yypt-1 : yypt+1] +//line gram.y:820 + { + yyDollar[1].item.Val = yylex.(*parser).unquoteString(yyDollar[1].item.Val) + yyVAL.node = yylex.(*parser).newStringLiteral(yyDollar[1].item) + } + case 160: + yyDollar = yyS[yypt-1 : yypt+1] +//line gram.y:825 + { + yyDollar[1].item.Val = yylex.(*parser).unquoteMultilineString(yyDollar[1].item.Val) + yyVAL.node = yylex.(*parser).newStringLiteral(yyDollar[1].item) + } + case 161: + yyDollar = yyS[yypt-1 : yypt+1] +//line gram.y:830 + { + yyVAL.node = yylex.(*parser).newNilLiteral(yyDollar[1].item.Pos) + } + case 162: + yyDollar = yyS[yypt-1 : yypt+1] +//line gram.y:834 + { + yyVAL.node = yylex.(*parser).newNilLiteral(yyDollar[1].item.Pos) + } + } + goto yystack /* stack new state and value */ +} diff --git a/pkg/v2/parser/lex.go b/pkg/v2/parser/lex.go new file mode 100644 index 0000000..ada536e --- /dev/null +++ b/pkg/v2/parser/lex.go @@ -0,0 +1,821 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the MIT License. +// This product includes software developed at Guance Cloud (https://www.guance.com/). +// Copyright 2021-present Guance, Inc. +// +// ==================================================================================== +// Copyright 2015 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package parser + +import ( + "fmt" + "strings" + "unicode" + "unicode/utf8" + + "github.com/GuanceCloud/platypus/pkg/token" + ast "github.com/GuanceCloud/platypus/pkg/v2/ast" +) + +type PositionRange struct { + Start, End token.Pos +} + +func (pos PositionRange) String() string { + return fmt.Sprintf("Ln: %d, Col: %d", pos.Start, pos.End) +} + +type Item struct { + Typ ItemType + Pos token.Pos + Val string +} + +func (i *Item) PositionRange() *PositionRange { + return &PositionRange{ + Start: i.Pos, + End: i.Pos + token.Pos(len(i.Val)), + } +} + +func (i Item) lexStr() string { + return fmt.Sprintf("% 06d %02d %s", i.Typ, i.Pos, i.String()) +} + +func (i Item) String() string { + switch { + case i.Typ == EOF: + return "EOF" + case i.Typ == ERROR: + return i.Val + case i.Typ == ID: + return fmt.Sprintf("%q", i.Val) + case i.Typ.IsKeyword(): + return fmt.Sprintf("<%s>", i.Val) + case i.Typ.IsOperator(): + return fmt.Sprintf("", i.Val) + case len(i.Val) > 10: + return fmt.Sprintf("%.10q...", i.Val) + } + return fmt.Sprintf("%q", i.Val) +} + +func (i ItemType) IsOperator() bool { return i > operatorsStart && i < operatorsEnd } +func (i ItemType) IsKeyword() bool { return i > keywordsStart && i < keywordsEnd } + +type ItemType int + +const ( + eof = -1 + lineComment = "#" + Digits = "0123456789" + HexDigits = "0123456789abcdefABCDEF" +) + +var ( + keywords = map[string]ItemType{ + // Keywords. + "if": IF, + "elif": ELIF, + "else": ELSE, + + "false": FALSE, + "true": TRUE, + + "nil": NIL, + "null": NULL, + + "for": FOR, + "in": IN, + "while": WHILE, + "break": BREAK, + "continue": CONTINUE, + + "return": RETURN, + + "string": STR, + "str": STR, + "bool": BOOL, + "int": INT, + "float": FLOAT, + "list": LIST, + "map": MAP, + "any": ANY, + + "let": LET, + "var": VAR, + "class": CLASS, + + "import": IMPORT, + "as": AS, + "type": TYPE, + + "switch": SWITCH, + "case": CASE, + "goto": GOTO, + "new": NEW, + "make": MAKE, + + "interface": INTERFACE, + "fn": FN, + "const": CONST, + } + + ItemTypeStr = map[ItemType]string{ + LEFT_PAREN: "(", + RIGHT_PAREN: ")", + LEFT_BRACKET: "[", + RIGHT_BRACKET: "]", + LEFT_BRACE: "{", + RIGHT_BRACE: "}", + COMMA: ",", + + EQ: "=", + ADD_EQ: "+=", + SUB_EQ: "-=", + MUL_EQ: "*=", + DIV_EQ: "/=", + MOD_EQ: "%=", + + SEMICOLON: ";", + DOT: ".", + COLON: ":", + + VAR_ARG: "...", + + EQEQ: "==", + NEQ: "!=", + LTE: "<=", + LT: "<", + GTE: ">=", + GT: ">", + + FN_RET: "->", + + NOT: "!", + SUB: "-", + ADD: "+", + MUL: "*", + MOD: "%", + DIV: "/", + + // XOR: "^", + AND: "&&", + OR: "||", + } + + AstOp = func(op ItemType) ast.Op { + return ast.Op(ItemTypeStr[op]) + } +) + +func init() { //nolint:gochecknoinits + // Add keywords to Item type strings. + for s, ty := range keywords { + ItemTypeStr[ty] = s + } + // Special numbers. + keywords["inf"] = NUMBER + keywords["nan"] = NUMBER +} + +func (i ItemType) String() string { + if s, ok := ItemTypeStr[i]; ok { + return s + } + return fmt.Sprintf("", i) +} + +func (i Item) desc() string { + if _, ok := ItemTypeStr[i.Typ]; ok { + return i.String() + } + if i.Typ == EOF { + return i.Typ.desc() + } + return fmt.Sprintf("%s %s", i.Typ.desc(), i) +} + +func (i ItemType) desc() string { + switch i { + case ERROR: + return "error" + case EOF: + return "end of input" + case EOL: + return "end of line" + case COMMENT: + return "comment" + case ID: + return "id" + case STRING: + return "string" + case NUMBER: + return "number" + } + return fmt.Sprintf("%q", i) +} + +// stateFn represents the state of the scanner as a function that returns the next state. +type stateFn func(*Lexer) stateFn + +// Pos is the position in a string. +// Negative numbers indicate undefined positions. +// type Pos int + +// Lexer holds the state of the scanner. +type Lexer struct { + input string // The string being scanned. + state stateFn // The next lexing function to enter. + pos token.Pos // Current position in the input. + start token.Pos // Start position of this Item. + width token.Pos // Width of last rune read from input. + lastPos token.Pos // Position of most recent Item returned by NextItem. + itemp *Item // Pointer to where the next scanned item should be placed. + scannedItem bool // Set to true every time an item is scanned. + + parenDepth int // nested depth of () exprs. + braceDepth int // nested depth of {} exprs. + bracketDepth int // nested depth of [] exprs. + + stringOpen rune // Quote rune of the string currently being read. + backquoteOpen rune // backquote keyworkds and utf8 characters + + // seriesDesc is set when a series description for the testing + // language is lexed. + // seriesDesc bool +} + +func Lex(input string) *Lexer { + l := &Lexer{ + input: input, + state: lexStatements, + } + return l +} + +// Lexer entry. +func lexStatements(l *Lexer) stateFn { + if strings.HasPrefix(l.input[l.pos:], lineComment) { + return lexLineComment + } + + switch r := l.next(); { + case r == ',': + l.emit(COMMA) + return lexSpaceAndLineCommentForOp(l) + case isSpaceNotEOL(r): + return lexSpaceNotEOL + + case r == '*': + if t := l.peek(); t == '=' { + l.next() + l.emit(MUL_EQ) + } else { + l.emit(MUL) + } + return lexSpaceAndLineCommentForOp(l) + case r == '/': + if t := l.peek(); t == '=' { + l.next() + l.emit(DIV_EQ) + } else { + l.emit(DIV) + } + return lexSpaceAndLineCommentForOp(l) + case r == '%': + if t := l.peek(); t == '=' { + l.next() + l.emit(MOD_EQ) + } else { + l.emit(MOD) + } + return lexSpaceAndLineCommentForOp(l) + case r == '+': + if t := l.peek(); t == '=' { + l.next() + l.emit(ADD_EQ) + } else { + l.emit(ADD) + } + return lexSpaceAndLineCommentForOp(l) + case r == '-': + switch l.peek() { + case '=': + l.next() + l.emit(SUB_EQ) + case '>': + l.next() + l.emit(FN_RET) + default: + l.emit(SUB) + } + return lexSpaceAndLineCommentForOp(l) + case r == '=': + if t := l.peek(); t == '=' { + l.next() + l.emit(EQEQ) + } else { + l.emit(EQ) + } + return lexSpaceAndLineCommentForOp(l) + case r == ':': + l.emit(COLON) + return lexSpaceAndLineCommentForOp(l) + case r == ';': + l.emit(SEMICOLON) + case isEOL(r): + l.emit(EOL) + + case r == '.': + if t := l.peek(); t == '.' { + l.next() + if t := l.peek(); t == '.' { + l.next() + l.emit(VAR_ARG) + } else { + l.backup() + l.emit(DOT) + } + } else { + l.emit(DOT) + } + return lexSpaceAndLineCommentForOp(l) + + case r == '|': + if t := l.peek(); t == '|' { + l.next() + l.emit(OR) + } else { + // TODO: add bit-or operator + return l.errorf("unexpected character `%q' after `!'", r) + } + return lexSpaceAndLineCommentForOp(l) + case r == '&': + if t := l.peek(); t == '&' { + l.next() + l.emit(AND) + } else { + // TODO: add bit-and operator + return l.errorf("unexpected character `%q' after `!'", r) + } + return lexSpaceAndLineCommentForOp(l) + + case r == '!': + switch nr := l.peek(); { + case nr == '=': + l.next() + l.emit(NEQ) + default: + l.emit(NOT) + } + return lexSpaceAndLineCommentForOp(l) + + case r == '<': + if t := l.peek(); t == '=' { + l.next() + l.emit(LTE) + } else { + l.emit(LT) + } + return lexSpaceAndLineCommentForOp(l) + + case r == '>': + if t := l.peek(); t == '=' { + l.next() + l.emit(GTE) + } else { + l.emit(GT) + } + return lexSpaceAndLineCommentForOp(l) + + case isDigit(r) || (r == '.' && isDigit(l.peek())): + l.backup() + return lexNumberOrDuration + + case r == '"': + if t1 := l.peek(); t1 == '"' { + l.next() + if t2 := l.peek(); t2 == '"' { + l.next() + return lexMultilineString + } else { + l.emit(STRING) + } + } else { + l.stringOpen = r + return lexString + } + + case r == '\'': + if t := l.peek(); t == '\'' { + l.next() + if t := l.peek(); t == '\'' { + l.next() + return lexMultilineString + } else { + l.emit(STRING) + } + } else { + l.stringOpen = r + return lexString + } + + case r == '`': + l.backquoteOpen = r + return lexRawString + + case isAlpha(r) || isUTF8(r): + l.backup() + return lexKeywordOrIdentifier + + case r == '(': + l.emit(LEFT_PAREN) + l.parenDepth++ + return lexSpaceAndLineCommentForOp(l) + + case r == ')': + l.emit(RIGHT_PAREN) + l.parenDepth-- + if l.parenDepth < 0 { + return l.errorf("unexpected right parenthesis %q", r) + } + return lexStatements + + case r == '{': + l.emit(LEFT_BRACE) + l.braceDepth++ + return lexSpaceAndLineCommentForOp(l) + + case r == '}': + l.emit(RIGHT_BRACE) + l.braceDepth-- + if l.braceDepth < 0 { + return l.errorf("unexpected right parenthesis %q", r) + } + + case r == '[': + l.bracketDepth++ + l.emit(LEFT_BRACKET) + return lexSpaceAndLineCommentForOp(l) + + case r == ']': + l.bracketDepth-- + l.emit(RIGHT_BRACKET) + + case r == eof: + switch { + case l.parenDepth != 0: + return l.errorf("unclosed left parenthesis") + case l.bracketDepth != 0: + return l.errorf("unclosed left bracket") + case l.braceDepth != 0: + return l.errorf("unclosed left brace") + } + + l.emit(EOF) + return nil + + default: + return l.errorf("unexpected character: %q", r) + } + return lexStatements +} + +// Other state functions +// scan alphanumberic identifier, maybe keyword. +func lexKeywordOrIdentifier(l *Lexer) stateFn { +__goon: + for { + switch r := l.next(); { + case isAlphaNumeric(r), isUTF8(r): + // absorb + default: + l.backup() + word := l.input[l.start:l.pos] + + if kw, ok := keywords[strings.ToLower(word)]; ok { + // log.Debugf("emit keyword: %s", kw) + l.emit(kw) + if kw == IN { + return lexSpaceAndLineCommentForOp(l) + } + } else { + l.emit(ID) + } + + break __goon + } + } + + return lexStatements +} + +func lexCommentForOp(l *Lexer) stateFn { + if l.peek() == '#' { + l.pos += token.Pos(len(lineComment)) + for r := l.next(); !isEOL(r) && r != eof; { + r = l.next() + } + l.backup() + l.emit(COMMENT) + if isSpace(l.peek()) { + return lexSpaceAndLineCommentForOp + } + } + return lexStatements +} + +func lexSpaceAndLineCommentForOp(l *Lexer) stateFn { + for isSpace(l.peek()) { + l.next() + } + l.ignore() + + if l.peek() == '#' { + return lexCommentForOp + } + + return lexStatements +} + +func lexSpaceNotEOL(l *Lexer) stateFn { + for isSpaceNotEOL(l.peek()) { + l.next() + } + + l.ignore() + return lexStatements +} + +func lexNumberOrDuration(l *Lexer) stateFn { + if l.scanNumber() { + l.emit(NUMBER) + return lexStatements + } + + return l.errorf("bad duration: %q", l.cur()) +} + +func lexRawString(l *Lexer) stateFn { +__goon: + for { + switch l.next() { + case utf8.RuneError: + l.errorf("invalid UTF-8 rune") + return lexRawString + case eof: + l.errorf("unterminated raw string") + return lexRawString + case l.backquoteOpen: + break __goon + } + } + + l.emit(QUOTED_STRING) + return lexStatements +} + +func lexLineComment(l *Lexer) stateFn { + l.pos += token.Pos(len(lineComment)) + for r := l.next(); !isEOL(r) && r != eof; { + r = l.next() + } + l.backup() + l.emit(COMMENT) + return lexStatements +} + +func lexEscape(l *Lexer) stateFn { + ch := l.next() + var n int + var base, max uint32 + + switch ch { + case 'a', 'b', 'f', 'n', 'r', 't', 'v', '\\', l.stringOpen, l.backquoteOpen: + return lexString + case '0', '1', '2', '3', '4', '5', '6', '7': + n, base, max = 3, 8, 255 + case 'x', 'X': + ch = l.next() + n, base, max = 2, 16, 255 + case 'u': + ch = l.next() + n, base, max = 4, 16, unicode.MaxRune + case 'U': + ch = l.next() + n, base, max = 8, 16, unicode.MaxRune + case eof: + l.errorf("escape squence not terminated") + return lexString + default: + l.errorf("unknown escape sequence %#U", ch) + return lexString + } + + log.Debugf("n: %d, base: %d, max: %d", n, base, max) + + var x uint32 + for n > 0 { + d := uint32(digitVal(ch)) + if d >= base { + if ch == eof { + l.errorf("escape sequence not terminated") + } + l.errorf("illegal character %#U in escape sequence", ch) + return lexString + } + + x = x*base + d + ch = l.next() + n-- + } + + if x > max || 0xD800 <= x && x < 0xE000 { + l.errorf("escape sequence is an invalid Unicode code point") + } + + log.Debugf("get number %d", x) + return lexString +} + +func lexMultilineString(l *Lexer) stateFn { +__goon: + for { + c := l.next() + switch c { + case eof: + return l.errorf("unterminated quoted string within lexMultilineString") + + case utf8.RuneError: + l.errorf("invalid UTF-8 rune") + + case '"', '\'': + if t := l.peek(); t == '"' || t == '\'' { + l.next() + if t := l.peek(); t == '"' || t == '\'' { + l.next() + break __goon + } + } + default: // pass + } + } + + l.emit(MULTILINE_STRING) + return lexStatements +} + +func lexString(l *Lexer) stateFn { +__goon: + for { + switch l.next() { + case '\\': + return lexEscape + + case utf8.RuneError: + l.errorf("invalid UTF-8 rune") + + case eof, '\n': + return l.errorf("unterminated quoted string within lexString") + + case l.stringOpen: + break __goon + } + } + + l.emit(STRING) + return lexStatements +} + +// lexer tool functions. +func (l *Lexer) next() rune { + if int(l.pos) >= len(l.input) { + l.width = 0 + return eof + } + r, w := utf8.DecodeRuneInString(l.input[l.pos:]) + l.width = token.Pos(w) + l.pos += l.width + return r +} + +func (l *Lexer) peek() rune { + r := l.next() + l.backup() + return r +} + +func (l *Lexer) emit(t ItemType) { + *l.itemp = Item{t, l.start, l.input[l.start:l.pos]} + + l.start = l.pos + l.scannedItem = true + // log.Debugf("emit: %+#v", l.itemp) +} + +func (l *Lexer) errorf(format string, args ...interface{}) stateFn { + *l.itemp = Item{ERROR, l.start, fmt.Sprintf(format, args...)} + l.scannedItem = true + + return nil +} + +func (l *Lexer) ignore() { + l.start = l.pos +} + +func (l *Lexer) backup() { l.pos -= l.width } + +func (l *Lexer) accept(valid string) bool { + if strings.ContainsRune(valid, l.next()) { + return true + } + l.backup() + return false +} + +func (l *Lexer) acceptRun(valid string) { + for strings.ContainsRune(valid, l.next()) { + /* consume */ + } + l.backup() +} + +func (l *Lexer) NextItem(itemp *Item) { + l.scannedItem = false + l.itemp = itemp + + if l.state != nil { + for !l.scannedItem { + l.state = l.state(l) + } + } else { + l.emit(EOF) + } + + l.lastPos = l.itemp.Pos +} + +func (l *Lexer) cur() string { + return l.input[l.start:l.pos] +} + +func (l *Lexer) scanNumber() bool { + digs := Digits + if l.accept("0") && l.accept("xX") { + digs = HexDigits + } + + l.acceptRun(digs) + if l.accept(".") { + l.acceptRun(digs) + } + + if l.accept("eE") { // scientific notation + l.accept("+-") + l.acceptRun(Digits) + } + + // next things should not be alphanumberic + if r := l.peek(); !isAlphaNumeric(r) { + return true + } + + return false +} + +// helpers. +func isAlphaNumeric(r rune) bool { return isAlpha(r) || isDigit(r) } +func isAlpha(r rune) bool { return r == '_' || ('a' <= r && r <= 'z') || ('A' <= r && r <= 'Z') } +func isUTF8(r rune) bool { return utf8.RuneLen(r) > 1 } +func isDigit(r rune) bool { return '0' <= r && r <= '9' } +func isSpaceNotEOL(r rune) bool { return r == ' ' || r == '\t' || r == '\r' } + +func isSpace(r rune) bool { return r == ' ' || r == '\t' || r == '\r' || r == '\n' } + +func isEOL(r rune) bool { return r == '\r' || r == '\n' } + +func digitVal(ch rune) int { + switch { + case '0' <= ch && ch <= '9': + return int(ch - '0') + case 'a' <= ch && ch <= 'f': + return int(ch - 'a' + 10) + case 'A' <= ch && ch <= 'F': + return int(ch - 'A' + 10) + } + return 16 // larger than any legal digit val +} diff --git a/pkg/v2/parser/lex_test.go b/pkg/v2/parser/lex_test.go new file mode 100644 index 0000000..ddf16f5 --- /dev/null +++ b/pkg/v2/parser/lex_test.go @@ -0,0 +1,612 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the MIT License. +// This product includes software developed at Guance Cloud (https://www.guance.com/). +// Copyright 2021-present Guance, Inc. +// +// ==================================================================================== +// Copyright 2015 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package parser + +import ( + + // "reflect" + "strings" + "testing" + "unicode/utf8" + + "github.com/GuanceCloud/platypus/pkg/token" + "github.com/stretchr/testify/assert" +) + +type testCase struct { + input string + expected []Item + fail bool +} + +var cases = []struct { + name string + tests []testCase +}{ + { + name: "identifiers", + tests: []testCase{ + { + input: "中文 abc", + expected: []Item{ + {ID, 0, "中文"}, + {ID, 7, "abc"}, + }, + }, + + { + input: "中文_abc", + expected: []Item{ + {ID, 0, "中文_abc"}, + }, + }, + + { + input: "NAME👍", + expected: []Item{ + {ID, 0, "NAME👍"}, + }, + }, + + { + input: "abc d", + expected: []Item{ + {ID, 0, "abc"}, + {ID, 4, "d"}, + }, + }, + + { + input: "0a:bc", + fail: true, + }, + { + input: "M{cpu}", + expected: []Item{ + {ID, 0, "M"}, + {LEFT_BRACE, 1, "{"}, + {ID, 2, "cpu"}, + {RIGHT_BRACE, 5, "}"}, + }, + }, + { + input: "metric{cpu}", + expected: []Item{ + {ID, 0, "metric"}, + {LEFT_BRACE, 6, "{"}, + {ID, 7, "cpu"}, + {RIGHT_BRACE, 10, "}"}, + }, + }, + { + input: "metric{cpu(some_field, other_field)}", + expected: []Item{ + {ID, 0, "metric"}, + {LEFT_BRACE, 6, "{"}, + {ID, 7, "cpu"}, + {LEFT_PAREN, 10, "("}, + {ID, 11, "some_field"}, + + {COMMA, 21, ","}, + + {ID, 23, "other_field"}, + {RIGHT_PAREN, 34, ")"}, + {RIGHT_BRACE, 35, "}"}, + }, + }, + { + input: "{}", + expected: []Item{ + {LEFT_BRACE, 0, "{"}, + {RIGHT_BRACE, 1, "}"}, + }, + }, + { + input: "logging", + expected: []Item{{ID, 0, "logging"}}, + }, + { + input: "abc def", + expected: []Item{{ID, 0, "abc"}, {ID, 4, "def"}}, + }, + }, + }, + + { + name: "common", + tests: []testCase{ + { + input: ",", + expected: []Item{{COMMA, 0, ","}}, + }, + { + input: "()", + expected: []Item{{LEFT_PAREN, 0, `(`}, {RIGHT_PAREN, 1, `)`}}, + }, + { + input: "{}", + expected: []Item{{LEFT_BRACE, 0, `{`}, {RIGHT_BRACE, 1, `}`}}, + }, + { + input: "\r\n\r", + expected: []Item{{EOL, 1, "\n"}}, + }, + }, + }, + { + name: "numbers", + tests: []testCase{ + { + input: "1", + expected: []Item{{NUMBER, 0, "1"}}, + }, + { + input: "4.23", + expected: []Item{{NUMBER, 0, "4.23"}}, + }, + /*{ + input: ".3", + expected: []Item{{NUMBER, 0, ".3"}}, + }, + { + input: "5.", + expected: []Item{{NUMBER, 0, "5."}}, + }, */ + { + input: "NaN", + expected: []Item{{NUMBER, 0, "NaN"}}, + }, + { + input: "nAN", + expected: []Item{{NUMBER, 0, "nAN"}}, + }, + { + input: "NaN 123", + expected: []Item{{NUMBER, 0, "NaN"}, {NUMBER, 4, "123"}}, + }, + { + input: "NaN123", + expected: []Item{{ID, 0, "NaN123"}}, + }, + { + input: "iNf", + expected: []Item{{NUMBER, 0, "iNf"}}, + }, + { + input: "Inf", + expected: []Item{{NUMBER, 0, "Inf"}}, + }, + { + input: "+Inf", + expected: []Item{{ADD, 0, "+"}, {NUMBER, 1, "Inf"}}, + }, + { + input: "+Inf 123", + expected: []Item{{ADD, 0, "+"}, {NUMBER, 1, "Inf"}, {NUMBER, 5, "123"}}, + }, + { + input: "-Inf", + expected: []Item{{SUB, 0, "-"}, {NUMBER, 1, "Inf"}}, + }, + { + input: "Infoo", + expected: []Item{{ID, 0, "Infoo"}}, + }, + { + input: "-Infoo", + expected: []Item{{SUB, 0, "-"}, {ID, 1, "Infoo"}}, + }, + { + input: "-Inf 123", + expected: []Item{{SUB, 0, "-"}, {NUMBER, 1, "Inf"}, {NUMBER, 5, "123"}}, + }, + { + input: "0x123 0X123", + expected: []Item{{NUMBER, 0, "0x123"}, {NUMBER, 6, "0X123"}}, + }, + { + input: "0123", + expected: []Item{{NUMBER, 0, "0123"}}, + }, + { + input: "7.823E5", + expected: []Item{{NUMBER, 0, "7.823E5"}}, + }, + }, + }, + { + name: "comments", + tests: []testCase{ + { + input: "# some comment", + expected: []Item{{COMMENT, 0, "# some comment"}}, + }, { + input: "5 # 1+1\n5", + expected: []Item{ + {NUMBER, 0, "5"}, + {COMMENT, 2, "# 1+1"}, + {EOL, 7, "\n"}, + {NUMBER, 8, "5"}, + }, + }, + }, + }, + + { + name: "operators", + tests: []testCase{ + { + input: `=`, + expected: []Item{{EQ, 0, `=`}}, + }, + { + // Inside braces equality is a single '=' character but in terms of a token + // it should be treated as ASSIGN. + input: `{=}`, + expected: []Item{{LEFT_BRACE, 0, `{`}, {EQ, 1, `=`}, {RIGHT_BRACE, 2, `}`}}, + }, + { + input: `!=`, + expected: []Item{{NEQ, 0, `!=`}}, + }, + { + input: `<`, + expected: []Item{{LT, 0, `<`}}, + }, + { + input: `>`, + expected: []Item{{GT, 0, `>`}}, + }, + { + input: `>=`, + expected: []Item{{GTE, 0, `>=`}}, + }, + { + input: `<=`, + expected: []Item{{LTE, 0, `<=`}}, + }, + { + input: `+`, + expected: []Item{{ADD, 0, `+`}}, + }, + { + input: `-`, + expected: []Item{{SUB, 0, `-`}}, + }, + { + input: `*`, + expected: []Item{{MUL, 0, `*`}}, + }, + { + input: `/`, + expected: []Item{{DIV, 0, `/`}}, + }, + // { + // input: `^`, + // expected: []Item{{XOR, 0, `^`}}, + // }, + { + input: `%`, + expected: []Item{{MOD, 0, `%`}}, + }, + { + input: `&&`, + expected: []Item{{AND, 0, `&&`}}, + }, + { + input: `||`, + expected: []Item{{OR, 0, `||`}}, + }, + }, + }, + { + name: "aggregators", + tests: []testCase{ + { + input: `sum`, + expected: []Item{{ID, 0, `sum`}}, + }, { + input: `AVG`, + expected: []Item{{ID, 0, `AVG`}}, + }, { + input: `MAX`, + expected: []Item{{ID, 0, `MAX`}}, + }, { + input: `min`, + expected: []Item{{ID, 0, `min`}}, + }, { + input: `count`, + expected: []Item{{ID, 0, `count`}}, + }, { + input: `stdvar`, + expected: []Item{{ID, 0, `stdvar`}}, + }, { + input: `stddev`, + expected: []Item{{ID, 0, `stddev`}}, + }, + }, + }, + { + name: "selectors", + tests: []testCase{ + { + input: `台北`, + // fail: true, + expected: []Item{ + {ID, 0, `台北`}, + }, + }, + { + input: `{台北='a'}`, + expected: []Item{ + {LEFT_BRACE, 0, `{`}, + {ID, 1, `台北`}, + {EQ, 7, `=`}, + {STRING, 8, `'a'`}, + {RIGHT_BRACE, 11, `}`}, + }, + // fail: true, + }, + { + input: `{0a='a'}`, + fail: true, + }, + { + input: `{foo='bar'}`, + expected: []Item{ + {LEFT_BRACE, 0, `{`}, + {ID, 1, `foo`}, + {EQ, 4, `=`}, + {STRING, 5, `'bar'`}, + {RIGHT_BRACE, 10, `}`}, + }, + }, + { + input: `{foo="bar"}`, + expected: []Item{ + {LEFT_BRACE, 0, `{`}, + {ID, 1, `foo`}, + {EQ, 4, `=`}, + {STRING, 5, `"bar"`}, + {RIGHT_BRACE, 10, `}`}, + }, + }, + { + input: `{foo="bar\"bar"}`, + expected: []Item{ + {LEFT_BRACE, 0, `{`}, + {ID, 1, `foo`}, + {EQ, 4, `=`}, + {STRING, 5, `"bar\"bar"`}, + {RIGHT_BRACE, 15, `}`}, + }, + }, + { + input: `{NaN != "bar" }`, + expected: []Item{ + {LEFT_BRACE, 0, `{`}, + {NUMBER, 1, `NaN`}, + {NEQ, 5, `!=`}, + {STRING, 8, `"bar"`}, + {RIGHT_BRACE, 14, `}`}, + }, + }, + { + input: `{alert!#"bar"}`, fail: true, + }, + }, + }, + { + name: "common errors", + tests: []testCase{ + { + input: `!(`, fail: true, + }, + { + input: "1a", fail: true, + }, + }, + }, + { + name: "mismatched parentheses", + tests: []testCase{ + { + input: `(`, fail: true, + }, { + input: `())`, fail: true, + }, { + input: `(()`, fail: true, + }, { + input: `{`, fail: true, + }, { + input: `}`, fail: true, + }, { + input: "{{", fail: true, + }, { + input: `[`, fail: true, + }, { + input: `[[`, fail: true, + }, { + input: `[]]`, fail: true, + }, { + input: `]`, fail: true, + }, + }, + }, + + { + name: "encoding issues", + tests: []testCase{ + { + input: "\"\xfff\"", + expected: []Item{ + {STRING, 0, "\"\xfff\""}, + }, + }, + { + input: "`\xff`", // invalid UTF-8 rune + fail: true, + }, + + { + input: "\xff", + expected: []Item{ + {ID, 0, "\xff"}, + }, + }, + }, + }, + { + name: "strings", + tests: []testCase{ + { + input: "\"test\\tsequence\"", + expected: []Item{{STRING, 0, `"test\tsequence"`}}, + }, + { + input: "\"test\\\\.expression1\"", + expected: []Item{{STRING, 0, `"test\\.expression1"`}}, + }, + { + input: "\"test\\.expression2\"", + expected: []Item{ + {ERROR, 0, "unknown escape sequence U+002E '.'"}, + {STRING, 0, `"test\.expression2"`}, + }, + }, + { + input: "`test\\.expression3`", + expected: []Item{{QUOTED_STRING, 0, "`test\\.expression3`"}}, + }, + { + input: "\".٩\"", + expected: []Item{{STRING, 0, `".٩"`}}, + }, + + { + input: "\"中文\"", + expected: []Item{{STRING, 0, `"中文"`}}, + }, + + { + input: "`中文`", + expected: []Item{{QUOTED_STRING, 0, "`中文`"}}, + }, + { + input: "''", + expected: []Item{{STRING, 0, "''"}}, + }, + + { + input: `""`, + expected: []Item{{STRING, 0, `""`}}, + }, + + { + input: `'''this +is +' +string'''`, + expected: []Item{ + {MULTILINE_STRING, 0, `'''this +is +' +string'''`}, + }, + }, + }, + }, +} + +// TestLexer tests basic functionality of the lexer. More elaborate tests are implemented +// for the parser to avoid duplicated effort. +func TestLexer(t *testing.T) { + for _, typ := range cases { + t.Run(typ.name, func(t *testing.T) { + for i, test := range typ.tests { + l := &Lexer{ + input: test.input, + } + + t.Logf("%s[%d]: input %q", typ.name, i, test.input) + + var out []Item + + for l.state = lexStatements; l.state != nil; { + out = append(out, Item{}) + + l.NextItem(&out[len(out)-1]) + } + + lastItem := out[len(out)-1] // ignore last EOF item + if test.fail { + hasError := false + for _, item := range out { + if item.Typ == ERROR { + hasError = true + } + } + if !hasError { + t.Fatalf("expected lexing error but did not fail: got\n%s", outStr(out)) + } + continue + } + + if lastItem.Typ == ERROR { // ERROR usually be the last item + t.Logf("%d: input %q", i, test.input) + t.Fatalf("unexpected lexing error at position %d: %s", lastItem.Pos, lastItem) + } + + eofItem := Item{EOF, token.Pos(len(test.input)), ""} + assert.Equal(t, eofItem, lastItem) + + out = out[:len(out)-1] + assert.Equal(t, test.expected, out) + } + }) + } +} + +func outStr(items []Item) string { + strs := []string{} + for _, item := range items { + strs = append(strs, item.lexStr()) + } + + return strings.Join(strs, "\n") +} + +func TestUTF8(t *testing.T) { + cases := []struct { + in []byte + }{ + { + in: []byte("abc中文def"), + }, + } + + for _, tc := range cases { + for len(tc.in) > 0 { + r, n := utf8.DecodeRune(tc.in) + t.Logf("r: %c(%02x, %d), n: %d", r, r, utf8.RuneLen(r), n) + tc.in = tc.in[n:] + } + } +} diff --git a/pkg/v2/parser/parser.go b/pkg/v2/parser/parser.go new file mode 100644 index 0000000..a3891fd --- /dev/null +++ b/pkg/v2/parser/parser.go @@ -0,0 +1,588 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the MIT License. +// This product includes software developed at Guance Cloud (https://www.guance.com/). +// Copyright 2021-present Guance, Inc. +// +// ==================================================================================== +// Copyright 2015 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package parser + +import ( + "errors" + "fmt" + "os" + "runtime" + "strconv" + "strings" + "sync" + + "github.com/GuanceCloud/platypus/internal/logger" + "github.com/GuanceCloud/platypus/pkg/errchain" + "github.com/GuanceCloud/platypus/pkg/v2/ast" + "go.uber.org/zap" + + plToken "github.com/GuanceCloud/platypus/pkg/token" +) + +var log logger.Logger = logger.NewStdoutLogger("iploc", zap.DebugLevel) + +func InitLog(logger logger.Logger) { + log = logger +} + +var parserPool = sync.Pool{ + New: func() interface{} { + return &parser{} + }, +} + +type parser struct { + lex Lexer + yyParser yyParserImpl + + parseResult ast.Stmts + lastClosing plToken.Pos + errs ParseErrors + + inject ItemType + injecting bool + + posCache plToken.PosCache +} + +func (p *parser) InjectItem(typ ItemType) { + if p.injecting { + log.Warnf("current inject is %v, new inject is %v", p.inject, typ) + panic("cannot inject multiple Items into the token stream") + } + + if typ != 0 && (typ <= startSymbolsStart || typ >= startSymbolsEnd) { + log.Warnf("current inject is %v", typ) + panic("cannot inject symbol that isn't start symbol") + } + p.inject = typ + p.injecting = true +} + +var errUnexpected = errors.New("unexpected error") + +func (p *parser) unexpected(context string, expected string) { + var errMsg strings.Builder + + if p.yyParser.lval.item.Typ == ERROR { // do not report lex error twice + return + } + + errMsg.WriteString("unexpected: ") + errMsg.WriteString(p.yyParser.lval.item.desc()) + + if context != "" { + errMsg.WriteString(" in: ") + errMsg.WriteString(context) + } + + if expected != "" { + errMsg.WriteString(", expected: ") + errMsg.WriteString(expected) + } + + p.addParseErr(p.yyParser.lval.item.PositionRange(), errors.New(errMsg.String())) +} + +func (p *parser) recover(errp *error) { + e := recover() //nolint: ifshort + if _, ok := e.(runtime.Error); ok { + buf := make([]byte, 64<<10) // 64k + buf = buf[:runtime.Stack(buf, false)] + fmt.Fprintf(os.Stderr, "parser panic: %v\n%s", e, buf) + *errp = errUnexpected + } else if e != nil { + if x, ok := e.(error); ok { + *errp = x + } + } +} + +func (p *parser) addParseErr(pr *PositionRange, err error) { + p.errs = append(p.errs, ParseError{ + Pos: pr, + Err: err, + Query: p.lex.input, + }) +} + +func (p *parser) addParseErrf(pr *PositionRange, format string, args ...interface{}) { + p.addParseErr(pr, fmt.Errorf(format, args...)) +} + +func (p *parser) pos(item Item) plToken.LnColPos { + return p.posCache.LnCol(item.Pos) +} + +func (p *parser) unquoteString(s string) string { + unq, err := Unquote(s) + if err != nil { + p.addParseErrf(p.yyParser.lval.item.PositionRange(), + "error unquoting string %q: %s", s, err) + return "" + } + return unq +} + +func (p *parser) unquoteMultilineString(s string) string { + unq, err := UnquoteMultiline(s) + if err != nil { + p.addParseErrf(p.yyParser.lval.item.PositionRange(), + "error unquoting multiline string %q: %s", s, err) + return "" + } + return unq +} + +// data_type +func (p *parser) newBuiltinType(name Item) ast.Node { + var dtyp ast.DType + switch name.Typ { + case BOOL: + dtyp = ast.Bool + case INT: + dtyp = ast.Int + case FLOAT: + dtyp = ast.Float + case STR: + dtyp = ast.String + case ANY: + dtyp = ast.Any + case LIST: + dtyp = ast.List + case MAP: + dtyp = ast.Map + default: + p.addParseErrf(p.yyParser.lval.item.PositionRange(), + "error data type") + return nil + } + return &ast.TypeBasic{ + DType: dtyp, + Pos: p.pos(name), + } +} + +// literal + +func (p *parser) newBoolLiteral(pos plToken.Pos, val bool) ast.Node { + return &ast.BoolLiteral{ + Val: val, + Start: p.posCache.LnCol(pos), + } +} + +func (p *parser) newNilLiteral(pos plToken.Pos) ast.Node { + return &ast.NilLiteral{ + Start: p.posCache.LnCol(pos), + } +} + +func (p *parser) newIdentifierLiteral(name Item) ast.Node { + return &ast.Identifier{ + Name: name.Val, + Start: p.posCache.LnCol(name.Pos), + } +} + +func (p *parser) newStringLiteral(val Item) ast.Node { + return &ast.StringLiteral{ + Val: val.Val, + Start: p.posCache.LnCol(val.Pos), + } +} + +func (p *parser) newParenExpr(lParen, rParen Item, node ast.Node) ast.Node { + return &ast.ParenExpr{ + Param: node, + LParen: p.posCache.LnCol(lParen.Pos), + RParen: p.posCache.LnCol(rParen.Pos), + } +} + +func (p *parser) newListLiteral(l, r Item, exprs []ast.Node) ast.Node { + return &ast.ListLiteral{ + List: exprs, + LBracket: p.pos(l), + RBracket: p.pos(r), + } +} + +func (p *parser) newMapLiteral(l, r Item, exprs [][2]ast.Node) ast.Node { + return &ast.MapLiteral{ + KeyValeList: exprs, + LBrace: p.pos(l), + RBrace: p.pos(r), + } +} + +func (p *parser) newNumberLiteral(v Item) ast.Node { + if n, err := strconv.ParseInt(v.Val, 0, 64); err != nil { + f, err := strconv.ParseFloat(v.Val, 64) + if err != nil { + p.addParseErrf(p.yyParser.lval.item.PositionRange(), + "error parsing number: %s", err) + return nil + } + return &ast.FloatLiteral{ + Val: f, + Start: p.posCache.LnCol(v.Pos), + } + } else { + return &ast.IntegerLiteral{ + Val: n, + Start: p.posCache.LnCol(v.Pos), + } + } +} + +func (p *parser) newFnParam(id ast.Node, typ ast.Node, val ast.Node, varb ...bool) ast.FnParam { + v := false + if len(varb) > 0 && varb[0] { + v = true + } + return ast.FnParam{ + Name: id, + DType: typ, + DefaultVal: val, + Varb: v, + } +} + +func (p *parser) newReturnStmt(pos Item, exprs []ast.Node) ast.Node { + return &ast.ReturnStmt{ + ReturnPos: p.pos(pos), + Exprs: exprs, + } +} + +func (p *parser) newFnDefStmt(fn Item, name ast.Node, params []ast.FnParam, results []ast.Node, body *ast.BlockStmt) ast.Node { + return &ast.FnDefStmt{ + FnPos: p.pos(fn), + Name: name, + FnType: &ast.TypeFn{ + Params: params, + Results: results, + }, + Block: body, + } +} + +func (p *parser) newBlockStmt(lBrace, rBrace Item, stmts ast.Stmts) *ast.BlockStmt { + return &ast.BlockStmt{ + LBracePos: p.posCache.LnCol(lBrace.Pos), + Stmts: stmts, + RBracePos: p.posCache.LnCol(rBrace.Pos), + } +} + +func (p *parser) newBreakStmt(pos plToken.Pos) ast.Node { + return &ast.BreakStmt{ + Start: p.posCache.LnCol(pos), + } +} + +func (p *parser) newContinueStmt(pos plToken.Pos) ast.Node { + return &ast.ContinueStmt{ + Start: p.posCache.LnCol(pos), + } +} + +func (p *parser) newForStmt(forTK Item, initExpr, condExpr, loopExpr ast.Node, body *ast.BlockStmt) ast.Node { + return &ast.ForStmt{ + Init: initExpr, + Loop: loopExpr, + Cond: condExpr, + Body: body, + + ForPos: p.pos(forTK), + } +} + +func (p *parser) newForInStmt(forTk Item, inExpr ast.Node, body *ast.BlockStmt) ast.Node { + return &ast.ForInStmt{ + InExpr: inExpr, + Body: body, + ForPos: p.pos(forTk), + } +} + +func (p *parser) newIfElifStmt(ifElifList []*ast.IfStmtElem) ast.Node { + if len(ifElifList) == 0 { + p.addParseErrf(p.yyParser.lval.item.PositionRange(), "invalid ifelse stmt is empty") + return nil + } + + return &ast.IfelseStmt{ + IfList: ast.IfList(ifElifList), + } +} + +func (p *parser) newIfElifelseStmt(ifElifList []*ast.IfStmtElem, + elseTk Item, elseElem *ast.BlockStmt, +) ast.Node { + if len(ifElifList) == 0 { + p.addParseErrf(p.yyParser.lval.item.PositionRange(), "invalid ifelse stmt is empty") + return nil + } + + return &ast.IfelseStmt{ + IfList: ast.IfList(ifElifList), + Else: elseElem, + ElsePos: p.posCache.LnCol(elseTk.Pos), + } +} + +func (p *parser) newIfElem(ifTk Item, condition ast.Node, block *ast.BlockStmt) *ast.IfStmtElem { + if condition == nil { + p.addParseErrf(p.yyParser.lval.item.PositionRange(), "invalid if/elif condition") + return nil + } + + ifElem := &ast.IfStmtElem{ + Condition: condition, + Block: block, + Start: p.posCache.LnCol(ifTk.Pos), + } + + return ifElem +} + +func (p *parser) newUnaryExpr(op Item, r ast.Node) ast.Node { + return &ast.UnaryExpr{ + Op: AstOp(op.Typ), + RHS: r, + OpPos: p.pos(op), + } +} + +func (p *parser) newAssignmentStmt(l, r []ast.Node, op Item) ast.Node { + return &ast.AssignmentStmt{ + LHS: l, + Op: AstOp(op.Typ), + RHS: r, + OpPos: p.posCache.LnCol(op.Pos), + } +} + +func (p *parser) newInExpr(l, r ast.Node, inOp Item) ast.Node { + return &ast.InExpr{ + LHS: l, + Op: ast.IN, + RHS: r, + OpPos: p.posCache.LnCol(inOp.Pos), + } +} + +func (p *parser) newConditionalExpr(l, r ast.Node, op Item) ast.Node { + return &ast.ConditionalExpr{ + RHS: r, + LHS: l, + Op: AstOp(op.Typ), + OpPos: p.posCache.LnCol(op.Pos), + } +} + +func (p *parser) newArithmeticExpr(l, r ast.Node, op Item) ast.Node { + return &ast.ArithmeticExpr{ + RHS: r, + LHS: l, + Op: AstOp(op.Typ), + + OpPos: p.posCache.LnCol(op.Pos), + } +} + +func (p *parser) newAttrExpr(obj, attr ast.Node) ast.Node { + pos := p.yyParser.lval.item.PositionRange() + + return &ast.AttrExpr{ + Obj: obj, + Attr: attr, + Start: p.posCache.LnCol(pos.Start), + } +} + +func (p *parser) newIndexExpr(lBracket, rBracket Item, obj, index ast.Node, dot ...Item) ast.Node { + var dotPos plToken.LnColPos + if len(dot) == 1 { + dotPos = p.pos(dot[0]) + } + return &ast.IndexExpr{ + Obj: obj, + Index: index, + Dot: dotPos, + LBracket: p.pos(lBracket), + RBracket: p.pos(rBracket), + } +} + +func (p *parser) newCallExpr(lParen, rParen Item, fn ast.Node, args []ast.Node) ast.Node { + + f := &ast.CallExpr{ + Obj: fn, + Param: args, + LParen: p.posCache.LnCol(lParen.Pos), + RParen: p.posCache.LnCol(rParen.Pos), + } + + return f +} +func (p *parser) newSliceExpr(l, r Item, obj, start, end, step ast.Node) ast.Node { + return &ast.SliceExpr{ + Obj: obj, + Start: start, + End: end, + Step: step, + LBracket: p.pos(l), + RBracket: p.pos(r), + } +} + +func (p *parser) newImportStmt(i Item, name []ast.Node, as ast.Node) ast.Node { + var names []*ast.Identifier + for v := range name { + if v, ok := name[v].(*ast.Identifier); ok { + names = append(names, v) + } else { + p.addParseErrf(p.yyParser.lval.item.PositionRange(), "invalid import statement") + return nil + } + } + + var asName *ast.Identifier + if as != nil { + if v, ok := as.(*ast.Identifier); ok { + asName = v + } else { + p.addParseErrf(p.yyParser.lval.item.PositionRange(), "invalid import statement") + return nil + } + } + + return &ast.ImportStmt{ + ImportPos: p.pos(i), + Name: names, + AsName: asName, + } +} + +func (p *parser) newConstDefStmt(c Item, name, value ast.Node) ast.Node { + return &ast.ConstDefStmt{ + ConstPos: p.pos(c), + Name: name, + Value: value, + } +} + +func (p *parser) newLetStmt(v Item, name, typ, value ast.Node) ast.Node { + return &ast.LetStmt{ + LetPos: p.pos(v), + Name: name.(*ast.Identifier), + Type: typ, + Value: value, + } +} + +// end of yylex.(*parser).newXXXX + +// impl Lex interface. +func (p *parser) Lex(lval *yySymType) int { + var typ ItemType + + if p.injecting { + p.injecting = false + return int(p.inject) + } + + for { // skip comment + p.lex.NextItem(&lval.item) + typ = lval.item.Typ + if typ != COMMENT { + break + } + } + + switch typ { + case ERROR: + pos := PositionRange{ + Start: p.lex.start, + End: plToken.Pos(len(p.lex.input)), + } + + p.addParseErr(&pos, errors.New(p.yyParser.lval.item.Val)) + return 0 // tell yacc it's the end of input + + case EOF: + lval.item.Typ = EOF + p.InjectItem(0) + case RIGHT_PAREN: + p.lastClosing = lval.item.Pos + plToken.Pos(len(lval.item.Val)) + } + return int(typ) +} + +func (p *parser) Error(e string) {} + +func newParser(input string) *parser { + p, ok := parserPool.Get().(*parser) + if !ok { + return nil + } + + p.injecting = false + p.errs = nil + p.parseResult = nil + p.lex = Lexer{ + input: input, + state: lexStatements, + } + p.posCache = *plToken.NewPosCache(input) + return p +} + +func ParsePipeline(name, input string) (res ast.Stmts, err error) { + p := newParser(input) + defer parserPool.Put(p) + defer p.recover(&err) + + p.InjectItem(START_STMTS) + p.yyParser.Parse(p) + + if len(p.errs) != 0 { + err = conv2PlError(name, p.errs, &p.posCache) + return + } + + if p.parseResult != nil { + res = p.parseResult + } + + return res, err +} + +func conv2PlError(name string, errs ParseErrors, posCache *plToken.PosCache) *errchain.PlError { + if len(errs) > 0 { + pos := posCache.LnCol(errs[0].Pos.Start) + return errchain.NewErr(name, pos, errs[0].Err.Error()) + } + + return nil +} diff --git a/pkg/v2/parser/parser_test.go b/pkg/v2/parser/parser_test.go new file mode 100644 index 0000000..de68799 --- /dev/null +++ b/pkg/v2/parser/parser_test.go @@ -0,0 +1,1791 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the MIT License. +// This product includes software developed at Guance Cloud (https://www.guance.com/). +// Copyright 2021-present Guance, Inc. +// +// ==================================================================================== +// Copyright 2015 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package parser + +import ( + "testing" + + "github.com/GuanceCloud/platypus/pkg/v2/ast" + "github.com/stretchr/testify/assert" +) + +func TestExprSeparation(t *testing.T) { + cases := []struct { + name string + in string + expected ast.Stmts + err string + fail bool + }{ + { + name: "test_if_nl", + in: ` + + # 0 + [ + + 1, 3, + "3", + true, + 1.] + + [ + 1, 3, + "3", + true, + 1. + ] + + # 只支持基础数据类型 + [1, 3, "3", true, 1. , + [1, 3, "3", true, 1. + ], {} + ] + + a = 1; func1() + func2(1, 3, + "3", true, 1. + + ) + if true { + ; + } + + #2 + if true { + + } elif false { + } elif x == y { a = + a + 1 } + a = b; a=c + a =d + + #3 + if true { + } elif false { + } elif x == y { + a = + a + + 1 + } else { + + } + `, + expected: ast.Stmts{ + &ast.ListLiteral{ + List: []ast.Node{ + &ast.IntegerLiteral{Val: 1}, + &ast.IntegerLiteral{Val: 3}, + &ast.StringLiteral{Val: "3"}, + &ast.BoolLiteral{Val: true}, + &ast.FloatLiteral{Val: 1.}, + }, + }, + + &ast.ListLiteral{ + List: []ast.Node{ + &ast.IntegerLiteral{Val: 1}, + &ast.IntegerLiteral{Val: 3}, + &ast.StringLiteral{Val: "3"}, + &ast.BoolLiteral{Val: true}, + &ast.FloatLiteral{Val: 1.}, + }, + }, + + &ast.ListLiteral{ + List: []ast.Node{ + &ast.IntegerLiteral{Val: 1}, + &ast.IntegerLiteral{Val: 3}, + &ast.StringLiteral{Val: "3"}, + &ast.BoolLiteral{Val: true}, + &ast.FloatLiteral{Val: 1.}, + + &ast.ListLiteral{ + List: []ast.Node{ + &ast.IntegerLiteral{Val: 1}, + &ast.IntegerLiteral{Val: 3}, + &ast.StringLiteral{Val: "3"}, + &ast.BoolLiteral{Val: true}, + &ast.FloatLiteral{Val: 1.}, + }, + }, + &ast.MapLiteral{}, + }, + }, + &ast.AssignmentStmt{ + Op: ast.EQ, + LHS: []ast.Node{&ast.Identifier{Name: "a"}}, + RHS: []ast.Node{&ast.IntegerLiteral{Val: 1}}, + }, + &ast.CallExpr{Obj: &ast.Identifier{Name: "func1"}}, + &ast.CallExpr{ + Obj: &ast.Identifier{Name: "func2"}, + Param: ast.FuncArgList{ + &ast.IntegerLiteral{Val: 1}, + &ast.IntegerLiteral{Val: 3}, + &ast.StringLiteral{Val: "3"}, + &ast.BoolLiteral{Val: true}, + &ast.FloatLiteral{Val: 1.}, + }, + }, + &ast.IfelseStmt{ + IfList: []*ast.IfStmtElem{ + {Condition: &ast.BoolLiteral{Val: true}, + Block: &ast.BlockStmt{}}, + }, + }, + + &ast.IfelseStmt{ + IfList: []*ast.IfStmtElem{ + {Condition: &ast.BoolLiteral{Val: true}, + Block: &ast.BlockStmt{}}, + {Condition: &ast.BoolLiteral{Val: false}, + Block: &ast.BlockStmt{}}, + { + Condition: &ast.ConditionalExpr{ + LHS: &ast.Identifier{Name: "x"}, + Op: AstOp(EQEQ), + RHS: &ast.Identifier{Name: "y"}, + }, + Block: &ast.BlockStmt{Stmts: ast.Stmts{ + &ast.AssignmentStmt{ + Op: ast.EQ, + LHS: []ast.Node{&ast.Identifier{Name: "a"}}, + RHS: []ast.Node{&ast.ArithmeticExpr{ + LHS: &ast.Identifier{Name: "a"}, + RHS: &ast.IntegerLiteral{Val: 1}, + Op: AstOp(ADD), + }}, + }, + }}, + }, + }, + }, + + &ast.AssignmentStmt{ + Op: ast.EQ, + LHS: []ast.Node{&ast.Identifier{Name: "a"}}, + RHS: []ast.Node{&ast.Identifier{Name: "b"}}, + }, + &ast.AssignmentStmt{ + Op: ast.EQ, + LHS: []ast.Node{&ast.Identifier{Name: "a"}}, + RHS: []ast.Node{&ast.Identifier{Name: "c"}}, + }, + &ast.AssignmentStmt{ + Op: ast.EQ, + LHS: []ast.Node{&ast.Identifier{Name: "a"}}, + RHS: []ast.Node{&ast.Identifier{Name: "d"}}, + }, + + &ast.IfelseStmt{ + IfList: []*ast.IfStmtElem{ + {Condition: &ast.BoolLiteral{Val: true}, + Block: &ast.BlockStmt{}}, + {Condition: &ast.BoolLiteral{Val: false}, + Block: &ast.BlockStmt{}}, + { + Condition: &ast.ConditionalExpr{ + LHS: &ast.Identifier{Name: "x"}, + Op: AstOp(EQEQ), + RHS: &ast.Identifier{Name: "y"}, + }, + Block: &ast.BlockStmt{Stmts: ast.Stmts{ + &ast.AssignmentStmt{ + Op: ast.EQ, + LHS: []ast.Node{&ast.Identifier{Name: "a"}}, + RHS: []ast.Node{&ast.ArithmeticExpr{ + LHS: &ast.Identifier{Name: "a"}, + RHS: &ast.IntegerLiteral{Val: 1}, + Op: AstOp(ADD), + }}, + }, + }}, + }, + }, + Else: nil, + }, + }, + }, + { + name: "+||", + in: "a * 1 + b || x + 1 && 1 / 2 == 1", + expected: ast.Stmts{ + &ast.ConditionalExpr{ + Op: AstOp(EQEQ), + LHS: &ast.ConditionalExpr{ + Op: AstOp(OR), + LHS: &ast.ArithmeticExpr{ + Op: AstOp(ADD), + LHS: &ast.ArithmeticExpr{ + Op: AstOp(MUL), + LHS: &ast.Identifier{Name: "a"}, + RHS: &ast.IntegerLiteral{Val: 1}, + }, + RHS: &ast.Identifier{Name: "b"}, + }, + RHS: &ast.ConditionalExpr{ + Op: AstOp(AND), + LHS: &ast.ArithmeticExpr{ + Op: AstOp(ADD), + LHS: &ast.Identifier{Name: "x"}, + RHS: &ast.IntegerLiteral{Val: 1}, + }, + RHS: &ast.ArithmeticExpr{ + Op: AstOp(DIV), + LHS: &ast.IntegerLiteral{Val: 1}, + RHS: &ast.IntegerLiteral{Val: 2}, + }, + }, + }, + RHS: &ast.IntegerLiteral{Val: 1}, + }, + }, + }, + { + name: "+||", + in: `a * -1 + b || x + 1 && 1 / 2 == 1 + a += b + +!-1 + a -= 1 + a *= 1 + a /= 1 + a %= 1 + `, + expected: ast.Stmts{ + + &ast.ConditionalExpr{ + Op: AstOp(EQEQ), + LHS: &ast.ConditionalExpr{ + Op: AstOp(OR), + LHS: &ast.ArithmeticExpr{ + Op: AstOp(ADD), + LHS: &ast.ArithmeticExpr{ + Op: AstOp(MUL), + LHS: &ast.Identifier{Name: "a"}, + RHS: &ast.IntegerLiteral{Val: -1}, + }, + RHS: &ast.Identifier{Name: "b"}, + }, + RHS: &ast.ConditionalExpr{ + Op: AstOp(AND), + LHS: &ast.ArithmeticExpr{ + Op: AstOp(ADD), + LHS: &ast.Identifier{Name: "x"}, + RHS: &ast.IntegerLiteral{Val: 1}, + }, + RHS: &ast.ArithmeticExpr{ + Op: AstOp(DIV), + LHS: &ast.IntegerLiteral{Val: 1}, + RHS: &ast.IntegerLiteral{Val: 2}, + }, + }, + }, + RHS: &ast.IntegerLiteral{Val: 1}, + }, + + &ast.AssignmentStmt{ + Op: ast.ADDEQ, + LHS: []ast.Node{&ast.Identifier{ + Name: "a", + }}, + RHS: []ast.Node{ + &ast.ArithmeticExpr{ + Op: ast.ADD, + LHS: &ast.Identifier{Name: "b"}, + RHS: &ast.UnaryExpr{ + Op: ast.ADD, + RHS: &ast.UnaryExpr{ + Op: ast.NOT, + RHS: &ast.IntegerLiteral{Val: -1}, + }, + }, + }, + }, + }, + + &ast.AssignmentStmt{ + Op: ast.SUBEQ, + LHS: []ast.Node{&ast.Identifier{ + Name: "a", + }}, + RHS: []ast.Node{&ast.IntegerLiteral{ + Val: 1, + }}, + }, + &ast.AssignmentStmt{ + Op: ast.MULEQ, + LHS: []ast.Node{&ast.Identifier{ + Name: "a", + }}, + RHS: []ast.Node{&ast.IntegerLiteral{ + Val: 1, + }}, + }, + &ast.AssignmentStmt{ + Op: ast.DIVEQ, + LHS: []ast.Node{&ast.Identifier{ + Name: "a", + }}, + RHS: []ast.Node{&ast.IntegerLiteral{ + Val: 1, + }}, + }, + &ast.AssignmentStmt{ + Op: ast.MODEQ, + LHS: []ast.Node{&ast.Identifier{ + Name: "a", + }}, + RHS: []ast.Node{&ast.IntegerLiteral{ + Val: 1, + }}, + }, + }, + }, + } + + // for idx := len(cases) - 1; idx >= 0; idx-- { + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + Stmts, err := ParsePipeline("", tc.in) + + if !tc.fail { + assert.Equal(t, err, nil) + } else { + t.Logf("expected error: %s", err) + assert.NotNil(t, err, "") + return + } + + if !tc.fail { + var x, y string + y = Stmts.String() + x = tc.expected.String() + assert.Nil(t, err) + assert.Equal(t, x, y) + // t.Logf("ok %s -> %s", tc.in, y) + } else { + t.Logf("%s -> expect fail: %v", tc.in, err) + assert.NotNil(t, err, "") + } + }) + } +} + +func TestParserFor(t *testing.T) { + cases := []struct { + name string + in string + expected ast.Stmts + err string + fail bool + }{ + { + name: "for_x_in_y", + in: `for x in y { + b = 1 + }`, + expected: ast.Stmts{ + &ast.ForInStmt{ + InExpr: &ast.InExpr{ + LHS: &ast.Identifier{Name: "x"}, + RHS: &ast.Identifier{Name: "y"}, + }, + Body: &ast.BlockStmt{Stmts: ast.Stmts{ + &ast.AssignmentStmt{ + Op: ast.EQ, + LHS: []ast.Node{&ast.Identifier{Name: "b"}}, + RHS: []ast.Node{&ast.IntegerLiteral{Val: 1}}, + }, + }}, + }, + }, + }, + { + name: "for_x_in_y", + in: `for x in [1,2.,"2"] { + if x != "2" { + continue } else { + break + } + a = a + 1 + }`, + expected: ast.Stmts{ + &ast.ForInStmt{ + InExpr: &ast.InExpr{ + LHS: &ast.Identifier{Name: "x"}, + RHS: &ast.ListLiteral{ + List: []ast.Node{ + &ast.IntegerLiteral{Val: 1}, + &ast.FloatLiteral{Val: 2.}, + &ast.StringLiteral{Val: "2"}, + }, + }, + }, + Body: &ast.BlockStmt{Stmts: ast.Stmts{ + &ast.IfelseStmt{ + IfList: []*ast.IfStmtElem{ + { + Condition: &ast.ConditionalExpr{ + LHS: &ast.Identifier{Name: "x"}, + Op: AstOp(NEQ), + RHS: &ast.StringLiteral{Val: "2"}, + }, + Block: &ast.BlockStmt{Stmts: ast.Stmts{ + &ast.ContinueStmt{}, + }}, + }, + }, + Else: &ast.BlockStmt{Stmts: ast.Stmts{ + &ast.BreakStmt{}, + }}, + }, + &ast.AssignmentStmt{ + Op: ast.EQ, + LHS: []ast.Node{&ast.Identifier{Name: "a"}}, + RHS: []ast.Node{&ast.ArithmeticExpr{ + LHS: &ast.Identifier{Name: "a"}, + Op: AstOp(ADD), + RHS: &ast.IntegerLiteral{Val: 1}, + }}, + }, + }}, + }, + }, + }, + { + name: "for cond ", + in: `for ; a == func() ; { + b = 1 + }`, + expected: ast.Stmts{ + &ast.ForStmt{ + Cond: &ast.ConditionalExpr{ + Op: AstOp(EQEQ), + LHS: &ast.Identifier{Name: "a"}, + RHS: &ast.CallExpr{ + Obj: &ast.Identifier{Name: "func"}, + }, + }, + Body: &ast.BlockStmt{Stmts: ast.Stmts{ + &ast.AssignmentStmt{ + Op: ast.EQ, + LHS: []ast.Node{&ast.Identifier{Name: "b"}}, + RHS: []ast.Node{&ast.IntegerLiteral{Val: 1}}, + }, + }}, + }, + }, + }, + { + name: "for_; cond ; loop ", + in: `for ; a == func() ; x = 2. { + b=2 + }`, + expected: ast.Stmts{&ast.ForStmt{ + Cond: &ast.ConditionalExpr{ + Op: AstOp(EQEQ), + LHS: &ast.Identifier{Name: "a"}, + RHS: &ast.CallExpr{ + Obj: &ast.Identifier{Name: "func"}, + }, + }, + Loop: &ast.AssignmentStmt{ + Op: ast.EQ, + LHS: []ast.Node{&ast.Identifier{ + Name: "x", + }}, + RHS: []ast.Node{&ast.FloatLiteral{ + Val: 2., + }}, + }, + Body: &ast.BlockStmt{Stmts: ast.Stmts{ + &ast.AssignmentStmt{ + Op: ast.EQ, + LHS: []ast.Node{&ast.Identifier{Name: "b"}}, + RHS: []ast.Node{&ast.IntegerLiteral{Val: 1}}, + }, + }}, + }}, + }, + { + name: "for init; cond ; loop ", + in: `for y=2; a == func() ; x = 2. { + b=2 + }`, + expected: ast.Stmts{&ast.ForStmt{ + Init: &ast.AssignmentStmt{ + Op: ast.EQ, + LHS: []ast.Node{&ast.Identifier{ + Name: "y", + }}, + RHS: []ast.Node{&ast.FloatLiteral{ + Val: 2., + }}, + }, + Cond: &ast.ConditionalExpr{ + Op: AstOp(EQEQ), + LHS: &ast.Identifier{Name: "a"}, + RHS: &ast.CallExpr{ + Obj: &ast.Identifier{Name: "func"}, + }, + }, + Loop: &ast.AssignmentStmt{ + Op: ast.EQ, + LHS: []ast.Node{&ast.Identifier{ + Name: "x", + }}, + RHS: []ast.Node{&ast.FloatLiteral{ + Val: 2., + }}, + }, + Body: &ast.BlockStmt{Stmts: ast.Stmts{ + &ast.AssignmentStmt{ + Op: ast.EQ, + LHS: []ast.Node{&ast.Identifier{Name: "b"}}, + RHS: []ast.Node{&ast.IntegerLiteral{Val: 1}}, + }, + }}, + }}, + }, + } + + // for idx := len(cases) - 1; idx >= 0; idx-- { + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + Stmts, err := ParsePipeline("", tc.in) + + if !tc.fail { + assert.Nil(t, err) + } else { + t.Logf("expected error: %s", err) + assert.NotNil(t, err, "") + return + } + + if !tc.fail { + var x, y string + x = tc.expected.String() + y = Stmts.String() + assert.Nil(t, err) + assert.Equal(t, x, y) + t.Logf("ok %s -> %s", tc.in, y) + } else { + t.Logf("%s -> expect fail: %v", tc.in, err) + assert.NotNil(t, err, "") + } + }) + } +} + +func TestParser(t *testing.T) { + cases := []struct { + name string + in string + expected ast.Stmts + err string + fail bool + }{ + { + name: "if-condition-list-paren2", + in: `if ((a==b) && (a==c)) || a==d { }`, + expected: ast.Stmts{&ast.IfelseStmt{ + IfList: ast.IfList{ + &ast.IfStmtElem{ + Condition: &ast.ConditionalExpr{ + Op: AstOp(OR), + LHS: &ast.ParenExpr{ + Param: &ast.ConditionalExpr{ + Op: AstOp(AND), + LHS: &ast.ParenExpr{ + Param: &ast.ConditionalExpr{ + Op: AstOp(EQEQ), + LHS: &ast.Identifier{Name: "a"}, + RHS: &ast.Identifier{Name: "b"}, + }, + }, + RHS: &ast.ParenExpr{ + Param: &ast.ConditionalExpr{ + Op: AstOp(EQEQ), + LHS: &ast.Identifier{Name: "a"}, + RHS: &ast.Identifier{Name: "c"}, + }, + }, + }, + }, + RHS: &ast.ConditionalExpr{ + Op: AstOp(EQEQ), + LHS: &ast.Identifier{Name: "a"}, + RHS: &ast.Identifier{Name: "d"}, + }, + }, + Block: &ast.BlockStmt{}, + }, + }, + }}, + }, + + { + name: "if-condition-list-paren", + in: `if (a==b) && (a==c) { }`, + expected: ast.Stmts{&ast.IfelseStmt{ + IfList: ast.IfList{&ast.IfStmtElem{ + Block: &ast.BlockStmt{}, + Condition: &ast.ConditionalExpr{ + Op: AstOp(AND), + LHS: &ast.ParenExpr{ + Param: &ast.ConditionalExpr{ + Op: AstOp(EQEQ), + LHS: &ast.Identifier{Name: "a"}, + RHS: &ast.Identifier{Name: "b"}, + }, + }, + RHS: &ast.ParenExpr{ + Param: &ast.ConditionalExpr{ + Op: AstOp(EQEQ), + LHS: &ast.Identifier{Name: "a"}, + RHS: &ast.Identifier{Name: "c"}, + }, + }, + }, + }}, + }}, + }, + + { + name: "if-condition-list", + in: `if a==b && a==c { }`, + expected: ast.Stmts{ + &ast.IfelseStmt{ + IfList: ast.IfList{ + &ast.IfStmtElem{ + Block: &ast.BlockStmt{}, + Condition: &ast.ConditionalExpr{ + Op: AstOp(AND), + LHS: &ast.ConditionalExpr{ + Op: AstOp(EQEQ), + LHS: &ast.Identifier{Name: "a"}, + RHS: &ast.Identifier{Name: "b"}, + }, + RHS: &ast.ConditionalExpr{ + Op: AstOp(EQEQ), + LHS: &ast.Identifier{Name: "a"}, + RHS: &ast.Identifier{Name: "c"}, + }, + }, + }, + }, + }, + }, + }, + + { + name: "if-error-non-condition", + in: `if { }`, + fail: true, + }, + + { + name: "if-elif-error-non-condition", + in: ` + if key=="11" { + + } elif { + + }`, + fail: true, + }, + + { + name: "if-elif-elif-error-non-condition", + in: ` + if key=="11" { + + } elif key=="22" { + + } elif { + + }`, + fail: true, + }, + + { + name: "if-elif-else-expr", + in: ` + if key=="11" { + g1(arg) + } elif key=="22" { + g2(arg) + } else { + g3(arg) + }`, + expected: ast.Stmts{&ast.IfelseStmt{ + IfList: ast.IfList{ + &ast.IfStmtElem{ + Condition: &ast.ConditionalExpr{ + Op: AstOp(EQEQ), + LHS: &ast.Identifier{Name: "key"}, + RHS: &ast.StringLiteral{Val: "11"}, + }, + Block: &ast.BlockStmt{Stmts: ast.Stmts{ + &ast.CallExpr{ + Obj: &ast.Identifier{Name: "g1"}, + Param: []ast.Node{ + &ast.Identifier{Name: "arg"}}, + }, + }}, + }, + &ast.IfStmtElem{ + Condition: &ast.ConditionalExpr{ + Op: AstOp(EQEQ), + LHS: &ast.Identifier{Name: "key"}, + RHS: &ast.StringLiteral{Val: "22"}, + }, + Block: &ast.BlockStmt{Stmts: ast.Stmts{&ast.CallExpr{ + Obj: &ast.Identifier{Name: "g2"}, + Param: []ast.Node{ + &ast.Identifier{Name: "arg"}}, + }}}, + }, + }, + Else: &ast.BlockStmt{Stmts: ast.Stmts{ + &ast.CallExpr{ + Obj: &ast.Identifier{Name: "g3"}, + Param: []ast.Node{ + &ast.Identifier{Name: "arg"}, + }, + }, + }}, + }}, + }, + + { + name: "if-elif-expr", + in: ` + if key=="11" { + g1(arg) + } elif key=="22" { + g2(arg) + }`, + expected: ast.Stmts{ + &ast.IfelseStmt{ + IfList: ast.IfList{ + &ast.IfStmtElem{ + Condition: &ast.ConditionalExpr{ + Op: AstOp(EQEQ), + LHS: &ast.Identifier{Name: "key"}, + RHS: &ast.StringLiteral{Val: "11"}, + }, + Block: &ast.BlockStmt{Stmts: ast.Stmts{&ast.CallExpr{ + Obj: &ast.Identifier{Name: "g1"}, + Param: []ast.Node{ + &ast.Identifier{Name: "arg"}, + }, + }}}, + }, + &ast.IfStmtElem{ + Condition: &ast.ConditionalExpr{ + Op: AstOp(EQEQ), + LHS: &ast.Identifier{Name: "key"}, + RHS: &ast.StringLiteral{Val: "22"}, + }, + Block: &ast.BlockStmt{Stmts: ast.Stmts{ + &ast.CallExpr{ + Obj: &ast.Identifier{Name: "g2"}, + Param: []ast.Node{ + &ast.Identifier{Name: "arg"}}, + }, + }}, + }, + }, + }, + }, + }, + + { + name: "if-elif-else-non-ast.Stmts", + in: ` + if key=="11"{ + + } elif key=="22" { + + } else { + + }`, + expected: ast.Stmts{&ast.IfelseStmt{ + IfList: ast.IfList{ + &ast.IfStmtElem{ + Block: &ast.BlockStmt{}, + Condition: &ast.ConditionalExpr{ + Op: AstOp(EQEQ), + LHS: &ast.Identifier{Name: "key"}, + RHS: &ast.StringLiteral{Val: "11"}, + }, + }, + &ast.IfStmtElem{ + Block: &ast.BlockStmt{}, + Condition: &ast.ConditionalExpr{ + Op: AstOp(EQEQ), + LHS: &ast.Identifier{Name: "key"}, + RHS: &ast.StringLiteral{Val: "22"}, + }}, + }, + Else: &ast.BlockStmt{Stmts: ast.Stmts{}}, + }}, + }, + + { + name: "if-elif-non-ast.Stmts", + in: ` + if key=="11" { + + } elif key=="22" { + + }`, + expected: ast.Stmts{&ast.IfelseStmt{ + IfList: ast.IfList{ + &ast.IfStmtElem{ + Block: &ast.BlockStmt{}, + Condition: &ast.ConditionalExpr{ + Op: AstOp(EQEQ), + LHS: &ast.Identifier{Name: "key"}, + RHS: &ast.StringLiteral{Val: "11"}, + }}, + &ast.IfStmtElem{ + Block: &ast.BlockStmt{}, + Condition: &ast.ConditionalExpr{ + Op: AstOp(EQEQ), + LHS: &ast.Identifier{Name: "key"}, + RHS: &ast.StringLiteral{Val: "22"}, + }}, + }, + }}, + }, + + { + name: "if-expr-non-ast.Stmts", + in: `if key=="11" { }`, + expected: ast.Stmts{ + &ast.IfelseStmt{ + IfList: ast.IfList{&ast.IfStmtElem{ + Block: &ast.BlockStmt{}, + Condition: &ast.ConditionalExpr{ + Op: AstOp(EQEQ), + LHS: &ast.Identifier{Name: "key"}, + RHS: &ast.StringLiteral{Val: "11"}, + }, + }}, + }, + }, + }, + { + name: "if-else-expr-non-ast.Stmts", + in: ` + if key=="11" { + + } else { + + }`, + expected: ast.Stmts{ + &ast.IfelseStmt{ + IfList: ast.IfList{ + &ast.IfStmtElem{ + Block: &ast.BlockStmt{}, + Condition: &ast.ConditionalExpr{ + Op: AstOp(EQEQ), + LHS: &ast.Identifier{Name: "key"}, + RHS: &ast.StringLiteral{Val: "11"}, + }, + }, + }, + }, + }, + }, + + { + name: "if-expr-non-ast.Stmts", + in: `if key=="11" { }`, + expected: ast.Stmts{ + &ast.IfelseStmt{ + IfList: ast.IfList{&ast.IfStmtElem{ + Block: &ast.BlockStmt{}, + Condition: &ast.ConditionalExpr{ + Op: AstOp(EQEQ), + LHS: &ast.Identifier{Name: "key"}, + RHS: &ast.StringLiteral{Val: "11"}, + }, + }}, + }, + }, + }, + + { + name: "if-else-expr", + in: `if key=="11" { g1(arg); g2(arg) } else { h(arg) } #ddwwdw `, + expected: ast.Stmts{ + &ast.IfelseStmt{ + IfList: ast.IfList{ + &ast.IfStmtElem{ + Condition: &ast.ConditionalExpr{ + Op: AstOp(EQEQ), + LHS: &ast.Identifier{Name: "key"}, + RHS: &ast.StringLiteral{Val: "11"}, + }, + Block: &ast.BlockStmt{Stmts: ast.Stmts{ + &ast.CallExpr{ + Obj: &ast.Identifier{Name: "g1"}, + Param: []ast.Node{ + + &ast.Identifier{Name: "arg"}, + }, + }, + &ast.CallExpr{ + Obj: &ast.Identifier{Name: "g2"}, + Param: []ast.Node{ + &ast.Identifier{Name: "arg"}, + }, + }, + }}, + }, + }, + Else: &ast.BlockStmt{Stmts: ast.Stmts{ + &ast.CallExpr{ + Obj: &ast.Identifier{Name: "h"}, + Param: []ast.Node{ + &ast.Identifier{Name: "arg"}, + }, + }, + }}, + }, + }, + }, + // { + // name: "if-else-expr", + // in: `if match(_,"./*")=="11" { g1(arg) g2(arg) } else { h(arg) }`, + // expected: ast.Stmts{ + // &ast.IfelseStmt{ + // ast.IfList: ast.IfList{ + // &IfExpr{ + // Condition: &ast.ConditionalExpr{ + // Op: AstOp(EQEQ), + // LHS: &ast.Identifier{Name: "match(_, './*')"}, + // RHS: &ast.StringLiteral{Val: "11"}, + // }, + // ast.Stmts: ast.Stmts{ + // &FuncStmt{ + // Name: "g1", + // Param: []ast.Node{&ast.Identifier{Name: "arg"}}, + // }, + // &FuncStmt{ + // Name: "g2", + // Param: []ast.Node{&ast.Identifier{Name: "arg"}}, + // }, + // }, + // }, + // }, + // Else: ast.Stmts{ + // &FuncStmt{ + // Name: "h", + // Param: []ast.Node{&ast.Identifier{Name: "arg"}}, + // }, + // }, + // }, + // }, + // }, + + { + name: "if-else-expr-newline", + in: ` + if key=="11" { #11aa + g(arg) } else { + + + h(arg) + }`, + expected: ast.Stmts{ + &ast.IfelseStmt{ + IfList: ast.IfList{&ast.IfStmtElem{ + Condition: &ast.ConditionalExpr{ + Op: AstOp(EQEQ), + LHS: &ast.Identifier{Name: "key"}, + RHS: &ast.StringLiteral{Val: "11"}, + }, + Block: &ast.BlockStmt{Stmts: ast.Stmts{ + &ast.CallExpr{ + Obj: &ast.Identifier{Name: "g"}, + Param: []ast.Node{ + &ast.Identifier{Name: "arg"}, + }, + }, + }}, + }}, + Else: &ast.BlockStmt{Stmts: ast.Stmts{&ast.CallExpr{ + Obj: &ast.Identifier{Name: "h"}, + Param: []ast.Node{ + &ast.Identifier{Name: "arg"}, + }, + }}}, + }, + }, + }, + + { + name: "if-nil", + in: `if abc == nil {}`, + expected: ast.Stmts{ + &ast.IfelseStmt{ + IfList: ast.IfList{ + &ast.IfStmtElem{ + Block: &ast.BlockStmt{}, + Condition: &ast.ConditionalExpr{ + Op: AstOp(EQEQ), + LHS: &ast.Identifier{Name: "abc"}, + RHS: &ast.NilLiteral{}, + }, + }, + }, + }, + }, + }, + + { + name: "if-expr", + in: `if key=="11" { g(arg) }`, + expected: ast.Stmts{ + &ast.IfelseStmt{IfList: ast.IfList{ + &ast.IfStmtElem{ + Condition: &ast.ConditionalExpr{ + Op: AstOp(EQEQ), + LHS: &ast.Identifier{Name: "key"}, + RHS: &ast.StringLiteral{Val: "11"}, + }, + Block: &ast.BlockStmt{ + Stmts: ast.Stmts{ + &ast.CallExpr{ + Obj: &ast.Identifier{Name: "g"}, + Param: []ast.Node{ + &ast.Identifier{Name: "arg"}, + }, + }, + }, + }, + }, + }}, + }, + }, + + { + name: "if-expr-newline", + in: ` + if key=="11" { + g(arg) + }`, + expected: ast.Stmts{ + &ast.IfelseStmt{ + IfList: ast.IfList{&ast.IfStmtElem{ + Condition: &ast.ConditionalExpr{ + Op: AstOp(EQEQ), + LHS: &ast.Identifier{Name: "key"}, + RHS: &ast.StringLiteral{Val: "11"}, + }, + Block: &ast.BlockStmt{Stmts: ast.Stmts{&ast.CallExpr{ + Obj: &ast.Identifier{Name: "g"}, + Param: []ast.Node{ + &ast.Identifier{Name: "arg"}, + }, + }}}, + }}, + }, + }, + }, + + { + name: "array-list in function arg value", + in: `f([1, 2.0, "3", true, false, nil, null, id_123])`, + expected: ast.Stmts{ + &ast.CallExpr{ + Obj: &ast.Identifier{Name: "f"}, + Param: []ast.Node{&ast.ListLiteral{ + List: []ast.Node{ + &ast.IntegerLiteral{Val: 1}, + &ast.FloatLiteral{Val: 2.0}, + &ast.StringLiteral{Val: "3"}, + &ast.BoolLiteral{Val: true}, + &ast.BoolLiteral{Val: false}, + &ast.NilLiteral{}, + &ast.NilLiteral{}, + &ast.Identifier{Name: "id_123"}, + }, + }}, + }, + }, + }, + + { + name: "attr-expr in function arg value", + in: `f(arg=a.b.c)`, + expected: ast.Stmts{ + &ast.CallExpr{ + Obj: &ast.Identifier{Name: "f"}, + Param: []ast.Node{&ast.AssignmentStmt{ + Op: ast.EQ, + LHS: []ast.Node{&ast.Identifier{Name: "arg"}}, + RHS: []ast.Node{&ast.AttrExpr{ + Obj: &ast.Identifier{Name: "a"}, + Attr: &ast.AttrExpr{ + Obj: &ast.AttrExpr{ + Obj: &ast.Identifier{Name: "b"}, + Attr: &ast.Identifier{Name: "c"}, + }, + }, + }}, + }}, + }, + }, + }, + + { + name: "func_call_in_assignement_right", + in: `a = fx("a", true, a1=["b", 1.1])`, + expected: ast.Stmts{ + &ast.AssignmentStmt{ + Op: ast.EQ, + LHS: []ast.Node{&ast.Identifier{Name: "a"}}, + RHS: []ast.Node{&ast.CallExpr{ + Obj: &ast.Identifier{Name: "fx"}, + Param: []ast.Node{ + &ast.StringLiteral{Val: "a"}, + &ast.BoolLiteral{Val: true}, + &ast.AssignmentStmt{ + Op: ast.EQ, + LHS: []ast.Node{&ast.Identifier{Name: "a1"}}, + RHS: []ast.Node{&ast.ListLiteral{ + List: []ast.Node{ + &ast.StringLiteral{Val: "b"}, + &ast.FloatLiteral{Val: 1.1}, + }, + }}, + }, + }, + }}, + }, + }, + }, + + { + name: "naming args", + in: `f(arg1=1, arg2=2)`, + expected: ast.Stmts{ + + &ast.CallExpr{ + Obj: &ast.Identifier{Name: "f"}, + Param: []ast.Node{ + &ast.AssignmentStmt{ + Op: ast.EQ, + LHS: []ast.Node{&ast.Identifier{Name: "arg1"}}, + RHS: []ast.Node{&ast.IntegerLiteral{Val: 1}}, + }, + &ast.AssignmentStmt{ + Op: ast.EQ, + LHS: []ast.Node{&ast.Identifier{Name: "arg2"}}, + RHS: []ast.Node{&ast.IntegerLiteral{Val: 2}}, + }, + }, + }, + }, + }, + + { + name: "func-cond-param-and-kwarg", + in: `f(arg1>1, arg2=2)`, + expected: ast.Stmts{ + + &ast.CallExpr{ + Obj: &ast.Identifier{Name: "f"}, + Param: []ast.Node{ + &ast.ConditionalExpr{ + LHS: &ast.Identifier{Name: "arg1"}, + Op: ast.GT, + RHS: &ast.IntegerLiteral{Val: 1}, + }, + &ast.AssignmentStmt{ + Op: ast.EQ, + LHS: []ast.Node{&ast.Identifier{Name: "arg2"}}, + RHS: []ast.Node{&ast.IntegerLiteral{Val: 2}}, + }, + }, + }, + }, + }, + + { + name: "json attr", + in: `f(.[2].x[3])`, + expected: ast.Stmts{ + &ast.CallExpr{ + Obj: &ast.Identifier{Name: "f"}, + Param: []ast.Node{&ast.AttrExpr{ + Obj: &ast.IndexExpr{ + Index: &ast.IntegerLiteral{Val: 2}, + }, + Attr: &ast.IndexExpr{ + Obj: &ast.Identifier{Name: "x"}, + Index: &ast.IntegerLiteral{Val: 3}, + }, + }}, + }, + }, + }, + + { // 如果 y 是 map 则支持 + name: "multi-dim arr", + in: `f(x.y[2.5]) + {} + a = {"1": 2, 3.1: 1} + `, + expected: ast.Stmts{ + &ast.CallExpr{ + Obj: &ast.Identifier{Name: "f"}, + Param: []ast.Node{ + &ast.AttrExpr{ + Obj: &ast.Identifier{Name: "x"}, + Attr: &ast.IndexExpr{ + Obj: &ast.Identifier{Name: "y"}, + Index: &ast.FloatLiteral{Val: 2.5}, + }, + }, + }, + }, + &ast.MapLiteral{}, + &ast.AssignmentStmt{ + Op: ast.EQ, + LHS: []ast.Node{&ast.Identifier{Name: "a"}}, + RHS: []ast.Node{&ast.MapLiteral{ + KeyValeList: [][2]ast.Node{ + { + &ast.StringLiteral{Val: "1"}, + &ast.IntegerLiteral{Val: 2}, + }, + { + &ast.FloatLiteral{Val: 3.1}, + &ast.IntegerLiteral{Val: 1}, + }, + }, + }}, + }, + }, + }, + + { + in: `f(x.y[1][2].z)`, + expected: ast.Stmts{ + &ast.CallExpr{ + Obj: &ast.Identifier{Name: "f"}, + Param: []ast.Node{ + &ast.AttrExpr{ + Obj: &ast.IndexExpr{ + Obj: &ast.IndexExpr{ + Obj: &ast.AttrExpr{ + Obj: &ast.Identifier{ + Name: "x", + }, + Attr: &ast.Identifier{ + Name: "y", + }, + }, + Index: &ast.IntegerLiteral{ + Val: 1, + }, + }, + Index: &ast.IntegerLiteral{ + Val: 2, + }, + }, + + Attr: &ast.Identifier{ + Name: "z", + }, + + // Obj: &ast.Identifier{Name: "x"}, + // Attr: &ast.AttrExpr{ + // Obj: &ast.IndexExpr{ + // Obj: &ast.IndexExpr{ + // Obj: , + // }, + // Index: []ast.Node{ + // &ast.IntegerLiteral{Val: 1}, + // &ast.IntegerLiteral{Val: 2}, + // }, + // }, + // Attr: &ast.Identifier{Name: "z"}, + // }, + }, + }, + }, + }, + }, + + { + name: "case:-multiple-functions", + in: `f1() + f2() + f3()`, + expected: ast.Stmts{ + &ast.CallExpr{ + Obj: &ast.Identifier{Name: "f1"}, + }, + &ast.CallExpr{ + Obj: &ast.Identifier{Name: "f2"}, + }, + &ast.CallExpr{ + Obj: &ast.Identifier{Name: "f3"}, + }, + }, + }, + + { + name: "embedded functions", + in: `f1(g(f2("abc"), 123.0), 1, 2)`, + expected: ast.Stmts{ + &ast.CallExpr{ + Obj: &ast.Identifier{Name: "f1"}, + Param: []ast.Node{ + &ast.CallExpr{ + Obj: &ast.Identifier{Name: "g"}, + Param: []ast.Node{ + + &ast.CallExpr{ + Obj: &ast.Identifier{Name: "f2"}, + Param: []ast.Node{ + &ast.StringLiteral{Val: "abc"}, + }, + }, + &ast.FloatLiteral{ + Val: 123.0, + }, + }, + }, + &ast.IntegerLiteral{Val: 1}, + &ast.IntegerLiteral{Val: 2}, + }, + }, + }, + }, + + { + name: "attr syntax with index syntax in function arg", + in: `json(_, x.y[1].z)`, + expected: ast.Stmts{ + &ast.CallExpr{ + Obj: &ast.Identifier{Name: "json"}, + Param: []ast.Node{ + &ast.Identifier{Name: "_"}, + &ast.AttrExpr{ + Obj: &ast.IndexExpr{ + Obj: &ast.AttrExpr{ + Obj: &ast.Identifier{Name: "x"}, + Attr: &ast.Identifier{Name: "y"}, + }, + Index: &ast.IntegerLiteral{Val: 1}, + }, + Attr: &ast.Identifier{Name: "z"}, + }, + }, + }, + }, + }, + + { + name: "simple attr syntax", + in: `json(_, x.y.z)`, + expected: ast.Stmts{ + &ast.CallExpr{ + Obj: &ast.Identifier{Name: "json"}, + Param: []ast.Node{ + &ast.Identifier{Name: "_"}, + &ast.AttrExpr{ + Obj: &ast.Identifier{Name: "x"}, + Attr: &ast.AttrExpr{ + Obj: &ast.Identifier{Name: "y"}, + Attr: &ast.Identifier{Name: "z"}, + }, + }, + }, + }, + }, + }, + + { + name: "simple attr syntax", + in: `match(_,"p([a-z]+)ch")`, + expected: ast.Stmts{ + &ast.CallExpr{ + Obj: &ast.Identifier{Name: "match"}, + Param: []ast.Node{ + &ast.Identifier{Name: "_"}, + &ast.StringLiteral{Val: "p([a-z]+)ch"}, + }, + }, + }, + }, + + { + name: "many param", + in: `f(a, b, 1, 2, )`, + expected: ast.Stmts{ + &ast.CallExpr{ + Obj: &ast.Identifier{Name: "f"}, + Param: []ast.Node{ + &ast.Identifier{Name: "a"}, + &ast.Identifier{Name: "b"}, + &ast.IntegerLiteral{Val: 1}, + &ast.IntegerLiteral{Val: 2}, + }, + }, + }, + }, + + { + name: `func-arg-with-multi-line-string`, + in: `abc(x, """ +this +is +multiline-string +""")`, + expected: ast.Stmts{ + + &ast.CallExpr{ + Obj: &ast.Identifier{Name: "abc"}, + Param: []ast.Node{ + &ast.Identifier{Name: "x"}, + &ast.StringLiteral{Val: ` +this +is +multiline-string +`}, + }, + }, + }, + }, + { + name: `func-func`, + in: `f1() + f2() + `, + expected: ast.Stmts{ + &ast.CallExpr{ + Obj: &ast.Identifier{Name: "f1"}, + Param: nil, + }, + &ast.CallExpr{ + Obj: &ast.Identifier{Name: "f2"}, + Param: nil, + }, + }, + }, + { + name: "valid slice with identifier", + in: `a[1:3]`, + expected: ast.Stmts{ + &ast.SliceExpr{ + Obj: &ast.Identifier{Name: "a"}, + Start: &ast.IntegerLiteral{ + Val: 1, + }, + End: &ast.IntegerLiteral{ + Val: 3, + }, + }, + }, + }, + { + name: "valid slice default start and end", + in: `a[:]`, + expected: ast.Stmts{ + &ast.SliceExpr{ + Obj: &ast.Identifier{Name: "a"}, + Start: nil, + End: nil, + }, + }, + }, + { + name: "valid slice with step", + in: `a[1:3:2]`, + expected: ast.Stmts{ + &ast.SliceExpr{ + Obj: &ast.Identifier{Name: "a"}, + Start: &ast.IntegerLiteral{ + Val: 1, + }, + End: &ast.IntegerLiteral{ + Val: 3, + }, + Step: &ast.IntegerLiteral{ + Val: 2, + }, + }, + }, + }, + { + name: "valid slice with double colon but empty step", + in: `a[::]`, + expected: ast.Stmts{ + &ast.SliceExpr{ + Obj: &ast.Identifier{Name: "a"}, + Start: nil, + End: nil, + Step: nil, + }, + }, + }, + { + name: "valid slice with string", + in: `"hello"[:3]`, + expected: ast.Stmts{ + &ast.SliceExpr{ + Obj: &ast.StringLiteral{Val: "hello"}, + Start: nil, + End: &ast.IntegerLiteral{ + Val: 3, + }, + }, + }, + }, + { + name: "valid slice with list", + in: `[1, 2, 3, 4][1:]`, + expected: ast.Stmts{ + &ast.SliceExpr{ + Obj: &ast.ListLiteral{ + List: []ast.Node{ + &ast.IntegerLiteral{Val: 1}, + &ast.IntegerLiteral{Val: 2}, + &ast.IntegerLiteral{Val: 3}, + &ast.IntegerLiteral{Val: 4}, + }, + }, + Start: &ast.IntegerLiteral{ + Val: 1, + }, + End: nil, + }, + }, + }, + { + name: "valid nested slice with identifier", + in: `a[1:3][0:2]`, + expected: ast.Stmts{ + &ast.SliceExpr{ + Obj: &ast.SliceExpr{ + Obj: &ast.Identifier{Name: "a"}, + Start: &ast.IntegerLiteral{ + Val: 1, + }, + End: &ast.IntegerLiteral{ + Val: 3, + }, + }, + Start: &ast.IntegerLiteral{ + Val: 0, + }, + End: &ast.IntegerLiteral{ + Val: 2, + }, + }, + }, + }, + { + name: "invalid slice with invalid object type", + in: `true[1:3]`, + expected: ast.Stmts{&ast.SliceExpr{ + Obj: &ast.BoolLiteral{ + Val: true, + }, + Start: &ast.IntegerLiteral{ + Val: 1, + }, + End: &ast.IntegerLiteral{ + Val: 3, + }, + }}, + }, + { + name: "invalid slice with invalid start type", + in: `a["1":3]`, + expected: ast.Stmts{&ast.SliceExpr{ + Obj: &ast.Identifier{ + Name: "a", + }, + Start: &ast.StringLiteral{ + Val: "1", + }, + End: &ast.IntegerLiteral{ + Val: 3, + }, + }}, + }, + { + name: "invalid slice with invalid end type", + in: `a[1:"3"]`, + expected: ast.Stmts{&ast.SliceExpr{ + Obj: &ast.Identifier{ + Name: "a", + }, + Start: &ast.IntegerLiteral{ + Val: 1, + }, + End: &ast.StringLiteral{ + Val: "3", + }, + }}}, + { + name: "invalid slice with no object", + in: `[1:3]`, + fail: true, + }, + } + + // for idx := len(cases) - 1; idx >= 0; idx-- { + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + Stmts, err := ParsePipeline("", tc.in) + + if !tc.fail { + assert.Nil(t, err) + } else { + t.Logf("expected error: %s", err) + if err == nil { + t.Error(tc) + } + assert.NotNil(t, err) + return + } + + if !tc.fail { + var x, y string + x = tc.expected.String() + y = Stmts.String() + assert.Nil(t, err) + assert.Equal(t, x, y) + t.Logf("ok %s -> %s", tc.in, y) + } else { + t.Logf("%s -> expect fail: %v", tc.in, err) + assert.NotNil(t, err, "") + } + }) + } +} + +func TestParserEOLS(t *testing.T) { + cases := []string{ + ` + +`, + ` +; +`, + ` + +;; +`, + ` +; + +`, + ` + +a + 1 +`, + ` + +a + 1 +;`, + ` + +; +a + +`, + + ` + +a +`, + ` +a + #abc +1 +a + 1 +x in [abc] + +x in # dd +[ abc] + +x in +[ abc]; + +x in [ abc +] + +x[ + a +] +x[a] +x[ + a] +x in pt_kvs_keys(fields=false,tags=true) +cALl( + a, v, + c ) +cALl( a, v, + c + ) +cALl(a, v,c) + +{ #d + x: call( #33 + + ), + a : x , d: e, + c: x +} +{} +a = +b +`, + ` +x[-1:3] +x[:][1:3] +x[1:2:3] +x[1:2:] +x[::1] +"hello"[a:b] +x[x[1]:1] +func(a, b, c)[func(a, b, c):b] +[1,2,3,4][a:b]`, + } + + for _, v := range cases { + stmts, err := ParsePipeline("", v) + if err != nil { + t.Fatal(err, v) + } + t.Log(stmts) + } +} diff --git a/pkg/v2/parser/strutil.go b/pkg/v2/parser/strutil.go new file mode 100644 index 0000000..46fb4f9 --- /dev/null +++ b/pkg/v2/parser/strutil.go @@ -0,0 +1,321 @@ +// Copyright 2015 The Prometheus Authors +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// NOTE: The functions in this file (Unquote, unquoteChar, contains, unhex) +// have been adapted from the "strconv" package of the Go standard library +// to work for Prometheus-style strings. Go's special-casing for single +// quotes was removed and single quoted strings are now treated the same as +// double-quoted ones. +// +// The original copyright notice from the Go project for these parts is +// reproduced here: +// +// ======================================================================== +// Copyright (c) 2009 The Go Authors. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// ======================================================================== + +package parser + +import ( + "errors" + "unicode/utf8" +) + +// ErrSyntax indicates that a value does not have the right syntax for the target type. +var ErrSyntax = errors.New("invalid syntax") + +func UnquoteMultiline(s string) (t string, err error) { + n := len(s) + if n < 6 { + return "", ErrSyntax + } + + if n == 6 { + return "", nil + } + + for i := 0; i < 3; i++ { + if s[i] != s[n-(i+1)] { + return "", ErrSyntax + } + } + + quote := s[0] + // remove header/tail ''' or """ + s = s[3 : n-3] + + if quote != '"' && quote != '\'' { + return "", ErrSyntax + } + + // Is it trivial? Avoid allocation. + if !contains(s, '\\') && !contains(s, quote) && !contains(s, '\n') { + return s, nil + } + + var runeTmp [utf8.UTFMax]byte + buf := make([]byte, 0, 3*len(s)/2) // Try to avoid more allocations. + for len(s) > 0 { + c, multibyte, ss, err := unquoteChar(s, byte(0), true) + if err != nil { + return "", err + } + s = ss + if c < utf8.RuneSelf || !multibyte { + buf = append(buf, byte(c)) + } else { + n := utf8.EncodeRune(runeTmp[:], c) + buf = append(buf, runeTmp[:n]...) + } + } + return string(buf), nil +} + +// Unquote interprets s as a single-quoted, double-quoted, or backquoted +// Prometheus query language string literal, returning the string value that s +// quotes. +// +// NOTE: This function as well as the necessary helper functions below +// (unquoteChar, contains, unhex) and associated tests have been adapted from +// the corresponding functions in the "strconv" package of the Go standard +// library to work for Prometheus-style strings. Go's special-casing for single +// quotes was removed and single quoted strings are now treated the same as +// double quoted ones. +func Unquote(s string) (t string, err error) { + n := len(s) + if n < 2 { + return "", ErrSyntax + } + quote := s[0] + if quote != s[n-1] { + return "", ErrSyntax + } + s = s[1 : n-1] + + if quote == '`' { + if contains(s, '`') { + return "", ErrSyntax + } + return s, nil + } + if quote != '"' && quote != '\'' { + return "", ErrSyntax + } + if contains(s, '\n') { + return "", ErrSyntax + } + + // Is it trivial? Avoid allocation. + if !contains(s, '\\') && !contains(s, quote) { + return s, nil + } + + var runeTmp [utf8.UTFMax]byte + buf := make([]byte, 0, 3*len(s)/2) // Try to avoid more allocations. + for len(s) > 0 { + c, multibyte, ss, err := unquoteChar(s, quote, false) + if err != nil { + return "", err + } + s = ss + if c < utf8.RuneSelf || !multibyte { + buf = append(buf, byte(c)) + } else { + n := utf8.EncodeRune(runeTmp[:], c) + buf = append(buf, runeTmp[:n]...) + } + } + return string(buf), nil +} + +// unquoteChar decodes the first character or byte in the escaped string +// or character literal represented by the string s. +// It returns four values: +// +// 1. value, the decoded Unicode code point or byte value; +// 2. multibyte, a boolean indicating whether the decoded character requires a multibyte UTF-8 representation; +// 3. tail, the remainder of the string after the character; and +// 4. an error that will be nil if the character is syntactically valid. +// +// The second argument, quote, specifies the type of literal being parsed +// and therefore which escaped quote character is permitted. +// If set to a single quote, it permits the sequence \' and disallows unescaped '. +// If set to a double quote, it permits \" and disallows unescaped ". +// If set to zero, it does not permit either escape and allows both quote characters to appear unescaped. +func unquoteChar(s string, quote byte, multiline bool) (value rune, multibyte bool, tail string, err error) { + if multiline { + // under multiline mode, all bytes keep as it is + switch c := s[0]; { + case c >= utf8.RuneSelf: + r, size := utf8.DecodeRuneInString(s) + return r, true, s[size:], nil + + default: + return rune(s[0]), false, s[1:], nil + } + } + + // easy cases + switch c := s[0]; { + case c == quote && (quote == '\'' || quote == '"'): + err = ErrSyntax + return + case c >= utf8.RuneSelf: + r, size := utf8.DecodeRuneInString(s) + return r, true, s[size:], nil + case c != '\\': + return rune(s[0]), false, s[1:], nil + } + + // Hard case: c is backslash. + if len(s) <= 1 { + err = ErrSyntax + return + } + c := s[1] + s = s[2:] + + switch c { + case 'a': + value = '\a' + case 'b': + value = '\b' + case 'f': + value = '\f' + case 'n': + value = '\n' + case 'r': + value = '\r' + case 't': + value = '\t' + case 'v': + value = '\v' + case 'x', 'u', 'U': + n := 0 + switch c { + case 'x': + n = 2 + case 'u': + n = 4 + case 'U': + n = 8 + } + var v rune + if len(s) < n { + err = ErrSyntax + return + } + for j := 0; j < n; j++ { + x, ok := unhex(s[j]) + if !ok { + err = ErrSyntax + return + } + v = v<<4 | x + } + s = s[n:] + if c == 'x' { + // Single-byte string, possibly not UTF-8. + value = v + break + } + if v > utf8.MaxRune { + err = ErrSyntax + return + } + value = v + multibyte = true + case '0', '1', '2', '3', '4', '5', '6', '7': + v := rune(c) - '0' + if len(s) < 2 { + err = ErrSyntax + return + } + for j := 0; j < 2; j++ { // One digit already; two more. + x := rune(s[j]) - '0' + if x < 0 || x > 7 { + err = ErrSyntax + return + } + v = (v << 3) | x + } + s = s[2:] + if v > 255 { + err = ErrSyntax + return + } + value = v + case '\\': + value = '\\' + case '\'', '"': + if c != quote { + err = ErrSyntax + return + } + value = rune(c) + default: + err = ErrSyntax + return + } + tail = s + return value, multibyte, tail, err +} + +// contains reports whether the string contains the byte c. +func contains(s string, c byte) bool { + for i := 0; i < len(s); i++ { + if s[i] == c { + return true + } + } + return false +} + +func unhex(b byte) (v rune, ok bool) { + c := rune(b) + switch { + case '0' <= c && c <= '9': + return c - '0', true + case 'a' <= c && c <= 'f': + return c - 'a' + 10, true + case 'A' <= c && c <= 'F': + return c - 'A' + 10, true + } + return +} diff --git a/pkg/v2/parser/strutil_test.go b/pkg/v2/parser/strutil_test.go new file mode 100644 index 0000000..5431465 --- /dev/null +++ b/pkg/v2/parser/strutil_test.go @@ -0,0 +1,159 @@ +// Unless explicitly stated otherwise all files in this repository are licensed +// under the MIT License. +// This product includes software developed at Guance Cloud (https://www.guance.com/). +// Copyright 2021-present Guance, Inc. + +package parser + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestUnquote(t *testing.T) { + cases := []struct { + name string + s string + expect string + fail bool + }{ + { + name: "str", + s: `"abc"`, + expect: "abc", + }, + { + name: "str-with-special-char", + s: `"abc\""`, + expect: "abc\"", + }, + { + name: "str-with-unicode", + s: `"中\\abc"`, + expect: "中\\abc", + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + x, err := Unquote(tc.s) + if tc.fail { + assert.Equal(t, err != nil, "") + return + } + + assert.Equal(t, err, nil, "expect nil, got %s", err) + assert.Equal(t, tc.expect, x) + }) + } +} + +func TestMultilineUnquote(t *testing.T) { + cases := []struct { + name string + s string + expect string + fail bool + }{ + { + name: "empty-multiline-str", + s: `""""""`, + expect: "", + }, + + { + name: "unmatched-multiline-str", + s: `"""abc""`, + expect: "", + fail: true, + }, + + { + name: "unmatched-multiline-str2", + s: `"""abc""'`, + expect: "", + fail: true, + }, + + { + name: "empty-multiline-str", + s: `""" +abc +"""`, + expect: ` +abc +`, + }, + + { + name: "empty-multiline-str-single-quote", + s: `''''''`, + expect: "", + }, + + { + name: "multiline-str-with-1-line", + s: `"""abc def"""`, + expect: "abc def", + }, + { + name: "multiline-str-only-new-line", + s: `""" +"""`, + expect: "\n", + }, + + { + name: "multiline-str", + s: `"""this is +multiline +string"""`, + expect: "this is\nmultiline\nstring", + }, + { + name: "multiline-str-with-special-chars", + s: `"""this is +multiline ""'\ +string"""`, + expect: "this is\nmultiline \"\"'\\\nstring", + }, + + { + name: "multiline-str-with-unicode", + s: `"""中\n\n\n +文"""`, + expect: "中\\n\\n\\n\n文", + }, + + { + name: "multiline-str-with-`", + s: "'''中`" + "\n" + "文'''", + expect: "中`\n文", + }, + + { + name: "multiline-str-with-escaped-char", + s: `''' +\r\n +\b\c'''`, + expect: ` +\r\n +\b\c`, + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + x, err := UnquoteMultiline(tc.s) + if tc.fail { + assert.NotEqual(t, err, nil, "") + t.Logf("[expect] %s => %s", tc.s, err) + return + } + + assert.Equal(t, err, nil, "expect nil, got %s", err) + assert.Equal(t, tc.expect, x) + }) + } +} diff --git a/pkg/v2/parser/y.output b/pkg/v2/parser/y.output new file mode 100644 index 0000000..24c6a8f --- /dev/null +++ b/pkg/v2/parser/y.output @@ -0,0 +1,5727 @@ + +state 0 + $accept: .start $end + + error shift 3 + START_STMTS shift 2 + . error + + start goto 1 + +state 1 + $accept: start.$end + start: start.EOF + + $end accept + EOF shift 4 + . error + + +state 2 + start: START_STMTS.stmts + start: START_STMTS.EOLS + start: START_STMTS.EOLS stmts + + SEMICOLON shift 23 + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + EOL shift 9 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + IF shift 49 + FOR shift 25 + BREAK shift 27 + CONTINUE shift 26 + RETURN shift 33 + FN shift 31 + LET shift 29 + IMPORT shift 32 + CONST shift 30 + . error + + stmts goto 5 + stmts_list goto 7 + if_elem goto 35 + if_elif_list goto 24 + exprs goto 34 + stmt goto 8 + assignment_stmt goto 22 + for_in_stmt goto 12 + for_stmt goto 13 + continue_stmt goto 14 + break_stmt goto 15 + ifelse_stmt goto 11 + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 28 + map_literal goto 39 + value_stmt goto 16 + list_literal goto 38 + basic_literal goto 37 + slice_expr goto 46 + let_stmt goto 17 + const_def_stmt goto 18 + fn_def_stmt goto 19 + import_stmt goto 20 + return_stmt goto 21 + sem goto 10 + EOLS goto 6 + +state 3 + start: error. (16) + + . reduce 16 (src line 187) + + +state 4 + start: start EOF. (15) + + . reduce 15 (src line 186) + + +state 5 + start: START_STMTS stmts. (12) + + . reduce 12 (src line 174) + + +state 6 + EOLS: EOLS.EOL + start: START_STMTS EOLS. (13) + start: START_STMTS EOLS.stmts + + SEMICOLON shift 23 + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + EOL shift 66 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + IF shift 49 + FOR shift 25 + BREAK shift 27 + CONTINUE shift 26 + RETURN shift 33 + FN shift 31 + LET shift 29 + IMPORT shift 32 + CONST shift 30 + . reduce 13 (src line 178) + + stmts goto 67 + stmts_list goto 7 + if_elem goto 35 + if_elif_list goto 24 + exprs goto 34 + stmt goto 8 + assignment_stmt goto 22 + for_in_stmt goto 12 + for_stmt goto 13 + continue_stmt goto 14 + break_stmt goto 15 + ifelse_stmt goto 11 + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 28 + map_literal goto 39 + value_stmt goto 16 + list_literal goto 38 + basic_literal goto 37 + slice_expr goto 46 + let_stmt goto 17 + const_def_stmt goto 18 + fn_def_stmt goto 19 + import_stmt goto 20 + return_stmt goto 21 + sem goto 10 + +state 7 + stmts: stmts_list.stmt + stmts: stmts_list. (18) + stmts_list: stmts_list.stmt sep + + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + IF shift 49 + FOR shift 25 + BREAK shift 27 + CONTINUE shift 26 + RETURN shift 33 + FN shift 31 + LET shift 29 + IMPORT shift 32 + CONST shift 30 + . reduce 18 (src line 203) + + if_elem goto 35 + if_elif_list goto 24 + exprs goto 34 + stmt goto 68 + assignment_stmt goto 22 + for_in_stmt goto 12 + for_stmt goto 13 + continue_stmt goto 14 + break_stmt goto 15 + ifelse_stmt goto 11 + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 28 + map_literal goto 39 + value_stmt goto 16 + list_literal goto 38 + basic_literal goto 37 + slice_expr goto 46 + let_stmt goto 17 + const_def_stmt goto 18 + fn_def_stmt goto 19 + import_stmt goto 20 + return_stmt goto 21 + +state 8 + stmts: stmt. (19) + stmts_list: stmt.sep + + SEMICOLON shift 70 + EOL shift 71 + . reduce 19 (src line 204) + + sep goto 69 + +state 9 + EOLS: EOL. (8) + + . reduce 8 (src line 166) + + +state 10 + sem: sem.EOL + sem: sem.SEMICOLON + stmts_list: sem. (21) + + SEMICOLON shift 73 + EOL shift 72 + . reduce 21 (src line 214) + + +state 11 + stmt: ifelse_stmt. (23) + + . reduce 23 (src line 226) + + +state 12 + stmt: for_in_stmt. (24) + + . reduce 24 (src line 227) + + +state 13 + stmt: for_stmt. (25) + + . reduce 25 (src line 228) + + +state 14 + stmt: continue_stmt. (26) + + . reduce 26 (src line 229) + + +state 15 + stmt: break_stmt. (27) + + . reduce 27 (src line 230) + + +state 16 + stmt: value_stmt. (28) + + . reduce 28 (src line 231) + + +state 17 + stmt: let_stmt. (29) + + . reduce 29 (src line 232) + + +state 18 + stmt: const_def_stmt. (30) + + . reduce 30 (src line 233) + + +state 19 + stmt: fn_def_stmt. (31) + + . reduce 31 (src line 234) + + +state 20 + stmt: import_stmt. (32) + + . reduce 32 (src line 235) + + +state 21 + stmt: return_stmt. (33) + + . reduce 33 (src line 236) + + +state 22 + stmt: assignment_stmt. (34) + + . reduce 34 (src line 237) + + +state 23 + sem: SEMICOLON. (5) + + . reduce 5 (src line 161) + + +state 24 + ifelse_stmt: if_elif_list. (105) + ifelse_stmt: if_elif_list.ELSE stmt_block + if_elif_list: if_elif_list.elif_elem + + ELIF shift 76 + ELSE shift 74 + . reduce 105 (src line 543) + + elif_elem goto 75 + +state 25 + for_in_stmt: FOR.in_expr stmt_block + for_stmt: FOR.for_init_elem SEMICOLON expr SEMICOLON for_loop_elem stmt_block + for_stmt: FOR.for_init_elem SEMICOLON expr SEMICOLON stmt_block + for_stmt: FOR.for_init_elem SEMICOLON SEMICOLON for_loop_elem stmt_block + for_stmt: FOR.for_init_elem SEMICOLON SEMICOLON stmt_block + for_stmt: FOR.SEMICOLON expr SEMICOLON for_loop_elem stmt_block + for_stmt: FOR.SEMICOLON expr SEMICOLON stmt_block + for_stmt: FOR.SEMICOLON SEMICOLON for_loop_elem stmt_block + for_stmt: FOR.SEMICOLON SEMICOLON stmt_block + + SEMICOLON shift 79 + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + LET shift 29 + . error + + exprs goto 34 + assignment_stmt goto 81 + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 77 + expr goto 80 + map_literal goto 39 + list_literal goto 38 + basic_literal goto 37 + for_init_elem goto 78 + slice_expr goto 46 + let_stmt goto 82 + +state 26 + continue_stmt: CONTINUE. (90) + + . reduce 90 (src line 478) + + +state 27 + break_stmt: BREAK. (89) + + . reduce 89 (src line 471) + + +state 28 + value_stmt: expr. (35) + exprs: expr. (81) + assignment_stmt: expr.ADD_EQ expr + assignment_stmt: expr.SUB_EQ expr + assignment_stmt: expr.MUL_EQ expr + assignment_stmt: expr.DIV_EQ expr + assignment_stmt: expr.MOD_EQ expr + in_expr: expr.IN expr + call_expr: expr.LEFT_PAREN function_args EOLS_SPACE RIGHT_PAREN + call_expr: expr.LEFT_PAREN function_args COMMA RIGHT_PAREN + call_expr: expr.LEFT_PAREN RIGHT_PAREN + conditional_expr: expr.GTE expr + conditional_expr: expr.GT expr + conditional_expr: expr.OR expr + conditional_expr: expr.AND expr + conditional_expr: expr.LT expr + conditional_expr: expr.LTE expr + conditional_expr: expr.NEQ expr + conditional_expr: expr.EQEQ expr + arithmeticExpr: expr.ADD expr + arithmeticExpr: expr.SUB expr + arithmeticExpr: expr.MUL expr + arithmeticExpr: expr.DIV expr + arithmeticExpr: expr.MOD expr + index_expr: expr.LEFT_BRACKET expr EOLS_SPACE RIGHT_BRACKET + attr_expr: expr.DOT expr + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty COLON expr_or_empty RIGHT_BRACKET + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty RIGHT_BRACKET + + COMMA reduce 81 (src line 427) + LEFT_PAREN shift 89 + LEFT_BRACKET shift 103 + ADD shift 98 + SUB shift 99 + MUL shift 100 + DIV shift 101 + MOD shift 102 + EQ reduce 81 (src line 427) + GTE shift 90 + GT shift 91 + LT shift 94 + LTE shift 95 + NEQ shift 96 + EQEQ shift 97 + ADD_EQ shift 83 + SUB_EQ shift 84 + DIV_EQ shift 86 + MUL_EQ shift 85 + MOD_EQ shift 87 + AND shift 93 + OR shift 92 + DOT shift 104 + IN shift 88 + . reduce 35 (src line 241) + + +state 29 + let_stmt: LET.identifier COLON data_type EQ expr + let_stmt: LET.identifier COLON data_type + let_stmt: LET.identifier + let_stmt: LET.identifier EQ expr + + ID shift 50 + QUOTED_STRING shift 51 + . error + + identifier goto 105 + +state 30 + const_def_stmt: CONST.identifier EQ expr + + ID shift 50 + QUOTED_STRING shift 51 + . error + + identifier goto 106 + +state 31 + fn_def_stmt: FN.identifier LEFT_PAREN RIGHT_PAREN stmt_block + fn_def_stmt: FN.identifier LEFT_PAREN RIGHT_PAREN FN_RET data_type stmt_block + fn_def_stmt: FN.identifier LEFT_PAREN RIGHT_PAREN FN_RET LEFT_PAREN fn_ret_types_multi RIGHT_PAREN stmt_block + fn_def_stmt: FN.identifier LEFT_PAREN fn_def_params RIGHT_PAREN stmt_block + fn_def_stmt: FN.identifier LEFT_PAREN fn_def_params RIGHT_PAREN FN_RET data_type stmt_block + fn_def_stmt: FN.identifier LEFT_PAREN fn_def_params RIGHT_PAREN FN_RET LEFT_PAREN fn_ret_types_multi RIGHT_PAREN stmt_block + + ID shift 50 + QUOTED_STRING shift 51 + . error + + identifier goto 107 + +state 32 + import_stmt: IMPORT.pkg_name + import_stmt: IMPORT.pkg_name AS identifier + + ID shift 50 + QUOTED_STRING shift 51 + . error + + pkg_name goto 108 + identifier goto 109 + +state 33 + return_stmt: RETURN. (69) + return_stmt: RETURN.exprs + + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + . reduce 69 (src line 367) + + exprs goto 110 + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 111 + map_literal goto 39 + list_literal goto 38 + basic_literal goto 37 + slice_expr goto 46 + +state 34 + exprs: exprs.COMMA expr + assignment_stmt: exprs.EQ exprs + + COMMA shift 112 + EQ shift 113 + . error + + +state 35 + if_elif_list: if_elem. (108) + + . reduce 108 (src line 559) + + +state 36 + expr: identifier. (36) + + . reduce 36 (src line 245) + + +state 37 + expr: basic_literal. (37) + + . reduce 37 (src line 246) + + +state 38 + expr: list_literal. (38) + + . reduce 38 (src line 247) + + +state 39 + expr: map_literal. (39) + + . reduce 39 (src line 248) + + +state 40 + expr: paren_expr. (40) + + . reduce 40 (src line 249) + + +state 41 + expr: unary_expr. (41) + + . reduce 41 (src line 250) + + +state 42 + expr: conditional_expr. (42) + + . reduce 42 (src line 251) + + +state 43 + expr: arithmeticExpr. (43) + + . reduce 43 (src line 252) + + +state 44 + expr: attr_expr. (44) + + . reduce 44 (src line 253) + + +state 45 + expr: index_expr. (45) + + . reduce 45 (src line 254) + + +state 46 + expr: slice_expr. (46) + + . reduce 46 (src line 255) + + +state 47 + expr: in_expr. (47) + + . reduce 47 (src line 256) + + +state 48 + expr: call_expr. (48) + + . reduce 48 (src line 257) + + +state 49 + if_elem: IF.expr stmt_block + + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + . error + + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 114 + map_literal goto 39 + list_literal goto 38 + basic_literal goto 37 + slice_expr goto 46 + +state 50 + identifier: ID. (154) + + . reduce 154 (src line 796) + + +state 51 + identifier: QUOTED_STRING. (155) + + . reduce 155 (src line 800) + + +state 52 + basic_literal: NUMBER. (156) + + . reduce 156 (src line 807) + + +state 53 + basic_literal: TRUE. (157) + + . reduce 157 (src line 811) + + +state 54 + basic_literal: FALSE. (158) + + . reduce 158 (src line 815) + + +state 55 + basic_literal: STRING. (159) + + . reduce 159 (src line 819) + + +state 56 + basic_literal: MULTILINE_STRING. (160) + + . reduce 160 (src line 824) + + +state 57 + basic_literal: NIL. (161) + + . reduce 161 (src line 829) + + +state 58 + basic_literal: NULL. (162) + + . reduce 162 (src line 833) + + +state 59 + list_literal: LEFT_BRACKET.exprs EOLS_SPACE RIGHT_BRACKET + list_literal: LEFT_BRACKET.exprs COMMA RIGHT_BRACKET + list_literal: LEFT_BRACKET.RIGHT_BRACKET + + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + RIGHT_BRACKET shift 116 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + . error + + exprs goto 115 + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 111 + map_literal goto 39 + list_literal goto 38 + basic_literal goto 37 + slice_expr goto 46 + +state 60 + map_literal: LEFT_BRACE.RIGHT_BRACE + map_literal: LEFT_BRACE.expr_colon_expr EOLS_SPACE RIGHT_BRACE + + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + RIGHT_BRACE shift 117 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + . error + + expr_colon_expr goto 118 + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 119 + map_literal goto 39 + list_literal goto 38 + basic_literal goto 37 + slice_expr goto 46 + +state 61 + paren_expr: LEFT_PAREN.expr EOLS_SPACE RIGHT_PAREN + + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + . error + + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 120 + map_literal goto 39 + list_literal goto 38 + basic_literal goto 37 + slice_expr goto 46 + +state 62 + unary_expr: ADD.expr + + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + . error + + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 121 + map_literal goto 39 + list_literal goto 38 + basic_literal goto 37 + slice_expr goto 46 + +state 63 + unary_expr: SUB.expr + + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + . error + + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 122 + map_literal goto 39 + list_literal goto 38 + basic_literal goto 37 + slice_expr goto 46 + +state 64 + unary_expr: NOT.expr + + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + . error + + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 123 + map_literal goto 39 + list_literal goto 38 + basic_literal goto 37 + slice_expr goto 46 + +state 65 + index_expr: DOT.LEFT_BRACKET expr EOLS_SPACE RIGHT_BRACKET + + LEFT_BRACKET shift 124 + . error + + +state 66 + EOLS: EOLS EOL. (9) + + . reduce 9 (src line 167) + + +state 67 + start: START_STMTS EOLS stmts. (14) + + . reduce 14 (src line 182) + + +state 68 + stmts: stmts_list stmt. (17) + stmts_list: stmts_list stmt.sep + + SEMICOLON shift 70 + EOL shift 71 + . reduce 17 (src line 197) + + sep goto 125 + +state 69 + sep: sep.SEMICOLON + sep: sep.EOL + stmts_list: stmt sep. (20) + + SEMICOLON shift 126 + EOL shift 127 + . reduce 20 (src line 210) + + +state 70 + sep: SEMICOLON. (1) + + . reduce 1 (src line 155) + + +state 71 + sep: EOL. (2) + + . reduce 2 (src line 156) + + +state 72 + sem: sem EOL. (6) + + . reduce 6 (src line 162) + + +state 73 + sem: sem SEMICOLON. (7) + + . reduce 7 (src line 163) + + +state 74 + ifelse_stmt: if_elif_list ELSE.stmt_block + + LEFT_BRACE shift 130 + . error + + stmt_block goto 128 + empty_block goto 129 + +state 75 + if_elif_list: if_elif_list elif_elem. (109) + + . reduce 109 (src line 563) + + +state 76 + elif_elem: ELIF.expr stmt_block + + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + . error + + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 131 + map_literal goto 39 + list_literal goto 38 + basic_literal goto 37 + slice_expr goto 46 + +state 77 + expr: in_expr. (47) + for_in_stmt: FOR in_expr.stmt_block + + LEFT_BRACE shift 130 + . reduce 47 (src line 256) + + stmt_block goto 132 + empty_block goto 129 + +state 78 + for_stmt: FOR for_init_elem.SEMICOLON expr SEMICOLON for_loop_elem stmt_block + for_stmt: FOR for_init_elem.SEMICOLON expr SEMICOLON stmt_block + for_stmt: FOR for_init_elem.SEMICOLON SEMICOLON for_loop_elem stmt_block + for_stmt: FOR for_init_elem.SEMICOLON SEMICOLON stmt_block + + SEMICOLON shift 133 + . error + + +state 79 + for_stmt: FOR SEMICOLON.expr SEMICOLON for_loop_elem stmt_block + for_stmt: FOR SEMICOLON.expr SEMICOLON stmt_block + for_stmt: FOR SEMICOLON.SEMICOLON for_loop_elem stmt_block + for_stmt: FOR SEMICOLON.SEMICOLON stmt_block + + SEMICOLON shift 135 + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + . error + + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 134 + map_literal goto 39 + list_literal goto 38 + basic_literal goto 37 + slice_expr goto 46 + +state 80 + exprs: expr. (81) + assignment_stmt: expr.ADD_EQ expr + assignment_stmt: expr.SUB_EQ expr + assignment_stmt: expr.MUL_EQ expr + assignment_stmt: expr.DIV_EQ expr + assignment_stmt: expr.MOD_EQ expr + for_init_elem: expr. (92) + in_expr: expr.IN expr + call_expr: expr.LEFT_PAREN function_args EOLS_SPACE RIGHT_PAREN + call_expr: expr.LEFT_PAREN function_args COMMA RIGHT_PAREN + call_expr: expr.LEFT_PAREN RIGHT_PAREN + conditional_expr: expr.GTE expr + conditional_expr: expr.GT expr + conditional_expr: expr.OR expr + conditional_expr: expr.AND expr + conditional_expr: expr.LT expr + conditional_expr: expr.LTE expr + conditional_expr: expr.NEQ expr + conditional_expr: expr.EQEQ expr + arithmeticExpr: expr.ADD expr + arithmeticExpr: expr.SUB expr + arithmeticExpr: expr.MUL expr + arithmeticExpr: expr.DIV expr + arithmeticExpr: expr.MOD expr + index_expr: expr.LEFT_BRACKET expr EOLS_SPACE RIGHT_BRACKET + attr_expr: expr.DOT expr + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty COLON expr_or_empty RIGHT_BRACKET + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty RIGHT_BRACKET + + SEMICOLON reduce 92 (src line 503) + LEFT_PAREN shift 89 + LEFT_BRACKET shift 103 + ADD shift 98 + SUB shift 99 + MUL shift 100 + DIV shift 101 + MOD shift 102 + GTE shift 90 + GT shift 91 + LT shift 94 + LTE shift 95 + NEQ shift 96 + EQEQ shift 97 + ADD_EQ shift 83 + SUB_EQ shift 84 + DIV_EQ shift 86 + MUL_EQ shift 85 + MOD_EQ shift 87 + AND shift 93 + OR shift 92 + DOT shift 104 + IN shift 88 + . reduce 81 (src line 427) + + +state 81 + for_init_elem: assignment_stmt. (93) + + . reduce 93 (src line 503) + + +state 82 + for_init_elem: let_stmt. (94) + + . reduce 94 (src line 503) + + +state 83 + assignment_stmt: expr ADD_EQ.expr + + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + . error + + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 136 + map_literal goto 39 + list_literal goto 38 + basic_literal goto 37 + slice_expr goto 46 + +state 84 + assignment_stmt: expr SUB_EQ.expr + + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + . error + + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 137 + map_literal goto 39 + list_literal goto 38 + basic_literal goto 37 + slice_expr goto 46 + +state 85 + assignment_stmt: expr MUL_EQ.expr + + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + . error + + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 138 + map_literal goto 39 + list_literal goto 38 + basic_literal goto 37 + slice_expr goto 46 + +state 86 + assignment_stmt: expr DIV_EQ.expr + + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + . error + + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 139 + map_literal goto 39 + list_literal goto 38 + basic_literal goto 37 + slice_expr goto 46 + +state 87 + assignment_stmt: expr MOD_EQ.expr + + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + . error + + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 140 + map_literal goto 39 + list_literal goto 38 + basic_literal goto 37 + slice_expr goto 46 + +state 88 + in_expr: expr IN.expr + + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + . error + + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 141 + map_literal goto 39 + list_literal goto 38 + basic_literal goto 37 + slice_expr goto 46 + +state 89 + call_expr: expr LEFT_PAREN.function_args EOLS_SPACE RIGHT_PAREN + call_expr: expr LEFT_PAREN.function_args COMMA RIGHT_PAREN + call_expr: expr LEFT_PAREN.RIGHT_PAREN + + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + RIGHT_PAREN shift 143 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + . error + + function_args goto 142 + call_expr goto 48 + named_arg goto 144 + identifier goto 146 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 145 + map_literal goto 39 + list_literal goto 38 + basic_literal goto 37 + slice_expr goto 46 + +state 90 + conditional_expr: expr GTE.expr + + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + . error + + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 147 + map_literal goto 39 + list_literal goto 38 + basic_literal goto 37 + slice_expr goto 46 + +state 91 + conditional_expr: expr GT.expr + + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + . error + + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 148 + map_literal goto 39 + list_literal goto 38 + basic_literal goto 37 + slice_expr goto 46 + +state 92 + conditional_expr: expr OR.expr + + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + . error + + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 149 + map_literal goto 39 + list_literal goto 38 + basic_literal goto 37 + slice_expr goto 46 + +state 93 + conditional_expr: expr AND.expr + + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + . error + + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 150 + map_literal goto 39 + list_literal goto 38 + basic_literal goto 37 + slice_expr goto 46 + +state 94 + conditional_expr: expr LT.expr + + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + . error + + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 151 + map_literal goto 39 + list_literal goto 38 + basic_literal goto 37 + slice_expr goto 46 + +state 95 + conditional_expr: expr LTE.expr + + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + . error + + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 152 + map_literal goto 39 + list_literal goto 38 + basic_literal goto 37 + slice_expr goto 46 + +state 96 + conditional_expr: expr NEQ.expr + + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + . error + + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 153 + map_literal goto 39 + list_literal goto 38 + basic_literal goto 37 + slice_expr goto 46 + +state 97 + conditional_expr: expr EQEQ.expr + + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + . error + + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 154 + map_literal goto 39 + list_literal goto 38 + basic_literal goto 37 + slice_expr goto 46 + +state 98 + arithmeticExpr: expr ADD.expr + + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + . error + + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 155 + map_literal goto 39 + list_literal goto 38 + basic_literal goto 37 + slice_expr goto 46 + +state 99 + arithmeticExpr: expr SUB.expr + + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + . error + + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 156 + map_literal goto 39 + list_literal goto 38 + basic_literal goto 37 + slice_expr goto 46 + +state 100 + arithmeticExpr: expr MUL.expr + + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + . error + + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 157 + map_literal goto 39 + list_literal goto 38 + basic_literal goto 37 + slice_expr goto 46 + +state 101 + arithmeticExpr: expr DIV.expr + + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + . error + + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 158 + map_literal goto 39 + list_literal goto 38 + basic_literal goto 37 + slice_expr goto 46 + +state 102 + arithmeticExpr: expr MOD.expr + + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + . error + + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 159 + map_literal goto 39 + list_literal goto 38 + basic_literal goto 37 + slice_expr goto 46 + +state 103 + index_expr: expr LEFT_BRACKET.expr EOLS_SPACE RIGHT_BRACKET + slice_expr: expr LEFT_BRACKET.expr_or_empty COLON expr_or_empty COLON expr_or_empty RIGHT_BRACKET + slice_expr: expr LEFT_BRACKET.expr_or_empty COLON expr_or_empty RIGHT_BRACKET + EOLS_SPACE: . (11) + + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + EOL shift 9 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + . reduce 11 (src line 171) + + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 160 + map_literal goto 39 + expr_or_empty goto 161 + list_literal goto 38 + basic_literal goto 37 + slice_expr goto 46 + EOLS goto 163 + EOLS_SPACE goto 162 + +state 104 + attr_expr: expr DOT.expr + + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + . error + + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 164 + map_literal goto 39 + list_literal goto 38 + basic_literal goto 37 + slice_expr goto 46 + +state 105 + let_stmt: LET identifier.COLON data_type EQ expr + let_stmt: LET identifier.COLON data_type + let_stmt: LET identifier. (57) + let_stmt: LET identifier.EQ expr + + COLON shift 165 + EQ shift 166 + . reduce 57 (src line 303) + + +state 106 + const_def_stmt: CONST identifier.EQ expr + + EQ shift 167 + . error + + +state 107 + fn_def_stmt: FN identifier.LEFT_PAREN RIGHT_PAREN stmt_block + fn_def_stmt: FN identifier.LEFT_PAREN RIGHT_PAREN FN_RET data_type stmt_block + fn_def_stmt: FN identifier.LEFT_PAREN RIGHT_PAREN FN_RET LEFT_PAREN fn_ret_types_multi RIGHT_PAREN stmt_block + fn_def_stmt: FN identifier.LEFT_PAREN fn_def_params RIGHT_PAREN stmt_block + fn_def_stmt: FN identifier.LEFT_PAREN fn_def_params RIGHT_PAREN FN_RET data_type stmt_block + fn_def_stmt: FN identifier.LEFT_PAREN fn_def_params RIGHT_PAREN FN_RET LEFT_PAREN fn_ret_types_multi RIGHT_PAREN stmt_block + + LEFT_PAREN shift 168 + . error + + +state 108 + pkg_name: pkg_name.DOT identifier + import_stmt: IMPORT pkg_name. (61) + import_stmt: IMPORT pkg_name.AS identifier + + DOT shift 169 + AS shift 170 + . reduce 61 (src line 329) + + +state 109 + pkg_name: identifier. (59) + + . reduce 59 (src line 319) + + +state 110 + return_stmt: RETURN exprs. (70) + exprs: exprs.COMMA expr + + COMMA shift 112 + . reduce 70 (src line 371) + + +state 111 + exprs: expr. (81) + in_expr: expr.IN expr + call_expr: expr.LEFT_PAREN function_args EOLS_SPACE RIGHT_PAREN + call_expr: expr.LEFT_PAREN function_args COMMA RIGHT_PAREN + call_expr: expr.LEFT_PAREN RIGHT_PAREN + conditional_expr: expr.GTE expr + conditional_expr: expr.GT expr + conditional_expr: expr.OR expr + conditional_expr: expr.AND expr + conditional_expr: expr.LT expr + conditional_expr: expr.LTE expr + conditional_expr: expr.NEQ expr + conditional_expr: expr.EQEQ expr + arithmeticExpr: expr.ADD expr + arithmeticExpr: expr.SUB expr + arithmeticExpr: expr.MUL expr + arithmeticExpr: expr.DIV expr + arithmeticExpr: expr.MOD expr + index_expr: expr.LEFT_BRACKET expr EOLS_SPACE RIGHT_BRACKET + attr_expr: expr.DOT expr + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty COLON expr_or_empty RIGHT_BRACKET + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty RIGHT_BRACKET + + LEFT_PAREN shift 89 + LEFT_BRACKET shift 103 + ADD shift 98 + SUB shift 99 + MUL shift 100 + DIV shift 101 + MOD shift 102 + GTE shift 90 + GT shift 91 + LT shift 94 + LTE shift 95 + NEQ shift 96 + EQEQ shift 97 + AND shift 93 + OR shift 92 + DOT shift 104 + IN shift 88 + . reduce 81 (src line 427) + + +state 112 + exprs: exprs COMMA.expr + + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + . error + + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 171 + map_literal goto 39 + list_literal goto 38 + basic_literal goto 37 + slice_expr goto 46 + +state 113 + assignment_stmt: exprs EQ.exprs + + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + . error + + exprs goto 172 + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 111 + map_literal goto 39 + list_literal goto 38 + basic_literal goto 37 + slice_expr goto 46 + +state 114 + if_elem: IF expr.stmt_block + in_expr: expr.IN expr + call_expr: expr.LEFT_PAREN function_args EOLS_SPACE RIGHT_PAREN + call_expr: expr.LEFT_PAREN function_args COMMA RIGHT_PAREN + call_expr: expr.LEFT_PAREN RIGHT_PAREN + conditional_expr: expr.GTE expr + conditional_expr: expr.GT expr + conditional_expr: expr.OR expr + conditional_expr: expr.AND expr + conditional_expr: expr.LT expr + conditional_expr: expr.LTE expr + conditional_expr: expr.NEQ expr + conditional_expr: expr.EQEQ expr + arithmeticExpr: expr.ADD expr + arithmeticExpr: expr.SUB expr + arithmeticExpr: expr.MUL expr + arithmeticExpr: expr.DIV expr + arithmeticExpr: expr.MOD expr + index_expr: expr.LEFT_BRACKET expr EOLS_SPACE RIGHT_BRACKET + attr_expr: expr.DOT expr + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty COLON expr_or_empty RIGHT_BRACKET + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty RIGHT_BRACKET + + LEFT_PAREN shift 89 + LEFT_BRACKET shift 103 + LEFT_BRACE shift 130 + ADD shift 98 + SUB shift 99 + MUL shift 100 + DIV shift 101 + MOD shift 102 + GTE shift 90 + GT shift 91 + LT shift 94 + LTE shift 95 + NEQ shift 96 + EQEQ shift 97 + AND shift 93 + OR shift 92 + DOT shift 104 + IN shift 88 + . error + + stmt_block goto 173 + empty_block goto 129 + +state 115 + exprs: exprs.COMMA expr + list_literal: LEFT_BRACKET exprs.EOLS_SPACE RIGHT_BRACKET + list_literal: LEFT_BRACKET exprs.COMMA RIGHT_BRACKET + EOLS_SPACE: . (11) + + COMMA shift 174 + EOL shift 9 + . reduce 11 (src line 171) + + EOLS goto 163 + EOLS_SPACE goto 175 + +state 116 + list_literal: LEFT_BRACKET RIGHT_BRACKET. (149) + + . reduce 149 (src line 769) + + +state 117 + map_literal: LEFT_BRACE RIGHT_BRACE. (152) + + . reduce 152 (src line 785) + + +state 118 + expr_colon_expr: expr_colon_expr.COMMA expr COLON expr + map_literal: LEFT_BRACE expr_colon_expr.EOLS_SPACE RIGHT_BRACE + EOLS_SPACE: . (11) + + COMMA shift 176 + EOL shift 9 + . reduce 11 (src line 171) + + EOLS goto 163 + EOLS_SPACE goto 177 + +state 119 + in_expr: expr.IN expr + call_expr: expr.LEFT_PAREN function_args EOLS_SPACE RIGHT_PAREN + call_expr: expr.LEFT_PAREN function_args COMMA RIGHT_PAREN + call_expr: expr.LEFT_PAREN RIGHT_PAREN + conditional_expr: expr.GTE expr + conditional_expr: expr.GT expr + conditional_expr: expr.OR expr + conditional_expr: expr.AND expr + conditional_expr: expr.LT expr + conditional_expr: expr.LTE expr + conditional_expr: expr.NEQ expr + conditional_expr: expr.EQEQ expr + arithmeticExpr: expr.ADD expr + arithmeticExpr: expr.SUB expr + arithmeticExpr: expr.MUL expr + arithmeticExpr: expr.DIV expr + arithmeticExpr: expr.MOD expr + index_expr: expr.LEFT_BRACKET expr EOLS_SPACE RIGHT_BRACKET + attr_expr: expr.DOT expr + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty COLON expr_or_empty RIGHT_BRACKET + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty RIGHT_BRACKET + expr_colon_expr: expr.COLON expr + + LEFT_PAREN shift 89 + LEFT_BRACKET shift 103 + COLON shift 178 + ADD shift 98 + SUB shift 99 + MUL shift 100 + DIV shift 101 + MOD shift 102 + GTE shift 90 + GT shift 91 + LT shift 94 + LTE shift 95 + NEQ shift 96 + EQEQ shift 97 + AND shift 93 + OR shift 92 + DOT shift 104 + IN shift 88 + . error + + +state 120 + in_expr: expr.IN expr + call_expr: expr.LEFT_PAREN function_args EOLS_SPACE RIGHT_PAREN + call_expr: expr.LEFT_PAREN function_args COMMA RIGHT_PAREN + call_expr: expr.LEFT_PAREN RIGHT_PAREN + conditional_expr: expr.GTE expr + conditional_expr: expr.GT expr + conditional_expr: expr.OR expr + conditional_expr: expr.AND expr + conditional_expr: expr.LT expr + conditional_expr: expr.LTE expr + conditional_expr: expr.NEQ expr + conditional_expr: expr.EQEQ expr + arithmeticExpr: expr.ADD expr + arithmeticExpr: expr.SUB expr + arithmeticExpr: expr.MUL expr + arithmeticExpr: expr.DIV expr + arithmeticExpr: expr.MOD expr + paren_expr: LEFT_PAREN expr.EOLS_SPACE RIGHT_PAREN + index_expr: expr.LEFT_BRACKET expr EOLS_SPACE RIGHT_BRACKET + attr_expr: expr.DOT expr + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty COLON expr_or_empty RIGHT_BRACKET + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty RIGHT_BRACKET + EOLS_SPACE: . (11) + + LEFT_PAREN shift 89 + LEFT_BRACKET shift 103 + EOL shift 9 + ADD shift 98 + SUB shift 99 + MUL shift 100 + DIV shift 101 + MOD shift 102 + GTE shift 90 + GT shift 91 + LT shift 94 + LTE shift 95 + NEQ shift 96 + EQEQ shift 97 + AND shift 93 + OR shift 92 + DOT shift 104 + IN shift 88 + . reduce 11 (src line 171) + + EOLS goto 163 + EOLS_SPACE goto 179 + +state 121 + in_expr: expr.IN expr + call_expr: expr.LEFT_PAREN function_args EOLS_SPACE RIGHT_PAREN + call_expr: expr.LEFT_PAREN function_args COMMA RIGHT_PAREN + call_expr: expr.LEFT_PAREN RIGHT_PAREN + unary_expr: ADD expr. (123) + conditional_expr: expr.GTE expr + conditional_expr: expr.GT expr + conditional_expr: expr.OR expr + conditional_expr: expr.AND expr + conditional_expr: expr.LT expr + conditional_expr: expr.LTE expr + conditional_expr: expr.NEQ expr + conditional_expr: expr.EQEQ expr + arithmeticExpr: expr.ADD expr + arithmeticExpr: expr.SUB expr + arithmeticExpr: expr.MUL expr + arithmeticExpr: expr.DIV expr + arithmeticExpr: expr.MOD expr + index_expr: expr.LEFT_BRACKET expr EOLS_SPACE RIGHT_BRACKET + attr_expr: expr.DOT expr + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty COLON expr_or_empty RIGHT_BRACKET + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty RIGHT_BRACKET + + LEFT_PAREN shift 89 + LEFT_BRACKET shift 103 + DOT shift 104 + . reduce 123 (src line 640) + + +state 122 + in_expr: expr.IN expr + call_expr: expr.LEFT_PAREN function_args EOLS_SPACE RIGHT_PAREN + call_expr: expr.LEFT_PAREN function_args COMMA RIGHT_PAREN + call_expr: expr.LEFT_PAREN RIGHT_PAREN + unary_expr: SUB expr. (124) + conditional_expr: expr.GTE expr + conditional_expr: expr.GT expr + conditional_expr: expr.OR expr + conditional_expr: expr.AND expr + conditional_expr: expr.LT expr + conditional_expr: expr.LTE expr + conditional_expr: expr.NEQ expr + conditional_expr: expr.EQEQ expr + arithmeticExpr: expr.ADD expr + arithmeticExpr: expr.SUB expr + arithmeticExpr: expr.MUL expr + arithmeticExpr: expr.DIV expr + arithmeticExpr: expr.MOD expr + index_expr: expr.LEFT_BRACKET expr EOLS_SPACE RIGHT_BRACKET + attr_expr: expr.DOT expr + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty COLON expr_or_empty RIGHT_BRACKET + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty RIGHT_BRACKET + + LEFT_PAREN shift 89 + LEFT_BRACKET shift 103 + DOT shift 104 + . reduce 124 (src line 644) + + +state 123 + in_expr: expr.IN expr + call_expr: expr.LEFT_PAREN function_args EOLS_SPACE RIGHT_PAREN + call_expr: expr.LEFT_PAREN function_args COMMA RIGHT_PAREN + call_expr: expr.LEFT_PAREN RIGHT_PAREN + unary_expr: NOT expr. (125) + conditional_expr: expr.GTE expr + conditional_expr: expr.GT expr + conditional_expr: expr.OR expr + conditional_expr: expr.AND expr + conditional_expr: expr.LT expr + conditional_expr: expr.LTE expr + conditional_expr: expr.NEQ expr + conditional_expr: expr.EQEQ expr + arithmeticExpr: expr.ADD expr + arithmeticExpr: expr.SUB expr + arithmeticExpr: expr.MUL expr + arithmeticExpr: expr.DIV expr + arithmeticExpr: expr.MOD expr + index_expr: expr.LEFT_BRACKET expr EOLS_SPACE RIGHT_BRACKET + attr_expr: expr.DOT expr + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty COLON expr_or_empty RIGHT_BRACKET + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty RIGHT_BRACKET + + LEFT_PAREN shift 89 + LEFT_BRACKET shift 103 + DOT shift 104 + . reduce 125 (src line 648) + + +state 124 + index_expr: DOT LEFT_BRACKET.expr EOLS_SPACE RIGHT_BRACKET + + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + . error + + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 180 + map_literal goto 39 + list_literal goto 38 + basic_literal goto 37 + slice_expr goto 46 + +state 125 + sep: sep.SEMICOLON + sep: sep.EOL + stmts_list: stmts_list stmt sep. (22) + + SEMICOLON shift 126 + EOL shift 127 + . reduce 22 (src line 218) + + +state 126 + sep: sep SEMICOLON. (3) + + . reduce 3 (src line 157) + + +state 127 + sep: sep EOL. (4) + + . reduce 4 (src line 158) + + +state 128 + ifelse_stmt: if_elif_list ELSE stmt_block. (106) + + . reduce 106 (src line 547) + + +state 129 + stmt_block: empty_block. (111) + + . reduce 111 (src line 576) + + +state 130 + stmt_block: LEFT_BRACE.stmts RIGHT_BRACE + empty_block: LEFT_BRACE.RIGHT_BRACE + + SEMICOLON shift 23 + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + RIGHT_BRACE shift 182 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + IF shift 49 + FOR shift 25 + BREAK shift 27 + CONTINUE shift 26 + RETURN shift 33 + FN shift 31 + LET shift 29 + IMPORT shift 32 + CONST shift 30 + . error + + stmts goto 181 + stmts_list goto 7 + if_elem goto 35 + if_elif_list goto 24 + exprs goto 34 + stmt goto 8 + assignment_stmt goto 22 + for_in_stmt goto 12 + for_stmt goto 13 + continue_stmt goto 14 + break_stmt goto 15 + ifelse_stmt goto 11 + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 28 + map_literal goto 39 + value_stmt goto 16 + list_literal goto 38 + basic_literal goto 37 + slice_expr goto 46 + let_stmt goto 17 + const_def_stmt goto 18 + fn_def_stmt goto 19 + import_stmt goto 20 + return_stmt goto 21 + sem goto 10 + +state 131 + elif_elem: ELIF expr.stmt_block + in_expr: expr.IN expr + call_expr: expr.LEFT_PAREN function_args EOLS_SPACE RIGHT_PAREN + call_expr: expr.LEFT_PAREN function_args COMMA RIGHT_PAREN + call_expr: expr.LEFT_PAREN RIGHT_PAREN + conditional_expr: expr.GTE expr + conditional_expr: expr.GT expr + conditional_expr: expr.OR expr + conditional_expr: expr.AND expr + conditional_expr: expr.LT expr + conditional_expr: expr.LTE expr + conditional_expr: expr.NEQ expr + conditional_expr: expr.EQEQ expr + arithmeticExpr: expr.ADD expr + arithmeticExpr: expr.SUB expr + arithmeticExpr: expr.MUL expr + arithmeticExpr: expr.DIV expr + arithmeticExpr: expr.MOD expr + index_expr: expr.LEFT_BRACKET expr EOLS_SPACE RIGHT_BRACKET + attr_expr: expr.DOT expr + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty COLON expr_or_empty RIGHT_BRACKET + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty RIGHT_BRACKET + + LEFT_PAREN shift 89 + LEFT_BRACKET shift 103 + LEFT_BRACE shift 130 + ADD shift 98 + SUB shift 99 + MUL shift 100 + DIV shift 101 + MOD shift 102 + GTE shift 90 + GT shift 91 + LT shift 94 + LTE shift 95 + NEQ shift 96 + EQEQ shift 97 + AND shift 93 + OR shift 92 + DOT shift 104 + IN shift 88 + . error + + stmt_block goto 183 + empty_block goto 129 + +state 132 + for_in_stmt: FOR in_expr stmt_block. (91) + + . reduce 91 (src line 489) + + +state 133 + for_stmt: FOR for_init_elem SEMICOLON.expr SEMICOLON for_loop_elem stmt_block + for_stmt: FOR for_init_elem SEMICOLON.expr SEMICOLON stmt_block + for_stmt: FOR for_init_elem SEMICOLON.SEMICOLON for_loop_elem stmt_block + for_stmt: FOR for_init_elem SEMICOLON.SEMICOLON stmt_block + + SEMICOLON shift 185 + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + . error + + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 184 + map_literal goto 39 + list_literal goto 38 + basic_literal goto 37 + slice_expr goto 46 + +state 134 + for_stmt: FOR SEMICOLON expr.SEMICOLON for_loop_elem stmt_block + for_stmt: FOR SEMICOLON expr.SEMICOLON stmt_block + in_expr: expr.IN expr + call_expr: expr.LEFT_PAREN function_args EOLS_SPACE RIGHT_PAREN + call_expr: expr.LEFT_PAREN function_args COMMA RIGHT_PAREN + call_expr: expr.LEFT_PAREN RIGHT_PAREN + conditional_expr: expr.GTE expr + conditional_expr: expr.GT expr + conditional_expr: expr.OR expr + conditional_expr: expr.AND expr + conditional_expr: expr.LT expr + conditional_expr: expr.LTE expr + conditional_expr: expr.NEQ expr + conditional_expr: expr.EQEQ expr + arithmeticExpr: expr.ADD expr + arithmeticExpr: expr.SUB expr + arithmeticExpr: expr.MUL expr + arithmeticExpr: expr.DIV expr + arithmeticExpr: expr.MOD expr + index_expr: expr.LEFT_BRACKET expr EOLS_SPACE RIGHT_BRACKET + attr_expr: expr.DOT expr + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty COLON expr_or_empty RIGHT_BRACKET + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty RIGHT_BRACKET + + SEMICOLON shift 186 + LEFT_PAREN shift 89 + LEFT_BRACKET shift 103 + ADD shift 98 + SUB shift 99 + MUL shift 100 + DIV shift 101 + MOD shift 102 + GTE shift 90 + GT shift 91 + LT shift 94 + LTE shift 95 + NEQ shift 96 + EQEQ shift 97 + AND shift 93 + OR shift 92 + DOT shift 104 + IN shift 88 + . error + + +state 135 + for_stmt: FOR SEMICOLON SEMICOLON.for_loop_elem stmt_block + for_stmt: FOR SEMICOLON SEMICOLON.stmt_block + + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 191 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + . error + + stmt_block goto 188 + empty_block goto 129 + exprs goto 34 + assignment_stmt goto 190 + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 189 + map_literal goto 39 + list_literal goto 38 + basic_literal goto 37 + for_loop_elem goto 187 + slice_expr goto 46 + +state 136 + assignment_stmt: expr ADD_EQ expr. (84) + in_expr: expr.IN expr + call_expr: expr.LEFT_PAREN function_args EOLS_SPACE RIGHT_PAREN + call_expr: expr.LEFT_PAREN function_args COMMA RIGHT_PAREN + call_expr: expr.LEFT_PAREN RIGHT_PAREN + conditional_expr: expr.GTE expr + conditional_expr: expr.GT expr + conditional_expr: expr.OR expr + conditional_expr: expr.AND expr + conditional_expr: expr.LT expr + conditional_expr: expr.LTE expr + conditional_expr: expr.NEQ expr + conditional_expr: expr.EQEQ expr + arithmeticExpr: expr.ADD expr + arithmeticExpr: expr.SUB expr + arithmeticExpr: expr.MUL expr + arithmeticExpr: expr.DIV expr + arithmeticExpr: expr.MOD expr + index_expr: expr.LEFT_BRACKET expr EOLS_SPACE RIGHT_BRACKET + attr_expr: expr.DOT expr + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty COLON expr_or_empty RIGHT_BRACKET + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty RIGHT_BRACKET + + LEFT_PAREN shift 89 + LEFT_BRACKET shift 103 + ADD shift 98 + SUB shift 99 + MUL shift 100 + DIV shift 101 + MOD shift 102 + GTE shift 90 + GT shift 91 + LT shift 94 + LTE shift 95 + NEQ shift 96 + EQEQ shift 97 + AND shift 93 + OR shift 92 + DOT shift 104 + IN shift 88 + . reduce 84 (src line 443) + + +state 137 + assignment_stmt: expr SUB_EQ expr. (85) + in_expr: expr.IN expr + call_expr: expr.LEFT_PAREN function_args EOLS_SPACE RIGHT_PAREN + call_expr: expr.LEFT_PAREN function_args COMMA RIGHT_PAREN + call_expr: expr.LEFT_PAREN RIGHT_PAREN + conditional_expr: expr.GTE expr + conditional_expr: expr.GT expr + conditional_expr: expr.OR expr + conditional_expr: expr.AND expr + conditional_expr: expr.LT expr + conditional_expr: expr.LTE expr + conditional_expr: expr.NEQ expr + conditional_expr: expr.EQEQ expr + arithmeticExpr: expr.ADD expr + arithmeticExpr: expr.SUB expr + arithmeticExpr: expr.MUL expr + arithmeticExpr: expr.DIV expr + arithmeticExpr: expr.MOD expr + index_expr: expr.LEFT_BRACKET expr EOLS_SPACE RIGHT_BRACKET + attr_expr: expr.DOT expr + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty COLON expr_or_empty RIGHT_BRACKET + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty RIGHT_BRACKET + + LEFT_PAREN shift 89 + LEFT_BRACKET shift 103 + ADD shift 98 + SUB shift 99 + MUL shift 100 + DIV shift 101 + MOD shift 102 + GTE shift 90 + GT shift 91 + LT shift 94 + LTE shift 95 + NEQ shift 96 + EQEQ shift 97 + AND shift 93 + OR shift 92 + DOT shift 104 + IN shift 88 + . reduce 85 (src line 448) + + +state 138 + assignment_stmt: expr MUL_EQ expr. (86) + in_expr: expr.IN expr + call_expr: expr.LEFT_PAREN function_args EOLS_SPACE RIGHT_PAREN + call_expr: expr.LEFT_PAREN function_args COMMA RIGHT_PAREN + call_expr: expr.LEFT_PAREN RIGHT_PAREN + conditional_expr: expr.GTE expr + conditional_expr: expr.GT expr + conditional_expr: expr.OR expr + conditional_expr: expr.AND expr + conditional_expr: expr.LT expr + conditional_expr: expr.LTE expr + conditional_expr: expr.NEQ expr + conditional_expr: expr.EQEQ expr + arithmeticExpr: expr.ADD expr + arithmeticExpr: expr.SUB expr + arithmeticExpr: expr.MUL expr + arithmeticExpr: expr.DIV expr + arithmeticExpr: expr.MOD expr + index_expr: expr.LEFT_BRACKET expr EOLS_SPACE RIGHT_BRACKET + attr_expr: expr.DOT expr + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty COLON expr_or_empty RIGHT_BRACKET + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty RIGHT_BRACKET + + LEFT_PAREN shift 89 + LEFT_BRACKET shift 103 + ADD shift 98 + SUB shift 99 + MUL shift 100 + DIV shift 101 + MOD shift 102 + GTE shift 90 + GT shift 91 + LT shift 94 + LTE shift 95 + NEQ shift 96 + EQEQ shift 97 + AND shift 93 + OR shift 92 + DOT shift 104 + IN shift 88 + . reduce 86 (src line 453) + + +state 139 + assignment_stmt: expr DIV_EQ expr. (87) + in_expr: expr.IN expr + call_expr: expr.LEFT_PAREN function_args EOLS_SPACE RIGHT_PAREN + call_expr: expr.LEFT_PAREN function_args COMMA RIGHT_PAREN + call_expr: expr.LEFT_PAREN RIGHT_PAREN + conditional_expr: expr.GTE expr + conditional_expr: expr.GT expr + conditional_expr: expr.OR expr + conditional_expr: expr.AND expr + conditional_expr: expr.LT expr + conditional_expr: expr.LTE expr + conditional_expr: expr.NEQ expr + conditional_expr: expr.EQEQ expr + arithmeticExpr: expr.ADD expr + arithmeticExpr: expr.SUB expr + arithmeticExpr: expr.MUL expr + arithmeticExpr: expr.DIV expr + arithmeticExpr: expr.MOD expr + index_expr: expr.LEFT_BRACKET expr EOLS_SPACE RIGHT_BRACKET + attr_expr: expr.DOT expr + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty COLON expr_or_empty RIGHT_BRACKET + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty RIGHT_BRACKET + + LEFT_PAREN shift 89 + LEFT_BRACKET shift 103 + ADD shift 98 + SUB shift 99 + MUL shift 100 + DIV shift 101 + MOD shift 102 + GTE shift 90 + GT shift 91 + LT shift 94 + LTE shift 95 + NEQ shift 96 + EQEQ shift 97 + AND shift 93 + OR shift 92 + DOT shift 104 + IN shift 88 + . reduce 87 (src line 458) + + +state 140 + assignment_stmt: expr MOD_EQ expr. (88) + in_expr: expr.IN expr + call_expr: expr.LEFT_PAREN function_args EOLS_SPACE RIGHT_PAREN + call_expr: expr.LEFT_PAREN function_args COMMA RIGHT_PAREN + call_expr: expr.LEFT_PAREN RIGHT_PAREN + conditional_expr: expr.GTE expr + conditional_expr: expr.GT expr + conditional_expr: expr.OR expr + conditional_expr: expr.AND expr + conditional_expr: expr.LT expr + conditional_expr: expr.LTE expr + conditional_expr: expr.NEQ expr + conditional_expr: expr.EQEQ expr + arithmeticExpr: expr.ADD expr + arithmeticExpr: expr.SUB expr + arithmeticExpr: expr.MUL expr + arithmeticExpr: expr.DIV expr + arithmeticExpr: expr.MOD expr + index_expr: expr.LEFT_BRACKET expr EOLS_SPACE RIGHT_BRACKET + attr_expr: expr.DOT expr + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty COLON expr_or_empty RIGHT_BRACKET + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty RIGHT_BRACKET + + LEFT_PAREN shift 89 + LEFT_BRACKET shift 103 + ADD shift 98 + SUB shift 99 + MUL shift 100 + DIV shift 101 + MOD shift 102 + GTE shift 90 + GT shift 91 + LT shift 94 + LTE shift 95 + NEQ shift 96 + EQEQ shift 97 + AND shift 93 + OR shift 92 + DOT shift 104 + IN shift 88 + . reduce 88 (src line 463) + + +state 141 + in_expr: expr.IN expr + in_expr: expr IN expr. (114) + call_expr: expr.LEFT_PAREN function_args EOLS_SPACE RIGHT_PAREN + call_expr: expr.LEFT_PAREN function_args COMMA RIGHT_PAREN + call_expr: expr.LEFT_PAREN RIGHT_PAREN + conditional_expr: expr.GTE expr + conditional_expr: expr.GT expr + conditional_expr: expr.OR expr + conditional_expr: expr.AND expr + conditional_expr: expr.LT expr + conditional_expr: expr.LTE expr + conditional_expr: expr.NEQ expr + conditional_expr: expr.EQEQ expr + arithmeticExpr: expr.ADD expr + arithmeticExpr: expr.SUB expr + arithmeticExpr: expr.MUL expr + arithmeticExpr: expr.DIV expr + arithmeticExpr: expr.MOD expr + index_expr: expr.LEFT_BRACKET expr EOLS_SPACE RIGHT_BRACKET + attr_expr: expr.DOT expr + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty COLON expr_or_empty RIGHT_BRACKET + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty RIGHT_BRACKET + + LEFT_PAREN shift 89 + LEFT_BRACKET shift 103 + ADD shift 98 + SUB shift 99 + MUL shift 100 + DIV shift 101 + MOD shift 102 + GTE shift 90 + GT shift 91 + LT shift 94 + LTE shift 95 + NEQ shift 96 + EQEQ shift 97 + DOT shift 104 + . reduce 114 (src line 595) + + +state 142 + function_args: function_args.COMMA expr + function_args: function_args.COMMA named_arg + call_expr: expr LEFT_PAREN function_args.EOLS_SPACE RIGHT_PAREN + call_expr: expr LEFT_PAREN function_args.COMMA RIGHT_PAREN + EOLS_SPACE: . (11) + + COMMA shift 192 + EOL shift 9 + . reduce 11 (src line 171) + + EOLS goto 163 + EOLS_SPACE goto 193 + +state 143 + call_expr: expr LEFT_PAREN RIGHT_PAREN. (122) + + . reduce 122 (src line 634) + + +state 144 + function_args: named_arg. (117) + + . reduce 117 (src line 609) + + +state 145 + in_expr: expr.IN expr + function_args: expr. (118) + call_expr: expr.LEFT_PAREN function_args EOLS_SPACE RIGHT_PAREN + call_expr: expr.LEFT_PAREN function_args COMMA RIGHT_PAREN + call_expr: expr.LEFT_PAREN RIGHT_PAREN + conditional_expr: expr.GTE expr + conditional_expr: expr.GT expr + conditional_expr: expr.OR expr + conditional_expr: expr.AND expr + conditional_expr: expr.LT expr + conditional_expr: expr.LTE expr + conditional_expr: expr.NEQ expr + conditional_expr: expr.EQEQ expr + arithmeticExpr: expr.ADD expr + arithmeticExpr: expr.SUB expr + arithmeticExpr: expr.MUL expr + arithmeticExpr: expr.DIV expr + arithmeticExpr: expr.MOD expr + index_expr: expr.LEFT_BRACKET expr EOLS_SPACE RIGHT_BRACKET + attr_expr: expr.DOT expr + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty COLON expr_or_empty RIGHT_BRACKET + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty RIGHT_BRACKET + + LEFT_PAREN shift 89 + LEFT_BRACKET shift 103 + ADD shift 98 + SUB shift 99 + MUL shift 100 + DIV shift 101 + MOD shift 102 + GTE shift 90 + GT shift 91 + LT shift 94 + LTE shift 95 + NEQ shift 96 + EQEQ shift 97 + AND shift 93 + OR shift 92 + DOT shift 104 + IN shift 88 + . reduce 118 (src line 613) + + +state 146 + expr: identifier. (36) + named_arg: identifier.EQ expr + + EQ shift 194 + . reduce 36 (src line 245) + + +state 147 + in_expr: expr.IN expr + call_expr: expr.LEFT_PAREN function_args EOLS_SPACE RIGHT_PAREN + call_expr: expr.LEFT_PAREN function_args COMMA RIGHT_PAREN + call_expr: expr.LEFT_PAREN RIGHT_PAREN + conditional_expr: expr.GTE expr + conditional_expr: expr GTE expr. (126) + conditional_expr: expr.GT expr + conditional_expr: expr.OR expr + conditional_expr: expr.AND expr + conditional_expr: expr.LT expr + conditional_expr: expr.LTE expr + conditional_expr: expr.NEQ expr + conditional_expr: expr.EQEQ expr + arithmeticExpr: expr.ADD expr + arithmeticExpr: expr.SUB expr + arithmeticExpr: expr.MUL expr + arithmeticExpr: expr.DIV expr + arithmeticExpr: expr.MOD expr + index_expr: expr.LEFT_BRACKET expr EOLS_SPACE RIGHT_BRACKET + attr_expr: expr.DOT expr + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty COLON expr_or_empty RIGHT_BRACKET + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty RIGHT_BRACKET + + LEFT_PAREN shift 89 + LEFT_BRACKET shift 103 + ADD shift 98 + SUB shift 99 + MUL shift 100 + DIV shift 101 + MOD shift 102 + DOT shift 104 + . reduce 126 (src line 654) + + +state 148 + in_expr: expr.IN expr + call_expr: expr.LEFT_PAREN function_args EOLS_SPACE RIGHT_PAREN + call_expr: expr.LEFT_PAREN function_args COMMA RIGHT_PAREN + call_expr: expr.LEFT_PAREN RIGHT_PAREN + conditional_expr: expr.GTE expr + conditional_expr: expr.GT expr + conditional_expr: expr GT expr. (127) + conditional_expr: expr.OR expr + conditional_expr: expr.AND expr + conditional_expr: expr.LT expr + conditional_expr: expr.LTE expr + conditional_expr: expr.NEQ expr + conditional_expr: expr.EQEQ expr + arithmeticExpr: expr.ADD expr + arithmeticExpr: expr.SUB expr + arithmeticExpr: expr.MUL expr + arithmeticExpr: expr.DIV expr + arithmeticExpr: expr.MOD expr + index_expr: expr.LEFT_BRACKET expr EOLS_SPACE RIGHT_BRACKET + attr_expr: expr.DOT expr + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty COLON expr_or_empty RIGHT_BRACKET + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty RIGHT_BRACKET + + LEFT_PAREN shift 89 + LEFT_BRACKET shift 103 + ADD shift 98 + SUB shift 99 + MUL shift 100 + DIV shift 101 + MOD shift 102 + DOT shift 104 + . reduce 127 (src line 658) + + +state 149 + in_expr: expr.IN expr + call_expr: expr.LEFT_PAREN function_args EOLS_SPACE RIGHT_PAREN + call_expr: expr.LEFT_PAREN function_args COMMA RIGHT_PAREN + call_expr: expr.LEFT_PAREN RIGHT_PAREN + conditional_expr: expr.GTE expr + conditional_expr: expr.GT expr + conditional_expr: expr.OR expr + conditional_expr: expr OR expr. (128) + conditional_expr: expr.AND expr + conditional_expr: expr.LT expr + conditional_expr: expr.LTE expr + conditional_expr: expr.NEQ expr + conditional_expr: expr.EQEQ expr + arithmeticExpr: expr.ADD expr + arithmeticExpr: expr.SUB expr + arithmeticExpr: expr.MUL expr + arithmeticExpr: expr.DIV expr + arithmeticExpr: expr.MOD expr + index_expr: expr.LEFT_BRACKET expr EOLS_SPACE RIGHT_BRACKET + attr_expr: expr.DOT expr + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty COLON expr_or_empty RIGHT_BRACKET + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty RIGHT_BRACKET + + LEFT_PAREN shift 89 + LEFT_BRACKET shift 103 + ADD shift 98 + SUB shift 99 + MUL shift 100 + DIV shift 101 + MOD shift 102 + GTE shift 90 + GT shift 91 + LT shift 94 + LTE shift 95 + NEQ shift 96 + EQEQ shift 97 + AND shift 93 + DOT shift 104 + IN shift 88 + . reduce 128 (src line 662) + + +state 150 + in_expr: expr.IN expr + call_expr: expr.LEFT_PAREN function_args EOLS_SPACE RIGHT_PAREN + call_expr: expr.LEFT_PAREN function_args COMMA RIGHT_PAREN + call_expr: expr.LEFT_PAREN RIGHT_PAREN + conditional_expr: expr.GTE expr + conditional_expr: expr.GT expr + conditional_expr: expr.OR expr + conditional_expr: expr.AND expr + conditional_expr: expr AND expr. (129) + conditional_expr: expr.LT expr + conditional_expr: expr.LTE expr + conditional_expr: expr.NEQ expr + conditional_expr: expr.EQEQ expr + arithmeticExpr: expr.ADD expr + arithmeticExpr: expr.SUB expr + arithmeticExpr: expr.MUL expr + arithmeticExpr: expr.DIV expr + arithmeticExpr: expr.MOD expr + index_expr: expr.LEFT_BRACKET expr EOLS_SPACE RIGHT_BRACKET + attr_expr: expr.DOT expr + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty COLON expr_or_empty RIGHT_BRACKET + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty RIGHT_BRACKET + + LEFT_PAREN shift 89 + LEFT_BRACKET shift 103 + ADD shift 98 + SUB shift 99 + MUL shift 100 + DIV shift 101 + MOD shift 102 + GTE shift 90 + GT shift 91 + LT shift 94 + LTE shift 95 + NEQ shift 96 + EQEQ shift 97 + DOT shift 104 + IN shift 88 + . reduce 129 (src line 666) + + +state 151 + in_expr: expr.IN expr + call_expr: expr.LEFT_PAREN function_args EOLS_SPACE RIGHT_PAREN + call_expr: expr.LEFT_PAREN function_args COMMA RIGHT_PAREN + call_expr: expr.LEFT_PAREN RIGHT_PAREN + conditional_expr: expr.GTE expr + conditional_expr: expr.GT expr + conditional_expr: expr.OR expr + conditional_expr: expr.AND expr + conditional_expr: expr.LT expr + conditional_expr: expr LT expr. (130) + conditional_expr: expr.LTE expr + conditional_expr: expr.NEQ expr + conditional_expr: expr.EQEQ expr + arithmeticExpr: expr.ADD expr + arithmeticExpr: expr.SUB expr + arithmeticExpr: expr.MUL expr + arithmeticExpr: expr.DIV expr + arithmeticExpr: expr.MOD expr + index_expr: expr.LEFT_BRACKET expr EOLS_SPACE RIGHT_BRACKET + attr_expr: expr.DOT expr + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty COLON expr_or_empty RIGHT_BRACKET + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty RIGHT_BRACKET + + LEFT_PAREN shift 89 + LEFT_BRACKET shift 103 + ADD shift 98 + SUB shift 99 + MUL shift 100 + DIV shift 101 + MOD shift 102 + DOT shift 104 + . reduce 130 (src line 670) + + +state 152 + in_expr: expr.IN expr + call_expr: expr.LEFT_PAREN function_args EOLS_SPACE RIGHT_PAREN + call_expr: expr.LEFT_PAREN function_args COMMA RIGHT_PAREN + call_expr: expr.LEFT_PAREN RIGHT_PAREN + conditional_expr: expr.GTE expr + conditional_expr: expr.GT expr + conditional_expr: expr.OR expr + conditional_expr: expr.AND expr + conditional_expr: expr.LT expr + conditional_expr: expr.LTE expr + conditional_expr: expr LTE expr. (131) + conditional_expr: expr.NEQ expr + conditional_expr: expr.EQEQ expr + arithmeticExpr: expr.ADD expr + arithmeticExpr: expr.SUB expr + arithmeticExpr: expr.MUL expr + arithmeticExpr: expr.DIV expr + arithmeticExpr: expr.MOD expr + index_expr: expr.LEFT_BRACKET expr EOLS_SPACE RIGHT_BRACKET + attr_expr: expr.DOT expr + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty COLON expr_or_empty RIGHT_BRACKET + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty RIGHT_BRACKET + + LEFT_PAREN shift 89 + LEFT_BRACKET shift 103 + ADD shift 98 + SUB shift 99 + MUL shift 100 + DIV shift 101 + MOD shift 102 + DOT shift 104 + . reduce 131 (src line 674) + + +state 153 + in_expr: expr.IN expr + call_expr: expr.LEFT_PAREN function_args EOLS_SPACE RIGHT_PAREN + call_expr: expr.LEFT_PAREN function_args COMMA RIGHT_PAREN + call_expr: expr.LEFT_PAREN RIGHT_PAREN + conditional_expr: expr.GTE expr + conditional_expr: expr.GT expr + conditional_expr: expr.OR expr + conditional_expr: expr.AND expr + conditional_expr: expr.LT expr + conditional_expr: expr.LTE expr + conditional_expr: expr.NEQ expr + conditional_expr: expr NEQ expr. (132) + conditional_expr: expr.EQEQ expr + arithmeticExpr: expr.ADD expr + arithmeticExpr: expr.SUB expr + arithmeticExpr: expr.MUL expr + arithmeticExpr: expr.DIV expr + arithmeticExpr: expr.MOD expr + index_expr: expr.LEFT_BRACKET expr EOLS_SPACE RIGHT_BRACKET + attr_expr: expr.DOT expr + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty COLON expr_or_empty RIGHT_BRACKET + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty RIGHT_BRACKET + + LEFT_PAREN shift 89 + LEFT_BRACKET shift 103 + ADD shift 98 + SUB shift 99 + MUL shift 100 + DIV shift 101 + MOD shift 102 + DOT shift 104 + . reduce 132 (src line 678) + + +state 154 + in_expr: expr.IN expr + call_expr: expr.LEFT_PAREN function_args EOLS_SPACE RIGHT_PAREN + call_expr: expr.LEFT_PAREN function_args COMMA RIGHT_PAREN + call_expr: expr.LEFT_PAREN RIGHT_PAREN + conditional_expr: expr.GTE expr + conditional_expr: expr.GT expr + conditional_expr: expr.OR expr + conditional_expr: expr.AND expr + conditional_expr: expr.LT expr + conditional_expr: expr.LTE expr + conditional_expr: expr.NEQ expr + conditional_expr: expr.EQEQ expr + conditional_expr: expr EQEQ expr. (133) + arithmeticExpr: expr.ADD expr + arithmeticExpr: expr.SUB expr + arithmeticExpr: expr.MUL expr + arithmeticExpr: expr.DIV expr + arithmeticExpr: expr.MOD expr + index_expr: expr.LEFT_BRACKET expr EOLS_SPACE RIGHT_BRACKET + attr_expr: expr.DOT expr + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty COLON expr_or_empty RIGHT_BRACKET + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty RIGHT_BRACKET + + LEFT_PAREN shift 89 + LEFT_BRACKET shift 103 + ADD shift 98 + SUB shift 99 + MUL shift 100 + DIV shift 101 + MOD shift 102 + DOT shift 104 + . reduce 133 (src line 682) + + +state 155 + in_expr: expr.IN expr + call_expr: expr.LEFT_PAREN function_args EOLS_SPACE RIGHT_PAREN + call_expr: expr.LEFT_PAREN function_args COMMA RIGHT_PAREN + call_expr: expr.LEFT_PAREN RIGHT_PAREN + conditional_expr: expr.GTE expr + conditional_expr: expr.GT expr + conditional_expr: expr.OR expr + conditional_expr: expr.AND expr + conditional_expr: expr.LT expr + conditional_expr: expr.LTE expr + conditional_expr: expr.NEQ expr + conditional_expr: expr.EQEQ expr + arithmeticExpr: expr.ADD expr + arithmeticExpr: expr ADD expr. (134) + arithmeticExpr: expr.SUB expr + arithmeticExpr: expr.MUL expr + arithmeticExpr: expr.DIV expr + arithmeticExpr: expr.MOD expr + index_expr: expr.LEFT_BRACKET expr EOLS_SPACE RIGHT_BRACKET + attr_expr: expr.DOT expr + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty COLON expr_or_empty RIGHT_BRACKET + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty RIGHT_BRACKET + + LEFT_PAREN shift 89 + LEFT_BRACKET shift 103 + MUL shift 100 + DIV shift 101 + MOD shift 102 + DOT shift 104 + . reduce 134 (src line 689) + + +state 156 + in_expr: expr.IN expr + call_expr: expr.LEFT_PAREN function_args EOLS_SPACE RIGHT_PAREN + call_expr: expr.LEFT_PAREN function_args COMMA RIGHT_PAREN + call_expr: expr.LEFT_PAREN RIGHT_PAREN + conditional_expr: expr.GTE expr + conditional_expr: expr.GT expr + conditional_expr: expr.OR expr + conditional_expr: expr.AND expr + conditional_expr: expr.LT expr + conditional_expr: expr.LTE expr + conditional_expr: expr.NEQ expr + conditional_expr: expr.EQEQ expr + arithmeticExpr: expr.ADD expr + arithmeticExpr: expr.SUB expr + arithmeticExpr: expr SUB expr. (135) + arithmeticExpr: expr.MUL expr + arithmeticExpr: expr.DIV expr + arithmeticExpr: expr.MOD expr + index_expr: expr.LEFT_BRACKET expr EOLS_SPACE RIGHT_BRACKET + attr_expr: expr.DOT expr + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty COLON expr_or_empty RIGHT_BRACKET + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty RIGHT_BRACKET + + LEFT_PAREN shift 89 + LEFT_BRACKET shift 103 + MUL shift 100 + DIV shift 101 + MOD shift 102 + DOT shift 104 + . reduce 135 (src line 693) + + +state 157 + in_expr: expr.IN expr + call_expr: expr.LEFT_PAREN function_args EOLS_SPACE RIGHT_PAREN + call_expr: expr.LEFT_PAREN function_args COMMA RIGHT_PAREN + call_expr: expr.LEFT_PAREN RIGHT_PAREN + conditional_expr: expr.GTE expr + conditional_expr: expr.GT expr + conditional_expr: expr.OR expr + conditional_expr: expr.AND expr + conditional_expr: expr.LT expr + conditional_expr: expr.LTE expr + conditional_expr: expr.NEQ expr + conditional_expr: expr.EQEQ expr + arithmeticExpr: expr.ADD expr + arithmeticExpr: expr.SUB expr + arithmeticExpr: expr.MUL expr + arithmeticExpr: expr MUL expr. (136) + arithmeticExpr: expr.DIV expr + arithmeticExpr: expr.MOD expr + index_expr: expr.LEFT_BRACKET expr EOLS_SPACE RIGHT_BRACKET + attr_expr: expr.DOT expr + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty COLON expr_or_empty RIGHT_BRACKET + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty RIGHT_BRACKET + + LEFT_PAREN shift 89 + LEFT_BRACKET shift 103 + DOT shift 104 + . reduce 136 (src line 697) + + +state 158 + in_expr: expr.IN expr + call_expr: expr.LEFT_PAREN function_args EOLS_SPACE RIGHT_PAREN + call_expr: expr.LEFT_PAREN function_args COMMA RIGHT_PAREN + call_expr: expr.LEFT_PAREN RIGHT_PAREN + conditional_expr: expr.GTE expr + conditional_expr: expr.GT expr + conditional_expr: expr.OR expr + conditional_expr: expr.AND expr + conditional_expr: expr.LT expr + conditional_expr: expr.LTE expr + conditional_expr: expr.NEQ expr + conditional_expr: expr.EQEQ expr + arithmeticExpr: expr.ADD expr + arithmeticExpr: expr.SUB expr + arithmeticExpr: expr.MUL expr + arithmeticExpr: expr.DIV expr + arithmeticExpr: expr DIV expr. (137) + arithmeticExpr: expr.MOD expr + index_expr: expr.LEFT_BRACKET expr EOLS_SPACE RIGHT_BRACKET + attr_expr: expr.DOT expr + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty COLON expr_or_empty RIGHT_BRACKET + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty RIGHT_BRACKET + + LEFT_PAREN shift 89 + LEFT_BRACKET shift 103 + DOT shift 104 + . reduce 137 (src line 701) + + +state 159 + in_expr: expr.IN expr + call_expr: expr.LEFT_PAREN function_args EOLS_SPACE RIGHT_PAREN + call_expr: expr.LEFT_PAREN function_args COMMA RIGHT_PAREN + call_expr: expr.LEFT_PAREN RIGHT_PAREN + conditional_expr: expr.GTE expr + conditional_expr: expr.GT expr + conditional_expr: expr.OR expr + conditional_expr: expr.AND expr + conditional_expr: expr.LT expr + conditional_expr: expr.LTE expr + conditional_expr: expr.NEQ expr + conditional_expr: expr.EQEQ expr + arithmeticExpr: expr.ADD expr + arithmeticExpr: expr.SUB expr + arithmeticExpr: expr.MUL expr + arithmeticExpr: expr.DIV expr + arithmeticExpr: expr.MOD expr + arithmeticExpr: expr MOD expr. (138) + index_expr: expr.LEFT_BRACKET expr EOLS_SPACE RIGHT_BRACKET + attr_expr: expr.DOT expr + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty COLON expr_or_empty RIGHT_BRACKET + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty RIGHT_BRACKET + + LEFT_PAREN shift 89 + LEFT_BRACKET shift 103 + DOT shift 104 + . reduce 138 (src line 705) + + +state 160 + in_expr: expr.IN expr + call_expr: expr.LEFT_PAREN function_args EOLS_SPACE RIGHT_PAREN + call_expr: expr.LEFT_PAREN function_args COMMA RIGHT_PAREN + call_expr: expr.LEFT_PAREN RIGHT_PAREN + conditional_expr: expr.GTE expr + conditional_expr: expr.GT expr + conditional_expr: expr.OR expr + conditional_expr: expr.AND expr + conditional_expr: expr.LT expr + conditional_expr: expr.LTE expr + conditional_expr: expr.NEQ expr + conditional_expr: expr.EQEQ expr + arithmeticExpr: expr.ADD expr + arithmeticExpr: expr.SUB expr + arithmeticExpr: expr.MUL expr + arithmeticExpr: expr.DIV expr + arithmeticExpr: expr.MOD expr + index_expr: expr.LEFT_BRACKET expr EOLS_SPACE RIGHT_BRACKET + index_expr: expr LEFT_BRACKET expr.EOLS_SPACE RIGHT_BRACKET + attr_expr: expr.DOT expr + expr_or_empty: expr. (143) + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty COLON expr_or_empty RIGHT_BRACKET + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty RIGHT_BRACKET + EOLS_SPACE: . (11) + + LEFT_PAREN shift 89 + LEFT_BRACKET shift 103 + COLON reduce 143 (src line 737) + EOL shift 9 + ADD shift 98 + SUB shift 99 + MUL shift 100 + DIV shift 101 + MOD shift 102 + GTE shift 90 + GT shift 91 + LT shift 94 + LTE shift 95 + NEQ shift 96 + EQEQ shift 97 + AND shift 93 + OR shift 92 + DOT shift 104 + IN shift 88 + . reduce 11 (src line 171) + + EOLS goto 163 + EOLS_SPACE goto 195 + +state 161 + slice_expr: expr LEFT_BRACKET expr_or_empty.COLON expr_or_empty COLON expr_or_empty RIGHT_BRACKET + slice_expr: expr LEFT_BRACKET expr_or_empty.COLON expr_or_empty RIGHT_BRACKET + + COLON shift 196 + . error + + +state 162 + expr_or_empty: EOLS_SPACE. (144) + + . reduce 144 (src line 741) + + +state 163 + EOLS: EOLS.EOL + EOLS_SPACE: EOLS. (10) + + EOL shift 66 + . reduce 10 (src line 170) + + +state 164 + in_expr: expr.IN expr + call_expr: expr.LEFT_PAREN function_args EOLS_SPACE RIGHT_PAREN + call_expr: expr.LEFT_PAREN function_args COMMA RIGHT_PAREN + call_expr: expr.LEFT_PAREN RIGHT_PAREN + conditional_expr: expr.GTE expr + conditional_expr: expr.GT expr + conditional_expr: expr.OR expr + conditional_expr: expr.AND expr + conditional_expr: expr.LT expr + conditional_expr: expr.LTE expr + conditional_expr: expr.NEQ expr + conditional_expr: expr.EQEQ expr + arithmeticExpr: expr.ADD expr + arithmeticExpr: expr.SUB expr + arithmeticExpr: expr.MUL expr + arithmeticExpr: expr.DIV expr + arithmeticExpr: expr.MOD expr + index_expr: expr.LEFT_BRACKET expr EOLS_SPACE RIGHT_BRACKET + attr_expr: expr.DOT expr + attr_expr: expr DOT expr. (142) + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty COLON expr_or_empty RIGHT_BRACKET + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty RIGHT_BRACKET + + . reduce 142 (src line 730) + + +state 165 + let_stmt: LET identifier COLON.data_type EQ expr + let_stmt: LET identifier COLON.data_type + + STR shift 200 + INT shift 198 + FLOAT shift 199 + BOOL shift 201 + ANY shift 202 + . error + + data_type goto 197 + +state 166 + let_stmt: LET identifier EQ.expr + + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + . error + + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 203 + map_literal goto 39 + list_literal goto 38 + basic_literal goto 37 + slice_expr goto 46 + +state 167 + const_def_stmt: CONST identifier EQ.expr + + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + . error + + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 204 + map_literal goto 39 + list_literal goto 38 + basic_literal goto 37 + slice_expr goto 46 + +state 168 + fn_def_stmt: FN identifier LEFT_PAREN.RIGHT_PAREN stmt_block + fn_def_stmt: FN identifier LEFT_PAREN.RIGHT_PAREN FN_RET data_type stmt_block + fn_def_stmt: FN identifier LEFT_PAREN.RIGHT_PAREN FN_RET LEFT_PAREN fn_ret_types_multi RIGHT_PAREN stmt_block + fn_def_stmt: FN identifier LEFT_PAREN.fn_def_params RIGHT_PAREN stmt_block + fn_def_stmt: FN identifier LEFT_PAREN.fn_def_params RIGHT_PAREN FN_RET data_type stmt_block + fn_def_stmt: FN identifier LEFT_PAREN.fn_def_params RIGHT_PAREN FN_RET LEFT_PAREN fn_ret_types_multi RIGHT_PAREN stmt_block + + ID shift 50 + RIGHT_PAREN shift 205 + QUOTED_STRING shift 51 + . error + + identifier goto 208 + fn_def_param goto 207 + fn_def_params goto 206 + +state 169 + pkg_name: pkg_name DOT.identifier + + ID shift 50 + QUOTED_STRING shift 51 + . error + + identifier goto 209 + +state 170 + import_stmt: IMPORT pkg_name AS.identifier + + ID shift 50 + QUOTED_STRING shift 51 + . error + + identifier goto 210 + +state 171 + exprs: exprs COMMA expr. (82) + in_expr: expr.IN expr + call_expr: expr.LEFT_PAREN function_args EOLS_SPACE RIGHT_PAREN + call_expr: expr.LEFT_PAREN function_args COMMA RIGHT_PAREN + call_expr: expr.LEFT_PAREN RIGHT_PAREN + conditional_expr: expr.GTE expr + conditional_expr: expr.GT expr + conditional_expr: expr.OR expr + conditional_expr: expr.AND expr + conditional_expr: expr.LT expr + conditional_expr: expr.LTE expr + conditional_expr: expr.NEQ expr + conditional_expr: expr.EQEQ expr + arithmeticExpr: expr.ADD expr + arithmeticExpr: expr.SUB expr + arithmeticExpr: expr.MUL expr + arithmeticExpr: expr.DIV expr + arithmeticExpr: expr.MOD expr + index_expr: expr.LEFT_BRACKET expr EOLS_SPACE RIGHT_BRACKET + attr_expr: expr.DOT expr + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty COLON expr_or_empty RIGHT_BRACKET + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty RIGHT_BRACKET + + LEFT_PAREN shift 89 + LEFT_BRACKET shift 103 + ADD shift 98 + SUB shift 99 + MUL shift 100 + DIV shift 101 + MOD shift 102 + GTE shift 90 + GT shift 91 + LT shift 94 + LTE shift 95 + NEQ shift 96 + EQEQ shift 97 + AND shift 93 + OR shift 92 + DOT shift 104 + IN shift 88 + . reduce 82 (src line 431) + + +state 172 + exprs: exprs.COMMA expr + assignment_stmt: exprs EQ exprs. (83) + + COMMA shift 112 + . reduce 83 (src line 438) + + +state 173 + if_elem: IF expr stmt_block. (107) + + . reduce 107 (src line 553) + + +state 174 + exprs: exprs COMMA.expr + list_literal: LEFT_BRACKET exprs COMMA.RIGHT_BRACKET + + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + RIGHT_BRACKET shift 211 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + . error + + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 171 + map_literal goto 39 + list_literal goto 38 + basic_literal goto 37 + slice_expr goto 46 + +state 175 + list_literal: LEFT_BRACKET exprs EOLS_SPACE.RIGHT_BRACKET + + RIGHT_BRACKET shift 212 + . error + + +state 176 + expr_colon_expr: expr_colon_expr COMMA.expr COLON expr + + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + . error + + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 213 + map_literal goto 39 + list_literal goto 38 + basic_literal goto 37 + slice_expr goto 46 + +state 177 + map_literal: LEFT_BRACE expr_colon_expr EOLS_SPACE.RIGHT_BRACE + + RIGHT_BRACE shift 214 + . error + + +state 178 + expr_colon_expr: expr COLON.expr + + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + . error + + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 215 + map_literal goto 39 + list_literal goto 38 + basic_literal goto 37 + slice_expr goto 46 + +state 179 + paren_expr: LEFT_PAREN expr EOLS_SPACE.RIGHT_PAREN + + RIGHT_PAREN shift 216 + . error + + +state 180 + in_expr: expr.IN expr + call_expr: expr.LEFT_PAREN function_args EOLS_SPACE RIGHT_PAREN + call_expr: expr.LEFT_PAREN function_args COMMA RIGHT_PAREN + call_expr: expr.LEFT_PAREN RIGHT_PAREN + conditional_expr: expr.GTE expr + conditional_expr: expr.GT expr + conditional_expr: expr.OR expr + conditional_expr: expr.AND expr + conditional_expr: expr.LT expr + conditional_expr: expr.LTE expr + conditional_expr: expr.NEQ expr + conditional_expr: expr.EQEQ expr + arithmeticExpr: expr.ADD expr + arithmeticExpr: expr.SUB expr + arithmeticExpr: expr.MUL expr + arithmeticExpr: expr.DIV expr + arithmeticExpr: expr.MOD expr + index_expr: expr.LEFT_BRACKET expr EOLS_SPACE RIGHT_BRACKET + index_expr: DOT LEFT_BRACKET expr.EOLS_SPACE RIGHT_BRACKET + attr_expr: expr.DOT expr + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty COLON expr_or_empty RIGHT_BRACKET + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty RIGHT_BRACKET + EOLS_SPACE: . (11) + + LEFT_PAREN shift 89 + LEFT_BRACKET shift 103 + EOL shift 9 + ADD shift 98 + SUB shift 99 + MUL shift 100 + DIV shift 101 + MOD shift 102 + GTE shift 90 + GT shift 91 + LT shift 94 + LTE shift 95 + NEQ shift 96 + EQEQ shift 97 + AND shift 93 + OR shift 92 + DOT shift 104 + IN shift 88 + . reduce 11 (src line 171) + + EOLS goto 163 + EOLS_SPACE goto 217 + +state 181 + stmt_block: LEFT_BRACE stmts.RIGHT_BRACE + + RIGHT_BRACE shift 218 + . error + + +state 182 + empty_block: LEFT_BRACE RIGHT_BRACE. (113) + + . reduce 113 (src line 584) + + +state 183 + elif_elem: ELIF expr stmt_block. (110) + + . reduce 110 (src line 569) + + +state 184 + for_stmt: FOR for_init_elem SEMICOLON expr.SEMICOLON for_loop_elem stmt_block + for_stmt: FOR for_init_elem SEMICOLON expr.SEMICOLON stmt_block + in_expr: expr.IN expr + call_expr: expr.LEFT_PAREN function_args EOLS_SPACE RIGHT_PAREN + call_expr: expr.LEFT_PAREN function_args COMMA RIGHT_PAREN + call_expr: expr.LEFT_PAREN RIGHT_PAREN + conditional_expr: expr.GTE expr + conditional_expr: expr.GT expr + conditional_expr: expr.OR expr + conditional_expr: expr.AND expr + conditional_expr: expr.LT expr + conditional_expr: expr.LTE expr + conditional_expr: expr.NEQ expr + conditional_expr: expr.EQEQ expr + arithmeticExpr: expr.ADD expr + arithmeticExpr: expr.SUB expr + arithmeticExpr: expr.MUL expr + arithmeticExpr: expr.DIV expr + arithmeticExpr: expr.MOD expr + index_expr: expr.LEFT_BRACKET expr EOLS_SPACE RIGHT_BRACKET + attr_expr: expr.DOT expr + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty COLON expr_or_empty RIGHT_BRACKET + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty RIGHT_BRACKET + + SEMICOLON shift 219 + LEFT_PAREN shift 89 + LEFT_BRACKET shift 103 + ADD shift 98 + SUB shift 99 + MUL shift 100 + DIV shift 101 + MOD shift 102 + GTE shift 90 + GT shift 91 + LT shift 94 + LTE shift 95 + NEQ shift 96 + EQEQ shift 97 + AND shift 93 + OR shift 92 + DOT shift 104 + IN shift 88 + . error + + +state 185 + for_stmt: FOR for_init_elem SEMICOLON SEMICOLON.for_loop_elem stmt_block + for_stmt: FOR for_init_elem SEMICOLON SEMICOLON.stmt_block + + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 191 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + . error + + stmt_block goto 221 + empty_block goto 129 + exprs goto 34 + assignment_stmt goto 190 + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 189 + map_literal goto 39 + list_literal goto 38 + basic_literal goto 37 + for_loop_elem goto 220 + slice_expr goto 46 + +state 186 + for_stmt: FOR SEMICOLON expr SEMICOLON.for_loop_elem stmt_block + for_stmt: FOR SEMICOLON expr SEMICOLON.stmt_block + + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 191 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + . error + + stmt_block goto 223 + empty_block goto 129 + exprs goto 34 + assignment_stmt goto 190 + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 189 + map_literal goto 39 + list_literal goto 38 + basic_literal goto 37 + for_loop_elem goto 222 + slice_expr goto 46 + +state 187 + for_stmt: FOR SEMICOLON SEMICOLON for_loop_elem.stmt_block + + LEFT_BRACE shift 130 + . error + + stmt_block goto 224 + empty_block goto 129 + +state 188 + for_stmt: FOR SEMICOLON SEMICOLON stmt_block. (104) + + . reduce 104 (src line 536) + + +state 189 + exprs: expr. (81) + assignment_stmt: expr.ADD_EQ expr + assignment_stmt: expr.SUB_EQ expr + assignment_stmt: expr.MUL_EQ expr + assignment_stmt: expr.DIV_EQ expr + assignment_stmt: expr.MOD_EQ expr + for_loop_elem: expr. (95) + in_expr: expr.IN expr + call_expr: expr.LEFT_PAREN function_args EOLS_SPACE RIGHT_PAREN + call_expr: expr.LEFT_PAREN function_args COMMA RIGHT_PAREN + call_expr: expr.LEFT_PAREN RIGHT_PAREN + conditional_expr: expr.GTE expr + conditional_expr: expr.GT expr + conditional_expr: expr.OR expr + conditional_expr: expr.AND expr + conditional_expr: expr.LT expr + conditional_expr: expr.LTE expr + conditional_expr: expr.NEQ expr + conditional_expr: expr.EQEQ expr + arithmeticExpr: expr.ADD expr + arithmeticExpr: expr.SUB expr + arithmeticExpr: expr.MUL expr + arithmeticExpr: expr.DIV expr + arithmeticExpr: expr.MOD expr + index_expr: expr.LEFT_BRACKET expr EOLS_SPACE RIGHT_BRACKET + attr_expr: expr.DOT expr + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty COLON expr_or_empty RIGHT_BRACKET + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty RIGHT_BRACKET + + LEFT_PAREN shift 89 + LEFT_BRACKET shift 103 + LEFT_BRACE reduce 95 (src line 506) + ADD shift 98 + SUB shift 99 + MUL shift 100 + DIV shift 101 + MOD shift 102 + GTE shift 90 + GT shift 91 + LT shift 94 + LTE shift 95 + NEQ shift 96 + EQEQ shift 97 + ADD_EQ shift 83 + SUB_EQ shift 84 + DIV_EQ shift 86 + MUL_EQ shift 85 + MOD_EQ shift 87 + AND shift 93 + OR shift 92 + DOT shift 104 + IN shift 88 + . reduce 81 (src line 427) + + +state 190 + for_loop_elem: assignment_stmt. (96) + + . reduce 96 (src line 506) + + +state 191 + stmt_block: LEFT_BRACE.stmts RIGHT_BRACE + empty_block: LEFT_BRACE.RIGHT_BRACE + map_literal: LEFT_BRACE.RIGHT_BRACE + map_literal: LEFT_BRACE.expr_colon_expr EOLS_SPACE RIGHT_BRACE + + SEMICOLON shift 23 + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + RIGHT_BRACE shift 225 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + IF shift 49 + FOR shift 25 + BREAK shift 27 + CONTINUE shift 26 + RETURN shift 33 + FN shift 31 + LET shift 29 + IMPORT shift 32 + CONST shift 30 + . error + + stmts goto 181 + stmts_list goto 7 + if_elem goto 35 + if_elif_list goto 24 + exprs goto 34 + expr_colon_expr goto 118 + stmt goto 8 + assignment_stmt goto 22 + for_in_stmt goto 12 + for_stmt goto 13 + continue_stmt goto 14 + break_stmt goto 15 + ifelse_stmt goto 11 + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 226 + map_literal goto 39 + value_stmt goto 16 + list_literal goto 38 + basic_literal goto 37 + slice_expr goto 46 + let_stmt goto 17 + const_def_stmt goto 18 + fn_def_stmt goto 19 + import_stmt goto 20 + return_stmt goto 21 + sem goto 10 + +state 192 + function_args: function_args COMMA.expr + function_args: function_args COMMA.named_arg + call_expr: expr LEFT_PAREN function_args COMMA.RIGHT_PAREN + + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + RIGHT_PAREN shift 229 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + . error + + call_expr goto 48 + named_arg goto 228 + identifier goto 146 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 227 + map_literal goto 39 + list_literal goto 38 + basic_literal goto 37 + slice_expr goto 46 + +state 193 + call_expr: expr LEFT_PAREN function_args EOLS_SPACE.RIGHT_PAREN + + RIGHT_PAREN shift 230 + . error + + +state 194 + named_arg: identifier EQ.expr + + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + . error + + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 231 + map_literal goto 39 + list_literal goto 38 + basic_literal goto 37 + slice_expr goto 46 + +state 195 + index_expr: expr LEFT_BRACKET expr EOLS_SPACE.RIGHT_BRACKET + + RIGHT_BRACKET shift 232 + . error + + +state 196 + slice_expr: expr LEFT_BRACKET expr_or_empty COLON.expr_or_empty COLON expr_or_empty RIGHT_BRACKET + slice_expr: expr LEFT_BRACKET expr_or_empty COLON.expr_or_empty RIGHT_BRACKET + EOLS_SPACE: . (11) + + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + EOL shift 9 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + . reduce 11 (src line 171) + + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 234 + map_literal goto 39 + expr_or_empty goto 233 + list_literal goto 38 + basic_literal goto 37 + slice_expr goto 46 + EOLS goto 163 + EOLS_SPACE goto 162 + +state 197 + let_stmt: LET identifier COLON data_type.EQ expr + let_stmt: LET identifier COLON data_type. (56) + + EQ shift 235 + . reduce 56 (src line 299) + + +state 198 + data_type: INT. (49) + + . reduce 49 (src line 265) + + +state 199 + data_type: FLOAT. (50) + + . reduce 50 (src line 269) + + +state 200 + data_type: STR. (51) + + . reduce 51 (src line 273) + + +state 201 + data_type: BOOL. (52) + + . reduce 52 (src line 277) + + +state 202 + data_type: ANY. (53) + + . reduce 53 (src line 281) + + +state 203 + let_stmt: LET identifier EQ expr. (58) + in_expr: expr.IN expr + call_expr: expr.LEFT_PAREN function_args EOLS_SPACE RIGHT_PAREN + call_expr: expr.LEFT_PAREN function_args COMMA RIGHT_PAREN + call_expr: expr.LEFT_PAREN RIGHT_PAREN + conditional_expr: expr.GTE expr + conditional_expr: expr.GT expr + conditional_expr: expr.OR expr + conditional_expr: expr.AND expr + conditional_expr: expr.LT expr + conditional_expr: expr.LTE expr + conditional_expr: expr.NEQ expr + conditional_expr: expr.EQEQ expr + arithmeticExpr: expr.ADD expr + arithmeticExpr: expr.SUB expr + arithmeticExpr: expr.MUL expr + arithmeticExpr: expr.DIV expr + arithmeticExpr: expr.MOD expr + index_expr: expr.LEFT_BRACKET expr EOLS_SPACE RIGHT_BRACKET + attr_expr: expr.DOT expr + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty COLON expr_or_empty RIGHT_BRACKET + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty RIGHT_BRACKET + + LEFT_PAREN shift 89 + LEFT_BRACKET shift 103 + ADD shift 98 + SUB shift 99 + MUL shift 100 + DIV shift 101 + MOD shift 102 + GTE shift 90 + GT shift 91 + LT shift 94 + LTE shift 95 + NEQ shift 96 + EQEQ shift 97 + AND shift 93 + OR shift 92 + DOT shift 104 + IN shift 88 + . reduce 58 (src line 307) + + +state 204 + const_def_stmt: CONST identifier EQ expr. (54) + in_expr: expr.IN expr + call_expr: expr.LEFT_PAREN function_args EOLS_SPACE RIGHT_PAREN + call_expr: expr.LEFT_PAREN function_args COMMA RIGHT_PAREN + call_expr: expr.LEFT_PAREN RIGHT_PAREN + conditional_expr: expr.GTE expr + conditional_expr: expr.GT expr + conditional_expr: expr.OR expr + conditional_expr: expr.AND expr + conditional_expr: expr.LT expr + conditional_expr: expr.LTE expr + conditional_expr: expr.NEQ expr + conditional_expr: expr.EQEQ expr + arithmeticExpr: expr.ADD expr + arithmeticExpr: expr.SUB expr + arithmeticExpr: expr.MUL expr + arithmeticExpr: expr.DIV expr + arithmeticExpr: expr.MOD expr + index_expr: expr.LEFT_BRACKET expr EOLS_SPACE RIGHT_BRACKET + attr_expr: expr.DOT expr + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty COLON expr_or_empty RIGHT_BRACKET + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty RIGHT_BRACKET + + LEFT_PAREN shift 89 + LEFT_BRACKET shift 103 + ADD shift 98 + SUB shift 99 + MUL shift 100 + DIV shift 101 + MOD shift 102 + GTE shift 90 + GT shift 91 + LT shift 94 + LTE shift 95 + NEQ shift 96 + EQEQ shift 97 + AND shift 93 + OR shift 92 + DOT shift 104 + IN shift 88 + . reduce 54 (src line 288) + + +state 205 + fn_def_stmt: FN identifier LEFT_PAREN RIGHT_PAREN.stmt_block + fn_def_stmt: FN identifier LEFT_PAREN RIGHT_PAREN.FN_RET data_type stmt_block + fn_def_stmt: FN identifier LEFT_PAREN RIGHT_PAREN.FN_RET LEFT_PAREN fn_ret_types_multi RIGHT_PAREN stmt_block + + LEFT_BRACE shift 130 + FN_RET shift 237 + . error + + stmt_block goto 236 + empty_block goto 129 + +state 206 + fn_def_params: fn_def_params.COMMA fn_def_param + fn_def_stmt: FN identifier LEFT_PAREN fn_def_params.RIGHT_PAREN stmt_block + fn_def_stmt: FN identifier LEFT_PAREN fn_def_params.RIGHT_PAREN FN_RET data_type stmt_block + fn_def_stmt: FN identifier LEFT_PAREN fn_def_params.RIGHT_PAREN FN_RET LEFT_PAREN fn_ret_types_multi RIGHT_PAREN stmt_block + + COMMA shift 238 + RIGHT_PAREN shift 239 + . error + + +state 207 + fn_def_params: fn_def_param. (71) + + . reduce 71 (src line 378) + + +state 208 + fn_def_param: identifier. (63) + fn_def_param: identifier.COLON data_type + fn_def_param: identifier.COLON VAR_ARG data_type + fn_def_param: identifier.COLON VAR_ARG + fn_def_param: identifier.EQ expr + fn_def_param: identifier.COLON data_type EQ expr + + COLON shift 240 + EQ shift 241 + . reduce 63 (src line 340) + + +state 209 + pkg_name: pkg_name DOT identifier. (60) + + . reduce 60 (src line 323) + + +state 210 + import_stmt: IMPORT pkg_name AS identifier. (62) + + . reduce 62 (src line 333) + + +state 211 + list_literal: LEFT_BRACKET exprs COMMA RIGHT_BRACKET. (148) + + . reduce 148 (src line 765) + + +state 212 + list_literal: LEFT_BRACKET exprs EOLS_SPACE RIGHT_BRACKET. (147) + + . reduce 147 (src line 761) + + +state 213 + in_expr: expr.IN expr + call_expr: expr.LEFT_PAREN function_args EOLS_SPACE RIGHT_PAREN + call_expr: expr.LEFT_PAREN function_args COMMA RIGHT_PAREN + call_expr: expr.LEFT_PAREN RIGHT_PAREN + conditional_expr: expr.GTE expr + conditional_expr: expr.GT expr + conditional_expr: expr.OR expr + conditional_expr: expr.AND expr + conditional_expr: expr.LT expr + conditional_expr: expr.LTE expr + conditional_expr: expr.NEQ expr + conditional_expr: expr.EQEQ expr + arithmeticExpr: expr.ADD expr + arithmeticExpr: expr.SUB expr + arithmeticExpr: expr.MUL expr + arithmeticExpr: expr.DIV expr + arithmeticExpr: expr.MOD expr + index_expr: expr.LEFT_BRACKET expr EOLS_SPACE RIGHT_BRACKET + attr_expr: expr.DOT expr + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty COLON expr_or_empty RIGHT_BRACKET + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty RIGHT_BRACKET + expr_colon_expr: expr_colon_expr COMMA expr.COLON expr + + LEFT_PAREN shift 89 + LEFT_BRACKET shift 103 + COLON shift 242 + ADD shift 98 + SUB shift 99 + MUL shift 100 + DIV shift 101 + MOD shift 102 + GTE shift 90 + GT shift 91 + LT shift 94 + LTE shift 95 + NEQ shift 96 + EQEQ shift 97 + AND shift 93 + OR shift 92 + DOT shift 104 + IN shift 88 + . error + + +state 214 + map_literal: LEFT_BRACE expr_colon_expr EOLS_SPACE RIGHT_BRACE. (153) + + . reduce 153 (src line 789) + + +state 215 + in_expr: expr.IN expr + call_expr: expr.LEFT_PAREN function_args EOLS_SPACE RIGHT_PAREN + call_expr: expr.LEFT_PAREN function_args COMMA RIGHT_PAREN + call_expr: expr.LEFT_PAREN RIGHT_PAREN + conditional_expr: expr.GTE expr + conditional_expr: expr.GT expr + conditional_expr: expr.OR expr + conditional_expr: expr.AND expr + conditional_expr: expr.LT expr + conditional_expr: expr.LTE expr + conditional_expr: expr.NEQ expr + conditional_expr: expr.EQEQ expr + arithmeticExpr: expr.ADD expr + arithmeticExpr: expr.SUB expr + arithmeticExpr: expr.MUL expr + arithmeticExpr: expr.DIV expr + arithmeticExpr: expr.MOD expr + index_expr: expr.LEFT_BRACKET expr EOLS_SPACE RIGHT_BRACKET + attr_expr: expr.DOT expr + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty COLON expr_or_empty RIGHT_BRACKET + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty RIGHT_BRACKET + expr_colon_expr: expr COLON expr. (150) + + LEFT_PAREN shift 89 + LEFT_BRACKET shift 103 + ADD shift 98 + SUB shift 99 + MUL shift 100 + DIV shift 101 + MOD shift 102 + GTE shift 90 + GT shift 91 + LT shift 94 + LTE shift 95 + NEQ shift 96 + EQEQ shift 97 + AND shift 93 + OR shift 92 + DOT shift 104 + IN shift 88 + . reduce 150 (src line 775) + + +state 216 + paren_expr: LEFT_PAREN expr EOLS_SPACE RIGHT_PAREN. (139) + + . reduce 139 (src line 712) + + +state 217 + index_expr: DOT LEFT_BRACKET expr EOLS_SPACE.RIGHT_BRACKET + + RIGHT_BRACKET shift 243 + . error + + +state 218 + stmt_block: LEFT_BRACE stmts RIGHT_BRACE. (112) + + . reduce 112 (src line 577) + + +state 219 + for_stmt: FOR for_init_elem SEMICOLON expr SEMICOLON.for_loop_elem stmt_block + for_stmt: FOR for_init_elem SEMICOLON expr SEMICOLON.stmt_block + + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 191 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + . error + + stmt_block goto 245 + empty_block goto 129 + exprs goto 34 + assignment_stmt goto 190 + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 189 + map_literal goto 39 + list_literal goto 38 + basic_literal goto 37 + for_loop_elem goto 244 + slice_expr goto 46 + +state 220 + for_stmt: FOR for_init_elem SEMICOLON SEMICOLON for_loop_elem.stmt_block + + LEFT_BRACE shift 130 + . error + + stmt_block goto 246 + empty_block goto 129 + +state 221 + for_stmt: FOR for_init_elem SEMICOLON SEMICOLON stmt_block. (100) + + . reduce 100 (src line 520) + + +state 222 + for_stmt: FOR SEMICOLON expr SEMICOLON for_loop_elem.stmt_block + + LEFT_BRACE shift 130 + . error + + stmt_block goto 247 + empty_block goto 129 + +state 223 + for_stmt: FOR SEMICOLON expr SEMICOLON stmt_block. (102) + + . reduce 102 (src line 528) + + +state 224 + for_stmt: FOR SEMICOLON SEMICOLON for_loop_elem stmt_block. (103) + + . reduce 103 (src line 532) + + +state 225 + empty_block: LEFT_BRACE RIGHT_BRACE. (113) + map_literal: LEFT_BRACE RIGHT_BRACE. (152) + + $end reduce 113 (src line 584) + SEMICOLON reduce 113 (src line 584) + EOF reduce 113 (src line 584) + RIGHT_BRACE reduce 113 (src line 584) + EOL reduce 113 (src line 584) + . reduce 152 (src line 785) + + +state 226 + value_stmt: expr. (35) + exprs: expr. (81) + assignment_stmt: expr.ADD_EQ expr + assignment_stmt: expr.SUB_EQ expr + assignment_stmt: expr.MUL_EQ expr + assignment_stmt: expr.DIV_EQ expr + assignment_stmt: expr.MOD_EQ expr + in_expr: expr.IN expr + call_expr: expr.LEFT_PAREN function_args EOLS_SPACE RIGHT_PAREN + call_expr: expr.LEFT_PAREN function_args COMMA RIGHT_PAREN + call_expr: expr.LEFT_PAREN RIGHT_PAREN + conditional_expr: expr.GTE expr + conditional_expr: expr.GT expr + conditional_expr: expr.OR expr + conditional_expr: expr.AND expr + conditional_expr: expr.LT expr + conditional_expr: expr.LTE expr + conditional_expr: expr.NEQ expr + conditional_expr: expr.EQEQ expr + arithmeticExpr: expr.ADD expr + arithmeticExpr: expr.SUB expr + arithmeticExpr: expr.MUL expr + arithmeticExpr: expr.DIV expr + arithmeticExpr: expr.MOD expr + index_expr: expr.LEFT_BRACKET expr EOLS_SPACE RIGHT_BRACKET + attr_expr: expr.DOT expr + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty COLON expr_or_empty RIGHT_BRACKET + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty RIGHT_BRACKET + expr_colon_expr: expr.COLON expr + + COMMA reduce 81 (src line 427) + LEFT_PAREN shift 89 + LEFT_BRACKET shift 103 + COLON shift 178 + ADD shift 98 + SUB shift 99 + MUL shift 100 + DIV shift 101 + MOD shift 102 + EQ reduce 81 (src line 427) + GTE shift 90 + GT shift 91 + LT shift 94 + LTE shift 95 + NEQ shift 96 + EQEQ shift 97 + ADD_EQ shift 83 + SUB_EQ shift 84 + DIV_EQ shift 86 + MUL_EQ shift 85 + MOD_EQ shift 87 + AND shift 93 + OR shift 92 + DOT shift 104 + IN shift 88 + . reduce 35 (src line 241) + + +state 227 + in_expr: expr.IN expr + function_args: function_args COMMA expr. (115) + call_expr: expr.LEFT_PAREN function_args EOLS_SPACE RIGHT_PAREN + call_expr: expr.LEFT_PAREN function_args COMMA RIGHT_PAREN + call_expr: expr.LEFT_PAREN RIGHT_PAREN + conditional_expr: expr.GTE expr + conditional_expr: expr.GT expr + conditional_expr: expr.OR expr + conditional_expr: expr.AND expr + conditional_expr: expr.LT expr + conditional_expr: expr.LTE expr + conditional_expr: expr.NEQ expr + conditional_expr: expr.EQEQ expr + arithmeticExpr: expr.ADD expr + arithmeticExpr: expr.SUB expr + arithmeticExpr: expr.MUL expr + arithmeticExpr: expr.DIV expr + arithmeticExpr: expr.MOD expr + index_expr: expr.LEFT_BRACKET expr EOLS_SPACE RIGHT_BRACKET + attr_expr: expr.DOT expr + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty COLON expr_or_empty RIGHT_BRACKET + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty RIGHT_BRACKET + + LEFT_PAREN shift 89 + LEFT_BRACKET shift 103 + ADD shift 98 + SUB shift 99 + MUL shift 100 + DIV shift 101 + MOD shift 102 + GTE shift 90 + GT shift 91 + LT shift 94 + LTE shift 95 + NEQ shift 96 + EQEQ shift 97 + AND shift 93 + OR shift 92 + DOT shift 104 + IN shift 88 + . reduce 115 (src line 601) + + +state 228 + function_args: function_args COMMA named_arg. (116) + + . reduce 116 (src line 605) + + +state 229 + call_expr: expr LEFT_PAREN function_args COMMA RIGHT_PAREN. (121) + + . reduce 121 (src line 630) + + +state 230 + call_expr: expr LEFT_PAREN function_args EOLS_SPACE RIGHT_PAREN. (120) + + . reduce 120 (src line 626) + + +state 231 + in_expr: expr.IN expr + named_arg: identifier EQ expr. (119) + call_expr: expr.LEFT_PAREN function_args EOLS_SPACE RIGHT_PAREN + call_expr: expr.LEFT_PAREN function_args COMMA RIGHT_PAREN + call_expr: expr.LEFT_PAREN RIGHT_PAREN + conditional_expr: expr.GTE expr + conditional_expr: expr.GT expr + conditional_expr: expr.OR expr + conditional_expr: expr.AND expr + conditional_expr: expr.LT expr + conditional_expr: expr.LTE expr + conditional_expr: expr.NEQ expr + conditional_expr: expr.EQEQ expr + arithmeticExpr: expr.ADD expr + arithmeticExpr: expr.SUB expr + arithmeticExpr: expr.MUL expr + arithmeticExpr: expr.DIV expr + arithmeticExpr: expr.MOD expr + index_expr: expr.LEFT_BRACKET expr EOLS_SPACE RIGHT_BRACKET + attr_expr: expr.DOT expr + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty COLON expr_or_empty RIGHT_BRACKET + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty RIGHT_BRACKET + + LEFT_PAREN shift 89 + LEFT_BRACKET shift 103 + ADD shift 98 + SUB shift 99 + MUL shift 100 + DIV shift 101 + MOD shift 102 + GTE shift 90 + GT shift 91 + LT shift 94 + LTE shift 95 + NEQ shift 96 + EQEQ shift 97 + AND shift 93 + OR shift 92 + DOT shift 104 + IN shift 88 + . reduce 119 (src line 619) + + +state 232 + index_expr: expr LEFT_BRACKET expr EOLS_SPACE RIGHT_BRACKET. (140) + + . reduce 140 (src line 719) + + +state 233 + slice_expr: expr LEFT_BRACKET expr_or_empty COLON expr_or_empty.COLON expr_or_empty RIGHT_BRACKET + slice_expr: expr LEFT_BRACKET expr_or_empty COLON expr_or_empty.RIGHT_BRACKET + + RIGHT_BRACKET shift 249 + COLON shift 248 + . error + + +state 234 + in_expr: expr.IN expr + call_expr: expr.LEFT_PAREN function_args EOLS_SPACE RIGHT_PAREN + call_expr: expr.LEFT_PAREN function_args COMMA RIGHT_PAREN + call_expr: expr.LEFT_PAREN RIGHT_PAREN + conditional_expr: expr.GTE expr + conditional_expr: expr.GT expr + conditional_expr: expr.OR expr + conditional_expr: expr.AND expr + conditional_expr: expr.LT expr + conditional_expr: expr.LTE expr + conditional_expr: expr.NEQ expr + conditional_expr: expr.EQEQ expr + arithmeticExpr: expr.ADD expr + arithmeticExpr: expr.SUB expr + arithmeticExpr: expr.MUL expr + arithmeticExpr: expr.DIV expr + arithmeticExpr: expr.MOD expr + index_expr: expr.LEFT_BRACKET expr EOLS_SPACE RIGHT_BRACKET + attr_expr: expr.DOT expr + expr_or_empty: expr. (143) + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty COLON expr_or_empty RIGHT_BRACKET + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty RIGHT_BRACKET + + LEFT_PAREN shift 89 + LEFT_BRACKET shift 103 + ADD shift 98 + SUB shift 99 + MUL shift 100 + DIV shift 101 + MOD shift 102 + GTE shift 90 + GT shift 91 + LT shift 94 + LTE shift 95 + NEQ shift 96 + EQEQ shift 97 + AND shift 93 + OR shift 92 + DOT shift 104 + IN shift 88 + . reduce 143 (src line 737) + + +state 235 + let_stmt: LET identifier COLON data_type EQ.expr + + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + . error + + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 250 + map_literal goto 39 + list_literal goto 38 + basic_literal goto 37 + slice_expr goto 46 + +state 236 + fn_def_stmt: FN identifier LEFT_PAREN RIGHT_PAREN stmt_block. (75) + + . reduce 75 (src line 401) + + +state 237 + fn_def_stmt: FN identifier LEFT_PAREN RIGHT_PAREN FN_RET.data_type stmt_block + fn_def_stmt: FN identifier LEFT_PAREN RIGHT_PAREN FN_RET.LEFT_PAREN fn_ret_types_multi RIGHT_PAREN stmt_block + + LEFT_PAREN shift 252 + STR shift 200 + INT shift 198 + FLOAT shift 199 + BOOL shift 201 + ANY shift 202 + . error + + data_type goto 251 + +state 238 + fn_def_params: fn_def_params COMMA.fn_def_param + + ID shift 50 + QUOTED_STRING shift 51 + . error + + identifier goto 208 + fn_def_param goto 253 + +state 239 + fn_def_stmt: FN identifier LEFT_PAREN fn_def_params RIGHT_PAREN.stmt_block + fn_def_stmt: FN identifier LEFT_PAREN fn_def_params RIGHT_PAREN.FN_RET data_type stmt_block + fn_def_stmt: FN identifier LEFT_PAREN fn_def_params RIGHT_PAREN.FN_RET LEFT_PAREN fn_ret_types_multi RIGHT_PAREN stmt_block + + LEFT_BRACE shift 130 + FN_RET shift 255 + . error + + stmt_block goto 254 + empty_block goto 129 + +state 240 + fn_def_param: identifier COLON.data_type + fn_def_param: identifier COLON.VAR_ARG data_type + fn_def_param: identifier COLON.VAR_ARG + fn_def_param: identifier COLON.data_type EQ expr + + STR shift 200 + INT shift 198 + FLOAT shift 199 + BOOL shift 201 + ANY shift 202 + VAR_ARG shift 257 + . error + + data_type goto 256 + +state 241 + fn_def_param: identifier EQ.expr + + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + . error + + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 258 + map_literal goto 39 + list_literal goto 38 + basic_literal goto 37 + slice_expr goto 46 + +state 242 + expr_colon_expr: expr_colon_expr COMMA expr COLON.expr + + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + . error + + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 259 + map_literal goto 39 + list_literal goto 38 + basic_literal goto 37 + slice_expr goto 46 + +state 243 + index_expr: DOT LEFT_BRACKET expr EOLS_SPACE RIGHT_BRACKET. (141) + + . reduce 141 (src line 723) + + +state 244 + for_stmt: FOR for_init_elem SEMICOLON expr SEMICOLON for_loop_elem.stmt_block + + LEFT_BRACE shift 130 + . error + + stmt_block goto 260 + empty_block goto 129 + +state 245 + for_stmt: FOR for_init_elem SEMICOLON expr SEMICOLON stmt_block. (98) + + . reduce 98 (src line 512) + + +state 246 + for_stmt: FOR for_init_elem SEMICOLON SEMICOLON for_loop_elem stmt_block. (99) + + . reduce 99 (src line 516) + + +state 247 + for_stmt: FOR SEMICOLON expr SEMICOLON for_loop_elem stmt_block. (101) + + . reduce 101 (src line 524) + + +state 248 + slice_expr: expr LEFT_BRACKET expr_or_empty COLON expr_or_empty COLON.expr_or_empty RIGHT_BRACKET + EOLS_SPACE: . (11) + + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + EOL shift 9 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + . reduce 11 (src line 171) + + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 234 + map_literal goto 39 + expr_or_empty goto 261 + list_literal goto 38 + basic_literal goto 37 + slice_expr goto 46 + EOLS goto 163 + EOLS_SPACE goto 162 + +state 249 + slice_expr: expr LEFT_BRACKET expr_or_empty COLON expr_or_empty RIGHT_BRACKET. (146) + + . reduce 146 (src line 752) + + +state 250 + let_stmt: LET identifier COLON data_type EQ expr. (55) + in_expr: expr.IN expr + call_expr: expr.LEFT_PAREN function_args EOLS_SPACE RIGHT_PAREN + call_expr: expr.LEFT_PAREN function_args COMMA RIGHT_PAREN + call_expr: expr.LEFT_PAREN RIGHT_PAREN + conditional_expr: expr.GTE expr + conditional_expr: expr.GT expr + conditional_expr: expr.OR expr + conditional_expr: expr.AND expr + conditional_expr: expr.LT expr + conditional_expr: expr.LTE expr + conditional_expr: expr.NEQ expr + conditional_expr: expr.EQEQ expr + arithmeticExpr: expr.ADD expr + arithmeticExpr: expr.SUB expr + arithmeticExpr: expr.MUL expr + arithmeticExpr: expr.DIV expr + arithmeticExpr: expr.MOD expr + index_expr: expr.LEFT_BRACKET expr EOLS_SPACE RIGHT_BRACKET + attr_expr: expr.DOT expr + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty COLON expr_or_empty RIGHT_BRACKET + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty RIGHT_BRACKET + + LEFT_PAREN shift 89 + LEFT_BRACKET shift 103 + ADD shift 98 + SUB shift 99 + MUL shift 100 + DIV shift 101 + MOD shift 102 + GTE shift 90 + GT shift 91 + LT shift 94 + LTE shift 95 + NEQ shift 96 + EQEQ shift 97 + AND shift 93 + OR shift 92 + DOT shift 104 + IN shift 88 + . reduce 55 (src line 295) + + +state 251 + fn_def_stmt: FN identifier LEFT_PAREN RIGHT_PAREN FN_RET data_type.stmt_block + + LEFT_BRACE shift 130 + . error + + stmt_block goto 262 + empty_block goto 129 + +state 252 + fn_def_stmt: FN identifier LEFT_PAREN RIGHT_PAREN FN_RET LEFT_PAREN.fn_ret_types_multi RIGHT_PAREN stmt_block + + STR shift 200 + INT shift 198 + FLOAT shift 199 + BOOL shift 201 + ANY shift 202 + . error + + fn_ret_types_multi goto 263 + data_type goto 264 + +state 253 + fn_def_params: fn_def_params COMMA fn_def_param. (72) + + . reduce 72 (src line 382) + + +state 254 + fn_def_stmt: FN identifier LEFT_PAREN fn_def_params RIGHT_PAREN stmt_block. (78) + + . reduce 78 (src line 413) + + +state 255 + fn_def_stmt: FN identifier LEFT_PAREN fn_def_params RIGHT_PAREN FN_RET.data_type stmt_block + fn_def_stmt: FN identifier LEFT_PAREN fn_def_params RIGHT_PAREN FN_RET.LEFT_PAREN fn_ret_types_multi RIGHT_PAREN stmt_block + + LEFT_PAREN shift 266 + STR shift 200 + INT shift 198 + FLOAT shift 199 + BOOL shift 201 + ANY shift 202 + . error + + data_type goto 265 + +state 256 + fn_def_param: identifier COLON data_type. (64) + fn_def_param: identifier COLON data_type.EQ expr + + EQ shift 267 + . reduce 64 (src line 344) + + +state 257 + fn_def_param: identifier COLON VAR_ARG.data_type + fn_def_param: identifier COLON VAR_ARG. (66) + + STR shift 200 + INT shift 198 + FLOAT shift 199 + BOOL shift 201 + ANY shift 202 + . reduce 66 (src line 352) + + data_type goto 268 + +state 258 + fn_def_param: identifier EQ expr. (67) + in_expr: expr.IN expr + call_expr: expr.LEFT_PAREN function_args EOLS_SPACE RIGHT_PAREN + call_expr: expr.LEFT_PAREN function_args COMMA RIGHT_PAREN + call_expr: expr.LEFT_PAREN RIGHT_PAREN + conditional_expr: expr.GTE expr + conditional_expr: expr.GT expr + conditional_expr: expr.OR expr + conditional_expr: expr.AND expr + conditional_expr: expr.LT expr + conditional_expr: expr.LTE expr + conditional_expr: expr.NEQ expr + conditional_expr: expr.EQEQ expr + arithmeticExpr: expr.ADD expr + arithmeticExpr: expr.SUB expr + arithmeticExpr: expr.MUL expr + arithmeticExpr: expr.DIV expr + arithmeticExpr: expr.MOD expr + index_expr: expr.LEFT_BRACKET expr EOLS_SPACE RIGHT_BRACKET + attr_expr: expr.DOT expr + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty COLON expr_or_empty RIGHT_BRACKET + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty RIGHT_BRACKET + + LEFT_PAREN shift 89 + LEFT_BRACKET shift 103 + ADD shift 98 + SUB shift 99 + MUL shift 100 + DIV shift 101 + MOD shift 102 + GTE shift 90 + GT shift 91 + LT shift 94 + LTE shift 95 + NEQ shift 96 + EQEQ shift 97 + AND shift 93 + OR shift 92 + DOT shift 104 + IN shift 88 + . reduce 67 (src line 356) + + +state 259 + in_expr: expr.IN expr + call_expr: expr.LEFT_PAREN function_args EOLS_SPACE RIGHT_PAREN + call_expr: expr.LEFT_PAREN function_args COMMA RIGHT_PAREN + call_expr: expr.LEFT_PAREN RIGHT_PAREN + conditional_expr: expr.GTE expr + conditional_expr: expr.GT expr + conditional_expr: expr.OR expr + conditional_expr: expr.AND expr + conditional_expr: expr.LT expr + conditional_expr: expr.LTE expr + conditional_expr: expr.NEQ expr + conditional_expr: expr.EQEQ expr + arithmeticExpr: expr.ADD expr + arithmeticExpr: expr.SUB expr + arithmeticExpr: expr.MUL expr + arithmeticExpr: expr.DIV expr + arithmeticExpr: expr.MOD expr + index_expr: expr.LEFT_BRACKET expr EOLS_SPACE RIGHT_BRACKET + attr_expr: expr.DOT expr + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty COLON expr_or_empty RIGHT_BRACKET + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty RIGHT_BRACKET + expr_colon_expr: expr_colon_expr COMMA expr COLON expr. (151) + + LEFT_PAREN shift 89 + LEFT_BRACKET shift 103 + ADD shift 98 + SUB shift 99 + MUL shift 100 + DIV shift 101 + MOD shift 102 + GTE shift 90 + GT shift 91 + LT shift 94 + LTE shift 95 + NEQ shift 96 + EQEQ shift 97 + AND shift 93 + OR shift 92 + DOT shift 104 + IN shift 88 + . reduce 151 (src line 779) + + +state 260 + for_stmt: FOR for_init_elem SEMICOLON expr SEMICOLON for_loop_elem stmt_block. (97) + + . reduce 97 (src line 508) + + +state 261 + slice_expr: expr LEFT_BRACKET expr_or_empty COLON expr_or_empty COLON expr_or_empty.RIGHT_BRACKET + + RIGHT_BRACKET shift 269 + . error + + +state 262 + fn_def_stmt: FN identifier LEFT_PAREN RIGHT_PAREN FN_RET data_type stmt_block. (76) + + . reduce 76 (src line 405) + + +state 263 + fn_ret_types_multi: fn_ret_types_multi.COMMA data_type + fn_def_stmt: FN identifier LEFT_PAREN RIGHT_PAREN FN_RET LEFT_PAREN fn_ret_types_multi.RIGHT_PAREN stmt_block + + COMMA shift 270 + RIGHT_PAREN shift 271 + . error + + +state 264 + fn_ret_types_multi: data_type. (73) + + . reduce 73 (src line 389) + + +state 265 + fn_def_stmt: FN identifier LEFT_PAREN fn_def_params RIGHT_PAREN FN_RET data_type.stmt_block + + LEFT_BRACE shift 130 + . error + + stmt_block goto 272 + empty_block goto 129 + +state 266 + fn_def_stmt: FN identifier LEFT_PAREN fn_def_params RIGHT_PAREN FN_RET LEFT_PAREN.fn_ret_types_multi RIGHT_PAREN stmt_block + + STR shift 200 + INT shift 198 + FLOAT shift 199 + BOOL shift 201 + ANY shift 202 + . error + + fn_ret_types_multi goto 273 + data_type goto 264 + +state 267 + fn_def_param: identifier COLON data_type EQ.expr + + ID shift 50 + NUMBER shift 52 + LEFT_PAREN shift 61 + LEFT_BRACKET shift 59 + LEFT_BRACE shift 60 + STRING shift 55 + QUOTED_STRING shift 51 + MULTILINE_STRING shift 56 + ADD shift 62 + SUB shift 63 + NOT shift 64 + DOT shift 65 + TRUE shift 53 + FALSE shift 54 + NIL shift 57 + NULL shift 58 + . error + + call_expr goto 48 + identifier goto 36 + unary_expr goto 41 + conditional_expr goto 42 + arithmeticExpr goto 43 + paren_expr goto 40 + index_expr goto 45 + attr_expr goto 44 + in_expr goto 47 + expr goto 274 + map_literal goto 39 + list_literal goto 38 + basic_literal goto 37 + slice_expr goto 46 + +state 268 + fn_def_param: identifier COLON VAR_ARG data_type. (65) + + . reduce 65 (src line 348) + + +state 269 + slice_expr: expr LEFT_BRACKET expr_or_empty COLON expr_or_empty COLON expr_or_empty RIGHT_BRACKET. (145) + + . reduce 145 (src line 748) + + +state 270 + fn_ret_types_multi: fn_ret_types_multi COMMA.data_type + + STR shift 200 + INT shift 198 + FLOAT shift 199 + BOOL shift 201 + ANY shift 202 + . error + + data_type goto 275 + +state 271 + fn_def_stmt: FN identifier LEFT_PAREN RIGHT_PAREN FN_RET LEFT_PAREN fn_ret_types_multi RIGHT_PAREN.stmt_block + + LEFT_BRACE shift 130 + . error + + stmt_block goto 276 + empty_block goto 129 + +state 272 + fn_def_stmt: FN identifier LEFT_PAREN fn_def_params RIGHT_PAREN FN_RET data_type stmt_block. (79) + + . reduce 79 (src line 417) + + +state 273 + fn_ret_types_multi: fn_ret_types_multi.COMMA data_type + fn_def_stmt: FN identifier LEFT_PAREN fn_def_params RIGHT_PAREN FN_RET LEFT_PAREN fn_ret_types_multi.RIGHT_PAREN stmt_block + + COMMA shift 270 + RIGHT_PAREN shift 277 + . error + + +state 274 + fn_def_param: identifier COLON data_type EQ expr. (68) + in_expr: expr.IN expr + call_expr: expr.LEFT_PAREN function_args EOLS_SPACE RIGHT_PAREN + call_expr: expr.LEFT_PAREN function_args COMMA RIGHT_PAREN + call_expr: expr.LEFT_PAREN RIGHT_PAREN + conditional_expr: expr.GTE expr + conditional_expr: expr.GT expr + conditional_expr: expr.OR expr + conditional_expr: expr.AND expr + conditional_expr: expr.LT expr + conditional_expr: expr.LTE expr + conditional_expr: expr.NEQ expr + conditional_expr: expr.EQEQ expr + arithmeticExpr: expr.ADD expr + arithmeticExpr: expr.SUB expr + arithmeticExpr: expr.MUL expr + arithmeticExpr: expr.DIV expr + arithmeticExpr: expr.MOD expr + index_expr: expr.LEFT_BRACKET expr EOLS_SPACE RIGHT_BRACKET + attr_expr: expr.DOT expr + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty COLON expr_or_empty RIGHT_BRACKET + slice_expr: expr.LEFT_BRACKET expr_or_empty COLON expr_or_empty RIGHT_BRACKET + + LEFT_PAREN shift 89 + LEFT_BRACKET shift 103 + ADD shift 98 + SUB shift 99 + MUL shift 100 + DIV shift 101 + MOD shift 102 + GTE shift 90 + GT shift 91 + LT shift 94 + LTE shift 95 + NEQ shift 96 + EQEQ shift 97 + AND shift 93 + OR shift 92 + DOT shift 104 + IN shift 88 + . reduce 68 (src line 360) + + +state 275 + fn_ret_types_multi: fn_ret_types_multi COMMA data_type. (74) + + . reduce 74 (src line 393) + + +state 276 + fn_def_stmt: FN identifier LEFT_PAREN RIGHT_PAREN FN_RET LEFT_PAREN fn_ret_types_multi RIGHT_PAREN stmt_block. (77) + + . reduce 77 (src line 409) + + +state 277 + fn_def_stmt: FN identifier LEFT_PAREN fn_def_params RIGHT_PAREN FN_RET LEFT_PAREN fn_ret_types_multi RIGHT_PAREN.stmt_block + + LEFT_BRACE shift 130 + . error + + stmt_block goto 278 + empty_block goto 129 + +state 278 + fn_def_stmt: FN identifier LEFT_PAREN fn_def_params RIGHT_PAREN FN_RET LEFT_PAREN fn_ret_types_multi RIGHT_PAREN stmt_block. (80) + + . reduce 80 (src line 421) + + +86 terminals, 52 nonterminals +163 grammar rules, 279/16000 states +0 shift/reduce, 0 reduce/reduce conflicts reported +151 working sets used +memory: parser 1263/240000 +237 extra closures +1819 shift entries, 13 exceptions +168 goto entries +858 entries saved by goto default +Optimizer space used: output 1323/240000 +1323 table entries, 520 zero +maximum spread: 84, maximum offset: 277 diff --git a/pkg/v2/sym/symbol.go b/pkg/v2/sym/symbol.go new file mode 100644 index 0000000..9db0f3a --- /dev/null +++ b/pkg/v2/sym/symbol.go @@ -0,0 +1,100 @@ +package sym + +type Sym struct { + Name string + Kind KindCat + Type Type +} + +type tables struct { + v []*Syms +} + +type Tables struct { + tables *tables + parent int + cur int +} + +func NewTabels() *Tables { + return &Tables{ + tables: &tables{}, + parent: 0, + cur: 0, + } +} + +func (tbs *Tables) NextScope() *Tables { + tbs.tables.v = append(tbs.tables.v, &Syms{}) + return &Tables{ + tables: tbs.tables, + parent: tbs.cur, + cur: len(tbs.tables.v) - 1, + } +} + +func (tbs *Tables) ScopeID() int { + return tbs.cur +} + +func (tbs *Tables) scope() *Syms { + return tbs.tables.v[tbs.cur] +} + +func (tbs *Tables) Define(name string, sym *Sym) bool { + return tbs.tables.v[tbs.cur].Define(name, sym) +} + +func (tbs *Tables) GetCur(name string) (*Sym, bool) { + return tbs.tables.v[tbs.cur].Get(name) +} + +func (tbs *Tables) Get(name string) (*Sym, bool) { + id := tbs.cur + for { + tb := tbs.tables.v[id] + if v, ok := tb.Get(name); ok { + return v, ok + } + if tb.ParentID != id { + id = tb.ParentID + } else { + return nil, false + } + } +} + +type Syms struct { + Symbols map[string]*Sym + + ParentID int + ID int +} + +func NewSyms(parent *Syms) *Syms { + var parentID, id int + if parent != nil { + parentID = parent.ID + id = parentID + 1 + } + + return &Syms{ + Symbols: map[string]*Sym{}, + ParentID: parentID, + ID: id, + } +} + +func (s *Syms) Define(name string, sym *Sym) bool { + if _, ok := s.Symbols[name]; ok { + return false + } + + s.Symbols[name] = sym + return true +} + +func (s *Syms) Get(name string) (*Sym, bool) { + sym, ok := s.Symbols[name] + return sym, ok +} diff --git a/pkg/v2/sym/typs.go b/pkg/v2/sym/typs.go new file mode 100644 index 0000000..c46dfe8 --- /dev/null +++ b/pkg/v2/sym/typs.go @@ -0,0 +1,153 @@ +package sym + +type TypCat int + +const ( + TypAnyCat TypCat = iota + TypBoolCat + TypIntCat + TypStringCat + TypFloatCat + TypMapCat + TypListCat + TypClassCat + TypFuncCat +) + +type KindCat int + +const ( + KindVarb KindCat = 1 << iota + KindConst + KindFunc + KindClass +) + +var ( + Bool = &TypBool{} + Float = &TypFloat{} + Int = &TypInt{} + Str = &TypString{} + Any = &TypAny{} +) + +type Type interface { + Category() TypCat +} + +type TypAny struct{} + +func (*TypAny) Category() TypCat { return TypAnyCat } + +type TypBool struct{} + +func (*TypBool) Category() TypCat { return TypBoolCat } + +type TypInt struct{} + +func (*TypInt) Category() TypCat { return TypIntCat } + +type TypFloat struct{} + +func (*TypFloat) Category() TypCat { return TypFloatCat } + +type TypString struct{} + +func (*TypString) Category() TypCat { return TypStringCat } + +type TypMap struct { + Key Type + Value Type +} + +func (*TypMap) Category() TypCat { return TypMapCat } + +type TypList struct { + Elem Type +} + +func NewListTyp(tp Type) *TypList { + return &TypList{ + Elem: tp, + } +} + +func NewMapTyp() *TypMap { + return &TypMap{ + Key: Str, + Value: Any, + } +} + +func (*TypList) Category() TypCat { return TypListCat } + +type Field struct { + Name string + Type Type +} + +type TypClass struct { + Name string + Fields []*Field + Method map[string]TypFunc +} + +func (*TypClass) Category() TypCat { return TypClassCat } + +type Param struct { + Type Type + IsVarb bool +} + +type TypFunc struct { + Name string + Params []*Param + Returns []Type +} + +func (TypFunc) Category() TypCat { return TypFuncCat } + +type TypeDesc struct { + typs []Type +} + +var innerTypes = []Type{ + &TypAny{}, + &TypBool{}, + &TypInt{}, + &TypFloat{}, + &TypString{}, + &TypList{ + Elem: &TypAny{}, + }, + &TypMap{Key: &TypString{}, + Value: &TypAny{}}, +} + +const ( + TypAnyIdx = iota + TypBoolIdx + TypIntIdx + TypFloatIdx + TypStringIdx + TypListIdx + TypMapIdx +) + +func NewTypeDesc() TypeDesc { + return TypeDesc{ + typs: append([]Type{}, innerTypes...)} +} + +func (t *TypeDesc) Insert(typ Type) int { + t.typs = append(t.typs, typ) + return len(t.typs) - 1 +} + +func (t *TypeDesc) Get(i int) Type { + return t.typs[i] +} + +func (t *TypeDesc) Len() int { + return len(t.typs) +} diff --git a/pkg/v2/vm/utils.go b/pkg/v2/vm/utils.go new file mode 100644 index 0000000..619ec10 --- /dev/null +++ b/pkg/v2/vm/utils.go @@ -0,0 +1,53 @@ +package vm + +import ( + "fmt" + + "github.com/GuanceCloud/platypus/pkg/v2/ir" +) + +func floatOp(op ir.OP, l, r float64) (float64, error) { + switch op { + case ir.OP_ADD: + return l + r, nil + case ir.OP_SUB: + return l - r, nil + case ir.OP_MUL: + return l * r, nil + case ir.OP_DIV: + if r == 0 { + return 0, fmt.Errorf("float division by zero") + } + return l / r, nil + } + + return 0, fmt.Errorf("unsupported op %s for float", op) +} + +func intOp(op ir.OP, l, r int64) (int64, error) { + switch op { + case ir.OP_ADD: + return l + r, nil + case ir.OP_SUB: + return l - r, nil + case ir.OP_MUL: + return l * r, nil + case ir.OP_DIV: + if r == 0 { + return 0, fmt.Errorf("integer division by zero") + } + return l / r, nil + } + + return 0, fmt.Errorf("unsupported op %s for integer", op) +} + +func boolOp(op ir.OP, l, r bool) (bool, error) { + switch op { + case ir.OP_ADD: + return l && r, nil + + } + + return false, fmt.Errorf("unsupported op %s for bool", op) +} diff --git a/pkg/v2/vm/vm.go b/pkg/v2/vm/vm.go new file mode 100644 index 0000000..3186d80 --- /dev/null +++ b/pkg/v2/vm/vm.go @@ -0,0 +1,131 @@ +package vm + +import ( + "fmt" + + "github.com/GuanceCloud/platypus/pkg/ast" + "github.com/GuanceCloud/platypus/pkg/v2/ir" +) + +type Task struct { + Insns []*ir.Insn + Regs Regs +} + +type Regs struct { + cur int +} + +func Run(task *Task) error { + return nil +} + +func Nop(task *Task) error { + return nil +} + +func Add(task *Task, insn *ir.Insn) error { + l := insn.Args.Arg2 + r := insn.Args.Arg3 + + switch l.DType { + case ast.String: + if r.DType != ast.String { + return fmt.Errorf("unsupported operand type(s) for +: %s and %s", l.DType, r.DType) + } + if insn.Op != ir.OP_ADD { + return fmt.Errorf("unsupported op %s for string", insn.Op) + } + insn.Args.Arg1.Set(l.Val.(string)+r.Val.(string), ast.String) + case ast.Int: + switch r.DType { + case ast.Int: + v, err := intOp(insn.Op, l.Val.(int64), r.Val.(int64)) + if err != nil { + return err + } + insn.Args.Arg1.Set(v, ast.Int) + case ast.Float: + v, err := floatOp(insn.Op, float64(l.Val.(int64)), r.Val.(float64)) + if err != nil { + return err + } + insn.Args.Arg1.Set(v, ast.Float) + case ast.Bool: + var rV int64 + if r.Val.(bool) { + rV = 1 + } + if v, err := intOp(insn.Op, l.Val.(int64), rV); err != nil { + return err + } else { + insn.Args.Arg1.Set(v, ast.Int) + } + default: + return fmt.Errorf("unsupported operand type(s) for +: %s and %s", l.DType, r.DType) + } + case ast.Float: + switch r.DType { + case ast.Int: + v, err := floatOp(insn.Op, l.Val.(float64), float64(r.Val.(int64))) + if err != nil { + return err + } + insn.Args.Arg1.Set(v, ast.Float) + case ast.Float: + v, err := floatOp(insn.Op, l.Val.(float64), r.Val.(float64)) + if err != nil { + return err + } + insn.Args.Arg1.Set(v, ast.Float) + case ast.Bool: + var rV float64 + if r.Val.(bool) { + rV = 1 + } + if v, err := floatOp(insn.Op, l.Val.(float64), rV); err != nil { + return err + } else { + insn.Args.Arg1.Set(v, ast.Float) + } + + default: + return fmt.Errorf("unsupported operand type(s) for +: %s and %s", l.DType, r.DType) + } + case ast.Bool: + switch r.DType { + case ast.Int: + var lv int64 + if l.Val.(bool) { + lv = 1 + } + if v, err := intOp(insn.Op, lv, r.Val.(int64)); err != nil { + return err + } else { + insn.Args.Arg1.Set(v, ast.Int) + } + case ast.Float: + var lv float64 + if l.Val.(bool) { + lv = 1 + } + if v, err := floatOp(insn.Op, lv, r.Val.(float64)); err != nil { + return err + } else { + insn.Args.Arg1.Set(v, ast.Float) + } + case ast.Bool: + v, err := boolOp(insn.Op, l.Val.(bool), r.Val.(bool)) + if err != nil { + return err + } + insn.Args.Arg1.Set(v, ast.Bool) + default: + return fmt.Errorf("unsupported operand type(s) for +: %s and %s", l.DType, r.DType) + } + default: + return fmt.Errorf("unsupported operand type(s) for +: %s and %s", l.DType, r.DType) + } + + return nil +}