- more work on Go parser
- added tests
SVN=126439
diff --git a/usr/gri/src/parser.go b/usr/gri/src/parser.go
index 333428c..d54937e 100644
--- a/usr/gri/src/parser.go
+++ b/usr/gri/src/parser.go
@@ -4,6 +4,7 @@
package Parser
+//import . "scanner"
import Scanner "scanner"
@@ -64,18 +65,27 @@
func (P *Parser) Error(msg string) {
panic "error: ", msg, "\n";
+ P.Next(); // make progress
}
func (P *Parser) Expect(tok int) {
- if tok != P.tok {
+ if P.tok == tok {
+ P.Next()
+ } else {
P.Error("expected `" + Scanner.TokenName(tok) + "`, found `" + Scanner.TokenName(P.tok) + "`");
}
- P.Next(); // make progress in any case
}
-func (P *Parser) ParseType();
+func (P *Parser) Optional(tok int) {
+ if P.tok == tok {
+ P.Next();
+ }
+}
+
+
+func (P *Parser) TryType() bool;
func (P *Parser) ParseExpression();
@@ -117,6 +127,15 @@
}
+func (P *Parser) ParseType() {
+ P.Trace("Type");
+ if !P.TryType() {
+ P.Error("type expected");
+ }
+ P.Ecart();
+}
+
+
func (P *Parser) ParseArrayType() {
P.Trace("ArrayType");
P.Expect(Scanner.LBRACK);
@@ -131,7 +150,13 @@
func (P *Parser) ParseChannelType() {
P.Trace("ChannelType");
- panic "ChannelType";
+ P.Expect(Scanner.CHAN);
+ switch P.tok {
+ case Scanner.LSS: fallthrough
+ case Scanner.GTR:
+ P.Next();
+ }
+ P.ParseType();
P.Ecart();
}
@@ -179,9 +204,7 @@
P.Expect(Scanner.SEMICOLON);
}
}
- if P.tok == Scanner.SEMICOLON {
- P.Next();
- }
+ P.Optional(Scanner.SEMICOLON);
P.Expect(Scanner.RBRACE);
P.Ecart();
}
@@ -195,8 +218,8 @@
}
-func (P *Parser) ParseType() {
- P.Trace("Type");
+func (P *Parser) TryType() bool {
+ P.Trace("Type (try)");
switch P.tok {
case Scanner.IDENT:
P.ParseTypeName();
@@ -215,9 +238,11 @@
case Scanner.MUL:
P.ParsePointerType();
default:
- P.Error("type expected");
+ P.Ecart();
+ return false;
}
P.Ecart();
+ return true;
}
@@ -242,9 +267,7 @@
P.Next();
P.ParseImportSpec();
}
- if P.tok == Scanner.SEMICOLON {
- P.Next();
- }
+ P.Optional(Scanner.SEMICOLON);
} else {
P.ParseImportSpec();
}
@@ -266,14 +289,7 @@
func (P *Parser) ParseConstSpec() {
P.Trace("ConstSpec");
P.ParseIdent();
- // TODO factor this code
- switch P.tok {
- case Scanner.IDENT, Scanner.LBRACK, Scanner.CHAN, Scanner.INTERFACE,
- Scanner.FUNC, Scanner.MAP, Scanner.STRUCT, Scanner.MUL:
- P.ParseType();
- default:
- break;
- }
+ P.TryType();
if P.tok == Scanner.ASSIGN {
P.Next();
P.ParseExpression();
@@ -286,14 +302,14 @@
P.Trace("ConstDecl");
P.Expect(Scanner.CONST);
if P.tok == Scanner.LPAREN {
- P.ParseConstSpec();
- for P.tok == Scanner.SEMICOLON {
- P.Next();
+ P.Next();
+ for P.tok != Scanner.RPAREN {
P.ParseConstSpec();
+ if P.tok != Scanner.RPAREN {
+ P.Expect(Scanner.SEMICOLON);
+ }
}
- if P.tok == Scanner.SEMICOLON {
- P.Next();
- }
+ P.Next();
} else {
P.ParseConstSpec();
}
@@ -304,14 +320,7 @@
func (P *Parser) ParseTypeSpec() {
P.Trace("TypeSpec");
P.ParseIdent();
- // TODO factor this code
- switch P.tok {
- case Scanner.IDENT, Scanner.LBRACK, Scanner.CHAN, Scanner.INTERFACE,
- Scanner.FUNC, Scanner.MAP, Scanner.STRUCT, Scanner.MUL:
- P.ParseType();
- default:
- break;
- }
+ P.TryType();
P.Ecart();
}
@@ -320,14 +329,14 @@
P.Trace("TypeDecl");
P.Expect(Scanner.TYPE);
if P.tok == Scanner.LPAREN {
- P.ParseTypeSpec();
- for P.tok == Scanner.SEMICOLON {
- P.Next();
+ P.Next();
+ for P.tok != Scanner.RPAREN {
P.ParseTypeSpec();
+ if P.tok != Scanner.RPAREN {
+ P.Expect(Scanner.SEMICOLON);
+ }
}
- if P.tok == Scanner.SEMICOLON {
- P.Next();
- }
+ P.Next();
} else {
P.ParseTypeSpec();
}
@@ -356,14 +365,14 @@
P.Trace("VarDecl");
P.Expect(Scanner.VAR);
if P.tok == Scanner.LPAREN {
- P.ParseVarSpec();
- for P.tok == Scanner.SEMICOLON {
- P.Next();
+ P.Next();
+ for P.tok != Scanner.RPAREN {
P.ParseVarSpec();
+ if P.tok != Scanner.RPAREN {
+ P.Expect(Scanner.SEMICOLON);
+ }
}
- if P.tok == Scanner.SEMICOLON {
- P.Next();
- }
+ P.Next();
} else {
P.ParseVarSpec();
}
@@ -445,7 +454,7 @@
func (P *Parser) ParseDeclaration();
-func (P *Parser) ParseStatement() bool;
+func (P *Parser) TryStatement() bool;
func (P *Parser) ParseStatementList();
func (P *Parser) ParseBlock();
func (P *Parser) ParsePrimaryExpr();
@@ -473,30 +482,28 @@
func (P *Parser) ParseSimpleStat() {
P.Trace("SimpleStat");
P.ParseExpression();
- switch P.tok {
- case Scanner.ASSIGN: fallthrough;
- case Scanner.DEFINE:
+ if P.tok == Scanner.COLON {
P.Next();
- P.ParseExpression();
- case Scanner.COMMA:
+ P.Ecart();
+ return;
+ }
+ if P.tok == 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");
- }
+ }
+ switch P.tok {
+ case Scanner.ASSIGN: fallthrough;
+ case Scanner.DEFINE: fallthrough;
+ case Scanner.ADD_ASSIGN: fallthrough;
+ case Scanner.SUB_ASSIGN: fallthrough;
+ case Scanner.MUL_ASSIGN: fallthrough;
+ case Scanner.QUO_ASSIGN: fallthrough;
+ case Scanner.REM_ASSIGN: fallthrough;
+ case Scanner.AND_ASSIGN: fallthrough;
+ case Scanner.OR_ASSIGN: fallthrough;
+ case Scanner.XOR_ASSIGN: fallthrough;
+ case Scanner.SHL_ASSIGN: fallthrough;
+ case Scanner.SHR_ASSIGN:
P.Next();
P.ParseExpressionList();
case Scanner.INC:
@@ -508,6 +515,13 @@
}
+func (P *Parser) ParseGoStat() {
+ P.Trace("GoStat");
+ P.Expect(Scanner.GO);
+ P.ParseExpression();
+}
+
+
func (P *Parser) ParseReturnStat() {
P.Trace("ReturnStat");
P.Expect(Scanner.RETURN);
@@ -518,9 +532,9 @@
}
-func (P *Parser) ParseBreakStat() {
- P.Trace("BreakStat");
- P.Expect(Scanner.BREAK);
+func (P *Parser) ParseControlFlowStat(tok int) {
+ P.Trace("ControlFlowStat");
+ P.Expect(tok);
if P.tok == Scanner.IDENT {
P.ParseIdent();
}
@@ -528,11 +542,10 @@
}
-func (P *Parser) ParseContinueStat() {
- P.Trace("ContinueStat");
- P.Expect(Scanner.CONTINUE);
- if P.tok == Scanner.IDENT {
- P.ParseIdent();
+func (P *Parser) ParseStatement() {
+ P.Trace("Statement");
+ if !P.TryStatement() {
+ P.Error("statement expected");
}
P.Ecart();
}
@@ -544,6 +557,7 @@
if P.tok != Scanner.LBRACE {
P.ParseSimpleStat();
if P.tok == Scanner.SEMICOLON {
+ P.Next();
P.ParseExpression();
}
}
@@ -554,9 +568,7 @@
P.ParseIfStat();
} else {
// TODO should be P.ParseBlock()
- if !P.ParseStatement() {
- P.Error("statement expected");
- }
+ P.ParseStatement();
}
}
P.Ecart();
@@ -614,15 +626,11 @@
P.ParseCaseList();
if P.tok != Scanner.FALLTHROUGH && P.tok != Scanner.RBRACE {
P.ParseStatementList();
- if P.tok == Scanner.SEMICOLON {
- P.Next();
- }
+ P.Optional(Scanner.SEMICOLON);
}
if P.tok == Scanner.FALLTHROUGH {
P.Next();
- if P.tok == Scanner.SEMICOLON {
- P.Next();
- }
+ P.Optional(Scanner.SEMICOLON);
}
P.Ecart();
}
@@ -634,6 +642,7 @@
if P.tok != Scanner.LBRACE {
P.ParseSimpleStat();
if P.tok == Scanner.SEMICOLON {
+ P.Next();
P.ParseExpression();
}
}
@@ -646,14 +655,16 @@
}
-func (P *Parser) ParseStatement() bool {
- P.Trace("Statement");
+func (P *Parser) TryStatement() bool {
+ P.Trace("Statement (try)");
switch P.tok {
case Scanner.CONST: fallthrough;
case Scanner.TYPE: fallthrough;
case Scanner.VAR: fallthrough;
case Scanner.FUNC:
P.ParseDeclaration();
+ case Scanner.GTR:
+ P.ParseSimpleStat(); // send
case Scanner.IDENT:
switch P.ident {
case "print", "panic":
@@ -662,15 +673,11 @@
P.ParseSimpleStat();
}
case Scanner.GO:
- panic "go statement";
+ P.ParseGoStat();
case Scanner.RETURN:
P.ParseReturnStat();
- case Scanner.BREAK:
- P.ParseBreakStat();
- case Scanner.CONTINUE:
- P.ParseContinueStat();
- case Scanner.GOTO:
- panic "goto statement";
+ case Scanner.BREAK, Scanner.CONTINUE, Scanner.GOTO:
+ P.ParseControlFlowStat(P.tok);
case Scanner.LBRACE:
P.ParseBlock();
case Scanner.IF:
@@ -695,10 +702,8 @@
func (P *Parser) ParseStatementList() {
P.Trace("StatementList");
- for P.ParseStatement() {
- if P.tok == Scanner.SEMICOLON {
- P.Next();
- }
+ for P.TryStatement() {
+ P.Optional(Scanner.SEMICOLON);
}
P.Ecart();
}
@@ -710,9 +715,7 @@
if P.tok != Scanner.RBRACE && P.tok != Scanner.SEMICOLON {
P.ParseStatementList();
}
- if P.tok == Scanner.SEMICOLON {
- P.Next();
- }
+ P.Optional(Scanner.SEMICOLON);
P.Expect(Scanner.RBRACE);
P.Ecart();
}
@@ -740,6 +743,7 @@
P.Next();
P.ParseIdent();
}
+ P.Optional(Scanner.COMMA);
P.Ecart();
}
@@ -759,7 +763,6 @@
P.ParseExportDecl();
default:
P.Error("declaration expected");
- P.Next(); // make progress
}
P.Ecart();
}
@@ -791,7 +794,8 @@
case Scanner.LPAREN:
P.Next();
P.ParseExpression();
- P.Expect(Scanner.LPAREN);
+ P.Expect(Scanner.RPAREN);
+ case Scanner.NIL: fallthrough;
case Scanner.IOTA: fallthrough;
case Scanner.TRUE: fallthrough;
case Scanner.FALSE:
@@ -895,6 +899,7 @@
case Scanner.SHL: fallthrough;
case Scanner.SHR: fallthrough;
case Scanner.AND:
+ P.Next();
P.ParseUnaryExpr();
default:
P.Ecart();
@@ -914,6 +919,7 @@
case Scanner.SUB: fallthrough;
case Scanner.OR: fallthrough;
case Scanner.XOR:
+ P.Next();
P.ParseMultiplicativeExpr();
default:
P.Ecart();
@@ -976,15 +982,11 @@
P.ParseIdent();
for P.tok == Scanner.IMPORT {
P.ParseImportDecl();
- if P.tok == Scanner.SEMICOLON {
- P.Next();
- }
+ P.Optional(Scanner.SEMICOLON);
}
for P.tok != Scanner.EOF {
P.ParseDeclaration();
- if P.tok == Scanner.SEMICOLON {
- P.Next();
- }
+ P.Optional(Scanner.SEMICOLON);
}
P.Ecart();
}