snapshot of pretty printer:

- almost there, receivers, labels, composites, comments are not yet printed
- runs through 18KLOC of Go code and prints it again

R=r
OCL=17237
CL=17237
This commit is contained in:
Robert Griesemer 2008-10-15 17:06:28 -07:00
parent 13508ceabe
commit 6b49713df5
4 changed files with 233 additions and 135 deletions

View File

@ -36,18 +36,26 @@ test: pretty
testnoisy: pretty
pretty *.go
pretty ../gosrc/*.go
#pretty $(GOROOT)/test/*.go # contains incorrect programs
pretty $(GOROOT)/test/235.go
pretty $(GOROOT)/test/args.go
pretty $(GOROOT)/test/bufiolib.go
pretty $(GOROOT)/test/char_lit.go
pretty $(GOROOT)/test/sieve.go
pretty $(GOROOT)/test/complit.go
pretty $(GOROOT)/test/const.go
pretty $(GOROOT)/test/dialgoogle.go
pretty $(GOROOT)/test/empty.go
pretty $(GOROOT)/test/env.go
pretty $(GOROOT)/test/float_lit.go
pretty $(GOROOT)/test/fmt_test.go
pretty $(GOROOT)/test/for.go
pretty $(GOROOT)/test/func.go
pretty $(GOROOT)/test/func1.go
pretty $(GOROOT)/test/func2.go
pretty $(GOROOT)/src/pkg/*.go
pretty $(GOROOT)/src/lib/flag.go
pretty $(GOROOT)/src/lib/fmt.go
pretty $(GOROOT)/src/lib/rand.go
pretty $(GOROOT)/src/lib/math/*.go
pretty $(GOROOT)/src/lib/container/*.go
pretty $(GOROOT)/src/lib/syscall/*.go
pretty $(GOROOT)/src/lib/*.go
pretty $(GOROOT)/src/lib/*/*.go
pretty $(GOROOT)/usr/r/*/*.go
echo "DONE"
# These tests don't work yet

View File

@ -38,6 +38,11 @@ func (p *List) at(i int) Node {
}
func (p *List) set(i int, x Node) {
p.a[i] = x;
}
func (p *List) Add (x Node) {
a := p.a;
n := len(a);
@ -100,7 +105,7 @@ export type Expr struct {
pos, tok int;
x, y *Expr; // binary (x, y) and unary (y) expressions
s string; // identifiers and literals
t *Type; // declarations and composite literals
t *Type; // operands that are types
}
@ -130,6 +135,13 @@ export func NewLit(pos, tok int, s string) *Expr {
}
export func NewTypeExpr(pos int, t *Type) *Expr {
e := new(Expr);
e.pos, e.tok, e.t = pos, Scanner.TYPE, t;
return e;
}
// ----------------------------------------------------------------------------
// Statements

View File

@ -238,10 +238,10 @@ func (P *Parser) ParseChannelType() *Node.Type {
}
func (P *Parser) ParseVarDeclList() {
func (P *Parser) ParseVarDeclList(list *Node.List) {
P.Trace("VarDeclList");
list := Node.NewList();
i0 := list.len();
list.Add(P.ParseType());
for P.tok == Scanner.COMMA {
P.Next();
@ -251,19 +251,31 @@ func (P *Parser) ParseVarDeclList() {
typ := P.TryType();
if typ != nil {
// all list entries must be identifiers;
// convert the list into an expression list of identifiers
for i, n := 0, list.len(); i < n; i++ {
// all list entries must be identifiers
// convert the type entries into identifiers
for i, n := i0, list.len(); i < n; i++ {
t := list.at(i).(*Node.Type);
if t.tok == Scanner.IDENT && t.expr.tok == Scanner.IDENT {
x := t.expr;
list.set(i, t.expr);
} else {
list.set(i, Node.NewLit(t.pos, Scanner.IDENT, "bad"));
P.Error(t.pos, "identifier expected");
}
}
// add type
list.Add(Node.NewTypeExpr(typ.pos, typ));
} else {
// all list entries are types
// convert all type entries into type expressions
for i, n := i0, list.len(); i < n; i++ {
t := list.at(i).(*Node.Type);
list.set(i, Node.NewTypeExpr(t.pos, t));
}
if P.tok == Scanner.COMMA {
panic("internal parser error");
}
}
P.Ecart();
@ -274,10 +286,10 @@ func (P *Parser) ParseParameterList() *Node.List {
P.Trace("ParameterList");
list := Node.NewList();
P.ParseVarDeclList();
P.ParseVarDeclList(list);
for P.tok == Scanner.COMMA {
P.Next();
P.ParseVarDeclList();
P.ParseVarDeclList(list);
}
P.Ecart();
@ -285,18 +297,18 @@ func (P *Parser) ParseParameterList() *Node.List {
}
func (P *Parser) ParseParameters() *Node.List {
func (P *Parser) ParseParameters() *Node.Type {
P.Trace("Parameters");
var list *Node.List;
t := Node.NewType(P.pos, Scanner.STRUCT);
P.Expect(Scanner.LPAREN);
if P.tok != Scanner.RPAREN {
list = P.ParseParameterList();
t.list = P.ParseParameterList();
}
P.Expect(Scanner.RPAREN);
P.Ecart();
return list;
return t;
}
@ -316,18 +328,23 @@ func (P *Parser) ParseResultList() {
}
func (P *Parser) ParseResult() *Node.List {
func (P *Parser) ParseResult() *Node.Type {
P.Trace("Result");
var list *Node.List;
var t *Node.Type;
if P.tok == Scanner.LPAREN {
list = P.ParseParameters();
t = P.ParseParameters();
} else {
typ := P.TryType();
if typ != nil {
t = Node.NewType(P.pos, Scanner.STRUCT);
t.list = Node.NewList();
t.list.Add(Node.NewTypeExpr(typ.pos, typ));
}
}
P.Ecart();
return list;
return t;
}
@ -341,8 +358,8 @@ func (P *Parser) ParseFunctionType() *Node.Type {
P.Trace("FunctionType");
t := Node.NewType(P.pos, Scanner.LPAREN);
t.list = P.ParseParameters();
P.ParseResult();
t.list = P.ParseParameters().list; // TODO find better solution
t.elt = P.ParseResult();
P.Ecart();
return t;
@ -405,7 +422,7 @@ func (P *Parser) ParseStructType() *Node.Type {
P.Next();
t.list = Node.NewList();
for P.tok == Scanner.IDENT {
P.ParseVarDeclList();
P.ParseVarDeclList(t.list);
if P.tok != Scanner.RBRACE {
P.Expect(Scanner.SEMICOLON);
}
@ -521,7 +538,7 @@ func (P *Parser) ParseFunctionLit() *Node.Expr {
P.scope_lev--;
P.Ecart();
return nil;
return Node.NewLit(P.pos, Scanner.INT, "0"); // "null" expr
}
@ -550,16 +567,17 @@ func (P *Parser) ParseOperand() *Node.Expr {
}
case Scanner.FUNC:
P.ParseFunctionLit();
x = P.ParseFunctionLit();
default:
typ := P.TryType();
if typ != nil {
break;
t := P.TryType();
if t != nil {
x = Node.NewTypeExpr(t.pos, t);
} else {
P.Error(P.pos, "operand expected");
P.Next(); // make progress
x = Node.NewLit(P.pos, Scanner.INT, "0"); // "null" expr
}
P.Error(P.pos, "operand expected");
P.Next(); // make progress
}
P.Ecart();
@ -635,7 +653,7 @@ func (P *Parser) ParseCall(x *Node.Expr) *Node.Expr {
}
func (P *Parser) ParseCompositeLit() {
func (P *Parser) ParseCompositeLit(t *Node.Type) *Node.Expr {
P.Trace("CompositeLit");
mode := 0;
@ -659,6 +677,7 @@ func (P *Parser) ParseCompositeLit() {
P.Expect(Scanner.RBRACE);
P.Ecart();
return Node.NewLit(P.pos, Scanner.INT, "0"); // "null" expr
}
@ -673,8 +692,19 @@ func (P *Parser) ParsePrimaryExpr() *Node.Expr {
case Scanner.LPAREN: x = P.ParseCall(x);
case Scanner.LBRACE:
if P.expr_lev > 0 {
P.ParseCompositeLit();
var t *Node.Type;
if x.tok == Scanner.TYPE {
t = x.t;
} else if x.tok == Scanner.IDENT {
// assume a type name
t = Node.NewType(x.pos, Scanner.IDENT);
t.expr = x;
} else {
P.Error(x.pos, "type expected for composite literal");
}
x = P.ParseCompositeLit(t);
} else {
// composites inside control clauses must be parenthesized
goto exit;
}
default: goto exit;
@ -1100,6 +1130,7 @@ func (P *Parser) ParseImportSpec() *Node.Decl {
if P.tok == Scanner.STRING {
// TODO eventually the scanner should strip the quotes
d.val = Node.NewLit(P.pos, Scanner.STRING, P.val);
P.Next();
} else {
P.Expect(Scanner.STRING); // use Expect() error handling
@ -1218,15 +1249,11 @@ func (P *Parser) ParseFunctionDecl(exported bool) *Node.Decl {
P.Expect(Scanner.FUNC);
if P.tok == Scanner.LPAREN {
pos := P.pos;
P.ParseParameters();
recv := P.ParseParameters();
// TODO: fix this
/*
if tmp.len() > 0 {
//recv = tmp.at(0);
}
*/
/*
if recv.idents.len() != 1 {
//P.Error(pos, "must have exactly one receiver");
if recv.list.len() != 1 {
P.Error(pos, "must have exactly one receiver");
}
*/
}

View File

@ -16,7 +16,7 @@ export type Printer struct {
}
func (P *Printer) String(s string) {
func (P *Printer) String(pos int, s string) {
if P.semi && P.level > 0 { // no semicolons at level 0
print(";");
}
@ -31,8 +31,13 @@ func (P *Printer) String(s string) {
}
func (P *Printer) Token(tok int) {
P.String(Scanner.TokenString(tok));
func (P *Printer) Blank() {
P.String(0, " ");
}
func (P *Printer) Token(pos int, tok int) {
P.String(pos, Scanner.TokenString(tok));
}
@ -44,7 +49,7 @@ func (P *Printer) NewLine() { // explicit "\n"
func (P *Printer) OpenScope(paren string) {
P.semi, P.newl = false, false;
P.String(paren);
P.String(0, paren);
P.level++;
P.indent++;
P.newl = true;
@ -54,7 +59,7 @@ func (P *Printer) OpenScope(paren string) {
func (P *Printer) CloseScope(paren string) {
P.indent--;
P.semi = false;
P.String(paren);
P.String(0, paren);
P.level--;
P.semi, P.newl = false, true;
}
@ -63,50 +68,91 @@ func (P *Printer) CloseScope(paren string) {
// ----------------------------------------------------------------------------
// Types
func (P *Printer) Type(t *Node.Type)
func (P *Printer) Expr(x *Node.Expr)
func (P *Printer) Parameters(list *Node.List) {
var prev int;
for i, n := 0, list.len(); i < n; i++ {
x := list.at(i).(*Node.Expr);
if i > 0 {
if prev == x.tok || prev == Scanner.TYPE {
P.String(0, ", ");
} else {
P.Blank();
}
}
P.Expr(x);
prev = x.tok;
}
}
func (P *Printer) Fields(list *Node.List) {
var prev int;
for i, n := 0, list.len(); i < n; i++ {
x := list.at(i).(*Node.Expr);
if i > 0 {
if prev == Scanner.TYPE {
P.String(0, ";");
P.newl = true;
} else if prev == x.tok {
P.String(0, ", ");
} else {
P.Blank();
}
}
P.Expr(x);
prev = x.tok;
}
P.newl = true;
}
func (P *Printer) Type(t *Node.Type) {
if t == nil { // TODO remove this check
P.String(0, "<nil type>");
return;
}
switch t.tok {
case Scanner.IDENT:
P.Expr(t.expr);
case Scanner.LBRACK:
P.String("[");
P.String(t.pos, "[");
if t.expr != nil {
P.Expr(t.expr);
}
P.String("] ");
P.String(0, "] ");
P.Type(t.elt);
case Scanner.STRUCT:
P.String("struct");
P.String(t.pos, "struct");
if t.list != nil {
P.OpenScope(" {");
/*
for i := 0; i < x.fields.len(); i++ {
P.Print(x.fields.at(i));
P.newl, P.semi = true, true;
}
*/
P.Fields(t.list);
P.CloseScope("}");
}
case Scanner.MAP:
P.String("[");
P.String(t.pos, "[");
P.Type(t.key);
P.String("] ");
P.String(0, "] ");
P.Type(t.elt);
case Scanner.CHAN:
var m string;
switch t.mode {
case Node.FULL: P.String("chan ");
case Node.RECV: P.String("<-chan ");
case Node.SEND: P.String("chan <- ");
case Node.FULL: m = "chan ";
case Node.RECV: m = "<-chan ";
case Node.SEND: m = "chan <- ";
}
P.String(t.pos, m);
P.Type(t.elt);
case Scanner.INTERFACE:
P.String("interface");
P.String(t.pos, "interface");
if t.list != nil {
P.OpenScope(" {");
/*
@ -119,20 +165,18 @@ func (P *Printer) Type(t *Node.Type) {
}
case Scanner.MUL:
P.String("*");
P.String(t.pos, "*");
P.Type(t.elt);
case Scanner.LPAREN:
P.String("(");
//P.PrintList(x.params);
P.String(")");
/*
if x.result != nil {
P.String(" (");
P.PrintList(x.result);
P.String(")");
P.String(t.pos, "(");
P.Parameters(t.list);
P.String(0, ")");
if t.elt != nil {
P.String(0, " (");
P.Parameters(t.elt.list);
P.String(0, ")");
}
*/
default:
panic("UNREACHABLE");
@ -149,49 +193,55 @@ func (P *Printer) Expr1(x *Node.Expr, prec1 int) {
}
switch x.tok {
case Scanner.VAR:
panic("UNIMPLEMENTED (VAR)");
case Scanner.TYPE:
P.Type(x.t);
case Scanner.IDENT, Scanner.INT, Scanner.STRING, Scanner.FLOAT:
P.String(x.s);
P.String(x.pos, x.s);
case Scanner.COMMA:
P.Expr1(x.x, 0);
P.String(", ");
P.String(x.pos, ", ");
P.Expr1(x.y, 0);
case Scanner.PERIOD:
P.Expr1(x.x, 8);
P.String(".");
P.Expr1(x.x, 8); // 8 == highest precedence
P.String(x.pos, ".");
P.Expr1(x.y, 8);
case Scanner.LBRACK:
P.Expr1(x.x, 8);
P.String("[");
P.String(x.pos, "[");
P.Expr1(x.y, 0);
P.String("]");
P.String(0, "]");
case Scanner.LPAREN:
P.Expr1(x.x, 8);
P.String("(");
P.String(x.pos, "(");
P.Expr1(x.y, 0);
P.String(")");
P.String(0, ")");
default:
if x.x == nil {
// unary expression
P.Token(x.tok);
P.Expr1(x.y, 7);
P.Token(x.pos, x.tok);
P.Expr1(x.y, 7); // 7 == unary operator precedence
} else {
// binary expression: print ()'s if necessary
prec := Scanner.Precedence(x.tok);
if prec < prec1 {
print("(");
P.String(0, "(");
}
P.Expr1(x.x, prec);
P.String(" ");
P.Token(x.tok);
P.String(" ");
P.Blank();
P.Token(x.pos, x.tok);
P.Blank();
P.Expr1(x.y, prec);
if prec < prec1 {
print(")");
P.String(0, ")");
}
}
}
@ -231,31 +281,30 @@ func (P *Printer) Block(list *Node.List, indent bool) {
func (P *Printer) ControlClause(s *Node.Stat) {
if s.init != nil {
P.String(" ");
P.Blank();
P.Stat(s.init);
P.semi = true;
P.String("");
}
if s.expr != nil {
P.String(" ");
P.Blank();
P.Expr(s.expr);
P.semi = false;
}
if s.tok == Scanner.FOR && s.post != nil {
P.semi = true;
P.String(" ");
P.Blank();
P.Stat(s.post);
P.semi = false;
}
P.String(" ");
P.Blank();
}
func (P *Printer) Declaration(d *Node.Decl);
func (P *Printer) Declaration(d *Node.Decl, parenthesized bool);
func (P *Printer) Stat(s *Node.Stat) {
if s == nil { // TODO remove this check
P.String("<nil stat>");
P.String(0, "<nil stat>");
return;
}
@ -265,66 +314,66 @@ func (P *Printer) Stat(s *Node.Stat) {
P.semi = true;
case Scanner.CONST, Scanner.TYPE, Scanner.VAR:
P.Declaration(s.decl);
P.Declaration(s.decl, false);
case Scanner.DEFINE, Scanner.ASSIGN, Scanner.ADD_ASSIGN,
Scanner.SUB_ASSIGN, Scanner.MUL_ASSIGN, Scanner.QUO_ASSIGN,
Scanner.REM_ASSIGN, Scanner.AND_ASSIGN, Scanner.OR_ASSIGN,
Scanner.XOR_ASSIGN, Scanner.SHL_ASSIGN, Scanner.SHR_ASSIGN:
P.Expr(s.lhs);
P.String(" ");
P.Token(s.tok);
P.String(" ");
P.Blank();
P.Token(s.pos, s.tok);
P.Blank();
P.Expr(s.expr);
P.semi = true;
case Scanner.INC, Scanner.DEC:
P.Expr(s.expr);
P.Token(s.tok);
P.Token(s.pos, s.tok);
P.semi = true;
case Scanner.LBRACE:
P.Block(s.block, true);
case Scanner.IF:
P.String("if");
P.String(s.pos, "if");
P.ControlClause(s);
P.Block(s.block, true);
if s.post != nil {
P.newl = false;
P.String(" else ");
P.String(0, " else ");
P.Stat(s.post);
}
case Scanner.FOR:
P.String("for");
P.String(s.pos, "for");
P.ControlClause(s);
P.Block(s.block, true);
case Scanner.SWITCH, Scanner.SELECT:
P.Token(s.tok);
P.Token(s.pos, s.tok);
P.ControlClause(s);
P.Block(s.block, false);
case Scanner.CASE, Scanner.DEFAULT:
P.Token(s.tok);
P.Token(s.pos, s.tok);
if s.expr != nil {
P.String(" ");
P.Blank();
P.Expr(s.expr);
}
P.String(":");
P.String(0, ":");
P.OpenScope("");
P.StatementList(s.block);
P.CloseScope("");
case Scanner.GO, Scanner.RETURN, Scanner.BREAK, Scanner.CONTINUE, Scanner.GOTO:
P.Token(s.tok);
P.String(" ");
P.Token(s.pos, s.tok);
P.Blank();
P.Expr(s.expr);
P.semi = true;
default:
P.String("<stat>");
P.String(s.pos, "<stat>");
P.semi = true;
}
}
@ -363,45 +412,47 @@ func (P *Printer) DoMethodDecl(x *AST.MethodDecl) {
*/
func (P *Printer) Declaration(d *Node.Decl) {
if d.tok == Scanner.FUNC || d.ident == nil {
func (P *Printer) Declaration(d *Node.Decl, parenthesized bool) {
if d == nil { // TODO remove this check
P.String(0, "<nil decl>");
return;
}
if !parenthesized {
if d.exported {
P.String("export ");
P.String(0, "export ");
}
P.Token(d.tok);
P.String(" ");
P.Token(d.pos, d.tok);
P.Blank();
}
if d.ident == nil {
switch d.list.len() {
case 0:
P.String("()");
case 1:
P.Declaration(d.list.at(0).(*Node.Decl));
default:
P.OpenScope("(");
for i := 0; i < d.list.len(); i++ {
P.Declaration(d.list.at(i).(*Node.Decl));
P.newl, P.semi = true, true;
}
P.CloseScope(")");
P.OpenScope("(");
for i := 0; i < d.list.len(); i++ {
P.Declaration(d.list.at(i).(*Node.Decl), true);
P.newl, P.semi = true, true;
}
P.CloseScope(")");
} else {
P.Expr(d.ident);
if d.typ != nil {
P.String(" ");
P.Blank();
P.Type(d.typ);
}
if d.val != nil {
P.String(" = ");
if d.tok == Scanner.IMPORT {
P.Blank();
} else {
P.String(0, " = ");
}
P.Expr(d.val);
}
if d.list != nil {
if d.tok != Scanner.FUNC {
panic("must be a func declaration");
}
P.String(" ");
P.Blank();
P.Block(d.list, true);
}
}
@ -419,12 +470,12 @@ func (P *Printer) Declaration(d *Node.Decl) {
// Program
func (P *Printer) Program(p *Node.Program) {
P.String("package ");
P.String(p.pos, "package ");
P.Expr(p.ident);
P.NewLine();
for i := 0; i < p.decls.len(); i++ {
P.Declaration(p.decls.at(i));
P.Declaration(p.decls.at(i), false);
}
P.newl = true;
P.String("");
P.String(0, ""); // flush
}