Commit 415397e3 authored by Robert Griesemer's avatar Robert Griesemer

- replaced recursive parsing of binary expressions with

  precedence-based expression parser

SVN=126556
parent cab94922
......@@ -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();
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment