diff --git a/ast/expressions.go b/ast/expressions.go index 4b768dc..6a0652b 100644 --- a/ast/expressions.go +++ b/ast/expressions.go @@ -15,6 +15,7 @@ func NewTestListStarExpression() *TestlistStarExpression { return node } +func (node *TestlistStarExpression) expressionStatementChild() {} func (node *TestlistStarExpression) SetChild(n TestlistStarExpressionChildNode) { node.ParentNode.SetChild(n) } @@ -31,6 +32,7 @@ type Comparison struct { func NewComparison() *Comparison { node := &Comparison{} node.initBaseNode(COMPARISON) + node.initListNode() return node } @@ -49,6 +51,7 @@ type Expression struct { func NewExpression() *Expression { node := &Expression{} node.initBaseNode(EXPR) + node.initListNode() return node } @@ -67,6 +70,7 @@ type XorExpression struct { func NewXorExpression() *XorExpression { node := &XorExpression{} node.initBaseNode(XOR_EXPR) + node.initListNode() return node } @@ -85,6 +89,7 @@ type AndExpression struct { func NewAndExpression() *AndExpression { node := &AndExpression{} node.initBaseNode(AND_EXPR) + node.initListNode() return node } @@ -103,8 +108,144 @@ type ShiftExpression struct { func NewShiftExpression() *ShiftExpression { node := &ShiftExpression{} node.initBaseNode(SHIFT_EXPR) + node.initListNode() return node } func (node *ShiftExpression) andExpressionChild() {} func (node *ShiftExpression) Append(n ShiftExpressionChildNode) { node.ListNode.Append(n) } + +type ArithmeticExpressionChildNode interface { + Node + arithmeticExpressionChild() +} + +type ArithmeticExpression struct { + ListNode +} + +func NewArithmeticExpression() *ArithmeticExpression { + node := &ArithmeticExpression{} + node.initBaseNode(ARITH_EXPR) + node.initListNode() + return node +} + +func (node *ArithmeticExpression) shiftExpressionChild() {} +func (node *ArithmeticExpression) Append(n ArithmeticExpressionChildNode) { node.ListNode.Append(n) } + +type TermChildNode interface { + Node + termChild() +} + +type Term struct { + ListNode +} + +func NewTerm() *Term { + node := &Term{} + node.initBaseNode(TERM) + node.initListNode() + return node +} + +func (node *Term) arithmeticExpressionChild() {} +func (node *Term) Append(n TermChildNode) { node.ListNode.Append(n) } + +type FactorChildNode interface { + Node + factorChild() +} + +type Factor struct { + ListNode +} + +func NewFactor() *Factor { + node := &Factor{} + node.initBaseNode(FACTOR) + node.initListNode() + return node +} + +func (node *Factor) factorChild() {} +func (node *Factor) powerChild() {} +func (node *Factor) termChild() {} +func (node *Factor) Append(n FactorChildNode) { node.ListNode.Append(n) } + +type PowerChildNode interface { + Node + powerChild() +} + +type Power struct { + ListNode +} + +func NewPower() *Power { + node := &Power{} + node.initBaseNode(POWER) + node.initListNode() + return node +} + +func (node *Power) factorChild() {} +func (node *Power) Append(n PowerChildNode) { node.ListNode.Append(n) } + +type AtomExpressionChildNode interface { + Node + atomExpressionChild() +} + +type AtomExpression struct { + ListNode +} + +func NewAtomExpression() *AtomExpression { + node := &AtomExpression{} + node.initBaseNode(ATOM_EXPR) + node.initListNode() + return node +} + +func (node *AtomExpression) powerChild() {} +func (node *AtomExpression) Append(n AtomExpressionChildNode) { node.ListNode.Append(n) } + +type AtomChildNode interface { + Node + atomChild() +} + +type Atom struct { + ListNode +} + +func NewAtom() *Atom { + node := &Atom{} + node.initBaseNode(ATOM) + node.initListNode() + return node +} + +func (node *Atom) atomExpressionChild() {} +func (node *Atom) Append(n AtomChildNode) { node.ListNode.Append(n) } + +type TrailerChildNode interface { + Node + trailerChild() +} + +type Trailer struct { + ListNode +} + +func NewTrailer() *Trailer { + node := &Trailer{} + node.initBaseNode(TRAILER) + node.initListNode() + return node +} + +func (node *Trailer) atomExpressionChild() {} +func (node *Trailer) Append(n TrailerChildNode) { node.ListNode.Append(n) } diff --git a/ast/nodes.go b/ast/nodes.go index 850e6a6..3f23bb2 100644 --- a/ast/nodes.go +++ b/ast/nodes.go @@ -16,8 +16,14 @@ func NewTokenNode(tok *token.Token) *TokenNode { Token: tok, } } -func (node *TokenNode) comparisonChild() {} -func (node *TokenNode) Name() string { return token.TokenNames[node.Token.ID] } +func (node *TokenNode) atomChild() {} +func (node *TokenNode) atomExpressionChild() {} +func (node *TokenNode) comparisonChild() {} +func (node *TokenNode) expressionStatementChild() {} +func (node *TokenNode) factorChild() {} +func (node *TokenNode) shiftExpressionChild() {} +func (node *TokenNode) trailerChild() {} +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/ast/smallstatements.go b/ast/smallstatements.go index 7460ce2..27811d6 100644 --- a/ast/smallstatements.go +++ b/ast/smallstatements.go @@ -2,7 +2,7 @@ package ast type SmallStatementChildNode interface { Node - smallStmtChildNode() + smallStmtChild() } type SmallStatement struct { @@ -17,16 +17,22 @@ func NewSmallStatement() *SmallStatement { func (node *SmallStatement) SetChild(n SmallStatementChildNode) { node.ParentNode.SetChild(n) } +type ExpressionStatementChildNode interface { + Node + expressionStatementChild() +} + type ExpressionStatement struct { - ParentNode + ListNode Expression *TestlistStarExpression } func NewExpressionStatement() *ExpressionStatement { node := &ExpressionStatement{} node.initBaseNode(EXPR_STMT) + node.initListNode() return node } -func (node *ExpressionStatement) smallStmtChildNode() {} -func (node *ExpressionStatement) SetChild(n *TestlistStarExpression) { node.ParentNode.SetChild(n) } +func (node *ExpressionStatement) smallStmtChild() {} +func (node *ExpressionStatement) Append(n ExpressionStatementChildNode) { node.ListNode.Append(n) } diff --git a/parser/parser.go b/parser/parser.go index 7f2358f..892b881 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -62,9 +62,205 @@ func (parser *Parser) parseCompoundStatement() *ast.CompoundStatement { return compoundStmt } +// atom: ('(' [yield_expr|testlist_comp] ')' | +// '[' [testlist_comp] ']' | +// '{' [dictorsetmaker] '}' | +// NAME | NUMBER | STRING+ | '...' | 'None' | 'True' | 'False') +func (parser *Parser) parseAtom() *ast.Atom { + atom := ast.NewAtom() + next := parser.nextToken() + switch next.ID { + case token.NAME, token.NUMBER, token.ELLIPSIS: + atom.Append(ast.NewTokenNode(next)) + case token.STRING: + atom.Append(ast.NewTokenNode(next)) + for { + next := parser.nextToken() + if next.ID != token.STRING { + parser.unreadToken(next) + break + } + atom.Append(ast.NewTokenNode(next)) + } + } + return atom +} + +// trailer: '(' [arglist] ')' | '[' subscriptlist ']' | '.' NAME +func (parser *Parser) parseTrailer() *ast.Trailer { + trailer := ast.NewTrailer() + next := parser.nextToken() + switch next.ID { + case token.LPAR: + next2 := parser.nextToken() + if next2.ID != token.RPAR { + return nil + } + trailer.Append(ast.NewTokenNode(next)) + trailer.Append(ast.NewTokenNode(next2)) + case token.LBRACE: + next2 := parser.nextToken() + if next2.ID != token.RBRACE { + return nil + } + trailer.Append(ast.NewTokenNode(next)) + trailer.Append(ast.NewTokenNode(next2)) + case token.DOT: + next2 := parser.nextToken() + if next2.ID == token.NAME { + trailer.Append(ast.NewTokenNode(next)) + trailer.Append(ast.NewTokenNode(next2)) + } else { + parser.addError("Expected \"NAME\" instead found \"" + next.ID.String() + "\"") + return nil + } + default: + parser.unreadToken(next) + return nil + } + return trailer +} + +// atom_expr: [AWAIT] atom trailer* +func (parser *Parser) parseAtomExpression() *ast.AtomExpression { + expr := ast.NewAtomExpression() + next := parser.nextToken() + if next.ID == token.AWAIT { + expr.Append(ast.NewTokenNode(next)) + } else { + parser.unreadToken(next) + } + + atom := parser.parseAtom() + if atom == nil { + return nil + } + expr.Append(atom) + for { + trailer := parser.parseTrailer() + if trailer == nil { + break + } + expr.Append(trailer) + } + + return expr +} + +// power: atom_expr ['**' factor] +func (parser *Parser) parsePower() *ast.Power { + power := ast.NewPower() + atomExpr := parser.parseAtomExpression() + if atomExpr == nil { + return nil + } + power.Append(atomExpr) + + next := parser.nextToken() + if next.ID == token.DOUBLESTAR { + factor := parser.parseFactor() + if factor == nil { + return nil + } else { + power.Append(factor) + } + } else { + parser.unreadToken(next) + } + return power +} + +// factor: ('+'|'-'|'~') factor | power +func (parser *Parser) parseFactor() *ast.Factor { + factor := ast.NewFactor() + next := parser.nextToken() + switch next.ID { + case token.PLUS, token.MINUS, token.TILDE: + node := parser.parseFactor() + if node == nil { + return nil + } + factor.Append(ast.NewTokenNode(next)) + factor.Append(node) + default: + parser.unreadToken(next) + power := parser.parsePower() + if power == nil { + return nil + } + factor.Append(power) + } + + return factor +} + +// term: factor (('*'|'@'|'/'|'%'|'//') factor)* +func (parser *Parser) parseTerm() *ast.Term { + term := ast.NewTerm() + factor := parser.parseFactor() + if factor == nil { + return nil + } + term.Append(factor) + for { + next := parser.nextToken() + if next.ID != token.STAR && next.ID != token.AMPER && next.ID != token.SLASH && next.ID != token.PERCENT && next.ID != token.DOUBLESLASH { + parser.unreadToken(next) + break + } + factor := parser.parseFactor() + if factor == nil { + return nil + } + term.Append(factor) + } + return term +} + +// arith_expr: term (('+'|'-') term)* +func (parser *Parser) parseArithmetricExpression() *ast.ArithmeticExpression { + expr := ast.NewArithmeticExpression() + term := parser.parseTerm() + if term == nil { + return nil + } + expr.Append(term) + for { + next := parser.nextToken() + if next.ID != token.PLUS || next.ID != token.MINUS { + parser.unreadToken(next) + break + } + term := parser.parseTerm() + if term == nil { + return nil + } + expr.Append(term) + } + return expr +} + // shift_expr: arith_expr (('<<'|'>>') arith_expr)* func (parser *Parser) parseShiftExpression() *ast.ShiftExpression { expr := ast.NewShiftExpression() + arithExpr := parser.parseArithmetricExpression() + if arithExpr == nil { + return nil + } + expr.Append(arithExpr) + for { + next := parser.nextToken() + if next.ID != token.LEFTSHIFT && next.ID != token.RIGHTSHIFT { + parser.unreadToken(next) + break + } + expr.Append(ast.NewTokenNode(next)) + arithExpr := parser.parseArithmetricExpression() + if arithExpr == nil { + return nil + } + expr.Append(arithExpr) + } return expr } @@ -199,6 +395,7 @@ func (parser *Parser) parseNotTest() *ast.NotTest { } notTest.SetChild(test) } else { + parser.unreadToken(next) comparison := parser.parseComparison() if comparison == nil { return nil @@ -302,11 +499,29 @@ func (parser *Parser) parseTestlistStarExpression() *ast.TestlistStarExpression // ('=' (yield_expr|testlist_star_expr))*) func (parser *Parser) parseExpressionStatement() *ast.ExpressionStatement { exprStmt := ast.NewExpressionStatement() - testlistStarExpression := parser.parseTestlistStarExpression() - if testlistStarExpression == nil { + expr := parser.parseTestlistStarExpression() + if expr == nil { return nil } - exprStmt.SetChild(testlistStarExpression) + exprStmt.Append(expr) + + if false { + } else { + for { + next := parser.nextToken() + if next.ID != token.EQUAL { + parser.unreadToken(next) + break + } + exprStmt.Append(ast.NewTokenNode(next)) + expr := parser.parseTestlistStarExpression() + if expr == nil { + return nil + } + exprStmt.Append(expr) + } + } + return exprStmt }