]> Cypherpunks repositories - gostls13.git/commitdiff
- go parser parses itself
authorRobert Griesemer <gri@golang.org>
Tue, 8 Jul 2008 23:39:04 +0000 (16:39 -0700)
committerRobert Griesemer <gri@golang.org>
Tue, 8 Jul 2008 23:39:04 +0000 (16:39 -0700)
SVN=126408

usr/gri/src/parser.go
usr/gri/src/scanner.go
usr/gri/src/test_parser.go

index e130bfe6b04950720f8145188a68d4e6b018864f..333428cf770356c9c28707c998d628b5533ffe7d 100644 (file)
@@ -9,34 +9,61 @@ import Scanner "scanner"
 
 export Parser
 type Parser struct {
-       verbose bool;
+       verbose, indent int;
        S *Scanner.Scanner;
        tok int;  // one token look-ahead
        beg, end int;  // token position
-};
+       ident string;  // last ident seen
+}
+
+
+func (P *Parser) PrintIndent() {
+       for i := P.indent; i > 0; i-- {
+               print "  ";
+       }
+}
+
+
+func (P *Parser) Trace(msg string) {
+       if P.verbose > 0 {
+               P.PrintIndent();
+               print msg, " {\n";
+               P.indent++;
+       }
+}
+
+
+func (P *Parser) Ecart() {
+       if P.verbose > 0 {
+               P.indent--;
+               P.PrintIndent();
+               print "}\n";
+       }
+}
 
 
 func (P *Parser) Next() {
-       P.tok, P.beg, P.end = P.S.Scan()
+       P.tok, P.beg, P.end = P.S.Scan();
+       if P.tok == Scanner.IDENT {
+               P.ident = P.S.src[P.beg : P.end];
+       }
+       if P.verbose > 1 {
+               P.PrintIndent();
+               print Scanner.TokenName(P.tok), "\n";
+       }
 }
 
 
-func (P *Parser) Open(S *Scanner.Scanner, verbose bool) {
+func (P *Parser) Open(S *Scanner.Scanner, verbose int) {
        P.verbose = verbose;
+       P.indent = 0;
        P.S = S;
        P.Next();
 }
 
 
 func (P *Parser) Error(msg string) {
-       print "error: ", msg, "\n";
-}
-
-
-func (P *Parser) Trace(msg string) {
-       if P.verbose {
-               print msg, "\n";
-       }
+       panic "error: ", msg, "\n";
 }
 
 
@@ -53,7 +80,10 @@ func (P *Parser) ParseExpression();
 
 
 func (P *Parser) ParseIdent() {
-       P.Trace("Ident");
+       if P.verbose > 0 {
+               P.PrintIndent();
+               print "Ident = \"", P.ident, "\"\n";
+       }
        P.Expect(Scanner.IDENT);
 }
 
@@ -65,6 +95,7 @@ func (P *Parser) ParseIdentList() {
                P.Next();
                P.ParseIdent();
        }
+       P.Ecart();
 }
 
 
@@ -75,12 +106,14 @@ func (P *Parser) ParseQualifiedIdent() {
                P.Next();
                P.ParseIdent();
        }
+       P.Ecart();
 }
 
 
 func (P *Parser) ParseTypeName() {
        P.Trace("TypeName");
        P.ParseQualifiedIdent();
+       P.Ecart();
 }
 
 
@@ -92,24 +125,28 @@ func (P *Parser) ParseArrayType() {
        }
        P.Expect(Scanner.RBRACK);
        P.ParseType();
+       P.Ecart();
 }
 
 
 func (P *Parser) ParseChannelType() {
        P.Trace("ChannelType");
-       panic "ChannelType"
+       panic "ChannelType";
+       P.Ecart();
 }
 
 
 func (P *Parser) ParseInterfaceType() {
        P.Trace("InterfaceType");
-       panic "InterfaceType"
+       panic "InterfaceType";
+       P.Ecart();
 }
 
 
 func (P *Parser) ParseFunctionType() {
        P.Trace("FunctionType");
-       panic "FunctionType"
+       panic "FunctionType";
+       P.Ecart();
 }
 
 
@@ -120,6 +157,7 @@ func (P *Parser) ParseMapType() {
        P.ParseType();
        P.Expect(Scanner.RBRACK);
        P.ParseType();
+       P.Ecart();
 }
 
 
@@ -127,6 +165,7 @@ func (P *Parser) ParseFieldDecl() {
        P.Trace("FieldDecl");
        P.ParseIdentList();
        P.ParseType();
+       P.Ecart();
 }
 
 
@@ -134,17 +173,17 @@ func (P *Parser) ParseStructType() {
        P.Trace("StructType");
        P.Expect(Scanner.STRUCT);
        P.Expect(Scanner.LBRACE);
-       if P.tok != Scanner.RBRACE {
+       for P.tok != Scanner.RBRACE {
                P.ParseFieldDecl();
-               for P.tok == Scanner.SEMICOLON {
-                       P.Next();
-                       P.ParseFieldDecl();
-               }
-               if P.tok == Scanner.SEMICOLON {
-                       P.Next();
+               if P.tok != Scanner.RBRACE {
+                       P.Expect(Scanner.SEMICOLON);
                }
        }
+       if P.tok == Scanner.SEMICOLON {
+               P.Next();
+       }
        P.Expect(Scanner.RBRACE);
+       P.Ecart();
 }
 
 
@@ -152,6 +191,7 @@ func (P *Parser) ParsePointerType() {
        P.Trace("PointerType");
        P.Expect(Scanner.MUL);
        P.ParseType();
+       P.Ecart();
 }
 
 
@@ -177,6 +217,7 @@ func (P *Parser) ParseType() {
        default:
                P.Error("type expected");
        }
+       P.Ecart();
 }
 
 
@@ -188,6 +229,7 @@ func (P *Parser) ParseImportSpec() {
                P.Next();
        }
        P.Expect(Scanner.STRING);
+       P.Ecart();
 }
 
 
@@ -206,16 +248,18 @@ func (P *Parser) ParseImportDecl() {
        } else {
                P.ParseImportSpec();
        }
+       P.Ecart();
 }
 
 
 func (P *Parser) ParseExpressionList() {
-  P.Trace("ExpressionList");
+       P.Trace("ExpressionList");
        P.ParseExpression();
        for P.tok == Scanner.COMMA {
                P.Next();
                P.ParseExpression();
        }
+       P.Ecart();
 }
 
 
@@ -234,6 +278,7 @@ func (P *Parser) ParseConstSpec() {
                P.Next();
                P.ParseExpression();
        }
+       P.Ecart();
 }
 
 
@@ -252,6 +297,7 @@ func (P *Parser) ParseConstDecl() {
        } else {
                P.ParseConstSpec();
        }
+       P.Ecart();
 }
 
 
@@ -266,6 +312,7 @@ func (P *Parser) ParseTypeSpec() {
        default:
                break;
        }
+       P.Ecart();
 }
 
 
@@ -284,6 +331,7 @@ func (P *Parser) ParseTypeDecl() {
        } else {
                P.ParseTypeSpec();
        }
+       P.Ecart();
 }
 
 
@@ -300,6 +348,7 @@ func (P *Parser) ParseVarSpec() {
                        P.ParseExpressionList();
                }
        }
+       P.Ecart();
 }
 
 
@@ -318,6 +367,7 @@ func (P *Parser) ParseVarDecl() {
        } else {
                P.ParseVarSpec();
        }
+       P.Ecart();
 }
 
 
@@ -325,6 +375,7 @@ func (P *Parser) ParseParameterSection() {
        P.Trace("ParameterSection");
        P.ParseIdentList();
        P.ParseType();
+       P.Ecart();
 }
 
 
@@ -335,6 +386,7 @@ func (P *Parser) ParseParameterList() {
                P.Next();
                P.ParseParameterSection();
        }
+       P.Ecart();
 }
 
 
@@ -345,6 +397,7 @@ func (P *Parser) ParseParameters() {
                P.ParseParameterList();
        }
        P.Expect(Scanner.RPAREN);
+       P.Ecart();
 }
 
 
@@ -356,6 +409,7 @@ func (P *Parser) ParseResult() {
        } else {
                P.ParseType();
        }
+       P.Ecart();
 }
 
 
@@ -386,17 +440,33 @@ func (P *Parser) ParseNamedSignature() {
        default:
                break;
        }
+       P.Ecart();
 }
 
 
 func (P *Parser) ParseDeclaration();
-func (P *Parser) ParseStatement();
+func (P *Parser) ParseStatement() bool;
+func (P *Parser) ParseStatementList();
 func (P *Parser) ParseBlock();
+func (P *Parser) ParsePrimaryExpr();
 
 
 func (P *Parser) ParsePrimaryExprList() {
        P.Trace("PrimaryExprList");
-       panic "PrimaryExprList"
+       P.ParsePrimaryExpr();
+       for P.tok == Scanner.COMMA {
+               P.Next();
+               P.ParsePrimaryExpr();
+       }
+       P.Ecart();
+}
+
+
+func (P *Parser) ParseBuiltinStat() {
+       P.Trace("BuiltinStat");
+       P.Expect(Scanner.IDENT);
+       P.ParseExpressionList();  // TODO should be optional
+       P.Ecart();
 }
 
 
@@ -404,17 +474,67 @@ func (P *Parser) ParseSimpleStat() {
        P.Trace("SimpleStat");
        P.ParseExpression();
        switch P.tok {
-       case Scanner.ASSIGN:
+       case Scanner.ASSIGN: fallthrough;
+       case Scanner.DEFINE:
                P.Next();
                P.ParseExpression();
        case Scanner.COMMA:
                P.Next();
                P.ParsePrimaryExprList();
+               switch P.tok {
+               case Scanner.ASSIGN:
+               case Scanner.ADD_ASSIGN:
+               case Scanner.SUB_ASSIGN:
+               case Scanner.MUL_ASSIGN:
+               case Scanner.QUO_ASSIGN:
+               case Scanner.REM_ASSIGN:
+               case Scanner.AND_ASSIGN:
+               case Scanner.OR_ASSIGN:
+               case Scanner.XOR_ASSIGN:
+               case Scanner.SHL_ASSIGN:
+               case Scanner.SHR_ASSIGN:
+                       break;
+               default:
+                       P.Error("expected assignment operand");
+               }
+               P.Next();
+               P.ParseExpressionList();
        case Scanner.INC:
                P.Next();
        case Scanner.DEC:
                P.Next();
        }
+       P.Ecart();
+}
+
+
+func (P *Parser) ParseReturnStat() {
+       P.Trace("ReturnStat");
+       P.Expect(Scanner.RETURN);
+       if P.tok != Scanner.SEMICOLON && P.tok != Scanner.RBRACE {
+               P.ParseExpressionList();
+       }
+       P.Ecart();
+}
+
+
+func (P *Parser) ParseBreakStat() {
+       P.Trace("BreakStat");
+       P.Expect(Scanner.BREAK);
+       if P.tok == Scanner.IDENT {
+               P.ParseIdent();
+       }
+       P.Ecart();
+}
+
+
+func (P *Parser) ParseContinueStat() {
+       P.Trace("ContinueStat");
+       P.Expect(Scanner.CONTINUE);
+       if P.tok == Scanner.IDENT {
+               P.ParseIdent();
+       }
+       P.Ecart();
 }
 
 
@@ -434,25 +554,99 @@ func (P *Parser) ParseIfStat() {
                        P.ParseIfStat();
                } else {
                        // TODO should be P.ParseBlock()
-                       P.ParseStatement();
+                       if !P.ParseStatement() {
+                               P.Error("statement expected");
+                       }
                }
        }
+       P.Ecart();
 }
 
 
 func (P *Parser) ParseForStat() {
        P.Trace("ForStat");
-       panic "for stat";
+       P.Expect(Scanner.FOR);
+       if P.tok != Scanner.LBRACE {
+               if P.tok != Scanner.SEMICOLON {
+                       P.ParseSimpleStat();
+               }
+               if P.tok == Scanner.SEMICOLON {
+                       P.Next();
+                       if P.tok != Scanner.SEMICOLON {
+                               P.ParseExpression();
+                       }
+                       P.Expect(Scanner.SEMICOLON);
+                       if P.tok != Scanner.LBRACE {
+                               P.ParseSimpleStat();
+                       }
+               }
+       }
+       P.ParseBlock();
+       P.Ecart();
+}
+
+
+func (P *Parser) ParseCase() {
+       P.Trace("Case");
+       if P.tok == Scanner.CASE {
+               P.Next();
+               P.ParseExpressionList();
+       } else {
+               P.Expect(Scanner.DEFAULT);
+       }
+       P.Expect(Scanner.COLON);
+       P.Ecart();
+}
+
+
+func (P *Parser) ParseCaseList() {
+       P.Trace("CaseList");
+       P.ParseCase();
+       for P.tok == Scanner.CASE || P.tok == Scanner.DEFAULT {
+               P.ParseCase();
+       }
+       P.Ecart();
+}
+
+
+func (P *Parser) ParseCaseClause() {
+       P.Trace("CaseClause");
+       P.ParseCaseList();
+       if P.tok != Scanner.FALLTHROUGH && P.tok != Scanner.RBRACE {
+               P.ParseStatementList();
+               if P.tok == Scanner.SEMICOLON {
+                       P.Next();
+               }
+       }
+       if P.tok == Scanner.FALLTHROUGH {
+               P.Next();
+               if P.tok == Scanner.SEMICOLON {
+                       P.Next();
+               }
+       }
+       P.Ecart();
 }
 
 
 func (P *Parser) ParseSwitchStat() {
        P.Trace("SwitchStat");
-       panic "switch stat";
+       P.Expect(Scanner.SWITCH);
+       if P.tok != Scanner.LBRACE {
+               P.ParseSimpleStat();
+               if P.tok == Scanner.SEMICOLON {
+                       P.ParseExpression();
+               }
+       }
+       P.Expect(Scanner.LBRACE);
+       for P.tok != Scanner.RBRACE {
+               P.ParseCaseClause();
+       }
+       P.Expect(Scanner.RBRACE);
+       P.Ecart();
 }
 
 
-func (P *Parser) ParseStatement() {
+func (P *Parser) ParseStatement() bool {
        P.Trace("Statement");
        switch P.tok {
        case Scanner.CONST: fallthrough;
@@ -461,15 +655,20 @@ func (P *Parser) ParseStatement() {
        case Scanner.FUNC:
                P.ParseDeclaration();
        case Scanner.IDENT:
-               P.ParseSimpleStat();
+               switch P.ident {
+               case "print", "panic":
+                       P.ParseBuiltinStat();
+               default:
+                       P.ParseSimpleStat();
+               }
        case Scanner.GO:
                panic "go statement";
        case Scanner.RETURN:
-               panic "return statement";
+               P.ParseReturnStat();
        case Scanner.BREAK:
-               panic "break statement";
+               P.ParseBreakStat();
        case Scanner.CONTINUE:
-               panic "continue statement";
+               P.ParseContinueStat();
        case Scanner.GOTO:
                panic "goto statement";
        case Scanner.LBRACE:
@@ -485,18 +684,23 @@ func (P *Parser) ParseStatement() {
        case Scanner.SELECT:
                panic "select statement";
        default:
-               P.Error("statement expected");
+               // no statement found
+               P.Ecart();
+               return false;
        }
+       P.Ecart();
+       return true;
 }
 
 
 func (P *Parser) ParseStatementList() {
        P.Trace("StatementList");
-       P.ParseStatement();
-       for P.tok == Scanner.SEMICOLON {
-               P.Next();
-               P.ParseStatement();
+       for P.ParseStatement() {
+               if P.tok == Scanner.SEMICOLON {
+                       P.Next();
+               }
        }
+       P.Ecart();
 }
 
 
@@ -510,6 +714,7 @@ func (P *Parser) ParseBlock() {
                P.Next();
        }
        P.Expect(Scanner.RBRACE);
+       P.Ecart();
 }
 
 
@@ -523,12 +728,19 @@ func (P *Parser) ParseFuncDecl() {
        } else {
                P.ParseBlock();
        }
+       P.Ecart();
 }
 
 
 func (P *Parser) ParseExportDecl() {
        P.Trace("ExportDecl");
-       P.Next();
+       P.Expect(Scanner.EXPORT);
+       P.ParseIdent();
+       for P.tok == Scanner.COMMA {
+               P.Next();
+               P.ParseIdent();
+       }
+       P.Ecart();
 }
 
 
@@ -549,27 +761,85 @@ func (P *Parser) ParseDeclaration() {
                P.Error("declaration expected");
                P.Next();  // make progress
        }
+       P.Ecart();
+}
+
+
+func (P *Parser) ParseNew() {
+       P.Trace("New");
+       P.Expect(Scanner.NEW);
+       P.Expect(Scanner.LPAREN);
+       P.ParseType();
+       if P.tok == Scanner.COMMA {
+               P.Next();
+               P.ParseExpressionList()
+       }
+       P.Expect(Scanner.RPAREN);
+       P.Ecart();
 }
 
 
 func (P *Parser) ParseOperand() {
        P.Trace("Operand");
-       P.Next();
+       switch P.tok {
+       case Scanner.IDENT:
+               P.ParseQualifiedIdent();
+       case Scanner.STRING:
+               fallthrough;
+       case Scanner.NUMBER:
+               P.Next();
+       case Scanner.LPAREN:
+               P.Next();
+               P.ParseExpression();
+               P.Expect(Scanner.LPAREN);
+       case Scanner.IOTA: fallthrough;
+       case Scanner.TRUE: fallthrough;
+       case Scanner.FALSE:
+               P.Next();
+       case Scanner.NEW:
+               P.ParseNew();
+       default:
+               panic "unknown operand"
+       }
+       P.Ecart();
 }
 
 
 func (P *Parser) ParseSelectorOrTypeAssertion() {
        P.Trace("SelectorOrTypeAssertion");
+       P.Expect(Scanner.PERIOD);
+       if P.tok == Scanner.IDENT {
+               P.ParseIdent();
+       } else {
+               P.Expect(Scanner.LPAREN);
+               P.ParseType();
+               P.Expect(Scanner.RPAREN);
+       }
+       P.Ecart();
 }
 
 
 func (P *Parser) ParseIndexOrSlice() {
        P.Trace("IndexOrSlice");
+       P.Expect(Scanner.LBRACK);
+       P.ParseExpression();
+       if P.tok == Scanner.COLON {
+               P.Next();
+               P.ParseExpression();
+       }
+       P.Expect(Scanner.RBRACK);
+       P.Ecart();
 }
 
 
 func (P *Parser) ParseInvocation() {
        P.Trace("Invocation");
+       P.Expect(Scanner.LPAREN);
+       if P.tok != Scanner.RPAREN {
+               P.ParseExpressionList();
+       }
+       P.Expect(Scanner.RPAREN);
+       P.Ecart();
 }
 
 
@@ -585,9 +855,11 @@ func (P *Parser) ParsePrimaryExpr() {
                case Scanner.LPAREN:
                        P.ParseInvocation();
                default:
+                       P.Ecart();
                        return;
                }
        }
+       P.Ecart();
 }
 
 
@@ -602,10 +874,13 @@ func (P *Parser) ParseUnaryExpr() {
        case Scanner.GTR: fallthrough;
        case Scanner.MUL: fallthrough;
        case Scanner.AND:
+               P.Next();
                P.ParseUnaryExpr();
+               P.Ecart();
                return;
        }
        P.ParsePrimaryExpr();
+       P.Ecart();
 }
 
 
@@ -622,9 +897,11 @@ func (P *Parser) ParseMultiplicativeExpr() {
                case Scanner.AND:
                        P.ParseUnaryExpr();
                default:
+                       P.Ecart();
                        return;
                }
        }
+       P.Ecart();
 }
 
 
@@ -639,9 +916,11 @@ func (P *Parser) ParseAdditiveExpr() {
                case Scanner.XOR:
                        P.ParseMultiplicativeExpr();
                default:
+                       P.Ecart();
                        return;
                }
        }
+       P.Ecart();
 }
 
 
@@ -655,8 +934,10 @@ func (P *Parser) ParseRelationalExpr() {
        case Scanner.LEQ: fallthrough;
        case Scanner.GTR: fallthrough;
        case Scanner.GEQ:
+               P.Next();
                P.ParseAdditiveExpr();
        }
+       P.Ecart();
 }
 
 
@@ -667,6 +948,7 @@ func (P *Parser) ParseLANDExpr() {
                P.Next();
                P.ParseRelationalExpr();
        }
+       P.Ecart();
 }
 
 
@@ -677,12 +959,14 @@ func (P *Parser) ParseLORExpr() {
                P.Next();
                P.ParseLANDExpr();
        }
+       P.Ecart();
 }
 
 
 func (P *Parser) ParseExpression() {
        P.Trace("Expression");
-       P.Next();
+       P.ParseLORExpr();
+       P.Ecart();
 }
 
 
@@ -702,4 +986,5 @@ func (P *Parser) ParseProgram() {
                        P.Next();
                }
        }
+       P.Ecart();
 }
index 5fd74cc44e6f9cd05acd8a5e0ff3d487f23200df..b3a29ab69af97d180f81477c9121c22eb3206461 100644 (file)
@@ -18,7 +18,7 @@ export
        AND_ASSIGN, OR_ASSIGN, XOR_ASSIGN, SHL_ASSIGN, SHR_ASSIGN,
        CAND, COR,
        BREAK, CASE, CHAN, CONST, CONTINUE, DEFAULT, ELSE, EXPORT, FALLTHROUGH, FALSE,
-       FOR, FUNC, GO, GOTO, IF, IMPORT, INTERFACE, MAP, NEW, NIL, PACKAGE, RANGE,
+       FOR, FUNC, GO, GOTO, IF, IMPORT, INTERFACE, IOTA, MAP, NEW, NIL, PACKAGE, RANGE,
        RETURN, SELECT, STRUCT, SWITCH, TRUE, TYPE, VAR
        
        
@@ -103,6 +103,7 @@ const (
        IF;
        IMPORT;
        INTERFACE;
+       IOTA;
        MAP;
        NEW;
        NIL;
@@ -140,8 +141,8 @@ func TokenName(tok int) string {
        case RPAREN: return ")";
        case LBRACK: return "[";
        case RBRACK: return "]";
-       case LBRACE: return "{";
-       case RBRACE: return "}";
+       case LBRACE: return "LBRACE";
+       case RBRACE: return "RBRACE";
 
        case ASSIGN: return "=";
        case DEFINE: return ":=";
@@ -203,6 +204,7 @@ func TokenName(tok int) string {
        case IF: return "if";
        case IMPORT: return "import";
        case INTERFACE: return "interface";
+       case IOTA: return "iota";
        case MAP: return "map";
        case NEW: return "new";
        case NIL: return "nil";
index a85e9b9272bbd29d653ce8f45fdf62b887b0e3ea..35d51b57aaf8ad604a39207bd6dd07826d58e239 100644 (file)
@@ -8,7 +8,7 @@ import Scanner "scanner"
 import Parser "parser"
 
 
-func Parse(src string, verbose bool) {
+func Parse(src string, verbose int) {
        S := new(Scanner.Scanner);
        S.Open(src);
        
@@ -20,10 +20,14 @@ func Parse(src string, verbose bool) {
 
 
 func main() {
-       verbose := false;
+       verbose := 0;
        for i := 1; i < sys.argc(); i++ {
-               if sys.argv(i) == "-v" {
-                       verbose = true;
+               switch sys.argv(i) {
+               case "-v":
+                       verbose = 1;
+                       continue;
+               case "-vv":
+                       verbose = 2;
                        continue;
                }