diff --git a/ast/expressions.go b/ast/expressions.go index cd82ea4..4b768dc 100644 --- a/ast/expressions.go +++ b/ast/expressions.go @@ -18,3 +18,93 @@ func NewTestListStarExpression() *TestlistStarExpression { func (node *TestlistStarExpression) SetChild(n TestlistStarExpressionChildNode) { node.ParentNode.SetChild(n) } + +type ComparisonChildNode interface { + Node + comparisonChild() +} + +type Comparison struct { + ListNode +} + +func NewComparison() *Comparison { + node := &Comparison{} + node.initBaseNode(COMPARISON) + return node +} + +func (node *Comparison) notTestChild() {} +func (node *Comparison) Append(n ComparisonChildNode) { node.ListNode.Append(n) } + +type ExpressionChildNode interface { + Node + expressionChild() +} + +type Expression struct { + ListNode +} + +func NewExpression() *Expression { + node := &Expression{} + node.initBaseNode(EXPR) + return node +} + +func (node *Expression) comparisonChild() {} +func (node *Expression) Append(n ExpressionChildNode) { node.ListNode.Append(n) } + +type XorExpressionChildNode interface { + Node + xorExpressionChild() +} + +type XorExpression struct { + ListNode +} + +func NewXorExpression() *XorExpression { + node := &XorExpression{} + node.initBaseNode(XOR_EXPR) + return node +} + +func (node *XorExpression) expressionChild() {} +func (node *XorExpression) Append(n XorExpressionChildNode) { node.ListNode.Append(n) } + +type AndExpressionChildNode interface { + Node + andExpressionChild() +} + +type AndExpression struct { + ListNode +} + +func NewAndExpression() *AndExpression { + node := &AndExpression{} + node.initBaseNode(AND_EXPR) + return node +} + +func (node *AndExpression) xorExpressionChild() {} +func (node *AndExpression) Append(n AndExpressionChildNode) { node.ListNode.Append(n) } + +type ShiftExpressionChildNode interface { + Node + shiftExpressionChild() +} + +type ShiftExpression struct { + ListNode +} + +func NewShiftExpression() *ShiftExpression { + node := &ShiftExpression{} + node.initBaseNode(SHIFT_EXPR) + return node +} + +func (node *ShiftExpression) andExpressionChild() {} +func (node *ShiftExpression) Append(n ShiftExpressionChildNode) { node.ListNode.Append(n) } diff --git a/ast/nodes.go b/ast/nodes.go index 04ccb12..850e6a6 100644 --- a/ast/nodes.go +++ b/ast/nodes.go @@ -16,7 +16,8 @@ func NewTokenNode(tok *token.Token) *TokenNode { Token: tok, } } -func (node *TokenNode) Name() string { return token.TokenNames[node.Token.ID] } +func (node *TokenNode) comparisonChild() {} +func (node *TokenNode) Name() string { return token.TokenNames[node.Token.ID] } func (node *TokenNode) Repr() []interface{} { parts := make([]interface{}, 0) parts = append(parts, node.Name()) diff --git a/parser/parser.go b/parser/parser.go index f553a40..7f2358f 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -62,9 +62,149 @@ func (parser *Parser) parseCompoundStatement() *ast.CompoundStatement { return compoundStmt } +// shift_expr: arith_expr (('<<'|'>>') arith_expr)* +func (parser *Parser) parseShiftExpression() *ast.ShiftExpression { + expr := ast.NewShiftExpression() + return expr +} + +// and_expr: shift_expr ('&' shift_expr)* +func (parser *Parser) parseAndExpression() *ast.AndExpression { + expr := ast.NewAndExpression() + shiftExpr := parser.parseShiftExpression() + if shiftExpr == nil { + return nil + } + expr.Append(shiftExpr) + for { + next := parser.nextToken() + if next.ID != token.AMPER { + parser.unreadToken(next) + break + } + shiftExpr := parser.parseShiftExpression() + if shiftExpr == nil { + return nil + } + expr.Append(shiftExpr) + } + return expr +} + +// xor_expr: and_expr ('^' and_expr)* +func (parser *Parser) parseXorExpression() *ast.XorExpression { + expr := ast.NewXorExpression() + andExpr := parser.parseAndExpression() + if andExpr == nil { + return nil + } + expr.Append(andExpr) + for { + next := parser.nextToken() + if next.ID != token.CIRCUMFLEX { + parser.unreadToken(next) + break + } + andExpr := parser.parseAndExpression() + if andExpr == nil { + return nil + } + expr.Append(andExpr) + } + return expr +} + +// expr: xor_expr ('|' xor_expr)* +func (parser *Parser) parseExpression() *ast.Expression { + expr := ast.NewExpression() + xorExpr := parser.parseXorExpression() + if xorExpr == nil { + return nil + } + expr.Append(xorExpr) + for { + next := parser.nextToken() + if next.ID != token.VBAR { + parser.unreadToken(next) + break + } + xorExpr := parser.parseXorExpression() + if xorExpr == nil { + return nil + } + expr.Append(xorExpr) + } + return expr +} + +// comparison: expr (comp_op expr)* +func (parser *Parser) parseComparison() *ast.Comparison { + comparison := ast.NewComparison() + expr := parser.parseExpression() + if expr == nil { + return nil + } + comparison.Append(expr) + + for { + // comp_op: '<'|'>'|'=='|'>='|'<='|'<>'|'!='|'in'|'not' 'in'|'is'|'is' 'not' + compOp := true + next := parser.nextToken() + switch next.Literal { + case "<", ">", "==", ">=", "<=", "<>", "!=", "in": + comparison.Append(ast.NewTokenNode(next)) + case "is": + comparison.Append(ast.NewTokenNode(next)) + next2 := parser.nextToken() + if next2.Literal == "not" { + comparison.Append(ast.NewTokenNode(next2)) + } else { + parser.unreadToken(next2) + } + case "not": + next2 := parser.nextToken() + if next2.Literal == "in" { + comparison.Append(ast.NewTokenNode(next)) + comparison.Append(ast.NewTokenNode(next2)) + } else { + parser.unreadToken(next2) + parser.unreadToken(next) + compOp = false + } + default: + parser.unreadToken(next) + compOp = false + } + if compOp == false { + break + } + expr := parser.parseExpression() + if expr == nil { + return nil + } + comparison.Append(expr) + } + + return comparison +} + // not_test: 'not' not_test | comparison func (parser *Parser) parseNotTest() *ast.NotTest { notTest := ast.NewNotTest() + next := parser.nextToken() + if next.IsLiteral("not") { + test := parser.parseNotTest() + if test == nil { + return nil + } + notTest.SetChild(test) + } else { + comparison := parser.parseComparison() + if comparison == nil { + return nil + } + notTest.SetChild(comparison) + } return notTest }