Commit 75a5d6cd authored by Robert Griesemer's avatar Robert Griesemer

Significant parser cleanup:

- commented public interface
- much better and very precise error messages
- much better tracing output
- many more checks (still permits more than just syntactically legal
  programs, but much more is checked that can be checked w/o semantic information)
- updated with respect to updated AST
- general cleanup throughout

Parser almost ready for move into lib/go.

R=r
OCL=26853
CL=26855
parent 7cba8e6f
...@@ -97,11 +97,11 @@ func Compile(src_file string, flags *Flags) (*ast.Package, ErrorList) { ...@@ -97,11 +97,11 @@ func Compile(src_file string, flags *Flags) (*ast.Package, ErrorList) {
var scanner scanner.Scanner; var scanner scanner.Scanner;
scanner.Init(src, &err, true); scanner.Init(src, &err, true);
pflags := uint(0); mode := uint(0);
if flags.Verbose { if flags.Verbose {
pflags |= parser.Trace; mode |= parser.Trace;
} }
prog, nerrs := parser.Parse(&scanner, &err, parser.ParseEntirePackage, pflags); prog, nerrs := parser.Parse(&scanner, &err, mode);
if err.errors.Len() == 0 { if err.errors.Len() == 0 {
TypeChecker.CheckProgram(&err, prog); TypeChecker.CheckProgram(&err, prog);
......
...@@ -21,8 +21,7 @@ import ( ...@@ -21,8 +21,7 @@ import (
// The parser calls Scan() repeatedly until token.EOF is returned. // The parser calls Scan() repeatedly until token.EOF is returned.
// Scan must return the current token position pos, the token value // Scan must return the current token position pos, the token value
// tok, and the corresponding token literal string lit; lit can be // tok, and the corresponding token literal string lit; lit can be
// undefined/nil unless the token is a literal (i.e., tok.IsLiteral() // undefined/nil unless the token is a literal (tok.IsLiteral() == true).
// is true).
// //
type Scanner interface { type Scanner interface {
Scan() (pos token.Position, tok token.Token, lit []byte); Scan() (pos token.Position, tok token.Token, lit []byte);
...@@ -39,14 +38,6 @@ type ErrorHandler interface { ...@@ -39,14 +38,6 @@ type ErrorHandler interface {
} }
// The following flags control optional parser functionality. A set of
// flags (or 0) must be provided as a parameter to the Parse function.
//
const (
Trace = 1 << iota; // print a trace of parsed productions
)
type interval struct { type interval struct {
beg, end int; beg, end int;
} }
...@@ -59,8 +50,9 @@ type parser struct { ...@@ -59,8 +50,9 @@ type parser struct {
errorCount int; errorCount int;
// Tracing/debugging // Tracing/debugging
trace bool; mode uint; // parsing mode
indent uint; trace bool; // == (mode & Trace != 0)
indent uint; // indentation used for tracing output
// Comments // Comments
comments vector.Vector; // list of collected, unassociated comments comments vector.Vector; // list of collected, unassociated comments
...@@ -77,37 +69,31 @@ type parser struct { ...@@ -77,37 +69,31 @@ type parser struct {
}; };
// When we don't have a position use nopos. // noPos is used when there is no corresponding source position for a token
// TODO make sure we always have a position. var noPos token.Position;
var nopos token.Position;
// ----------------------------------------------------------------------------
// Helper functions
func unreachable() {
panic("unreachable");
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Parsing support // Parsing support
func (p *parser) printIndent() { func (p *parser) printTrace(a ...) {
i := p.indent; const dots =
// reduce printing time by a factor of 2 or more ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . "
for ; i > 10; i -= 10 { ". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ";
fmt.Printf(". . . . . . . . . . "); const n = uint(len(dots));
}
for ; i > 0; i-- { fmt.Printf("%5d:%3d: ", p.pos.Line, p.pos.Column);
fmt.Printf(". "); i := 2*p.indent;
for ; i > n; i -= n {
fmt.Print(dots[0 : i%n]);
} }
fmt.Print(dots[0 : i]);
fmt.Println(a);
} }
func trace(p *parser, msg string) *parser { func trace(p *parser, msg string) *parser {
p.printIndent(); p.printTrace(msg, "(");
fmt.Printf("%s (\n", msg);
p.indent++; p.indent++;
return p; return p;
} }
...@@ -115,35 +101,35 @@ func trace(p *parser, msg string) *parser { ...@@ -115,35 +101,35 @@ func trace(p *parser, msg string) *parser {
func un/*trace*/(p *parser) { func un/*trace*/(p *parser) {
p.indent--; p.indent--;
p.printIndent(); p.printTrace(")");
fmt.Printf(")\n");
} }
func (p *parser) next0() { func (p *parser) next0() {
p.pos, p.tok, p.lit = p.scanner.Scan(); // Because of one-token look-ahead, print the previous token
p.opt_semi = false; // when tracing as it provides a more readable output. The
// very first token (p.pos.Line == 0) is not initialized (it
if p.trace { // is token.ILLEGAL), so don't print it .
p.printIndent(); if p.trace && p.pos.Line > 0 {
switch p.tok { s := p.tok.String();
case token.IDENT, token.INT, token.FLOAT, token.CHAR, token.STRING: switch {
fmt.Printf("%d:%d: %s = %s\n", p.pos.Line, p.pos.Column, p.tok.String(), p.lit); case p.tok.IsLiteral():
case token.LPAREN: p.printTrace(s, string(p.lit));
// don't print '(' - screws up selection in terminal window case p.tok.IsOperator(), p.tok.IsKeyword():
fmt.Printf("%d:%d: LPAREN\n", p.pos.Line, p.pos.Column); p.printTrace("\"" + s + "\"");
case token.RPAREN:
// don't print ')' - screws up selection in terminal window
fmt.Printf("%d:%d: RPAREN\n", p.pos.Line, p.pos.Column);
default: default:
fmt.Printf("%d:%d: %s\n", p.pos.Line, p.pos.Column, p.tok.String()); p.printTrace(s);
} }
} }
p.pos, p.tok, p.lit = p.scanner.Scan();
p.opt_semi = false;
} }
// Collect a comment in the parser's comment list and return the line // Collect a comment in the parser's comment list and return the line
// on which the comment ends. // on which the comment ends.
//
func (p *parser) collectComment() int { func (p *parser) collectComment() int {
// For /*-style comments, the comment may end on a different line. // For /*-style comments, the comment may end on a different line.
// Scan the comment for '\n' chars and adjust the end line accordingly. // Scan the comment for '\n' chars and adjust the end line accordingly.
...@@ -176,6 +162,30 @@ func (p *parser) getComments() interval { ...@@ -176,6 +162,30 @@ func (p *parser) getComments() interval {
} }
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);
}
// remove comments from the general list
p.comments.Cut(doc.beg, doc.end);
return c;
}
func (p *parser) next() { func (p *parser) next() {
p.next0(); p.next0();
p.last_doc = interval{0, 0}; p.last_doc = interval{0, 0};
...@@ -193,41 +203,27 @@ func (p *parser) error(pos token.Position, msg string) { ...@@ -193,41 +203,27 @@ func (p *parser) error(pos token.Position, msg string) {
} }
func (p *parser) expect(tok token.Token) token.Position { func (p *parser) error_expected(pos token.Position, msg string) {
if p.tok != tok { msg = "expected " + msg;
msg := "expected '" + tok.String() + "', found '" + p.tok.String() + "'"; if pos.Offset == p.pos.Offset {
// the error happened at the current position;
// make the error message more specific
msg += ", found '" + p.tok.String() + "'";
if p.tok.IsLiteral() { if p.tok.IsLiteral() {
msg += " " + string(p.lit); msg += " " + string(p.lit);
} }
p.error(p.pos, msg);
} }
pos := p.pos; p.error(pos, msg);
p.next(); // make progress in any case
return pos;
} }
func (p *parser) getDoc() ast.Comments { func (p *parser) expect(tok token.Token) token.Position {
doc := p.last_doc; pos := p.pos;
n := doc.end - doc.beg; if p.tok != tok {
p.error_expected(pos, "'" + tok.String() + "'");
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);
} }
p.next(); // make progress in any case
// remove comments from the general list return pos;
p.comments.Cut(doc.beg, doc.end);
return c;
} }
...@@ -235,23 +231,19 @@ func (p *parser) getDoc() ast.Comments { ...@@ -235,23 +231,19 @@ func (p *parser) getDoc() ast.Comments {
// Common productions // Common productions
func (p *parser) tryType() ast.Expr; func (p *parser) tryType() ast.Expr;
func (p *parser) parseExpression(prec int) ast.Expr; func (p *parser) parseStringList(x *ast.StringLit) []*ast.StringLit
func (p *parser) parseExpression() ast.Expr;
func (p *parser) parseStatement() ast.Stmt; func (p *parser) parseStatement() ast.Stmt;
func (p *parser) parseDeclaration() ast.Decl; func (p *parser) parseDeclaration() ast.Decl;
func (p *parser) parseIdent() *ast.Ident { func (p *parser) parseIdent() *ast.Ident {
if p.trace {
defer un(trace(p, "Ident"));
}
if p.tok == token.IDENT { if p.tok == token.IDENT {
x := &ast.Ident{p.pos, p.lit}; x := &ast.Ident{p.pos, p.lit};
p.next(); p.next();
return x; return x;
} }
p.expect(token.IDENT); // use expect() error handling p.expect(token.IDENT); // use expect() error handling
return &ast.Ident{p.pos, [0]byte{}}; return &ast.Ident{p.pos, [0]byte{}};
} }
...@@ -287,10 +279,10 @@ func (p *parser) parseExpressionList() []ast.Expr { ...@@ -287,10 +279,10 @@ func (p *parser) parseExpressionList() []ast.Expr {
} }
list := vector.New(0); list := vector.New(0);
list.Push(p.parseExpression(1)); list.Push(p.parseExpression());
for p.tok == token.COMMA { for p.tok == token.COMMA {
p.next(); p.next();
list.Push(p.parseExpression(1)); list.Push(p.parseExpression());
} }
// convert list // convert list
...@@ -312,9 +304,10 @@ func (p *parser) parseType() ast.Expr { ...@@ -312,9 +304,10 @@ func (p *parser) parseType() ast.Expr {
} }
typ := p.tryType(); typ := p.tryType();
if typ == nil { if typ == nil {
p.error(p.pos, "type expected"); p.error_expected(p.pos, "type");
typ = &ast.BadExpr{p.pos}; return &ast.BadExpr{p.pos};
} }
return typ; return typ;
...@@ -327,7 +320,8 @@ func (p *parser) parseQualifiedIdent() ast.Expr { ...@@ -327,7 +320,8 @@ func (p *parser) parseQualifiedIdent() ast.Expr {
} }
var x ast.Expr = p.parseIdent(); var x ast.Expr = p.parseIdent();
for p.tok == token.PERIOD { if p.tok == token.PERIOD {
// first identifier is a package identifier
p.next(); p.next();
sel := p.parseIdent(); sel := p.parseIdent();
x = &ast.SelectorExpr{x, sel}; x = &ast.SelectorExpr{x, sel};
...@@ -345,67 +339,164 @@ func (p *parser) parseTypeName() ast.Expr { ...@@ -345,67 +339,164 @@ func (p *parser) parseTypeName() ast.Expr {
} }
func (p *parser) parseArrayType() *ast.ArrayType { func (p *parser) parseArrayOrSliceType(ellipsis_ok bool) ast.Expr {
if p.trace { if p.trace {
defer un(trace(p, "ArrayType")); defer un(trace(p, "ArrayOrSliceType"));
} }
lbrack := p.expect(token.LBRACK); lbrack := p.expect(token.LBRACK);
var len ast.Expr; var len ast.Expr;
if p.tok == token.ELLIPSIS { if ellipsis_ok && p.tok == token.ELLIPSIS {
len = &ast.Ellipsis{p.pos}; len = &ast.Ellipsis{p.pos};
p.next(); p.next();
} else if p.tok != token.RBRACK { } else if p.tok != token.RBRACK {
len = p.parseExpression(1); len = p.parseExpression();
} }
p.expect(token.RBRACK); p.expect(token.RBRACK);
elt := p.parseType(); elt := p.parseType();
return &ast.ArrayType{lbrack, len, elt}; if len != nil {
return &ast.ArrayType{lbrack, len, elt};
}
return &ast.SliceType{lbrack, elt};
} }
func (p *parser) parseChannelType() *ast.ChannelType { func (p *parser) makeIdentList(list *vector.Vector) []*ast.Ident {
idents := make([]*ast.Ident, list.Len());
for i := 0; i < list.Len(); i++ {
ident, is_ident := list.At(i).(*ast.Ident);
if !is_ident {
pos := list.At(i).(ast.Expr).Pos();
p.error_expected(pos, "identifier");
idents[i] = &ast.Ident{pos, []byte{}};
}
idents[i] = ident;
}
return idents;
}
func (p *parser) parseFieldDecl() *ast.Field {
if p.trace { if p.trace {
defer un(trace(p, "ChannelType")); defer un(trace(p, "FieldDecl"));
} }
pos := p.pos; doc := p.getDoc();
dir := ast.SEND | ast.RECV;
if p.tok == token.CHAN { // a list of identifiers looks like a list of type names
p.next(); list := vector.New(0);
if p.tok == token.ARROW { for {
// TODO do not allow ()'s here
list.Push(p.parseType());
if p.tok == token.COMMA {
p.next(); p.next();
dir = ast.SEND; } else {
break;
} }
}
// if we had a list of identifiers, it must be followed by a type
typ := p.tryType();
// optional tag
var tag []*ast.StringLit;
if p.tok == token.STRING {
tag = p.parseStringList(nil);
}
// analyze case
var idents []*ast.Ident;
if typ != nil {
// IdentifierList Type
idents = p.makeIdentList(list);
} else { } else {
p.expect(token.ARROW); // Type (anonymous field)
p.expect(token.CHAN); if list.Len() == 1 {
dir = ast.RECV; // TODO check that this looks like a type
typ = list.At(0).(ast.Expr);
} else {
p.error_expected(p.pos, "anonymous field");
typ = &ast.BadExpr{p.pos};
}
} }
value := p.parseType();
return &ast.ChannelType{pos, dir, value}; return &ast.Field{doc, idents, typ, tag};
} }
func (p *parser) tryParameterType() ast.Expr { func (p *parser) parseStructType() *ast.StructType {
if p.tok == token.ELLIPSIS { if p.trace {
x := &ast.Ellipsis{p.pos}; defer un(trace(p, "StructType"));
}
pos := p.expect(token.STRUCT);
var lbrace, rbrace token.Position;
var fields []*ast.Field;
if p.tok == token.LBRACE {
lbrace = p.pos;
p.next(); p.next();
return x;
list := vector.New(0);
for p.tok != token.RBRACE && p.tok != token.EOF {
list.Push(p.parseFieldDecl());
if p.tok == token.SEMICOLON {
p.next();
} else {
break;
}
}
if p.tok == token.SEMICOLON {
p.next();
}
rbrace = p.expect(token.RBRACE);
p.opt_semi = true;
// convert vector
fields = make([]*ast.Field, list.Len());
for i := list.Len() - 1; i >= 0; i-- {
fields[i] = list.At(i).(*ast.Field);
}
}
return &ast.StructType{pos, lbrace, fields, rbrace};
}
func (p *parser) parsePointerType() *ast.StarExpr {
if p.trace {
defer un(trace(p, "PointerType"));
}
star := p.expect(token.MUL);
base := p.parseType();
return &ast.StarExpr{star, base};
}
func (p *parser) tryParameterType(ellipsis_ok bool) ast.Expr {
if ellipsis_ok && p.tok == token.ELLIPSIS {
pos := p.pos;
p.next();
if p.tok != token.RPAREN {
// "..." always must be at the very end of a parameter list
p.error(pos, "expected type, found '...'");
}
return &ast.Ellipsis{pos};
} }
return p.tryType(); return p.tryType();
} }
func (p *parser) parseParameterType() ast.Expr { func (p *parser) parseParameterType(ellipsis_ok bool) ast.Expr {
typ := p.tryParameterType(); typ := p.tryParameterType(ellipsis_ok);
if typ == nil { if typ == nil {
p.error(p.pos, "type expected"); p.error_expected(p.pos, "type");
typ = &ast.BadExpr{p.pos}; typ = &ast.BadExpr{p.pos};
} }
return typ; return typ;
} }
...@@ -419,7 +510,7 @@ func (p *parser) parseParameterDecl(ellipsis_ok bool) (*vector.Vector, ast.Expr) ...@@ -419,7 +510,7 @@ func (p *parser) parseParameterDecl(ellipsis_ok bool) (*vector.Vector, ast.Expr)
list := vector.New(0); list := vector.New(0);
for { for {
// TODO do not allow ()'s here // TODO do not allow ()'s here
list.Push(p.parseParameterType()); list.Push(p.parseParameterType(ellipsis_ok));
if p.tok == token.COMMA { if p.tok == token.COMMA {
p.next(); p.next();
} else { } else {
...@@ -428,7 +519,7 @@ func (p *parser) parseParameterDecl(ellipsis_ok bool) (*vector.Vector, ast.Expr) ...@@ -428,7 +519,7 @@ func (p *parser) parseParameterDecl(ellipsis_ok bool) (*vector.Vector, ast.Expr)
} }
// if we had a list of identifiers, it must be followed by a type // if we had a list of identifiers, it must be followed by a type
typ := p.tryParameterType(); typ := p.tryParameterType(ellipsis_ok);
return list, typ; return list, typ;
} }
...@@ -439,26 +530,22 @@ func (p *parser) parseParameterList(ellipsis_ok bool) []*ast.Field { ...@@ -439,26 +530,22 @@ func (p *parser) parseParameterList(ellipsis_ok bool) []*ast.Field {
defer un(trace(p, "ParameterList")); defer un(trace(p, "ParameterList"));
} }
list, typ := p.parseParameterDecl(false); list, typ := p.parseParameterDecl(ellipsis_ok);
if typ != nil { if typ != nil {
// IdentifierList Type // IdentifierList Type
// convert list of identifiers into []*Ident idents := p.makeIdentList(list);
idents := make([]*ast.Ident, list.Len());
for i := 0; i < list.Len(); i++ {
idents[i] = list.At(i).(*ast.Ident);
}
list.Init(0); list.Init(0);
list.Push(&ast.Field{nil, idents, typ, nil}); list.Push(&ast.Field{nil, idents, typ, nil});
for p.tok == token.COMMA { for p.tok == token.COMMA {
p.next(); p.next();
idents := p.parseIdentList(nil); idents := p.parseIdentList(nil);
typ := p.parseParameterType(); typ := p.parseParameterType(ellipsis_ok);
list.Push(&ast.Field{nil, idents, typ, nil}); list.Push(&ast.Field{nil, idents, typ, nil});
} }
} else { } else {
// Type { "," Type } // Type { "," Type } (anonymous parameters)
// convert list of types into list of *Param // convert list of types into list of *Param
for i := 0; i < list.Len(); i++ { for i := 0; i < list.Len(); i++ {
list.Set(i, &ast.Field{nil, nil, list.At(i).(ast.Expr), nil}); list.Set(i, &ast.Field{nil, nil, list.At(i).(ast.Expr), nil});
...@@ -475,7 +562,6 @@ func (p *parser) parseParameterList(ellipsis_ok bool) []*ast.Field { ...@@ -475,7 +562,6 @@ func (p *parser) parseParameterList(ellipsis_ok bool) []*ast.Field {
} }
// TODO make sure Go spec is updated
func (p *parser) parseParameters(ellipsis_ok bool) []*ast.Field { func (p *parser) parseParameters(ellipsis_ok bool) []*ast.Field {
if p.trace { if p.trace {
defer un(trace(p, "Parameters")); defer un(trace(p, "Parameters"));
...@@ -512,18 +598,12 @@ func (p *parser) parseResult() []*ast.Field { ...@@ -512,18 +598,12 @@ func (p *parser) parseResult() []*ast.Field {
} }
// Function types
//
// (params)
// (params) type
// (params) (results)
func (p *parser) parseSignature() (params []*ast.Field, results []*ast.Field) { func (p *parser) parseSignature() (params []*ast.Field, results []*ast.Field) {
if p.trace { if p.trace {
defer un(trace(p, "Signature")); defer un(trace(p, "Signature"));
} }
params = p.parseParameters(true); // TODO find better solution params = p.parseParameters(true);
results = p.parseResult(); results = p.parseResult();
return params, results; return params, results;
...@@ -552,10 +632,10 @@ func (p *parser) parseMethodSpec() *ast.Field { ...@@ -552,10 +632,10 @@ func (p *parser) parseMethodSpec() *ast.Field {
var typ ast.Expr; var typ ast.Expr;
x := p.parseQualifiedIdent(); x := p.parseQualifiedIdent();
if tmp, is_ident := x.(*ast.Ident); is_ident && (p.tok == token.COMMA || p.tok == token.LPAREN) { if tmp, is_ident := x.(*ast.Ident); is_ident && (p.tok == token.COMMA || p.tok == token.LPAREN) {
// method(s) // methods
idents = p.parseIdentList(x); idents = p.parseIdentList(x);
params, results := p.parseSignature(); params, results := p.parseSignature();
typ = &ast.FunctionType{nopos, params, results}; typ = &ast.FunctionType{noPos, params, results};
} else { } else {
// embedded interface // embedded interface
typ = x; typ = x;
...@@ -614,133 +694,46 @@ func (p *parser) parseMapType() *ast.MapType { ...@@ -614,133 +694,46 @@ func (p *parser) parseMapType() *ast.MapType {
} }
func (p *parser) parseStringList(x *ast.StringLit) []*ast.StringLit func (p *parser) parseChannelType() *ast.ChannelType {
func (p *parser) parseFieldDecl() *ast.Field {
if p.trace {
defer un(trace(p, "FieldDecl"));
}
doc := p.getDoc();
// a list of identifiers looks like a list of type names
list := vector.New(0);
for {
// TODO do not allow ()'s here
list.Push(p.parseType());
if p.tok == token.COMMA {
p.next();
} else {
break;
}
}
// if we had a list of identifiers, it must be followed by a type
typ := p.tryType();
// optional tag
var tag []*ast.StringLit;
if p.tok == token.STRING {
tag = p.parseStringList(nil);
}
// analyze case
var idents []*ast.Ident;
if typ != nil {
// non-empty identifier list followed by a type
idents = make([]*ast.Ident, list.Len());
for i := 0; i < list.Len(); i++ {
if ident, is_ident := list.At(i).(*ast.Ident); is_ident {
idents[i] = ident;
} else {
p.error(list.At(i).(ast.Expr).Pos(), "identifier expected");
}
}
} else {
// anonymous field
if list.Len() == 1 {
// TODO should do more checks here
typ = list.At(0).(ast.Expr);
} else {
p.error(p.pos, "anonymous field expected");
}
}
return &ast.Field{doc, idents, typ, tag};
}
func (p *parser) parseStructType() *ast.StructType {
if p.trace { if p.trace {
defer un(trace(p, "StructType")); defer un(trace(p, "ChannelType"));
} }
pos := p.expect(token.STRUCT); pos := p.pos;
var lbrace, rbrace token.Position; dir := ast.SEND | ast.RECV;
var fields []*ast.Field; if p.tok == token.CHAN {
if p.tok == token.LBRACE {
lbrace = p.pos;
p.next(); p.next();
if p.tok == token.ARROW {
list := vector.New(0);
for p.tok != token.RBRACE && p.tok != token.EOF {
list.Push(p.parseFieldDecl());
if p.tok == token.SEMICOLON {
p.next();
} else {
break;
}
}
if p.tok == token.SEMICOLON {
p.next(); p.next();
dir = ast.SEND;
} }
} else {
rbrace = p.expect(token.RBRACE); p.expect(token.ARROW);
p.opt_semi = true; p.expect(token.CHAN);
dir = ast.RECV;
// convert vector
fields = make([]*ast.Field, list.Len());
for i := list.Len() - 1; i >= 0; i-- {
fields[i] = list.At(i).(*ast.Field);
}
}
return &ast.StructType{pos, lbrace, fields, rbrace};
}
func (p *parser) parsePointerType() *ast.StarExpr {
if p.trace {
defer un(trace(p, "PointerType"));
} }
value := p.parseType();
star := p.expect(token.MUL); return &ast.ChannelType{pos, dir, value};
base := p.parseType();
return &ast.StarExpr{star, base};
} }
func (p *parser) tryType() ast.Expr { func (p *parser) tryRawType(ellipsis_ok bool) ast.Expr {
if p.trace {
defer un(trace(p, "Type (try)"));
}
switch p.tok { switch p.tok {
case token.IDENT: return p.parseTypeName(); case token.IDENT: return p.parseTypeName();
case token.LBRACK: return p.parseArrayType(); case token.LBRACK: return p.parseArrayOrSliceType(ellipsis_ok);
case token.CHAN, token.ARROW: return p.parseChannelType();
case token.INTERFACE: return p.parseInterfaceType();
case token.FUNC: return p.parseFunctionType();
case token.MAP: return p.parseMapType();
case token.STRUCT: return p.parseStructType(); case token.STRUCT: return p.parseStructType();
case token.MUL: return p.parsePointerType(); case token.MUL: return p.parsePointerType();
case token.FUNC: return p.parseFunctionType();
case token.INTERFACE: return p.parseInterfaceType();
case token.MAP: return p.parseMapType();
case token.CHAN, token.ARROW: return p.parseChannelType();
case token.LPAREN: case token.LPAREN:
lparen := p.pos; lparen := p.pos;
p.next(); p.next();
x := p.parseType(); typ := p.parseType();
rparen := p.expect(token.RPAREN); rparen := p.expect(token.RPAREN);
return &ast.ParenExpr{lparen, x, rparen}; return &ast.ParenExpr{lparen, typ, rparen};
} }
// no type found // no type found
...@@ -748,10 +741,15 @@ func (p *parser) tryType() ast.Expr { ...@@ -748,10 +741,15 @@ func (p *parser) tryType() ast.Expr {
} }
func (p *parser) tryType() ast.Expr {
return p.tryRawType(false);
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Blocks // Blocks
func asStmtList(list *vector.Vector) []ast.Stmt { func makeStmtList(list *vector.Vector) []ast.Stmt {
stats := make([]ast.Stmt, list.Len()); stats := make([]ast.Stmt, list.Len());
for i := 0; i < list.Len(); i++ { for i := 0; i < list.Len(); i++ {
stats[i] = list.At(i).(ast.Stmt); stats[i] = list.At(i).(ast.Stmt);
...@@ -782,13 +780,13 @@ func (p *parser) parseStatementList() []ast.Stmt { ...@@ -782,13 +780,13 @@ func (p *parser) parseStatementList() []ast.Stmt {
} }
} }
return asStmtList(list); return makeStmtList(list);
} }
func (p *parser) parseBlockStmt() *ast.BlockStmt { func (p *parser) parseBlockStmt() *ast.BlockStmt {
if p.trace { if p.trace {
defer un(trace(p, "compositeStmt")); defer un(trace(p, "BlockStmt"));
} }
lbrace := p.expect(token.LBRACE); lbrace := p.expect(token.LBRACE);
...@@ -803,20 +801,6 @@ func (p *parser) parseBlockStmt() *ast.BlockStmt { ...@@ -803,20 +801,6 @@ func (p *parser) parseBlockStmt() *ast.BlockStmt {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Expressions // Expressions
func (p *parser) parseFunctionLit() ast.Expr {
if p.trace {
defer un(trace(p, "FunctionLit"));
}
typ := p.parseFunctionType();
p.expr_lev++;
body := p.parseBlockStmt();
p.expr_lev--;
return &ast.FunctionLit{typ, body};
}
func (p *parser) parseStringList(x *ast.StringLit) []*ast.StringLit { func (p *parser) parseStringList(x *ast.StringLit) []*ast.StringLit {
if p.trace { if p.trace {
defer un(trace(p, "StringList")); defer un(trace(p, "StringList"));
...@@ -842,6 +826,23 @@ func (p *parser) parseStringList(x *ast.StringLit) []*ast.StringLit { ...@@ -842,6 +826,23 @@ func (p *parser) parseStringList(x *ast.StringLit) []*ast.StringLit {
} }
func (p *parser) parseFunctionLit() ast.Expr {
if p.trace {
defer un(trace(p, "FunctionLit"));
}
typ := p.parseFunctionType();
p.expr_lev++;
body := p.parseBlockStmt();
p.expr_lev--;
return &ast.FunctionLit{typ, body};
}
// parseOperand may return an expression or a raw type (incl. array
// types of the form [...]T. Callers must verify the result.
//
func (p *parser) parseOperand() ast.Expr { func (p *parser) parseOperand() ast.Expr {
if p.trace { if p.trace {
defer un(trace(p, "Operand")); defer un(trace(p, "Operand"));
...@@ -878,7 +879,7 @@ func (p *parser) parseOperand() ast.Expr { ...@@ -878,7 +879,7 @@ func (p *parser) parseOperand() ast.Expr {
lparen := p.pos; lparen := p.pos;
p.next(); p.next();
p.expr_lev++; p.expr_lev++;
x := p.parseExpression(1); x := p.parseExpression();
p.expr_lev--; p.expr_lev--;
rparen := p.expect(token.RPAREN); rparen := p.expect(token.RPAREN);
return &ast.ParenExpr{lparen, x, rparen}; return &ast.ParenExpr{lparen, x, rparen};
...@@ -887,15 +888,14 @@ func (p *parser) parseOperand() ast.Expr { ...@@ -887,15 +888,14 @@ func (p *parser) parseOperand() ast.Expr {
return p.parseFunctionLit(); return p.parseFunctionLit();
default: default:
t := p.tryType(); t := p.tryRawType(true); // could be type for composite literal
if t != nil { if t != nil {
return t; return t;
} else {
p.error(p.pos, "operand expected");
p.next(); // make progress
} }
} }
p.error_expected(p.pos, "operand");
p.next(); // make progress
return &ast.BadExpr{p.pos}; return &ast.BadExpr{p.pos};
} }
...@@ -910,24 +910,21 @@ func (p *parser) parseSelectorOrTypeAssertion(x ast.Expr) ast.Expr { ...@@ -910,24 +910,21 @@ func (p *parser) parseSelectorOrTypeAssertion(x ast.Expr) ast.Expr {
// selector // selector
sel := p.parseIdent(); sel := p.parseIdent();
return &ast.SelectorExpr{x, sel}; return &ast.SelectorExpr{x, sel};
}
// type assertion
p.expect(token.LPAREN);
var typ ast.Expr;
if p.tok == token.TYPE {
// special case for type switch
typ = &ast.Ident{p.pos, p.lit};
p.next();
} else { } else {
// type assertion typ = p.parseType();
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.lit};
p.next();
} else {
typ = p.parseType();
}
p.expect(token.RPAREN);
return &ast.TypeAssertExpr{x, typ};
} }
p.expect(token.RPAREN);
unreachable(); return &ast.TypeAssertExpr{x, typ};
return nil;
} }
...@@ -938,28 +935,26 @@ func (p *parser) parseIndexOrSlice(x ast.Expr) ast.Expr { ...@@ -938,28 +935,26 @@ func (p *parser) parseIndexOrSlice(x ast.Expr) ast.Expr {
p.expect(token.LBRACK); p.expect(token.LBRACK);
p.expr_lev++; p.expr_lev++;
index := p.parseExpression(1); begin := p.parseExpression();
p.expr_lev--; var end ast.Expr;
if p.tok == token.COLON {
if p.tok == token.RBRACK {
// index
p.next(); p.next();
return &ast.IndexExpr{x, index}; end = p.parseExpression();
} }
// slice
p.expect(token.COLON);
p.expr_lev++;
end := p.parseExpression(1);
p.expr_lev--; p.expr_lev--;
p.expect(token.RBRACK); p.expect(token.RBRACK);
return &ast.SliceExpr{x, index, end};
if end != nil {
return &ast.SliceExpr{x, begin, end};
}
return &ast.IndexExpr{x, begin};
} }
func (p *parser) parseCall(fun ast.Expr) *ast.CallExpr { func (p *parser) parseCallOrConversion(fun ast.Expr) *ast.CallExpr {
if p.trace { if p.trace {
defer un(trace(p, "Call")); defer un(trace(p, "CallOrConversion"));
} }
lparen := p.expect(token.LPAREN); lparen := p.expect(token.LPAREN);
...@@ -968,34 +963,51 @@ func (p *parser) parseCall(fun ast.Expr) *ast.CallExpr { ...@@ -968,34 +963,51 @@ func (p *parser) parseCall(fun ast.Expr) *ast.CallExpr {
args = p.parseExpressionList(); args = p.parseExpressionList();
} }
rparen := p.expect(token.RPAREN); rparen := p.expect(token.RPAREN);
return &ast.CallExpr{fun, lparen, args, rparen}; return &ast.CallExpr{fun, lparen, args, rparen};
} }
func (p *parser) parseElementList() []ast.Expr { func (p *parser) parseKeyValueExpr() ast.Expr {
if p.trace {
defer un(trace(p, "KeyValueExpr"));
}
key := p.parseExpression();
if p.tok == token.COLON {
colon := p.pos;
p.next();
value := p.parseExpression();
return &ast.KeyValueExpr{key, colon, value};
}
return key;
}
func isPair(x ast.Expr) bool {
tmp, is_pair := x.(*ast.KeyValueExpr);
return is_pair;
}
func (p *parser) parseExpressionOrKeyValueList() []ast.Expr {
if p.trace { if p.trace {
defer un(trace(p, "ElementList")); defer un(trace(p, "ExpressionOrKeyValueList"));
} }
var pairs bool;
list := vector.New(0); list := vector.New(0);
singles := true; for p.tok != token.RBRACE && p.tok != token.EOF {
for p.tok != token.RBRACE { x := p.parseKeyValueExpr();
x := p.parseExpression(0);
if list.Len() == 0 { if list.Len() == 0 {
// first element determines syntax for remaining elements pairs = isPair(x);
if t, is_binary := x.(*ast.BinaryExpr); is_binary && t.Op == token.COLON {
singles = false;
}
} else { } else {
// not the first element - check syntax // not the first element - check syntax
if singles { if pairs != isPair(x) {
if t, is_binary := x.(*ast.BinaryExpr); is_binary && t.Op == token.COLON { p.error_expected(x.Pos(), "all single expressions or all key-value pairs");
p.error(t.X.Pos(), "single value expected; found pair");
}
} else {
if t, is_binary := x.(*ast.BinaryExpr); !is_binary || t.Op != token.COLON {
p.error(x.Pos(), "key:value pair expected; found single value");
}
} }
} }
...@@ -1026,13 +1038,91 @@ func (p *parser) parseCompositeLit(typ ast.Expr) ast.Expr { ...@@ -1026,13 +1038,91 @@ func (p *parser) parseCompositeLit(typ ast.Expr) ast.Expr {
lbrace := p.expect(token.LBRACE); lbrace := p.expect(token.LBRACE);
var elts []ast.Expr; var elts []ast.Expr;
if p.tok != token.RBRACE { if p.tok != token.RBRACE {
elts = p.parseElementList(); elts = p.parseExpressionOrKeyValueList();
} }
rbrace := p.expect(token.RBRACE); rbrace := p.expect(token.RBRACE);
return &ast.CompositeLit{typ, lbrace, elts, rbrace}; return &ast.CompositeLit{typ, lbrace, elts, rbrace};
} }
// TODO apply these make functions more thoroughly
// (all uses of parseExpression)
// makeExpr makes sure x is an expression and not a type.
func (p *parser) makeExpr(x ast.Expr) ast.Expr {
// TODO should provide predicate in AST nodes
switch t := x.(type) {
case *ast.BadExpr: return x;
case *ast.Ident: return x;
case *ast.IntLit: return x;
case *ast.FloatLit: return x;
case *ast.CharLit: return x;
case *ast.StringLit: return x;
case *ast.StringList: return x;
case *ast.FunctionLit: return x;
case *ast.CompositeLit: return x;
case *ast.ParenExpr: return p.makeExpr(t.X);
case *ast.SelectorExpr: return x;
case *ast.IndexExpr: return x;
case *ast.SliceExpr: return x;
case *ast.TypeAssertExpr: return x;
case *ast.CallExpr: return x;
case *ast.StarExpr: return x;
case *ast.UnaryExpr: return x;
case *ast.BinaryExpr: return x;
}
// all other nodes are not proper expressions
p.error_expected(x.Pos(), "expression");
panic();
return &ast.BadExpr{x.Pos()};
}
// makeType makes sure x is a type and not an expression.
func (p *parser) makeType(x ast.Expr) ast.Expr {
// TODO should provide predicate in AST nodes
switch t := x.(type) {
case *ast.BadExpr: return x;
case *ast.Ident: return x;
case *ast.ParenExpr: return p.makeType(t.X);
case *ast.ArrayType:
if len, is_ellipsis := t.Len.(*ast.Ellipsis); is_ellipsis {
p.error(len.Pos(), "expected array length, found '...'");
return &ast.BadExpr{x.Pos()};
}
return x;
case *ast.SliceType: return x;
case *ast.StructType: return x;
case *ast.FunctionType: return x;
case *ast.InterfaceType: return x;
case *ast.MapType: return x;
case *ast.ChannelType: return x;
}
// all other nodes are not types
p.error_expected(x.Pos(), "type");
return &ast.BadExpr{x.Pos()};
}
// makeExprOrType makes sure that x is an expression or a type
// (and not a raw type such as [...]T).
//
func (p *parser) makeExprOrType(x ast.Expr) ast.Expr {
// TODO should provide predicate in AST nodes
if t, is_array := x.(*ast.ArrayType); is_array {
if len, is_ellipsis := t.Len.(*ast.Ellipsis); is_ellipsis {
p.error(len.Pos(), "expected array length, found '...'");
return &ast.BadExpr{x.Pos()};
}
}
// all other nodes are expressions or types
return x;
}
func (p *parser) parsePrimaryExpr() ast.Expr { func (p *parser) parsePrimaryExpr() ast.Expr {
if p.trace { if p.trace {
defer un(trace(p, "PrimaryExpr")); defer un(trace(p, "PrimaryExpr"));
...@@ -1041,21 +1131,21 @@ func (p *parser) parsePrimaryExpr() ast.Expr { ...@@ -1041,21 +1131,21 @@ func (p *parser) parsePrimaryExpr() ast.Expr {
x := p.parseOperand(); x := p.parseOperand();
for { for {
switch p.tok { switch p.tok {
case token.PERIOD: x = p.parseSelectorOrTypeAssertion(x); case token.PERIOD: x = p.parseSelectorOrTypeAssertion(p.makeExpr(x));
case token.LBRACK: x = p.parseIndexOrSlice(x); case token.LBRACK: x = p.parseIndexOrSlice(p.makeExpr(x));
case token.LPAREN: x = p.parseCall(x); case token.LPAREN: x = p.parseCallOrConversion(p.makeExprOrType(x));
case token.LBRACE: case token.LBRACE:
if p.expr_lev >= 0 { if p.expr_lev >= 0 {
x = p.parseCompositeLit(x); x = p.parseCompositeLit(x);
} else { } else {
return x; return p.makeExprOrType(x);
} }
default: default:
return x; return p.makeExprOrType(x);
} }
} }
unreachable(); panic(); // unreachable
return nil; return nil;
} }
...@@ -1067,17 +1157,17 @@ func (p *parser) parseUnaryExpr() ast.Expr { ...@@ -1067,17 +1157,17 @@ func (p *parser) parseUnaryExpr() ast.Expr {
switch p.tok { switch p.tok {
case token.ADD, token.SUB, token.NOT, token.XOR, token.ARROW, token.AND, token.RANGE: case token.ADD, token.SUB, token.NOT, token.XOR, token.ARROW, token.AND, token.RANGE:
pos, tok := p.pos, p.tok; pos, op := p.pos, p.tok;
p.next(); p.next();
x := p.parseUnaryExpr(); x := p.parseUnaryExpr();
return &ast.UnaryExpr{pos, tok, x}; return &ast.UnaryExpr{pos, op, p.makeExpr(x)};
case token.MUL: case token.MUL:
// unary "*" expression or pointer type // unary "*" expression or pointer type
pos := p.pos; pos := p.pos;
p.next(); p.next();
x := p.parseUnaryExpr(); x := p.parseUnaryExpr();
return &ast.StarExpr{pos, x}; return &ast.StarExpr{pos, p.makeExprOrType(x)};
} }
return p.parsePrimaryExpr(); return p.parsePrimaryExpr();
...@@ -1092,10 +1182,10 @@ func (p *parser) parseBinaryExpr(prec1 int) ast.Expr { ...@@ -1092,10 +1182,10 @@ func (p *parser) parseBinaryExpr(prec1 int) ast.Expr {
x := p.parseUnaryExpr(); x := p.parseUnaryExpr();
for prec := p.tok.Precedence(); prec >= prec1; prec-- { for prec := p.tok.Precedence(); prec >= prec1; prec-- {
for p.tok.Precedence() == prec { for p.tok.Precedence() == prec {
pos, tok := p.pos, p.tok; pos, op := p.pos, p.tok;
p.next(); p.next();
y := p.parseBinaryExpr(prec + 1); y := p.parseBinaryExpr(prec + 1);
x = &ast.BinaryExpr{x, pos, tok, y}; x = &ast.BinaryExpr{p.makeExpr(x), pos, op, p.makeExpr(y)};
} }
} }
...@@ -1103,16 +1193,12 @@ func (p *parser) parseBinaryExpr(prec1 int) ast.Expr { ...@@ -1103,16 +1193,12 @@ func (p *parser) parseBinaryExpr(prec1 int) ast.Expr {
} }
func (p *parser) parseExpression(prec int) ast.Expr { func (p *parser) parseExpression() ast.Expr {
if p.trace { if p.trace {
defer un(trace(p, "Expression")); defer un(trace(p, "Expression"));
} }
if prec < 0 { return p.parseBinaryExpr(token.LowestPrec + 1);
panic("precedence must be >= 0");
}
return p.parseBinaryExpr(prec);
} }
...@@ -1172,11 +1258,11 @@ func (p *parser) parseSimpleStmt() ast.Stmt { ...@@ -1172,11 +1258,11 @@ func (p *parser) parseSimpleStmt() ast.Stmt {
func (p *parser) parseCallExpr() *ast.CallExpr { func (p *parser) parseCallExpr() *ast.CallExpr {
x := p.parseExpression(1); x := p.parseExpression();
if call, is_call := x.(*ast.CallExpr); is_call { if call, is_call := x.(*ast.CallExpr); is_call {
return call; return call;
} }
p.error(x.Pos(), "expected function/method call"); p.error_expected(x.Pos(), "function/method call");
return nil; return nil;
} }
...@@ -1256,16 +1342,12 @@ func (p *parser) asExpr(s ast.Stmt) ast.Expr { ...@@ -1256,16 +1342,12 @@ func (p *parser) asExpr(s ast.Stmt) ast.Expr {
if es, is_expr := s.(*ast.ExprStmt); is_expr { if es, is_expr := s.(*ast.ExprStmt); is_expr {
return es.X; return es.X;
} }
p.error(s.Pos(), "condition expected; found simple statement"); p.error(s.Pos(), "expected condition, found simple statement");
return &ast.BadExpr{s.Pos()}; return &ast.BadExpr{s.Pos()};
} }
func (p *parser) parseControlClause(isForStmt bool) (s1, s2, s3 ast.Stmt) { func (p *parser) parseControlClause(isForStmt bool) (s1, s2, s3 ast.Stmt) {
if p.trace {
defer un(trace(p, "ControlClause"));
}
if p.tok != token.LBRACE { if p.tok != token.LBRACE {
prev_lev := p.expr_lev; prev_lev := p.expr_lev;
p.expr_lev = -1; p.expr_lev = -1;
...@@ -1375,25 +1457,21 @@ func (p *parser) parseSwitchStmt() ast.Stmt { ...@@ -1375,25 +1457,21 @@ func (p *parser) parseSwitchStmt() ast.Stmt {
} }
rbrace := p.expect(token.RBRACE); rbrace := p.expect(token.RBRACE);
p.opt_semi = true; p.opt_semi = true;
body := &ast.BlockStmt{lbrace, asStmtList(cases), rbrace}; body := &ast.BlockStmt{lbrace, makeStmtList(cases), rbrace};
return &ast.SwitchStmt{pos, s1, p.asExpr(s2), body}; return &ast.SwitchStmt{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.BlockStmt{lbrace, asStmtList(cases), rbrace};
return &ast.TypeSwitchStmt{pos, s1, s2, body};
} }
unreachable(); // type switch
return nil; // 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.BlockStmt{lbrace, makeStmtList(cases), rbrace};
return &ast.TypeSwitchStmt{pos, s1, s2, body};
} }
...@@ -1410,17 +1488,17 @@ func (p *parser) parseCommClause() *ast.CommClause { ...@@ -1410,17 +1488,17 @@ func (p *parser) parseCommClause() *ast.CommClause {
p.next(); p.next();
if p.tok == token.ARROW { if p.tok == token.ARROW {
// RecvExpr without assignment // RecvExpr without assignment
rhs = p.parseExpression(1); rhs = p.parseExpression();
} else { } else {
// SendExpr or RecvExpr // SendExpr or RecvExpr
rhs = p.parseExpression(1); rhs = p.parseExpression();
if p.tok == token.ASSIGN || p.tok == token.DEFINE { if p.tok == token.ASSIGN || p.tok == token.DEFINE {
// RecvExpr with assignment // RecvExpr with assignment
tok = p.tok; tok = p.tok;
p.next(); p.next();
lhs = rhs; lhs = rhs;
if p.tok == token.ARROW { if p.tok == token.ARROW {
rhs = p.parseExpression(1); rhs = p.parseExpression();
} else { } else {
p.expect(token.ARROW); // use expect() error handling p.expect(token.ARROW); // use expect() error handling
} }
...@@ -1451,7 +1529,7 @@ func (p *parser) parseSelectStmt() *ast.SelectStmt { ...@@ -1451,7 +1529,7 @@ func (p *parser) parseSelectStmt() *ast.SelectStmt {
} }
rbrace := p.expect(token.RBRACE); rbrace := p.expect(token.RBRACE);
p.opt_semi = true; p.opt_semi = true;
body := &ast.BlockStmt{lbrace, asStmtList(cases), rbrace}; body := &ast.BlockStmt{lbrace, makeStmtList(cases), rbrace};
return &ast.SelectStmt{pos, body}; return &ast.SelectStmt{pos, body};
} }
...@@ -1469,7 +1547,7 @@ func (p *parser) parseForStmt() ast.Stmt { ...@@ -1469,7 +1547,7 @@ func (p *parser) parseForStmt() ast.Stmt {
if as, is_as := s2.(*ast.AssignStmt); is_as { if as, is_as := s2.(*ast.AssignStmt); is_as {
// possibly a for statement with a range clause; check assignment operator // possibly a for statement with a range clause; check assignment operator
if as.Tok != token.ASSIGN && as.Tok != token.DEFINE { if as.Tok != token.ASSIGN && as.Tok != token.DEFINE {
p.error(as.TokPos, "'=' or ':=' expected"); p.error_expected(as.TokPos, "'=' or ':='");
return &ast.BadStmt{pos}; return &ast.BadStmt{pos};
} }
// check lhs // check lhs
...@@ -1481,19 +1559,19 @@ func (p *parser) parseForStmt() ast.Stmt { ...@@ -1481,19 +1559,19 @@ func (p *parser) parseForStmt() ast.Stmt {
case 1: case 1:
key = as.Lhs[0]; key = as.Lhs[0];
default: default:
p.error(as.Lhs[0].Pos(), "expected 1 or 2 expressions"); p.error_expected(as.Lhs[0].Pos(), "1 or 2 expressions");
return &ast.BadStmt{pos}; return &ast.BadStmt{pos};
} }
// check rhs // check rhs
if len(as.Rhs) != 1 { if len(as.Rhs) != 1 {
p.error(as.Rhs[0].Pos(), "expected 1 expressions"); p.error_expected(as.Rhs[0].Pos(), "1 expressions");
return &ast.BadStmt{pos}; return &ast.BadStmt{pos};
} }
if rhs, is_unary := as.Rhs[0].(*ast.UnaryExpr); is_unary && rhs.Op == token.RANGE { if rhs, is_unary := as.Rhs[0].(*ast.UnaryExpr); is_unary && rhs.Op == token.RANGE {
// rhs is range expression; check lhs // rhs is range expression; check lhs
return &ast.RangeStmt{pos, key, value, as.TokPos, as.Tok, rhs.X, body} return &ast.RangeStmt{pos, key, value, as.TokPos, as.Tok, rhs.X, body}
} else { } else {
p.error(s2.Pos(), "range clause expected"); p.error_expected(s2.Pos(), "range clause");
return &ast.BadStmt{pos}; return &ast.BadStmt{pos};
} }
} else { } else {
...@@ -1501,7 +1579,7 @@ func (p *parser) parseForStmt() ast.Stmt { ...@@ -1501,7 +1579,7 @@ func (p *parser) parseForStmt() ast.Stmt {
return &ast.ForStmt{pos, s1, p.asExpr(s2), s3, body}; return &ast.ForStmt{pos, s1, p.asExpr(s2), s3, body};
} }
unreachable(); panic(); // unreachable
return nil; return nil;
} }
...@@ -1532,19 +1610,19 @@ func (p *parser) parseStatement() ast.Stmt { ...@@ -1532,19 +1610,19 @@ func (p *parser) parseStatement() ast.Stmt {
return p.parseBlockStmt(); return p.parseBlockStmt();
case token.IF: case token.IF:
return p.parseIfStmt(); return p.parseIfStmt();
case token.FOR:
return p.parseForStmt();
case token.SWITCH: case token.SWITCH:
return p.parseSwitchStmt(); return p.parseSwitchStmt();
case token.SELECT: case token.SELECT:
return p.parseSelectStmt(); return p.parseSelectStmt();
case token.FOR:
return p.parseForStmt();
case token.SEMICOLON, token.RBRACE: case token.SEMICOLON, token.RBRACE:
// don't consume the ";", it is the separator following the empty statement // don't consume the ";", it is the separator following the empty statement
return &ast.EmptyStmt{p.pos}; return &ast.EmptyStmt{p.pos};
} }
// no statement found // no statement found
p.error(p.pos, "statement expected"); p.error_expected(p.pos, "statement");
return &ast.BadStmt{p.pos}; return &ast.BadStmt{p.pos};
} }
...@@ -1581,7 +1659,7 @@ func (p *parser) parseConstSpec(pos token.Position, doc ast.Comments) *ast.Const ...@@ -1581,7 +1659,7 @@ func (p *parser) parseConstSpec(pos token.Position, doc ast.Comments) *ast.Const
defer un(trace(p, "ConstSpec")); defer un(trace(p, "ConstSpec"));
} }
names := p.parseIdentList(nil); idents := p.parseIdentList(nil);
typ := p.tryType(); typ := p.tryType();
var values []ast.Expr; var values []ast.Expr;
if typ != nil || p.tok == token.ASSIGN { if typ != nil || p.tok == token.ASSIGN {
...@@ -1589,7 +1667,7 @@ func (p *parser) parseConstSpec(pos token.Position, doc ast.Comments) *ast.Const ...@@ -1589,7 +1667,7 @@ func (p *parser) parseConstSpec(pos token.Position, doc ast.Comments) *ast.Const
values = p.parseExpressionList(); values = p.parseExpressionList();
} }
return &ast.ConstDecl{doc, pos, names, typ, values}; return &ast.ConstDecl{doc, pos, idents, typ, values};
} }
...@@ -1610,7 +1688,7 @@ func (p *parser) parseVarSpec(pos token.Position, doc ast.Comments) *ast.VarDecl ...@@ -1610,7 +1688,7 @@ func (p *parser) parseVarSpec(pos token.Position, doc ast.Comments) *ast.VarDecl
defer un(trace(p, "VarSpec")); defer un(trace(p, "VarSpec"));
} }
names := p.parseIdentList(nil); idents := p.parseIdentList(nil);
typ := p.tryType(); typ := p.tryType();
var values []ast.Expr; var values []ast.Expr;
if typ == nil || p.tok == token.ASSIGN { if typ == nil || p.tok == token.ASSIGN {
...@@ -1618,7 +1696,7 @@ func (p *parser) parseVarSpec(pos token.Position, doc ast.Comments) *ast.VarDecl ...@@ -1618,7 +1696,7 @@ func (p *parser) parseVarSpec(pos token.Position, doc ast.Comments) *ast.VarDecl
values = p.parseExpressionList(); values = p.parseExpressionList();
} }
return &ast.VarDecl{doc, pos, names, typ, values}; return &ast.VarDecl{doc, pos, idents, typ, values};
} }
...@@ -1630,7 +1708,7 @@ func (p *parser) parseSpec(pos token.Position, doc ast.Comments, keyword int) as ...@@ -1630,7 +1708,7 @@ func (p *parser) parseSpec(pos token.Position, doc ast.Comments, keyword int) as
case token.VAR: return p.parseVarSpec(pos, doc); case token.VAR: return p.parseVarSpec(pos, doc);
} }
unreachable(); panic(); // unreachable
return nil; return nil;
} }
...@@ -1647,7 +1725,7 @@ func (p *parser) parseDecl(keyword int) ast.Decl { ...@@ -1647,7 +1725,7 @@ func (p *parser) parseDecl(keyword int) ast.Decl {
p.next(); p.next();
list := vector.New(0); list := vector.New(0);
for p.tok != token.RPAREN && p.tok != token.EOF { for p.tok != token.RPAREN && p.tok != token.EOF {
list.Push(p.parseSpec(nopos, nil, keyword)); list.Push(p.parseSpec(noPos, nil, keyword));
if p.tok == token.SEMICOLON { if p.tok == token.SEMICOLON {
p.next(); p.next();
} else { } else {
...@@ -1670,15 +1748,6 @@ func (p *parser) parseDecl(keyword int) ast.Decl { ...@@ -1670,15 +1748,6 @@ func (p *parser) parseDecl(keyword int) ast.Decl {
} }
// Function and method declarations
//
// func ident (params)
// func ident (params) type
// func ident (params) (results)
// func (recv) ident (params)
// func (recv) ident (params) type
// func (recv) ident (params) (results)
func (p *parser) parseFunctionDecl() *ast.FuncDecl { func (p *parser) parseFunctionDecl() *ast.FuncDecl {
if p.trace { if p.trace {
defer un(trace(p, "FunctionDecl")); defer un(trace(p, "FunctionDecl"));
...@@ -1690,11 +1759,11 @@ func (p *parser) parseFunctionDecl() *ast.FuncDecl { ...@@ -1690,11 +1759,11 @@ func (p *parser) parseFunctionDecl() *ast.FuncDecl {
var recv *ast.Field; var recv *ast.Field;
if p.tok == token.LPAREN { if p.tok == token.LPAREN {
pos := p.pos; pos := p.pos;
tmp := p.parseParameters(true); tmp := p.parseParameters(false);
if len(tmp) == 1 { if len(tmp) == 1 {
recv = tmp[0]; recv = tmp[0];
} else { } else {
p.error(pos, "must have exactly one receiver"); p.error_expected(pos, "exactly one receiver");
} }
} }
...@@ -1723,7 +1792,7 @@ func (p *parser) parseDeclaration() ast.Decl { ...@@ -1723,7 +1792,7 @@ func (p *parser) parseDeclaration() ast.Decl {
} }
pos := p.pos; pos := p.pos;
p.error(pos, "declaration expected"); p.error_expected(pos, "declaration");
p.next(); // make progress p.next(); // make progress
return &ast.BadDecl{pos}; return &ast.BadDecl{pos};
} }
...@@ -1732,16 +1801,18 @@ func (p *parser) parseDeclaration() ast.Decl { ...@@ -1732,16 +1801,18 @@ func (p *parser) parseDeclaration() ast.Decl {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Packages // Packages
// The Mode constants control how much of the source text is parsed. // A set of flags (or 0) must be provided via the mode parameter to
type Mode int; // the Parse function. They control the amount of source code parsed
// and other optional parser functionality.
//
const ( const (
ParseEntirePackage Mode = iota; PackageClauseOnly = 1 << iota; // parsing stops after package clause
ParseImportDeclsOnly; ImportsOnly; // parsing stops after import declarations
ParsePackageClauseOnly; Trace; // print a trace of parsed productions
) )
func (p *parser) parsePackage(mode Mode) *ast.Package { func (p *parser) parsePackage() *ast.Package {
if p.trace { if p.trace {
defer un(trace(p, "Program")); defer un(trace(p, "Program"));
} }
...@@ -1749,16 +1820,15 @@ func (p *parser) parsePackage(mode Mode) *ast.Package { ...@@ -1749,16 +1820,15 @@ func (p *parser) parsePackage(mode Mode) *ast.Package {
// package clause // package clause
comment := p.getDoc(); comment := p.getDoc();
pos := p.expect(token.PACKAGE); pos := p.expect(token.PACKAGE);
name := p.parseIdent(); ident := p.parseIdent();
if p.tok == token.SEMICOLON { if p.tok == token.SEMICOLON {
// common error // common error
p.error(p.pos, "extra semicolon"); p.error(p.pos, "extra semicolon");
p.next(); p.next();
} }
var decls []ast.Decl; var decls []ast.Decl;
if mode <= ParseImportDeclsOnly { if p.mode & PackageClauseOnly == 0 {
// import decls // import decls
list := vector.New(0); list := vector.New(0);
for p.tok == token.IMPORT { for p.tok == token.IMPORT {
...@@ -1768,7 +1838,7 @@ func (p *parser) parsePackage(mode Mode) *ast.Package { ...@@ -1768,7 +1838,7 @@ func (p *parser) parsePackage(mode Mode) *ast.Package {
} }
} }
if mode <= ParseEntirePackage { if p.mode & ImportsOnly == 0 {
// rest of package body // rest of package body
for p.tok != token.EOF { for p.tok != token.EOF {
list.Push(p.parseDeclaration()); list.Push(p.parseDeclaration());
...@@ -1791,7 +1861,7 @@ func (p *parser) parsePackage(mode Mode) *ast.Package { ...@@ -1791,7 +1861,7 @@ func (p *parser) parsePackage(mode Mode) *ast.Package {
comments[i] = p.comments.At(i).(*ast.Comment); comments[i] = p.comments.At(i).(*ast.Comment);
} }
return &ast.Package{comment, pos, name, decls, comments}; return &ast.Package{comment, pos, ident, decls, comments};
} }
...@@ -1809,23 +1879,25 @@ func (p *parser) parsePackage(mode Mode) *ast.Package { ...@@ -1809,23 +1879,25 @@ func (p *parser) parsePackage(mode Mode) *ast.Package {
// be constructed partially, with ast.BadX nodes representing the fragments // be constructed partially, with ast.BadX nodes representing the fragments
// of source code that contained syntax errors. // of source code that contained syntax errors.
// //
// The amount of source text parsed can be controlled with the mode parameter. // The mode parameter controls the amount of source text parsed and other
// The flags parameter controls optional parser functionality such as tracing. // optional parser functionality.
// //
// (*) Note that a scanner may find lexical syntax errors but still return // (*) Note that a scanner may find lexical syntax errors but still return
// a legal token sequence. To be sure there are no syntax errors in the // a legal token sequence. To be sure there are no syntax errors in the
// source (and not just the token sequence corresponding to the source) // source (and not just the token sequence corresponding to the source)
// both the parser and scanner error count must be 0. // both the parser and scanner error count must be 0.
// //
func Parse(scanner Scanner, err ErrorHandler, mode Mode, flags uint) (*ast.Package, int) { func Parse(scanner Scanner, err ErrorHandler, mode uint) (*ast.Package, int) {
// initialize parser state // initialize parser state
var p parser; var p parser;
p.scanner = scanner; p.scanner = scanner;
p.err = err; p.err = err;
p.trace = flags & Trace != 0; p.mode = mode;
p.trace = mode & Trace != 0; // for convenience (p.trace is used frequently)
p.comments.Init(0); p.comments.Init(0);
p.next(); p.next();
// parse program // parse program
return p.parsePackage(mode), p.errorCount; pak := p.parsePackage();
return pak, p.errorCount;
} }
...@@ -591,6 +591,15 @@ func (P *Printer) DoBinaryExpr(x *ast.BinaryExpr) { ...@@ -591,6 +591,15 @@ func (P *Printer) DoBinaryExpr(x *ast.BinaryExpr) {
} }
func (P *Printer) DoKeyValueExpr(x *ast.KeyValueExpr) {
P.Expr(x.Key);
P.separator = blank;
P.Token(x.Colon, token.COLON);
P.separator = blank;
P.Expr(x.Value);
}
func (P *Printer) DoStarExpr(x *ast.StarExpr) { func (P *Printer) DoStarExpr(x *ast.StarExpr) {
P.Token(x.Pos(), token.MUL); P.Token(x.Pos(), token.MUL);
P.Expr(x.X); P.Expr(x.X);
...@@ -721,9 +730,14 @@ func (P *Printer) DoEllipsis(x *ast.Ellipsis) { ...@@ -721,9 +730,14 @@ func (P *Printer) DoEllipsis(x *ast.Ellipsis) {
func (P *Printer) DoArrayType(x *ast.ArrayType) { func (P *Printer) DoArrayType(x *ast.ArrayType) {
P.Token(x.Pos(), token.LBRACK); P.Token(x.Pos(), token.LBRACK);
if x.Len != nil { P.Expr(x.Len);
P.Expr(x.Len); P.Token(nopos, token.RBRACK);
} P.Expr(x.Elt);
}
func (P *Printer) DoSliceType(x *ast.SliceType) {
P.Token(x.Pos(), token.LBRACK);
P.Token(nopos, token.RBRACK); P.Token(nopos, token.RBRACK);
P.Expr(x.Elt); P.Expr(x.Elt);
} }
...@@ -751,11 +765,6 @@ func (P *Printer) DoInterfaceType(x *ast.InterfaceType) { ...@@ -751,11 +765,6 @@ func (P *Printer) DoInterfaceType(x *ast.InterfaceType) {
} }
func (P *Printer) DoSliceType(x *ast.SliceType) {
unimplemented();
}
func (P *Printer) DoMapType(x *ast.MapType) { func (P *Printer) DoMapType(x *ast.MapType) {
P.Token(x.Pos(), token.MAP); P.Token(x.Pos(), token.MAP);
P.separator = blank; P.separator = blank;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment