Commit 0d6a5f41 authored by Robert Griesemer's avatar Robert Griesemer

weekly snapshot:

- template-driven ast printing now can successfully
  reproduce entire Go programs

next steps:
- fine-tuning of output
- print interspersed comments
- cleanup and testing against all Go programs
- replace astprinter

R=r
OCL=28181
CL=28181
parent 49f74948
...@@ -2,216 +2,314 @@ ...@@ -2,216 +2,314 @@
// Use of this source code is governed by a BSD-style // Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
// Format file for printing AST nodes (package "ast").
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Debugging // Debugging
token.Token = token.Token =
^ : "%s"; ^:string;
array =
*;
pointer =
*;
string =
"%s";
char =
"%c";
bytes =
{*};
nil =
; // TODO we see a lot of nil's - why?
not_empty =
*:nil;
// Format file for printing AST nodes (package "ast").
ast;
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// TODO should these be automatic? // TODO these are implicit - only here for debugging
Expr = ast.Expr =
"expr "; *;
//*;
Stmt = ast.Stmt =
*; *;
Decl = ast.Decl =
*; *;
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Comments // Comments
Comment = ast.Comment =
Text : "%s\n"; Text:string "\n";
Comments = ast.Comments =
{*}; {*};
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Expressions & Types // Expressions & Types
Field = ast.Field =
{Names ", "} Type; [Names:not_empty {Names / ", "} " "] Type;
BadExpr = ast.BadExpr =
"BAD EXPR"; "BAD EXPR";
Ident = ast.Ident =
Value; Value;
Elipsis = ast.Ellipsis =
"..."; "...";
IntLit = ast.IntLit =
Value : "%s"; Value:string;
FloatLit = ast.FloatLit =
Value : "%s"; Value:string;
CharLit = ast.CharLit =
Value : "%s"; Value:string;
StringLit = ast.StringLit =
Value : "%s"; Value:string;
StringList = ast.StringList =
{ Strings }; {Strings / "\n"};
FuncLit = ast.FuncLit =
"func "; "func ";
CompositeLit = ast.CompositeLit =
Type "{}"; Type "{" {Elts / ", "} "}";
ParenExpr = ast.ParenExpr =
"(" X ")"; "(" X ")";
SelectorExpr = ast.SelectorExpr =
X "." Sel; X "." Sel;
IndexExpr = ast.IndexExpr =
X "[" Index "]"; X "[" Index "]";
SliceExpr = ast.SliceExpr =
X "[" Begin " : " End "]"; X "[" Begin ":" End "]";
TypeAssertExpr = ast.TypeAssertExpr =
X ".(" Type ")"; X ".(" Type ")";
CallExpr = ast.CallExpr =
Fun "(" {Args} ")"; Fun "(" {Args / ", "} ")";
StarExpr = ast.StarExpr =
"*" X; "*" X;
UnaryExpr = ast.UnaryExpr =
Op X; Op X;
BinaryExpr = ast.BinaryExpr =
X Op Y; X " " Op " " Y;
KeyValueExpr = ast.KeyValueExpr =
Key ": " Value; Key ": " Value;
ArrayType = ast.ArrayType =
"[" Len "]" Elt; "[" Len "]" Elt;
SliceType = ast.SliceType =
"[]" Elt; "[]" Elt;
StructType = ast.StructType =
"struct {\n" "struct {"
[Fields:not_empty
>> "\t" "\n"
{Fields / ";\n"}
<< "\n"
]
"}"; "}";
FuncType = signature =
"(" {Params " "} ")"; "(" {Params / ", "} ")" [Results:not_empty " (" {Results / ", "} ")"];
funcSignature =
*:signature;
ast.FuncType =
"func" ^:signature;
// BUG take this one away and the code crashes ast.InterfaceType =
InterfaceType = "interface {"
"interface {}"; [Methods:not_empty
>> "\t" "\n"
{Methods / ";\n"} // TODO should not start with "func"
<< "\n"
]
"}";
MapType = ast.MapType =
"map[" Key "]" Value; "map[" Key "]" Value;
ChanType = ast.ChanType =
"chan"; "chan";
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Statements // Statements
BadStmt = ast.BadStmt =
"BAD STMT"; "BAD STMT";
DeclStmt = ast.DeclStmt =
Decl; Decl;
EmptyStmt = ast.EmptyStmt =
; ;
LabeledStmt = ast.LabeledStmt =
Label ":\t" Stmt; Label ":\t" Stmt;
ExprStmt = ast.ExprStmt =
X; X;
IncDecStmt = ast.IncDecStmt =
X Tok; X Tok;
AssignStmt = ast.AssignStmt =
"assignment " {Lhs ", "}; {Lhs / ", "} " " Tok " " {Rhs / ", "};
//{Lhs ", "} Tok {Rhs ", "};
GoStmt = ast.GoStmt =
"go " Call; "go " Call;
ReturnStmt = ast.ReturnStmt =
"return" {" " Results}; "return" {" " Results / ","};
BranchStmt = ast.BranchStmt =
Tok [" " Label]; Tok [" " Label];
BlockStmt = blockStmt = // like ast.BlockStmt but w/o indentation
"{\n" {List ";\n"} "}\n"; "{"
[List:not_empty
IfStmt = "\n"
"if " "{" [Body] "}" [Else]; {List / ";\n"}
"\n"
SwitchStmt = ]
"switch {}"; "}";
TypeSwitchStmt =
"switch {}";
SelectStmt = blockStmtPtr =
"select {}"; *:blockStmt;
ForStmt = ast.BlockStmt =
"for {}"; "{"
[List:not_empty
>> "\t" "\n"
{List / ";\n"}
<< "\n"
]
"}";
RangeStmt = ast.IfStmt =
"range"; "if " [Init "; "] [Cond " "] Body [" else " Else];
ast.CaseClause =
( Values:not_empty "case " {Values / ", "}
| "default"
)
":"
[Body:not_empty
>> "\t" "\n"
{Body / ";\n"}
<<
];
ast.SwitchStmt =
"switch " [Init "; "] [Tag " "]
Body:blockStmtPtr;
ast.TypeCaseClause =
( Type:not_empty "case " Type
| "default"
)
":"
[Body:not_empty
>> "\t" "\n"
{Body / ";\n"}
<<
];
ast.TypeSwitchStmt =
"switch " Assign " "
Body:blockStmtPtr;
ast.CommClause =
"CommClause";
ast.SelectStmt =
"select "
Body:blockStmtPtr;
ast.ForStmt =
"for "
[ Init:not_empty
[Init] "; " [Cond] "; " [Post " "]
| Post:not_empty
[Init] "; " [Cond] "; " [Post " "]
| Cond " "
]
Body;
ast.RangeStmt =
"for " Key [", " Value] " " Tok " range " X
" "
Body;
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Declarations // Declarations
Spec = ast.Spec =
*; *;
ImportSpec = ast.ImportSpec =
"import"; Doc
[Name] "\t" {Path};
ValueSpec = ast.ValueSpec =
"value"; {Names / ", "} [" " Type] [Values:not_empty " = " {Values / ", "}];
TypeSpec = ast.TypeSpec =
"type"; Name " " // TODO using "\t" instead of " " screws up struct field alignment
Type;
BadDecl = ast.BadDecl =
"BAD DECL"; "BAD DECL";
GenDecl = ast.GenDecl =
Doc Doc
Tok " (\n" Tok " ("
")\n"; >> "\t" "\n"
{Specs / ";\n"}
FuncDecl = <<
"func " ["(" Recv ") "] Name Type [" " Body]; "\n"
")";
ast.FuncDecl =
"func " ["(" Recv ") "] Name Type:funcSignature
[" " Body]
"\n";
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Program // Program
Program = ast.Program =
Doc Doc
"package " Name "\n\n" "package " Name "\n\n"
{Decls "\n\n"}; {Decls / "\n\n"};
This diff is collapsed.
...@@ -11,10 +11,10 @@ import ( ...@@ -11,10 +11,10 @@ import (
func check(t *testing.T, form, expected string, args ...) { func check(t *testing.T, form, expected string, args ...) {
result := format.Parse(form).Sprint(args); result := format.Parse(form, nil).Sprint(args);
if result != expected { if result != expected {
t.Errorf( t.Errorf(
"format : %s\nresult : %s\nexpected: %s\n\n", "format : %s\nresult : `%s`\nexpected: `%s`\n\n",
form, result, expected form, result, expected
) )
} }
...@@ -22,13 +22,19 @@ func check(t *testing.T, form, expected string, args ...) { ...@@ -22,13 +22,19 @@ func check(t *testing.T, form, expected string, args ...) {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// - formatting of basic type int // Syntax
const F0 = func TestA(t *testing.T) {
`int = "0x%x";` // TODO fill this in
}
// ----------------------------------------------------------------------------
// - formatting of basic types
func Test0(t *testing.T) { func Test0(t *testing.T) {
check(t, F0, "0x2a", 42); check(t, `bool = "%v"`, "false", false);
check(t, `int = "%b %d %o 0x%x"`, "101010 42 52 0x2a", 42);
} }
...@@ -60,7 +66,7 @@ type T2 struct { ...@@ -60,7 +66,7 @@ type T2 struct {
const F2a = const F2a =
F1 + F1 +
`pointer = *;` `pointer = *;`
`format.T2 = s ["-" p "-"];`; `format.T2 = s ["-" p "-"];`
const F2b = const F2b =
F1 + F1 +
...@@ -82,14 +88,43 @@ type T3 struct { ...@@ -82,14 +88,43 @@ type T3 struct {
} }
const F3a = const F3a =
`format.T3 = s { " " a a "," };`; `format.T3 = s {" " a a / ","};`
const F3b = const F3b =
`format.T3 = [a:""] s | "nothing";`; // use 'a' to select alternative w/o printing a `nil = ;`
`empty = *:nil;`
`format.T3 = s [a:empty ": " {a / "-"}]`
func Test3(t *testing.T) { func Test3(t *testing.T) {
check(t, F3a, "foo", T3{"foo", nil}); check(t, F3a, "foo", T3{"foo", nil});
check(t, F3a, "foo 00, 11, 22,", T3{"foo", []int{0, 1, 2}}); check(t, F3a, "foo 00, 11, 22", T3{"foo", []int{0, 1, 2}});
//check(t, F3b, "nothing", T3{"bar", nil}); // TODO fix this check(t, F3b, "bar", T3{"bar", nil});
check(t, F3b, "bar", T3{"bar", []int{0}}); check(t, F3b, "bal: 2-3-5", T3{"bal", []int{2, 3, 5}});
}
// ----------------------------------------------------------------------------
// - formatting of a struct with alternative field
type T4 struct {
x *int;
a []int;
}
const F4a =
`nil = ;`
`empty = *:nil;`
`format.T4 = "<" (x:empty x | "-") ">" `
const F4b =
`nil = ;`
`empty = *:nil;`
`format.T4 = "<" (a:empty {a / ", "} | "-") ">" `
func Test4(t *testing.T) {
x := 7;
check(t, F4a, "<->", T4{nil, nil});
check(t, F4a, "<7>", T4{&x, nil});
check(t, F4b, "<->", T4{nil, nil});
check(t, F4b, "<2, 3, 7>", T4{nil, []int{2, 3, 7}});
} }
...@@ -66,7 +66,7 @@ func makeTabwriter(writer io.Write) *tabwriter.Writer { ...@@ -66,7 +66,7 @@ func makeTabwriter(writer io.Write) *tabwriter.Writer {
if *usetabs { if *usetabs {
padchar = '\t'; padchar = '\t';
} }
return tabwriter.NewWriter(writer, *tabwidth, 1, padchar, tabwriter.FilterHTML); return tabwriter.NewWriter(writer, *tabwidth, 1, padchar, 0);
} }
...@@ -114,7 +114,7 @@ func main() { ...@@ -114,7 +114,7 @@ func main() {
fmt.Fprintf(os.Stderr, "%s: %v\n", ast_txt, err); fmt.Fprintf(os.Stderr, "%s: %v\n", ast_txt, err);
sys.Exit(1); sys.Exit(1);
} }
ast_format := format.Parse(src); ast_format := format.Parse(src, nil);
if ast_format == nil { if ast_format == nil {
fmt.Fprintf(os.Stderr, "%s: format errors\n", ast_txt); fmt.Fprintf(os.Stderr, "%s: format errors\n", ast_txt);
sys.Exit(1); sys.Exit(1);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment