]> Cypherpunks repositories - gostls13.git/commitdiff
- replaced recursive parsing of binary expressions with
authorRobert Griesemer <gri@golang.org>
Wed, 9 Jul 2008 21:48:26 +0000 (14:48 -0700)
committerRobert Griesemer <gri@golang.org>
Wed, 9 Jul 2008 21:48:26 +0000 (14:48 -0700)
  precedence-based expression parser

SVN=126556

usr/gri/src/parser.go

index 355120d4d5621585fa47c136f8f8e0998c9b0a19..e811fc8e72ba720c4b2c17af4a6cfeb60cd0f0d8 100644 (file)
@@ -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();
 }