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)
// Nesting level
- level int; // 0 = global scope, -1 = function/struct scope of global functions/structs, etc.
+ level int; // 0 = global scope, -1 = function scope of global functions, etc.
};
func (P *Parser) Next() {
+ P.old = P.tok;
if P.tokchan == nil {
P.pos, P.tok, P.val = P.scanner.Scan();
} else {
P.indent = 0;
P.scanner = scanner;
P.tokchan = tokchan;
+ P.old = Scanner.ILLEGAL;
P.Next();
P.level = 0;
}
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");
decl := new(AST.MethodDecl);
decl.ident = P.ParseIdent();
decl.typ = P.ParseFunctionType();
- P.Optional(Scanner.SEMICOLON);
P.Ecart();
return decl;
typ.methods = AST.NewList();
P.Expect(Scanner.INTERFACE);
- P.Expect(Scanner.LBRACE);
- P.OpenScope();
- P.level--;
- for P.tok == Scanner.IDENT {
- typ.methods.Add(P.ParseMethodDecl());
- }
- P.level++;
- P.CloseScope();
- P.Expect(Scanner.RBRACE);
+ if P.tok == Scanner.LBRACE {
+ P.Next();
+ for P.tok == Scanner.IDENT {
+ typ.methods.Add(P.ParseMethodDecl());
+ if P.tok != Scanner.RBRACE {
+ P.Expect(Scanner.SEMICOLON);
+ }
+ }
+ P.Expect(Scanner.RBRACE);
+ }
+
P.Ecart();
return typ;
}
typ.fields = AST.NewList();
P.Expect(Scanner.STRUCT);
- P.Expect(Scanner.LBRACE);
- P.OpenScope();
- P.level--;
- for P.tok == Scanner.IDENT {
- typ.fields.Add(P.ParseVarDeclList());
- if P.tok != Scanner.RBRACE {
- P.Expect(Scanner.SEMICOLON);
+
+ if P.tok == Scanner.LBRACE {
+ P.Next();
+ for P.tok == Scanner.IDENT {
+ typ.fields.Add(P.ParseVarDeclList());
+ if P.tok != Scanner.RBRACE {
+ P.Expect(Scanner.SEMICOLON);
+ }
}
+ P.Optional(Scanner.SEMICOLON);
+ P.Expect(Scanner.RBRACE);
}
- P.Optional(Scanner.SEMICOLON);
- P.level++;
- P.CloseScope();
- P.Expect(Scanner.RBRACE);
-
+
P.Ecart();
return typ;
}
P.Trace("Statement");
stat, ok := P.TryStatement();
- if !ok {
+ if ok {
+ P.OptSemicolon(Scanner.RBRACE);
+ } else {
P.Error(P.pos, "statement expected");
P.Next(); // make progress
}
- P.Ecart();
+ P.Ecart();
return stat;
}
P.Next();
for P.tok != Scanner.RPAREN {
decl.decls.Add(P.ParseSpec(exported, keyword));
- if P.tok != Scanner.RPAREN {
- // P.Expect(Scanner.SEMICOLON);
- P.Optional(Scanner.SEMICOLON); // TODO this seems wrong! (needed for math.go)
- }
+ P.OptSemicolon(Scanner.RPAREN);
}
P.Next(); // consume ")"
} else {
// func (recv) ident (params) type
// func (recv) ident (params) (results)
-func (P *Parser) ParseFuncDecl(exported bool) *AST.FuncDecl {
- P.Trace("FuncDecl");
+func (P *Parser) ParseFunctionDecl(exported bool) *AST.FuncDecl {
+ P.Trace("FunctionDecl");
fun := new(AST.FuncDecl);
fun.pos = P.pos;
P.level++;
P.CloseScope();
- if P.tok == Scanner.SEMICOLON {
- // forward declaration
- P.Next();
- } else {
+ if P.tok == Scanner.LBRACE {
fun.body = P.ParseBlock();
}
case Scanner.CONST, Scanner.TYPE, Scanner.VAR:
node = P.ParseDecl(exported, P.tok);
case Scanner.FUNC:
- node = P.ParseFuncDecl(exported);
+ node = P.ParseFunctionDecl(exported);
case Scanner.EXPORT:
if exported {
P.Error(P.pos, "cannot mark export declaration for export");
P.Next(); // make progress
}
}
-
+
+ P.OptSemicolon(Scanner.RBRACE);
+
if indent != P.indent {
panic("imbalanced tracing code (Declaration)");
}
pos := P.pos;
P.Expect(Scanner.PACKAGE);
ident := P.ParseIdent();
- P.Optional(Scanner.SEMICOLON);
decls := AST.NewList();
{ P.OpenScope();
for P.tok != Scanner.EOF {
decls.Add(P.ParseDeclaration());
- P.Optional(Scanner.SEMICOLON);
}
if P.level != 0 {