blob: e4c257309d884dad670acff4b6557f5482084e58 [file] [log] [blame]
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Format file for printing AST nodes.
ast "ast";
token "token";
// ----------------------------------------------------------------------------
// Basic types, support rules
array =
*;
ptr =
*;
string =
"%s";
char =
"%c";
bytes =
{*};
empty =
;
exists =
*:empty;
ast.Expr =
*;
ast.Stmt =
*;
ast.Decl =
*;
// ----------------------------------------------------------------------------
// Tokens and comments
token.Token =
@:string;
ast.Comment =
// TODO this doesn't indent properly after //-style comments because
// the '\n'-char is printed as part of the comment - need to
// address this
Text:string [Text:isMultiLineComment "\n"];
ast.Comments =
{*};
// ----------------------------------------------------------------------------
// Expressions & Types
ast.Field =
[Names:exists {Names / ", "} " "] Type;
ast.BadExpr =
"BAD EXPR";
ast.Ident =
Value;
ast.Ellipsis =
"...";
ast.IntLit =
Value:string;
ast.FloatLit =
Value:string;
ast.CharLit =
Value:string;
ast.StringLit =
Value:string;
ast.StringList =
{Strings / "\n"};
ast.FuncLit =
Type " " Body @:clearOptSemi; // no optional ; after a func literal body
ast.CompositeLit =
Type "{" {Elts / ", "} "}";
ast.ParenExpr =
"(" X ")";
ast.SelectorExpr =
X "." Sel;
ast.IndexExpr =
X "[" Index [":" End] "]";
ast.TypeAssertExpr =
X ".(" Type ")";
ast.CallExpr =
Fun "(" {Args / ", "} ")";
ast.StarExpr =
"*" X;
ast.UnaryExpr =
Op X;
ast.BinaryExpr =
X " " Op " " Y;
ast.KeyValueExpr =
Key ": " Value;
ast.ArrayType =
"[" [Len] "]" Elt;
ast.StructType =
"struct"
[Lbrace:isValidPos " {"]
[ Fields:exists
( "\t" >> "\n"
{Fields / ";\n"}
) "\n"
]
[Rbrace:isValidPos "}"];
signature =
"(" {Params / ", "} ")" [Results:exists " (" {Results / ", "} ")"];
funcSignature =
*:signature;
ast.FuncType =
[Position:isValidPos "func"] @:signature;
ast.InterfaceType =
"interface"
[Lbrace:isValidPos " {"]
[ Methods:exists
( "\t" >> "\n"
{Methods / ";\n"}
) "\n"
]
[Rbrace:isValidPos "}"];
ast.MapType =
"map[" Key "]" Value;
ast.ChanType =
( Dir:isSend Dir:isRecv
"chan "
| Dir:isSend
"chan <- "
| "<-chan "
)
Value;
// ----------------------------------------------------------------------------
// Statements
ast.BadStmt =
"BAD STMT";
ast.DeclStmt =
Decl;
ast.EmptyStmt =
;
ast.LabeledStmt =
Label ":\t" Stmt;
ast.ExprStmt =
X;
ast.IncDecStmt =
X Tok;
ast.AssignStmt =
{Lhs / ", "} " " Tok " " {Rhs / ", "};
ast.GoStmt =
"go " Call;
ast.DeferStmt =
"defer " Call;
ast.ReturnStmt =
"return" {" " Results / ","};
ast.BranchStmt =
Tok [" " Label];
stmtList =
{@ / @:optSemi "\n"};
blockStmt = // like ast.BlockStmt but w/o indentation
"{"
[List:exists
"\n"
List:stmtList
"\n"
]
"}" @:setOptSemi;
blockStmtPtr =
*:blockStmt;
ast.BlockStmt =
"{"
[List:exists
( "\t" >> "\n"
List:stmtList
) "\n"
]
"}" @:setOptSemi;
ast.IfStmt =
"if " [Init "; "] [Cond " "] Body [" else " Else];
ast.CaseClause =
( Values:exists "case " {Values / ", "}
| "default"
)
":"
[Body:exists
( "\t" >> "\n"
Body:stmtList
)
];
ast.SwitchStmt =
"switch " [Init "; "] [Tag " "]
Body:blockStmtPtr;
ast.TypeCaseClause =
( Type:exists "case " Type
| "default"
)
":"
[Body:exists
( "\t" >> "\n"
Body:stmtList
)
];
ast.TypeSwitchStmt =
"switch " Assign " "
Body:blockStmtPtr;
ast.CommClause =
( "case " [Lhs " " Tok " "] Rhs
| "default"
)
":"
[Body:exists
( "\t" >> "\n"
Body:stmtList
)
];
ast.SelectStmt =
"select "
Body:blockStmtPtr;
ast.ForStmt =
"for "
[ (Init:exists | Post:exists)
[Init] "; " [Cond] "; " [Post " "]
| Cond " "
]
Body;
ast.RangeStmt =
"for " Key [", " Value] " " Tok " range " X
" "
Body;
// ----------------------------------------------------------------------------
// Declarations
ast.Spec =
*;
ast.ImportSpec =
Doc
[Name] "\t" {Path};
ast.ValueSpec =
{Names / ", "} [" " Type] [Values:exists " = " {Values / ", "}];
ast.TypeSpec =
Name " " // TODO using "\t" instead of " " screws up struct field alignment
Type;
ast.BadDecl =
"BAD DECL";
ast.GenDecl =
Doc
Tok " "
( Lparen:isValidPos "("
[Specs:exists
( "\t" >> "\n"
{Specs / ";\n"}
) "\n"
]
")" @:setOptSemi
| {Specs / ";\n"}
);
ast.FuncDecl =
"func " ["(" Recv ") "] Name Type:funcSignature
[" " Body]
"\n";
// ----------------------------------------------------------------------------
// Program
ast.Program =
Doc
"package " Name "\n\n"
{Decls / "\n\n"};