]> Cypherpunks repositories - gostls13.git/commitdiff
- more cleanups (simpler code for optional semi's, bug fixes)
authorRobert Griesemer <gri@golang.org>
Fri, 10 Oct 2008 01:03:16 +0000 (18:03 -0700)
committerRobert Griesemer <gri@golang.org>
Fri, 10 Oct 2008 01:03:16 +0000 (18:03 -0700)
R=r
OCL=16869
CL=16869

usr/gri/pretty/parser.go

index fde763595f7b0996ecbfd4f243ef1d37588a2c71..6ccfe1dadbd7a04d38d92517ca9d0b219362e57d 100644 (file)
@@ -15,10 +15,10 @@ export type Parser struct {
        tokchan *<-chan *Scanner.Token;
        
        // Scanner.Token
-       old int;  // previous token
        pos int;  // token source position
        tok int;  // one token look-ahead
        val string;  // token value (for IDENT, NUMBER, STRING only)
+       semi bool;  // true if a semicolon was inserted by the previous statement
 
        // Nesting level
        level int;  // 0 = global scope, -1 = function scope of global functions, etc.
@@ -54,13 +54,13 @@ func (P *Parser) Ecart() {
 
 
 func (P *Parser) Next() {
-       P.old = P.tok;
        if P.tokchan == nil {
                P.pos, P.tok, P.val = P.scanner.Scan();
        } else {
                t := <-P.tokchan;
                P.tok, P.pos, P.val = t.tok, t.pos, t.val;
        }
+       P.semi = false;
        if P.verbose {
                P.PrintIndent();
                print("[", P.pos, "] ", Scanner.TokenName(P.tok), "\n");
@@ -73,7 +73,6 @@ func (P *Parser) Open(verbose bool, scanner *Scanner.Scanner, tokchan *<-chan *S
        P.indent = 0;
        P.scanner = scanner;
        P.tokchan = tokchan;
-       P.old = Scanner.ILLEGAL;
        P.Next();
        P.level = 0;
 }
@@ -92,8 +91,8 @@ func (P *Parser) Expect(tok int) {
 }
 
 
-func (P *Parser) Optional(tok int) {
-       if P.tok == tok {
+func (P *Parser) OptSemicolon() {
+       if P.tok == Scanner.SEMICOLON {
                P.Next();
        }
 }
@@ -115,22 +114,10 @@ func (P *Parser) CloseScope() {
 
 func (P *Parser) TryType() (typ AST.Type, ok bool);
 func (P *Parser) ParseExpression() AST.Expr;
-func (P *Parser) TryStatement() (stat AST.Stat, ok bool);
+func (P *Parser) ParseStatement() AST.Stat;
 func (P *Parser) ParseDeclaration() AST.Node;
 
 
-func (P *Parser) OptSemicolon(tok int) {
-       P.Trace("OptSemicolon");
-       if P.tok == Scanner.SEMICOLON {
-               P.Next();
-       } else if P.level != 0 || P.old != tok || P.tok != tok {
-               // TODO FIX THIS
-               // P.Expect(Scanner.SEMICOLON);
-       }
-       P.Ecart();
-}
-
-
 func (P *Parser) ParseIdent() *AST.Ident {
        P.Trace("Ident");
 
@@ -454,7 +441,7 @@ func (P *Parser) ParseStructType() *AST.StructType {
                                P.Expect(Scanner.SEMICOLON);
                        }
                }
-               P.Optional(Scanner.SEMICOLON);
+               P.OptSemicolon();
                P.Expect(Scanner.RBRACE);
        }
 
@@ -503,31 +490,16 @@ func (P *Parser) TryType() (typ_ AST.Type, ok_ bool) {
 // ----------------------------------------------------------------------------
 // Blocks
 
-func (P *Parser) ParseStatement() AST.Stat {
-       P.Trace("Statement");
-       
-       stat, ok := P.TryStatement();
-       if ok {
-               P.OptSemicolon(Scanner.RBRACE);
-       } else {
-               P.Error(P.pos, "statement expected");
-               P.Next();  // make progress
-       }
-       
-       P.Ecart();
-       return stat;
-}
-
-
 func (P *Parser) ParseStatementList() *AST.List {
        P.Trace("StatementList");
        
        stats := AST.NewList();
-       for {
-               stat, ok := P.TryStatement();
-               if ok {
-                       stats.Add(stat);
-                       P.Optional(Scanner.SEMICOLON);
+       for P.tok != Scanner.CASE && P.tok != Scanner.DEFAULT && P.tok != Scanner.RBRACE && P.tok != Scanner.EOF {
+               stats.Add(P.ParseStatement());
+               if P.tok == Scanner.SEMICOLON {
+                       P.Next();
+               } else if P.semi {
+                       P.semi = false;  // consume inserted ";"
                } else {
                        break;
                }
@@ -546,13 +518,13 @@ func (P *Parser) ParseBlock() *AST.Block {
        
        P.Expect(Scanner.LBRACE);
        P.OpenScope();
-       
-       if P.tok != Scanner.RBRACE && P.tok != Scanner.SEMICOLON {
+       if P.tok != Scanner.RBRACE {
                block.stats = P.ParseStatementList();
        }
-       P.Optional(Scanner.SEMICOLON);
+       P.OptSemicolon();
        P.CloseScope();
        P.Expect(Scanner.RBRACE);
+       P.semi = true;  // allow optional semicolon
        
        P.Ecart();
        return block;
@@ -801,14 +773,15 @@ func (P *Parser) ParsePrimaryExpr() AST.Expr {
        P.Trace("PrimaryExpr");
        
        x := P.ParseOperand();
-       L: for {
+       for {
                switch P.tok {
                case Scanner.PERIOD: x = P.ParseSelectorOrTypeGuard(x);
                case Scanner.LBRACK: x = P.ParseIndexOrSlice(x);
                case Scanner.LPAREN: x = P.ParseCall(x);
-               default: break L;
+               default: goto exit;
                }
        }
+exit:
 
        P.Ecart();
        return x;
@@ -899,6 +872,7 @@ func (P *Parser) ParseSimpleStat() AST.Stat {
                        l.ident = AST.NIL;
                }
                P.Next();  // consume ":"
+               P.semi = true;  // allow optional semicolon
                stat = l;
                
        case
@@ -1083,14 +1057,8 @@ func (P *Parser) ParseCaseClause() *AST.CaseClause {
        P.Trace("CaseClause");
 
        clause := P.ParseCase();
-       if P.tok != Scanner.FALLTHROUGH && P.tok != Scanner.RBRACE {
+       if P.tok != Scanner.CASE && P.tok != Scanner.DEFAULT && P.tok != Scanner.RBRACE {
                clause.stats = P.ParseStatementList();
-               P.Optional(Scanner.SEMICOLON);
-       }
-       if P.tok == Scanner.FALLTHROUGH {
-               P.Next();
-               clause.falls = true;
-               P.Optional(Scanner.SEMICOLON);
        }
        
        P.Ecart();
@@ -1107,10 +1075,11 @@ func (P *Parser) ParseSwitchStat() *AST.SwitchStat {
        stat.cases = AST.NewList();
        
        P.Expect(Scanner.LBRACE);
-       for P.tok == Scanner.CASE || P.tok == Scanner.DEFAULT {
+       for P.tok != Scanner.RBRACE && P.tok != Scanner.EOF {
                stat.cases.Add(P.ParseCaseClause());
        }
        P.Expect(Scanner.RBRACE);
+       P.semi = true;  // allow optional semicolon
 
        P.Ecart();
        return stat;
@@ -1122,19 +1091,10 @@ func (P *Parser) ParseCommCase() {
   
   if P.tok == Scanner.CASE {
        P.Next();
-       if P.tok == Scanner.GTR {
-               // send
+       P.ParseExpression();
+       if P.tok == Scanner.ASSIGN || P.tok == Scanner.DEFINE {
                P.Next();
-               P.ParseExpression();
-               P.Expect(Scanner.EQL);
-               P.ParseExpression();
-       } else {
-               // receive
-               if P.tok != Scanner.LSS {
-                       P.ParseIdent();
-                       P.Expect(Scanner.ASSIGN);
-               }
-               P.Expect(Scanner.LSS);
+               P.Expect(Scanner.ARROW);
                P.ParseExpression();
        }
   } else {
@@ -1152,26 +1112,12 @@ func (P *Parser) ParseCommClause() {
        P.ParseCommCase();
        if P.tok != Scanner.CASE && P.tok != Scanner.DEFAULT && P.tok != Scanner.RBRACE {
                P.ParseStatementList();
-               P.Optional(Scanner.SEMICOLON);
        }
        
        P.Ecart();
 }
 
 
-func (P *Parser) ParseRangeStat() {
-       P.Trace("RangeStat");
-       
-       P.Expect(Scanner.RANGE);
-       P.ParseIdentList();
-       P.Expect(Scanner.DEFINE);
-       P.ParseExpression();
-       P.ParseBlock();
-       
-       P.Ecart();
-}
-
-
 func (P *Parser) ParseSelectStat() {
        P.Trace("SelectStat");
        
@@ -1180,18 +1126,46 @@ func (P *Parser) ParseSelectStat() {
        for P.tok != Scanner.RBRACE && P.tok != Scanner.EOF {
                P.ParseCommClause();
        }
-       P.Next();
+       P.Expect(Scanner.RBRACE);
+       P.semi = true;  // allow optional semicolon
        
        P.Ecart();
 }
 
 
-func (P *Parser) TryStatement() (stat_ AST.Stat, ok_ bool) {
-       P.Trace("Statement (try)");
+func (P *Parser) ParseFallthroughStat() {
+       P.Trace("FallthroughStat");
+       
+       P.Expect(Scanner.FALLTHROUGH);
+
+       P.Ecart();
+}
+
+
+func (P *Parser) ParseEmptyStat() {
+       P.Trace("EmptyStat");
+       P.Ecart();
+}
+
+
+func (P *Parser) ParseRangeStat() {
+       P.Trace("RangeStat");
+       
+       P.Expect(Scanner.RANGE);
+       P.ParseIdentList();
+       P.Expect(Scanner.DEFINE);
+       P.ParseExpression();
+       P.ParseBlock();
+       
+       P.Ecart();;
+}
+
+
+func (P *Parser) ParseStatement() AST.Stat {
+       P.Trace("Statement");
        indent := P.indent;
 
        var stat AST.Stat = AST.NIL;
-       res := true;
        switch P.tok {
        case Scanner.CONST, Scanner.TYPE, Scanner.VAR:
                stat = P.ParseDeclaration();
@@ -1218,16 +1192,17 @@ func (P *Parser) TryStatement() (stat_ AST.Stat, ok_ bool) {
                P.ParseRangeStat();
        case Scanner.SELECT:
                P.ParseSelectStat();
+       case Scanner.FALLTHROUGH:
+               P.ParseFallthroughStat();
        default:
-               // no statement found
-               res = false;
+               P.ParseEmptyStat();  // for complete tracing output only
        }
 
        if indent != P.indent {
                panic("imbalanced tracing code (Statement)");
        }
        P.Ecart();
-       return stat, res;
+       return stat;
 }
 
 
@@ -1284,6 +1259,7 @@ func (P *Parser) ParseTypeSpec(exported bool) *AST.TypeDecl {
        decl := new(AST.TypeDecl);
        decl.ident = P.ParseIdent();
        decl.typ = P.ParseType();
+       P.semi = true;  // allow optional semicolon
        
        P.Ecart();
        return decl;
@@ -1335,13 +1311,17 @@ func (P *Parser) ParseDecl(exported bool, keyword int) *AST.Declaration {
        P.Expect(keyword);
        if P.tok == Scanner.LPAREN {
                P.Next();
-               decl.decls.Add(P.ParseSpec(exported, keyword));
-               P.OptSemicolon(Scanner.RPAREN);
-               for P.tok != Scanner.RPAREN {
+               for P.tok != Scanner.RPAREN && P.tok != Scanner.EOF {
                        decl.decls.Add(P.ParseSpec(exported, keyword));
-                       P.OptSemicolon(Scanner.RPAREN);
+                       if P.tok == Scanner.SEMICOLON {
+                               P.Next();
+                       } else {
+                               break;
+                       }
                }
-               P.Next();  // consume ")"
+               P.Expect(Scanner.RPAREN);
+               P.semi = true;  // allow optional semicolon
+               
        } else {
                decl.decls.Add(P.ParseSpec(exported, keyword));
        }
@@ -1462,8 +1442,6 @@ func (P *Parser) ParseDeclaration() AST.Node {
                }
        }
 
-       P.OptSemicolon(Scanner.RBRACE);
-
        if indent != P.indent {
                panic("imbalanced tracing code (Declaration)");
        }
@@ -1491,11 +1469,12 @@ func (P *Parser) ParseProgram() *AST.Program {
                
                for P.tok == Scanner.IMPORT {
                        decls.Add(P.ParseDecl(false, Scanner.IMPORT));
-                       P.Optional(Scanner.SEMICOLON);
+                       P.OptSemicolon();
                }
                
                for P.tok != Scanner.EOF {
                        decls.Add(P.ParseDeclaration());
+                       P.OptSemicolon();
                }
                
                if P.level != 0 {