mirror of
https://github.com/golang/go
synced 2024-11-12 10:30:23 -07:00
snapshot: more pretty printer stuff
R=r OCL=15863 CL=15863
This commit is contained in:
parent
99ec031391
commit
c51195386e
@ -49,6 +49,7 @@ export type Visitor interface {
|
||||
DoSwitchStat(x *SwitchStat);
|
||||
DoReturnStat(x *ReturnStat);
|
||||
DoIncDecStat(x *IncDecStat);
|
||||
DoControlFlowStat(x *ControlFlowStat);
|
||||
|
||||
// Program
|
||||
DoProgram(x *Program);
|
||||
@ -65,6 +66,9 @@ export type Node interface {
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Lists
|
||||
//
|
||||
// If p is a list and p == nil, then p.len() == 0.
|
||||
// Thus, empty lists can be represented by nil.
|
||||
|
||||
export type List struct {
|
||||
a *[] Node
|
||||
@ -335,19 +339,26 @@ export type Assignment struct {
|
||||
}
|
||||
|
||||
|
||||
export type ControlClause struct {
|
||||
init Stat;
|
||||
expr Expr;
|
||||
post Stat;
|
||||
has_init, has_expr, has_post bool;
|
||||
}
|
||||
|
||||
|
||||
export type IfStat struct {
|
||||
pos int; // position of "if"
|
||||
init Stat;
|
||||
cond Expr;
|
||||
then, else_ *Block;
|
||||
ctrl *ControlClause;
|
||||
then *Block;
|
||||
else_ Stat;
|
||||
has_else bool;
|
||||
}
|
||||
|
||||
|
||||
export type ForStat struct {
|
||||
pos int; // position of "for"
|
||||
init Stat;
|
||||
cond Expr;
|
||||
post Stat;
|
||||
ctrl *ControlClause;
|
||||
body *Block;
|
||||
}
|
||||
|
||||
@ -362,15 +373,14 @@ export type CaseClause struct {
|
||||
|
||||
export type SwitchStat struct {
|
||||
pos int; // position of "switch"
|
||||
init Stat;
|
||||
tag Expr;
|
||||
ctrl *ControlClause;
|
||||
cases *List; // list of *CaseClause
|
||||
}
|
||||
|
||||
|
||||
export type ReturnStat struct {
|
||||
pos int; // position of "return"
|
||||
res *List;
|
||||
res *List; // list of Expr
|
||||
}
|
||||
|
||||
|
||||
@ -381,17 +391,24 @@ export type IncDecStat struct {
|
||||
}
|
||||
|
||||
|
||||
func (x *Block) Visit(v Visitor) { v.DoBlock(x); }
|
||||
func (x *ExprStat) Visit(v Visitor) { v.DoExprStat(x); }
|
||||
func (x *Assignment) Visit(v Visitor) { v.DoAssignment(x); }
|
||||
func (x *IfStat) Visit(v Visitor) { v.DoIfStat(x); }
|
||||
func (x *ForStat) Visit(v Visitor) { v.DoForStat(x); }
|
||||
func (x *CaseClause) Visit(v Visitor) { v.DoCaseClause(x); }
|
||||
func (x *SwitchStat) Visit(v Visitor) { v.DoSwitchStat(x); }
|
||||
func (x *ReturnStat) Visit(v Visitor) { v.DoReturnStat(x); }
|
||||
func (x *IncDecStat) Visit(v Visitor) { v.DoIncDecStat(x); }
|
||||
export type ControlFlowStat struct {
|
||||
pos int; // position of token
|
||||
tok int;
|
||||
label *Ident; // nil, if no label
|
||||
}
|
||||
|
||||
|
||||
func (x *Block) Visit(v Visitor) { v.DoBlock(x); }
|
||||
func (x *ExprStat) Visit(v Visitor) { v.DoExprStat(x); }
|
||||
func (x *Assignment) Visit(v Visitor) { v.DoAssignment(x); }
|
||||
func (x *IfStat) Visit(v Visitor) { v.DoIfStat(x); }
|
||||
func (x *ForStat) Visit(v Visitor) { v.DoForStat(x); }
|
||||
func (x *CaseClause) Visit(v Visitor) { v.DoCaseClause(x); }
|
||||
func (x *SwitchStat) Visit(v Visitor) { v.DoSwitchStat(x); }
|
||||
func (x *ReturnStat) Visit(v Visitor) { v.DoReturnStat(x); }
|
||||
func (x *IncDecStat) Visit(v Visitor) { v.DoIncDecStat(x); }
|
||||
func (x *ControlFlowStat) Visit(v Visitor) { v.DoControlFlowStat(x); }
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Program
|
||||
|
||||
|
@ -912,99 +912,91 @@ func (P *Parser) ParseGoStat() {
|
||||
func (P *Parser) ParseReturnStat() *AST.ReturnStat {
|
||||
P.Trace("ReturnStat");
|
||||
|
||||
ret := new(AST.ReturnStat);
|
||||
ret.pos = P.pos;
|
||||
stat := new(AST.ReturnStat);
|
||||
stat.pos = P.pos;
|
||||
|
||||
P.Expect(Scanner.RETURN);
|
||||
if P.tok != Scanner.SEMICOLON && P.tok != Scanner.RBRACE {
|
||||
ret.res = P.ParseExpressionList();
|
||||
stat.res = P.ParseExpressionList();
|
||||
}
|
||||
|
||||
P.Ecart();
|
||||
return ret;
|
||||
return stat;
|
||||
}
|
||||
|
||||
|
||||
func (P *Parser) ParseControlFlowStat(tok int) {
|
||||
func (P *Parser) ParseControlFlowStat(tok int) *AST.ControlFlowStat {
|
||||
P.Trace("ControlFlowStat");
|
||||
|
||||
stat := new(AST.ControlFlowStat);
|
||||
stat.pos, stat.tok = P.pos, P.tok;
|
||||
|
||||
P.Expect(tok);
|
||||
if P.tok == Scanner.IDENT {
|
||||
P.ParseIdent();
|
||||
stat.label = P.ParseIdent();
|
||||
}
|
||||
|
||||
P.Ecart();
|
||||
return stat;
|
||||
}
|
||||
|
||||
|
||||
func (P *Parser) ParseStatHeader(keyword int) (init_ AST.Stat, expr_ AST.Expr, post_ AST.Stat) {
|
||||
func (P *Parser) ParseControlClause(keyword int) *AST.ControlClause {
|
||||
P.Trace("StatHeader");
|
||||
|
||||
var (
|
||||
init AST.Stat = AST.NIL;
|
||||
expr AST.Expr = AST.NIL;
|
||||
post AST.Stat = AST.NIL;
|
||||
)
|
||||
|
||||
has_init, has_expr, has_post := false, false, false;
|
||||
ctrl := new(AST.ControlClause);
|
||||
ctrl.init, ctrl.expr, ctrl.post = AST.NIL, AST.NIL, AST.NIL;
|
||||
|
||||
P.Expect(keyword);
|
||||
if P.tok != Scanner.LBRACE {
|
||||
if P.tok != Scanner.SEMICOLON {
|
||||
init = P.ParseSimpleStat();
|
||||
has_init = true;
|
||||
ctrl.init = P.ParseSimpleStat();
|
||||
ctrl.has_init = true;
|
||||
}
|
||||
if P.tok == Scanner.SEMICOLON {
|
||||
P.Next();
|
||||
if P.tok != Scanner.SEMICOLON && P.tok != Scanner.LBRACE {
|
||||
ctrl.expr = P.ParseExpression();
|
||||
ctrl.has_expr = true;
|
||||
}
|
||||
if keyword == Scanner.FOR {
|
||||
if P.tok != Scanner.SEMICOLON {
|
||||
expr = P.ParseExpression();
|
||||
has_expr = true;
|
||||
}
|
||||
P.Expect(Scanner.SEMICOLON);
|
||||
if P.tok != Scanner.LBRACE {
|
||||
post = P.ParseSimpleStat();
|
||||
has_post = true;
|
||||
}
|
||||
} else {
|
||||
if P.tok != Scanner.LBRACE {
|
||||
expr = P.ParseExpression();
|
||||
has_expr = true;
|
||||
ctrl.post = P.ParseSimpleStat();
|
||||
ctrl.has_post = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ctrl.expr, ctrl.has_expr = ctrl.init, ctrl.has_init;
|
||||
ctrl.init, ctrl.has_init = AST.NIL, false;
|
||||
}
|
||||
}
|
||||
|
||||
P.Ecart();
|
||||
return init, expr, post;
|
||||
return ctrl;
|
||||
}
|
||||
|
||||
|
||||
func (P *Parser) ParseIfStat() *AST.IfStat {
|
||||
P.Trace("IfStat");
|
||||
|
||||
x := new(AST.IfStat);
|
||||
x.pos = P.pos;
|
||||
var dummy AST.Stat;
|
||||
|
||||
x.init, x.cond, dummy = P.ParseStatHeader(Scanner.IF);
|
||||
|
||||
x.then = P.ParseBlock();
|
||||
stat := new(AST.IfStat);
|
||||
stat.pos = P.pos;
|
||||
stat.ctrl = P.ParseControlClause(Scanner.IF);
|
||||
stat.then = P.ParseBlock();
|
||||
if P.tok == Scanner.ELSE {
|
||||
P.Next();
|
||||
b := new(AST.Block);
|
||||
b.stats = AST.NewList();
|
||||
if P.tok == Scanner.IF {
|
||||
b.stats.Add(P.ParseIfStat());
|
||||
stat.else_ = P.ParseIfStat();
|
||||
} else {
|
||||
// TODO should be P.ParseBlock()
|
||||
b.stats.Add(P.ParseStatement());
|
||||
// TODO: Should be P.ParseBlock().
|
||||
stat.else_ = P.ParseStatement();
|
||||
}
|
||||
x.else_ = b;
|
||||
stat.has_else = true;
|
||||
}
|
||||
|
||||
P.Ecart();
|
||||
return x;
|
||||
return stat;
|
||||
}
|
||||
|
||||
|
||||
@ -1014,7 +1006,7 @@ func (P *Parser) ParseForStat() *AST.ForStat {
|
||||
stat := new(AST.ForStat);
|
||||
stat.pos = P.pos;
|
||||
|
||||
P.ParseStatHeader(Scanner.FOR);
|
||||
stat.ctrl = P.ParseControlClause(Scanner.FOR);
|
||||
stat.body = P.ParseBlock();
|
||||
|
||||
P.Ecart();
|
||||
@ -1065,11 +1057,9 @@ func (P *Parser) ParseSwitchStat() *AST.SwitchStat {
|
||||
|
||||
stat := new(AST.SwitchStat);
|
||||
stat.pos = P.pos;
|
||||
stat.init = AST.NIL;
|
||||
stat.ctrl = P.ParseControlClause(Scanner.SWITCH);
|
||||
stat.cases = AST.NewList();
|
||||
|
||||
P.ParseStatHeader(Scanner.SWITCH);
|
||||
|
||||
P.Expect(Scanner.LBRACE);
|
||||
for P.tok == Scanner.CASE || P.tok == Scanner.DEFAULT {
|
||||
stat.cases.Add(P.ParseCaseClause());
|
||||
@ -1169,7 +1159,7 @@ func (P *Parser) TryStatement() (stat_ AST.Stat, ok_ bool) {
|
||||
case Scanner.RETURN:
|
||||
stat = P.ParseReturnStat();
|
||||
case Scanner.BREAK, Scanner.CONTINUE, Scanner.GOTO:
|
||||
P.ParseControlFlowStat(P.tok);
|
||||
stat = P.ParseControlFlowStat(P.tok);
|
||||
case Scanner.LBRACE:
|
||||
stat = P.ParseBlock();
|
||||
case Scanner.IF:
|
||||
@ -1219,7 +1209,7 @@ func (P *Parser) ParseImportSpec() {
|
||||
}
|
||||
|
||||
|
||||
func (P *Parser) ParseConstSpec(exported bool) AST.Decl {
|
||||
func (P *Parser) ParseConstSpec(exported bool) *AST.ConstDecl {
|
||||
P.Trace("ConstSpec");
|
||||
|
||||
decl := new(AST.ConstDecl);
|
||||
@ -1237,7 +1227,7 @@ func (P *Parser) ParseConstSpec(exported bool) AST.Decl {
|
||||
}
|
||||
|
||||
|
||||
func (P *Parser) ParseTypeSpec(exported bool) AST.Decl {
|
||||
func (P *Parser) ParseTypeSpec(exported bool) *AST.TypeDecl {
|
||||
P.Trace("TypeSpec");
|
||||
|
||||
decl := new(AST.TypeDecl);
|
||||
@ -1249,7 +1239,7 @@ func (P *Parser) ParseTypeSpec(exported bool) AST.Decl {
|
||||
}
|
||||
|
||||
|
||||
func (P *Parser) ParseVarSpec(exported bool) AST.Decl {
|
||||
func (P *Parser) ParseVarSpec(exported bool) *AST.VarDecl {
|
||||
P.Trace("VarSpec");
|
||||
|
||||
decl := new(AST.VarDecl);
|
||||
@ -1270,7 +1260,7 @@ func (P *Parser) ParseVarSpec(exported bool) AST.Decl {
|
||||
}
|
||||
|
||||
|
||||
// TODO With method variables, we wouldn't need this dispatch function.
|
||||
// TODO Replace this by using function pointers derived from methods.
|
||||
func (P *Parser) ParseSpec(exported bool, keyword int) AST.Decl {
|
||||
var decl AST.Decl = AST.NIL;
|
||||
switch keyword {
|
||||
@ -1333,13 +1323,14 @@ func (P *Parser) ParseFuncDecl(exported bool) *AST.FuncDecl {
|
||||
|
||||
var recv *AST.VarDeclList;
|
||||
if P.tok == Scanner.LPAREN {
|
||||
recv_pos := P.pos;
|
||||
recv := P.ParseParameters().at(0);
|
||||
/*
|
||||
if n != 1 {
|
||||
P.Error(recv_pos, "must have exactly one receiver");
|
||||
pos := P.pos;
|
||||
tmp := P.ParseParameters();
|
||||
if tmp.len() > 0 {
|
||||
recv = tmp.at(0);
|
||||
}
|
||||
if recv.idents.len() != 1 {
|
||||
P.Error(pos, "must have exactly one receiver");
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
fun.ident = P.ParseIdent();
|
||||
|
@ -8,7 +8,8 @@ import Scanner "scanner"
|
||||
import AST "ast"
|
||||
|
||||
|
||||
type Printer /* implements AST.Visitor */ struct {
|
||||
// Printer implements AST.Visitor
|
||||
type Printer struct {
|
||||
indent int;
|
||||
}
|
||||
|
||||
@ -49,7 +50,7 @@ func (P *Printer) PrintList(p *AST.List) {
|
||||
// Basics
|
||||
|
||||
func (P *Printer) DoNil(x *AST.Nil) {
|
||||
P.String("?");
|
||||
P.String("<NIL>");
|
||||
}
|
||||
|
||||
|
||||
@ -162,7 +163,7 @@ func (P *Printer) DoFuncDecl(x *AST.FuncDecl) {
|
||||
P.String("func ");
|
||||
if x.typ.recv != nil {
|
||||
P.String("(");
|
||||
P.PrintList(x.typ.recv.idents);
|
||||
P.DoVarDeclList(x.typ.recv);
|
||||
P.String(") ");
|
||||
}
|
||||
P.DoIdent(x.ident);
|
||||
@ -193,6 +194,7 @@ func (P *Printer) DoDeclaration(x *AST.Declaration) {
|
||||
if i > 0 {
|
||||
P.NewLine(0);
|
||||
}
|
||||
//print("*** i = ", i, "\n");
|
||||
P.Print(x.decls.at(i));
|
||||
}
|
||||
P.NewLine(-1);
|
||||
@ -291,21 +293,38 @@ func (P *Printer) DoAssignment(x *AST.Assignment) {
|
||||
}
|
||||
|
||||
|
||||
func (P *Printer) PrintControlClause(x *AST.ControlClause) {
|
||||
if x.has_init {
|
||||
P.String(" ");
|
||||
P.Print(x.init);
|
||||
P.String(";");
|
||||
}
|
||||
if x.has_expr {
|
||||
P.String(" ");
|
||||
P.Print(x.expr);
|
||||
}
|
||||
if x.has_post {
|
||||
P.String("; ");
|
||||
P.Print(x.post);
|
||||
}
|
||||
P.String(" ");
|
||||
}
|
||||
|
||||
|
||||
func (P *Printer) DoIfStat(x *AST.IfStat) {
|
||||
P.String("if ");
|
||||
P.Print(x.init);
|
||||
P.String("; ");
|
||||
P.Print(x.cond);
|
||||
P.String("if");
|
||||
P.PrintControlClause(x.ctrl);
|
||||
P.DoBlock(x.then);
|
||||
if x.else_ != nil {
|
||||
if x.has_else {
|
||||
P.String(" else ");
|
||||
P.DoBlock(x.else_);
|
||||
P.Print(x.else_);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
func (P *Printer) DoForStat(x *AST.ForStat) {
|
||||
P.String("for ");
|
||||
P.String("for");
|
||||
P.PrintControlClause(x.ctrl);
|
||||
P.DoBlock(x.body);
|
||||
}
|
||||
|
||||
@ -360,7 +379,8 @@ func (P *Printer) DoCaseClause(x *AST.CaseClause) {
|
||||
|
||||
|
||||
func (P *Printer) DoSwitchStat(x *AST.SwitchStat) {
|
||||
P.String("switch ");
|
||||
P.String("switch");
|
||||
P.PrintControlClause(x.ctrl);
|
||||
P.String("{");
|
||||
P.NewLine(0);
|
||||
for i := 0; i < x.cases.len(); i++ {
|
||||
@ -385,6 +405,16 @@ func (P *Printer) DoIncDecStat(x *AST.IncDecStat) {
|
||||
}
|
||||
|
||||
|
||||
func (P *Printer) DoControlFlowStat(x *AST.ControlFlowStat) {
|
||||
P.String(Scanner.TokenName(x.tok));
|
||||
if x.label != nil {
|
||||
P.String(" ");
|
||||
P.Print(x.label);
|
||||
}
|
||||
P.String(";");
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Program
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user