From c407f08d6fbc7e83d6184c85e9fd5350aef499ac Mon Sep 17 00:00:00 2001 From: brettlangdon Date: Sat, 19 Sep 2015 14:24:01 -0400 Subject: [PATCH] add parsing of or test and or test --- ast/tests.go | 23 ++++++++++++++++-- parser/parser.go | 61 +++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 81 insertions(+), 3 deletions(-) diff --git a/ast/tests.go b/ast/tests.go index 9a188fd..1da010d 100644 --- a/ast/tests.go +++ b/ast/tests.go @@ -6,7 +6,7 @@ type TestChildNode interface { } type Test struct { - ParentNode + ListNode } func NewTest() *Test { @@ -16,7 +16,8 @@ func NewTest() *Test { } func (node *Test) testlistStarExpressionChild() {} -func (node *Test) SetChild(n TestChildNode) { node.ParentNode.SetChild(n) } +func (node *Test) testChild() {} +func (node *Test) Append(n TestChildNode) { node.ListNode.Append(n) } type OrTestChildNode interface { Node @@ -35,3 +36,21 @@ func NewOrTest() *OrTest { func (node *OrTest) testChild() {} func (node *OrTest) Append(n OrTestChildNode) { node.ListNode.Append(n) } + +type AndTestChildNode interface { + Node + andTestChild() +} + +type AndTest struct { + ListNode +} + +func NewAndTest() *AndTest { + node := &AndTest{} + node.initBaseNode(AND_TEST) + return node +} + +func (node *AndTest) orTestChild() {} +func (node *AndTest) Append(n AndTestChildNode) { node.ListNode.Append(n) } diff --git a/parser/parser.go b/parser/parser.go index 00b2b6e..9933815 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -36,12 +36,24 @@ func (parser *Parser) addError(msg string) { }) } -func (parser *Parser) expect(tokID token.TokenID) { +func (parser *Parser) expect(tokID token.TokenID) bool { next := parser.nextToken() if next.ID != tokID { msg := "Unexpected token \"" + next.ID.String() + "\" expected \"" + tokID.String() + "\"" parser.addError(msg) + return false } + return true +} + +func (parser *Parser) expectLiteral(literal string) bool { + next := parser.nextToken() + if next.ID != token.NAME || next.Literal != literal { + msg := "Unexpected literal \"" + next.Literal + "\" expected \"" + literal + "\"" + parser.addError(msg) + return false + } + return true } // compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef | decorated | async_stmt @@ -50,15 +62,62 @@ func (parser *Parser) parseCompoundStatement() *ast.CompoundStatement { return compoundStmt } +// and_test: not_test ('and' not_test)* +func (parser *Parser) parseAndTest() *ast.AndTest { + andTest := ast.NewAndTest() + return andTest +} + // or_test: and_test ('or' and_test)* func (parser *Parser) parseOrTest() *ast.OrTest { orTest := ast.NewOrTest() + andTest := parser.parseAndTest() + if andTest == nil { + return nil + } + orTest.Append(andTest) + for { + next := parser.nextToken() + if next.ID != token.NAME || next.Literal != "and" { + parser.unreadToken(next) + break + } + andTest = parser.parseAndTest() + if andTest == nil { + return nil + } + orTest.Append(andTest) + } return orTest } // test: or_test ['if' or_test 'else' test] | lambdef func (parser *Parser) parseTest() *ast.Test { test := ast.NewTest() + + orTest := parser.parseOrTest() + if orTest != nil { + test.Append(orTest) + next := parser.nextToken() + // Do not use `parser.expectLiteral`, this next part is optional + if next.ID == token.NAME && next.Literal == "if" { + orTest = parser.parseOrTest() + if orTest != nil { + test.Append(orTest) + if parser.expectLiteral("else") { + elseTest := parser.parseTest() + if elseTest == nil { + return nil + } + test.Append(test) + } + } + } else { + parser.unreadToken(next) + } + } else { + // TODO: parser.parseLambDef() + } return test }