From 9e3b0f444ae27629b3e93b2e8d0d8ba0f6f939ba Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Fri, 23 Jan 2009 09:44:01 -0800 Subject: [PATCH] snapshot before making more changes: - fine-tuning of ast - more accurate block pos info (improved printing in some cases) - collecting local variables and fields - more work on type checking - lots of minor tweaks R=r OCL=23375 CL=23375 --- usr/gri/pretty/ast.go | 65 ++++++++-- usr/gri/pretty/parser.go | 264 ++++++++++++++++++++------------------ usr/gri/pretty/printer.go | 46 ++++--- usr/gri/pretty/scanner.go | 4 +- usr/gri/pretty/test.sh | 5 +- 5 files changed, 222 insertions(+), 162 deletions(-) diff --git a/usr/gri/pretty/ast.go b/usr/gri/pretty/ast.go index 788ac74b14..0a6d3485c5 100644 --- a/usr/gri/pretty/ast.go +++ b/usr/gri/pretty/ast.go @@ -16,12 +16,23 @@ type ( Object struct; Type struct; + Block struct; Expr struct; Stat struct; Decl struct; ) +// ---------------------------------------------------------------------------- +// Support + +func assert(pred bool) { + if !pred { + panic("assertion failed"); + } +} + + // ---------------------------------------------------------------------------- // Objects @@ -63,7 +74,7 @@ type Object struct { Pnolev int; // >= 0: package no., <= 0: function nesting level, 0: global level // attached values - Block *array.Array; End int; // stats for function literals; end of block pos + Body *Block; // function body } @@ -174,16 +185,41 @@ type Node struct { } +// ---------------------------------------------------------------------------- +// Blocks +// +// Syntactic constructs of the form: +// +// "{" StatementList "}" +// ":" StatementList + +type Block struct { + Node; + List *array.Array; + End int; // position of closing "}" if present +} + + +func NewBlock(pos, tok int) *Block { + assert(tok == Scanner.LBRACE || tok == Scanner.COLON); + b := new(Block); + b.Pos, b.Tok, b.List = pos, tok, array.New(0); + return b; +} + + // ---------------------------------------------------------------------------- // Expressions type Expr struct { Node; X, Y *Expr; // binary (X, Y) and unary (Y) expressions - Obj *Object; + Obj *Object; // identifiers, literals + Typ *Type; } +// Length of a comma-separated expression list. func (x *Expr) Len() int { if x == nil { return 0; @@ -196,6 +232,19 @@ func (x *Expr) Len() int { } +// The i'th expression in a comma-separated expression list. +func (x *Expr) At(i int) *Expr { + for j := 0; j < i; j++ { + assert(x.Tok == Scanner.COMMA); + x = x.Y; + } + if x.Tok == Scanner.COMMA { + x = x.X; + } + return x; +} + + func NewExpr(pos, tok int, x, y *Expr) *Expr { if x != nil && x.Tok == Scanner.TYPE || y != nil && y.Tok == Scanner.TYPE { panic("no type expression allowed"); @@ -302,7 +351,7 @@ type Type struct { Form int; // type form Size int; // size in bytes Obj *Object; // primary type object or NULL - Scope *Scope; // forwards, structs, interfaces, functions + Scope *Scope; // locals, fields & methods // syntactic components Pos int; // source position (< 0 if unknown position) @@ -311,7 +360,6 @@ type Type struct { Key *Type; // receiver type or map key Elt *Type; // array, map, channel or pointer element type, function result type List *array.Array; End int; // struct fields, interface methods, function parameters - Scope *Scope; // struct fields, methods } @@ -351,9 +399,9 @@ func (t *Type) Nfields() int { // requires complete Type.Pos access func NewTypeExpr(typ *Type) *Expr { - obj := NewObject(typ.Pos, TYPE, ""); - obj.Typ = typ; - return NewLit(Scanner.TYPE, obj); + e := new(Expr); + e.Pos, e.Tok, e.Typ = typ.Pos, Scanner.TYPE, typ; + return e; } @@ -367,7 +415,7 @@ type Stat struct { Node; Init, Post *Stat; Expr *Expr; - Block *array.Array; End int; // block end position + Body *Block; // composite statement body Decl *Decl; } @@ -391,7 +439,6 @@ type Decl struct { Typ *Type; Val *Expr; // list of *Decl for ()-style declarations - // list of *Stat for func declarations (or nil for forward decl) List *array.Array; End int; } diff --git a/usr/gri/pretty/parser.go b/usr/gri/pretty/parser.go index 38c87bf284..fbea1fcdab 100644 --- a/usr/gri/pretty/parser.go +++ b/usr/gri/pretty/parser.go @@ -97,7 +97,14 @@ func (P *Parser) Next0() { if P.verbose { P.PrintIndent(); - print("[", P.pos, "] ", Scanner.TokenString(P.tok), "\n"); + s := Scanner.TokenString(P.tok); + // rewrite "{" and "}" so we don't screw up double-click selection + // in terminal window (we print scopes using the same characters) + switch s { + case "{": s = "LBRACE"; + case "}": s = "RBRACE"; + } + print("[", P.pos, "] ", s, "\n"); } } @@ -168,15 +175,15 @@ func (P *Parser) DeclareInScope(scope *AST.Scope, x *AST.Expr, kind int) { panic("cannot declare objects in other packages"); } if x.Tok != Scanner.ILLEGAL { // ignore bad exprs + assert(x.Tok == Scanner.IDENT); obj := x.Obj; - assert(x.Tok == Scanner.IDENT && obj.Kind == AST.NONE); obj.Kind = kind; obj.Pnolev = P.scope_lev; - if scope.LookupLocal(obj.Ident) != nil { + if scope.LookupLocal(obj.Ident) == nil { + scope.Insert(obj); + } else { P.Error(obj.Pos, `"` + obj.Ident + `" is declared already`); - return; // don't insert it into the scope } - scope.Insert(obj); } } @@ -197,7 +204,7 @@ func (P *Parser) Declare(p *AST.Expr, kind int) { func exprType(x *AST.Expr) *AST.Type { var t *AST.Type; if x.Tok == Scanner.TYPE { - t = x.Obj.Typ; + t = x.Typ; } else if x.Tok == Scanner.IDENT { // assume a type name t = AST.NewType(x.Pos, AST.TYPENAME); @@ -505,7 +512,7 @@ func (P *Parser) ParseResultList() { } -func (P *Parser) ParseResult() *AST.Type { +func (P *Parser) ParseResult(ftyp *AST.Type) *AST.Type { P.Trace("Result"); var t *AST.Type; @@ -539,9 +546,10 @@ func (P *Parser) ParseFunctionType() *AST.Type { P.scope_lev++; t := AST.NewType(P.pos, AST.FUNCTION); + t.Scope = P.top_scope; t.List = P.ParseParameters(true).List; // TODO find better solution t.End = P.pos; - t.Elt = P.ParseResult(); + t.Elt = P.ParseResult(t); P.scope_lev--; P.CloseScope(); @@ -620,10 +628,9 @@ func (P *Parser) ParseStructType() *AST.Type { P.Expect(Scanner.STRUCT); if P.tok == Scanner.LBRACE { P.Next(); - P.OpenScope(); - P.scope_lev++; t.List = array.New(0); + t.Scope = AST.NewScope(nil); for P.tok != Scanner.RBRACE && P.tok != Scanner.EOF { P.ParseVarList(t.List, false); if P.tok == Scanner.STRING { @@ -639,9 +646,15 @@ func (P *Parser) ParseStructType() *AST.Type { P.OptSemicolon(); t.End = P.pos; - P.scope_lev--; - P.CloseScope(); P.Expect(Scanner.RBRACE); + + // enter fields into struct scope + for i, n := 0, t.List.Len(); i < n; i++ { + x := t.List.At(i).(*AST.Expr); + if x.Tok == Scanner.IDENT { + P.DeclareInScope(t.Scope, x, AST.FIELD); + } + } } P.Ecart(); @@ -685,10 +698,9 @@ func (P *Parser) TryType() *AST.Type { // ---------------------------------------------------------------------------- // Blocks -func (P *Parser) ParseStatementList() *array.Array { +func (P *Parser) ParseStatementList(list *array.Array) { P.Trace("StatementList"); - list := array.New(0); for P.tok != Scanner.CASE && P.tok != Scanner.DEFAULT && P.tok != Scanner.RBRACE && P.tok != Scanner.EOF { s := P.ParseStatement(); if s != nil { @@ -710,25 +722,42 @@ func (P *Parser) ParseStatementList() *array.Array { } P.Ecart(); - return list; } -func (P *Parser) ParseBlock() (slist *array.Array, end int) { +func (P *Parser) ParseBlock(ftyp *AST.Type, tok int) *AST.Block { P.Trace("Block"); - P.Expect(Scanner.LBRACE); - P.OpenScope(); + b := AST.NewBlock(P.pos, tok); + P.Expect(tok); - slist = P.ParseStatementList(); - end = P.pos; + P.OpenScope(); + // enter recv and parameters into function scope + if ftyp != nil { + assert(ftyp.Form == AST.FUNCTION); + if ftyp.Key != nil { + } + if ftyp.List != nil { + for i, n := 0, ftyp.List.Len(); i < n; i++ { + x := ftyp.List.At(i).(*AST.Expr); + if x.Tok == Scanner.IDENT { + P.DeclareInScope(P.top_scope, x, AST.VAR); + } + } + } + } + P.ParseStatementList(b.List); P.CloseScope(); - P.Expect(Scanner.RBRACE); - P.opt_semi = true; + + if tok == Scanner.LBRACE { + b.End = P.pos; + P.Expect(Scanner.RBRACE); + P.opt_semi = true; + } P.Ecart(); - return slist, end; + return b; } @@ -759,43 +788,20 @@ func (P *Parser) ParseExpressionList() *AST.Expr { func (P *Parser) ParseFunctionLit() *AST.Expr { P.Trace("FunctionLit"); - val := AST.NewObject(P.pos, AST.NONE, ""); - x := AST.NewLit(Scanner.FUNC, val); + f := AST.NewObject(P.pos, AST.FUNC, ""); P.Expect(Scanner.FUNC); - val.Typ = P.ParseFunctionType(); + f.Typ = P.ParseFunctionType(); P.expr_lev++; P.scope_lev++; - val.Block, val.End = P.ParseBlock(); + f.Body = P.ParseBlock(f.Typ, Scanner.LBRACE); P.scope_lev--; P.expr_lev--; P.Ecart(); - return x; + return AST.NewLit(Scanner.FUNC, f); } -/* -func (P *Parser) ParseNewCall() *AST.Expr { - P.Trace("NewCall"); - - x := AST.NewExpr(P.pos, Scanner.NEW, nil, nil); - P.Next(); - P.Expect(Scanner.LPAREN); - P.expr_lev++; - x.t = P.ParseType(); - if P.tok == Scanner.COMMA { - P.Next(); - x.Y = P.ParseExpressionList(); - } - P.expr_lev--; - P.Expect(Scanner.RPAREN); - - P.Ecart(); - return x; -} -*/ - - func (P *Parser) ParseOperand() *AST.Expr { P.Trace("Operand"); @@ -850,11 +856,18 @@ func (P *Parser) ParseSelectorOrTypeGuard(x *AST.Expr) *AST.Expr { P.Expect(Scanner.PERIOD); if P.tok == Scanner.IDENT { - x.Y = P.ParseIdent(nil); + // TODO should always guarantee x.Typ != nil + var scope *AST.Scope; + if x.Typ != nil { + scope = x.Typ.Scope; + } + x.Y = P.ParseIdent(scope); + x.Typ = x.Y.Obj.Typ; } else { P.Expect(Scanner.LPAREN); x.Y = AST.NewTypeExpr(P.ParseType()); + x.Typ = x.Y.Typ; P.Expect(Scanner.RPAREN); } @@ -1246,28 +1259,25 @@ func (P *Parser) ParseIfStat() *AST.Stat { P.OpenScope(); s := P.ParseControlClause(Scanner.IF); - s.Block, s.End = P.ParseBlock(); + s.Body = P.ParseBlock(nil, Scanner.LBRACE); if P.tok == Scanner.ELSE { P.Next(); s1 := AST.BadStat; - if P.tok == Scanner.IF { - s1 = P.ParseIfStat(); + if P.tok == Scanner.IF || P.tok == Scanner.LBRACE { + s1 = P.ParseStatement(); } else if P.sixg { s1 = P.ParseStatement(); if s1 != nil { // not the empty statement - if s1.Tok != Scanner.LBRACE { - // wrap in a block if we don't have one - b := AST.NewStat(P.pos, Scanner.LBRACE); - b.Block = array.New(0); - b.Block.Push(s1); - s1 = b; - } - s.Post = s1; + assert(s1.Tok != Scanner.LBRACE); + // wrap in a block since we don't have one + b := AST.NewStat(s1.Pos, Scanner.LBRACE); + b.Body = AST.NewBlock(s1.Pos, Scanner.LBRACE); + b.Body.List.Push(s1); + s1 = b; } } else { - s1 = AST.NewStat(P.pos, Scanner.LBRACE); - s1.Block, s1.End = P.ParseBlock(); + P.Error(P.pos, "'if' or '{' expected - illegal 'else' branch"); } s.Post = s1; } @@ -1283,7 +1293,7 @@ func (P *Parser) ParseForStat() *AST.Stat { P.OpenScope(); s := P.ParseControlClause(Scanner.FOR); - s.Block, s.End = P.ParseBlock(); + s.Body = P.ParseBlock(nil, Scanner.LBRACE); P.CloseScope(); P.Ecart(); @@ -1291,8 +1301,8 @@ func (P *Parser) ParseForStat() *AST.Stat { } -func (P *Parser) ParseCase() *AST.Stat { - P.Trace("Case"); +func (P *Parser) ParseSwitchCase() *AST.Stat { + P.Trace("SwitchCase"); s := AST.NewStat(P.pos, P.tok); if P.tok == Scanner.CASE { @@ -1301,7 +1311,6 @@ func (P *Parser) ParseCase() *AST.Stat { } else { P.Expect(Scanner.DEFAULT); } - P.Expect(Scanner.COLON); P.Ecart(); return s; @@ -1311,10 +1320,8 @@ func (P *Parser) ParseCase() *AST.Stat { func (P *Parser) ParseCaseClause() *AST.Stat { P.Trace("CaseClause"); - s := P.ParseCase(); - if P.tok != Scanner.CASE && P.tok != Scanner.DEFAULT && P.tok != Scanner.RBRACE { - s.Block = P.ParseStatementList(); - } + s := P.ParseSwitchCase(); + s.Body = P.ParseBlock(nil, Scanner.COLON); P.Ecart(); return s; @@ -1326,15 +1333,16 @@ func (P *Parser) ParseSwitchStat() *AST.Stat { P.OpenScope(); s := P.ParseControlClause(Scanner.SWITCH); - s.Block = array.New(0); + b := AST.NewBlock(P.pos, Scanner.LBRACE); P.Expect(Scanner.LBRACE); for P.tok != Scanner.RBRACE && P.tok != Scanner.EOF { - s.Block.Push(P.ParseCaseClause()); + b.List.Push(P.ParseCaseClause()); } - s.End = P.pos; + b.End = P.pos; P.Expect(Scanner.RBRACE); P.opt_semi = true; P.CloseScope(); + s.Body = b; P.Ecart(); return s; @@ -1362,7 +1370,6 @@ func (P *Parser) ParseCommCase() *AST.Stat { } else { P.Expect(Scanner.DEFAULT); } - P.Expect(Scanner.COLON); P.Ecart(); return s; @@ -1373,9 +1380,7 @@ func (P *Parser) ParseCommClause() *AST.Stat { P.Trace("CommClause"); s := P.ParseCommCase(); - if P.tok != Scanner.CASE && P.tok != Scanner.DEFAULT && P.tok != Scanner.RBRACE { - s.Block = P.ParseStatementList(); - } + s.Body = P.ParseBlock(nil, Scanner.COLON); P.Ecart(); return s; @@ -1386,29 +1391,16 @@ func (P *Parser) ParseSelectStat() *AST.Stat { P.Trace("SelectStat"); s := AST.NewStat(P.pos, Scanner.SELECT); - s.Block = array.New(0); P.Expect(Scanner.SELECT); + b := AST.NewBlock(P.pos, Scanner.LBRACE); P.Expect(Scanner.LBRACE); for P.tok != Scanner.RBRACE && P.tok != Scanner.EOF { - s.Block.Push(P.ParseCommClause()); + b.List.Push(P.ParseCommClause()); } + b.End = P.pos; P.Expect(Scanner.RBRACE); P.opt_semi = true; - - P.Ecart(); - return s; -} - - -func (P *Parser) ParseRangeStat() *AST.Stat { - P.Trace("RangeStat"); - - s := AST.NewStat(P.pos, Scanner.RANGE); - P.Expect(Scanner.RANGE); - P.ParseIdentList(); - P.Expect(Scanner.DEFINE); - s.Expr = P.ParseExpression(1); - s.Block, s.End = P.ParseBlock(); + s.Body = b; P.Ecart(); return s; @@ -1442,15 +1434,13 @@ func (P *Parser) ParseStatement() *AST.Stat { s = P.ParseControlFlowStat(P.tok); case Scanner.LBRACE: s = AST.NewStat(P.pos, Scanner.LBRACE); - s.Block, s.End = P.ParseBlock(); + s.Body = P.ParseBlock(nil, Scanner.LBRACE); case Scanner.IF: s = P.ParseIfStat(); case Scanner.FOR: s = P.ParseForStat(); case Scanner.SWITCH: s = P.ParseSwitchStat(); - case Scanner.RANGE: - s = P.ParseRangeStat(); case Scanner.SELECT: s = P.ParseSelectStat(); default: @@ -1469,10 +1459,9 @@ func (P *Parser) ParseStatement() *AST.Stat { // ---------------------------------------------------------------------------- // Declarations -func (P *Parser) ParseImportSpec(pos int) *AST.Decl { +func (P *Parser) ParseImportSpec(d *AST.Decl) { P.Trace("ImportSpec"); - d := AST.NewDecl(pos, Scanner.IMPORT); if P.tok == Scanner.PERIOD { P.Error(P.pos, `"import ." not yet handled properly`); P.Next(); @@ -1494,14 +1483,12 @@ func (P *Parser) ParseImportSpec(pos int) *AST.Decl { } P.Ecart(); - return d; } -func (P *Parser) ParseConstSpec(pos int) *AST.Decl { +func (P *Parser) ParseConstSpec(d *AST.Decl) { P.Trace("ConstSpec"); - d := AST.NewDecl(pos, Scanner.CONST); d.Ident = P.ParseIdentList(); d.Typ = P.TryType(); if P.tok == Scanner.ASSIGN { @@ -1512,27 +1499,23 @@ func (P *Parser) ParseConstSpec(pos int) *AST.Decl { P.Declare(d.Ident, AST.CONST); P.Ecart(); - return d; } -func (P *Parser) ParseTypeSpec(pos int) *AST.Decl { +func (P *Parser) ParseTypeSpec(d *AST.Decl) { P.Trace("TypeSpec"); - d := AST.NewDecl(pos, Scanner.TYPE); d.Ident = P.ParseIdent(nil); d.Typ = P.ParseType(); P.opt_semi = true; P.Ecart(); - return d; } -func (P *Parser) ParseVarSpec(pos int) *AST.Decl { +func (P *Parser) ParseVarSpec(d *AST.Decl) { P.Trace("VarSpec"); - d := AST.NewDecl(pos, Scanner.VAR); d.Ident = P.ParseIdentList(); if P.tok == Scanner.ASSIGN { P.Next(); @@ -1548,35 +1531,59 @@ func (P *Parser) ParseVarSpec(pos int) *AST.Decl { P.Declare(d.Ident, AST.VAR); P.Ecart(); - return d; } -// TODO replace this by using function pointers derived from methods -func (P *Parser) ParseSpec(pos int, keyword int) *AST.Decl { - switch keyword { - case Scanner.IMPORT: return P.ParseImportSpec(pos); - case Scanner.CONST: return P.ParseConstSpec(pos); - case Scanner.TYPE: return P.ParseTypeSpec(pos); - case Scanner.VAR: return P.ParseVarSpec(pos); +func (P *Parser) ParseSpec(d *AST.Decl) { + switch d.Tok { + case Scanner.IMPORT: P.ParseImportSpec(d); + case Scanner.CONST: P.ParseConstSpec(d); + case Scanner.TYPE: P.ParseTypeSpec(d); + case Scanner.VAR: P.ParseVarSpec(d); + default: unreachable(); + } + + // semantic checks + if d.Tok == Scanner.IMPORT { + // TODO + } else { + if d.Typ != nil { + // apply type to all variables + } + if d.Val != nil { + // initialization/assignment + llen := d.Ident.Len(); + rlen := d.Val.Len(); + if llen == rlen { + // TODO + } else if rlen == 1 { + // TODO + } else { + if llen < rlen { + P.Error(d.Val.At(llen).Pos, "more expressions than variables"); + } else { + P.Error(d.Ident.At(rlen).Pos, "more variables than expressions"); + } + } + } else { + // TODO + } } - panic("UNREACHABLE"); - return nil; } func (P *Parser) ParseDecl(keyword int) *AST.Decl { P.Trace("Decl"); - d := AST.BadDecl; - pos := P.pos; + d := AST.NewDecl(P.pos, keyword); P.Expect(keyword); if P.tok == Scanner.LPAREN { P.Next(); - d = AST.NewDecl(pos, keyword); d.List = array.New(0); for P.tok != Scanner.RPAREN && P.tok != Scanner.EOF { - d.List.Push(P.ParseSpec(pos, keyword)); + d1 := AST.NewDecl(P.pos, keyword); + P.ParseSpec(d1); + d.List.Push(d1); if P.tok == Scanner.SEMICOLON { P.Next(); } else { @@ -1588,7 +1595,7 @@ func (P *Parser) ParseDecl(keyword int) *AST.Decl { P.opt_semi = true; } else { - d = P.ParseSpec(pos, keyword); + P.ParseSpec(d); } P.Ecart(); @@ -1625,9 +1632,10 @@ func (P *Parser) ParseFunctionDecl() *AST.Decl { d.Typ.Key = recv; if P.tok == Scanner.LBRACE { - P.scope_lev++; - d.List, d.End = P.ParseBlock(); - P.scope_lev--; + f := AST.NewObject(d.Pos, AST.FUNC, d.Ident.Obj.Ident); + f.Typ = d.Typ; + f.Body = P.ParseBlock(d.Typ, Scanner.LBRACE); + d.Val = AST.NewLit(Scanner.FUNC, f); } P.Ecart(); diff --git a/usr/gri/pretty/printer.go b/usr/gri/pretty/printer.go index 25ac9cd67b..87b5f68167 100644 --- a/usr/gri/pretty/printer.go +++ b/usr/gri/pretty/printer.go @@ -537,7 +537,7 @@ func (P *Printer) Type(t *AST.Type) int { // ---------------------------------------------------------------------------- // Expressions -func (P *Printer) Block(pos int, list *array.Array, end int, indent bool); +func (P *Printer) Block(b *AST.Block, indent bool); func (P *Printer) Expr1(x *AST.Expr, prec1 int) { if x == nil { @@ -547,7 +547,7 @@ func (P *Printer) Expr1(x *AST.Expr, prec1 int) { switch x.Tok { case Scanner.TYPE: // type expr - P.Type(x.Obj.Typ); + P.Type(x.Typ); case Scanner.IDENT: P.HtmlIdentifier(x); @@ -560,7 +560,7 @@ func (P *Printer) Expr1(x *AST.Expr, prec1 int) { // function literal P.String(x.Pos, "func"); P.Type(x.Obj.Typ); - P.Block(0, x.Obj.Block, x.Obj.End, true); + P.Block(x.Obj.Body, true); P.newlines = 0; case Scanner.COMMA: @@ -646,24 +646,22 @@ func (P *Printer) Expr(x *AST.Expr) { func (P *Printer) Stat(s *AST.Stat) func (P *Printer) StatementList(list *array.Array) { - if list != nil { + for i, n := 0, list.Len(); i < n; i++ { + P.newlines = 1; // for first entry + P.Stat(list.At(i).(*AST.Stat)); P.newlines = 1; - for i, n := 0, list.Len(); i < n; i++ { - P.Stat(list.At(i).(*AST.Stat)); - P.newlines = 1; - P.state = inside_list; - } + P.state = inside_list; } } -func (P *Printer) Block(pos int, list *array.Array, end int, indent bool) { +func (P *Printer) Block(b *AST.Block, indent bool) { P.state = opening_scope; - P.String(pos, "{"); + P.Token(b.Pos, b.Tok); if !indent { P.indentation--; } - P.StatementList(list); + P.StatementList(b.List); if !indent { P.indentation++; } @@ -671,7 +669,11 @@ func (P *Printer) Block(pos int, list *array.Array, end int, indent bool) { P.separator = none; } P.state = closing_scope; - P.String(end, "}"); + if b.Tok == Scanner.LBRACE { + P.String(b.End, "}"); + } else { + P.String(0, ""); // process closing_scope state transition! + } } @@ -737,12 +739,12 @@ func (P *Printer) Stat(s *AST.Stat) { case Scanner.LBRACE: // block - P.Block(s.Pos, s.Block, s.End, true); + P.Block(s.Body, true); case Scanner.IF: P.String(s.Pos, "if"); P.ControlClause(s); - P.Block(0, s.Block, s.End, true); + P.Block(s.Body, true); if s.Post != nil { P.separator = blank; P.String(0, "else"); @@ -753,12 +755,12 @@ func (P *Printer) Stat(s *AST.Stat) { case Scanner.FOR: P.String(s.Pos, "for"); P.ControlClause(s); - P.Block(0, s.Block, s.End, true); + P.Block(s.Body, true); case Scanner.SWITCH, Scanner.SELECT: P.Token(s.Pos, s.Tok); P.ControlClause(s); - P.Block(0, s.Block, s.End, false); + P.Block(s.Body, false); case Scanner.CASE, Scanner.DEFAULT: P.Token(s.Pos, s.Tok); @@ -766,9 +768,11 @@ func (P *Printer) Stat(s *AST.Stat) { P.separator = blank; P.Expr(s.Expr); } - P.String(0, ":"); + // TODO: try to use P.Block instead + // P.Block(s.Body, true); + P.String(s.Body.Pos, ":"); P.indentation++; - P.StatementList(s.Block); + P.StatementList(s.Body.List); P.indentation--; P.newlines = 1; @@ -850,9 +854,9 @@ func (P *Printer) Declaration(d *AST.Decl, parenthesized bool) { } P.Expr(d.Ident); P.separator = P.Type(d.Typ); - if d.List != nil { + if d.Val != nil { P.separator = blank; - P.Block(0, d.List, d.End, true); + P.Block(d.Val.Obj.Body, true); } default: diff --git a/usr/gri/pretty/scanner.go b/usr/gri/pretty/scanner.go index fda7c541ef..49aaecb6ad 100644 --- a/usr/gri/pretty/scanner.go +++ b/usr/gri/pretty/scanner.go @@ -170,8 +170,8 @@ func TokenString(tok int) string { case RPAREN: return ")"; case LBRACK: return "["; case RBRACK: return "]"; - case LBRACE: return "LBRACE"; - case RBRACE: return "RBRACE"; + case LBRACE: return "{"; + case RBRACE: return "}"; case COMMA: return ","; case SEMICOLON: return ";"; diff --git a/usr/gri/pretty/test.sh b/usr/gri/pretty/test.sh index 03b8a917c8..9d07fe81fb 100755 --- a/usr/gri/pretty/test.sh +++ b/usr/gri/pretty/test.sh @@ -24,9 +24,10 @@ apply1() { #echo $1 $2 case `basename $F` in # files with errors (skip them) + # the following have semantic errors: bug039.go | bug040.go method1.go | selftest1.go | func3.go | \ - bug014.go | bug025.go | bug029.go | bug032.go | bug050.go | bug068.go | \ - bug088.go | bug083.go | bug106.go | bug125.go | bug126.go ) ;; + bug014.go | bug025.go | bug029.go | bug032.go | bug039.go | bug040.go | bug050.go | bug068.go | \ + bug088.go | bug083.go | bug106.go | bug125.go | bug126.go | bug132.go ) ;; * ) $1 $2; count $F;; esac } -- 2.48.1