| // 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"}; |