mirror of
https://github.com/golang/go
synced 2024-11-26 04:27:58 -07:00
- more cleanups (simpler code for optional semi's, bug fixes)
R=r OCL=16869 CL=16869
This commit is contained in:
parent
bbfe31238b
commit
583dac04e3
@ -15,10 +15,10 @@ export type Parser struct {
|
|||||||
tokchan *<-chan *Scanner.Token;
|
tokchan *<-chan *Scanner.Token;
|
||||||
|
|
||||||
// Scanner.Token
|
// Scanner.Token
|
||||||
old int; // previous token
|
|
||||||
pos int; // token source position
|
pos int; // token source position
|
||||||
tok int; // one token look-ahead
|
tok int; // one token look-ahead
|
||||||
val string; // token value (for IDENT, NUMBER, STRING only)
|
val string; // token value (for IDENT, NUMBER, STRING only)
|
||||||
|
semi bool; // true if a semicolon was inserted by the previous statement
|
||||||
|
|
||||||
// Nesting level
|
// Nesting level
|
||||||
level int; // 0 = global scope, -1 = function scope of global functions, etc.
|
level int; // 0 = global scope, -1 = function scope of global functions, etc.
|
||||||
@ -54,13 +54,13 @@ func (P *Parser) Ecart() {
|
|||||||
|
|
||||||
|
|
||||||
func (P *Parser) Next() {
|
func (P *Parser) Next() {
|
||||||
P.old = P.tok;
|
|
||||||
if P.tokchan == nil {
|
if P.tokchan == nil {
|
||||||
P.pos, P.tok, P.val = P.scanner.Scan();
|
P.pos, P.tok, P.val = P.scanner.Scan();
|
||||||
} else {
|
} else {
|
||||||
t := <-P.tokchan;
|
t := <-P.tokchan;
|
||||||
P.tok, P.pos, P.val = t.tok, t.pos, t.val;
|
P.tok, P.pos, P.val = t.tok, t.pos, t.val;
|
||||||
}
|
}
|
||||||
|
P.semi = false;
|
||||||
if P.verbose {
|
if P.verbose {
|
||||||
P.PrintIndent();
|
P.PrintIndent();
|
||||||
print("[", P.pos, "] ", Scanner.TokenName(P.tok), "\n");
|
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.indent = 0;
|
||||||
P.scanner = scanner;
|
P.scanner = scanner;
|
||||||
P.tokchan = tokchan;
|
P.tokchan = tokchan;
|
||||||
P.old = Scanner.ILLEGAL;
|
|
||||||
P.Next();
|
P.Next();
|
||||||
P.level = 0;
|
P.level = 0;
|
||||||
}
|
}
|
||||||
@ -92,8 +91,8 @@ func (P *Parser) Expect(tok int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (P *Parser) Optional(tok int) {
|
func (P *Parser) OptSemicolon() {
|
||||||
if P.tok == tok {
|
if P.tok == Scanner.SEMICOLON {
|
||||||
P.Next();
|
P.Next();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -115,22 +114,10 @@ func (P *Parser) CloseScope() {
|
|||||||
|
|
||||||
func (P *Parser) TryType() (typ AST.Type, ok bool);
|
func (P *Parser) TryType() (typ AST.Type, ok bool);
|
||||||
func (P *Parser) ParseExpression() AST.Expr;
|
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) 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 {
|
func (P *Parser) ParseIdent() *AST.Ident {
|
||||||
P.Trace("Ident");
|
P.Trace("Ident");
|
||||||
|
|
||||||
@ -454,7 +441,7 @@ func (P *Parser) ParseStructType() *AST.StructType {
|
|||||||
P.Expect(Scanner.SEMICOLON);
|
P.Expect(Scanner.SEMICOLON);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
P.Optional(Scanner.SEMICOLON);
|
P.OptSemicolon();
|
||||||
P.Expect(Scanner.RBRACE);
|
P.Expect(Scanner.RBRACE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -503,31 +490,16 @@ func (P *Parser) TryType() (typ_ AST.Type, ok_ bool) {
|
|||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Blocks
|
// 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 {
|
func (P *Parser) ParseStatementList() *AST.List {
|
||||||
P.Trace("StatementList");
|
P.Trace("StatementList");
|
||||||
|
|
||||||
stats := AST.NewList();
|
stats := AST.NewList();
|
||||||
for {
|
for P.tok != Scanner.CASE && P.tok != Scanner.DEFAULT && P.tok != Scanner.RBRACE && P.tok != Scanner.EOF {
|
||||||
stat, ok := P.TryStatement();
|
stats.Add(P.ParseStatement());
|
||||||
if ok {
|
if P.tok == Scanner.SEMICOLON {
|
||||||
stats.Add(stat);
|
P.Next();
|
||||||
P.Optional(Scanner.SEMICOLON);
|
} else if P.semi {
|
||||||
|
P.semi = false; // consume inserted ";"
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -546,13 +518,13 @@ func (P *Parser) ParseBlock() *AST.Block {
|
|||||||
|
|
||||||
P.Expect(Scanner.LBRACE);
|
P.Expect(Scanner.LBRACE);
|
||||||
P.OpenScope();
|
P.OpenScope();
|
||||||
|
if P.tok != Scanner.RBRACE {
|
||||||
if P.tok != Scanner.RBRACE && P.tok != Scanner.SEMICOLON {
|
|
||||||
block.stats = P.ParseStatementList();
|
block.stats = P.ParseStatementList();
|
||||||
}
|
}
|
||||||
P.Optional(Scanner.SEMICOLON);
|
P.OptSemicolon();
|
||||||
P.CloseScope();
|
P.CloseScope();
|
||||||
P.Expect(Scanner.RBRACE);
|
P.Expect(Scanner.RBRACE);
|
||||||
|
P.semi = true; // allow optional semicolon
|
||||||
|
|
||||||
P.Ecart();
|
P.Ecart();
|
||||||
return block;
|
return block;
|
||||||
@ -801,14 +773,15 @@ func (P *Parser) ParsePrimaryExpr() AST.Expr {
|
|||||||
P.Trace("PrimaryExpr");
|
P.Trace("PrimaryExpr");
|
||||||
|
|
||||||
x := P.ParseOperand();
|
x := P.ParseOperand();
|
||||||
L: for {
|
for {
|
||||||
switch P.tok {
|
switch P.tok {
|
||||||
case Scanner.PERIOD: x = P.ParseSelectorOrTypeGuard(x);
|
case Scanner.PERIOD: x = P.ParseSelectorOrTypeGuard(x);
|
||||||
case Scanner.LBRACK: x = P.ParseIndexOrSlice(x);
|
case Scanner.LBRACK: x = P.ParseIndexOrSlice(x);
|
||||||
case Scanner.LPAREN: x = P.ParseCall(x);
|
case Scanner.LPAREN: x = P.ParseCall(x);
|
||||||
default: break L;
|
default: goto exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
exit:
|
||||||
|
|
||||||
P.Ecart();
|
P.Ecart();
|
||||||
return x;
|
return x;
|
||||||
@ -899,6 +872,7 @@ func (P *Parser) ParseSimpleStat() AST.Stat {
|
|||||||
l.ident = AST.NIL;
|
l.ident = AST.NIL;
|
||||||
}
|
}
|
||||||
P.Next(); // consume ":"
|
P.Next(); // consume ":"
|
||||||
|
P.semi = true; // allow optional semicolon
|
||||||
stat = l;
|
stat = l;
|
||||||
|
|
||||||
case
|
case
|
||||||
@ -1083,14 +1057,8 @@ func (P *Parser) ParseCaseClause() *AST.CaseClause {
|
|||||||
P.Trace("CaseClause");
|
P.Trace("CaseClause");
|
||||||
|
|
||||||
clause := P.ParseCase();
|
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();
|
clause.stats = P.ParseStatementList();
|
||||||
P.Optional(Scanner.SEMICOLON);
|
|
||||||
}
|
|
||||||
if P.tok == Scanner.FALLTHROUGH {
|
|
||||||
P.Next();
|
|
||||||
clause.falls = true;
|
|
||||||
P.Optional(Scanner.SEMICOLON);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
P.Ecart();
|
P.Ecart();
|
||||||
@ -1107,10 +1075,11 @@ func (P *Parser) ParseSwitchStat() *AST.SwitchStat {
|
|||||||
stat.cases = AST.NewList();
|
stat.cases = AST.NewList();
|
||||||
|
|
||||||
P.Expect(Scanner.LBRACE);
|
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());
|
stat.cases.Add(P.ParseCaseClause());
|
||||||
}
|
}
|
||||||
P.Expect(Scanner.RBRACE);
|
P.Expect(Scanner.RBRACE);
|
||||||
|
P.semi = true; // allow optional semicolon
|
||||||
|
|
||||||
P.Ecart();
|
P.Ecart();
|
||||||
return stat;
|
return stat;
|
||||||
@ -1122,19 +1091,10 @@ func (P *Parser) ParseCommCase() {
|
|||||||
|
|
||||||
if P.tok == Scanner.CASE {
|
if P.tok == Scanner.CASE {
|
||||||
P.Next();
|
P.Next();
|
||||||
if P.tok == Scanner.GTR {
|
P.ParseExpression();
|
||||||
// send
|
if P.tok == Scanner.ASSIGN || P.tok == Scanner.DEFINE {
|
||||||
P.Next();
|
P.Next();
|
||||||
P.ParseExpression();
|
P.Expect(Scanner.ARROW);
|
||||||
P.Expect(Scanner.EQL);
|
|
||||||
P.ParseExpression();
|
|
||||||
} else {
|
|
||||||
// receive
|
|
||||||
if P.tok != Scanner.LSS {
|
|
||||||
P.ParseIdent();
|
|
||||||
P.Expect(Scanner.ASSIGN);
|
|
||||||
}
|
|
||||||
P.Expect(Scanner.LSS);
|
|
||||||
P.ParseExpression();
|
P.ParseExpression();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1152,26 +1112,12 @@ func (P *Parser) ParseCommClause() {
|
|||||||
P.ParseCommCase();
|
P.ParseCommCase();
|
||||||
if P.tok != Scanner.CASE && P.tok != Scanner.DEFAULT && P.tok != Scanner.RBRACE {
|
if P.tok != Scanner.CASE && P.tok != Scanner.DEFAULT && P.tok != Scanner.RBRACE {
|
||||||
P.ParseStatementList();
|
P.ParseStatementList();
|
||||||
P.Optional(Scanner.SEMICOLON);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
P.Ecart();
|
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() {
|
func (P *Parser) ParseSelectStat() {
|
||||||
P.Trace("SelectStat");
|
P.Trace("SelectStat");
|
||||||
|
|
||||||
@ -1180,18 +1126,46 @@ func (P *Parser) ParseSelectStat() {
|
|||||||
for P.tok != Scanner.RBRACE && P.tok != Scanner.EOF {
|
for P.tok != Scanner.RBRACE && P.tok != Scanner.EOF {
|
||||||
P.ParseCommClause();
|
P.ParseCommClause();
|
||||||
}
|
}
|
||||||
P.Next();
|
P.Expect(Scanner.RBRACE);
|
||||||
|
P.semi = true; // allow optional semicolon
|
||||||
|
|
||||||
P.Ecart();
|
P.Ecart();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func (P *Parser) TryStatement() (stat_ AST.Stat, ok_ bool) {
|
func (P *Parser) ParseFallthroughStat() {
|
||||||
P.Trace("Statement (try)");
|
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;
|
indent := P.indent;
|
||||||
|
|
||||||
var stat AST.Stat = AST.NIL;
|
var stat AST.Stat = AST.NIL;
|
||||||
res := true;
|
|
||||||
switch P.tok {
|
switch P.tok {
|
||||||
case Scanner.CONST, Scanner.TYPE, Scanner.VAR:
|
case Scanner.CONST, Scanner.TYPE, Scanner.VAR:
|
||||||
stat = P.ParseDeclaration();
|
stat = P.ParseDeclaration();
|
||||||
@ -1218,16 +1192,17 @@ func (P *Parser) TryStatement() (stat_ AST.Stat, ok_ bool) {
|
|||||||
P.ParseRangeStat();
|
P.ParseRangeStat();
|
||||||
case Scanner.SELECT:
|
case Scanner.SELECT:
|
||||||
P.ParseSelectStat();
|
P.ParseSelectStat();
|
||||||
|
case Scanner.FALLTHROUGH:
|
||||||
|
P.ParseFallthroughStat();
|
||||||
default:
|
default:
|
||||||
// no statement found
|
P.ParseEmptyStat(); // for complete tracing output only
|
||||||
res = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if indent != P.indent {
|
if indent != P.indent {
|
||||||
panic("imbalanced tracing code (Statement)");
|
panic("imbalanced tracing code (Statement)");
|
||||||
}
|
}
|
||||||
P.Ecart();
|
P.Ecart();
|
||||||
return stat, res;
|
return stat;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1284,6 +1259,7 @@ func (P *Parser) ParseTypeSpec(exported bool) *AST.TypeDecl {
|
|||||||
decl := new(AST.TypeDecl);
|
decl := new(AST.TypeDecl);
|
||||||
decl.ident = P.ParseIdent();
|
decl.ident = P.ParseIdent();
|
||||||
decl.typ = P.ParseType();
|
decl.typ = P.ParseType();
|
||||||
|
P.semi = true; // allow optional semicolon
|
||||||
|
|
||||||
P.Ecart();
|
P.Ecart();
|
||||||
return decl;
|
return decl;
|
||||||
@ -1335,13 +1311,17 @@ func (P *Parser) ParseDecl(exported bool, keyword int) *AST.Declaration {
|
|||||||
P.Expect(keyword);
|
P.Expect(keyword);
|
||||||
if P.tok == Scanner.LPAREN {
|
if P.tok == Scanner.LPAREN {
|
||||||
P.Next();
|
P.Next();
|
||||||
|
for P.tok != Scanner.RPAREN && P.tok != Scanner.EOF {
|
||||||
decl.decls.Add(P.ParseSpec(exported, keyword));
|
decl.decls.Add(P.ParseSpec(exported, keyword));
|
||||||
P.OptSemicolon(Scanner.RPAREN);
|
if P.tok == Scanner.SEMICOLON {
|
||||||
for P.tok != Scanner.RPAREN {
|
P.Next();
|
||||||
decl.decls.Add(P.ParseSpec(exported, keyword));
|
} else {
|
||||||
P.OptSemicolon(Scanner.RPAREN);
|
break;
|
||||||
}
|
}
|
||||||
P.Next(); // consume ")"
|
}
|
||||||
|
P.Expect(Scanner.RPAREN);
|
||||||
|
P.semi = true; // allow optional semicolon
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
decl.decls.Add(P.ParseSpec(exported, keyword));
|
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 {
|
if indent != P.indent {
|
||||||
panic("imbalanced tracing code (Declaration)");
|
panic("imbalanced tracing code (Declaration)");
|
||||||
}
|
}
|
||||||
@ -1491,11 +1469,12 @@ func (P *Parser) ParseProgram() *AST.Program {
|
|||||||
|
|
||||||
for P.tok == Scanner.IMPORT {
|
for P.tok == Scanner.IMPORT {
|
||||||
decls.Add(P.ParseDecl(false, Scanner.IMPORT));
|
decls.Add(P.ParseDecl(false, Scanner.IMPORT));
|
||||||
P.Optional(Scanner.SEMICOLON);
|
P.OptSemicolon();
|
||||||
}
|
}
|
||||||
|
|
||||||
for P.tok != Scanner.EOF {
|
for P.tok != Scanner.EOF {
|
||||||
decls.Add(P.ParseDeclaration());
|
decls.Add(P.ParseDeclaration());
|
||||||
|
P.OptSemicolon();
|
||||||
}
|
}
|
||||||
|
|
||||||
if P.level != 0 {
|
if P.level != 0 {
|
||||||
|
Loading…
Reference in New Issue
Block a user