mirror of
https://github.com/golang/go
synced 2024-09-24 05:20:13 -06: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:
parent
5a5784977a
commit
592dbb2d0a
@ -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,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;
|
||||
SEND;
|
||||
RECV;
|
||||
@ -54,80 +191,6 @@ const /* channel mode */ (
|
||||
|
||||
|
||||
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.
|
||||
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 *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) 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 *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;
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
|
||||
for P.tok == token.STRING {
|
||||
y := &ast.BasicLit{P.loc, P.tok, P.val};
|
||||
P.next();
|
||||
x = &ast.ConcatExpr{x, y};
|
||||
if P.tok != token.STRING {
|
||||
panic();
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
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()};
|
||||
|
||||
} 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);
|
||||
// selector
|
||||
sel := P.parseIdent();
|
||||
return &ast.Selector{x, sel, period};
|
||||
}
|
||||
|
||||
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 {
|
||||
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);
|
||||
}
|
||||
P.expect(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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
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);
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user