summaryrefslogtreecommitdiff
path: root/usr/gri/pretty/parser.go
diff options
context:
space:
mode:
authorRobert Griesemer <gri@golang.org>2009-03-20 17:18:48 -0700
committerRobert Griesemer <gri@golang.org>2009-03-20 17:18:48 -0700
commit21bbab179109ac1e7b114adb7e6951392e84cc17 (patch)
treeac8f61c0bdf9479c947fbec61171add3ef4a5384 /usr/gri/pretty/parser.go
parent3308a5032636f93ce81335c42c4a31e5a42c80b5 (diff)
downloadgolang-21bbab179109ac1e7b114adb7e6951392e84cc17.tar.gz
- completed AST cleanup
- implemented support for type switches R=r OCL=26608 CL=26608
Diffstat (limited to 'usr/gri/pretty/parser.go')
-rw-r--r--usr/gri/pretty/parser.go836
1 files changed, 429 insertions, 407 deletions
diff --git a/usr/gri/pretty/parser.go b/usr/gri/pretty/parser.go
index ffe9615c9..5c13e5998 100644
--- a/usr/gri/pretty/parser.go
+++ b/usr/gri/pretty/parser.go
@@ -25,6 +25,11 @@ import (
type Position scanner.Location
+type interval struct {
+ beg, end int;
+}
+
+
// A Parser holds the parser's internal state while processing
// a given text. It can be allocated as part of another data
// structure but must be initialized via Init before use.
@@ -37,11 +42,11 @@ type Parser struct {
trace bool;
indent uint;
- comments vector.Vector;
- last_comment ast.CommentGroup;
+ comments vector.Vector; // list of collected, unassociated comments
+ last_doc interval; // last comments interval of consecutive comments
// The next token
- loc Position; // token location
+ pos Position; // token location
tok int; // one token look-ahead
val []byte; // token value
@@ -51,9 +56,9 @@ type Parser struct {
};
-// When we don't have a location use noloc.
+// When we don't have a location use nopos.
// TODO make sure we always have a location.
-var noloc Position;
+var nopos Position;
// ----------------------------------------------------------------------------
@@ -95,32 +100,35 @@ func un/*trace*/(P *Parser) {
func (P *Parser) next0() {
- P.loc, P.tok, P.val = P.scanner.Scan();
+ P.pos, P.tok, P.val = P.scanner.Scan();
P.opt_semi = false;
if P.trace {
P.printIndent();
switch P.tok {
case token.IDENT, token.INT, token.FLOAT, token.CHAR, token.STRING:
- fmt.Printf("%d:%d: %s = %s\n", P.loc.Line, P.loc.Col, token.TokenString(P.tok), P.val);
+ fmt.Printf("%d:%d: %s = %s\n", P.pos.Line, P.pos.Col, token.TokenString(P.tok), P.val);
case token.LPAREN:
// don't print '(' - screws up selection in terminal window
- fmt.Printf("%d:%d: LPAREN\n", P.loc.Line, P.loc.Col);
+ fmt.Printf("%d:%d: LPAREN\n", P.pos.Line, P.pos.Col);
case token.RPAREN:
// don't print ')' - screws up selection in terminal window
- fmt.Printf("%d:%d: RPAREN\n", P.loc.Line, P.loc.Col);
+ fmt.Printf("%d:%d: RPAREN\n", P.pos.Line, P.pos.Col);
default:
- fmt.Printf("%d:%d: %s\n", P.loc.Line, P.loc.Col, token.TokenString(P.tok));
+ fmt.Printf("%d:%d: %s\n", P.pos.Line, P.pos.Col, token.TokenString(P.tok));
}
}
}
-func (P *Parser) getComment() *ast.Comment {
- defer P.next0();
-
- // for /*-style comments, the comment may end on a different line
- endline := P.loc.Line;
+// Collect a comment in the parser's comment list and return the line
+// on which the comment ends.
+func (P *Parser) collectComment() int {
+ // For /*-style comments, the comment may end on a different line.
+ // Scan the comment for '\n' chars and adjust the end line accordingly.
+ // (Note that the position of the next token may be even further down
+ // as there may be more whitespace lines after the comment.)
+ endline := P.pos.Line;
if P.val[1] == '*' {
for i, b := range P.val {
if b == '\n' {
@@ -128,51 +136,30 @@ func (P *Parser) getComment() *ast.Comment {
}
}
}
+ P.comments.Push(&ast.Comment{P.pos, P.val, endline});
+ P.next0();
- return &ast.Comment{P.loc, endline, P.val};
-}
-
-
-func (P *Parser) getCommentGroup() ast.CommentGroup {
- list := vector.New(0);
-
- // group adjacent comments
- // (an empty line terminates a group)
- endline := P.loc.Line;
- for P.tok == token.COMMENT && endline+1 >= P.loc.Line {
- c := P.getComment();
- list.Push(c);
- endline = c.EndLine;
- }
-
- // convert list
- group := make(ast.CommentGroup, list.Len());
- for i := 0; i < list.Len(); i++ {
- group[i] = list.At(i).(*ast.Comment);
- }
-
- return group;
+ return endline;
}
-func (P *Parser) getLastComment() ast.CommentGroup {
- c := P.last_comment;
- if c != nil && c[len(c) - 1].EndLine + 1 < P.loc.Line {
- // empty line between last comment and current token,
- // at least one line of space between last comment
- // and current token; ignore this comment
- return nil;
+func (P *Parser) getComments() interval {
+ // group adjacent comments, an empty line terminates a group
+ beg := P.comments.Len();
+ endline := P.pos.Line;
+ for P.tok == token.COMMENT && endline+1 >= P.pos.Line {
+ endline = P.collectComment();
}
- return c;
+ end := P.comments.Len();
+ return interval {beg, end};
}
func (P *Parser) next() {
P.next0();
- P.last_comment = nil;
+ P.last_doc = interval{0, 0};
for P.tok == token.COMMENT {
- P.last_comment = P.getCommentGroup();
- P.comments.Push(P.last_comment);
+ P.last_doc = P.getComments();
}
}
@@ -186,8 +173,8 @@ func (P *Parser) Init(scanner *scanner.Scanner, err scanner.ErrorHandler, trace
}
-func (P *Parser) error(loc Position, msg string) {
- P.err.Error(loc, msg);
+func (P *Parser) error(pos Position, msg string) {
+ P.err.Error(pos, msg);
}
@@ -197,14 +184,36 @@ func (P *Parser) expect(tok int) Position {
if token.IsLiteral(P.tok) {
msg += " " + string(P.val);
}
- P.error(P.loc, msg);
+ P.error(P.pos, msg);
}
- loc := P.loc;
+ loc := P.pos;
P.next(); // make progress in any case
return loc;
}
+func (P *Parser) getDoc() ast.Comments {
+ doc := P.last_doc;
+ n := doc.end - doc.beg;
+
+ if n <= 0 || P.comments.At(doc.end - 1).(*ast.Comment).EndLine + 1 < P.pos.Line {
+ // no comments or empty line between last comment and current token;
+ // do not use as documentation
+ return nil;
+ }
+
+ // found immediately adjacent comment interval;
+ // use as documentation
+ c := make(ast.Comments, n);
+ for i := 0; i < n; i++ {
+ c[i] = P.comments.At(doc.beg + i).(*ast.Comment);
+ // TODO find a better way to do this
+ P.comments.Set(doc.beg + i, nil); // remove the comment from the general list
+ }
+ return c;
+}
+
+
// ----------------------------------------------------------------------------
// Common productions
@@ -220,13 +229,13 @@ func (P *Parser) parseIdent() *ast.Ident {
}
if P.tok == token.IDENT {
- x := &ast.Ident{string(P.val), P.loc};
+ x := &ast.Ident{P.pos, P.val};
P.next();
return x;
}
-
P.expect(token.IDENT); // use expect() error handling
- return &ast.Ident{"", P.loc};
+
+ return &ast.Ident{P.pos, [0]byte{}};
}
@@ -250,6 +259,7 @@ func (P *Parser) parseIdentList(x ast.Expr) []*ast.Ident {
for i := 0; i < list.Len(); i++ {
idents[i] = list.At(i).(*ast.Ident);
}
+
return idents;
}
@@ -271,6 +281,7 @@ func (P *Parser) parseExpressionList() []ast.Expr {
for i := 0; i < list.Len(); i++ {
exprs[i] = list.At(i).(ast.Expr);
}
+
return exprs;
}
@@ -283,13 +294,13 @@ func (P *Parser) parseType() ast.Expr {
defer un(trace(P, "Type"));
}
- t := P.tryType();
- if t == nil {
- P.error(P.loc, "type expected");
- t = &ast.BadExpr{P.loc};
+ typ := P.tryType();
+ if typ == nil {
+ P.error(P.pos, "type expected");
+ typ = &ast.BadExpr{P.pos};
}
- return t;
+ return typ;
}
@@ -309,12 +320,10 @@ func (P *Parser) parseQualifiedIdent() ast.Expr {
var x ast.Expr = P.parseIdent();
for P.tok == token.PERIOD {
- pos := P.loc;
P.next();
sel := P.parseIdent();
- x = &ast.Selector{x, sel, pos};
+ x = &ast.SelectorExpr{x, sel};
}
-
return x;
}
@@ -333,11 +342,10 @@ func (P *Parser) parseArrayType() *ast.ArrayType {
defer un(trace(P, "ArrayType"));
}
- loc := P.loc;
- P.expect(token.LBRACK);
+ lbrack := P.expect(token.LBRACK);
var len ast.Expr;
if P.tok == token.ELLIPSIS {
- len = &ast.Ellipsis{P.loc};
+ len = &ast.Ellipsis{P.pos};
P.next();
} else if P.tok != token.RBRACK {
len = P.parseExpression(1);
@@ -345,7 +353,7 @@ func (P *Parser) parseArrayType() *ast.ArrayType {
P.expect(token.RBRACK);
elt := P.parseType();
- return &ast.ArrayType{loc, len, elt};
+ return &ast.ArrayType{lbrack, len, elt};
}
@@ -354,28 +362,28 @@ func (P *Parser) parseChannelType() *ast.ChannelType {
defer un(trace(P, "ChannelType"));
}
- loc := P.loc;
- mode := ast.FULL;
+ pos := P.pos;
+ dir := ast.SEND | ast.RECV;
if P.tok == token.CHAN {
P.next();
if P.tok == token.ARROW {
P.next();
- mode = ast.SEND;
+ dir = ast.SEND;
}
} else {
P.expect(token.ARROW);
P.expect(token.CHAN);
- mode = ast.RECV;
+ dir = ast.RECV;
}
- val := P.parseVarType();
+ value := P.parseVarType();
- return &ast.ChannelType{loc, mode, val};
+ return &ast.ChannelType{pos, dir, value};
}
func (P *Parser) tryParameterType() ast.Expr {
if P.tok == token.ELLIPSIS {
- loc := P.loc;
+ loc := P.pos;
P.next();
return &ast.Ellipsis{loc};
}
@@ -386,9 +394,10 @@ func (P *Parser) tryParameterType() ast.Expr {
func (P *Parser) parseParameterType() ast.Expr {
typ := P.tryParameterType();
if typ == nil {
- P.error(P.loc, "type expected");
- typ = &ast.BadExpr{P.loc};
+ P.error(P.pos, "type expected");
+ typ = &ast.BadExpr{P.pos};
}
+
return typ;
}
@@ -431,20 +440,20 @@ func (P *Parser) parseParameterList(ellipsis_ok bool) []*ast.Field {
idents[i] = list.At(i).(*ast.Ident);
}
list.Init(0);
- list.Push(&ast.Field{idents, typ, nil, nil});
+ list.Push(&ast.Field{nil, idents, typ, nil});
for P.tok == token.COMMA {
P.next();
idents := P.parseIdentList(nil);
typ := P.parseParameterType();
- list.Push(&ast.Field{idents, typ, nil, nil});
+ list.Push(&ast.Field{nil, idents, typ, nil});
}
} else {
// Type { "," Type }
// convert list of types into list of *Param
for i := 0; i < list.Len(); i++ {
- list.Set(i, &ast.Field{nil, list.At(i).(ast.Expr), nil, nil});
+ list.Set(i, &ast.Field{nil, nil, list.At(i).(ast.Expr), nil});
}
}
@@ -487,7 +496,7 @@ func (P *Parser) parseResult() []*ast.Field {
typ := P.tryType();
if typ != nil {
result = make([]*ast.Field, 1);
- result[0] = &ast.Field{nil, typ, nil, nil};
+ result[0] = &ast.Field{nil, nil, typ, nil};
}
}
@@ -507,7 +516,7 @@ func (P *Parser) parseSignature() *ast.Signature {
}
params := P.parseParameters(true); // TODO find better solution
- //t.End = P.loc;
+ //t.End = P.pos;
result := P.parseResult();
return &ast.Signature{params, result};
@@ -519,11 +528,10 @@ func (P *Parser) parseFunctionType() *ast.FunctionType {
defer un(trace(P, "FunctionType"));
}
- loc := P.loc;
- P.expect(token.FUNC);
+ pos := P.expect(token.FUNC);
sig := P.parseSignature();
- return &ast.FunctionType{loc, sig};
+ return &ast.FunctionType{pos, sig};
}
@@ -532,19 +540,20 @@ func (P *Parser) parseMethodSpec() *ast.Field {
defer un(trace(P, "MethodSpec"));
}
+ doc := P.getDoc();
var idents []*ast.Ident;
var typ ast.Expr;
x := P.parseQualifiedIdent();
if tmp, is_ident := x.(*ast.Ident); is_ident && (P.tok == token.COMMA || P.tok == token.LPAREN) {
// method(s)
idents = P.parseIdentList(x);
- typ = &ast.FunctionType{noloc, P.parseSignature()};
+ typ = &ast.FunctionType{nopos, P.parseSignature()};
} else {
// embedded interface
typ = x;
}
- return &ast.Field{idents, typ, nil, nil};
+ return &ast.Field{doc, idents, typ, nil};
}
@@ -553,12 +562,11 @@ func (P *Parser) parseInterfaceType() *ast.InterfaceType {
defer un(trace(P, "InterfaceType"));
}
- loc := P.loc;
- var end Position;
+ pos := P.expect(token.INTERFACE);
+ var lbrace, rbrace Position;
var methods []*ast.Field;
-
- P.expect(token.INTERFACE);
if P.tok == token.LBRACE {
+ lbrace = P.pos;
P.next();
list := vector.New(0);
@@ -569,8 +577,7 @@ func (P *Parser) parseInterfaceType() *ast.InterfaceType {
}
}
- end = P.loc;
- P.expect(token.RBRACE);
+ rbrace = P.expect(token.RBRACE);
P.opt_semi = true;
// convert vector
@@ -580,7 +587,7 @@ func (P *Parser) parseInterfaceType() *ast.InterfaceType {
}
}
- return &ast.InterfaceType{loc, methods, end};
+ return &ast.InterfaceType{pos, lbrace, methods, rbrace};
}
@@ -589,25 +596,24 @@ func (P *Parser) parseMapType() *ast.MapType {
defer un(trace(P, "MapType"));
}
- loc := P.loc;
- P.expect(token.MAP);
+ pos := P.expect(token.MAP);
P.expect(token.LBRACK);
key := P.parseVarType();
P.expect(token.RBRACK);
- val := P.parseVarType();
+ value := P.parseVarType();
- return &ast.MapType{loc, key, val};
+ return &ast.MapType{pos, key, value};
}
-func (P *Parser) parseStringLit() ast.Expr
+func (P *Parser) parseStringLit(x *ast.BasicLit) *ast.StringLit
func (P *Parser) parseFieldDecl() *ast.Field {
if P.trace {
defer un(trace(P, "FieldDecl"));
}
- comment := P.getLastComment();
+ doc := P.getDoc();
// a list of identifiers looks like a list of type names
list := vector.New(0);
@@ -627,7 +633,7 @@ func (P *Parser) parseFieldDecl() *ast.Field {
// optional tag
var tag ast.Expr;
if P.tok == token.STRING {
- tag = P.parseStringLit();
+ tag = P.parseStringLit(nil);
}
// analyze case
@@ -648,25 +654,24 @@ func (P *Parser) parseFieldDecl() *ast.Field {
// TODO should do more checks here
typ = list.At(0).(ast.Expr);
} else {
- P.error(P.loc, "anonymous field expected");
+ P.error(P.pos, "anonymous field expected");
}
}
- return &ast.Field{idents, typ, tag, comment};
+ return &ast.Field{doc, idents, typ, tag};
}
-func (P *Parser) parseStructType() ast.Expr {
+func (P *Parser) parseStructType() *ast.StructType {
if P.trace {
defer un(trace(P, "StructType"));
}
- loc := P.loc;
- var end Position;
+ pos := P.expect(token.STRUCT);
+ var lbrace, rbrace Position;
var fields []*ast.Field;
-
- P.expect(token.STRUCT);
if P.tok == token.LBRACE {
+ lbrace = P.pos;
P.next();
list := vector.New(0);
@@ -682,8 +687,7 @@ func (P *Parser) parseStructType() ast.Expr {
P.next();
}
- end = P.loc;
- P.expect(token.RBRACE);
+ rbrace = P.expect(token.RBRACE);
P.opt_semi = true;
// convert vector
@@ -693,20 +697,19 @@ func (P *Parser) parseStructType() ast.Expr {
}
}
- return &ast.StructType{loc, fields, end};
+ return &ast.StructType{pos, lbrace, fields, rbrace};
}
-func (P *Parser) parsePointerType() ast.Expr {
+func (P *Parser) parsePointerType() *ast.StarExpr {
if P.trace {
defer un(trace(P, "PointerType"));
}
- loc := P.loc;
- P.expect(token.MUL);
+ star := P.expect(token.MUL);
base := P.parseType();
- return &ast.PointerType{loc, base};
+ return &ast.StarExpr{star, base};
}
@@ -725,11 +728,11 @@ func (P *Parser) tryType() ast.Expr {
case token.STRUCT: return P.parseStructType();
case token.MUL: return P.parsePointerType();
case token.LPAREN:
- lparen := P.loc;
+ lparen := P.pos;
P.next();
x := P.parseType();
rparen := P.expect(token.RPAREN);
- return &ast.Group{x, lparen, rparen};
+ return &ast.ParenExpr{lparen, x, rparen};
}
// no type found
@@ -740,12 +743,21 @@ func (P *Parser) tryType() ast.Expr {
// ----------------------------------------------------------------------------
// Blocks
+func asStatList(list *vector.Vector) []ast.Stat {
+ stats := make([]ast.Stat, list.Len());
+ for i := 0; i < list.Len(); i++ {
+ stats[i] = list.At(i).(ast.Stat);
+ }
+ return stats;
+}
+
-func (P *Parser) parseStatementList(list *vector.Vector) {
+func (P *Parser) parseStatementList() []ast.Stat {
if P.trace {
defer un(trace(P, "StatementList"));
}
+ list := vector.New(0);
expect_semi := false;
for P.tok != token.CASE && P.tok != token.DEFAULT && P.tok != token.RBRACE && P.tok != token.EOF {
if expect_semi {
@@ -761,6 +773,8 @@ func (P *Parser) parseStatementList(list *vector.Vector) {
expect_semi = true;
}
}
+
+ return asStatList(list);
}
@@ -769,18 +783,15 @@ func (P *Parser) parseBlock(tok int) *ast.Block {
defer un(trace(P, "Block"));
}
- b := ast.NewBlock(P.loc, tok);
- P.expect(tok);
-
- P.parseStatementList(b.List);
-
+ pos := P.expect(tok);
+ list := P.parseStatementList();
+ var end scanner.Location;
if tok == token.LBRACE {
- b.End = P.loc;
- P.expect(token.RBRACE);
+ end = P.expect(token.RBRACE);
P.opt_semi = true;
}
- return b;
+ return &ast.Block{pos, tok, list, end};
}
@@ -792,29 +803,28 @@ func (P *Parser) parseFunctionLit() ast.Expr {
defer un(trace(P, "FunctionLit"));
}
- pos := P.loc;
- P.expect(token.FUNC);
+ pos := P.expect(token.FUNC);
typ := P.parseSignature();
P.expr_lev++;
body := P.parseBlock(token.LBRACE);
P.expr_lev--;
- return &ast.FunctionLit{typ, body, pos};
+ return &ast.FunctionLit{pos, typ, body};
}
-func (P *Parser) parseStringLit() ast.Expr {
+func (P *Parser) parseStringLit(x *ast.BasicLit) *ast.StringLit {
if P.trace {
defer un(trace(P, "StringLit"));
}
- if P.tok != token.STRING {
- panic();
- }
-
list := vector.New(0);
+ if x != nil {
+ list.Push(x);
+ }
+
for P.tok == token.STRING {
- list.Push(&ast.BasicLit{token.STRING, P.val, P.loc});
+ list.Push(&ast.BasicLit{P.pos, token.STRING, P.val});
P.next();
}
@@ -838,21 +848,26 @@ func (P *Parser) parseOperand() ast.Expr {
return P.parseIdent();
case token.INT, token.FLOAT, token.CHAR:
- x := &ast.BasicLit{P.tok, P.val, P.loc};
+ x := &ast.BasicLit{P.pos, P.tok, P.val};
P.next();
return x;
case token.STRING:
- return P.parseStringLit();
+ x := &ast.BasicLit{P.pos, token.STRING, P.val};
+ P.next();
+ if P.tok == token.STRING {
+ return P.parseStringLit(x);
+ }
+ return x;
case token.LPAREN:
- lparen := P.loc;
+ lparen := P.pos;
P.next();
P.expr_lev++;
x := P.parseExpression(1);
P.expr_lev--;
rparen := P.expect(token.RPAREN);
- return &ast.Group{x, lparen, rparen};
+ return &ast.ParenExpr{lparen, x, rparen};
case token.FUNC:
return P.parseFunctionLit();
@@ -862,12 +877,12 @@ func (P *Parser) parseOperand() ast.Expr {
if t != nil {
return t;
} else {
- P.error(P.loc, "operand expected");
+ P.error(P.pos, "operand expected");
P.next(); // make progress
}
}
- return &ast.BadExpr{P.loc};
+ return &ast.BadExpr{P.pos};
}
@@ -876,25 +891,29 @@ func (P *Parser) parseSelectorOrTypeAssertion(x ast.Expr) ast.Expr {
defer un(trace(P, "SelectorOrTypeAssertion"));
}
- period := P.expect(token.PERIOD);
-
+ P.expect(token.PERIOD);
if P.tok == token.IDENT {
// selector
sel := P.parseIdent();
- return &ast.Selector{x, sel, period};
- }
-
- // type assertion
- lparen := P.expect(token.LPAREN);
- var typ ast.Expr;
- if P.tok == token.TYPE {
- typ = &ast.TypeType{P.loc};
- P.next();
+ return &ast.SelectorExpr{x, sel};
+
} else {
- typ = P.parseType();
+ // type assertion
+ P.expect(token.LPAREN);
+ var typ ast.Expr;
+ if P.tok == token.TYPE {
+ // special case for type switch syntax
+ typ = &ast.Ident{P.pos, P.val};
+ P.next();
+ } else {
+ typ = P.parseType();
+ }
+ P.expect(token.RPAREN);
+ return &ast.TypeAssertExpr{x, typ};
}
- rparen := P.expect(token.RPAREN);
- return &ast.TypeAssertion{x, typ, period, lparen, rparen};
+
+ unreachable();
+ return nil;
}
@@ -903,29 +922,28 @@ func (P *Parser) parseIndexOrSlice(x ast.Expr) ast.Expr {
defer un(trace(P, "IndexOrSlice"));
}
- lbrack := P.expect(token.LBRACK);
+ P.expect(token.LBRACK);
P.expr_lev++;
index := P.parseExpression(1);
P.expr_lev--;
if P.tok == token.RBRACK {
// index
- rbrack := P.loc;
P.next();
- return &ast.Index{x, index, lbrack, rbrack};
+ return &ast.IndexExpr{x, index};
}
// slice
- colon := P.expect(token.COLON);
+ P.expect(token.COLON);
P.expr_lev++;
end := P.parseExpression(1);
P.expr_lev--;
- rbrack := P.expect(token.RBRACK);
- return &ast.Slice{x, index, end, lbrack, colon, rbrack};
+ P.expect(token.RBRACK);
+ return &ast.SliceExpr{x, index, end};
}
-func (P *Parser) parseCall(fun ast.Expr) *ast.Call {
+func (P *Parser) parseCall(fun ast.Expr) *ast.CallExpr {
if P.trace {
defer un(trace(P, "Call"));
}
@@ -936,54 +954,7 @@ func (P *Parser) parseCall(fun ast.Expr) *ast.Call {
args = P.parseExpressionList();
}
rparen := P.expect(token.RPAREN);
- return &ast.Call{fun, args, lparen, rparen};
-}
-
-
-func (P *Parser) parseCompositeElements(close int) ast.Expr {
- x := P.parseExpression(0);
- if P.tok == token.COMMA {
- loc := P.loc;
- P.next();
-
- // first element determines mode
- singles := true;
- if t, is_binary := x.(*ast.BinaryExpr); is_binary && t.Op == token.COLON {
- singles = false;
- }
-
- var last *ast.BinaryExpr;
- for P.tok != close && P.tok != token.EOF {
- y := P.parseExpression(0);
-
- if singles {
- if t, is_binary := y.(*ast.BinaryExpr); is_binary && t.Op == token.COLON {
- P.error(t.X.Pos(), "single value expected; found pair");
- }
- } else {
- if t, is_binary := y.(*ast.BinaryExpr); !is_binary || t.Op != token.COLON {
- P.error(y.Pos(), "key:value pair expected; found single value");
- }
- }
-
- if last == nil {
- last = &ast.BinaryExpr{token.COMMA, x, y, loc};
- x = last;
- } else {
- last.Y = &ast.BinaryExpr{token.COMMA, last.Y, y, loc};
- last = last.Y.(*ast.BinaryExpr);
- }
-
- if P.tok == token.COMMA {
- loc = P.loc;
- P.next();
- } else {
- break;
- }
-
- }
- }
- return x;
+ return &ast.CallExpr{fun, lparen, args, rparen};
}
@@ -998,17 +969,17 @@ func (P *Parser) parseElementList() []ast.Expr {
x := P.parseExpression(0);
if list.Len() == 0 {
// first element determines syntax for remaining elements
- if t, is_binary := x.(*ast.BinaryExpr); is_binary && t.Op == token.COLON {
+ if t, is_binary := x.(*ast.BinaryExpr); is_binary && t.Tok == token.COLON {
singles = false;
}
} else {
// not the first element - check syntax
if singles {
- if t, is_binary := x.(*ast.BinaryExpr); is_binary && t.Op == token.COLON {
+ if t, is_binary := x.(*ast.BinaryExpr); is_binary && t.Tok == token.COLON {
P.error(t.X.Pos(), "single value expected; found pair");
}
} else {
- if t, is_binary := x.(*ast.BinaryExpr); !is_binary || t.Op != token.COLON {
+ if t, is_binary := x.(*ast.BinaryExpr); !is_binary || t.Tok != token.COLON {
P.error(x.Pos(), "key:value pair expected; found single value");
}
}
@@ -1044,7 +1015,7 @@ func (P *Parser) parseCompositeLit(typ ast.Expr) ast.Expr {
elts = P.parseElementList();
}
rbrace := P.expect(token.RBRACE);
- return &ast.CompositeLit{typ, elts, lbrace, rbrace};
+ return &ast.CompositeLit{typ, lbrace, elts, rbrace};
}
@@ -1081,11 +1052,18 @@ func (P *Parser) parseUnaryExpr() ast.Expr {
}
switch P.tok {
- case token.ADD, token.SUB, token.MUL, token.NOT, token.XOR, token.ARROW, token.AND:
- loc, tok := P.loc, P.tok;
+ case token.ADD, token.SUB, token.NOT, token.XOR, token.ARROW, token.AND, token.RANGE:
+ pos, tok := P.pos, P.tok;
P.next();
- y := P.parseUnaryExpr();
- return &ast.UnaryExpr{tok, y, loc};
+ x := P.parseUnaryExpr();
+ return &ast.UnaryExpr{pos, tok, x};
+
+ case token.MUL:
+ // unary "*" expression or pointer type
+ pos := P.pos;
+ P.next();
+ x := P.parseUnaryExpr();
+ return &ast.StarExpr{pos, x};
}
return P.parsePrimaryExpr();
@@ -1100,10 +1078,10 @@ func (P *Parser) parseBinaryExpr(prec1 int) ast.Expr {
x := P.parseUnaryExpr();
for prec := token.Precedence(P.tok); prec >= prec1; prec-- {
for token.Precedence(P.tok) == prec {
- loc, tok := P.loc, P.tok;
+ pos, tok := P.pos, P.tok;
P.next();
y := P.parseBinaryExpr(prec + 1);
- x = &ast.BinaryExpr{tok, x, y, loc};
+ x = &ast.BinaryExpr{x, pos, tok, y};
}
}
@@ -1128,13 +1106,7 @@ func (P *Parser) parseExpression(prec int) ast.Expr {
// Statements
-const /* mode */ (
- label_ok = 1 << iota;
- range_ok;
-)
-
-
-func (P *Parser) parseSimpleStat(mode int) ast.Stat {
+func (P *Parser) parseSimpleStat() ast.Stat {
if P.trace {
defer un(trace(P, "SimpleStat"));
}
@@ -1144,15 +1116,13 @@ func (P *Parser) parseSimpleStat(mode int) ast.Stat {
switch P.tok {
case token.COLON:
// labeled statement
- loc := P.loc;
P.expect(token.COLON);
- P.opt_semi = true;
- if mode & label_ok != 0 && len(x) == 1 {
+ if len(x) == 1 {
if label, is_ident := x[0].(*ast.Ident); is_ident {
- return &ast.LabeledStat{loc, label, P.parseStatement()};
+ return &ast.LabeledStat{label, P.parseStatement()};
}
}
- P.error(loc, "illegal label declaration");
+ P.error(x[0].Pos(), "illegal label declaration");
return nil;
case
@@ -1161,34 +1131,29 @@ func (P *Parser) parseSimpleStat(mode int) ast.Stat {
token.REM_ASSIGN, token.AND_ASSIGN, token.OR_ASSIGN,
token.XOR_ASSIGN, token.SHL_ASSIGN, token.SHR_ASSIGN:
// assignment statement or range clause
- loc, tok := P.loc, P.tok;
+ pos, tok := P.pos, P.tok;
P.next();
+ /*
if mode & range_ok != 0 && P.tok == token.RANGE {
// range clause
P.next();
if len(x) != 1 && len(x) != 2 {
- P.error(loc, "expected 1 or 2 expressions on lhs of range clause");
+ P.error(x[0].Pos(), "expected 1 or 2 expressions on lhs of range clause");
}
if tok != token.DEFINE && tok != token.ASSIGN {
- P.error(loc, "expected '=' or ':=', found '" + token.TokenString(tok) + "'");
+ P.error(pos, "expected '=' or ':=', found '" + token.TokenString(tok) + "'");
}
y := P.parseExpression(1);
- return &ast.RangeClause{loc, tok, x, y};
+ return &ast.RangeClause{x, pos, tok, y};
} else {
- // assignment statement
- y := P.parseExpressionList();
- xl, yl := len(x), len(y);
- if xl > 1 && yl > 1 && xl != yl {
- P.error(loc, "arity of lhs doesn't match rhs"); // TODO use better loc for error
- }
- if xl == 1 && yl == 1 {
- // common case - use smaller node
- return &ast.AssignmentStat{loc, tok, x[0], y[0]};
- } else {
- // general case
- return &ast.TupleAssignStat{loc, tok, x, y};
- }
+ */
+ // assignment statement
+ y := P.parseExpressionList();
+ xl, yl := len(x), len(y);
+ if xl > 1 && yl > 1 && xl != yl {
+ P.error(x[0].Pos(), "arity of lhs doesn't match rhs"); // TODO use better loc for error
}
+ return &ast.AssignmentStat{x, pos, tok, y};
default:
if len(x) > 1 {
@@ -1196,13 +1161,12 @@ func (P *Parser) parseSimpleStat(mode int) ast.Stat {
}
if P.tok == token.INC || P.tok == token.DEC {
- s := &ast.IncDecStat{P.loc, P.tok, x[0]};
+ s := &ast.IncDecStat{x[0], P.tok};
P.next(); // consume "++" or "--"
return s;
}
- // TODO change ILLEGAL -> NONE
- return &ast.ExpressionStat{x[0].Pos(), token.ILLEGAL, x[0]};
+ return &ast.ExprStat{x[0]};
}
unreachable();
@@ -1210,14 +1174,25 @@ func (P *Parser) parseSimpleStat(mode int) ast.Stat {
}
-func (P *Parser) parseInvocationStat(keyword int) *ast.ExpressionStat {
+func (P *Parser) parseGoStat() *ast.GoStat {
if P.trace {
- defer un(trace(P, "InvocationStat"));
+ defer un(trace(P, "GoStat"));
}
- loc := P.loc;
- P.expect(keyword);
- return &ast.ExpressionStat{loc, keyword, P.parseExpression(1)};
+ pos := P.expect(token.GO);
+ call := P.parseExpression(1);
+ return &ast.GoStat{pos, call};
+}
+
+
+func (P *Parser) parseDeferStat() *ast.DeferStat {
+ if P.trace {
+ defer un(trace(P, "DeferStat"));
+ }
+
+ pos := P.expect(token.DEFER);
+ call := P.parseExpression(1);
+ return &ast.DeferStat{pos, call};
}
@@ -1226,7 +1201,7 @@ func (P *Parser) parseReturnStat() *ast.ReturnStat {
defer un(trace(P, "ReturnStat"));
}
- loc := P.loc;
+ loc := P.pos;
P.expect(token.RETURN);
var x []ast.Expr;
if P.tok != token.SEMICOLON && P.tok != token.RBRACE {
@@ -1242,7 +1217,7 @@ func (P *Parser) parseControlFlowStat(tok int) *ast.ControlFlowStat {
defer un(trace(P, "ControlFlowStat"));
}
- s := &ast.ControlFlowStat{P.loc, tok, nil};
+ s := &ast.ControlFlowStat{P.pos, tok, nil};
P.expect(tok);
if tok != token.FALLTHROUGH && P.tok == token.IDENT {
s.Label = P.parseIdent();
@@ -1252,7 +1227,33 @@ func (P *Parser) parseControlFlowStat(tok int) *ast.ControlFlowStat {
}
-func (P *Parser) parseControlClause(isForStat bool) (init ast.Stat, expr ast.Expr, post ast.Stat) {
+/*
+func (P *Parser) asIdent(x ast.Expr) *ast.Ident {
+ if name, ok := x.(*ast.Ident); ok {
+ return name;
+ }
+ P.error(x.Pos(), "identifier expected");
+ return &ast.Ident{x.Pos(), [...]byte{'B', 'A', 'D'}};
+}
+
+
+func (P *Parser) isTypeSwitch(init ast.Stat) (lhs *ast.Ident, rhs ast.Expr) {
+ if assign, ok := init.(*ast.AssignmentStat); ok {
+ if guard, ok := assign.Rhs.(*ast.TypeAssertion); ok {
+ if tmp, ok := guard.Typ.(*ast.TypeType); ok {
+ // we appear to have a type switch
+ // TODO various error checks
+ return P.asIdent(assign.Lhs), guard.X;
+ }
+ }
+ }
+ return nil, nil;
+}
+*/
+
+
+
+func (P *Parser) parseControlClause(isForStat bool) (s1, s2, s3 ast.Stat) {
if P.trace {
defer un(trace(P, "ControlClause"));
}
@@ -1262,39 +1263,49 @@ func (P *Parser) parseControlClause(isForStat bool) (init ast.Stat, expr ast.Exp
P.expr_lev = -1;
if P.tok != token.SEMICOLON {
- mode := 0;
- if isForStat {
- mode = range_ok;
- }
- init = P.parseSimpleStat(mode);
+ s1 = P.parseSimpleStat();
}
- if dummy, is_range := init.(*ast.RangeClause); !is_range {
- if P.tok == token.SEMICOLON {
- P.next();
- if P.tok != token.SEMICOLON && P.tok != token.LBRACE {
- expr = P.parseExpression(1);
- }
- if isForStat {
- P.expect(token.SEMICOLON);
- if P.tok != token.LBRACE {
- post = P.parseSimpleStat(0);
- }
- }
- } else {
- if init != nil { // guard in case of errors
- if s, is_expr_stat := init.(*ast.ExpressionStat); is_expr_stat {
- expr, init = s.Expr, nil;
- } else {
- P.error(noloc, "illegal control clause");
- }
+ if P.tok == token.SEMICOLON {
+ P.next();
+ if P.tok != token.LBRACE && P.tok != token.SEMICOLON {
+ s2 = P.parseSimpleStat();
+ }
+ if isForStat {
+ // for statements have a 3rd section
+ P.expect(token.SEMICOLON);
+ if P.tok != token.LBRACE {
+ s3 = P.parseSimpleStat();
}
}
+ } else {
+ s1, s2 = nil, s1;
}
-
+
P.expr_lev = prev_lev;
}
- return init, expr, post;
+ return s1, s2, s3;
+}
+
+
+func (P *Parser) isExpr(s ast.Stat) bool {
+ if s == nil {
+ return true;
+ }
+ dummy, is_expr := s.(*ast.ExprStat);
+ return is_expr;
+}
+
+
+func (P *Parser) asExpr(s ast.Stat) ast.Expr {
+ if s == nil {
+ return nil;
+ }
+ if es, is_expr := s.(*ast.ExprStat); is_expr {
+ return es.X;
+ }
+ P.error(s.Pos(), "condition expected; found simple statement");
+ return &ast.BadExpr{s.Pos()};
}
@@ -1303,9 +1314,8 @@ func (P *Parser) parseIfStat() *ast.IfStat {
defer un(trace(P, "IfStat"));
}
- loc := P.loc;
- P.expect(token.IF);
- init, cond, dummy := P.parseControlClause(false);
+ pos := P.expect(token.IF);
+ s1, s2, dummy := P.parseControlClause(false);
body := P.parseBlock(token.LBRACE);
var else_ ast.Stat;
if P.tok == token.ELSE {
@@ -1313,92 +1323,84 @@ func (P *Parser) parseIfStat() *ast.IfStat {
else_ = P.parseStatement();
}
- return &ast.IfStat{loc, init, cond, body, else_};
+ return &ast.IfStat{pos, s1, P.asExpr(s2), body, else_};
}
-func (P *Parser) parseForStat() *ast.ForStat {
+func (P *Parser) parseCaseClause() *ast.CaseClause {
if P.trace {
- defer un(trace(P, "ForStat"));
+ defer un(trace(P, "CaseClause"));
}
- loc := P.loc;
- P.expect(token.FOR);
- init, cond, post := P.parseControlClause(true);
- body := P.parseBlock(token.LBRACE);
-
- return &ast.ForStat{loc, init, cond, post, body};
-}
-
-
-func (P *Parser) asIdent(x ast.Expr) *ast.Ident {
- if name, ok := x.(*ast.Ident); ok {
- return name;
+ // SwitchCase
+ loc := P.pos;
+ var x []ast.Expr;
+ if P.tok == token.CASE {
+ P.next();
+ x = P.parseExpressionList();
+ } else {
+ P.expect(token.DEFAULT);
}
- P.error(x.Pos(), "identifier expected");
- return &ast.Ident{"BAD", noloc};
-}
-
-func (P *Parser) isTypeSwitch(init ast.Stat) (lhs *ast.Ident, rhs ast.Expr) {
- if assign, ok := init.(*ast.AssignmentStat); ok {
- if guard, ok := assign.Rhs.(*ast.TypeAssertion); ok {
- if tmp, ok := guard.Typ.(*ast.TypeType); ok {
- // we appear to have a type switch
- // TODO various error checks
- return P.asIdent(assign.Lhs), guard.X;
- }
- }
- }
- return nil, nil;
+ return &ast.CaseClause{loc, x, P.parseBlock(token.COLON)};
}
-func (P *Parser) parseCaseClause() *ast.CaseClause {
+func (P *Parser) parseTypeCaseClause() *ast.TypeCaseClause {
if P.trace {
defer un(trace(P, "CaseClause"));
}
- // SwitchCase
- loc := P.loc;
- var x []ast.Expr;
+ // TypeSwitchCase
+ pos := P.pos;
+ var typ ast.Expr;
if P.tok == token.CASE {
P.next();
- x = P.parseExpressionList();
+ typ = P.parseType();
} else {
P.expect(token.DEFAULT);
}
- return &ast.CaseClause{loc, x, P.parseBlock(token.COLON)};
+ return &ast.TypeCaseClause{pos, typ, P.parseBlock(token.COLON)};
}
-func (P *Parser) parseSwitchStat() *ast.SwitchStat {
+func (P *Parser) parseSwitchStat() ast.Stat {
if P.trace {
defer un(trace(P, "SwitchStat"));
}
- loc := P.loc;
- P.expect(token.SWITCH);
- init, tag, post := P.parseControlClause(false);
- body := ast.NewBlock(P.loc, token.LBRACE);
- P.expect(token.LBRACE);
- for P.tok != token.RBRACE && P.tok != token.EOF {
- body.List.Push(P.parseCaseClause());
- }
- body.End = P.loc;
- P.expect(token.RBRACE);
- P.opt_semi = true;
+ pos := P.expect(token.SWITCH);
+ s1, s2, dummy := P.parseControlClause(false);
- if lhs, rhs := P.isTypeSwitch(init); lhs != nil {
- if tag != nil {
- P.error(loc, "illegal type switch clause");
+ if P.isExpr(s2) {
+ // expression switch
+ lbrace := P.expect(token.LBRACE);
+ cases := vector.New(0);
+ for P.tok == token.CASE || P.tok == token.DEFAULT {
+ cases.Push(P.parseCaseClause());
}
- // TODO fix location
- init = &ast.TypeSwitchClause{loc, lhs, rhs};
+ rbrace := P.expect(token.RBRACE);
+ P.opt_semi = true;
+ body := &ast.Block{lbrace, token.LBRACE, asStatList(cases), rbrace};
+ return &ast.SwitchStat{pos, s1, P.asExpr(s2), body};
+
+ } else {
+ // type switch
+ // TODO do all the checks!
+ lbrace := P.expect(token.LBRACE);
+ cases := vector.New(0);
+ for P.tok == token.CASE || P.tok == token.DEFAULT {
+ cases.Push(P.parseTypeCaseClause());
+ }
+ rbrace := P.expect(token.RBRACE);
+ P.opt_semi = true;
+ body := &ast.Block{lbrace, token.LBRACE, asStatList(cases), rbrace};
+ return &ast.TypeSwitchStat{pos, s1, s2, body};
}
- return &ast.SwitchStat{loc, init, tag, body};
+ unreachable();
+ return nil;
}
@@ -1408,7 +1410,7 @@ func (P *Parser) parseCommClause() *ast.CommClause {
}
// CommCase
- loc := P.loc;
+ loc := P.pos;
var tok int;
var lhs, rhs ast.Expr;
if P.tok == token.CASE {
@@ -1445,18 +1447,40 @@ func (P *Parser) parseSelectStat() *ast.SelectStat {
defer un(trace(P, "SelectStat"));
}
- loc := P.loc;
- P.expect(token.SELECT);
- body := ast.NewBlock(P.loc, token.LBRACE);
- P.expect(token.LBRACE);
- for P.tok != token.RBRACE && P.tok != token.EOF {
- body.List.Push(P.parseCommClause());
+ pos := P.expect(token.SELECT);
+ lbrace := P.expect(token.LBRACE);
+ cases := vector.New(0);
+ for P.tok == token.CASE || P.tok == token.DEFAULT {
+ cases.Push(P.parseCommClause());
}
- body.End = P.loc;
- P.expect(token.RBRACE);
+ rbrace := P.expect(token.RBRACE);
P.opt_semi = true;
+ body := &ast.Block{lbrace, token.LBRACE, asStatList(cases), rbrace};
- return &ast.SelectStat{loc, body};
+ return &ast.SelectStat{pos, body};
+}
+
+
+func (P *Parser) parseForStat() ast.Stat {
+ if P.trace {
+ defer un(trace(P, "ForStat"));
+ }
+
+ pos := P.expect(token.FOR);
+ s1, s2, s3 := P.parseControlClause(true);
+ body := P.parseBlock(token.LBRACE);
+
+ if as, is_as := s2.(*ast.AssignmentStat); is_as {
+ // probably a for statement with a range clause
+ // TODO do all the checks!
+ return &ast.RangeStat{pos, s2, body};
+ } else {
+ // regular for statement
+ return &ast.ForStat{pos, s1, P.asExpr(s2), s3, body};
+ }
+
+ unreachable();
+ return nil;
}
@@ -1467,15 +1491,17 @@ func (P *Parser) parseStatement() ast.Stat {
switch P.tok {
case token.CONST, token.TYPE, token.VAR:
- return &ast.DeclarationStat{P.parseDeclaration()};
+ return &ast.DeclStat{P.parseDeclaration()};
case
// tokens that may start a top-level expression
token.IDENT, token.INT, token.FLOAT, token.CHAR, token.STRING, token.FUNC, token.LPAREN, // operand
token.LBRACK, token.STRUCT, // composite type
token.MUL, token.AND, token.ARROW: // unary operators
- return P.parseSimpleStat(label_ok);
- case token.GO, token.DEFER:
- return P.parseInvocationStat(P.tok);
+ return P.parseSimpleStat();
+ case token.GO:
+ return P.parseGoStat();
+ case token.DEFER:
+ return P.parseDeferStat();
case token.RETURN:
return P.parseReturnStat();
case token.BREAK, token.CONTINUE, token.GOTO, token.FALLTHROUGH:
@@ -1492,43 +1518,43 @@ func (P *Parser) parseStatement() ast.Stat {
return P.parseSelectStat();
case token.SEMICOLON, token.RBRACE:
// don't consume the ";", it is the separator following the empty statement
- return &ast.EmptyStat{P.loc};
+ return &ast.EmptyStat{P.pos};
}
// no statement found
- P.error(P.loc, "statement expected");
- return &ast.BadStat{P.loc};
+ P.error(P.pos, "statement expected");
+ return &ast.BadStat{P.pos};
}
// ----------------------------------------------------------------------------
// Declarations
-func (P *Parser) parseImportSpec(loc Position) *ast.ImportDecl {
+func (P *Parser) parseImportSpec(pos Position, doc ast.Comments) *ast.ImportDecl {
if P.trace {
defer un(trace(P, "ImportSpec"));
}
var ident *ast.Ident;
if P.tok == token.PERIOD {
- P.error(P.loc, `"import ." not yet handled properly`);
+ P.error(P.pos, `"import ." not yet handled properly`);
P.next();
} else if P.tok == token.IDENT {
ident = P.parseIdent();
}
- var path ast.Expr;
+ var path *ast.StringLit;
if P.tok == token.STRING {
- path = P.parseStringLit();
+ path = P.parseStringLit(nil);
} else {
P.expect(token.STRING); // use expect() error handling
}
- return &ast.ImportDecl{loc, ident, path};
+ return &ast.ImportDecl{doc, pos, ident, path};
}
-func (P *Parser) parseConstSpec(loc Position, comment ast.CommentGroup) *ast.ConstDecl {
+func (P *Parser) parseConstSpec(pos Position, doc ast.Comments) *ast.ConstDecl {
if P.trace {
defer un(trace(P, "ConstSpec"));
}
@@ -1541,11 +1567,11 @@ func (P *Parser) parseConstSpec(loc Position, comment ast.CommentGroup) *ast.Con
values = P.parseExpressionList();
}
- return &ast.ConstDecl{loc, names, typ, values, comment};
+ return &ast.ConstDecl{doc, pos, names, typ, values};
}
-func (P *Parser) parseTypeSpec(loc Position, comment ast.CommentGroup) *ast.TypeDecl {
+func (P *Parser) parseTypeSpec(pos Position, doc ast.Comments) *ast.TypeDecl {
if P.trace {
defer un(trace(P, "TypeSpec"));
}
@@ -1553,11 +1579,11 @@ func (P *Parser) parseTypeSpec(loc Position, comment ast.CommentGroup) *ast.Type
ident := P.parseIdent();
typ := P.parseType();
- return &ast.TypeDecl{loc, ident, typ, comment};
+ return &ast.TypeDecl{doc, pos, ident, typ};
}
-func (P *Parser) parseVarSpec(loc Position, comment ast.CommentGroup) *ast.VarDecl {
+func (P *Parser) parseVarSpec(pos Position, doc ast.Comments) *ast.VarDecl {
if P.trace {
defer un(trace(P, "VarSpec"));
}
@@ -1570,16 +1596,16 @@ func (P *Parser) parseVarSpec(loc Position, comment ast.CommentGroup) *ast.VarDe
values = P.parseExpressionList();
}
- return &ast.VarDecl{loc, names, typ, values, comment};
+ return &ast.VarDecl{doc, pos, names, typ, values};
}
-func (P *Parser) parseSpec(loc Position, comment ast.CommentGroup, keyword int) ast.Decl {
+func (P *Parser) parseSpec(pos Position, doc ast.Comments, keyword int) ast.Decl {
switch keyword {
- case token.IMPORT: return P.parseImportSpec(loc);
- case token.CONST: return P.parseConstSpec(loc, comment);
- case token.TYPE: return P.parseTypeSpec(loc, comment);
- case token.VAR: return P.parseVarSpec(loc, comment);
+ case token.IMPORT: return P.parseImportSpec(pos, doc);
+ case token.CONST: return P.parseConstSpec(pos, doc);
+ case token.TYPE: return P.parseTypeSpec(pos, doc);
+ case token.VAR: return P.parseVarSpec(pos, doc);
}
unreachable();
@@ -1592,22 +1618,21 @@ func (P *Parser) parseDecl(keyword int) ast.Decl {
defer un(trace(P, "Decl"));
}
- comment := P.getLastComment();
- loc := P.loc;
- P.expect(keyword);
+ doc := P.getDoc();
+ pos := P.expect(keyword);
if P.tok == token.LPAREN {
+ lparen := P.pos;
P.next();
list := vector.New(0);
for P.tok != token.RPAREN && P.tok != token.EOF {
- list.Push(P.parseSpec(noloc, nil, keyword));
+ list.Push(P.parseSpec(nopos, nil, keyword));
if P.tok == token.SEMICOLON {
P.next();
} else {
break;
}
}
- end := P.loc;
- P.expect(token.RPAREN);
+ rparen := P.expect(token.RPAREN);
P.opt_semi = true;
// convert vector
@@ -1616,10 +1641,10 @@ func (P *Parser) parseDecl(keyword int) ast.Decl {
decls[i] = list.At(i).(ast.Decl);
}
- return &ast.DeclList{loc, keyword, decls, end};
+ return &ast.DeclList{doc, pos, keyword, lparen, decls, rparen};
}
- return P.parseSpec(loc, comment, keyword);
+ return P.parseSpec(pos, doc, keyword);
}
@@ -1637,13 +1662,12 @@ func (P *Parser) parseFunctionDecl() *ast.FuncDecl {
defer un(trace(P, "FunctionDecl"));
}
- comment := P.getLastComment();
- loc := P.loc;
- P.expect(token.FUNC);
+ doc := P.getDoc();
+ pos := P.expect(token.FUNC);
var recv *ast.Field;
if P.tok == token.LPAREN {
- loc := P.loc;
+ loc := P.pos;
tmp := P.parseParameters(true);
if len(tmp) == 1 {
recv = tmp[0];
@@ -1660,7 +1684,7 @@ func (P *Parser) parseFunctionDecl() *ast.FuncDecl {
body = P.parseBlock(token.LBRACE);
}
- return &ast.FuncDecl{loc, recv, ident, sig, body, comment};
+ return &ast.FuncDecl{doc, pos, recv, ident, sig, body};
}
@@ -1676,7 +1700,7 @@ func (P *Parser) parseDeclaration() ast.Decl {
return P.parseFunctionDecl();
}
- loc := P.loc;
+ loc := P.pos;
P.error(loc, "declaration expected");
P.next(); // make progress
return &ast.BadDecl{loc};
@@ -1686,16 +1710,6 @@ func (P *Parser) parseDeclaration() ast.Decl {
// ----------------------------------------------------------------------------
// Program
-func (P *Parser) getComments() []ast.CommentGroup {
- // convert comments vector
- list := make([]ast.CommentGroup, P.comments.Len());
- for i := 0; i < P.comments.Len(); i++ {
- list[i] = P.comments.At(i).(ast.CommentGroup);
- }
- return list;
-}
-
-
// The Parse function is parametrized with one of the following
// constants. They control how much of the source text is parsed.
//
@@ -1710,19 +1724,18 @@ const (
//
// foo bar
//
-func (P *Parser) Parse(mode int) *ast.Program {
+func (P *Parser) Parse(mode int) *ast.Package {
if P.trace {
defer un(trace(P, "Program"));
}
// package clause
- comment := P.getLastComment();
- loc := P.loc;
- P.expect(token.PACKAGE);
+ comment := P.getDoc();
+ pos := P.expect(token.PACKAGE);
name := P.parseIdent();
if P.tok == token.SEMICOLON {
// common error
- P.error(P.loc, "extra semicolon");
+ P.error(P.pos, "extra semicolon");
P.next();
}
@@ -1748,12 +1761,21 @@ func (P *Parser) Parse(mode int) *ast.Program {
}
}
- // convert list
+ // convert declaration list
decls = make([]ast.Decl, list.Len());
for i := 0; i < list.Len(); i++ {
decls[i] = list.At(i).(ast.Decl);
}
}
- return &ast.Program{loc, name, decls, comment, P.getComments()};
+ // convert comments list
+ comments := make([]*ast.Comment, P.comments.Len());
+ for i := 0; i < P.comments.Len(); i++ {
+ c := P.comments.At(i);
+ if c != nil {
+ comments[i] = c.(*ast.Comment);
+ }
+ }
+
+ return &ast.Package{comment, pos, name, decls, comments};
}