From: Robert Griesemer Date: Thu, 5 Feb 2009 02:28:41 +0000 (-0800) Subject: today's snapshot: steps towards using interfaces for statements in ast X-Git-Tag: weekly.2009-11-06~2237 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=1595a1947c047070542b6c8d7478eaf485489bbb;p=gostls13.git today's snapshot: steps towards using interfaces for statements in ast R=r OCL=24380 CL=24380 --- diff --git a/usr/gri/pretty/ast.go b/usr/gri/pretty/ast.go index cfd345d5a9..c0b3c86278 100644 --- a/usr/gri/pretty/ast.go +++ b/usr/gri/pretty/ast.go @@ -18,7 +18,7 @@ type ( Block struct; Expr interface; - Stat struct; + StatImpl struct; Decl struct; ) @@ -350,11 +350,11 @@ func NewBlock(pos, tok int) *Block { // Expressions type ( - Visitor interface; + ExprVisitor interface; Expr interface { Pos() int; - Visit(v Visitor); + Visit(v ExprVisitor); }; BadExpr struct { @@ -421,7 +421,7 @@ type ( ) -type Visitor interface { +type ExprVisitor interface { DoBadExpr(x *BadExpr); DoIdent(x *Ident); DoBinaryExpr(x *BinaryExpr); @@ -451,18 +451,18 @@ func (x *Index) Pos() int { return x.Pos_; } func (x *Call) Pos() int { return x.Pos_; } -func (x *BadExpr) Visit(v Visitor) { v.DoBadExpr(x); } -func (x *Ident) Visit(v Visitor) { v.DoIdent(x); } -func (x *BinaryExpr) Visit(v Visitor) { v.DoBinaryExpr(x); } -func (x *UnaryExpr) Visit(v Visitor) { v.DoUnaryExpr(x); } -func (x *BasicLit) Visit(v Visitor) { v.DoBasicLit(x); } -func (x *FunctionLit) Visit(v Visitor) { v.DoFunctionLit(x); } -func (x *CompositeLit) Visit(v Visitor) { v.DoCompositeLit(x); } -func (x *TypeLit) Visit(v Visitor) { v.DoTypeLit(x); } -func (x *Selector) Visit(v Visitor) { v.DoSelector(x); } -func (x *TypeGuard) Visit(v Visitor) { v.DoTypeGuard(x); } -func (x *Index) Visit(v Visitor) { v.DoIndex(x); } -func (x *Call) Visit(v Visitor) { v.DoCall(x); } +func (x *BadExpr) Visit(v ExprVisitor) { v.DoBadExpr(x); } +func (x *Ident) Visit(v ExprVisitor) { v.DoIdent(x); } +func (x *BinaryExpr) Visit(v ExprVisitor) { v.DoBinaryExpr(x); } +func (x *UnaryExpr) Visit(v ExprVisitor) { v.DoUnaryExpr(x); } +func (x *BasicLit) Visit(v ExprVisitor) { v.DoBasicLit(x); } +func (x *FunctionLit) Visit(v ExprVisitor) { v.DoFunctionLit(x); } +func (x *CompositeLit) Visit(v ExprVisitor) { v.DoCompositeLit(x); } +func (x *TypeLit) Visit(v ExprVisitor) { v.DoTypeLit(x); } +func (x *Selector) Visit(v ExprVisitor) { v.DoSelector(x); } +func (x *TypeGuard) Visit(v ExprVisitor) { v.DoTypeGuard(x); } +func (x *Index) Visit(v ExprVisitor) { v.DoIndex(x); } +func (x *Call) Visit(v ExprVisitor) { v.DoCall(x); } @@ -518,23 +518,112 @@ func (t *Type) Nfields() int { // ---------------------------------------------------------------------------- // Statements -type Stat struct { +type ( + StatVisitor interface; + + Stat interface { + Visit(v StatVisitor); + }; + + BadStat struct { + Pos int; + }; + + LabelDecl struct { + Pos int; // position of ":" + Label *Ident; + }; + + DeclarationStat struct { + Decl *Decl; + }; + + ExpressionStat struct { + Pos int; // position of Tok + Tok int; // INC, DEC, RETURN, GO, DEFER + Expr Expr; + }; + + IfStat struct { + Pos int; // position of "if" + Init Stat; + Cond Expr; + Body *Block; + Else Stat; + }; + + ForStat struct { + Pos int; // position of "for" + Init Stat; + Cond Expr; + Post Stat; + Body *Block; + }; + + SwitchStat struct { + Pos int; // position of "switch" + Init Stat; + Tag Expr; + Body *Block; + }; + + SelectStat struct { + Pos int; // position of "select" + Body *Block; + }; + + ControlFlowStat struct { + Pos int; // position of Tok + Tok int; // BREAK, CONTINUE, GOTO, FALLTHROUGH + Label *Ident; // if any, or nil + }; +) + + +type StatVisitor interface { + DoBadStat(s *BadStat); + DoLabelDecl(s *LabelDecl); + DoDeclarationStat(s *DeclarationStat); + DoExpressionStat(s *ExpressionStat); + DoIfStat(s *IfStat); + DoForStat(s *ForStat); + DoSwitchStat(s *SwitchStat); + DoSelectStat(s *SelectStat); + DoControlFlowStat(s *ControlFlowStat); +} + + +func (s *BadStat) Visit(v StatVisitor) { v.DoBadStat(s); } +func (s *LabelDecl) Visit(v StatVisitor) { v.DoLabelDecl(s); } +func (s *DeclarationStat) Visit(v StatVisitor) { v.DoDeclarationStat(s); } +func (s *ExpressionStat) Visit(v StatVisitor) { v.DoExpressionStat(s); } +func (s *IfStat) Visit(v StatVisitor) { v.DoIfStat(s); } +func (s *ForStat) Visit(v StatVisitor) { v.DoForStat(s); } +func (s *SwitchStat) Visit(v StatVisitor) { v.DoSwitchStat(s); } +func (s *SelectStat) Visit(v StatVisitor) { v.DoSelectStat(s); } +func (s *ControlFlowStat) Visit(v StatVisitor) { v.DoControlFlowStat(s); } + + +// ---------------------------------------------------------------------------- +// Old style statements + +type StatImpl struct { Node; - Init, Post *Stat; + Init, Post *StatImpl; Expr Expr; Body *Block; // composite statement body Decl *Decl; // declaration statement } -func NewStat(pos, tok int) *Stat { - s := new(Stat); +func NewStat(pos, tok int) *StatImpl { + s := new(StatImpl); s.Pos, s.Tok = pos, tok; return s; } -var BadStat = NewStat(0, Scanner.ILLEGAL); +var OldBadStat = NewStat(0, Scanner.ILLEGAL); // ---------------------------------------------------------------------------- diff --git a/usr/gri/pretty/parser.go b/usr/gri/pretty/parser.go index ae904a6511..f7e4ccd62c 100644 --- a/usr/gri/pretty/parser.go +++ b/usr/gri/pretty/parser.go @@ -5,6 +5,7 @@ package Parser import ( + "flag"; "fmt"; "array"; Scanner "scanner"; @@ -83,6 +84,13 @@ func (P *Parser) Ecart() { } +func (P *Parser) VerifyIndent(indent uint) { + if indent != P.indent { + panic("imbalanced tracing code"); + } +} + + func (P *Parser) Next0() { if P.tokchan == nil { P.pos, P.tok, P.val = P.scanner.Scan(); @@ -247,7 +255,8 @@ func (P *Parser) NewBinary(pos, tok int, x, y AST.Expr) *AST.BinaryExpr { func (P *Parser) TryType() *AST.Type; func (P *Parser) ParseExpression(prec int) AST.Expr; -func (P *Parser) ParseStatement() *AST.Stat; +func (P *Parser) ParseStatement() AST.Stat; +func (P *Parser) OldParseStatement() *AST.StatImpl; func (P *Parser) ParseDeclaration() *AST.Decl; @@ -746,14 +755,24 @@ func (P *Parser) TryType() *AST.Type { // ---------------------------------------------------------------------------- // Blocks + +var newstat = flag.Bool("newstat", false, "use new statement parsing - work in progress"); + + func (P *Parser) ParseStatementList(list *array.Array) { if P.verbose { P.Trace("StatementList"); defer P.Ecart(); + defer P.VerifyIndent(P.indent); } for P.tok != Scanner.CASE && P.tok != Scanner.DEFAULT && P.tok != Scanner.RBRACE && P.tok != Scanner.EOF { - s := P.ParseStatement(); + var s interface{}; + if *newstat { + s = P.ParseStatement(); + } else { + s = P.OldParseStatement(); + } if s != nil { // not the empty statement list.Push(s); @@ -1133,31 +1152,93 @@ func (P *Parser) ParseExpression(prec int) AST.Expr { if P.verbose { P.Trace("Expression"); defer P.Ecart(); + defer P.VerifyIndent(P.indent); } - indent := P.indent; if prec < 0 { panic("precedence must be >= 0"); } - x := P.NoType(P.ParseBinaryExpr(prec)); - if indent != P.indent { - panic("imbalanced tracing code (Expression)"); - } - return x; + return P.NoType(P.ParseBinaryExpr(prec)); } // ---------------------------------------------------------------------------- // Statements -func (P *Parser) ParseSimpleStat(range_ok bool) *AST.Stat { +func (P *Parser) ParseSimpleStat(range_ok bool) AST.Stat { + if P.verbose { + P.Trace("SimpleStat"); + defer P.Ecart(); + } + + x := P.ParseExpressionList(); + + switch P.tok { + case Scanner.COLON: + // label declaration + pos := P.pos; + P.Next(); // consume ":" + if AST.ExprLen(x) == 1 { + if label, is_ident := x.(*AST.Ident); is_ident { + return &AST.LabelDecl{pos, label}; + } + } + P.Error(x.Pos(), "illegal label declaration"); + return nil; + + 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: + // declaration/assignment + pos, tok := P.pos, P.tok; + P.Next(); + var y AST.Expr; + if range_ok && P.tok == Scanner.RANGE { + range_pos := P.pos; + P.Next(); + y = &AST.UnaryExpr{range_pos, Scanner.RANGE, P.ParseExpression(1)}; + if tok != Scanner.DEFINE && tok != Scanner.ASSIGN { + P.Error(pos, "expected '=' or ':=', found '" + Scanner.TokenString(tok) + "'"); + } + } else { + y = P.ParseExpressionList(); + if xl, yl := AST.ExprLen(x), AST.ExprLen(y); xl > 1 && yl > 1 && xl != yl { + P.Error(x.Pos(), "arity of lhs doesn't match rhs"); + } + } + // TODO changed ILLEGAL -> NONE + return &AST.ExpressionStat{x.Pos(), Scanner.ILLEGAL, P.NewBinary(pos, tok, x, y)}; + + default: + if AST.ExprLen(x) != 1 { + P.Error(x.Pos(), "only one expression allowed"); + } + + if P.tok == Scanner.INC || P.tok == Scanner.DEC { + s := &AST.ExpressionStat{P.pos, P.tok, x}; + P.Next(); // consume "++" or "--" + return s; + } + + // TODO changed ILLEGAL -> NONE + return &AST.ExpressionStat{x.Pos(), Scanner.ILLEGAL, x}; + } + + unreachable(); + return nil; +} + + +func (P *Parser) OldParseSimpleStat(range_ok bool) *AST.StatImpl { if P.verbose { P.Trace("SimpleStat"); defer P.Ecart(); } - s := AST.BadStat; + s := AST.OldBadStat; x := P.ParseExpressionList(); switch P.tok { @@ -1180,7 +1261,7 @@ func (P *Parser) ParseSimpleStat(range_ok bool) *AST.Stat { pos, tok := P.pos, P.tok; P.Next(); var y AST.Expr = &AST.BadExpr{pos}; - if P.tok == Scanner.RANGE { + if range_ok && P.tok == Scanner.RANGE { range_pos := P.pos; P.Next(); y = P.ParseExpression(1); @@ -1197,14 +1278,6 @@ func (P *Parser) ParseSimpleStat(range_ok bool) *AST.Stat { s = AST.NewStat(x.Pos(), Scanner.EXPRSTAT); s.Expr = P.NewBinary(pos, tok, x, y); - case Scanner.RANGE: - pos := P.pos; - P.Next(); - y := P.ParseExpression(1); - y = &AST.UnaryExpr{pos, Scanner.RANGE, y}; - s = AST.NewStat(x.Pos(), Scanner.EXPRSTAT); - s.Expr = P.NewBinary(pos, Scanner.DEFINE, x, y); - default: var pos, tok int; if P.tok == Scanner.INC || P.tok == Scanner.DEC { @@ -1225,7 +1298,19 @@ func (P *Parser) ParseSimpleStat(range_ok bool) *AST.Stat { } -func (P *Parser) ParseInvocationStat(keyword int) *AST.Stat { +func (P *Parser) ParseInvocationStat(keyword int) *AST.ExpressionStat { + if P.verbose { + P.Trace("InvocationStat"); + defer P.Ecart(); + } + + pos := P.pos; + P.Expect(keyword); + return &AST.ExpressionStat{pos, keyword, P.ParseExpression(1)}; +} + + +func (P *Parser) OldParseInvocationStat(keyword int) *AST.StatImpl { if P.verbose { P.Trace("InvocationStat"); defer P.Ecart(); @@ -1239,7 +1324,24 @@ func (P *Parser) ParseInvocationStat(keyword int) *AST.Stat { } -func (P *Parser) ParseReturnStat() *AST.Stat { +func (P *Parser) ParseReturnStat() *AST.ExpressionStat { + if P.verbose { + P.Trace("ReturnStat"); + defer P.Ecart(); + } + + pos := P.pos; + P.Expect(Scanner.RETURN); + var x AST.Expr; + if P.tok != Scanner.SEMICOLON && P.tok != Scanner.RBRACE { + x = P.ParseExpressionList(); + } + + return &AST.ExpressionStat{pos, Scanner.RETURN, x}; +} + + +func (P *Parser) OldParseReturnStat() *AST.StatImpl { if P.verbose { P.Trace("ReturnStat"); defer P.Ecart(); @@ -1255,7 +1357,7 @@ func (P *Parser) ParseReturnStat() *AST.Stat { } -func (P *Parser) ParseControlFlowStat(tok int) *AST.Stat { +func (P *Parser) ParseControlFlowStat(tok int) *AST.StatImpl { if P.verbose { P.Trace("ControlFlowStat"); defer P.Ecart(); @@ -1271,7 +1373,47 @@ func (P *Parser) ParseControlFlowStat(tok int) *AST.Stat { } -func (P *Parser) ParseControlClause(keyword int) *AST.Stat { +func (P *Parser) ParseControlClause(isForStat bool) (init AST.Stat, expr AST.Expr, post AST.Stat) { + if P.verbose { + P.Trace("ControlClause"); + defer P.Ecart(); + } + + if P.tok != Scanner.LBRACE { + prev_lev := P.expr_lev; + P.expr_lev = -1; + if P.tok != Scanner.SEMICOLON { + init = P.ParseSimpleStat(isForStat); + // TODO check for range clause and exit if found + } + if P.tok == Scanner.SEMICOLON { + P.Next(); + if P.tok != Scanner.SEMICOLON && P.tok != Scanner.LBRACE { + expr = P.ParseExpression(1); + } + if isForStat { + P.Expect(Scanner.SEMICOLON); + if P.tok != Scanner.LBRACE { + post = P.ParseSimpleStat(false); + } + } + } else { + if init != nil { // guard in case of errors + if s, is_expr_stat := init.(*AST.ExpressionStat); is_expr_stat { + expr, init = s.Expr, nil; + } else { + P.Error(0, "illegal control clause"); + } + } + } + P.expr_lev = prev_lev; + } + + return init, expr, post; +} + + +func (P *Parser) OldParseControlClause(keyword int) *AST.StatImpl { if P.verbose { P.Trace("ControlClause"); defer P.Ecart(); @@ -1283,7 +1425,7 @@ func (P *Parser) ParseControlClause(keyword int) *AST.Stat { prev_lev := P.expr_lev; P.expr_lev = -1; if P.tok != Scanner.SEMICOLON { - s.Init = P.ParseSimpleStat(keyword == Scanner.FOR); + s.Init = P.OldParseSimpleStat(keyword == Scanner.FOR); // TODO check for range clause and exit if found } if P.tok == Scanner.SEMICOLON { @@ -1294,7 +1436,7 @@ func (P *Parser) ParseControlClause(keyword int) *AST.Stat { if keyword == Scanner.FOR { P.Expect(Scanner.SEMICOLON); if P.tok != Scanner.LBRACE { - s.Post = P.ParseSimpleStat(false); + s.Post = P.OldParseSimpleStat(false); } } } else { @@ -1309,22 +1451,61 @@ func (P *Parser) ParseControlClause(keyword int) *AST.Stat { } -func (P *Parser) ParseIfStat() *AST.Stat { +func (P *Parser) ParseIfStat() *AST.IfStat { + if P.verbose { + P.Trace("IfStat"); + defer P.Ecart(); + } + + P.OpenScope(); + pos := P.pos; + P.Expect(Scanner.IF); + init, cond, dummy := P.ParseControlClause(false); + body := P.ParseBlock(nil, Scanner.LBRACE); + var else_ AST.Stat; + if P.tok == Scanner.ELSE { + P.Next(); + if P.tok == Scanner.IF || P.tok == Scanner.LBRACE { + else_ = P.ParseStatement(); + } else if P.sixg { + else_ = P.ParseStatement(); + if else_ != nil { + // not the empty statement + // wrap in a block since we don't have one + panic(); + /* + b := AST.NewStat(s1.Pos, Scanner.LBRACE); + b.Body = AST.NewBlock(s1.Pos, Scanner.LBRACE); + b.Body.List.Push(s1); + s1 = b; + */ + } + } else { + P.Error(P.pos, "'if' or '{' expected - illegal 'else' branch"); + } + } + P.CloseScope(); + + return &AST.IfStat{pos, init, cond, body, else_ }; +} + + +func (P *Parser) OldParseIfStat() *AST.StatImpl { if P.verbose { P.Trace("IfStat"); defer P.Ecart(); } P.OpenScope(); - s := P.ParseControlClause(Scanner.IF); + s := P.OldParseControlClause(Scanner.IF); s.Body = P.ParseBlock(nil, Scanner.LBRACE); if P.tok == Scanner.ELSE { P.Next(); - s1 := AST.BadStat; + s1 := AST.OldBadStat; if P.tok == Scanner.IF || P.tok == Scanner.LBRACE { - s1 = P.ParseStatement(); + s1 = P.OldParseStatement(); } else if P.sixg { - s1 = P.ParseStatement(); + s1 = P.OldParseStatement(); if s1 != nil { // not the empty statement assert(s1.Tok != Scanner.LBRACE); @@ -1345,14 +1526,31 @@ func (P *Parser) ParseIfStat() *AST.Stat { } -func (P *Parser) ParseForStat() *AST.Stat { +func (P *Parser) ParseForStat() *AST.ForStat { if P.verbose { P.Trace("ForStat"); defer P.Ecart(); } P.OpenScope(); - s := P.ParseControlClause(Scanner.FOR); + pos := P.pos; + P.Expect(Scanner.FOR); + init, cond, post := P.ParseControlClause(true); + body := P.ParseBlock(nil, Scanner.LBRACE); + P.CloseScope(); + + return &AST.ForStat{pos, init, cond, post, body}; +} + + +func (P *Parser) OldParseForStat() *AST.StatImpl { + if P.verbose { + P.Trace("ForStat"); + defer P.Ecart(); + } + + P.OpenScope(); + s := P.OldParseControlClause(Scanner.FOR); s.Body = P.ParseBlock(nil, Scanner.LBRACE); P.CloseScope(); @@ -1360,7 +1558,7 @@ func (P *Parser) ParseForStat() *AST.Stat { } -func (P *Parser) ParseSwitchCase() *AST.Stat { +func (P *Parser) ParseSwitchCase() *AST.StatImpl { if P.verbose { P.Trace("SwitchCase"); defer P.Ecart(); @@ -1378,7 +1576,7 @@ func (P *Parser) ParseSwitchCase() *AST.Stat { } -func (P *Parser) ParseCaseClause() *AST.Stat { +func (P *Parser) ParseCaseClause() *AST.StatImpl { if P.verbose { P.Trace("CaseClause"); defer P.Ecart(); @@ -1391,14 +1589,38 @@ func (P *Parser) ParseCaseClause() *AST.Stat { } -func (P *Parser) ParseSwitchStat() *AST.Stat { +func (P *Parser) ParseSwitchStat() *AST.SwitchStat { + if P.verbose { + P.Trace("SwitchStat"); + defer P.Ecart(); + } + + P.OpenScope(); + pos := P.pos; + P.Expect(Scanner.SWITCH); + init, tag, post := P.ParseControlClause(false); + body := AST.NewBlock(P.pos, Scanner.LBRACE); + P.Expect(Scanner.LBRACE); + for P.tok != Scanner.RBRACE && P.tok != Scanner.EOF { + body.List.Push(P.ParseCaseClause()); + } + body.End = P.pos; + P.Expect(Scanner.RBRACE); + P.opt_semi = true; + P.CloseScope(); + + return &AST.SwitchStat{pos, init, tag, body}; +} + + +func (P *Parser) OldParseSwitchStat() *AST.StatImpl { if P.verbose { P.Trace("SwitchStat"); defer P.Ecart(); } P.OpenScope(); - s := P.ParseControlClause(Scanner.SWITCH); + s := P.OldParseControlClause(Scanner.SWITCH); b := AST.NewBlock(P.pos, Scanner.LBRACE); P.Expect(Scanner.LBRACE); for P.tok != Scanner.RBRACE && P.tok != Scanner.EOF { @@ -1414,7 +1636,7 @@ func (P *Parser) ParseSwitchStat() *AST.Stat { } -func (P *Parser) ParseCommCase() *AST.Stat { +func (P *Parser) ParseCommCase() *AST.StatImpl { if P.verbose { P.Trace("CommCase"); defer P.Ecart(); @@ -1443,7 +1665,7 @@ func (P *Parser) ParseCommCase() *AST.Stat { } -func (P *Parser) ParseCommClause() *AST.Stat { +func (P *Parser) ParseCommClause() *AST.StatImpl { if P.verbose { P.Trace("CommClause"); defer P.Ecart(); @@ -1456,12 +1678,36 @@ func (P *Parser) ParseCommClause() *AST.Stat { } -func (P *Parser) ParseSelectStat() *AST.Stat { +func (P *Parser) ParseSelectStat() *AST.SelectStat { if P.verbose { P.Trace("SelectStat"); defer P.Ecart(); } + P.OpenScope(); + pos := P.pos; + P.Expect(Scanner.SELECT); + body := AST.NewBlock(P.pos, Scanner.LBRACE); + P.Expect(Scanner.LBRACE); + for P.tok != Scanner.RBRACE && P.tok != Scanner.EOF { + body.List.Push(P.ParseCommClause()); + } + body.End = P.pos; + P.Expect(Scanner.RBRACE); + P.opt_semi = true; + P.CloseScope(); + + return &AST.SelectStat{pos, body}; +} + + +func (P *Parser) OldParseSelectStat() *AST.StatImpl { + if P.verbose { + P.Trace("SelectStat"); + defer P.Ecart(); + } + + P.OpenScope(); s := AST.NewStat(P.pos, Scanner.SELECT); P.Expect(Scanner.SELECT); b := AST.NewBlock(P.pos, Scanner.LBRACE); @@ -1472,20 +1718,66 @@ func (P *Parser) ParseSelectStat() *AST.Stat { b.End = P.pos; P.Expect(Scanner.RBRACE); P.opt_semi = true; + P.CloseScope(); s.Body = b; return s; } -func (P *Parser) ParseStatement() *AST.Stat { +func (P *Parser) ParseStatement() AST.Stat { if P.verbose { P.Trace("Statement"); defer P.Ecart(); + defer P.VerifyIndent(P.indent); + } + + s := AST.OldBadStat; + switch P.tok { + case Scanner.CONST, Scanner.TYPE, Scanner.VAR: + return &AST.DeclarationStat{P.ParseDeclaration()}; + case Scanner.FUNC: + // for now we do not allow local function declarations, + // instead we assume this starts a function literal + fallthrough; + case + // only the tokens that are legal top-level expression starts + Scanner.IDENT, Scanner.INT, Scanner.FLOAT, Scanner.STRING, Scanner.LPAREN, // operand + Scanner.LBRACK, Scanner.STRUCT, // composite type + Scanner.MUL, Scanner.AND, Scanner.ARROW: // unary + return P.ParseSimpleStat(false); + case Scanner.GO, Scanner.DEFER: + return P.ParseInvocationStat(P.tok); + case Scanner.RETURN: + return P.ParseReturnStat(); + case Scanner.BREAK, Scanner.CONTINUE, Scanner.GOTO, Scanner.FALLTHROUGH: + s = P.ParseControlFlowStat(P.tok); + case Scanner.LBRACE: + s = AST.NewStat(P.pos, Scanner.LBRACE); + s.Body = P.ParseBlock(nil, Scanner.LBRACE); + case Scanner.IF: + return P.ParseIfStat(); + case Scanner.FOR: + return P.ParseForStat(); + case Scanner.SWITCH: + return P.ParseSwitchStat(); + case Scanner.SELECT: + return P.ParseSelectStat(); + } + + // empty statement + return nil; +} + + +func (P *Parser) OldParseStatement() *AST.StatImpl { + if P.verbose { + P.Trace("Statement"); + defer P.Ecart(); + defer P.VerifyIndent(P.indent); } - indent := P.indent; - s := AST.BadStat; + s := AST.OldBadStat; switch P.tok { case Scanner.CONST, Scanner.TYPE, Scanner.VAR: s = AST.NewStat(P.pos, P.tok); @@ -1499,32 +1791,29 @@ func (P *Parser) ParseStatement() *AST.Stat { Scanner.IDENT, Scanner.INT, Scanner.FLOAT, Scanner.STRING, Scanner.LPAREN, // operand Scanner.LBRACK, Scanner.STRUCT, // composite type Scanner.MUL, Scanner.AND, Scanner.ARROW: // unary - s = P.ParseSimpleStat(false); + s = P.OldParseSimpleStat(false); case Scanner.GO, Scanner.DEFER: - s = P.ParseInvocationStat(P.tok); + s = P.OldParseInvocationStat(P.tok); case Scanner.RETURN: - s = P.ParseReturnStat(); + s = P.OldParseReturnStat(); case Scanner.BREAK, Scanner.CONTINUE, Scanner.GOTO, Scanner.FALLTHROUGH: s = P.ParseControlFlowStat(P.tok); case Scanner.LBRACE: s = AST.NewStat(P.pos, Scanner.LBRACE); s.Body = P.ParseBlock(nil, Scanner.LBRACE); case Scanner.IF: - s = P.ParseIfStat(); + s = P.OldParseIfStat(); case Scanner.FOR: - s = P.ParseForStat(); + s = P.OldParseForStat(); case Scanner.SWITCH: - s = P.ParseSwitchStat(); + s = P.OldParseSwitchStat(); case Scanner.SELECT: - s = P.ParseSelectStat(); + s = P.OldParseSelectStat(); default: // empty statement s = nil; } - if indent != P.indent { - panic("imbalanced tracing code (Statement)"); - } return s; } @@ -1719,6 +2008,7 @@ func (P *Parser) ParseDeclaration() *AST.Decl { if P.verbose { P.Trace("Declaration"); defer P.Ecart(); + defer P.VerifyIndent(P.indent); } indent := P.indent; @@ -1734,9 +2024,6 @@ func (P *Parser) ParseDeclaration() *AST.Decl { P.Next(); // make progress } - if indent != P.indent { - panic("imbalanced tracing code (Declaration)"); - } return d; } diff --git a/usr/gri/pretty/printer.go b/usr/gri/pretty/printer.go index 5e3f8a4b74..143886fce7 100644 --- a/usr/gri/pretty/printer.go +++ b/usr/gri/pretty/printer.go @@ -371,9 +371,8 @@ func (P *Printer) Token(pos int, tok int) { func (P *Printer) Error(pos int, tok int, msg string) { - P.String(0, "<"); - P.Token(pos, tok); - P.String(0, " " + msg + ">"); + fmt.Printf("\ninternal printing error: pos = %d, tok = %s, %s\n", pos, Scanner.TokenString(tok), msg); + panic(); } @@ -723,12 +722,25 @@ func (P *Printer) Expr(x AST.Expr) { // ---------------------------------------------------------------------------- // Statements -func (P *Printer) Stat(s *AST.Stat) +func (P *Printer) Stat(s AST.Stat) { + s.Visit(P); +} + + +func (P *Printer) StatImpl(s *AST.StatImpl) func (P *Printer) StatementList(list *array.Array) { for i, n := 0, list.Len(); i < n; i++ { P.newlines = 1; // for first entry - P.Stat(list.At(i).(*AST.Stat)); + + if s, is_StatImpl := list.At(i).(*AST.StatImpl); is_StatImpl { + P.StatImpl(s); + } else if s, is_Stat := list.At(i).(AST.Stat); is_Stat { + s.Visit(P); + } else { + panic(); + } + P.newlines = 1; P.state = inside_list; } @@ -757,7 +769,7 @@ func (P *Printer) Block(b *AST.Block, indent bool) { } -func (P *Printer) ControlClause(s *AST.Stat) { +func (P *Printer) OldControlClause(s *AST.StatImpl) { has_post := s.Tok == Scanner.FOR && s.Post != nil; // post also used by "if" P.separator = blank; @@ -770,7 +782,7 @@ func (P *Printer) ControlClause(s *AST.Stat) { // all semicolons required // (they are not separators, print them explicitly) if s.Init != nil { - P.Stat(s.Init); + P.StatImpl(s.Init); P.separator = none; } P.String(0, ";"); @@ -783,7 +795,7 @@ func (P *Printer) ControlClause(s *AST.Stat) { P.String(0, ";"); P.separator = blank; if has_post { - P.Stat(s.Post); + P.StatImpl(s.Post); } } } @@ -793,7 +805,7 @@ func (P *Printer) ControlClause(s *AST.Stat) { func (P *Printer) Declaration(d *AST.Decl, parenthesized bool); -func (P *Printer) Stat(s *AST.Stat) { +func (P *Printer) StatImpl(s *AST.StatImpl) { switch s.Tok { case Scanner.EXPRSTAT: // expression statement @@ -823,23 +835,23 @@ func (P *Printer) Stat(s *AST.Stat) { case Scanner.IF: P.String(s.Pos, "if"); - P.ControlClause(s); + P.OldControlClause(s); P.Block(s.Body, true); if s.Post != nil { P.separator = blank; P.String(0, "else"); P.separator = blank; - P.Stat(s.Post); + P.StatImpl(s.Post); } case Scanner.FOR: P.String(s.Pos, "for"); - P.ControlClause(s); + P.OldControlClause(s); P.Block(s.Body, true); case Scanner.SWITCH, Scanner.SELECT: P.Token(s.Pos, s.Tok); - P.ControlClause(s); + P.OldControlClause(s); P.Block(s.Body, false); case Scanner.CASE, Scanner.DEFAULT: @@ -872,6 +884,116 @@ func (P *Printer) Stat(s *AST.Stat) { } +func (P *Printer) DoBadStat(s *AST.BadStat) { + panic(); +} + + +func (P *Printer) DoLabelDecl(s *AST.LabelDecl) { + panic(); +} + + +func (P *Printer) DoDeclarationStat(s *AST.DeclarationStat) { + P.Declaration(s.Decl, false); +} + + +func (P *Printer) DoExpressionStat(s *AST.ExpressionStat) { + switch s.Tok { + case Scanner.ILLEGAL: + P.Expr(s.Expr); + case Scanner.INC, Scanner.DEC: + P.Expr(s.Expr); + P.Token(s.Pos, s.Tok); + case Scanner.RETURN, Scanner.GO, Scanner.DEFER: + P.Token(s.Pos, s.Tok); + if s.Expr != nil { + P.separator = blank; + P.Expr(s.Expr); + } + default: + P.Error(s.Pos, s.Tok, "DoExpressionStat"); + unreachable(); + } + P.separator = semicolon; +} + + +func (P *Printer) ControlClause(isForStat bool, init AST.Stat, expr AST.Expr, post AST.Stat) { + P.separator = blank; + if init == nil && post == nil { + // no semicolons required + if expr != nil { + P.Expr(expr); + } + } else { + // all semicolons required + // (they are not separators, print them explicitly) + if init != nil { + P.Stat(init); + P.separator = none; + } + P.String(0, ";"); + P.separator = blank; + if expr != nil { + P.Expr(expr); + P.separator = none; + } + if isForStat { + P.String(0, ";"); + P.separator = blank; + if post != nil { + P.Stat(post); + } + } + } + P.separator = blank; +} + + +func (P *Printer) DoIfStat(s *AST.IfStat) { + P.String(s.Pos, "if"); + P.ControlClause(false, s.Init, s.Cond, nil); + P.Block(s.Body, true); + if s.Else != nil { + P.separator = blank; + P.String(0, "else"); + P.separator = blank; + P.Stat(s.Else); + } +} + + +func (P *Printer) DoForStat(s *AST.ForStat) { + P.String(s.Pos, "for"); + P.ControlClause(true, s.Init, s.Cond, s.Post); + P.Block(s.Body, true); +} + + +func (P *Printer) DoSwitchStat(s *AST.SwitchStat) { + P.String(s.Pos, "switch"); + P.ControlClause(false, s.Init, s.Tag, nil); + P.Block(s.Body, false); +} + + +func (P *Printer) DoSelectStat(s *AST.SelectStat) { + panic(); +} + + +func (P *Printer) DoControlFlowStat(s *AST.ControlFlowStat) { + P.Token(s.Pos, s.Tok); + if s.Label != nil { + P.separator = blank; + P.Expr(s.Label); + } + P.separator = semicolon; +} + + // ---------------------------------------------------------------------------- // Declarations