diff --git a/usr/gri/pretty/ast.go b/usr/gri/pretty/ast.go
index 142b875016d..a963495c2f2 100644
--- a/usr/gri/pretty/ast.go
+++ b/usr/gri/pretty/ast.go
@@ -2,45 +2,55 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// The AST package declares the types used to represent
+// syntax trees for Go source files.
+//
package ast
import (
- "vector";
"token";
"scanner";
)
+// TODO rename Position to scanner.Position, possibly factor out
+type Position scanner.Location
+
+
+// TODO try to get rid of these
type (
Block struct;
- Expr interface;
- Decl interface;
- ExprVisitor interface;
Signature struct;
)
-// TODO rename scanner.Location to scanner.Position, possibly factor out
-type Position scanner.Location
-
-
// ----------------------------------------------------------------------------
-// Comments
+// Interfaces
+//
+// There are 3 main classes of nodes: Expressions and type nodes,
+// statement nodes, and declaration nodes. The node names usually
+// match the corresponding Go spec production names to which they
+// correspond. The node fields correspond to the individual parts
+// of the respective productions.
+//
+// Nodes contain selective position information: a position field
+// marking the beginning of the corresponding source text segment
+// if necessary; and specific position information for language
+// constructs where comments may be found between parts of the
+// construct (typically any larger, parenthesized subpart). The
+// position information is needed to properly position comments
+// when printing the construct.
-type Comment struct {
- Loc scanner.Location;
- EndLine int; // the line where the comment ends
- Text []byte;
-}
+// TODO: For comment positioning only the byte position and not
+// a complete Position field is needed. May be able to trim node
+// sizes a bit.
-// A CommentGroup is a sequence of consequtive comments
-// with no other tokens and no empty lines inbetween.
-type CommentGroup []*Comment
-
-
-// ----------------------------------------------------------------------------
-// Expressions and types
+type (
+ ExprVisitor interface;
+ StatVisitor interface;
+ DeclVisitor interface;
+)
// All expression nodes implement the Expr interface.
@@ -52,130 +62,161 @@ type Expr interface {
// Pos returns the (beginning) position of the expression.
Pos() Position;
-};
+}
+// All statement nodes implement the Stat interface.
+type Stat interface {
+ // For a (dynamic) node type X, calling Visit with a statement
+ // visitor v invokes the node-specific DoX function of the visitor.
+ //
+ Visit(v StatVisitor);
+
+ // Pos returns the (beginning) position of the statement.
+ Pos() Position;
+}
+
+
+// All declaration nodes implement the Decl interface.
+type Decl interface {
+ // For a (dynamic) node type X, calling Visit with a declaration
+ // visitor v invokes the node-specific DoX function of the visitor.
+ //
+ Visit(v DeclVisitor);
+
+ // Pos returns the (beginning) position of the declaration.
+ Pos() Position;
+}
+
+
+// ----------------------------------------------------------------------------
+// Comments
+
+// A Comment node represents a single //-style or /*-style comment.
+type Comment struct {
+ Pos_ Position; // beginning position of the comment
+ Text []byte; // the comment text (without '\n' for //-style comments)
+ EndLine int; // the line where the comment ends
+}
+
+
+// A Comments node represents a sequence of single comments
+// with no other tokens and no empty lines between.
+//
+type Comments []*Comment
+
+
+// ----------------------------------------------------------------------------
+// Expressions and types
+
// An expression is represented by a tree consisting of one
-// or several of the following concrete expression nodes.
+// or more 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.
+ // A BadExpr node is a placeholder for expressions containing
+ // syntax errors for which no correct expression nodes can be
+ // created.
//
BadExpr struct {
- Pos_ Position; // bad expression position
+ Pos_ Position; // beginning position of bad expression
};
-
- // An Ident node represents an identifier (identifier).
+ // An Ident node represents an identifier.
Ident struct {
- Str string; // identifier string (e.g. foobar)
Pos_ Position; // identifier position
+ Lit []byte; // identifier string (e.g. foobar)
};
-
- // An basic literal is represented by a BasicLit node.
+ // A BasicLit node represents a basic literal.
BasicLit struct {
- Tok int; // literal token
- Lit []byte; // literal string
Pos_ Position; // literal string position
+ Tok int; // literal token (INT, FLOAT, CHAR, STRING)
+ Lit []byte; // literal string
};
-
- // A sequence of string literals (StringLit) is represented
- // by a StringLit node.
- //
+ // A StringLit node represents a sequence of string literals.
StringLit struct {
Strings []*BasicLit; // sequence of strings
};
-
- // A function literal (FunctionLit) is represented by a FunctionLit node.
+ // A FunctionLit node represents a function literal.
FunctionLit struct {
+ Func Position; // position of "func" keyword
Typ *Signature; // function signature
Body *Block; // function body
- Func Position; // position of "func" keyword
};
-
- // A composite literal (CompositeLit) is represented by a CompositeLit node.
+ // A CompositeLit node represents a composite literal.
CompositeLit struct {
Typ Expr; // literal type
+ Lbrace Position; // position of "{"
Elts []Expr; // list of composite elements
- Lbrace, Rbrace Position; // positions of "{" and "}"
+ Rbrace Position; // position of "}"
};
-
- // A parenthesized expression is represented by a Group node.
- Group struct {
+ // A ParenExpr node represents a parenthesized expression.
+ ParenExpr struct {
+ Lparen Position; // position of "("
X Expr; // parenthesized expression
- Lparen, Rparen Position; // positions of "(" and ")"
+ Rparen Position; // position of ")"
};
-
- // A primary expression followed by a selector is represented
- // by a Selector node.
- //
- Selector struct {
+ // A SelectorExpr node represents a primary expression followed by a selector.
+ SelectorExpr 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 {
+ // An IndexExpr node represents a primary expression followed by an index.
+ IndexExpr 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 {
+ // A SliceExpr node represents a primary expression followed by a slice.
+ SliceExpr struct {
X Expr; // primary expression
- Beg, End Expr; // slice range
- Lbrack, Colon, Rbrack Position; // positions of "[", ":", and "]"
+ Begin, End Expr; // slice range
};
-
- // A primary expression followed by a type assertion is represented
- // by a TypeAssertion node.
+ // A TypeAssertExpr node represents a primary expression followed by a
+ // type assertion.
//
- TypeAssertion struct {
+ TypeAssertExpr 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 {
+ // A CallExpr node represents a primary expression followed by an argument list.
+ CallExpr struct {
Fun Expr; // function expression
+ Lparen Position; // position of "("
Args []Expr; // function arguments
- Lparen, Rparen Position; // positions of "(" and ")"
+ Rparen Position; // positions of ")"
};
-
- // A unary expression (UnaryExpr) is represented by a UnaryExpr node.
- UnaryExpr struct {
- Op int; // operator token
+ // A StarExpr node represents an expression of the form "*" Expression.
+ // Semantically it could be a unary "*" expression, or a pointer type.
+ StarExpr struct {
+ Star Position; // position of "*"
X Expr; // operand
- Pos_ Position; // operator position
};
+ // A UnaryExpr node represents a unary expression.
+ // Unary "*" expressions are represented via DerefExpr nodes.
+ //
+ UnaryExpr struct {
+ Pos_ Position; // token position
+ Tok int; // operator
+ X Expr; // operand
+ };
- // A binary expression (BinaryExpr) is represented by a BinaryExpr node.
+ // A BinaryExpr node represents a binary expression.
BinaryExpr struct {
- Op int; // operator token
- X, Y Expr; // left and right operand
- Pos_ Position; // operator position
+ X Expr; // left operand
+ Pos_ Position; // token position
+ Tok int; // operator
+ Y Expr; // right operand
};
)
@@ -183,81 +224,127 @@ type (
// The direction of a channel type is indicated by one
// of the following constants.
//
-const /* channel direction */ (
- FULL = iota;
- SEND;
+type ChanDir int
+const (
+ SEND ChanDir = 1 << iota;
RECV;
)
+// A type is represented by a tree consisting of one
+// or more of the following type-specific expression
+// nodes.
+//
type (
- // Type literals are treated like expressions.
+ // An Ellipsis node stands for the "..." type in a
+ // parameter list or the "..." length in an array type.
+ //
Ellipsis struct { // neither a type nor an expression
- Loc_ scanner.Location;
+ Pos_ Position; // position of "..."
};
- TypeType struct { // for type switches
- Loc_ scanner.Location; // location of "type"
- };
-
+ // An ArrayType node represents an array type.
ArrayType struct {
- Loc_ scanner.Location; // location of "["
- Len Expr;
- Elt Expr;
- };
-
- Field struct {
- Names []*Ident;
- Typ Expr;
- Tag Expr; // nil = no tag
- Comment CommentGroup;
+ Lbrack Position; // position of "["
+ Len Expr; // an Ellipsis node for [...]T array types
+ Elt Expr; // element type
};
+ // A SliceType node represents a slice type.
+ SliceType struct {
+ Lbrack Position; // position of "["
+ Elt Expr; // element type
+ };
+
+ // A Field represents a Field declaration list in a struct type,
+ // a method in an interface type, or a parameter declaration in
+ // a signature.
+ Field struct {
+ Doc Comments; // associated documentation (struct types only)
+ Names []*Ident; // field/method/parameter names; nil if anonymous field
+ Typ Expr; // field/method/parameter type
+ Tag Expr; // field tag; nil if no tag
+ };
+
+ // A StructType node represents a struct type.
StructType struct {
- Loc_ scanner.Location; // location of "struct"
- Fields []*Field;
- End scanner.Location; // location of "}"
+ Struct, Lbrace Position; // positions of "struct" keyword, "{"
+ Fields []*Field; // list of field declarations; nil if forward declaration
+ Rbrace Position; // position of "}"
};
-
- PointerType struct {
- Loc_ scanner.Location; // location of "*"
- Base Expr;
- };
-
+
+ // Note: pointer types are represented via StarExpr nodes.
+
+ // A signature node represents the parameter and result
+ // sections of a function type only.
+ //
Signature struct {
Params []*Field;
Result []*Field;
};
+ // A FunctionType node represents a function type.
FunctionType struct {
- Loc_ scanner.Location; // location of "func"
+ Func Position; // position of "func" keyword
Sig *Signature;
};
+ // An InterfaceType node represents an interface type.
InterfaceType struct {
- Loc_ scanner.Location; // location of "interface"
- Methods []*Field;
- End scanner.Location; // location of "}", End == 0 if forward declaration
+ Interface, Lbrace Position; // positions of "interface" keyword, "{"
+ Methods []*Field; // list of methods; nil if forward declaration
+ Rbrace Position; // position of "}"
};
- SliceType struct {
- Loc_ scanner.Location; // location of "["
- };
-
+ // A MapType node represents a map type.
MapType struct {
- Loc_ scanner.Location; // location of "map"
+ Map Position; // position of "map" keyword
Key Expr;
- Val Expr;
+ Value Expr;
};
-
+
+ // A ChannelType node represents a channel type.
ChannelType struct {
- Loc_ scanner.Location; // location of "chan" or "<-"
- Dir int;
- Val Expr;
+ Pos_ Position; // position of "chan" keyword or "<-" (whichever comes first)
+ Dir ChanDir;
+ Value Expr; // value type
};
)
+// Pos() implementations for all expression/type nodes.
+//
+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 *ParenExpr) Pos() Position { return x.Lparen; }
+func (x *SelectorExpr) Pos() Position { return x.X.Pos(); }
+func (x *IndexExpr) Pos() Position { return x.X.Pos(); }
+func (x *SliceExpr) Pos() Position { return x.X.Pos(); }
+func (x *TypeAssertExpr) Pos() Position { return x.X.Pos(); }
+func (x *CallExpr) Pos() Position { return x.Fun.Pos(); }
+func (x *StarExpr) Pos() Position { return x.Star; }
+func (x *UnaryExpr) Pos() Position { return x.Pos_; }
+func (x *BinaryExpr) Pos() Position { return x.X.Pos(); }
+
+func (x *Ellipsis) Pos() Position { return x.Pos_; }
+func (x *ArrayType) Pos() Position { return x.Lbrack; }
+func (x *SliceType) Pos() Position { return x.Lbrack; }
+func (x *StructType) Pos() Position { return x.Struct; }
+func (x *FunctionType) Pos() Position { return x.Func; }
+func (x *InterfaceType) Pos() Position { return x.Interface; }
+func (x *MapType) Pos() Position { return x.Map; }
+func (x *ChannelType) Pos() Position { return x.Pos_; }
+
+
+// All expression/type nodes implement a Visit method which takes
+// an ExprVisitor as argument. For a given node x of type X, and
+// an implementation v of an ExprVisitor, calling x.Visit(v) will
+// result in a call of v.DoX(x) (through a double-dispatch).
+//
type ExprVisitor interface {
// Expressions
DoBadExpr(x *BadExpr);
@@ -266,336 +353,391 @@ type ExprVisitor interface {
DoStringLit(x *StringLit);
DoFunctionLit(x *FunctionLit);
DoCompositeLit(x *CompositeLit);
- DoGroup(x *Group);
- DoSelector(x *Selector);
- DoIndex(x *Index);
- DoSlice(x *Slice);
- DoTypeAssertion(x *TypeAssertion);
- DoCall(x *Call);
+ DoParenExpr(x *ParenExpr);
+ DoSelectorExpr(x *SelectorExpr);
+ DoIndexExpr(x *IndexExpr);
+ DoSliceExpr(x *SliceExpr);
+ DoTypeAssertExpr(x *TypeAssertExpr);
+ DoCallExpr(x *CallExpr);
+ DoStarExpr(x *StarExpr);
DoUnaryExpr(x *UnaryExpr);
DoBinaryExpr(x *BinaryExpr);
- // Types
+ // Type expressions
DoEllipsis(x *Ellipsis);
- DoTypeType(x *TypeType);
DoArrayType(x *ArrayType);
+ DoSliceType(x *SliceType);
DoStructType(x *StructType);
- DoPointerType(x *PointerType);
DoFunctionType(x *FunctionType);
DoInterfaceType(x *InterfaceType);
- DoSliceType(x *SliceType);
DoMapType(x *MapType);
DoChannelType(x *ChannelType);
}
-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_; }
-
-
+// Visit() implementations for all expression/type nodes.
+//
func (x *BadExpr) Visit(v ExprVisitor) { v.DoBadExpr(x); }
func (x *Ident) Visit(v ExprVisitor) { v.DoIdent(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 *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 *ParenExpr) Visit(v ExprVisitor) { v.DoParenExpr(x); }
+func (x *SelectorExpr) Visit(v ExprVisitor) { v.DoSelectorExpr(x); }
+func (x *IndexExpr) Visit(v ExprVisitor) { v.DoIndexExpr(x); }
+func (x *SliceExpr) Visit(v ExprVisitor) { v.DoSliceExpr(x); }
+func (x *TypeAssertExpr) Visit(v ExprVisitor) { v.DoTypeAssertExpr(x); }
+func (x *CallExpr) Visit(v ExprVisitor) { v.DoCallExpr(x); }
+func (x *StarExpr) Visit(v ExprVisitor) { v.DoStarExpr(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); }
func (x *ArrayType) Visit(v ExprVisitor) { v.DoArrayType(x); }
+func (x *SliceType) Visit(v ExprVisitor) { v.DoSliceType(x); }
func (x *StructType) Visit(v ExprVisitor) { v.DoStructType(x); }
-func (x *PointerType) Visit(v ExprVisitor) { v.DoPointerType(x); }
func (x *FunctionType) Visit(v ExprVisitor) { v.DoFunctionType(x); }
func (x *InterfaceType) Visit(v ExprVisitor) { v.DoInterfaceType(x); }
-func (x *SliceType) Visit(v ExprVisitor) { v.DoSliceType(x); }
func (x *MapType) Visit(v ExprVisitor) { v.DoMapType(x); }
func (x *ChannelType) Visit(v ExprVisitor) { v.DoChannelType(x); }
// ----------------------------------------------------------------------------
// Blocks
-//
-// Syntactic constructs of the form:
+
+// A Block represents syntactic constructs of the form:
//
// "{" StatementList "}"
// ":" StatementList
-
+//
type Block struct {
- Loc scanner.Location;
+ Pos_ Position;
Tok int;
- List *vector.Vector;
- End scanner.Location; // location of closing "}" if present
-}
-
-
-func NewBlock(loc scanner.Location, tok int) *Block {
- if tok != token.LBRACE && tok != token.COLON {
- panic();
- }
- var end scanner.Location;
- return &Block{loc, tok, vector.New(0), end};
+ List []Stat;
+ Rparen Position; // position of closing "}" if present
}
// ----------------------------------------------------------------------------
// Statements
+// A statement is represented by a tree consisting of one
+// or more of the following concrete statement nodes.
+//
type (
- StatVisitor interface;
-
- Stat interface {
- Visit(v StatVisitor);
- };
-
+ // A BadStat node is a placeholder for statements containing
+ // syntax errors for which no correct statement nodes can be
+ // created.
+ //
BadStat struct {
- Loc scanner.Location;
+ Pos_ Position; // beginning position of bad statement
};
+ // A DeclStat node represents a declaration in a statement list.
+ DeclStat struct {
+ Decl Decl;
+ };
+
+ // An EmptyStat node represents an empty statement.
+ // The "position" of the empty statement is the position
+ // of the immediately preceeding semicolon.
+ //
+ EmptyStat struct {
+ Semicolon Position; // position of preceeding ";"
+ };
+
+ // A LabeledStat node represents a labeled statement.
LabeledStat struct {
- Loc scanner.Location; // location of ":"
Label *Ident;
Stat Stat;
};
- DeclarationStat struct {
- Decl Decl;
- };
-
- ExpressionStat struct {
- Loc scanner.Location; // location of Tok
- Tok int; // GO, DEFER
- Expr Expr;
- };
-
- AssignmentStat struct {
- Loc scanner.Location; // location of Tok
- Tok int; // assignment token
- Lhs, Rhs Expr;
- };
-
- TupleAssignStat struct {
- Loc scanner.Location; // location of Tok
- Tok int; // assignment token
- Lhs, Rhs []Expr;
+ // An ExprStat node represents a (stand-alone) expression
+ // in a statement list.
+ //
+ ExprStat struct {
+ X Expr; // expression
};
+ // An IncDecStat node represents an increment or decrement statement.
IncDecStat struct {
- Loc scanner.Location; // location of '++' or '--'
- Tok int; // token.INC or token.DEC
- Expr Expr;
+ X Expr;
+ Tok int; // INC or DEC
};
+ // An AssignmentStat node represents an assignment or
+ // a short variable declaration.
+ AssignmentStat struct {
+ Lhs []Expr;
+ Pos_ Position; // token position
+ Tok int; // assignment token, DEFINE
+ Rhs []Expr;
+ };
+
+ // A GoStat node represents a go statement.
+ GoStat struct {
+ Go Position; // position of "go" keyword
+ Call Expr;
+ };
+
+ // A DeferStat node represents a defer statement.
+ DeferStat struct {
+ Defer Position; // position of "defer" keyword
+ Call Expr;
+ };
+
+ // A ReturnStat node represents a return statement.
+ ReturnStat struct {
+ Return Position; // position of "return" keyword
+ Results []Expr;
+ };
+
+ // A ControlFlowStat node represents a break, continue, goto,
+ // or fallthrough statement.
+ //
+ ControlFlowStat struct {
+ Pos_ Position; // position of keyword
+ Tok int; // keyword token (BREAK, CONTINUE, GOTO, FALLTHROUGH)
+ Label *Ident;
+ };
+
+ // A CompositeStat node represents a braced statement list.
CompositeStat struct {
Body *Block;
};
+ // An IfStat node represents an if statement.
IfStat struct {
- Loc scanner.Location; // location of "if"
+ If Position; // position of "if" keyword
Init Stat;
Cond Expr;
Body *Block;
Else Stat;
};
-
- RangeClause struct { // appears only as Init stat in a ForStat
- Loc scanner.Location; // location of "=" or ":="
- Tok int; // token.ASSIGN or token.DEFINE
- Lhs []Expr;
- Rhs Expr;
+
+ // A CaseClause represents a case of an expression switch statement.
+ CaseClause struct {
+ Case Position; // position of "case" or "default" keyword
+ Values []Expr; // nil means default case
+ Body *Block;
};
+ // A SwitchStat node represents an expression switch statement.
+ SwitchStat struct {
+ Switch Position; // position of "switch" keyword
+ Init Stat;
+ Tag Expr;
+ Body *Block; // CaseClauses only
+ };
+
+ // A TypeCaseClause represents a case of a type switch statement.
+ TypeCaseClause struct {
+ Case Position; // position of "case" or "default" keyword
+ Typ Expr; // nil means default case
+ Body *Block;
+ };
+
+ // An TypeSwitchStat node represents a type switch statement.
+ TypeSwitchStat struct {
+ Switch Position; // position of "switch" keyword
+ Init Stat;
+ Assign Stat; // x := y.(type)
+ Body *Block; // TypeCaseClauses only
+ };
+
+ // A CommClause node represents a case of a select statement.
+ CommClause struct {
+ Case Position; // position of "case" or "default" keyword
+ Tok int; // ASSIGN, DEFINE (valid only if Lhs != nil)
+ Lhs, Rhs Expr; // Rhs == nil means default case
+ Body *Block;
+ };
+
+ // An SelectStat node represents a select statement.
+ SelectStat struct {
+ Select Position; // position of "select" keyword
+ Body *Block; // CommClauses only
+ };
+
+ // A ForStat represents a for statement.
ForStat struct {
- Loc scanner.Location; // location of "for"
+ For Position; // position of "for" keyword
Init Stat;
Cond Expr;
Post Stat;
Body *Block;
};
- TypeSwitchClause struct { // appears only as Init stat in a SwitchStat
- Loc scanner.Location; // location of ":="
- Lhs *Ident;
- Rhs Expr;
- };
-
- CaseClause struct {
- Loc scanner.Location; // location of "case" or "default"
- Values []Expr; // nil means default case
+ // A RangeStat represents a for statement with a range clause.
+ RangeStat struct {
+ For Position; // position of "for" keyword
+ Range Stat;
Body *Block;
};
-
- SwitchStat struct {
- Loc scanner.Location; // location of "switch"
- Init Stat;
- Tag Expr;
- Body *Block;
- };
-
- CommClause struct {
- Loc scanner.Location; // location of "case" or "default"
- Tok int; // token.ASSIGN, token.DEFINE (valid only if Lhs != nil)
- Lhs, Rhs Expr; // Rhs == nil means default case
- Body *Block;
- };
-
- SelectStat struct {
- Loc scanner.Location; // location of "select"
- Body *Block;
- };
-
- ControlFlowStat struct {
- Loc scanner.Location; // location of Tok
- Tok int; // BREAK, CONTINUE, GOTO, FALLTHROUGH
- Label *Ident; // if any, or nil
- };
-
- ReturnStat struct {
- Loc scanner.Location; // location of "return"
- Results []Expr;
- };
-
- EmptyStat struct {
- Loc scanner.Location; // location of ";"
- };
)
+// Pos() implementations for all statement nodes.
+//
+func (s *BadStat) Pos() Position { return s.Pos_; }
+func (s *DeclStat) Pos() Position { return s.Decl.Pos(); }
+func (s *EmptyStat) Pos() Position { return s.Semicolon; }
+func (s *LabeledStat) Pos() Position { return s.Label.Pos(); }
+func (s *ExprStat) Pos() Position { return s.X.Pos(); }
+func (s *IncDecStat) Pos() Position { return s.X.Pos(); }
+func (s *AssignmentStat) Pos() Position { return s.Lhs[0].Pos(); }
+func (s *GoStat) Pos() Position { return s.Go; }
+func (s *DeferStat) Pos() Position { return s.Defer; }
+func (s *ReturnStat) Pos() Position { return s.Return; }
+func (s *ControlFlowStat) Pos() Position { return s.Pos_; }
+func (s *CompositeStat) Pos() Position { return s.Body.Pos_; }
+func (s *IfStat) Pos() Position { return s.If; }
+func (s *CaseClause) Pos() Position { return s.Case; }
+func (s *SwitchStat) Pos() Position { return s.Switch; }
+func (s *TypeCaseClause) Pos() Position { return s.Case; }
+func (s *TypeSwitchStat) Pos() Position { return s.Switch; }
+func (s *CommClause) Pos() Position { return s.Case; }
+func (s *SelectStat) Pos() Position { return s.Select; }
+func (s *ForStat) Pos() Position { return s.For; }
+func (s *RangeStat) Pos() Position { return s.For; }
+
+
+// All statement nodes implement a Visit method which takes
+// a StatVisitor as argument. For a given node x of type X, and
+// an implementation v of a StatVisitor, calling x.Visit(v) will
+// result in a call of v.DoX(x) (through a double-dispatch).
+//
type StatVisitor interface {
DoBadStat(s *BadStat);
+ DoDeclStat(s *DeclStat);
+ DoEmptyStat(s *EmptyStat);
DoLabeledStat(s *LabeledStat);
- DoDeclarationStat(s *DeclarationStat);
- DoExpressionStat(s *ExpressionStat);
- DoAssignmentStat(s *AssignmentStat);
- DoTupleAssignStat(s *TupleAssignStat);
+ DoExprStat(s *ExprStat);
DoIncDecStat(s *IncDecStat);
+ DoAssignmentStat(s *AssignmentStat);
+ DoGoStat(s *GoStat);
+ DoDeferStat(s *DeferStat);
+ DoReturnStat(s *ReturnStat);
+ DoControlFlowStat(s *ControlFlowStat);
DoCompositeStat(s *CompositeStat);
DoIfStat(s *IfStat);
- DoRangeClause(s *RangeClause);
- DoForStat(s *ForStat);
- DoTypeSwitchClause(s *TypeSwitchClause);
DoCaseClause(s *CaseClause);
DoSwitchStat(s *SwitchStat);
+ DoTypeCaseClause(s *TypeCaseClause);
+ DoTypeSwitchStat(s *TypeSwitchStat);
DoCommClause(s *CommClause);
DoSelectStat(s *SelectStat);
- DoControlFlowStat(s *ControlFlowStat);
- DoReturnStat(s *ReturnStat);
- DoEmptyStat(s *EmptyStat);
+ DoForStat(s *ForStat);
+ DoRangeStat(s *RangeStat);
}
+// Visit() implementations for all statement nodes.
+//
func (s *BadStat) Visit(v StatVisitor) { v.DoBadStat(s); }
+func (s *DeclStat) Visit(v StatVisitor) { v.DoDeclStat(s); }
+func (s *EmptyStat) Visit(v StatVisitor) { v.DoEmptyStat(s); }
func (s *LabeledStat) Visit(v StatVisitor) { v.DoLabeledStat(s); }
-func (s *DeclarationStat) Visit(v StatVisitor) { v.DoDeclarationStat(s); }
-func (s *ExpressionStat) Visit(v StatVisitor) { v.DoExpressionStat(s); }
-func (s *AssignmentStat) Visit(v StatVisitor) { v.DoAssignmentStat(s); }
-func (s *TupleAssignStat) Visit(v StatVisitor) { v.DoTupleAssignStat(s); }
+func (s *ExprStat) Visit(v StatVisitor) { v.DoExprStat(s); }
func (s *IncDecStat) Visit(v StatVisitor) { v.DoIncDecStat(s); }
+func (s *AssignmentStat) Visit(v StatVisitor) { v.DoAssignmentStat(s); }
+func (s *GoStat) Visit(v StatVisitor) { v.DoGoStat(s); }
+func (s *DeferStat) Visit(v StatVisitor) { v.DoDeferStat(s); }
+func (s *ReturnStat) Visit(v StatVisitor) { v.DoReturnStat(s); }
+func (s *ControlFlowStat) Visit(v StatVisitor) { v.DoControlFlowStat(s); }
func (s *CompositeStat) Visit(v StatVisitor) { v.DoCompositeStat(s); }
func (s *IfStat) Visit(v StatVisitor) { v.DoIfStat(s); }
-func (s *RangeClause) Visit(v StatVisitor) { v.DoRangeClause(s); }
-func (s *ForStat) Visit(v StatVisitor) { v.DoForStat(s); }
-func (s *TypeSwitchClause) Visit(v StatVisitor) { v.DoTypeSwitchClause(s); }
func (s *CaseClause) Visit(v StatVisitor) { v.DoCaseClause(s); }
func (s *SwitchStat) Visit(v StatVisitor) { v.DoSwitchStat(s); }
+func (s *TypeCaseClause) Visit(v StatVisitor) { v.DoTypeCaseClause(s); }
+func (s *TypeSwitchStat) Visit(v StatVisitor) { v.DoTypeSwitchStat(s); }
func (s *CommClause) Visit(v StatVisitor) { v.DoCommClause(s); }
func (s *SelectStat) Visit(v StatVisitor) { v.DoSelectStat(s); }
-func (s *ControlFlowStat) Visit(v StatVisitor) { v.DoControlFlowStat(s); }
-func (s *ReturnStat) Visit(v StatVisitor) { v.DoReturnStat(s); }
-func (s *EmptyStat) Visit(v StatVisitor) { v.DoEmptyStat(s); }
+func (s *ForStat) Visit(v StatVisitor) { v.DoForStat(s); }
+func (s *RangeStat) Visit(v StatVisitor) { v.DoRangeStat(s); }
// ----------------------------------------------------------------------------
// Declarations
-type (
- DeclVisitor interface;
-
- Decl interface {
- Visit(v DeclVisitor);
- };
-
+// A declaration is represented by one of the following declaration nodes.
+//
+type (
+ // A BadDecl node is a placeholder for declarations containing
+ // syntax errors for which no correct declaration nodes can be
+ // created.
+ //
BadDecl struct {
- Loc scanner.Location;
+ Pos_ Position; // beginning position of bad declaration
};
ImportDecl struct {
- Loc scanner.Location; // if > 0: position of "import"
- Name *Ident;
- Path Expr;
+ Doc Comments; // associated documentation
+ Import Position; // position of "import" keyword
+ Name *Ident; // local package name or nil
+ Path *StringLit; // package path
};
-
+
ConstDecl struct {
- Loc scanner.Location; // if > 0: position of "const"
+ Doc Comments; // associated documentation
+ Const Position; // position of "const" keyword
Names []*Ident;
- Typ Expr;
+ Typ Expr; // constant type or nil
Values []Expr;
- Comment CommentGroup;
};
-
+
TypeDecl struct {
- Loc scanner.Location; // if > 0: position of "type"
+ Doc Comments; // associated documentation
+ Type Position; // position of "type" keyword
Name *Ident;
Typ Expr;
- Comment CommentGroup;
};
-
+
VarDecl struct {
- Loc scanner.Location; // if > 0: position of "var"
+ Doc Comments; // associated documentation
+ Var Position; // position of "var" keyword
Names []*Ident;
- Typ Expr;
+ Typ Expr; // variable type or nil
Values []Expr;
- Comment CommentGroup;
};
FuncDecl struct {
- Loc scanner.Location; // location of "func"
- Recv *Field;
- Name *Ident;
- Sig *Signature;
- Body *Block;
- Comment CommentGroup;
+ Doc Comments; // associated documentation
+ Func Position; // position of "func" keyword
+ Recv *Field; // receiver (methods) or nil (functions)
+ Name *Ident; // function/method name
+ Sig *Signature; // parameters and results
+ Body *Block; // function body or nil (forward declaration)
};
-
+
DeclList struct {
- Loc scanner.Location; // location of Tok
- Tok int;
- List []Decl;
- End scanner.Location;
+ Doc Comments; // associated documentation
+ Pos_ Position; // position of token
+ Tok int; // IMPORT, CONST, VAR, TYPE
+ Lparen Position; // position of '('
+ List []Decl; // the list of parenthesized declarations
+ Rparen Position; // position of ')'
};
)
+// Pos() implementations for all declaration nodes.
+//
+func (d *BadDecl) Pos() Position { return d.Pos_; }
+func (d *ImportDecl) Pos() Position { return d.Import; }
+func (d *ConstDecl) Pos() Position { return d.Const; }
+func (d *TypeDecl) Pos() Position { return d.Type; }
+func (d *VarDecl) Pos() Position { return d.Var; }
+func (d *FuncDecl) Pos() Position { return d.Func; }
+func (d *DeclList) Pos() Position { return d.Lparen; }
+
+
+// All declaration nodes implement a Visit method which takes
+// a DeclVisitor as argument. For a given node x of type X, and
+// an implementation v of a DeclVisitor, calling x.Visit(v) will
+// result in a call of v.DoX(x) (through a double-dispatch).
+//
type DeclVisitor interface {
DoBadDecl(d *BadDecl);
DoImportDecl(d *ImportDecl);
@@ -607,6 +749,8 @@ type DeclVisitor interface {
}
+// Visit() implementations for all declaration nodes.
+//
func (d *BadDecl) Visit(v DeclVisitor) { v.DoBadDecl(d); }
func (d *ImportDecl) Visit(v DeclVisitor) { v.DoImportDecl(d); }
func (d *ConstDecl) Visit(v DeclVisitor) { v.DoConstDecl(d); }
@@ -617,20 +761,13 @@ func (d *DeclList) Visit(v DeclVisitor) { v.DoDeclList(d); }
// ----------------------------------------------------------------------------
-// Program
+// Packages
-// TODO rename to Package
-type Program struct {
- Loc scanner.Location; // tok is token.PACKAGE
- Name *Ident;
- Decls []Decl;
- Comment CommentGroup;
- Comments []CommentGroup;
-}
-
-
-func NewProgram(loc scanner.Location) *Program {
- p := new(Program);
- p.Loc = loc;
- return p;
+// A Package node represents the root node of an AST.
+type Package struct {
+ Doc Comments; // associated documentation
+ Package Position; // position of "package" keyword
+ Name *Ident; // package name
+ Decls []Decl; // top-level declarations
+ Comments []*Comment; // list of unassociated comments
}
diff --git a/usr/gri/pretty/compilation.go b/usr/gri/pretty/compilation.go
index 5803f701b8d..8a9065ac97e 100644
--- a/usr/gri/pretty/compilation.go
+++ b/usr/gri/pretty/compilation.go
@@ -83,7 +83,7 @@ func (h *errorHandler) Error(loc scanner.Location, msg string) {
}
-func Compile(src_file string, flags *Flags) (*ast.Program, ErrorList) {
+func Compile(src_file string, flags *Flags) (*ast.Package, ErrorList) {
src, ok := Platform.ReadSourceFile(src_file);
if !ok {
print("cannot open ", src_file, "\n");
diff --git a/usr/gri/pretty/parser.go b/usr/gri/pretty/parser.go
index ffe9615c9dd..5c13e59987f 100644
--- a/usr/gri/pretty/parser.go
+++ b/usr/gri/pretty/parser.go
@@ -25,6 +25,11 @@ import (
type Position scanner.Location
+type interval struct {
+ beg, end int;
+}
+
+
// A Parser holds the parser's internal state while processing
// a given text. It can be allocated as part of another data
// structure but must be initialized via Init before use.
@@ -37,11 +42,11 @@ type Parser struct {
trace bool;
indent uint;
- comments vector.Vector;
- last_comment ast.CommentGroup;
+ comments vector.Vector; // list of collected, unassociated comments
+ last_doc interval; // last comments interval of consecutive comments
// The next token
- loc Position; // token location
+ pos Position; // token location
tok int; // one token look-ahead
val []byte; // token value
@@ -51,9 +56,9 @@ type Parser struct {
};
-// When we don't have a location use noloc.
+// When we don't have a location use nopos.
// TODO make sure we always have a location.
-var noloc Position;
+var nopos Position;
// ----------------------------------------------------------------------------
@@ -95,32 +100,35 @@ func un/*trace*/(P *Parser) {
func (P *Parser) next0() {
- P.loc, P.tok, P.val = P.scanner.Scan();
+ P.pos, P.tok, P.val = P.scanner.Scan();
P.opt_semi = false;
if P.trace {
P.printIndent();
switch P.tok {
case token.IDENT, token.INT, token.FLOAT, token.CHAR, token.STRING:
- fmt.Printf("%d:%d: %s = %s\n", P.loc.Line, P.loc.Col, token.TokenString(P.tok), P.val);
+ fmt.Printf("%d:%d: %s = %s\n", P.pos.Line, P.pos.Col, token.TokenString(P.tok), P.val);
case token.LPAREN:
// don't print '(' - screws up selection in terminal window
- fmt.Printf("%d:%d: LPAREN\n", P.loc.Line, P.loc.Col);
+ fmt.Printf("%d:%d: LPAREN\n", P.pos.Line, P.pos.Col);
case token.RPAREN:
// don't print ')' - screws up selection in terminal window
- fmt.Printf("%d:%d: RPAREN\n", P.loc.Line, P.loc.Col);
+ fmt.Printf("%d:%d: RPAREN\n", P.pos.Line, P.pos.Col);
default:
- fmt.Printf("%d:%d: %s\n", P.loc.Line, P.loc.Col, token.TokenString(P.tok));
+ fmt.Printf("%d:%d: %s\n", P.pos.Line, P.pos.Col, token.TokenString(P.tok));
}
}
}
-func (P *Parser) getComment() *ast.Comment {
- defer P.next0();
-
- // for /*-style comments, the comment may end on a different line
- endline := P.loc.Line;
+// Collect a comment in the parser's comment list and return the line
+// on which the comment ends.
+func (P *Parser) collectComment() int {
+ // For /*-style comments, the comment may end on a different line.
+ // Scan the comment for '\n' chars and adjust the end line accordingly.
+ // (Note that the position of the next token may be even further down
+ // as there may be more whitespace lines after the comment.)
+ endline := P.pos.Line;
if P.val[1] == '*' {
for i, b := range P.val {
if b == '\n' {
@@ -128,51 +136,30 @@ func (P *Parser) getComment() *ast.Comment {
}
}
}
+ P.comments.Push(&ast.Comment{P.pos, P.val, endline});
+ P.next0();
- return &ast.Comment{P.loc, endline, P.val};
+ return endline;
}
-func (P *Parser) getCommentGroup() ast.CommentGroup {
- list := vector.New(0);
-
- // group adjacent comments
- // (an empty line terminates a group)
- endline := P.loc.Line;
- for P.tok == token.COMMENT && endline+1 >= P.loc.Line {
- c := P.getComment();
- list.Push(c);
- endline = c.EndLine;
+func (P *Parser) getComments() interval {
+ // group adjacent comments, an empty line terminates a group
+ beg := P.comments.Len();
+ endline := P.pos.Line;
+ for P.tok == token.COMMENT && endline+1 >= P.pos.Line {
+ endline = P.collectComment();
}
-
- // convert list
- group := make(ast.CommentGroup, list.Len());
- for i := 0; i < list.Len(); i++ {
- group[i] = list.At(i).(*ast.Comment);
- }
-
- return group;
-}
-
-
-func (P *Parser) getLastComment() ast.CommentGroup {
- c := P.last_comment;
- if c != nil && c[len(c) - 1].EndLine + 1 < P.loc.Line {
- // empty line between last comment and current token,
- // at least one line of space between last comment
- // and current token; ignore this comment
- return nil;
- }
- return c;
+ end := P.comments.Len();
+ return interval {beg, end};
}
func (P *Parser) next() {
P.next0();
- P.last_comment = nil;
+ P.last_doc = interval{0, 0};
for P.tok == token.COMMENT {
- P.last_comment = P.getCommentGroup();
- P.comments.Push(P.last_comment);
+ P.last_doc = P.getComments();
}
}
@@ -186,8 +173,8 @@ func (P *Parser) Init(scanner *scanner.Scanner, err scanner.ErrorHandler, trace
}
-func (P *Parser) error(loc Position, msg string) {
- P.err.Error(loc, msg);
+func (P *Parser) error(pos Position, msg string) {
+ P.err.Error(pos, msg);
}
@@ -197,14 +184,36 @@ func (P *Parser) expect(tok int) Position {
if token.IsLiteral(P.tok) {
msg += " " + string(P.val);
}
- P.error(P.loc, msg);
+ P.error(P.pos, msg);
}
- loc := P.loc;
+ loc := P.pos;
P.next(); // make progress in any case
return loc;
}
+func (P *Parser) getDoc() ast.Comments {
+ doc := P.last_doc;
+ n := doc.end - doc.beg;
+
+ if n <= 0 || P.comments.At(doc.end - 1).(*ast.Comment).EndLine + 1 < P.pos.Line {
+ // no comments or empty line between last comment and current token;
+ // do not use as documentation
+ return nil;
+ }
+
+ // found immediately adjacent comment interval;
+ // use as documentation
+ c := make(ast.Comments, n);
+ for i := 0; i < n; i++ {
+ c[i] = P.comments.At(doc.beg + i).(*ast.Comment);
+ // TODO find a better way to do this
+ P.comments.Set(doc.beg + i, nil); // remove the comment from the general list
+ }
+ return c;
+}
+
+
// ----------------------------------------------------------------------------
// Common productions
@@ -220,13 +229,13 @@ func (P *Parser) parseIdent() *ast.Ident {
}
if P.tok == token.IDENT {
- x := &ast.Ident{string(P.val), P.loc};
+ x := &ast.Ident{P.pos, P.val};
P.next();
return x;
}
-
P.expect(token.IDENT); // use expect() error handling
- return &ast.Ident{"", P.loc};
+
+ return &ast.Ident{P.pos, [0]byte{}};
}
@@ -250,6 +259,7 @@ func (P *Parser) parseIdentList(x ast.Expr) []*ast.Ident {
for i := 0; i < list.Len(); i++ {
idents[i] = list.At(i).(*ast.Ident);
}
+
return idents;
}
@@ -271,6 +281,7 @@ func (P *Parser) parseExpressionList() []ast.Expr {
for i := 0; i < list.Len(); i++ {
exprs[i] = list.At(i).(ast.Expr);
}
+
return exprs;
}
@@ -283,13 +294,13 @@ func (P *Parser) parseType() ast.Expr {
defer un(trace(P, "Type"));
}
- t := P.tryType();
- if t == nil {
- P.error(P.loc, "type expected");
- t = &ast.BadExpr{P.loc};
+ typ := P.tryType();
+ if typ == nil {
+ P.error(P.pos, "type expected");
+ typ = &ast.BadExpr{P.pos};
}
- return t;
+ return typ;
}
@@ -309,12 +320,10 @@ func (P *Parser) parseQualifiedIdent() ast.Expr {
var x ast.Expr = P.parseIdent();
for P.tok == token.PERIOD {
- pos := P.loc;
P.next();
sel := P.parseIdent();
- x = &ast.Selector{x, sel, pos};
+ x = &ast.SelectorExpr{x, sel};
}
-
return x;
}
@@ -333,11 +342,10 @@ func (P *Parser) parseArrayType() *ast.ArrayType {
defer un(trace(P, "ArrayType"));
}
- loc := P.loc;
- P.expect(token.LBRACK);
+ lbrack := P.expect(token.LBRACK);
var len ast.Expr;
if P.tok == token.ELLIPSIS {
- len = &ast.Ellipsis{P.loc};
+ len = &ast.Ellipsis{P.pos};
P.next();
} else if P.tok != token.RBRACK {
len = P.parseExpression(1);
@@ -345,7 +353,7 @@ func (P *Parser) parseArrayType() *ast.ArrayType {
P.expect(token.RBRACK);
elt := P.parseType();
- return &ast.ArrayType{loc, len, elt};
+ return &ast.ArrayType{lbrack, len, elt};
}
@@ -354,28 +362,28 @@ func (P *Parser) parseChannelType() *ast.ChannelType {
defer un(trace(P, "ChannelType"));
}
- loc := P.loc;
- mode := ast.FULL;
+ pos := P.pos;
+ dir := ast.SEND | ast.RECV;
if P.tok == token.CHAN {
P.next();
if P.tok == token.ARROW {
P.next();
- mode = ast.SEND;
+ dir = ast.SEND;
}
} else {
P.expect(token.ARROW);
P.expect(token.CHAN);
- mode = ast.RECV;
+ dir = ast.RECV;
}
- val := P.parseVarType();
+ value := P.parseVarType();
- return &ast.ChannelType{loc, mode, val};
+ return &ast.ChannelType{pos, dir, value};
}
func (P *Parser) tryParameterType() ast.Expr {
if P.tok == token.ELLIPSIS {
- loc := P.loc;
+ loc := P.pos;
P.next();
return &ast.Ellipsis{loc};
}
@@ -386,9 +394,10 @@ func (P *Parser) tryParameterType() ast.Expr {
func (P *Parser) parseParameterType() ast.Expr {
typ := P.tryParameterType();
if typ == nil {
- P.error(P.loc, "type expected");
- typ = &ast.BadExpr{P.loc};
+ P.error(P.pos, "type expected");
+ typ = &ast.BadExpr{P.pos};
}
+
return typ;
}
@@ -431,20 +440,20 @@ func (P *Parser) parseParameterList(ellipsis_ok bool) []*ast.Field {
idents[i] = list.At(i).(*ast.Ident);
}
list.Init(0);
- list.Push(&ast.Field{idents, typ, nil, nil});
+ list.Push(&ast.Field{nil, idents, typ, nil});
for P.tok == token.COMMA {
P.next();
idents := P.parseIdentList(nil);
typ := P.parseParameterType();
- list.Push(&ast.Field{idents, typ, nil, nil});
+ list.Push(&ast.Field{nil, idents, typ, nil});
}
} else {
// Type { "," Type }
// convert list of types into list of *Param
for i := 0; i < list.Len(); i++ {
- list.Set(i, &ast.Field{nil, list.At(i).(ast.Expr), nil, nil});
+ list.Set(i, &ast.Field{nil, nil, list.At(i).(ast.Expr), nil});
}
}
@@ -487,7 +496,7 @@ func (P *Parser) parseResult() []*ast.Field {
typ := P.tryType();
if typ != nil {
result = make([]*ast.Field, 1);
- result[0] = &ast.Field{nil, typ, nil, nil};
+ result[0] = &ast.Field{nil, nil, typ, nil};
}
}
@@ -507,7 +516,7 @@ func (P *Parser) parseSignature() *ast.Signature {
}
params := P.parseParameters(true); // TODO find better solution
- //t.End = P.loc;
+ //t.End = P.pos;
result := P.parseResult();
return &ast.Signature{params, result};
@@ -519,11 +528,10 @@ func (P *Parser) parseFunctionType() *ast.FunctionType {
defer un(trace(P, "FunctionType"));
}
- loc := P.loc;
- P.expect(token.FUNC);
+ pos := P.expect(token.FUNC);
sig := P.parseSignature();
- return &ast.FunctionType{loc, sig};
+ return &ast.FunctionType{pos, sig};
}
@@ -532,19 +540,20 @@ func (P *Parser) parseMethodSpec() *ast.Field {
defer un(trace(P, "MethodSpec"));
}
+ doc := P.getDoc();
var idents []*ast.Ident;
var typ ast.Expr;
x := P.parseQualifiedIdent();
if tmp, is_ident := x.(*ast.Ident); is_ident && (P.tok == token.COMMA || P.tok == token.LPAREN) {
// method(s)
idents = P.parseIdentList(x);
- typ = &ast.FunctionType{noloc, P.parseSignature()};
+ typ = &ast.FunctionType{nopos, P.parseSignature()};
} else {
// embedded interface
typ = x;
}
- return &ast.Field{idents, typ, nil, nil};
+ return &ast.Field{doc, idents, typ, nil};
}
@@ -553,12 +562,11 @@ func (P *Parser) parseInterfaceType() *ast.InterfaceType {
defer un(trace(P, "InterfaceType"));
}
- loc := P.loc;
- var end Position;
+ pos := P.expect(token.INTERFACE);
+ var lbrace, rbrace Position;
var methods []*ast.Field;
-
- P.expect(token.INTERFACE);
if P.tok == token.LBRACE {
+ lbrace = P.pos;
P.next();
list := vector.New(0);
@@ -569,8 +577,7 @@ func (P *Parser) parseInterfaceType() *ast.InterfaceType {
}
}
- end = P.loc;
- P.expect(token.RBRACE);
+ rbrace = P.expect(token.RBRACE);
P.opt_semi = true;
// convert vector
@@ -580,7 +587,7 @@ func (P *Parser) parseInterfaceType() *ast.InterfaceType {
}
}
- return &ast.InterfaceType{loc, methods, end};
+ return &ast.InterfaceType{pos, lbrace, methods, rbrace};
}
@@ -589,25 +596,24 @@ func (P *Parser) parseMapType() *ast.MapType {
defer un(trace(P, "MapType"));
}
- loc := P.loc;
- P.expect(token.MAP);
+ pos := P.expect(token.MAP);
P.expect(token.LBRACK);
key := P.parseVarType();
P.expect(token.RBRACK);
- val := P.parseVarType();
+ value := P.parseVarType();
- return &ast.MapType{loc, key, val};
+ return &ast.MapType{pos, key, value};
}
-func (P *Parser) parseStringLit() ast.Expr
+func (P *Parser) parseStringLit(x *ast.BasicLit) *ast.StringLit
func (P *Parser) parseFieldDecl() *ast.Field {
if P.trace {
defer un(trace(P, "FieldDecl"));
}
- comment := P.getLastComment();
+ doc := P.getDoc();
// a list of identifiers looks like a list of type names
list := vector.New(0);
@@ -627,7 +633,7 @@ func (P *Parser) parseFieldDecl() *ast.Field {
// optional tag
var tag ast.Expr;
if P.tok == token.STRING {
- tag = P.parseStringLit();
+ tag = P.parseStringLit(nil);
}
// analyze case
@@ -648,25 +654,24 @@ func (P *Parser) parseFieldDecl() *ast.Field {
// TODO should do more checks here
typ = list.At(0).(ast.Expr);
} else {
- P.error(P.loc, "anonymous field expected");
+ P.error(P.pos, "anonymous field expected");
}
}
- return &ast.Field{idents, typ, tag, comment};
+ return &ast.Field{doc, idents, typ, tag};
}
-func (P *Parser) parseStructType() ast.Expr {
+func (P *Parser) parseStructType() *ast.StructType {
if P.trace {
defer un(trace(P, "StructType"));
}
- loc := P.loc;
- var end Position;
+ pos := P.expect(token.STRUCT);
+ var lbrace, rbrace Position;
var fields []*ast.Field;
-
- P.expect(token.STRUCT);
if P.tok == token.LBRACE {
+ lbrace = P.pos;
P.next();
list := vector.New(0);
@@ -682,8 +687,7 @@ func (P *Parser) parseStructType() ast.Expr {
P.next();
}
- end = P.loc;
- P.expect(token.RBRACE);
+ rbrace = P.expect(token.RBRACE);
P.opt_semi = true;
// convert vector
@@ -693,20 +697,19 @@ func (P *Parser) parseStructType() ast.Expr {
}
}
- return &ast.StructType{loc, fields, end};
+ return &ast.StructType{pos, lbrace, fields, rbrace};
}
-func (P *Parser) parsePointerType() ast.Expr {
+func (P *Parser) parsePointerType() *ast.StarExpr {
if P.trace {
defer un(trace(P, "PointerType"));
}
- loc := P.loc;
- P.expect(token.MUL);
+ star := P.expect(token.MUL);
base := P.parseType();
- return &ast.PointerType{loc, base};
+ return &ast.StarExpr{star, base};
}
@@ -725,11 +728,11 @@ func (P *Parser) tryType() ast.Expr {
case token.STRUCT: return P.parseStructType();
case token.MUL: return P.parsePointerType();
case token.LPAREN:
- lparen := P.loc;
+ lparen := P.pos;
P.next();
x := P.parseType();
rparen := P.expect(token.RPAREN);
- return &ast.Group{x, lparen, rparen};
+ return &ast.ParenExpr{lparen, x, rparen};
}
// no type found
@@ -740,12 +743,21 @@ func (P *Parser) tryType() ast.Expr {
// ----------------------------------------------------------------------------
// Blocks
+func asStatList(list *vector.Vector) []ast.Stat {
+ stats := make([]ast.Stat, list.Len());
+ for i := 0; i < list.Len(); i++ {
+ stats[i] = list.At(i).(ast.Stat);
+ }
+ return stats;
+}
-func (P *Parser) parseStatementList(list *vector.Vector) {
+
+func (P *Parser) parseStatementList() []ast.Stat {
if P.trace {
defer un(trace(P, "StatementList"));
}
+ list := vector.New(0);
expect_semi := false;
for P.tok != token.CASE && P.tok != token.DEFAULT && P.tok != token.RBRACE && P.tok != token.EOF {
if expect_semi {
@@ -761,6 +773,8 @@ func (P *Parser) parseStatementList(list *vector.Vector) {
expect_semi = true;
}
}
+
+ return asStatList(list);
}
@@ -769,18 +783,15 @@ func (P *Parser) parseBlock(tok int) *ast.Block {
defer un(trace(P, "Block"));
}
- b := ast.NewBlock(P.loc, tok);
- P.expect(tok);
-
- P.parseStatementList(b.List);
-
+ pos := P.expect(tok);
+ list := P.parseStatementList();
+ var end scanner.Location;
if tok == token.LBRACE {
- b.End = P.loc;
- P.expect(token.RBRACE);
+ end = P.expect(token.RBRACE);
P.opt_semi = true;
}
- return b;
+ return &ast.Block{pos, tok, list, end};
}
@@ -792,29 +803,28 @@ func (P *Parser) parseFunctionLit() ast.Expr {
defer un(trace(P, "FunctionLit"));
}
- pos := P.loc;
- P.expect(token.FUNC);
+ pos := P.expect(token.FUNC);
typ := P.parseSignature();
P.expr_lev++;
body := P.parseBlock(token.LBRACE);
P.expr_lev--;
- return &ast.FunctionLit{typ, body, pos};
+ return &ast.FunctionLit{pos, typ, body};
}
-func (P *Parser) parseStringLit() ast.Expr {
+func (P *Parser) parseStringLit(x *ast.BasicLit) *ast.StringLit {
if P.trace {
defer un(trace(P, "StringLit"));
}
- if P.tok != token.STRING {
- panic();
- }
-
list := vector.New(0);
+ if x != nil {
+ list.Push(x);
+ }
+
for P.tok == token.STRING {
- list.Push(&ast.BasicLit{token.STRING, P.val, P.loc});
+ list.Push(&ast.BasicLit{P.pos, token.STRING, P.val});
P.next();
}
@@ -838,21 +848,26 @@ func (P *Parser) parseOperand() ast.Expr {
return P.parseIdent();
case token.INT, token.FLOAT, token.CHAR:
- x := &ast.BasicLit{P.tok, P.val, P.loc};
+ x := &ast.BasicLit{P.pos, P.tok, P.val};
P.next();
return x;
case token.STRING:
- return P.parseStringLit();
+ x := &ast.BasicLit{P.pos, token.STRING, P.val};
+ P.next();
+ if P.tok == token.STRING {
+ return P.parseStringLit(x);
+ }
+ return x;
case token.LPAREN:
- lparen := P.loc;
+ lparen := P.pos;
P.next();
P.expr_lev++;
x := P.parseExpression(1);
P.expr_lev--;
rparen := P.expect(token.RPAREN);
- return &ast.Group{x, lparen, rparen};
+ return &ast.ParenExpr{lparen, x, rparen};
case token.FUNC:
return P.parseFunctionLit();
@@ -862,12 +877,12 @@ func (P *Parser) parseOperand() ast.Expr {
if t != nil {
return t;
} else {
- P.error(P.loc, "operand expected");
+ P.error(P.pos, "operand expected");
P.next(); // make progress
}
}
- return &ast.BadExpr{P.loc};
+ return &ast.BadExpr{P.pos};
}
@@ -876,25 +891,29 @@ func (P *Parser) parseSelectorOrTypeAssertion(x ast.Expr) ast.Expr {
defer un(trace(P, "SelectorOrTypeAssertion"));
}
- period := P.expect(token.PERIOD);
-
+ P.expect(token.PERIOD);
if P.tok == token.IDENT {
// selector
sel := P.parseIdent();
- return &ast.Selector{x, sel, period};
- }
-
- // type assertion
- lparen := P.expect(token.LPAREN);
- var typ ast.Expr;
- if P.tok == token.TYPE {
- typ = &ast.TypeType{P.loc};
- P.next();
+ return &ast.SelectorExpr{x, sel};
+
} else {
- typ = P.parseType();
+ // type assertion
+ P.expect(token.LPAREN);
+ var typ ast.Expr;
+ if P.tok == token.TYPE {
+ // special case for type switch syntax
+ typ = &ast.Ident{P.pos, P.val};
+ P.next();
+ } else {
+ typ = P.parseType();
+ }
+ P.expect(token.RPAREN);
+ return &ast.TypeAssertExpr{x, typ};
}
- rparen := P.expect(token.RPAREN);
- return &ast.TypeAssertion{x, typ, period, lparen, rparen};
+
+ unreachable();
+ return nil;
}
@@ -903,29 +922,28 @@ func (P *Parser) parseIndexOrSlice(x ast.Expr) ast.Expr {
defer un(trace(P, "IndexOrSlice"));
}
- lbrack := P.expect(token.LBRACK);
+ P.expect(token.LBRACK);
P.expr_lev++;
index := P.parseExpression(1);
P.expr_lev--;
if P.tok == token.RBRACK {
// index
- rbrack := P.loc;
P.next();
- return &ast.Index{x, index, lbrack, rbrack};
+ return &ast.IndexExpr{x, index};
}
// slice
- colon := P.expect(token.COLON);
+ P.expect(token.COLON);
P.expr_lev++;
end := P.parseExpression(1);
P.expr_lev--;
- rbrack := P.expect(token.RBRACK);
- return &ast.Slice{x, index, end, lbrack, colon, rbrack};
+ P.expect(token.RBRACK);
+ return &ast.SliceExpr{x, index, end};
}
-func (P *Parser) parseCall(fun ast.Expr) *ast.Call {
+func (P *Parser) parseCall(fun ast.Expr) *ast.CallExpr {
if P.trace {
defer un(trace(P, "Call"));
}
@@ -936,54 +954,7 @@ func (P *Parser) parseCall(fun ast.Expr) *ast.Call {
args = P.parseExpressionList();
}
rparen := P.expect(token.RPAREN);
- return &ast.Call{fun, args, lparen, rparen};
-}
-
-
-func (P *Parser) parseCompositeElements(close int) ast.Expr {
- x := P.parseExpression(0);
- if P.tok == token.COMMA {
- loc := P.loc;
- P.next();
-
- // first element determines mode
- singles := true;
- if t, is_binary := x.(*ast.BinaryExpr); is_binary && t.Op == token.COLON {
- singles = false;
- }
-
- var last *ast.BinaryExpr;
- for P.tok != close && P.tok != token.EOF {
- y := P.parseExpression(0);
-
- if singles {
- if t, is_binary := y.(*ast.BinaryExpr); is_binary && t.Op == token.COLON {
- P.error(t.X.Pos(), "single value expected; found pair");
- }
- } else {
- if t, is_binary := y.(*ast.BinaryExpr); !is_binary || t.Op != token.COLON {
- P.error(y.Pos(), "key:value pair expected; found single value");
- }
- }
-
- if last == nil {
- last = &ast.BinaryExpr{token.COMMA, x, y, loc};
- x = last;
- } else {
- last.Y = &ast.BinaryExpr{token.COMMA, last.Y, y, loc};
- last = last.Y.(*ast.BinaryExpr);
- }
-
- if P.tok == token.COMMA {
- loc = P.loc;
- P.next();
- } else {
- break;
- }
-
- }
- }
- return x;
+ return &ast.CallExpr{fun, lparen, args, rparen};
}
@@ -998,17 +969,17 @@ func (P *Parser) parseElementList() []ast.Expr {
x := P.parseExpression(0);
if list.Len() == 0 {
// first element determines syntax for remaining elements
- if t, is_binary := x.(*ast.BinaryExpr); is_binary && t.Op == token.COLON {
+ if t, is_binary := x.(*ast.BinaryExpr); is_binary && t.Tok == token.COLON {
singles = false;
}
} else {
// not the first element - check syntax
if singles {
- if t, is_binary := x.(*ast.BinaryExpr); is_binary && t.Op == token.COLON {
+ if t, is_binary := x.(*ast.BinaryExpr); is_binary && t.Tok == token.COLON {
P.error(t.X.Pos(), "single value expected; found pair");
}
} else {
- if t, is_binary := x.(*ast.BinaryExpr); !is_binary || t.Op != token.COLON {
+ if t, is_binary := x.(*ast.BinaryExpr); !is_binary || t.Tok != token.COLON {
P.error(x.Pos(), "key:value pair expected; found single value");
}
}
@@ -1044,7 +1015,7 @@ func (P *Parser) parseCompositeLit(typ ast.Expr) ast.Expr {
elts = P.parseElementList();
}
rbrace := P.expect(token.RBRACE);
- return &ast.CompositeLit{typ, elts, lbrace, rbrace};
+ return &ast.CompositeLit{typ, lbrace, elts, rbrace};
}
@@ -1081,11 +1052,18 @@ func (P *Parser) parseUnaryExpr() ast.Expr {
}
switch P.tok {
- case token.ADD, token.SUB, token.MUL, token.NOT, token.XOR, token.ARROW, token.AND:
- loc, tok := P.loc, P.tok;
+ case token.ADD, token.SUB, token.NOT, token.XOR, token.ARROW, token.AND, token.RANGE:
+ pos, tok := P.pos, P.tok;
P.next();
- y := P.parseUnaryExpr();
- return &ast.UnaryExpr{tok, y, loc};
+ x := P.parseUnaryExpr();
+ return &ast.UnaryExpr{pos, tok, x};
+
+ case token.MUL:
+ // unary "*" expression or pointer type
+ pos := P.pos;
+ P.next();
+ x := P.parseUnaryExpr();
+ return &ast.StarExpr{pos, x};
}
return P.parsePrimaryExpr();
@@ -1100,10 +1078,10 @@ func (P *Parser) parseBinaryExpr(prec1 int) ast.Expr {
x := P.parseUnaryExpr();
for prec := token.Precedence(P.tok); prec >= prec1; prec-- {
for token.Precedence(P.tok) == prec {
- loc, tok := P.loc, P.tok;
+ pos, tok := P.pos, P.tok;
P.next();
y := P.parseBinaryExpr(prec + 1);
- x = &ast.BinaryExpr{tok, x, y, loc};
+ x = &ast.BinaryExpr{x, pos, tok, y};
}
}
@@ -1128,13 +1106,7 @@ func (P *Parser) parseExpression(prec int) ast.Expr {
// Statements
-const /* mode */ (
- label_ok = 1 << iota;
- range_ok;
-)
-
-
-func (P *Parser) parseSimpleStat(mode int) ast.Stat {
+func (P *Parser) parseSimpleStat() ast.Stat {
if P.trace {
defer un(trace(P, "SimpleStat"));
}
@@ -1144,15 +1116,13 @@ func (P *Parser) parseSimpleStat(mode int) ast.Stat {
switch P.tok {
case token.COLON:
// labeled statement
- loc := P.loc;
P.expect(token.COLON);
- P.opt_semi = true;
- if mode & label_ok != 0 && len(x) == 1 {
+ if len(x) == 1 {
if label, is_ident := x[0].(*ast.Ident); is_ident {
- return &ast.LabeledStat{loc, label, P.parseStatement()};
+ return &ast.LabeledStat{label, P.parseStatement()};
}
}
- P.error(loc, "illegal label declaration");
+ P.error(x[0].Pos(), "illegal label declaration");
return nil;
case
@@ -1161,34 +1131,29 @@ func (P *Parser) parseSimpleStat(mode int) ast.Stat {
token.REM_ASSIGN, token.AND_ASSIGN, token.OR_ASSIGN,
token.XOR_ASSIGN, token.SHL_ASSIGN, token.SHR_ASSIGN:
// assignment statement or range clause
- loc, tok := P.loc, P.tok;
+ pos, tok := P.pos, P.tok;
P.next();
+ /*
if mode & range_ok != 0 && P.tok == token.RANGE {
// range clause
P.next();
if len(x) != 1 && len(x) != 2 {
- P.error(loc, "expected 1 or 2 expressions on lhs of range clause");
+ P.error(x[0].Pos(), "expected 1 or 2 expressions on lhs of range clause");
}
if tok != token.DEFINE && tok != token.ASSIGN {
- P.error(loc, "expected '=' or ':=', found '" + token.TokenString(tok) + "'");
+ P.error(pos, "expected '=' or ':=', found '" + token.TokenString(tok) + "'");
}
y := P.parseExpression(1);
- return &ast.RangeClause{loc, tok, x, y};
+ return &ast.RangeClause{x, pos, tok, y};
} else {
- // assignment statement
- y := P.parseExpressionList();
- xl, yl := len(x), len(y);
- if xl > 1 && yl > 1 && xl != yl {
- P.error(loc, "arity of lhs doesn't match rhs"); // TODO use better loc for error
- }
- if xl == 1 && yl == 1 {
- // common case - use smaller node
- return &ast.AssignmentStat{loc, tok, x[0], y[0]};
- } else {
- // general case
- return &ast.TupleAssignStat{loc, tok, x, y};
- }
+ */
+ // assignment statement
+ y := P.parseExpressionList();
+ xl, yl := len(x), len(y);
+ if xl > 1 && yl > 1 && xl != yl {
+ P.error(x[0].Pos(), "arity of lhs doesn't match rhs"); // TODO use better loc for error
}
+ return &ast.AssignmentStat{x, pos, tok, y};
default:
if len(x) > 1 {
@@ -1196,13 +1161,12 @@ func (P *Parser) parseSimpleStat(mode int) ast.Stat {
}
if P.tok == token.INC || P.tok == token.DEC {
- s := &ast.IncDecStat{P.loc, P.tok, x[0]};
+ s := &ast.IncDecStat{x[0], P.tok};
P.next(); // consume "++" or "--"
return s;
}
- // TODO change ILLEGAL -> NONE
- return &ast.ExpressionStat{x[0].Pos(), token.ILLEGAL, x[0]};
+ return &ast.ExprStat{x[0]};
}
unreachable();
@@ -1210,14 +1174,25 @@ func (P *Parser) parseSimpleStat(mode int) ast.Stat {
}
-func (P *Parser) parseInvocationStat(keyword int) *ast.ExpressionStat {
+func (P *Parser) parseGoStat() *ast.GoStat {
if P.trace {
- defer un(trace(P, "InvocationStat"));
+ defer un(trace(P, "GoStat"));
}
- loc := P.loc;
- P.expect(keyword);
- return &ast.ExpressionStat{loc, keyword, P.parseExpression(1)};
+ pos := P.expect(token.GO);
+ call := P.parseExpression(1);
+ return &ast.GoStat{pos, call};
+}
+
+
+func (P *Parser) parseDeferStat() *ast.DeferStat {
+ if P.trace {
+ defer un(trace(P, "DeferStat"));
+ }
+
+ pos := P.expect(token.DEFER);
+ call := P.parseExpression(1);
+ return &ast.DeferStat{pos, call};
}
@@ -1226,7 +1201,7 @@ func (P *Parser) parseReturnStat() *ast.ReturnStat {
defer un(trace(P, "ReturnStat"));
}
- loc := P.loc;
+ loc := P.pos;
P.expect(token.RETURN);
var x []ast.Expr;
if P.tok != token.SEMICOLON && P.tok != token.RBRACE {
@@ -1242,7 +1217,7 @@ func (P *Parser) parseControlFlowStat(tok int) *ast.ControlFlowStat {
defer un(trace(P, "ControlFlowStat"));
}
- s := &ast.ControlFlowStat{P.loc, tok, nil};
+ s := &ast.ControlFlowStat{P.pos, tok, nil};
P.expect(tok);
if tok != token.FALLTHROUGH && P.tok == token.IDENT {
s.Label = P.parseIdent();
@@ -1252,91 +1227,13 @@ func (P *Parser) parseControlFlowStat(tok int) *ast.ControlFlowStat {
}
-func (P *Parser) parseControlClause(isForStat bool) (init ast.Stat, expr ast.Expr, post ast.Stat) {
- if P.trace {
- defer un(trace(P, "ControlClause"));
- }
-
- if P.tok != token.LBRACE {
- prev_lev := P.expr_lev;
- P.expr_lev = -1;
-
- if P.tok != token.SEMICOLON {
- mode := 0;
- if isForStat {
- mode = range_ok;
- }
- init = P.parseSimpleStat(mode);
- }
- if dummy, is_range := init.(*ast.RangeClause); !is_range {
- if P.tok == token.SEMICOLON {
- P.next();
- if P.tok != token.SEMICOLON && P.tok != token.LBRACE {
- expr = P.parseExpression(1);
- }
- if isForStat {
- P.expect(token.SEMICOLON);
- if P.tok != token.LBRACE {
- post = P.parseSimpleStat(0);
- }
- }
- } else {
- if init != nil { // guard in case of errors
- if s, is_expr_stat := init.(*ast.ExpressionStat); is_expr_stat {
- expr, init = s.Expr, nil;
- } else {
- P.error(noloc, "illegal control clause");
- }
- }
- }
- }
-
- P.expr_lev = prev_lev;
- }
-
- return init, expr, post;
-}
-
-
-func (P *Parser) parseIfStat() *ast.IfStat {
- if P.trace {
- defer un(trace(P, "IfStat"));
- }
-
- loc := P.loc;
- P.expect(token.IF);
- init, cond, dummy := P.parseControlClause(false);
- body := P.parseBlock(token.LBRACE);
- var else_ ast.Stat;
- if P.tok == token.ELSE {
- P.next();
- else_ = P.parseStatement();
- }
-
- return &ast.IfStat{loc, init, cond, body, else_};
-}
-
-
-func (P *Parser) parseForStat() *ast.ForStat {
- if P.trace {
- defer un(trace(P, "ForStat"));
- }
-
- loc := P.loc;
- P.expect(token.FOR);
- init, cond, post := P.parseControlClause(true);
- body := P.parseBlock(token.LBRACE);
-
- return &ast.ForStat{loc, init, cond, post, body};
-}
-
-
+/*
func (P *Parser) asIdent(x ast.Expr) *ast.Ident {
if name, ok := x.(*ast.Ident); ok {
return name;
}
P.error(x.Pos(), "identifier expected");
- return &ast.Ident{"BAD", noloc};
+ return &ast.Ident{x.Pos(), [...]byte{'B', 'A', 'D'}};
}
@@ -1352,6 +1249,82 @@ func (P *Parser) isTypeSwitch(init ast.Stat) (lhs *ast.Ident, rhs ast.Expr) {
}
return nil, nil;
}
+*/
+
+
+
+func (P *Parser) parseControlClause(isForStat bool) (s1, s2, s3 ast.Stat) {
+ if P.trace {
+ defer un(trace(P, "ControlClause"));
+ }
+
+ if P.tok != token.LBRACE {
+ prev_lev := P.expr_lev;
+ P.expr_lev = -1;
+
+ if P.tok != token.SEMICOLON {
+ s1 = P.parseSimpleStat();
+ }
+ if P.tok == token.SEMICOLON {
+ P.next();
+ if P.tok != token.LBRACE && P.tok != token.SEMICOLON {
+ s2 = P.parseSimpleStat();
+ }
+ if isForStat {
+ // for statements have a 3rd section
+ P.expect(token.SEMICOLON);
+ if P.tok != token.LBRACE {
+ s3 = P.parseSimpleStat();
+ }
+ }
+ } else {
+ s1, s2 = nil, s1;
+ }
+
+ P.expr_lev = prev_lev;
+ }
+
+ return s1, s2, s3;
+}
+
+
+func (P *Parser) isExpr(s ast.Stat) bool {
+ if s == nil {
+ return true;
+ }
+ dummy, is_expr := s.(*ast.ExprStat);
+ return is_expr;
+}
+
+
+func (P *Parser) asExpr(s ast.Stat) ast.Expr {
+ if s == nil {
+ return nil;
+ }
+ if es, is_expr := s.(*ast.ExprStat); is_expr {
+ return es.X;
+ }
+ P.error(s.Pos(), "condition expected; found simple statement");
+ return &ast.BadExpr{s.Pos()};
+}
+
+
+func (P *Parser) parseIfStat() *ast.IfStat {
+ if P.trace {
+ defer un(trace(P, "IfStat"));
+ }
+
+ pos := P.expect(token.IF);
+ s1, s2, dummy := P.parseControlClause(false);
+ body := P.parseBlock(token.LBRACE);
+ var else_ ast.Stat;
+ if P.tok == token.ELSE {
+ P.next();
+ else_ = P.parseStatement();
+ }
+
+ return &ast.IfStat{pos, s1, P.asExpr(s2), body, else_};
+}
func (P *Parser) parseCaseClause() *ast.CaseClause {
@@ -1360,7 +1333,7 @@ func (P *Parser) parseCaseClause() *ast.CaseClause {
}
// SwitchCase
- loc := P.loc;
+ loc := P.pos;
var x []ast.Expr;
if P.tok == token.CASE {
P.next();
@@ -1373,32 +1346,61 @@ func (P *Parser) parseCaseClause() *ast.CaseClause {
}
-func (P *Parser) parseSwitchStat() *ast.SwitchStat {
+func (P *Parser) parseTypeCaseClause() *ast.TypeCaseClause {
+ if P.trace {
+ defer un(trace(P, "CaseClause"));
+ }
+
+ // TypeSwitchCase
+ pos := P.pos;
+ var typ ast.Expr;
+ if P.tok == token.CASE {
+ P.next();
+ typ = P.parseType();
+ } else {
+ P.expect(token.DEFAULT);
+ }
+
+ return &ast.TypeCaseClause{pos, typ, P.parseBlock(token.COLON)};
+}
+
+
+func (P *Parser) parseSwitchStat() ast.Stat {
if P.trace {
defer un(trace(P, "SwitchStat"));
}
- loc := P.loc;
- P.expect(token.SWITCH);
- init, tag, post := P.parseControlClause(false);
- body := ast.NewBlock(P.loc, token.LBRACE);
- P.expect(token.LBRACE);
- for P.tok != token.RBRACE && P.tok != token.EOF {
- body.List.Push(P.parseCaseClause());
- }
- body.End = P.loc;
- P.expect(token.RBRACE);
- P.opt_semi = true;
+ pos := P.expect(token.SWITCH);
+ s1, s2, dummy := P.parseControlClause(false);
- if lhs, rhs := P.isTypeSwitch(init); lhs != nil {
- if tag != nil {
- P.error(loc, "illegal type switch clause");
+ if P.isExpr(s2) {
+ // expression switch
+ lbrace := P.expect(token.LBRACE);
+ cases := vector.New(0);
+ for P.tok == token.CASE || P.tok == token.DEFAULT {
+ cases.Push(P.parseCaseClause());
}
- // TODO fix location
- init = &ast.TypeSwitchClause{loc, lhs, rhs};
+ rbrace := P.expect(token.RBRACE);
+ P.opt_semi = true;
+ body := &ast.Block{lbrace, token.LBRACE, asStatList(cases), rbrace};
+ return &ast.SwitchStat{pos, s1, P.asExpr(s2), body};
+
+ } else {
+ // type switch
+ // TODO do all the checks!
+ lbrace := P.expect(token.LBRACE);
+ cases := vector.New(0);
+ for P.tok == token.CASE || P.tok == token.DEFAULT {
+ cases.Push(P.parseTypeCaseClause());
+ }
+ rbrace := P.expect(token.RBRACE);
+ P.opt_semi = true;
+ body := &ast.Block{lbrace, token.LBRACE, asStatList(cases), rbrace};
+ return &ast.TypeSwitchStat{pos, s1, s2, body};
}
- return &ast.SwitchStat{loc, init, tag, body};
+ unreachable();
+ return nil;
}
@@ -1408,7 +1410,7 @@ func (P *Parser) parseCommClause() *ast.CommClause {
}
// CommCase
- loc := P.loc;
+ loc := P.pos;
var tok int;
var lhs, rhs ast.Expr;
if P.tok == token.CASE {
@@ -1445,18 +1447,40 @@ func (P *Parser) parseSelectStat() *ast.SelectStat {
defer un(trace(P, "SelectStat"));
}
- loc := P.loc;
- P.expect(token.SELECT);
- body := ast.NewBlock(P.loc, token.LBRACE);
- P.expect(token.LBRACE);
- for P.tok != token.RBRACE && P.tok != token.EOF {
- body.List.Push(P.parseCommClause());
+ pos := P.expect(token.SELECT);
+ lbrace := P.expect(token.LBRACE);
+ cases := vector.New(0);
+ for P.tok == token.CASE || P.tok == token.DEFAULT {
+ cases.Push(P.parseCommClause());
}
- body.End = P.loc;
- P.expect(token.RBRACE);
+ rbrace := P.expect(token.RBRACE);
P.opt_semi = true;
+ body := &ast.Block{lbrace, token.LBRACE, asStatList(cases), rbrace};
- return &ast.SelectStat{loc, body};
+ return &ast.SelectStat{pos, body};
+}
+
+
+func (P *Parser) parseForStat() ast.Stat {
+ if P.trace {
+ defer un(trace(P, "ForStat"));
+ }
+
+ pos := P.expect(token.FOR);
+ s1, s2, s3 := P.parseControlClause(true);
+ body := P.parseBlock(token.LBRACE);
+
+ if as, is_as := s2.(*ast.AssignmentStat); is_as {
+ // probably a for statement with a range clause
+ // TODO do all the checks!
+ return &ast.RangeStat{pos, s2, body};
+ } else {
+ // regular for statement
+ return &ast.ForStat{pos, s1, P.asExpr(s2), s3, body};
+ }
+
+ unreachable();
+ return nil;
}
@@ -1467,15 +1491,17 @@ func (P *Parser) parseStatement() ast.Stat {
switch P.tok {
case token.CONST, token.TYPE, token.VAR:
- return &ast.DeclarationStat{P.parseDeclaration()};
+ return &ast.DeclStat{P.parseDeclaration()};
case
// tokens that may start a top-level expression
token.IDENT, token.INT, token.FLOAT, token.CHAR, token.STRING, token.FUNC, token.LPAREN, // operand
token.LBRACK, token.STRUCT, // composite type
token.MUL, token.AND, token.ARROW: // unary operators
- return P.parseSimpleStat(label_ok);
- case token.GO, token.DEFER:
- return P.parseInvocationStat(P.tok);
+ return P.parseSimpleStat();
+ case token.GO:
+ return P.parseGoStat();
+ case token.DEFER:
+ return P.parseDeferStat();
case token.RETURN:
return P.parseReturnStat();
case token.BREAK, token.CONTINUE, token.GOTO, token.FALLTHROUGH:
@@ -1492,43 +1518,43 @@ func (P *Parser) parseStatement() ast.Stat {
return P.parseSelectStat();
case token.SEMICOLON, token.RBRACE:
// don't consume the ";", it is the separator following the empty statement
- return &ast.EmptyStat{P.loc};
+ return &ast.EmptyStat{P.pos};
}
// no statement found
- P.error(P.loc, "statement expected");
- return &ast.BadStat{P.loc};
+ P.error(P.pos, "statement expected");
+ return &ast.BadStat{P.pos};
}
// ----------------------------------------------------------------------------
// Declarations
-func (P *Parser) parseImportSpec(loc Position) *ast.ImportDecl {
+func (P *Parser) parseImportSpec(pos Position, doc ast.Comments) *ast.ImportDecl {
if P.trace {
defer un(trace(P, "ImportSpec"));
}
var ident *ast.Ident;
if P.tok == token.PERIOD {
- P.error(P.loc, `"import ." not yet handled properly`);
+ P.error(P.pos, `"import ." not yet handled properly`);
P.next();
} else if P.tok == token.IDENT {
ident = P.parseIdent();
}
- var path ast.Expr;
+ var path *ast.StringLit;
if P.tok == token.STRING {
- path = P.parseStringLit();
+ path = P.parseStringLit(nil);
} else {
P.expect(token.STRING); // use expect() error handling
}
- return &ast.ImportDecl{loc, ident, path};
+ return &ast.ImportDecl{doc, pos, ident, path};
}
-func (P *Parser) parseConstSpec(loc Position, comment ast.CommentGroup) *ast.ConstDecl {
+func (P *Parser) parseConstSpec(pos Position, doc ast.Comments) *ast.ConstDecl {
if P.trace {
defer un(trace(P, "ConstSpec"));
}
@@ -1541,11 +1567,11 @@ func (P *Parser) parseConstSpec(loc Position, comment ast.CommentGroup) *ast.Con
values = P.parseExpressionList();
}
- return &ast.ConstDecl{loc, names, typ, values, comment};
+ return &ast.ConstDecl{doc, pos, names, typ, values};
}
-func (P *Parser) parseTypeSpec(loc Position, comment ast.CommentGroup) *ast.TypeDecl {
+func (P *Parser) parseTypeSpec(pos Position, doc ast.Comments) *ast.TypeDecl {
if P.trace {
defer un(trace(P, "TypeSpec"));
}
@@ -1553,11 +1579,11 @@ func (P *Parser) parseTypeSpec(loc Position, comment ast.CommentGroup) *ast.Type
ident := P.parseIdent();
typ := P.parseType();
- return &ast.TypeDecl{loc, ident, typ, comment};
+ return &ast.TypeDecl{doc, pos, ident, typ};
}
-func (P *Parser) parseVarSpec(loc Position, comment ast.CommentGroup) *ast.VarDecl {
+func (P *Parser) parseVarSpec(pos Position, doc ast.Comments) *ast.VarDecl {
if P.trace {
defer un(trace(P, "VarSpec"));
}
@@ -1570,16 +1596,16 @@ func (P *Parser) parseVarSpec(loc Position, comment ast.CommentGroup) *ast.VarDe
values = P.parseExpressionList();
}
- return &ast.VarDecl{loc, names, typ, values, comment};
+ return &ast.VarDecl{doc, pos, names, typ, values};
}
-func (P *Parser) parseSpec(loc Position, comment ast.CommentGroup, keyword int) ast.Decl {
+func (P *Parser) parseSpec(pos Position, doc ast.Comments, keyword int) ast.Decl {
switch keyword {
- case token.IMPORT: return P.parseImportSpec(loc);
- case token.CONST: return P.parseConstSpec(loc, comment);
- case token.TYPE: return P.parseTypeSpec(loc, comment);
- case token.VAR: return P.parseVarSpec(loc, comment);
+ case token.IMPORT: return P.parseImportSpec(pos, doc);
+ case token.CONST: return P.parseConstSpec(pos, doc);
+ case token.TYPE: return P.parseTypeSpec(pos, doc);
+ case token.VAR: return P.parseVarSpec(pos, doc);
}
unreachable();
@@ -1592,22 +1618,21 @@ func (P *Parser) parseDecl(keyword int) ast.Decl {
defer un(trace(P, "Decl"));
}
- comment := P.getLastComment();
- loc := P.loc;
- P.expect(keyword);
+ doc := P.getDoc();
+ pos := P.expect(keyword);
if P.tok == token.LPAREN {
+ lparen := P.pos;
P.next();
list := vector.New(0);
for P.tok != token.RPAREN && P.tok != token.EOF {
- list.Push(P.parseSpec(noloc, nil, keyword));
+ list.Push(P.parseSpec(nopos, nil, keyword));
if P.tok == token.SEMICOLON {
P.next();
} else {
break;
}
}
- end := P.loc;
- P.expect(token.RPAREN);
+ rparen := P.expect(token.RPAREN);
P.opt_semi = true;
// convert vector
@@ -1616,10 +1641,10 @@ func (P *Parser) parseDecl(keyword int) ast.Decl {
decls[i] = list.At(i).(ast.Decl);
}
- return &ast.DeclList{loc, keyword, decls, end};
+ return &ast.DeclList{doc, pos, keyword, lparen, decls, rparen};
}
- return P.parseSpec(loc, comment, keyword);
+ return P.parseSpec(pos, doc, keyword);
}
@@ -1637,13 +1662,12 @@ func (P *Parser) parseFunctionDecl() *ast.FuncDecl {
defer un(trace(P, "FunctionDecl"));
}
- comment := P.getLastComment();
- loc := P.loc;
- P.expect(token.FUNC);
+ doc := P.getDoc();
+ pos := P.expect(token.FUNC);
var recv *ast.Field;
if P.tok == token.LPAREN {
- loc := P.loc;
+ loc := P.pos;
tmp := P.parseParameters(true);
if len(tmp) == 1 {
recv = tmp[0];
@@ -1660,7 +1684,7 @@ func (P *Parser) parseFunctionDecl() *ast.FuncDecl {
body = P.parseBlock(token.LBRACE);
}
- return &ast.FuncDecl{loc, recv, ident, sig, body, comment};
+ return &ast.FuncDecl{doc, pos, recv, ident, sig, body};
}
@@ -1676,7 +1700,7 @@ func (P *Parser) parseDeclaration() ast.Decl {
return P.parseFunctionDecl();
}
- loc := P.loc;
+ loc := P.pos;
P.error(loc, "declaration expected");
P.next(); // make progress
return &ast.BadDecl{loc};
@@ -1686,16 +1710,6 @@ func (P *Parser) parseDeclaration() ast.Decl {
// ----------------------------------------------------------------------------
// Program
-func (P *Parser) getComments() []ast.CommentGroup {
- // convert comments vector
- list := make([]ast.CommentGroup, P.comments.Len());
- for i := 0; i < P.comments.Len(); i++ {
- list[i] = P.comments.At(i).(ast.CommentGroup);
- }
- return list;
-}
-
-
// The Parse function is parametrized with one of the following
// constants. They control how much of the source text is parsed.
//
@@ -1710,19 +1724,18 @@ const (
//
// foo bar
//
-func (P *Parser) Parse(mode int) *ast.Program {
+func (P *Parser) Parse(mode int) *ast.Package {
if P.trace {
defer un(trace(P, "Program"));
}
// package clause
- comment := P.getLastComment();
- loc := P.loc;
- P.expect(token.PACKAGE);
+ comment := P.getDoc();
+ pos := P.expect(token.PACKAGE);
name := P.parseIdent();
if P.tok == token.SEMICOLON {
// common error
- P.error(P.loc, "extra semicolon");
+ P.error(P.pos, "extra semicolon");
P.next();
}
@@ -1748,12 +1761,21 @@ func (P *Parser) Parse(mode int) *ast.Program {
}
}
- // convert list
+ // convert declaration list
decls = make([]ast.Decl, list.Len());
for i := 0; i < list.Len(); i++ {
decls[i] = list.At(i).(ast.Decl);
}
}
- return &ast.Program{loc, name, decls, comment, P.getComments()};
+ // convert comments list
+ comments := make([]*ast.Comment, P.comments.Len());
+ for i := 0; i < P.comments.Len(); i++ {
+ c := P.comments.At(i);
+ if c != nil {
+ comments[i] = c.(*ast.Comment);
+ }
+ }
+
+ return &ast.Package{comment, pos, name, decls, comments};
}
diff --git a/usr/gri/pretty/printer.go b/usr/gri/pretty/printer.go
index ac8e646a6e5..49f77386fbc 100644
--- a/usr/gri/pretty/printer.go
+++ b/usr/gri/pretty/printer.go
@@ -37,9 +37,9 @@ var (
)
-// When we don't have a location use noloc.
+// When we don't have a location use nopos.
// TODO make sure we always have a location.
-var noloc scanner.Location;
+var nopos scanner.Location;
// ----------------------------------------------------------------------------
@@ -64,7 +64,7 @@ func assert(pred bool) {
// TODO this should be an AST method
func isExported(name *ast.Ident) bool {
- ch, len := utf8.DecodeRuneInString(name.Str, 0);
+ ch, len := utf8.DecodeRune(name.Lit);
return unicode.IsUpper(ch);
}
@@ -110,7 +110,7 @@ type Printer struct {
full bool; // if false, print interface only; print all otherwise
// comments
- comments []ast.CommentGroup; // the list of all comments groups
+ comments []*ast.Comment; // the list of unassociated comments
cindex int; // the current comment group index
cloc scanner.Location; // the position of the next comment group
@@ -138,17 +138,17 @@ func (P *Printer) hasComment(loc scanner.Location) bool {
}
-func (P *Printer) nextCommentGroup() {
+func (P *Printer) nextComments() {
P.cindex++;
- if P.comments != nil && P.cindex < len(P.comments) {
- P.cloc = P.comments[P.cindex][0].Loc;
+ if P.comments != nil && P.cindex < len(P.comments) && P.comments[P.cindex] != nil {
+ P.cloc = P.comments[P.cindex].Pos_;
} else {
P.cloc = scanner.Location{1<<30, 1<<30, 1}; // infinite
}
}
-func (P *Printer) Init(text io.Write, comments []ast.CommentGroup, html bool) {
+func (P *Printer) Init(text io.Write, comments []*ast.Comment, html bool) {
// writers
P.text = text;
@@ -158,7 +158,7 @@ func (P *Printer) Init(text io.Write, comments []ast.CommentGroup, html bool) {
// comments
P.comments = comments;
P.cindex = -1;
- P.nextCommentGroup();
+ P.nextComments();
// formatting parameters & semantic state initialized correctly by default
@@ -271,9 +271,9 @@ func (P *Printer) TaggedString(loc scanner.Location, tag, s, endtag string) {
// interleave comments, if any
nlcount := 0;
if P.full {
- for ; P.hasComment(loc); P.nextCommentGroup() {
+ for ; P.hasComment(loc); P.nextComments() {
// we have a comment group that comes before the string
- comment := P.comments[P.cindex][0]; // TODO broken
+ comment := P.comments[P.cindex];
ctext := string(comment.Text); // TODO get rid of string conversion here
// classify comment (len(ctext) >= 2)
@@ -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.Pos_, x.Str);
+ P.String(x.Pos_, string(x.Lit));
/*
obj := x.Obj;
if P.html && obj.Kind != symbolTable.NONE {
@@ -450,7 +450,7 @@ func (P *Printer) Idents(list []*ast.Ident, full bool) int {
n := 0;
for i, x := range list {
if n > 0 {
- P.Token(noloc, token.COMMA);
+ P.Token(nopos, token.COMMA);
P.separator = blank;
P.state = inside_list;
}
@@ -466,7 +466,7 @@ func (P *Printer) Idents(list []*ast.Ident, full bool) int {
func (P *Printer) Exprs(list []ast.Expr) {
for i, x := range list {
if i > 0 {
- P.Token(noloc, token.COMMA);
+ P.Token(nopos, token.COMMA);
P.separator = blank;
P.state = inside_list;
}
@@ -476,7 +476,7 @@ func (P *Printer) Exprs(list []ast.Expr) {
func (P *Printer) Parameters(list []*ast.Field) {
- P.Token(noloc, token.LPAREN);
+ P.Token(nopos, token.LPAREN);
if len(list) > 0 {
for i, par := range list {
if i > 0 {
@@ -489,7 +489,7 @@ func (P *Printer) Parameters(list []*ast.Field) {
P.Expr(par.Typ);
}
}
- P.Token(noloc, token.RPAREN);
+ P.Token(nopos, token.RPAREN);
}
@@ -515,10 +515,10 @@ func (P *Printer) Signature(sig *ast.Signature) {
}
-func (P *Printer) Fields(list []*ast.Field, end scanner.Location, is_interface bool) {
+func (P *Printer) Fields(lbrace scanner.Location, list []*ast.Field, rbrace scanner.Location, is_interface bool) {
P.state = opening_scope;
P.separator = blank;
- P.Token(noloc, token.LBRACE);
+ P.Token(lbrace, token.LBRACE);
if len(list) > 0 {
P.newlines = 1;
@@ -553,7 +553,7 @@ func (P *Printer) Fields(list []*ast.Field, end scanner.Location, is_interface b
}
P.state = closing_scope;
- P.Token(end, token.RBRACE);
+ P.Token(rbrace, token.RBRACE);
P.opt_semi = true;
}
@@ -566,7 +566,7 @@ func (P *Printer) Expr1(x ast.Expr, prec1 int)
func (P *Printer) DoBadExpr(x *ast.BadExpr) {
- P.String(noloc, "BadExpr");
+ P.String(nopos, "BadExpr");
}
@@ -576,30 +576,39 @@ func (P *Printer) DoIdent(x *ast.Ident) {
func (P *Printer) DoBinaryExpr(x *ast.BinaryExpr) {
- prec := token.Precedence(x.Op);
+ prec := token.Precedence(x.Tok);
if prec < P.prec {
- P.Token(noloc, token.LPAREN);
+ P.Token(nopos, token.LPAREN);
}
P.Expr1(x.X, prec);
P.separator = blank;
- P.Token(x.Pos_, x.Op);
+ P.Token(x.Pos_, x.Tok);
P.separator = blank;
P.Expr1(x.Y, prec);
if prec < P.prec {
- P.Token(noloc, token.RPAREN);
+ P.Token(nopos, token.RPAREN);
}
}
+func (P *Printer) DoStarExpr(x *ast.StarExpr) {
+ P.Token(x.Star, token.MUL);
+ P.Expr(x.X);
+}
+
+
func (P *Printer) DoUnaryExpr(x *ast.UnaryExpr) {
prec := token.UnaryPrec;
if prec < P.prec {
- P.Token(noloc, token.LPAREN);
+ P.Token(nopos, token.LPAREN);
+ }
+ P.Token(x.Pos_, 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);
+ P.Token(nopos, token.RPAREN);
}
}
@@ -629,48 +638,48 @@ func (P *Printer) DoFunctionLit(x *ast.FunctionLit) {
}
-func (P *Printer) DoGroup(x *ast.Group) {
+func (P *Printer) DoParenExpr(x *ast.ParenExpr) {
P.Token(x.Lparen, token.LPAREN);
P.Expr(x.X);
P.Token(x.Rparen, token.RPAREN);
}
-func (P *Printer) DoSelector(x *ast.Selector) {
+func (P *Printer) DoSelectorExpr(x *ast.SelectorExpr) {
P.Expr1(x.X, token.HighestPrec);
- P.Token(x.Period, token.PERIOD);
+ P.Token(nopos, token.PERIOD);
P.Expr1(x.Sel, token.HighestPrec);
}
-func (P *Printer) DoTypeAssertion(x *ast.TypeAssertion) {
+func (P *Printer) DoTypeAssertExpr(x *ast.TypeAssertExpr) {
P.Expr1(x.X, token.HighestPrec);
- P.Token(x.Period, token.PERIOD);
- P.Token(x.Lparen, token.LPAREN);
+ P.Token(nopos, token.PERIOD);
+ P.Token(nopos, token.LPAREN);
P.Expr(x.Typ);
- P.Token(x.Rparen, token.RPAREN);
+ P.Token(nopos, token.RPAREN);
}
-func (P *Printer) DoIndex(x *ast.Index) {
+func (P *Printer) DoIndexExpr(x *ast.IndexExpr) {
P.Expr1(x.X, token.HighestPrec);
- P.Token(x.Lbrack, token.LBRACK);
+ P.Token(nopos, token.LBRACK);
P.Expr(x.Index);
- P.Token(x.Rbrack, token.RBRACK);
+ P.Token(nopos, token.RBRACK);
}
-func (P *Printer) DoSlice(x *ast.Slice) {
+func (P *Printer) DoSliceExpr(x *ast.SliceExpr) {
P.Expr1(x.X, token.HighestPrec);
- P.Token(x.Lbrack, token.LBRACK);
- P.Expr(x.Beg);
- P.Token(x.Colon, token.COLON);
+ P.Token(nopos, token.LBRACK);
+ P.Expr(x.Begin);
+ P.Token(nopos, token.COLON);
P.Expr(x.End);
- P.Token(x.Rbrack, token.RBRACK);
+ P.Token(nopos, token.RBRACK);
}
-func (P *Printer) DoCall(x *ast.Call) {
+func (P *Printer) DoCallExpr(x *ast.CallExpr) {
P.Expr1(x.Fun, token.HighestPrec);
P.Token(x.Lparen, token.LPAREN);
P.Exprs(x.Args);
@@ -687,49 +696,38 @@ func (P *Printer) DoCompositeLit(x *ast.CompositeLit) {
func (P *Printer) DoEllipsis(x *ast.Ellipsis) {
- P.Token(x.Loc_, token.ELLIPSIS);
+ P.Token(x.Pos_, token.ELLIPSIS);
}
func (P *Printer) DoArrayType(x *ast.ArrayType) {
- P.Token(x.Loc_, token.LBRACK);
+ P.Token(x.Lbrack, token.LBRACK);
if x.Len != nil {
P.Expr(x.Len);
}
- P.Token(noloc, token.RBRACK);
+ P.Token(nopos, token.RBRACK);
P.Expr(x.Elt);
}
-func (P *Printer) DoTypeType(x *ast.TypeType) {
- P.Token(x.Loc_, token.TYPE);
-}
-
-
func (P *Printer) DoStructType(x *ast.StructType) {
- P.Token(x.Loc_, token.STRUCT);
- if x.End.Pos > 0 {
- P.Fields(x.Fields, x.End, false);
+ P.Token(x.Struct, token.STRUCT);
+ if x.Fields != nil {
+ P.Fields(x.Lbrace, x.Fields, x.Rbrace, false);
}
}
-func (P *Printer) DoPointerType(x *ast.PointerType) {
- P.Token(x.Loc_, token.MUL);
- P.Expr(x.Base);
-}
-
-
func (P *Printer) DoFunctionType(x *ast.FunctionType) {
- P.Token(x.Loc_, token.FUNC);
+ P.Token(x.Func, token.FUNC);
P.Signature(x.Sig);
}
func (P *Printer) DoInterfaceType(x *ast.InterfaceType) {
- P.Token(x.Loc_, token.INTERFACE);
- if x.End.Pos > 0 {
- P.Fields(x.Methods, x.End, true);
+ P.Token(x.Interface, token.INTERFACE);
+ if x.Methods != nil {
+ P.Fields(x.Lbrace, x.Methods, x.Rbrace, true);
}
}
@@ -740,29 +738,29 @@ func (P *Printer) DoSliceType(x *ast.SliceType) {
func (P *Printer) DoMapType(x *ast.MapType) {
- P.Token(x.Loc_, token.MAP);
+ P.Token(x.Map, token.MAP);
P.separator = blank;
- P.Token(noloc, token.LBRACK);
+ P.Token(nopos, token.LBRACK);
P.Expr(x.Key);
- P.Token(noloc, token.RBRACK);
- P.Expr(x.Val);
+ P.Token(nopos, token.RBRACK);
+ P.Expr(x.Value);
}
func (P *Printer) DoChannelType(x *ast.ChannelType) {
switch x.Dir {
- case ast.FULL:
- P.Token(x.Loc_, token.CHAN);
+ case ast.SEND | ast.RECV:
+ P.Token(x.Pos_, token.CHAN);
case ast.RECV:
- P.Token(x.Loc_, token.ARROW);
- P.Token(noloc, token.CHAN);
+ P.Token(x.Pos_, token.ARROW);
+ P.Token(nopos, token.CHAN);
case ast.SEND:
- P.Token(x.Loc_, token.CHAN);
+ P.Token(x.Pos_, token.CHAN);
P.separator = blank;
- P.Token(noloc, token.ARROW);
+ P.Token(nopos, token.ARROW);
}
P.separator = blank;
- P.Expr(x.Val);
+ P.Expr(x.Value);
}
@@ -791,8 +789,86 @@ func (P *Printer) Stat(s ast.Stat) {
}
-func (P *Printer) StatementList(list *vector.Vector) {
- for i := 0; i < list.Len(); i++ {
+func (P *Printer) DoBadStat(s *ast.BadStat) {
+ panic();
+}
+
+
+func (P *Printer) Decl(d ast.Decl);
+
+func (P *Printer) DoDeclStat(s *ast.DeclStat) {
+ P.Decl(s.Decl);
+}
+
+
+func (P *Printer) DoEmptyStat(s *ast.EmptyStat) {
+ P.String(s.Semicolon, "");
+}
+
+
+func (P *Printer) DoLabeledStat(s *ast.LabeledStat) {
+ P.indentation--;
+ P.Expr(s.Label);
+ P.Token(nopos, token.COLON);
+ P.indentation++;
+ // TODO be more clever if s.Stat is a labeled stat as well
+ P.separator = tab;
+ P.Stat(s.Stat);
+}
+
+
+func (P *Printer) DoExprStat(s *ast.ExprStat) {
+ P.Expr(s.X);
+}
+
+
+func (P *Printer) DoIncDecStat(s *ast.IncDecStat) {
+ P.Expr(s.X);
+ P.Token(nopos, s.Tok);
+}
+
+
+func (P *Printer) DoAssignmentStat(s *ast.AssignmentStat) {
+ P.Exprs(s.Lhs);
+ P.separator = blank;
+ P.Token(s.Pos_, s.Tok);
+ P.separator = blank;
+ P.Exprs(s.Rhs);
+}
+
+
+func (P *Printer) DoGoStat(s *ast.GoStat) {
+ P.Token(s.Go, token.GO);
+ P.separator = blank;
+ P.Expr(s.Call);
+}
+
+
+func (P *Printer) DoDeferStat(s *ast.DeferStat) {
+ P.Token(s.Defer, token.DEFER);
+ P.separator = blank;
+ P.Expr(s.Call);
+}
+
+
+func (P *Printer) DoReturnStat(s *ast.ReturnStat) {
+ P.Token(s.Return, token.RETURN);
+ P.separator = blank;
+ P.Exprs(s.Results);
+}
+
+
+func (P *Printer) DoControlFlowStat(s *ast.ControlFlowStat) {
+ P.Token(s.Pos_, s.Tok);
+ if s.Label != nil {
+ P.separator = blank;
+ P.Expr(s.Label);
+ }
+}
+
+
+func (P *Printer) StatementList(list []ast.Stat) {
+ for i, s := range list {
if i == 0 {
P.newlines = 1;
} else { // i > 0
@@ -801,7 +877,7 @@ func (P *Printer) StatementList(list *vector.Vector) {
P.separator = semicolon;
}
}
- P.Stat(list.At(i).(ast.Stat));
+ P.Stat(s);
P.newlines = 1;
P.state = inside_list;
}
@@ -810,7 +886,7 @@ func (P *Printer) StatementList(list *vector.Vector) {
func (P *Printer) Block(b *ast.Block, indent bool) {
P.state = opening_scope;
- P.Token(b.Loc, b.Tok);
+ P.Token(b.Pos_, b.Tok);
if !indent {
P.indentation--;
}
@@ -823,81 +899,14 @@ func (P *Printer) Block(b *ast.Block, indent bool) {
}
P.state = closing_scope;
if b.Tok == token.LBRACE {
- P.Token(b.End, token.RBRACE);
+ P.Token(b.Rparen, token.RBRACE);
P.opt_semi = true;
} else {
- P.String(noloc, ""); // process closing_scope state transition!
+ P.String(nopos, ""); // process closing_scope state transition!
}
}
-func (P *Printer) Decl(d ast.Decl);
-
-func (P *Printer) DoBadStat(s *ast.BadStat) {
- panic();
-}
-
-
-func (P *Printer) DoLabeledStat(s *ast.LabeledStat) {
- P.indentation--;
- P.Expr(s.Label);
- P.Token(s.Loc, token.COLON);
- P.indentation++;
- // TODO be more clever if s.Stat is a labeled stat as well
- P.separator = tab;
- P.Stat(s.Stat);
-}
-
-
-func (P *Printer) DoDeclarationStat(s *ast.DeclarationStat) {
- P.Decl(s.Decl);
-}
-
-
-func (P *Printer) DoExpressionStat(s *ast.ExpressionStat) {
- switch s.Tok {
- case token.ILLEGAL:
- P.Expr(s.Expr);
- case token.INC, token.DEC:
- P.Expr(s.Expr);
- P.Token(s.Loc, s.Tok);
- case token.RETURN, token.GO, token.DEFER:
- P.Token(s.Loc, s.Tok);
- if s.Expr != nil {
- P.separator = blank;
- P.Expr(s.Expr);
- }
- default:
- P.Error(s.Loc, s.Tok, "DoExpressionStat");
- unreachable();
- }
-}
-
-
-func (P *Printer) DoAssignmentStat(s *ast.AssignmentStat) {
- P.Expr(s.Lhs);
- P.separator = blank;
- P.Token(s.Loc, s.Tok);
- P.separator = blank;
- P.Expr(s.Rhs);
-}
-
-
-func (P *Printer) DoTupleAssignStat(s *ast.TupleAssignStat) {
- P.Exprs(s.Lhs);
- P.separator = blank;
- P.Token(s.Loc, s.Tok);
- P.separator = blank;
- P.Exprs(s.Rhs);
-}
-
-
-func (P *Printer) DoIncDecStat(s *ast.IncDecStat) {
- P.Expr(s.Expr);
- P.Token(s.Loc, s.Tok);
-}
-
-
func (P *Printer) DoCompositeStat(s *ast.CompositeStat) {
P.Block(s.Body, true);
}
@@ -910,12 +919,6 @@ func (P *Printer) ControlClause(isForStat bool, init ast.Stat, expr ast.Expr, po
if expr != nil {
P.Expr(expr);
}
- } else if range_clause, ok := init.(*ast.RangeClause); ok {
- // range clause
- P.Stat(range_clause);
- } else if typeswitch_clause, ok := init.(*ast.TypeSwitchClause); ok {
- // type switch clause
- P.Stat(typeswitch_clause);
} else {
// all semicolons required
// (they are not separators, print them explicitly)
@@ -923,14 +926,14 @@ func (P *Printer) ControlClause(isForStat bool, init ast.Stat, expr ast.Expr, po
P.Stat(init);
P.separator = none;
}
- P.Token(noloc, token.SEMICOLON);
+ P.Token(nopos, token.SEMICOLON);
P.separator = blank;
if expr != nil {
P.Expr(expr);
P.separator = none;
}
if isForStat {
- P.Token(noloc, token.SEMICOLON);
+ P.Token(nopos, token.SEMICOLON);
P.separator = blank;
if post != nil {
P.Stat(post);
@@ -942,60 +945,29 @@ func (P *Printer) ControlClause(isForStat bool, init ast.Stat, expr ast.Expr, po
func (P *Printer) DoIfStat(s *ast.IfStat) {
- P.Token(s.Loc, token.IF);
+ P.Token(s.If, token.IF);
P.ControlClause(false, s.Init, s.Cond, nil);
P.Block(s.Body, true);
if s.Else != nil {
P.separator = blank;
- P.Token(noloc, token.ELSE);
+ P.Token(nopos, token.ELSE);
P.separator = blank;
P.Stat(s.Else);
}
}
-func (P *Printer) DoRangeClause(s *ast.RangeClause) {
- P.Exprs(s.Lhs);
- P.separator = blank;
- P.Token(s.Loc, s.Tok);
- P.separator = blank;
- P.Token(noloc, token.RANGE);
- P.separator = blank;
- P.Expr(s.Rhs);
-}
-
-
-func (P *Printer) DoForStat(s *ast.ForStat) {
- P.Token(s.Loc, token.FOR);
- P.ControlClause(true, s.Init, s.Cond, s.Post);
- P.Block(s.Body, true);
-}
-
-
-func (P *Printer) DoTypeSwitchClause(s *ast.TypeSwitchClause) {
- P.Expr(s.Lhs);
- P.separator = blank;
- P.Token(s.Loc, token.DEFINE);
- P.separator = blank;
- P.Expr(s.Rhs);
- P.Token(s.Loc, token.PERIOD);
- P.Token(s.Loc, token.LPAREN);
- P.Token(s.Loc, token.TYPE);
- P.Token(s.Loc, token.RPAREN);
-}
-
-
func (P *Printer) DoCaseClause(s *ast.CaseClause) {
if s.Values != nil {
- P.Token(s.Loc, token.CASE);
+ P.Token(s.Case, token.CASE);
P.separator = blank;
P.Exprs(s.Values);
} else {
- P.Token(s.Loc, token.DEFAULT);
+ P.Token(s.Case, token.DEFAULT);
}
// TODO: try to use P.Block instead
// P.Block(s.Body, true);
- P.Token(s.Body.Loc, token.COLON);
+ P.Token(s.Body.Pos_, token.COLON);
P.indentation++;
P.StatementList(s.Body.List);
P.indentation--;
@@ -1004,36 +976,62 @@ func (P *Printer) DoCaseClause(s *ast.CaseClause) {
func (P *Printer) DoSwitchStat(s *ast.SwitchStat) {
- P.Token(s.Loc, token.SWITCH);
+ P.Token(s.Switch, token.SWITCH);
P.ControlClause(false, s.Init, s.Tag, nil);
P.Block(s.Body, false);
}
-func (P *Printer) DoTypeSwitchStat(s *ast.SwitchStat) {
- P.Token(s.Loc, token.SWITCH);
- P.ControlClause(false, s.Init, s.Tag, nil);
+func (P *Printer) DoTypeCaseClause(s *ast.TypeCaseClause) {
+ if s.Typ != nil {
+ P.Token(s.Case, token.CASE);
+ P.separator = blank;
+ P.Expr(s.Typ);
+ } else {
+ P.Token(s.Case, token.DEFAULT);
+ }
+ // TODO: try to use P.Block instead
+ // P.Block(s.Body, true);
+ P.Token(s.Body.Pos_, token.COLON);
+ P.indentation++;
+ P.StatementList(s.Body.List);
+ P.indentation--;
+ P.newlines = 1;
+}
+
+
+func (P *Printer) DoTypeSwitchStat(s *ast.TypeSwitchStat) {
+ P.Token(s.Switch, token.SWITCH);
+ P.separator = blank;
+ if s.Init != nil {
+ P.Stat(s.Init);
+ P.separator = none;
+ P.Token(nopos, token.SEMICOLON);
+ }
+ P.separator = blank;
+ P.Stat(s.Assign);
+ P.separator = blank;
P.Block(s.Body, false);
}
func (P *Printer) DoCommClause(s *ast.CommClause) {
if s.Rhs != nil {
- P.Token(s.Loc, token.CASE);
+ P.Token(s.Case, token.CASE);
P.separator = blank;
if s.Lhs != nil {
P.Expr(s.Lhs);
P.separator = blank;
- P.Token(noloc, s.Tok);
+ P.Token(nopos, s.Tok);
P.separator = blank;
}
P.Expr(s.Rhs);
} else {
- P.Token(s.Loc, token.DEFAULT);
+ P.Token(s.Case, token.DEFAULT);
}
// TODO: try to use P.Block instead
// P.Block(s.Body, true);
- P.Token(s.Body.Loc, token.COLON);
+ P.Token(s.Body.Pos_, token.COLON);
P.indentation++;
P.StatementList(s.Body.List);
P.indentation--;
@@ -1042,30 +1040,25 @@ func (P *Printer) DoCommClause(s *ast.CommClause) {
func (P *Printer) DoSelectStat(s *ast.SelectStat) {
- P.Token(s.Loc, token.SELECT);
+ P.Token(s.Select, token.SELECT);
P.separator = blank;
P.Block(s.Body, false);
}
-func (P *Printer) DoControlFlowStat(s *ast.ControlFlowStat) {
- P.Token(s.Loc, s.Tok);
- if s.Label != nil {
- P.separator = blank;
- P.Expr(s.Label);
- }
+func (P *Printer) DoForStat(s *ast.ForStat) {
+ P.Token(s.For, token.FOR);
+ P.ControlClause(true, s.Init, s.Cond, s.Post);
+ P.Block(s.Body, true);
}
-func (P *Printer) DoReturnStat(s *ast.ReturnStat) {
- P.Token(s.Loc, token.RETURN);
+func (P *Printer) DoRangeStat(s *ast.RangeStat) {
+ P.Token(s.For, token.FOR);
P.separator = blank;
- P.Exprs(s.Results);
-}
-
-
-func (P *Printer) DoEmptyStat(s *ast.EmptyStat) {
- P.String(s.Loc, "");
+ P.Stat(s.Range);
+ P.separator = blank;
+ P.Block(s.Body, true);
}
@@ -1073,13 +1066,13 @@ func (P *Printer) DoEmptyStat(s *ast.EmptyStat) {
// Declarations
func (P *Printer) DoBadDecl(d *ast.BadDecl) {
- P.String(d.Loc, "Constants
\n");
P.Printf("");
P.DoConstDecl(d);
- P.String(noloc, "");
+ P.String(nopos, "");
P.Printf("
"); P.DoTypeDecl(d); - P.String(noloc, ""); + P.String(nopos, ""); P.Printf("\n"); - if d.Comment != nil { - P.printComment(d.Comment); + if d.Doc != nil { + P.printComment(d.Doc); } } @@ -1287,10 +1277,10 @@ func (P *Printer) Interface(p *ast.Program) { P.Printf("
"); P.DoVarDecl(d); - P.String(noloc, ""); + P.String(nopos, ""); P.Printf("\n"); - if d.Comment != nil { - P.printComment(d.Comment); + if d.Doc != nil { + P.printComment(d.Doc); } } @@ -1299,16 +1289,16 @@ func (P *Printer) Interface(p *ast.Program) { if d.Recv != nil { P.Printf("
");
P.DoFuncDecl(d);
- P.String(noloc, "");
+ P.String(nopos, "");
P.Printf("