1
0
mirror of https://github.com/golang/go synced 2024-11-11 23:10:23 -07:00

daily snapshot:

- first part of AST cleaned up and documented
- tons of related cleanups and adjustments

R=r
OCL=26430
CL=26430
This commit is contained in:
Robert Griesemer 2009-03-17 18:41:35 -07:00
parent 5a5784977a
commit 592dbb2d0a
3 changed files with 425 additions and 278 deletions

View File

@ -15,17 +15,13 @@ type (
Block struct; Block struct;
Expr interface; Expr interface;
Decl interface; Decl interface;
ExprVisitor interface;
Signature struct;
) )
// ---------------------------------------------------------------------------- // TODO rename scanner.Location to scanner.Position, possibly factor out
// Support type Position scanner.Location
func assert(pred bool) {
if !pred {
panic("assertion failed");
}
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -44,9 +40,150 @@ type CommentGroup []*Comment
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Expressions // Expressions and types
const /* channel mode */ (
// All expression nodes implement the Expr interface.
type Expr interface {
// For a (dynamic) node type X, calling Visit with an expression
// visitor v invokes the node-specific DoX function of the visitor.
//
Visit(v ExprVisitor);
// Pos returns the (beginning) position of the expression.
Pos() Position;
};
// An expression is represented by a tree consisting of one
// or several of the following concrete expression nodes.
//
type (
// A BadExpr node is a placeholder node for expressions containing
// syntax errors for which not correct expression tree can be created.
//
BadExpr struct {
Pos_ Position; // bad expression position
};
// An Ident node represents an identifier (identifier).
Ident struct {
Str string; // identifier string (e.g. foobar)
Pos_ Position; // identifier position
};
// An basic literal is represented by a BasicLit node.
BasicLit struct {
Tok int; // literal token
Lit []byte; // literal string
Pos_ Position; // literal string position
};
// A sequence of string literals (StringLit) is represented
// by a StringLit node.
//
StringLit struct {
Strings []*BasicLit; // sequence of strings
};
// A function literal (FunctionLit) is represented by a FunctionLit node.
FunctionLit struct {
Typ *Signature; // function signature
Body *Block; // function body
Func Position; // position of "func" keyword
};
// A composite literal (CompositeLit) is represented by a CompositeLit node.
CompositeLit struct {
Typ Expr; // literal type
Elts []Expr; // list of composite elements
Lbrace, Rbrace Position; // positions of "{" and "}"
};
// A parenthesized expression is represented by a Group node.
Group struct {
X Expr; // parenthesized expression
Lparen, Rparen Position; // positions of "(" and ")"
};
// A primary expression followed by a selector is represented
// by a Selector node.
//
Selector struct {
X Expr; // primary expression
Sel *Ident; // field selector
Period Position; // position of "."
};
// A primary expression followed by an index is represented
// by an Index node.
//
Index struct {
X Expr; // primary expression
Index Expr; // index expression
Lbrack, Rbrack Position; // positions of "[" and "]"
};
// A primary expression followed by a slice is represented
// by a Slice node.
//
Slice struct {
X Expr; // primary expression
Beg, End Expr; // slice range
Lbrack, Colon, Rbrack Position; // positions of "[", ":", and "]"
};
// A primary expression followed by a type assertion is represented
// by a TypeAssertion node.
//
TypeAssertion struct {
X Expr; // primary expression
Typ Expr; // asserted type
Period, Lparen, Rparen Position; // positions of ".", "(", and ")"
};
// A primary expression followed by an argument list is represented
// by a Call node.
//
Call struct {
Fun Expr; // function expression
Args []Expr; // function arguments
Lparen, Rparen Position; // positions of "(" and ")"
};
// A unary expression (UnaryExpr) is represented by a UnaryExpr node.
UnaryExpr struct {
Op int; // operator token
X Expr; // operand
Pos_ Position; // operator position
};
// A binary expression (BinaryExpr) is represented by a BinaryExpr node.
BinaryExpr struct {
Op int; // operator token
X, Y Expr; // left and right operand
Pos_ Position; // operator position
};
)
// The direction of a channel type is indicated by one
// of the following constants.
//
const /* channel direction */ (
FULL = iota; FULL = iota;
SEND; SEND;
RECV; RECV;
@ -54,80 +191,6 @@ const /* channel mode */ (
type ( type (
ExprVisitor interface;
Signature struct;
Expr interface {
Loc() scanner.Location;
Visit(v ExprVisitor);
};
BadExpr struct {
Loc_ scanner.Location;
};
Ident struct {
Loc_ scanner.Location;
Str string;
};
BinaryExpr struct {
Loc_ scanner.Location;
Tok int;
X, Y Expr;
};
UnaryExpr struct {
Loc_ scanner.Location;
Tok int;
X Expr;
};
// TODO this should probably just be a list instead
ConcatExpr struct {
X, Y Expr;
};
BasicLit struct {
Loc_ scanner.Location;
Tok int;
Val []byte;
};
FunctionLit struct {
Loc_ scanner.Location; // location of "func"
Typ *Signature;
Body *Block;
};
Group struct {
Loc_ scanner.Location; // location of "("
X Expr;
};
Selector struct {
Loc_ scanner.Location; // location of "."
X Expr;
Sel *Ident;
};
TypeGuard struct {
Loc_ scanner.Location; // location of "."
X Expr;
Typ Expr;
};
Index struct {
Loc_ scanner.Location; // location of "["
X, I Expr;
};
Call struct {
Loc_ scanner.Location; // location of "(" or "{"
Tok int;
F, Args Expr
};
// Type literals are treated like expressions. // Type literals are treated like expressions.
Ellipsis struct { // neither a type nor an expression Ellipsis struct { // neither a type nor an expression
Loc_ scanner.Location; Loc_ scanner.Location;
@ -189,26 +252,30 @@ type (
ChannelType struct { ChannelType struct {
Loc_ scanner.Location; // location of "chan" or "<-" Loc_ scanner.Location; // location of "chan" or "<-"
Mode int; Dir int;
Val Expr; Val Expr;
}; };
) )
type ExprVisitor interface { type ExprVisitor interface {
// Expressions
DoBadExpr(x *BadExpr); DoBadExpr(x *BadExpr);
DoIdent(x *Ident); DoIdent(x *Ident);
DoBinaryExpr(x *BinaryExpr);
DoUnaryExpr(x *UnaryExpr);
DoConcatExpr(x *ConcatExpr);
DoBasicLit(x *BasicLit); DoBasicLit(x *BasicLit);
DoStringLit(x *StringLit);
DoFunctionLit(x *FunctionLit); DoFunctionLit(x *FunctionLit);
DoCompositeLit(x *CompositeLit);
DoGroup(x *Group); DoGroup(x *Group);
DoSelector(x *Selector); DoSelector(x *Selector);
DoTypeGuard(x *TypeGuard);
DoIndex(x *Index); DoIndex(x *Index);
DoSlice(x *Slice);
DoTypeAssertion(x *TypeAssertion);
DoCall(x *Call); DoCall(x *Call);
DoUnaryExpr(x *UnaryExpr);
DoBinaryExpr(x *BinaryExpr);
// Types
DoEllipsis(x *Ellipsis); DoEllipsis(x *Ellipsis);
DoTypeType(x *TypeType); DoTypeType(x *TypeType);
DoArrayType(x *ArrayType); DoArrayType(x *ArrayType);
@ -222,44 +289,47 @@ type ExprVisitor interface {
} }
// TODO replace these with an embedded field func (x *BadExpr) Pos() Position { return x.Pos_; }
func (x *BadExpr) Loc() scanner.Location { return x.Loc_; } func (x *Ident) Pos() Position { return x.Pos_; }
func (x *Ident) Loc() scanner.Location { return x.Loc_; } func (x *BasicLit) Pos() Position { return x.Pos_; }
func (x *BinaryExpr) Loc() scanner.Location { return x.Loc_; } func (x *StringLit) Pos() Position { return x.Strings[0].Pos(); }
func (x *UnaryExpr) Loc() scanner.Location { return x.Loc_; } func (x *FunctionLit) Pos() Position { return x.Func; }
func (x *ConcatExpr) Loc() scanner.Location { return x.X.Loc(); } func (x *CompositeLit) Pos() Position { return x.Typ.Pos(); }
func (x *BasicLit) Loc() scanner.Location { return x.Loc_; } func (x *Group) Pos() Position { return x.Lparen; }
func (x *FunctionLit) Loc() scanner.Location { return x.Loc_; } func (x *Selector) Pos() Position { return x.X.Pos(); }
func (x *Group) Loc() scanner.Location { return x.Loc_; } func (x *Index) Pos() Position { return x.X.Pos(); }
func (x *Selector) Loc() scanner.Location { return x.Loc_; } func (x *Slice) Pos() Position { return x.X.Pos(); }
func (x *TypeGuard) Loc() scanner.Location { return x.Loc_; } func (x *TypeAssertion) Pos() Position { return x.X.Pos(); }
func (x *Index) Loc() scanner.Location { return x.Loc_; } func (x *Call) Pos() Position { return x.Fun.Pos(); }
func (x *Call) Loc() scanner.Location { return x.Loc_; } func (x *UnaryExpr) Pos() Position { return x.Pos_; }
func (x *BinaryExpr) Pos() Position { return x.X.Pos(); }
func (x *Ellipsis) Loc() scanner.Location { return x.Loc_; } func (x *Ellipsis) Pos() Position { return x.Loc_; }
func (x *TypeType) Loc() scanner.Location { return x.Loc_; } func (x *TypeType) Pos() Position { return x.Loc_; }
func (x *ArrayType) Loc() scanner.Location { return x.Loc_; } func (x *ArrayType) Pos() Position { return x.Loc_; }
func (x *StructType) Loc() scanner.Location { return x.Loc_; } func (x *StructType) Pos() Position { return x.Loc_; }
func (x *PointerType) Loc() scanner.Location { return x.Loc_; } func (x *PointerType) Pos() Position { return x.Loc_; }
func (x *FunctionType) Loc() scanner.Location { return x.Loc_; } func (x *FunctionType) Pos() Position { return x.Loc_; }
func (x *InterfaceType) Loc() scanner.Location { return x.Loc_; } func (x *InterfaceType) Pos() Position { return x.Loc_; }
func (x *SliceType) Loc() scanner.Location { return x.Loc_; } func (x *SliceType) Pos() Position { return x.Loc_; }
func (x *MapType) Loc() scanner.Location { return x.Loc_; } func (x *MapType) Pos() Position { return x.Loc_; }
func (x *ChannelType) Loc() scanner.Location { return x.Loc_; } func (x *ChannelType) Pos() Position { return x.Loc_; }
func (x *BadExpr) Visit(v ExprVisitor) { v.DoBadExpr(x); } func (x *BadExpr) Visit(v ExprVisitor) { v.DoBadExpr(x); }
func (x *Ident) Visit(v ExprVisitor) { v.DoIdent(x); } func (x *Ident) Visit(v ExprVisitor) { v.DoIdent(x); }
func (x *BinaryExpr) Visit(v ExprVisitor) { v.DoBinaryExpr(x); }
func (x *UnaryExpr) Visit(v ExprVisitor) { v.DoUnaryExpr(x); }
func (x *ConcatExpr) Visit(v ExprVisitor) { v.DoConcatExpr(x); }
func (x *BasicLit) Visit(v ExprVisitor) { v.DoBasicLit(x); } func (x *BasicLit) Visit(v ExprVisitor) { v.DoBasicLit(x); }
func (x *StringLit) Visit(v ExprVisitor) { v.DoStringLit(x); }
func (x *FunctionLit) Visit(v ExprVisitor) { v.DoFunctionLit(x); } func (x *FunctionLit) Visit(v ExprVisitor) { v.DoFunctionLit(x); }
func (x *CompositeLit) Visit(v ExprVisitor) { v.DoCompositeLit(x); }
func (x *Group) Visit(v ExprVisitor) { v.DoGroup(x); } func (x *Group) Visit(v ExprVisitor) { v.DoGroup(x); }
func (x *Selector) Visit(v ExprVisitor) { v.DoSelector(x); } func (x *Selector) Visit(v ExprVisitor) { v.DoSelector(x); }
func (x *TypeGuard) Visit(v ExprVisitor) { v.DoTypeGuard(x); }
func (x *Index) Visit(v ExprVisitor) { v.DoIndex(x); } func (x *Index) Visit(v ExprVisitor) { v.DoIndex(x); }
func (x *Slice) Visit(v ExprVisitor) { v.DoSlice(x); }
func (x *TypeAssertion) Visit(v ExprVisitor) { v.DoTypeAssertion(x); }
func (x *Call) Visit(v ExprVisitor) { v.DoCall(x); } func (x *Call) Visit(v ExprVisitor) { v.DoCall(x); }
func (x *UnaryExpr) Visit(v ExprVisitor) { v.DoUnaryExpr(x); }
func (x *BinaryExpr) Visit(v ExprVisitor) { v.DoBinaryExpr(x); }
func (x *Ellipsis) Visit(v ExprVisitor) { v.DoEllipsis(x); } func (x *Ellipsis) Visit(v ExprVisitor) { v.DoEllipsis(x); }
func (x *TypeType) Visit(v ExprVisitor) { v.DoTypeType(x); } func (x *TypeType) Visit(v ExprVisitor) { v.DoTypeType(x); }
@ -290,7 +360,9 @@ type Block struct {
func NewBlock(loc scanner.Location, tok int) *Block { func NewBlock(loc scanner.Location, tok int) *Block {
assert(tok == token.LBRACE || tok == token.COLON); if tok != token.LBRACE && tok != token.COLON {
panic();
}
var end scanner.Location; var end scanner.Location;
return &Block{loc, tok, vector.New(0), end}; return &Block{loc, tok, vector.New(0), end};
} }
@ -322,7 +394,7 @@ type (
ExpressionStat struct { ExpressionStat struct {
Loc scanner.Location; // location of Tok Loc scanner.Location; // location of Tok
Tok int; // INC, DEC, RETURN, GO, DEFER Tok int; // GO, DEFER
Expr Expr; Expr Expr;
}; };

View File

@ -21,6 +21,10 @@ import (
) )
// TODO rename Position to scanner.Position, possibly factor out
type Position scanner.Location
// A Parser holds the parser's internal state while processing // A Parser holds the parser's internal state while processing
// a given text. It can be allocated as part of another data // a given text. It can be allocated as part of another data
// structure but must be initialized via Init before use. // structure but must be initialized via Init before use.
@ -37,7 +41,7 @@ type Parser struct {
last_comment ast.CommentGroup; last_comment ast.CommentGroup;
// The next token // The next token
loc scanner.Location; // token location loc Position; // token location
tok int; // one token look-ahead tok int; // one token look-ahead
val []byte; // token value val []byte; // token value
@ -49,7 +53,7 @@ type Parser struct {
// When we don't have a location use noloc. // When we don't have a location use noloc.
// TODO make sure we always have a location. // TODO make sure we always have a location.
var noloc scanner.Location; var noloc Position;
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -182,12 +186,12 @@ func (P *Parser) Init(scanner *scanner.Scanner, err scanner.ErrorHandler, trace
} }
func (P *Parser) error(loc scanner.Location, msg string) { func (P *Parser) error(loc Position, msg string) {
P.err.Error(loc, msg); P.err.Error(loc, msg);
} }
func (P *Parser) expect(tok int) { func (P *Parser) expect(tok int) Position {
if P.tok != tok { if P.tok != tok {
msg := "expected '" + token.TokenString(tok) + "', found '" + token.TokenString(P.tok) + "'"; msg := "expected '" + token.TokenString(tok) + "', found '" + token.TokenString(P.tok) + "'";
if token.IsLiteral(P.tok) { if token.IsLiteral(P.tok) {
@ -195,7 +199,9 @@ func (P *Parser) expect(tok int) {
} }
P.error(P.loc, msg); P.error(P.loc, msg);
} }
loc := P.loc;
P.next(); // make progress in any case P.next(); // make progress in any case
return loc;
} }
@ -214,13 +220,13 @@ func (P *Parser) parseIdent() *ast.Ident {
} }
if P.tok == token.IDENT { if P.tok == token.IDENT {
x := &ast.Ident{P.loc, string(P.val)}; x := &ast.Ident{string(P.val), P.loc};
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.loc, ""}; return &ast.Ident{"", P.loc};
} }
@ -254,13 +260,13 @@ func (P *Parser) parseExpressionList() []ast.Expr {
} }
list := vector.New(0); list := vector.New(0);
list.Push(P.parseExpression(1)); // TODO should use a const instead of 1 list.Push(P.parseExpression(1));
for P.tok == token.COMMA { for P.tok == token.COMMA {
P.next(); P.next();
list.Push(P.parseExpression(1)); // TODO should use a const instead of 1 list.Push(P.parseExpression(1));
} }
// convert vector // convert list
exprs := make([]ast.Expr, list.Len()); exprs := make([]ast.Expr, list.Len());
for i := 0; i < list.Len(); i++ { for i := 0; i < list.Len(); i++ {
exprs[i] = list.At(i).(ast.Expr); exprs[i] = list.At(i).(ast.Expr);
@ -303,10 +309,10 @@ func (P *Parser) parseQualifiedIdent() ast.Expr {
var x ast.Expr = P.parseIdent(); var x ast.Expr = P.parseIdent();
for P.tok == token.PERIOD { for P.tok == token.PERIOD {
loc := P.loc; pos := P.loc;
P.next(); P.next();
y := P.parseIdent(); sel := P.parseIdent();
x = &ast.Selector{loc, x, y}; x = &ast.Selector{x, sel, pos};
} }
return x; return x;
@ -548,7 +554,7 @@ func (P *Parser) parseInterfaceType() *ast.InterfaceType {
} }
loc := P.loc; loc := P.loc;
var end scanner.Location; var end Position;
var methods []*ast.Field; var methods []*ast.Field;
P.expect(token.INTERFACE); P.expect(token.INTERFACE);
@ -633,7 +639,7 @@ func (P *Parser) parseFieldDecl() *ast.Field {
if ident, is_ident := list.At(i).(*ast.Ident); is_ident { if ident, is_ident := list.At(i).(*ast.Ident); is_ident {
idents[i] = ident; idents[i] = ident;
} else { } else {
P.error(list.At(i).(ast.Expr).Loc(), "identifier expected"); P.error(list.At(i).(ast.Expr).Pos(), "identifier expected");
} }
} }
} else { } else {
@ -656,7 +662,7 @@ func (P *Parser) parseStructType() ast.Expr {
} }
loc := P.loc; loc := P.loc;
var end scanner.Location; var end Position;
var fields []*ast.Field; var fields []*ast.Field;
P.expect(token.STRUCT); P.expect(token.STRUCT);
@ -719,11 +725,11 @@ func (P *Parser) tryType() ast.Expr {
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.LPAREN: case token.LPAREN:
loc := P.loc; lparen := P.loc;
P.next(); P.next();
t := P.parseType(); x := P.parseType();
P.expect(token.RPAREN); rparen := P.expect(token.RPAREN);
return &ast.Group{loc, t}; return &ast.Group{x, lparen, rparen};
} }
// no type found // no type found
@ -786,14 +792,14 @@ func (P *Parser) parseFunctionLit() ast.Expr {
defer un(trace(P, "FunctionLit")); defer un(trace(P, "FunctionLit"));
} }
loc := P.loc; pos := P.loc;
P.expect(token.FUNC); P.expect(token.FUNC);
typ := P.parseSignature(); typ := P.parseSignature();
P.expr_lev++; P.expr_lev++;
body := P.parseBlock(token.LBRACE); body := P.parseBlock(token.LBRACE);
P.expr_lev--; P.expr_lev--;
return &ast.FunctionLit{loc, typ, body}; return &ast.FunctionLit{typ, body, pos};
} }
@ -802,16 +808,23 @@ func (P *Parser) parseStringLit() ast.Expr {
defer un(trace(P, "StringLit")); defer un(trace(P, "StringLit"));
} }
var x ast.Expr = &ast.BasicLit{P.loc, P.tok, P.val}; if P.tok != token.STRING {
P.expect(token.STRING); // always satisfied panic();
for P.tok == token.STRING {
y := &ast.BasicLit{P.loc, P.tok, P.val};
P.next();
x = &ast.ConcatExpr{x, y};
} }
return x; list := vector.New(0);
for P.tok == token.STRING {
list.Push(&ast.BasicLit{token.STRING, P.val, P.loc});
P.next();
}
// convert list
strings := make([]*ast.BasicLit, list.Len());
for i := 0; i < list.Len(); i++ {
strings[i] = list.At(i).(*ast.BasicLit);
}
return &ast.StringLit{strings};
} }
@ -825,7 +838,7 @@ func (P *Parser) parseOperand() ast.Expr {
return P.parseIdent(); return P.parseIdent();
case token.INT, token.FLOAT, token.CHAR: case token.INT, token.FLOAT, token.CHAR:
x := &ast.BasicLit{P.loc, P.tok, P.val}; x := &ast.BasicLit{P.tok, P.val, P.loc};
P.next(); P.next();
return x; return x;
@ -833,13 +846,13 @@ func (P *Parser) parseOperand() ast.Expr {
return P.parseStringLit(); return P.parseStringLit();
case token.LPAREN: case token.LPAREN:
loc := P.loc; lparen := P.loc;
P.next(); P.next();
P.expr_lev++; P.expr_lev++;
x := P.parseExpression(1); x := P.parseExpression(1);
P.expr_lev--; P.expr_lev--;
P.expect(token.RPAREN); rparen := P.expect(token.RPAREN);
return &ast.Group{loc, x}; return &ast.Group{x, lparen, rparen};
case token.FUNC: case token.FUNC:
return P.parseFunctionLit(); return P.parseFunctionLit();
@ -858,51 +871,74 @@ func (P *Parser) parseOperand() ast.Expr {
} }
func (P *Parser) parseSelectorOrTypeGuard(x ast.Expr) ast.Expr { func (P *Parser) parseSelectorOrTypeAssertion(x ast.Expr) ast.Expr {
if P.trace { if P.trace {
defer un(trace(P, "SelectorOrTypeGuard")); defer un(trace(P, "SelectorOrTypeAssertion"));
} }
loc := P.loc; period := P.expect(token.PERIOD);
P.expect(token.PERIOD);
if P.tok == token.IDENT { if P.tok == token.IDENT {
x = &ast.Selector{loc, x, P.parseIdent()}; // selector
sel := P.parseIdent();
} else { return &ast.Selector{x, sel, period};
P.expect(token.LPAREN);
var typ ast.Expr;
if P.tok == token.TYPE {
typ = &ast.TypeType{P.loc};
P.next();
} else {
typ = P.parseType();
}
x = &ast.TypeGuard{loc, x, typ};
P.expect(token.RPAREN);
} }
return x; // type assertion
lparen := P.expect(token.LPAREN);
var typ ast.Expr;
if P.tok == token.TYPE {
typ = &ast.TypeType{P.loc};
P.next();
} else {
typ = P.parseType();
}
rparen := P.expect(token.RPAREN);
return &ast.TypeAssertion{x, typ, period, lparen, rparen};
} }
func (P *Parser) parseIndex(x ast.Expr) ast.Expr { func (P *Parser) parseIndexOrSlice(x ast.Expr) ast.Expr {
if P.trace { if P.trace {
defer un(trace(P, "IndexOrSlice")); defer un(trace(P, "IndexOrSlice"));
} }
loc := P.loc; lbrack := P.expect(token.LBRACK);
P.expect(token.LBRACK);
P.expr_lev++; P.expr_lev++;
i := P.parseExpression(0); index := P.parseExpression(1);
P.expr_lev--; P.expr_lev--;
P.expect(token.RBRACK);
return &ast.Index{loc, x, i}; if P.tok == token.RBRACK {
// index
rbrack := P.loc;
P.next();
return &ast.Index{x, index, lbrack, rbrack};
}
// slice
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};
} }
func (P *Parser) parseBinaryExpr(prec1 int) ast.Expr func (P *Parser) parseCall(fun ast.Expr) *ast.Call {
if P.trace {
defer un(trace(P, "Call"));
}
lparen := P.expect(token.LPAREN);
var args []ast.Expr;
if P.tok != token.RPAREN {
args = P.parseExpressionList();
}
rparen := P.expect(token.RPAREN);
return &ast.Call{fun, args, lparen, rparen};
}
func (P *Parser) parseCompositeElements(close int) ast.Expr { func (P *Parser) parseCompositeElements(close int) ast.Expr {
x := P.parseExpression(0); x := P.parseExpression(0);
@ -912,7 +948,7 @@ func (P *Parser) parseCompositeElements(close int) ast.Expr {
// first element determines mode // first element determines mode
singles := true; singles := true;
if t, is_binary := x.(*ast.BinaryExpr); is_binary && t.Tok == token.COLON { if t, is_binary := x.(*ast.BinaryExpr); is_binary && t.Op == token.COLON {
singles = false; singles = false;
} }
@ -921,20 +957,20 @@ func (P *Parser) parseCompositeElements(close int) ast.Expr {
y := P.parseExpression(0); y := P.parseExpression(0);
if singles { if singles {
if t, is_binary := y.(*ast.BinaryExpr); is_binary && t.Tok == token.COLON { if t, is_binary := y.(*ast.BinaryExpr); is_binary && t.Op == token.COLON {
P.error(t.X.Loc(), "single value expected; found pair"); P.error(t.X.Pos(), "single value expected; found pair");
} }
} else { } else {
if t, is_binary := y.(*ast.BinaryExpr); !is_binary || t.Tok != token.COLON { if t, is_binary := y.(*ast.BinaryExpr); !is_binary || t.Op != token.COLON {
P.error(y.Loc(), "key:value pair expected; found single value"); P.error(y.Pos(), "key:value pair expected; found single value");
} }
} }
if last == nil { if last == nil {
last = &ast.BinaryExpr{loc, token.COMMA, x, y}; last = &ast.BinaryExpr{token.COMMA, x, y, loc};
x = last; x = last;
} else { } else {
last.Y = &ast.BinaryExpr{loc, token.COMMA, last.Y, y}; last.Y = &ast.BinaryExpr{token.COMMA, last.Y, y, loc};
last = last.Y.(*ast.BinaryExpr); last = last.Y.(*ast.BinaryExpr);
} }
@ -951,20 +987,64 @@ func (P *Parser) parseCompositeElements(close int) ast.Expr {
} }
func (P *Parser) parseCallOrCompositeLit(f ast.Expr, open, close int) ast.Expr { func (P *Parser) parseElementList() []ast.Expr {
if P.trace { if P.trace {
defer un(trace(P, "CallOrCompositeLit")); defer un(trace(P, "ElementList"));
} }
loc := P.loc; list := vector.New(0);
P.expect(open); singles := true;
var args ast.Expr; for P.tok != token.RBRACE {
if P.tok != close { x := P.parseExpression(0);
args = P.parseCompositeElements(close); if list.Len() == 0 {
} // first element determines syntax for remaining elements
P.expect(close); if t, is_binary := x.(*ast.BinaryExpr); is_binary && t.Op == 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 {
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");
}
}
}
return &ast.Call{loc, open, f, args}; list.Push(x);
if P.tok == token.COMMA {
P.next();
} else {
break;
}
}
// convert list
elts := make([]ast.Expr, list.Len());
for i := 0; i < list.Len(); i++ {
elts[i] = list.At(i).(ast.Expr);
}
return elts;
}
func (P *Parser) parseCompositeLit(typ ast.Expr) ast.Expr {
if P.trace {
defer un(trace(P, "CompositeLit"));
}
lbrace := P.expect(token.LBRACE);
var elts []ast.Expr;
if P.tok != token.RBRACE {
elts = P.parseElementList();
}
rbrace := P.expect(token.RBRACE);
return &ast.CompositeLit{typ, elts, lbrace, rbrace};
} }
@ -976,13 +1056,12 @@ 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.parseSelectorOrTypeGuard(x); case token.PERIOD: x = P.parseSelectorOrTypeAssertion(x);
case token.LBRACK: x = P.parseIndex(x); case token.LBRACK: x = P.parseIndexOrSlice(x);
// TODO fix once we have decided on literal/conversion syntax case token.LPAREN: x = P.parseCall(x);
case token.LPAREN: x = P.parseCallOrCompositeLit(x, token.LPAREN, token.RPAREN);
case token.LBRACE: case token.LBRACE:
if P.expr_lev >= 0 { if P.expr_lev >= 0 {
x = P.parseCallOrCompositeLit(x, token.LBRACE, token.RBRACE); x = P.parseCompositeLit(x);
} else { } else {
return x; return x;
} }
@ -1006,17 +1085,7 @@ func (P *Parser) parseUnaryExpr() ast.Expr {
loc, tok := P.loc, P.tok; loc, tok := P.loc, P.tok;
P.next(); P.next();
y := P.parseUnaryExpr(); y := P.parseUnaryExpr();
return &ast.UnaryExpr{loc, tok, y}; return &ast.UnaryExpr{tok, y, loc};
/*
if lit, ok := y.(*ast.TypeLit); ok && tok == token.MUL {
// pointer type
t := ast.NewType(pos, ast.POINTER);
t.Elt = lit.Typ;
return &ast.TypeLit{t};
} else {
return &ast.UnaryExpr{loc, tok, y};
}
*/
} }
return P.parsePrimaryExpr(); return P.parsePrimaryExpr();
@ -1034,7 +1103,7 @@ func (P *Parser) parseBinaryExpr(prec1 int) ast.Expr {
loc, tok := P.loc, P.tok; loc, tok := P.loc, P.tok;
P.next(); P.next();
y := P.parseBinaryExpr(prec + 1); y := P.parseBinaryExpr(prec + 1);
x = &ast.BinaryExpr{loc, tok, x, y}; x = &ast.BinaryExpr{tok, x, y, loc};
} }
} }
@ -1070,7 +1139,6 @@ func (P *Parser) parseSimpleStat(mode int) ast.Stat {
defer un(trace(P, "SimpleStat")); defer un(trace(P, "SimpleStat"));
} }
loc := P.loc;
x := P.parseExpressionList(); x := P.parseExpressionList();
switch P.tok { switch P.tok {
@ -1123,8 +1191,8 @@ func (P *Parser) parseSimpleStat(mode int) ast.Stat {
} }
default: default:
if len(x) != 1 { if len(x) > 1 {
P.error(loc, "only one expression allowed"); P.error(x[0].Pos(), "only one expression allowed");
} }
if P.tok == token.INC || P.tok == token.DEC { if P.tok == token.INC || P.tok == token.DEC {
@ -1134,7 +1202,7 @@ func (P *Parser) parseSimpleStat(mode int) ast.Stat {
} }
// TODO change ILLEGAL -> NONE // TODO change ILLEGAL -> NONE
return &ast.ExpressionStat{loc, token.ILLEGAL, x[0]}; return &ast.ExpressionStat{x[0].Pos(), token.ILLEGAL, x[0]};
} }
unreachable(); unreachable();
@ -1267,14 +1335,14 @@ func (P *Parser) asIdent(x ast.Expr) *ast.Ident {
if name, ok := x.(*ast.Ident); ok { if name, ok := x.(*ast.Ident); ok {
return name; return name;
} }
P.error(x.Loc(), "identifier expected"); P.error(x.Pos(), "identifier expected");
return &ast.Ident{noloc, "BAD"}; return &ast.Ident{"BAD", noloc};
} }
func (P *Parser) isTypeSwitch(init ast.Stat) (lhs *ast.Ident, rhs ast.Expr) { func (P *Parser) isTypeSwitch(init ast.Stat) (lhs *ast.Ident, rhs ast.Expr) {
if assign, ok := init.(*ast.AssignmentStat); ok { if assign, ok := init.(*ast.AssignmentStat); ok {
if guard, ok := assign.Rhs.(*ast.TypeGuard); ok { if guard, ok := assign.Rhs.(*ast.TypeAssertion); ok {
if tmp, ok := guard.Typ.(*ast.TypeType); ok { if tmp, ok := guard.Typ.(*ast.TypeType); ok {
// we appear to have a type switch // we appear to have a type switch
// TODO various error checks // TODO various error checks
@ -1436,7 +1504,7 @@ func (P *Parser) parseStatement() ast.Stat {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Declarations // Declarations
func (P *Parser) parseImportSpec(loc scanner.Location) *ast.ImportDecl { func (P *Parser) parseImportSpec(loc Position) *ast.ImportDecl {
if P.trace { if P.trace {
defer un(trace(P, "ImportSpec")); defer un(trace(P, "ImportSpec"));
} }
@ -1460,7 +1528,7 @@ func (P *Parser) parseImportSpec(loc scanner.Location) *ast.ImportDecl {
} }
func (P *Parser) parseConstSpec(loc scanner.Location, comment ast.CommentGroup) *ast.ConstDecl { func (P *Parser) parseConstSpec(loc Position, comment ast.CommentGroup) *ast.ConstDecl {
if P.trace { if P.trace {
defer un(trace(P, "ConstSpec")); defer un(trace(P, "ConstSpec"));
} }
@ -1477,7 +1545,7 @@ func (P *Parser) parseConstSpec(loc scanner.Location, comment ast.CommentGroup)
} }
func (P *Parser) parseTypeSpec(loc scanner.Location, comment ast.CommentGroup) *ast.TypeDecl { func (P *Parser) parseTypeSpec(loc Position, comment ast.CommentGroup) *ast.TypeDecl {
if P.trace { if P.trace {
defer un(trace(P, "TypeSpec")); defer un(trace(P, "TypeSpec"));
} }
@ -1489,7 +1557,7 @@ func (P *Parser) parseTypeSpec(loc scanner.Location, comment ast.CommentGroup) *
} }
func (P *Parser) parseVarSpec(loc scanner.Location, comment ast.CommentGroup) *ast.VarDecl { func (P *Parser) parseVarSpec(loc Position, comment ast.CommentGroup) *ast.VarDecl {
if P.trace { if P.trace {
defer un(trace(P, "VarSpec")); defer un(trace(P, "VarSpec"));
} }
@ -1506,7 +1574,7 @@ func (P *Parser) parseVarSpec(loc scanner.Location, comment ast.CommentGroup) *a
} }
func (P *Parser) parseSpec(loc scanner.Location, comment ast.CommentGroup, keyword int) ast.Decl { func (P *Parser) parseSpec(loc Position, comment ast.CommentGroup, keyword int) ast.Decl {
switch keyword { switch keyword {
case token.IMPORT: return P.parseImportSpec(loc); case token.IMPORT: return P.parseImportSpec(loc);
case token.CONST: return P.parseConstSpec(loc, comment); case token.CONST: return P.parseConstSpec(loc, comment);

View File

@ -409,7 +409,7 @@ func (P *Printer) Error(loc scanner.Location, tok int, msg string) {
// HTML support // HTML support
func (P *Printer) HtmlIdentifier(x *ast.Ident) { func (P *Printer) HtmlIdentifier(x *ast.Ident) {
P.String(x.Loc_, x.Str); P.String(x.Pos_, x.Str);
/* /*
obj := x.Obj; obj := x.Obj;
if P.html && obj.Kind != symbolTable.NONE { if P.html && obj.Kind != symbolTable.NONE {
@ -576,26 +576,17 @@ func (P *Printer) DoIdent(x *ast.Ident) {
func (P *Printer) DoBinaryExpr(x *ast.BinaryExpr) { func (P *Printer) DoBinaryExpr(x *ast.BinaryExpr) {
if x.Tok == token.COMMA { prec := token.Precedence(x.Op);
// (don't use binary expression printing because of different spacing) if prec < P.prec {
P.Expr(x.X); P.Token(noloc, token.LPAREN);
P.Token(x.Loc_, token.COMMA); }
P.separator = blank; P.Expr1(x.X, prec);
P.state = inside_list; P.separator = blank;
P.Expr(x.Y); P.Token(x.Pos_, x.Op);
} else { P.separator = blank;
prec := token.Precedence(x.Tok); P.Expr1(x.Y, prec);
if prec < P.prec { if prec < P.prec {
P.Token(noloc, token.LPAREN); P.Token(noloc, token.RPAREN);
}
P.Expr1(x.X, prec);
P.separator = blank;
P.Token(x.Loc_, x.Tok);
P.separator = blank;
P.Expr1(x.Y, prec);
if prec < P.prec {
P.Token(noloc, token.RPAREN);
}
} }
} }
@ -605,10 +596,7 @@ func (P *Printer) DoUnaryExpr(x *ast.UnaryExpr) {
if prec < P.prec { if prec < P.prec {
P.Token(noloc, token.LPAREN); P.Token(noloc, token.LPAREN);
} }
P.Token(x.Loc_, x.Tok); P.Token(x.Pos_, x.Op);
if x.Tok == token.RANGE {
P.separator = blank;
}
P.Expr1(x.X, prec); P.Expr1(x.X, prec);
if prec < P.prec { if prec < P.prec {
P.Token(noloc, token.RPAREN); P.Token(noloc, token.RPAREN);
@ -616,21 +604,24 @@ func (P *Printer) DoUnaryExpr(x *ast.UnaryExpr) {
} }
func (P *Printer) DoConcatExpr(x *ast.ConcatExpr) { func (P *Printer) DoBasicLit(x *ast.BasicLit) {
P.Expr1(x.X, token.HighestPrec); // TODO get rid of string conversion here
P.separator = blank; P.String(x.Pos_, string(x.Lit));
P.Expr1(x.Y, token.HighestPrec);
} }
func (P *Printer) DoBasicLit(x *ast.BasicLit) { func (P *Printer) DoStringLit(x *ast.StringLit) {
// TODO get rid of string conversion here for i, x := range x.Strings {
P.String(x.Loc_, string(x.Val)); if i > 0 {
P.separator = blank;
}
P.DoBasicLit(x);
}
} }
func (P *Printer) DoFunctionLit(x *ast.FunctionLit) { func (P *Printer) DoFunctionLit(x *ast.FunctionLit) {
P.Token(x.Loc_, token.FUNC); P.Token(x.Func, token.FUNC);
P.Signature(x.Typ); P.Signature(x.Typ);
P.separator = blank; P.separator = blank;
P.Block(x.Body, true); P.Block(x.Body, true);
@ -639,44 +630,59 @@ func (P *Printer) DoFunctionLit(x *ast.FunctionLit) {
func (P *Printer) DoGroup(x *ast.Group) { func (P *Printer) DoGroup(x *ast.Group) {
P.Token(x.Loc_, token.LPAREN); P.Token(x.Lparen, token.LPAREN);
P.Expr(x.X); P.Expr(x.X);
P.Token(noloc, token.RPAREN); P.Token(x.Rparen, token.RPAREN);
} }
func (P *Printer) DoSelector(x *ast.Selector) { func (P *Printer) DoSelector(x *ast.Selector) {
P.Expr1(x.X, token.HighestPrec); P.Expr1(x.X, token.HighestPrec);
P.Token(x.Loc_, token.PERIOD); P.Token(x.Period, token.PERIOD);
P.Expr1(x.Sel, token.HighestPrec); P.Expr1(x.Sel, token.HighestPrec);
} }
func (P *Printer) DoTypeGuard(x *ast.TypeGuard) { func (P *Printer) DoTypeAssertion(x *ast.TypeAssertion) {
P.Expr1(x.X, token.HighestPrec); P.Expr1(x.X, token.HighestPrec);
P.Token(x.Loc_, token.PERIOD); P.Token(x.Period, token.PERIOD);
P.Token(noloc, token.LPAREN); P.Token(x.Lparen, token.LPAREN);
P.Expr(x.Typ); P.Expr(x.Typ);
P.Token(noloc, token.RPAREN); P.Token(x.Rparen, token.RPAREN);
} }
func (P *Printer) DoIndex(x *ast.Index) { func (P *Printer) DoIndex(x *ast.Index) {
P.Expr1(x.X, token.HighestPrec); P.Expr1(x.X, token.HighestPrec);
P.Token(x.Loc_, token.LBRACK); P.Token(x.Lbrack, token.LBRACK);
P.Expr1(x.I, 0); P.Expr(x.Index);
P.Token(noloc, token.RBRACK); P.Token(x.Rbrack, token.RBRACK);
}
func (P *Printer) DoSlice(x *ast.Slice) {
P.Expr1(x.X, token.HighestPrec);
P.Token(x.Lbrack, token.LBRACK);
P.Expr(x.Beg);
P.Token(x.Colon, token.COLON);
P.Expr(x.End);
P.Token(x.Rbrack, token.RBRACK);
} }
func (P *Printer) DoCall(x *ast.Call) { func (P *Printer) DoCall(x *ast.Call) {
P.Expr1(x.F, token.HighestPrec); P.Expr1(x.Fun, token.HighestPrec);
P.Token(x.Loc_, x.Tok); P.Token(x.Lparen, token.LPAREN);
P.Expr(x.Args); P.Exprs(x.Args);
switch x.Tok { P.Token(x.Rparen, token.RPAREN);
case token.LPAREN: P.Token(noloc, token.RPAREN); }
case token.LBRACE: P.Token(noloc, token.RBRACE);
}
func (P *Printer) DoCompositeLit(x *ast.CompositeLit) {
P.Expr1(x.Typ, token.HighestPrec);
P.Token(x.Lbrace, token.LBRACE);
P.Exprs(x.Elts);
P.Token(x.Rbrace, token.RBRACE);
} }
@ -744,7 +750,7 @@ func (P *Printer) DoMapType(x *ast.MapType) {
func (P *Printer) DoChannelType(x *ast.ChannelType) { func (P *Printer) DoChannelType(x *ast.ChannelType) {
switch x.Mode { switch x.Dir {
case ast.FULL: case ast.FULL:
P.Token(x.Loc_, token.CHAN); P.Token(x.Loc_, token.CHAN);
case ast.RECV: case ast.RECV:
@ -1079,11 +1085,12 @@ func (P *Printer) DoImportDecl(d *ast.ImportDecl) {
if d.Name != nil { if d.Name != nil {
P.Expr(d.Name); P.Expr(d.Name);
} else { } else {
P.String(d.Path.Loc(), ""); // flush pending ';' separator/newlines P.String(d.Path.Pos(), ""); // flush pending ';' separator/newlines
} }
P.separator = tab; P.separator = tab;
if lit, is_lit := d.Path.(*ast.BasicLit); is_lit && lit.Tok == token.STRING { if lit, is_lit := d.Path.(*ast.StringLit); is_lit {
P.HtmlPackageName(lit.Loc_, string(lit.Val)); // TODO incorrect (string lit could be a list of strings)
P.HtmlPackageName(lit.Pos(), string(lit.Strings[0].Lit));
} else { } else {
// we should only reach here for strange imports // we should only reach here for strange imports
// import "foo" "bar" // import "foo" "bar"