Sel *Ident; // field selector
};
- // An IndexExpr node represents an expression followed by an index.
+ // An IndexExpr node represents an expression followed by an index or slice.
IndexExpr struct {
X Expr; // expression
- Index Expr; // index expression
- };
-
- // A SliceExpr node represents an expression followed by a slice.
- SliceExpr struct {
- X Expr; // expression
- Begin, End Expr; // slice range
+ Index Expr; // index expression or beginning of slice range
+ End Expr; // end of slice range; or nil
};
// A TypeAssertExpr node represents an expression followed by a
// nodes.
//
type (
- // An ArrayType node represents an array type.
+ // An ArrayType node represents an array or slice type.
ArrayType struct {
token.Position; // position of "["
- Len Expr; // possibly an Ellipsis node for [...]T array types
- Elt Expr; // element type
- };
-
- // A SliceType node represents a slice type.
- SliceType struct {
- token.Position; // position of "["
+ Len Expr; // Ellipsis node for [...]T array types, nil for slice types
Elt Expr; // element type
};
func (x *CompositeLit) Pos() token.Position { return x.Type.Pos(); }
func (x *SelectorExpr) Pos() token.Position { return x.X.Pos(); }
func (x *IndexExpr) Pos() token.Position { return x.X.Pos(); }
-func (x *SliceExpr) Pos() token.Position { return x.X.Pos(); }
func (x *TypeAssertExpr) Pos() token.Position { return x.X.Pos(); }
func (x *CallExpr) Pos() token.Position { return x.Fun.Pos(); }
func (x *BinaryExpr) Pos() token.Position { return x.X.Pos(); }
DoParenExpr(x *ParenExpr);
DoSelectorExpr(x *SelectorExpr);
DoIndexExpr(x *IndexExpr);
- DoSliceExpr(x *SliceExpr);
DoTypeAssertExpr(x *TypeAssertExpr);
DoCallExpr(x *CallExpr);
DoStarExpr(x *StarExpr);
// Type expressions
DoEllipsis(x *Ellipsis);
DoArrayType(x *ArrayType);
- DoSliceType(x *SliceType);
DoStructType(x *StructType);
DoFuncType(x *FuncType);
DoInterfaceType(x *InterfaceType);
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 *KeyValueExpr) Visit(v ExprVisitor) { v.DoKeyValueExpr(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 *FuncType) Visit(v ExprVisitor) { v.DoFuncType(x); }
func (x *InterfaceType) Visit(v ExprVisitor) { v.DoInterfaceType(x); }
}
-func (p *parser) parseArrayOrSliceType(ellipsis_ok bool) ast.Expr {
+func (p *parser) parseArrayType(ellipsis_ok bool) ast.Expr {
if p.trace {
- defer un(trace(p, "ArrayOrSliceType"));
+ defer un(trace(p, "ArrayType"));
}
lbrack := p.expect(token.LBRACK);
p.expect(token.RBRACK);
elt := p.parseType();
- if len != nil {
- return &ast.ArrayType{lbrack, len, elt};
- }
-
- return &ast.SliceType{lbrack, elt};
+ return &ast.ArrayType{lbrack, len, elt};
}
func (p *parser) tryRawType(ellipsis_ok bool) ast.Expr {
switch p.tok {
case token.IDENT: return p.parseTypeName();
- case token.LBRACK: return p.parseArrayOrSliceType(ellipsis_ok);
+ case token.LBRACK: return p.parseArrayType(ellipsis_ok);
case token.STRUCT: return p.parseStructType();
case token.MUL: return p.parsePointerType();
case token.FUNC: return p.parseFuncType();
}
-func (p *parser) parseIndexOrSlice(x ast.Expr) ast.Expr {
+func (p *parser) parseIndex(x ast.Expr) ast.Expr {
if p.trace {
- defer un(trace(p, "IndexOrSlice"));
+ defer un(trace(p, "Index"));
}
p.expect(token.LBRACK);
p.expr_lev--;
p.expect(token.RBRACK);
- if end != nil {
- return &ast.SliceExpr{x, begin, end};
- }
-
- return &ast.IndexExpr{x, begin};
+ return &ast.IndexExpr{x, begin, end};
}
case *ast.ParenExpr:
case *ast.SelectorExpr:
case *ast.IndexExpr:
- case *ast.SliceExpr:
case *ast.TypeAssertExpr:
case *ast.CallExpr:
case *ast.StarExpr:
case *ast.ParenExpr: p.checkCompositeLitType(t.X);
case *ast.SelectorExpr: p.checkTypeName(t.X);
case *ast.ArrayType: return x;
- case *ast.SliceType: return x;
case *ast.StructType: return x;
case *ast.MapType: return x;
default:
for {
switch p.tok {
case token.PERIOD: x = p.parseSelectorOrTypeAssertion(p.checkExpr(x));
- case token.LBRACK: x = p.parseIndexOrSlice(p.checkExpr(x));
+ case token.LBRACK: x = p.parseIndex(p.checkExpr(x));
case token.LPAREN: x = p.parseCallOrConversion(p.checkExprOrType(x));
case token.LBRACE:
if p.expr_lev >= 0 {
// Format file for printing AST nodes (package "ast").
// ----------------------------------------------------------------------------
-// Debugging
+// Elementary types
token.Token =
^:string;
bytes =
{*};
-nil =
- ; // TODO we see a lot of nil's - why?
+empty =
+ ;
exists =
- *:nil;
+ *:empty;
// ----------------------------------------------------------------------------
X "." Sel;
ast.IndexExpr =
- X "[" Index "]";
-
-ast.SliceExpr =
- X "[" Begin ":" End "]";
+ X "[" Index [":" End] "]";
ast.TypeAssertExpr =
X ".(" Type ")";
Key ": " Value;
ast.ArrayType =
- "[" Len "]" Elt;
-
-ast.SliceType =
- "[]" Elt;
+ "[" [Len] "]" Elt;
ast.StructType =
"struct"
P.Expr1(x.X, token.HighestPrec);
P.Token(noPos, token.LBRACK);
P.Expr(x.Index);
- P.Token(noPos, token.RBRACK);
-}
-
-
-func (P *Printer) DoSliceExpr(x *ast.SliceExpr) {
- P.Expr1(x.X, token.HighestPrec);
- P.Token(noPos, token.LBRACK);
- P.Expr(x.Begin);
- P.Token(noPos, token.COLON);
- P.Expr(x.End);
+ if x.End != nil {
+ P.Token(noPos, token.COLON);
+ P.Expr(x.End);
+ }
P.Token(noPos, token.RBRACK);
}
func (P *Printer) DoArrayType(x *ast.ArrayType) {
P.Token(x.Pos(), token.LBRACK);
- P.Expr(x.Len);
- P.Token(noPos, token.RBRACK);
- P.Expr(x.Elt);
-}
-
-
-func (P *Printer) DoSliceType(x *ast.SliceType) {
- P.Token(x.Pos(), token.LBRACK);
+ if x.Len != nil {
+ P.Expr(x.Len);
+ }
P.Token(noPos, token.RBRACK);
P.Expr(x.Elt);
}