diff options
author | Robert Griesemer <gri@golang.org> | 2008-07-09 14:48:26 -0700 |
---|---|---|
committer | Robert Griesemer <gri@golang.org> | 2008-07-09 14:48:26 -0700 |
commit | 3cedc9f3ae53a276e87caacb050599b8d3df94e5 (patch) | |
tree | 62dd16b23baee80ce1d06abb60974eeaf0a2cd12 | |
parent | 44810ab8e61f6e33b859d20bc0559c7ff207f46d (diff) | |
download | golang-3cedc9f3ae53a276e87caacb050599b8d3df94e5.tar.gz |
- replaced recursive parsing of binary expressions with
precedence-based expression parser
SVN=126556
-rw-r--r-- | usr/gri/src/parser.go | 115 |
1 files changed, 39 insertions, 76 deletions
diff --git a/usr/gri/src/parser.go b/usr/gri/src/parser.go index 355120d4d..e811fc8e7 100644 --- a/usr/gri/src/parser.go +++ b/usr/gri/src/parser.go @@ -20,7 +20,7 @@ type Parser struct { func (P *Parser) PrintIndent() { for i := P.indent; i > 0; i-- { - print " "; + print ". "; } } @@ -556,6 +556,7 @@ func (P *Parser) ParseGoStat() { P.Trace("GoStat"); P.Expect(Scanner.GO); P.ParseExpression(); + P.Ecart(); } @@ -755,6 +756,8 @@ func (P *Parser) ParseSelectStat() bool { func (P *Parser) TryStatement() bool { P.Trace("Statement (try)"); + indent := P.indent; + res := true; switch P.tok { case Scanner.CONST: fallthrough; case Scanner.TYPE: fallthrough; @@ -790,11 +793,13 @@ func (P *Parser) TryStatement() bool { P.ParseSelectStat(); default: // no statement found - P.Ecart(); - return false; + res = false; + } + if indent != P.indent { + panic "imbalanced tracing code" } P.Ecart(); - return true; + return res; } @@ -856,6 +861,7 @@ func (P *Parser) ParseExportDecl() { func (P *Parser) ParseDeclaration() { P.Trace("Declaration"); + indent := P.indent; switch P.tok { case Scanner.CONST: P.ParseConstDecl(); @@ -870,6 +876,9 @@ func (P *Parser) ParseDeclaration() { default: P.Error("declaration expected"); } + if indent != P.indent { + panic "imbalanced tracing code" + } P.Ecart(); } @@ -907,7 +916,7 @@ func (P *Parser) ParseOperand() { case Scanner.NEW: P.ParseNew(); default: - panic "unknown operand" + P.Error("operand expected"); } P.Ecart(); } @@ -992,90 +1001,44 @@ func (P *Parser) ParseUnaryExpr() { } -func (P *Parser) ParseMultiplicativeExpr() { - P.Trace("MultiplicativeExpr"); - P.ParseUnaryExpr(); - for { - switch P.tok { - case Scanner.MUL: fallthrough; - case Scanner.QUO: fallthrough; - case Scanner.REM: fallthrough; - case Scanner.SHL: fallthrough; - case Scanner.SHR: fallthrough; - case Scanner.AND: - P.Next(); - P.ParseUnaryExpr(); - default: - P.Ecart(); - return; - } +func Precedence(tok int) int { + // TODO should use a map or array here for lookup + switch tok { + case Scanner.COR: + return 1; + case Scanner.CAND: + return 2; + case Scanner.EQL, Scanner.NEQ, Scanner.LSS, Scanner.LEQ, Scanner.GTR, Scanner.GEQ: + return 3; + case Scanner.ADD, Scanner.SUB, Scanner.OR, Scanner.XOR: + return 4; + case Scanner.MUL, Scanner.QUO, Scanner.REM, Scanner.SHL, Scanner.SHR, Scanner.AND: + return 5; } - P.Ecart(); + return 0; } -func (P *Parser) ParseAdditiveExpr() { - P.Trace("AdditiveExpr"); - P.ParseMultiplicativeExpr(); - for { - switch P.tok { - case Scanner.ADD: fallthrough; - case Scanner.SUB: fallthrough; - case Scanner.OR: fallthrough; - case Scanner.XOR: +func (P *Parser) ParseBinaryExpr(prec1 int) { + P.Trace("BinaryExpr"); + P.ParseUnaryExpr(); + for prec := Precedence(P.tok); prec >= prec1; prec-- { + for Precedence(P.tok) == prec { P.Next(); - P.ParseMultiplicativeExpr(); - default: - P.Ecart(); - return; + P.ParseBinaryExpr(prec + 1); } } P.Ecart(); } -func (P *Parser) ParseRelationalExpr() { - P.Trace("RelationalExpr"); - P.ParseAdditiveExpr(); - switch P.tok { - case Scanner.EQL: fallthrough; - case Scanner.NEQ: fallthrough; - case Scanner.LSS: fallthrough; - case Scanner.LEQ: fallthrough; - case Scanner.GTR: fallthrough; - case Scanner.GEQ: - P.Next(); - P.ParseAdditiveExpr(); - } - P.Ecart(); -} - - -func (P *Parser) ParseLANDExpr() { - P.Trace("LANDExpr"); - P.ParseRelationalExpr(); - for P.tok == Scanner.CAND { - P.Next(); - P.ParseRelationalExpr(); - } - P.Ecart(); -} - - -func (P *Parser) ParseLORExpr() { - P.Trace("LORExpr"); - P.ParseLANDExpr(); - for P.tok == Scanner.COR { - P.Next(); - P.ParseLANDExpr(); - } - P.Ecart(); -} - - func (P *Parser) ParseExpression() { P.Trace("Expression"); - P.ParseLORExpr(); + indent := P.indent; + P.ParseBinaryExpr(1); + if indent != P.indent { + panic "imbalanced tracing code"; + } P.Ecart(); } |