summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Griesemer <gri@golang.org>2009-03-17 18:41:35 -0700
committerRobert Griesemer <gri@golang.org>2009-03-17 18:41:35 -0700
commit064cd49c722ae84641f81a74ac4460820af68514 (patch)
treebab0604f2ba5be4c8f2c56bc8ac37798996ed877
parentc8f94017eb1b054c30c16ec40fa9f6e8cd23e2e1 (diff)
downloadgolang-064cd49c722ae84641f81a74ac4460820af68514.tar.gz
daily snapshot:
- first part of AST cleaned up and documented - tons of related cleanups and adjustments R=r OCL=26430 CL=26430
-rw-r--r--usr/gri/pretty/ast.go268
-rw-r--r--usr/gri/pretty/parser.go268
-rw-r--r--usr/gri/pretty/printer.go115
3 files changed, 399 insertions, 252 deletions
diff --git a/usr/gri/pretty/ast.go b/usr/gri/pretty/ast.go
index 5cc5308f1..142b87501 100644
--- a/usr/gri/pretty/ast.go
+++ b/usr/gri/pretty/ast.go
@@ -15,17 +15,13 @@ type (
Block struct;
Expr interface;
Decl interface;
+ ExprVisitor interface;
+ Signature struct;
)
-// ----------------------------------------------------------------------------
-// Support
-
-func assert(pred bool) {
- if !pred {
- panic("assertion failed");
- }
-}
+// TODO rename scanner.Location to scanner.Position, possibly factor out
+type Position scanner.Location
// ----------------------------------------------------------------------------
@@ -44,90 +40,157 @@ type CommentGroup []*Comment
// ----------------------------------------------------------------------------
-// Expressions
+// Expressions and types
-const /* channel mode */ (
- FULL = iota;
- SEND;
- RECV;
-)
+
+// 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 (
- ExprVisitor interface;
- Signature struct;
-
- Expr interface {
- Loc() scanner.Location;
- Visit(v ExprVisitor);
- };
-
+ // A BadExpr node is a placeholder node for expressions containing
+ // syntax errors for which not correct expression tree can be created.
+ //
BadExpr struct {
- Loc_ scanner.Location;
+ Pos_ Position; // bad expression position
};
+
+ // An Ident node represents an identifier (identifier).
Ident struct {
- Loc_ scanner.Location;
- Str string;
+ Str string; // identifier string (e.g. foobar)
+ Pos_ Position; // identifier position
};
- BinaryExpr struct {
- Loc_ scanner.Location;
- Tok int;
- X, Y Expr;
- };
- UnaryExpr struct {
- Loc_ scanner.Location;
- Tok int;
- X Expr;
+ // An basic literal is represented by a BasicLit node.
+ BasicLit struct {
+ Tok int; // literal token
+ Lit []byte; // literal string
+ Pos_ Position; // literal string position
};
- // TODO this should probably just be a list instead
- ConcatExpr struct {
- X, Y Expr;
- };
- BasicLit struct {
- Loc_ scanner.Location;
- Tok int;
- Val []byte;
+ // 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 {
- Loc_ scanner.Location; // location of "func"
- Typ *Signature;
- Body *Block;
+ 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 {
- Loc_ scanner.Location; // location of "("
- X Expr;
+ 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 {
- Loc_ scanner.Location; // location of "."
- X Expr;
- Sel *Ident;
+ X Expr; // primary expression
+ Sel *Ident; // field selector
+ Period Position; // position of "."
};
- TypeGuard struct {
- Loc_ scanner.Location; // location of "."
- X Expr;
- Typ Expr;
- };
+ // A primary expression followed by an index is represented
+ // by an Index node.
+ //
Index struct {
- Loc_ scanner.Location; // location of "["
- X, I Expr;
+ 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 {
- Loc_ scanner.Location; // location of "(" or "{"
- Tok int;
- F, Args Expr
+ 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;
+ SEND;
+ RECV;
+)
+
+
+type (
// Type literals are treated like expressions.
Ellipsis struct { // neither a type nor an expression
Loc_ scanner.Location;
@@ -189,26 +252,30 @@ type (
ChannelType struct {
Loc_ scanner.Location; // location of "chan" or "<-"
- Mode int;
+ Dir int;
Val Expr;
};
)
type ExprVisitor interface {
+ // Expressions
DoBadExpr(x *BadExpr);
DoIdent(x *Ident);
- DoBinaryExpr(x *BinaryExpr);
- DoUnaryExpr(x *UnaryExpr);
- DoConcatExpr(x *ConcatExpr);
DoBasicLit(x *BasicLit);
+ DoStringLit(x *StringLit);
DoFunctionLit(x *FunctionLit);
+ DoCompositeLit(x *CompositeLit);
DoGroup(x *Group);
DoSelector(x *Selector);
- DoTypeGuard(x *TypeGuard);
DoIndex(x *Index);
+ DoSlice(x *Slice);
+ DoTypeAssertion(x *TypeAssertion);
DoCall(x *Call);
-
+ DoUnaryExpr(x *UnaryExpr);
+ DoBinaryExpr(x *BinaryExpr);
+
+ // Types
DoEllipsis(x *Ellipsis);
DoTypeType(x *TypeType);
DoArrayType(x *ArrayType);
@@ -222,44 +289,47 @@ type ExprVisitor interface {
}
-// TODO replace these with an embedded field
-func (x *BadExpr) Loc() scanner.Location { return x.Loc_; }
-func (x *Ident) Loc() scanner.Location { return x.Loc_; }
-func (x *BinaryExpr) Loc() scanner.Location { return x.Loc_; }
-func (x *UnaryExpr) Loc() scanner.Location { return x.Loc_; }
-func (x *ConcatExpr) Loc() scanner.Location { return x.X.Loc(); }
-func (x *BasicLit) Loc() scanner.Location { return x.Loc_; }
-func (x *FunctionLit) Loc() scanner.Location { return x.Loc_; }
-func (x *Group) Loc() scanner.Location { return x.Loc_; }
-func (x *Selector) Loc() scanner.Location { return x.Loc_; }
-func (x *TypeGuard) Loc() scanner.Location { return x.Loc_; }
-func (x *Index) Loc() scanner.Location { return x.Loc_; }
-func (x *Call) Loc() scanner.Location { return x.Loc_; }
-
-func (x *Ellipsis) Loc() scanner.Location { return x.Loc_; }
-func (x *TypeType) Loc() scanner.Location { return x.Loc_; }
-func (x *ArrayType) Loc() scanner.Location { return x.Loc_; }
-func (x *StructType) Loc() scanner.Location { return x.Loc_; }
-func (x *PointerType) Loc() scanner.Location { return x.Loc_; }
-func (x *FunctionType) Loc() scanner.Location { return x.Loc_; }
-func (x *InterfaceType) Loc() scanner.Location { return x.Loc_; }
-func (x *SliceType) Loc() scanner.Location { return x.Loc_; }
-func (x *MapType) Loc() scanner.Location { return x.Loc_; }
-func (x *ChannelType) Loc() scanner.Location { return x.Loc_; }
+func (x *BadExpr) Pos() Position { return x.Pos_; }
+func (x *Ident) Pos() Position { return x.Pos_; }
+func (x *BasicLit) Pos() Position { return x.Pos_; }
+func (x *StringLit) Pos() Position { return x.Strings[0].Pos(); }
+func (x *FunctionLit) Pos() Position { return x.Func; }
+func (x *CompositeLit) Pos() Position { return x.Typ.Pos(); }
+func (x *Group) Pos() Position { return x.Lparen; }
+func (x *Selector) Pos() Position { return x.X.Pos(); }
+func (x *Index) Pos() Position { return x.X.Pos(); }
+func (x *Slice) Pos() Position { return x.X.Pos(); }
+func (x *TypeAssertion) Pos() Position { return x.X.Pos(); }
+func (x *Call) Pos() Position { return x.Fun.Pos(); }
+func (x *UnaryExpr) Pos() Position { return x.Pos_; }
+func (x *BinaryExpr) Pos() Position { return x.X.Pos(); }
+
+func (x *Ellipsis) Pos() Position { return x.Loc_; }
+func (x *TypeType) Pos() Position { return x.Loc_; }
+func (x *ArrayType) Pos() Position { return x.Loc_; }
+func (x *StructType) Pos() Position { return x.Loc_; }
+func (x *PointerType) Pos() Position { return x.Loc_; }
+func (x *FunctionType) Pos() Position { return x.Loc_; }
+func (x *InterfaceType) Pos() Position { return x.Loc_; }
+func (x *SliceType) Pos() Position { return x.Loc_; }
+func (x *MapType) Pos() Position { return x.Loc_; }
+func (x *ChannelType) Pos() Position { return x.Loc_; }
func (x *BadExpr) Visit(v ExprVisitor) { v.DoBadExpr(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 *StringLit) Visit(v ExprVisitor) { v.DoStringLit(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 *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 *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 *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 *TypeType) Visit(v ExprVisitor) { v.DoTypeType(x); }
@@ -290,7 +360,9 @@ type Block struct {
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;
return &Block{loc, tok, vector.New(0), end};
}
@@ -322,7 +394,7 @@ type (
ExpressionStat struct {
Loc scanner.Location; // location of Tok
- Tok int; // INC, DEC, RETURN, GO, DEFER
+ Tok int; // GO, DEFER
Expr Expr;
};
diff --git a/usr/gri/pretty/parser.go b/usr/gri/pretty/parser.go
index 5bfa8bfe5..ffe9615c9 100644
--- a/usr/gri/pretty/parser.go
+++ b/usr/gri/pretty/parser.go
@@ -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 given text. It can be allocated as part of another data
// structure but must be initialized via Init before use.
@@ -37,7 +41,7 @@ type Parser struct {
last_comment ast.CommentGroup;
// The next token
- loc scanner.Location; // token location
+ loc Position; // token location
tok int; // one token look-ahead
val []byte; // token value
@@ -49,7 +53,7 @@ type Parser struct {
// When we don't have a location use noloc.
// 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);
}
-func (P *Parser) expect(tok int) {
+func (P *Parser) expect(tok int) Position {
if P.tok != tok {
msg := "expected '" + token.TokenString(tok) + "', found '" + token.TokenString(P.tok) + "'";
if token.IsLiteral(P.tok) {
@@ -195,7 +199,9 @@ func (P *Parser) expect(tok int) {
}
P.error(P.loc, msg);
}
+ loc := P.loc;
P.next(); // make progress in any case
+ return loc;
}
@@ -214,13 +220,13 @@ func (P *Parser) parseIdent() *ast.Ident {
}
if P.tok == token.IDENT {
- x := &ast.Ident{P.loc, string(P.val)};
+ x := &ast.Ident{string(P.val), P.loc};
P.next();
return x;
}
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.Push(P.parseExpression(1)); // TODO should use a const instead of 1
+ list.Push(P.parseExpression(1));
for P.tok == token.COMMA {
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());
for i := 0; i < list.Len(); i++ {
exprs[i] = list.At(i).(ast.Expr);
@@ -303,10 +309,10 @@ func (P *Parser) parseQualifiedIdent() ast.Expr {
var x ast.Expr = P.parseIdent();
for P.tok == token.PERIOD {
- loc := P.loc;
+ pos := P.loc;
P.next();
- y := P.parseIdent();
- x = &ast.Selector{loc, x, y};
+ sel := P.parseIdent();
+ x = &ast.Selector{x, sel, pos};
}
return x;
@@ -548,7 +554,7 @@ func (P *Parser) parseInterfaceType() *ast.InterfaceType {
}
loc := P.loc;
- var end scanner.Location;
+ var end Position;
var methods []*ast.Field;
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 {
idents[i] = ident;
} else {
- P.error(list.At(i).(ast.Expr).Loc(), "identifier expected");
+ P.error(list.At(i).(ast.Expr).Pos(), "identifier expected");
}
}
} else {
@@ -656,7 +662,7 @@ func (P *Parser) parseStructType() ast.Expr {
}
loc := P.loc;
- var end scanner.Location;
+ var end Position;
var fields []*ast.Field;
P.expect(token.STRUCT);
@@ -719,11 +725,11 @@ func (P *Parser) tryType() ast.Expr {
case token.STRUCT: return P.parseStructType();
case token.MUL: return P.parsePointerType();
case token.LPAREN:
- loc := P.loc;
+ lparen := P.loc;
P.next();
- t := P.parseType();
- P.expect(token.RPAREN);
- return &ast.Group{loc, t};
+ x := P.parseType();
+ rparen := P.expect(token.RPAREN);
+ return &ast.Group{x, lparen, rparen};
}
// no type found
@@ -786,14 +792,14 @@ func (P *Parser) parseFunctionLit() ast.Expr {
defer un(trace(P, "FunctionLit"));
}
- loc := P.loc;
+ pos := P.loc;
P.expect(token.FUNC);
typ := P.parseSignature();
P.expr_lev++;
body := P.parseBlock(token.LBRACE);
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"));
}
- var x ast.Expr = &ast.BasicLit{P.loc, P.tok, P.val};
- P.expect(token.STRING); // always satisfied
+ if P.tok != token.STRING {
+ panic();
+ }
+ list := vector.New(0);
for P.tok == token.STRING {
- y := &ast.BasicLit{P.loc, P.tok, P.val};
+ list.Push(&ast.BasicLit{token.STRING, P.val, P.loc});
P.next();
- x = &ast.ConcatExpr{x, y};
}
- return x;
+ // 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();
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();
return x;
@@ -833,13 +846,13 @@ func (P *Parser) parseOperand() ast.Expr {
return P.parseStringLit();
case token.LPAREN:
- loc := P.loc;
+ lparen := P.loc;
P.next();
P.expr_lev++;
x := P.parseExpression(1);
P.expr_lev--;
- P.expect(token.RPAREN);
- return &ast.Group{loc, x};
+ rparen := P.expect(token.RPAREN);
+ return &ast.Group{x, lparen, rparen};
case token.FUNC:
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 {
- defer un(trace(P, "SelectorOrTypeGuard"));
+ defer un(trace(P, "SelectorOrTypeAssertion"));
}
- loc := P.loc;
- P.expect(token.PERIOD);
+ period := P.expect(token.PERIOD);
if P.tok == token.IDENT {
- x = &ast.Selector{loc, x, P.parseIdent()};
-
+ // 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();
} else {
- 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);
+ typ = P.parseType();
}
-
- return x;
+ 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 {
defer un(trace(P, "IndexOrSlice"));
}
- loc := P.loc;
- P.expect(token.LBRACK);
+ lbrack := P.expect(token.LBRACK);
P.expr_lev++;
- i := P.parseExpression(0);
+ index := P.parseExpression(1);
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 {
x := P.parseExpression(0);
@@ -912,7 +948,7 @@ func (P *Parser) parseCompositeElements(close int) ast.Expr {
// first element determines mode
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;
}
@@ -921,20 +957,20 @@ func (P *Parser) parseCompositeElements(close int) ast.Expr {
y := P.parseExpression(0);
if singles {
- if t, is_binary := y.(*ast.BinaryExpr); is_binary && t.Tok == token.COLON {
- P.error(t.X.Loc(), "single value expected; found pair");
+ 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.Tok != token.COLON {
- P.error(y.Loc(), "key:value pair expected; found single value");
+ 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{loc, token.COMMA, x, y};
+ last = &ast.BinaryExpr{token.COMMA, x, y, loc};
x = last;
} 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);
}
@@ -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 {
- defer un(trace(P, "CallOrCompositeLit"));
+ defer un(trace(P, "ElementList"));
}
- loc := P.loc;
- P.expect(open);
- var args ast.Expr;
- if P.tok != close {
- args = P.parseCompositeElements(close);
+ list := vector.New(0);
+ singles := true;
+ for P.tok != token.RBRACE {
+ 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 {
+ 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");
+ }
+ }
+ }
+
+ 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"));
}
- P.expect(close);
- return &ast.Call{loc, open, f, args};
+ 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();
for {
switch P.tok {
- case token.PERIOD: x = P.parseSelectorOrTypeGuard(x);
- case token.LBRACK: x = P.parseIndex(x);
- // TODO fix once we have decided on literal/conversion syntax
- case token.LPAREN: x = P.parseCallOrCompositeLit(x, token.LPAREN, token.RPAREN);
+ case token.PERIOD: x = P.parseSelectorOrTypeAssertion(x);
+ case token.LBRACK: x = P.parseIndexOrSlice(x);
+ case token.LPAREN: x = P.parseCall(x);
case token.LBRACE:
if P.expr_lev >= 0 {
- x = P.parseCallOrCompositeLit(x, token.LBRACE, token.RBRACE);
+ x = P.parseCompositeLit(x);
} else {
return x;
}
@@ -1006,17 +1085,7 @@ func (P *Parser) parseUnaryExpr() ast.Expr {
loc, tok := P.loc, P.tok;
P.next();
y := P.parseUnaryExpr();
- return &ast.UnaryExpr{loc, tok, y};
- /*
- 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 &ast.UnaryExpr{tok, y, loc};
}
return P.parsePrimaryExpr();
@@ -1034,7 +1103,7 @@ func (P *Parser) parseBinaryExpr(prec1 int) ast.Expr {
loc, tok := P.loc, P.tok;
P.next();
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"));
}
- loc := P.loc;
x := P.parseExpressionList();
switch P.tok {
@@ -1123,8 +1191,8 @@ func (P *Parser) parseSimpleStat(mode int) ast.Stat {
}
default:
- if len(x) != 1 {
- P.error(loc, "only one expression allowed");
+ if len(x) > 1 {
+ P.error(x[0].Pos(), "only one expression allowed");
}
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
- return &ast.ExpressionStat{loc, token.ILLEGAL, x[0]};
+ return &ast.ExpressionStat{x[0].Pos(), token.ILLEGAL, x[0]};
}
unreachable();
@@ -1267,14 +1335,14 @@ func (P *Parser) asIdent(x ast.Expr) *ast.Ident {
if name, ok := x.(*ast.Ident); ok {
return name;
}
- P.error(x.Loc(), "identifier expected");
- return &ast.Ident{noloc, "BAD"};
+ 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.TypeGuard); 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
@@ -1436,7 +1504,7 @@ func (P *Parser) parseStatement() ast.Stat {
// ----------------------------------------------------------------------------
// Declarations
-func (P *Parser) parseImportSpec(loc scanner.Location) *ast.ImportDecl {
+func (P *Parser) parseImportSpec(loc Position) *ast.ImportDecl {
if P.trace {
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 {
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 {
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 {
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 {
case token.IMPORT: return P.parseImportSpec(loc);
case token.CONST: return P.parseConstSpec(loc, comment);
diff --git a/usr/gri/pretty/printer.go b/usr/gri/pretty/printer.go
index 39e65cfab..ac8e646a6 100644
--- a/usr/gri/pretty/printer.go
+++ b/usr/gri/pretty/printer.go
@@ -409,7 +409,7 @@ func (P *Printer) Error(loc scanner.Location, tok int, msg string) {
// HTML support
func (P *Printer) HtmlIdentifier(x *ast.Ident) {
- P.String(x.Loc_, x.Str);
+ P.String(x.Pos_, x.Str);
/*
obj := x.Obj;
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) {
- if x.Tok == token.COMMA {
- // (don't use binary expression printing because of different spacing)
- P.Expr(x.X);
- P.Token(x.Loc_, token.COMMA);
- P.separator = blank;
- P.state = inside_list;
- P.Expr(x.Y);
- } else {
- prec := token.Precedence(x.Tok);
- if prec < P.prec {
- P.Token(noloc, token.LPAREN);
- }
- 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);
- }
+ prec := token.Precedence(x.Op);
+ if prec < P.prec {
+ P.Token(noloc, token.LPAREN);
+ }
+ P.Expr1(x.X, prec);
+ P.separator = blank;
+ P.Token(x.Pos_, x.Op);
+ 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 {
P.Token(noloc, token.LPAREN);
}
- P.Token(x.Loc_, x.Tok);
- if x.Tok == token.RANGE {
- P.separator = blank;
- }
+ P.Token(x.Pos_, x.Op);
P.Expr1(x.X, prec);
if prec < P.prec {
P.Token(noloc, token.RPAREN);
@@ -616,21 +604,24 @@ func (P *Printer) DoUnaryExpr(x *ast.UnaryExpr) {
}
-func (P *Printer) DoConcatExpr(x *ast.ConcatExpr) {
- P.Expr1(x.X, token.HighestPrec);
- P.separator = blank;
- P.Expr1(x.Y, token.HighestPrec);
+func (P *Printer) DoBasicLit(x *ast.BasicLit) {
+ // TODO get rid of string conversion here
+ P.String(x.Pos_, string(x.Lit));
}
-func (P *Printer) DoBasicLit(x *ast.BasicLit) {
- // TODO get rid of string conversion here
- P.String(x.Loc_, string(x.Val));
+func (P *Printer) DoStringLit(x *ast.StringLit) {
+ for i, x := range x.Strings {
+ if i > 0 {
+ P.separator = blank;
+ }
+ P.DoBasicLit(x);
+ }
}
func (P *Printer) DoFunctionLit(x *ast.FunctionLit) {
- P.Token(x.Loc_, token.FUNC);
+ P.Token(x.Func, token.FUNC);
P.Signature(x.Typ);
P.separator = blank;
P.Block(x.Body, true);
@@ -639,44 +630,59 @@ func (P *Printer) DoFunctionLit(x *ast.FunctionLit) {
func (P *Printer) DoGroup(x *ast.Group) {
- P.Token(x.Loc_, token.LPAREN);
+ P.Token(x.Lparen, token.LPAREN);
P.Expr(x.X);
- P.Token(noloc, token.RPAREN);
+ P.Token(x.Rparen, token.RPAREN);
}
func (P *Printer) DoSelector(x *ast.Selector) {
P.Expr1(x.X, token.HighestPrec);
- P.Token(x.Loc_, token.PERIOD);
+ P.Token(x.Period, token.PERIOD);
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.Token(x.Loc_, token.PERIOD);
- P.Token(noloc, token.LPAREN);
+ P.Token(x.Period, token.PERIOD);
+ P.Token(x.Lparen, token.LPAREN);
P.Expr(x.Typ);
- P.Token(noloc, token.RPAREN);
+ P.Token(x.Rparen, token.RPAREN);
}
func (P *Printer) DoIndex(x *ast.Index) {
P.Expr1(x.X, token.HighestPrec);
- P.Token(x.Loc_, token.LBRACK);
- P.Expr1(x.I, 0);
- P.Token(noloc, token.RBRACK);
+ P.Token(x.Lbrack, token.LBRACK);
+ P.Expr(x.Index);
+ 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) {
- P.Expr1(x.F, token.HighestPrec);
- P.Token(x.Loc_, x.Tok);
- P.Expr(x.Args);
- switch x.Tok {
- case token.LPAREN: P.Token(noloc, token.RPAREN);
- case token.LBRACE: P.Token(noloc, token.RBRACE);
- }
+ P.Expr1(x.Fun, token.HighestPrec);
+ P.Token(x.Lparen, token.LPAREN);
+ P.Exprs(x.Args);
+ P.Token(x.Rparen, token.RPAREN);
+}
+
+
+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) {
- switch x.Mode {
+ switch x.Dir {
case ast.FULL:
P.Token(x.Loc_, token.CHAN);
case ast.RECV:
@@ -1079,11 +1085,12 @@ func (P *Printer) DoImportDecl(d *ast.ImportDecl) {
if d.Name != nil {
P.Expr(d.Name);
} else {
- P.String(d.Path.Loc(), ""); // flush pending ';' separator/newlines
+ P.String(d.Path.Pos(), ""); // flush pending ';' separator/newlines
}
P.separator = tab;
- if lit, is_lit := d.Path.(*ast.BasicLit); is_lit && lit.Tok == token.STRING {
- P.HtmlPackageName(lit.Loc_, string(lit.Val));
+ if lit, is_lit := d.Path.(*ast.StringLit); is_lit {
+ // TODO incorrect (string lit could be a list of strings)
+ P.HtmlPackageName(lit.Pos(), string(lit.Strings[0].Lit));
} else {
// we should only reach here for strange imports
// import "foo" "bar"