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 @@
// 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 (package "ast").
// ----------------------------------------------------------------------------
// Debugging
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 =
"expr ";
//*;
ast.Expr =
*;
Stmt =
ast.Stmt =
*;
Decl =
ast.Decl =
*;
// ----------------------------------------------------------------------------
// Comments
Comment =
Text : "%s\n";
ast.Comment =
Text:string "\n";
Comments =
ast.Comments =
{*};
// ----------------------------------------------------------------------------
// Expressions & Types
Field =
{Names ", "} Type;
ast.Field =
[Names:not_empty {Names / ", "} " "] Type;
BadExpr =
ast.BadExpr =
"BAD EXPR";
Ident =
ast.Ident =
Value;
Elipsis =
ast.Ellipsis =
"...";
IntLit =
Value : "%s";
ast.IntLit =
Value:string;
FloatLit =
Value : "%s";
ast.FloatLit =
Value:string;
CharLit =
Value : "%s";
ast.CharLit =
Value:string;
StringLit =
Value : "%s";
ast.StringLit =
Value:string;
StringList =
{ Strings };
ast.StringList =
{Strings / "\n"};
FuncLit =
ast.FuncLit =
"func ";
CompositeLit =
Type "{}";
ast.CompositeLit =
Type "{" {Elts / ", "} "}";
ParenExpr =
ast.ParenExpr =
"(" X ")";
SelectorExpr =
ast.SelectorExpr =
X "." Sel;
IndexExpr =
ast.IndexExpr =
X "[" Index "]";
SliceExpr =
X "[" Begin " : " End "]";
ast.SliceExpr =
X "[" Begin ":" End "]";
TypeAssertExpr =
ast.TypeAssertExpr =
X ".(" Type ")";
CallExpr =
Fun "(" {Args} ")";
ast.CallExpr =
Fun "(" {Args / ", "} ")";
StarExpr =
ast.StarExpr =
"*" X;
UnaryExpr =
ast.UnaryExpr =
Op X;
BinaryExpr =
X Op Y;
ast.BinaryExpr =
X " " Op " " Y;
KeyValueExpr =
ast.KeyValueExpr =
Key ": " Value;
ArrayType =
ast.ArrayType =
"[" Len "]" Elt;
SliceType =
ast.SliceType =
"[]" Elt;
StructType =
"struct {\n"
ast.StructType =
"struct {"
[Fields:not_empty
>> "\t" "\n"
{Fields / ";\n"}
<< "\n"
]
"}";
FuncType =
"(" {Params " "} ")";
signature =
"(" {Params / ", "} ")" [Results:not_empty " (" {Results / ", "} ")"];
funcSignature =
*:signature;
ast.FuncType =
"func" ^:signature;
// BUG take this one away and the code crashes
InterfaceType =
"interface {}";
ast.InterfaceType =
"interface {"
[Methods:not_empty
>> "\t" "\n"
{Methods / ";\n"} // TODO should not start with "func"
<< "\n"
]
"}";
MapType =
ast.MapType =
"map[" Key "]" Value;
ChanType =
ast.ChanType =
"chan";
// ----------------------------------------------------------------------------
// Statements
BadStmt =
ast.BadStmt =
"BAD STMT";
DeclStmt =
ast.DeclStmt =
Decl;
EmptyStmt =
ast.EmptyStmt =
;
LabeledStmt =
ast.LabeledStmt =
Label ":\t" Stmt;
ExprStmt =
ast.ExprStmt =
X;
IncDecStmt =
ast.IncDecStmt =
X Tok;
AssignStmt =
"assignment " {Lhs ", "};
//{Lhs ", "} Tok {Rhs ", "};
ast.AssignStmt =
{Lhs / ", "} " " Tok " " {Rhs / ", "};
GoStmt =
ast.GoStmt =
"go " Call;
ReturnStmt =
"return" {" " Results};
ast.ReturnStmt =
"return" {" " Results / ","};
BranchStmt =
ast.BranchStmt =
Tok [" " Label];
BlockStmt =
"{\n" {List ";\n"} "}\n";
IfStmt =
"if " "{" [Body] "}" [Else];
SwitchStmt =
"switch {}";
TypeSwitchStmt =
"switch {}";
blockStmt = // like ast.BlockStmt but w/o indentation
"{"
[List:not_empty
"\n"
{List / ";\n"}
"\n"
]
"}";
SelectStmt =
"select {}";
blockStmtPtr =
*:blockStmt;
ForStmt =
"for {}";
ast.BlockStmt =
"{"
[List:not_empty
>> "\t" "\n"
{List / ";\n"}
<< "\n"
]
"}";
RangeStmt =
"range";
ast.IfStmt =
"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
Spec =
ast.Spec =
*;
ImportSpec =
"import";
ast.ImportSpec =
Doc
[Name] "\t" {Path};
ValueSpec =
"value";
ast.ValueSpec =
{Names / ", "} [" " Type] [Values:not_empty " = " {Values / ", "}];
TypeSpec =
"type";
ast.TypeSpec =
Name " " // TODO using "\t" instead of " " screws up struct field alignment
Type;
BadDecl =
ast.BadDecl =
"BAD DECL";
GenDecl =
ast.GenDecl =
Doc
Tok " (\n"
")\n";
FuncDecl =
"func " ["(" Recv ") "] Name Type [" " Body];
Tok " ("
>> "\t" "\n"
{Specs / ";\n"}
<<
"\n"
")";
ast.FuncDecl =
"func " ["(" Recv ") "] Name Type:funcSignature
[" " Body]
"\n";
// ----------------------------------------------------------------------------
// Program
Program =
ast.Program =
Doc
"package " Name "\n\n"
{Decls "\n\n"};
{Decls / "\n\n"};
This diff is collapsed.
......@@ -11,10 +11,10 @@ import (
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 {
t.Errorf(
"format : %s\nresult : %s\nexpected: %s\n\n",
"format : %s\nresult : `%s`\nexpected: `%s`\n\n",
form, result, expected
)
}
......@@ -22,13 +22,19 @@ func check(t *testing.T, form, expected string, args ...) {
// ----------------------------------------------------------------------------
// - formatting of basic type int
// Syntax
const F0 =
`int = "0x%x";`
func TestA(t *testing.T) {
// TODO fill this in
}
// ----------------------------------------------------------------------------
// - formatting of basic types
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 {
const F2a =
F1 +
`pointer = *;`
`format.T2 = s ["-" p "-"];`;
`format.T2 = s ["-" p "-"];`
const F2b =
F1 +
......@@ -82,14 +88,43 @@ type T3 struct {
}
const F3a =
`format.T3 = s { " " a a "," };`;
`format.T3 = s {" " a a / ","};`
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) {
check(t, F3a, "foo", T3{"foo", nil});
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", []int{0}});
check(t, F3a, "foo 00, 11, 22", T3{"foo", []int{0, 1, 2}});
check(t, F3b, "bar", T3{"bar", nil});
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 {
if *usetabs {
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() {
fmt.Fprintf(os.Stderr, "%s: %v\n", ast_txt, err);
sys.Exit(1);
}
ast_format := format.Parse(src);
ast_format := format.Parse(src, nil);
if ast_format == nil {
fmt.Fprintf(os.Stderr, "%s: format errors\n", ast_txt);
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