From 82fbbdfc7d355e744f5e7f34803d43b9469c48f9 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 15 Oct 2008 11:48:18 -0700 Subject: [PATCH] snapshot - fixed expression and statement printing - missing: declarations, comments R=r OCL=17207 CL=17207 --- usr/gri/pretty/Makefile | 17 +++- usr/gri/pretty/node.go | 74 ++-------------- usr/gri/pretty/parser.go | 89 ++++++++++--------- usr/gri/pretty/printer.go | 176 ++++++++++++++++++-------------------- usr/gri/pretty/scanner.go | 4 +- 5 files changed, 154 insertions(+), 206 deletions(-) diff --git a/usr/gri/pretty/Makefile b/usr/gri/pretty/Makefile index d1d2c277b21..8fd88a0ce99 100644 --- a/usr/gri/pretty/Makefile +++ b/usr/gri/pretty/Makefile @@ -11,7 +11,22 @@ pretty: pretty.6 test: pretty pretty -s *.go pretty -s ../gosrc/*.go - pretty -s $(GOROOT)/test/*.go + #pretty -s $(GOROOT)/test/*.go # contains incorrect programs + pretty -s $(GOROOT)/test/235.go + pretty -s $(GOROOT)/test/args.go + pretty -s $(GOROOT)/test/bufiolib.go + pretty -s $(GOROOT)/test/char_lit.go + pretty -s $(GOROOT)/test/complit.go + pretty -s $(GOROOT)/test/const.go + pretty -s $(GOROOT)/test/dialgoogle.go + pretty -s $(GOROOT)/test/empty.go + pretty -s $(GOROOT)/test/env.go + pretty -s $(GOROOT)/test/float_lit.go + pretty -s $(GOROOT)/test/fmt_test.go + pretty -s $(GOROOT)/test/for.go + pretty -s $(GOROOT)/test/func.go + pretty -s $(GOROOT)/test/func1.go + pretty -s $(GOROOT)/test/func2.go pretty -s $(GOROOT)/src/pkg/*.go pretty -s $(GOROOT)/src/lib/*.go pretty -s $(GOROOT)/src/lib/*/*.go diff --git a/usr/gri/pretty/node.go b/usr/gri/pretty/node.go index 93f646b5309..51ea1e68136 100644 --- a/usr/gri/pretty/node.go +++ b/usr/gri/pretty/node.go @@ -6,9 +6,9 @@ package Node import Scanner "scanner" -type Node interface {} type ( + Node interface {}; Type struct; Expr struct; Stat struct; @@ -56,20 +56,6 @@ func (p *List) Add (x Node) { } -/* -func (p *List) Print() { - print("("); - for i, n := 0, p.len(); i < n; i++ { - if i > 0 { - print(", "); - } - p.at(i).Print(); - } - print(")"); -} -*/ - - export func NewList() *List { p := new(List); p.a = new([] Node, 10) [0 : 0]; @@ -110,19 +96,11 @@ export func NewType(pos, tok int) *Type { // Expression pairs are represented as binary expressions with operator ":" // Expression lists are represented as binary expressions with operator "," -export type Val struct { - i int; - f float; - s string; - t *Type; -} - - export type Expr struct { pos, tok int; x, y *Expr; // binary (x, y) and unary (y) expressions - ident string; // identifiers - val *Val; // literals + s string; // identifiers and literals + t *Type; // declarations and composite literals } @@ -138,28 +116,6 @@ func (x *Expr) len() int { } -/* -func (x *Expr) Print() { - switch { - case x == nil: - print("nil"); - case x.val != nil: - print(x.val.s); - default: - if x.x == nil { - print(Scanner.TokenName(x.tok)); - } else { - x.x.Print(); - print(" "); - print(Scanner.TokenName(x.tok)); - print(" "); - } - x.y.Print(); - } -} -*/ - - export func NewExpr(pos, tok int, x, y *Expr) *Expr { e := new(Expr); e.pos, e.tok, e.x, e.y = pos, tok, x, y; @@ -167,16 +123,9 @@ export func NewExpr(pos, tok int, x, y *Expr) *Expr { } -export func NewIdent(pos int, ident string) *Expr { +export func NewLit(pos, tok int, s string) *Expr { e := new(Expr); - e.pos, e.tok, e.ident = pos, Scanner.IDENT, ident; - return e; -} - - -export func NewVal(pos, tok int, val *Val) *Expr { - e := new(Expr); - e.pos, e.tok, e.val = pos, tok, val; + e.pos, e.tok, e.s = pos, tok, s; return e; } @@ -186,9 +135,8 @@ export func NewVal(pos, tok int, val *Val) *Expr { export type Stat struct { pos, tok int; - init *Stat; - expr *Expr; - post *Stat; + init, post *Stat; + lhs, expr *Expr; block *List; decl *Decl; } @@ -204,14 +152,6 @@ export func NewStat(pos, tok int) *Stat { // ---------------------------------------------------------------------------- // Declarations -export type VarDeclList struct { -} - - -func (d *VarDeclList) Print() { -} - - export type Decl struct { pos, tok int; exported bool; diff --git a/usr/gri/pretty/parser.go b/usr/gri/pretty/parser.go index 4dcacdc16f6..a51683d678b 100644 --- a/usr/gri/pretty/parser.go +++ b/usr/gri/pretty/parser.go @@ -66,7 +66,7 @@ func (P *Parser) Next() { P.opt_semi = false; if P.verbose { P.PrintIndent(); - print("[", P.pos, "] ", Scanner.TokenName(P.tok), "\n"); + print("[", P.pos, "] ", Scanner.TokenString(P.tok), "\n"); } } @@ -89,7 +89,7 @@ func (P *Parser) Error(pos int, msg string) { func (P *Parser) Expect(tok int) { if P.tok != tok { - P.Error(P.pos, "expected '" + Scanner.TokenName(tok) + "', found '" + Scanner.TokenName(P.tok) + "'"); + P.Error(P.pos, "expected '" + Scanner.TokenString(tok) + "', found '" + Scanner.TokenString(P.tok) + "'"); } P.Next(); // make progress in any case } @@ -116,10 +116,10 @@ func (P *Parser) ParseIdent() *Node.Expr { var x *Node.Expr; if P.tok == Scanner.IDENT { - x = Node.NewIdent(P.pos, P.val); + x = Node.NewLit(P.pos, Scanner.IDENT, P.val); if P.verbose { P.PrintIndent(); - print("Ident = \"", x.val, "\"\n"); + print("Ident = \"", x.s, "\"\n"); } P.Next(); } else { @@ -238,24 +238,35 @@ func (P *Parser) ParseChannelType() *Node.Type { } -func (P *Parser) ParseVarDeclList() *Node.VarDeclList { +func (P *Parser) ParseVarDeclList() { P.Trace("VarDeclList"); - list := new(Node.VarDeclList); - P.ParseType(); + list := Node.NewList(); + list.Add(P.ParseType()); for P.tok == Scanner.COMMA { P.Next(); - P.ParseType(); + list.Add(P.ParseType()); } - + typ := P.TryType(); - if typ == nil { - // we must have a list of types + 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++ { + t := list.at(i).(*Node.Type); + if t.tok == Scanner.IDENT && t.expr.tok == Scanner.IDENT { + x := t.expr; + } else { + P.Error(t.pos, "identifier expected"); + } + } + } else { + // all list entries are types + } P.Ecart(); - return list; } @@ -263,10 +274,10 @@ func (P *Parser) ParseParameterList() *Node.List { P.Trace("ParameterList"); list := Node.NewList(); - list.Add(P.ParseVarDeclList()); + P.ParseVarDeclList(); for P.tok == Scanner.COMMA { P.Next(); - list.Add(P.ParseVarDeclList()); + P.ParseVarDeclList(); } P.Ecart(); @@ -394,7 +405,7 @@ func (P *Parser) ParseStructType() *Node.Type { P.Next(); t.list = Node.NewList(); for P.tok == Scanner.IDENT { - t.list.Add(P.ParseVarDeclList()); + P.ParseVarDeclList(); if P.tok != Scanner.RBRACE { P.Expect(Scanner.SEMICOLON); } @@ -529,18 +540,13 @@ func (P *Parser) ParseOperand() *Node.Expr { P.expr_lev--; P.Expect(Scanner.RPAREN); - case Scanner.INT, Scanner.FLOAT: - val := new(Node.Val); - val.s = P.val; - x = Node.NewVal(P.pos, P.tok, val); + case Scanner.INT, Scanner.FLOAT, Scanner.STRING: + x = Node.NewLit(P.pos, P.tok, P.val); P.Next(); - - case Scanner.STRING: - val := new(Node.Val); - val.s = P.val; - x = Node.NewVal(P.pos, Scanner.STRING, val); - for P.Next(); P.tok == Scanner.STRING; P.Next() { - val.s += P.val; + if x.tok == Scanner.STRING { + for ; P.tok == Scanner.STRING; P.Next() { + x.s += P.val; + } } case Scanner.FUNC: @@ -744,12 +750,12 @@ func (P *Parser) ParseSimpleStat() *Node.Stat { P.Trace("SimpleStat"); var s *Node.Stat; - list := P.ParseExpressionList(); + x := P.ParseExpressionList(); switch P.tok { case Scanner.COLON: // label declaration - if list.len() == 1 { + if x.len() == 1 { } else { P.Error(P.pos, "illegal label declaration"); } @@ -763,21 +769,22 @@ func (P *Parser) ParseSimpleStat() *Node.Stat { Scanner.XOR_ASSIGN, Scanner.SHL_ASSIGN, Scanner.SHR_ASSIGN: s = Node.NewStat(P.pos, P.tok); P.Next(); + s.lhs = x; s.expr = P.ParseExpressionList(); default: if P.tok == Scanner.INC || P.tok == Scanner.DEC { s = Node.NewStat(P.pos, P.tok); - if list.len() == 1 { - s.expr = list; + if x.len() == 1 { + s.expr = x; } else { P.Error(P.pos, "more then one operand"); } P.Next(); } else { s = Node.NewStat(P.pos, 0); // TODO give this a token value - if list.len() == 1 { - s.expr = list; + if x.len() == 1 { + s.expr = x; } else { P.Error(P.pos, "syntax error"); } @@ -830,7 +837,7 @@ func (P *Parser) ParseControlFlowStat(tok int) *Node.Stat { func (P *Parser) ParseControlClause(keyword int) *Node.Stat { - P.Trace("StatHeader"); + P.Trace("ControlClause"); s := Node.NewStat(P.pos, keyword); P.Expect(keyword); @@ -872,9 +879,9 @@ func (P *Parser) ParseIfStat() *Node.Stat { if P.tok == Scanner.ELSE { P.Next(); if P.tok == Scanner.IF { - P.ParseIfStat(); + s.post = P.ParseIfStat(); } else { - P.ParseStatement(); + s.post = P.ParseStatement(); } } @@ -1005,12 +1012,6 @@ func (P *Parser) ParseFallthroughStat() *Node.Stat { } -func (P *Parser) ParseEmptyStat() { - P.Trace("EmptyStat"); - P.Ecart(); -} - - func (P *Parser) ParseRangeStat() *Node.Stat { P.Trace("RangeStat"); @@ -1026,6 +1027,12 @@ func (P *Parser) ParseRangeStat() *Node.Stat { } +func (P *Parser) ParseEmptyStat() { + P.Trace("EmptyStat"); + P.Ecart(); +} + + func (P *Parser) ParseStatement() *Node.Stat { P.Trace("Statement"); indent := P.indent; diff --git a/usr/gri/pretty/printer.go b/usr/gri/pretty/printer.go index 1bd44fd168c..76b9dd9dce4 100644 --- a/usr/gri/pretty/printer.go +++ b/usr/gri/pretty/printer.go @@ -13,7 +13,6 @@ export type Printer struct { indent int; // indentation level semi bool; // pending ";" newl bool; // pending "\n" - prec int; // operator precedence } @@ -32,6 +31,11 @@ func (P *Printer) String(s string) { } +func (P *Printer) Token(tok int) { + P.String(Scanner.TokenString(tok)); +} + + func (P *Printer) NewLine() { // explicit "\n" print("\n"); P.semi, P.newl = false, true; @@ -139,107 +143,69 @@ func (P *Printer) Type(t *Node.Type) { // ---------------------------------------------------------------------------- // Expressions -func (P *Printer) Val(tok int, val *Node.Val) { - P.String(val.s); // for now -} - - -func (P *Printer) Expr(x *Node.Expr) { +func (P *Printer) Expr1(x *Node.Expr, prec1 int) { if x == nil { return; // empty expression list } switch x.tok { - case Scanner.IDENT: - P.String(x.ident); + case Scanner.IDENT, Scanner.INT, Scanner.STRING, Scanner.FLOAT: + P.String(x.s); - case Scanner.INT, Scanner.STRING, Scanner.FLOAT: - P.Val(x.tok, x.val); + case Scanner.COMMA: + P.Expr1(x.x, 0); + P.String(", "); + P.Expr1(x.y, 0); - case Scanner.LPAREN: - // calls - P.Expr(x.x); - P.String("("); - P.Expr(x.y); - P.String(")"); + case Scanner.PERIOD: + P.Expr1(x.x, 8); + P.String("."); + P.Expr1(x.y, 8); case Scanner.LBRACK: - P.Expr(x.x); + P.Expr1(x.x, 8); P.String("["); - P.Expr(x.y); + P.Expr1(x.y, 0); P.String("]"); + + case Scanner.LPAREN: + P.Expr1(x.x, 8); + P.String("("); + P.Expr1(x.y, 0); + P.String(")"); default: if x.x == nil { // unary expression - P.String(Scanner.TokenName(x.tok)); - P.Expr(x.y); + P.Token(x.tok); + P.Expr1(x.y, 7); } else { // binary expression: print ()'s if necessary - // TODO: pass precedence as parameter instead - outer := P.prec; - P.prec = Scanner.Precedence(x.tok); - if P.prec < outer { + prec := Scanner.Precedence(x.tok); + if prec < prec1 { print("("); } - P.Expr(x.x); - if x.tok != Scanner.PERIOD && x.tok != Scanner.COMMA { - P.String(" "); - } - P.String(Scanner.TokenName(x.tok)); - if x.tok != Scanner.PERIOD { - P.String(" "); - } - P.Expr(x.y); - if P.prec < outer { + P.Expr1(x.x, prec); + P.String(" "); + P.Token(x.tok); + P.String(" "); + P.Expr1(x.y, prec); + if prec < prec1 { print(")"); } - P.prec = outer; } } } +func (P *Printer) Expr(x *Node.Expr) { + P.Expr1(x, 0); +} + + // ---------------------------------------------------------------------------- // Statements -/* -func (P *Printer) DoLabel(x *AST.Label) { - P.indent--; - P.newl = true; - P.Print(x.ident); - P.String(":"); - P.indent++; -} - - -func (P *Printer) DoExprStat(x *AST.ExprStat) { - P.Print(x.expr); - P.semi = true; -} - - -func (P *Printer) DoAssignment(x *AST.Assignment) { - P.PrintList(x.lhs); - P.String(" " + Scanner.TokenName(x.tok) + " "); - P.PrintList(x.rhs); - P.semi = true; -} - - -func (P *Printer) DoIfStat(x *AST.IfStat) { - P.String("if"); - P.PrintControlClause(x.ctrl); - P.DoBlock(x.then); - if x.has_else { - P.newl = false; - P.String(" else "); - P.Print(x.else_); - } -} -*/ - - func (P *Printer) Stat(s *Node.Stat) func (P *Printer) StatementList(list *Node.List) { @@ -250,9 +216,15 @@ func (P *Printer) StatementList(list *Node.List) { } -func (P *Printer) Block(list *Node.List) { +func (P *Printer) Block(list *Node.List, indent bool) { P.OpenScope("{"); + if !indent { + P.indent--; + } P.StatementList(list); + if !indent { + P.indent++; + } P.CloseScope("}"); } @@ -269,7 +241,7 @@ func (P *Printer) ControlClause(s *Node.Stat) { P.Expr(s.expr); P.semi = false; } - if s.post != nil { + if s.tok == Scanner.FOR && s.post != nil { P.semi = true; P.String(" "); P.Stat(s.post); @@ -286,6 +258,7 @@ func (P *Printer) Stat(s *Node.Stat) { P.String(""); return; } + switch s.tok { case 0: // TODO use a real token const P.Expr(s.expr); @@ -298,23 +271,43 @@ func (P *Printer) Stat(s *Node.Stat) { 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.String(Scanner.TokenName(s.tok)); + P.Expr(s.lhs); + P.String(" "); + P.Token(s.tok); P.String(" "); P.Expr(s.expr); P.semi = true; case Scanner.INC, Scanner.DEC: P.Expr(s.expr); - P.String(Scanner.TokenName(s.tok)); + P.Token(s.tok); P.semi = true; - case Scanner.IF, Scanner.FOR, Scanner.SWITCH, Scanner.SELECT: - P.String(Scanner.TokenName(s.tok)); + case Scanner.LBRACE: + P.Block(s.block, true); + + case Scanner.IF: + P.String("if"); P.ControlClause(s); - P.Block(s.block); - + P.Block(s.block, true); + if s.post != nil { + P.newl = false; + P.String(" else "); + P.Stat(s.post); + } + + case Scanner.FOR: + P.String("for"); + P.ControlClause(s); + P.Block(s.block, true); + + case Scanner.SWITCH, Scanner.SELECT: + P.Token(s.tok); + P.ControlClause(s); + P.Block(s.block, false); + case Scanner.CASE, Scanner.DEFAULT: - P.String(Scanner.TokenName(s.tok)); + P.Token(s.tok); if s.expr != nil { P.String(" "); P.Expr(s.expr); @@ -323,9 +316,10 @@ func (P *Printer) Stat(s *Node.Stat) { P.OpenScope(""); P.StatementList(s.block); P.CloseScope(""); - + case Scanner.GO, Scanner.RETURN, Scanner.BREAK, Scanner.CONTINUE, Scanner.GOTO: - P.String("go "); + P.Token(s.tok); + P.String(" "); P.Expr(s.expr); P.semi = true; @@ -341,15 +335,6 @@ func (P *Printer) Stat(s *Node.Stat) { /* -func (P *Printer) DoImportDecl(x *AST.ImportDecl) { - if x.ident != nil { - P.Print(x.ident); - P.String(" "); - } - P.String(x.file); -} - - func (P *Printer) DoFuncDecl(x *AST.FuncDecl) { P.String("func "); if x.typ.recv != nil { @@ -383,7 +368,7 @@ func (P *Printer) Declaration(d *Node.Decl) { if d.exported { P.String("export "); } - P.String(Scanner.TokenName(d.tok)); + P.Token(d.tok); P.String(" "); } @@ -417,10 +402,11 @@ func (P *Printer) Declaration(d *Node.Decl) { panic("must be a func declaration"); } P.String(" "); - P.Block(d.list); + P.Block(d.list, true); } } + // extra newline at the top level if P.level == 0 { P.NewLine(); } diff --git a/usr/gri/pretty/scanner.go b/usr/gri/pretty/scanner.go index 56ab9956ad5..92129272079 100644 --- a/usr/gri/pretty/scanner.go +++ b/usr/gri/pretty/scanner.go @@ -106,7 +106,7 @@ export const ( ) -export func TokenName(tok int) string { +export func TokenString(tok int) string { switch (tok) { case ILLEGAL: return "ILLEGAL"; @@ -233,7 +233,7 @@ func init() { Keywords = new(map [string] int); for i := KEYWORDS_BEG + 1; i < KEYWORDS_END; i++ { - Keywords[TokenName(i)] = i; + Keywords[TokenString(i)] = i; } // Provide column information in error messages for gri only...