summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Griesemer <gri@golang.org>2008-10-09 18:03:16 -0700
committerRobert Griesemer <gri@golang.org>2008-10-09 18:03:16 -0700
commit63afa9b4c88ed94faba388d89b8eda7c2cbc2ed9 (patch)
treed4bc5355d95274421bb1735b318d24caf2d7e6ee
parent8ec1e53973d4fafc3ce3c667f22bdb601a766e1b (diff)
downloadgolang-63afa9b4c88ed94faba388d89b8eda7c2cbc2ed9.tar.gz
- more cleanups (simpler code for optional semi's, bug fixes)
R=r OCL=16869 CL=16869
-rw-r--r--usr/gri/pretty/parser.go167
1 files changed, 73 insertions, 94 deletions
diff --git a/usr/gri/pretty/parser.go b/usr/gri/pretty/parser.go
index fde763595..6ccfe1dad 100644
--- a/usr/gri/pretty/parser.go
+++ b/usr/gri/pretty/parser.go
@@ -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 {