Commit c5119538 authored by Robert Griesemer's avatar Robert Griesemer

snapshot: more pretty printer stuff

R=r
OCL=15863
CL=15863
parent 99ec0313
...@@ -49,6 +49,7 @@ export type Visitor interface { ...@@ -49,6 +49,7 @@ export type Visitor interface {
DoSwitchStat(x *SwitchStat); DoSwitchStat(x *SwitchStat);
DoReturnStat(x *ReturnStat); DoReturnStat(x *ReturnStat);
DoIncDecStat(x *IncDecStat); DoIncDecStat(x *IncDecStat);
DoControlFlowStat(x *ControlFlowStat);
// Program // Program
DoProgram(x *Program); DoProgram(x *Program);
...@@ -65,6 +66,9 @@ export type Node interface { ...@@ -65,6 +66,9 @@ export type Node interface {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Lists // 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 { export type List struct {
a *[] Node a *[] Node
...@@ -335,19 +339,26 @@ export type Assignment struct { ...@@ -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 { export type IfStat struct {
pos int; // position of "if" pos int; // position of "if"
init Stat; ctrl *ControlClause;
cond Expr; then *Block;
then, else_ *Block; else_ Stat;
has_else bool;
} }
export type ForStat struct { export type ForStat struct {
pos int; // position of "for" pos int; // position of "for"
init Stat; ctrl *ControlClause;
cond Expr;
post Stat;
body *Block; body *Block;
} }
...@@ -362,15 +373,14 @@ export type CaseClause struct { ...@@ -362,15 +373,14 @@ export type CaseClause struct {
export type SwitchStat struct { export type SwitchStat struct {
pos int; // position of "switch" pos int; // position of "switch"
init Stat; ctrl *ControlClause;
tag Expr;
cases *List; // list of *CaseClause cases *List; // list of *CaseClause
} }
export type ReturnStat struct { export type ReturnStat struct {
pos int; // position of "return" pos int; // position of "return"
res *List; res *List; // list of Expr
} }
...@@ -381,16 +391,23 @@ export type IncDecStat struct { ...@@ -381,16 +391,23 @@ export type IncDecStat struct {
} }
func (x *Block) Visit(v Visitor) { v.DoBlock(x); } export type ControlFlowStat struct {
func (x *ExprStat) Visit(v Visitor) { v.DoExprStat(x); } pos int; // position of token
func (x *Assignment) Visit(v Visitor) { v.DoAssignment(x); } tok int;
func (x *IfStat) Visit(v Visitor) { v.DoIfStat(x); } label *Ident; // nil, if no label
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 *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 // Program
......
...@@ -404,7 +404,7 @@ func (P *Parser) ParseMapType() *AST.MapType { ...@@ -404,7 +404,7 @@ func (P *Parser) ParseMapType() *AST.MapType {
func (P *Parser) ParseStructType() *AST.StructType { func (P *Parser) ParseStructType() *AST.StructType {
P.Trace("StructType"); P.Trace("StructType");
typ := new(AST.StructType); typ := new(AST.StructType);
typ.pos = P.pos; typ.pos = P.pos;
typ.fields = AST.NewList(); typ.fields = AST.NewList();
...@@ -912,99 +912,91 @@ func (P *Parser) ParseGoStat() { ...@@ -912,99 +912,91 @@ func (P *Parser) ParseGoStat() {
func (P *Parser) ParseReturnStat() *AST.ReturnStat { func (P *Parser) ParseReturnStat() *AST.ReturnStat {
P.Trace("ReturnStat"); P.Trace("ReturnStat");
ret := new(AST.ReturnStat); stat := new(AST.ReturnStat);
ret.pos = P.pos; stat.pos = P.pos;
P.Expect(Scanner.RETURN); P.Expect(Scanner.RETURN);
if P.tok != Scanner.SEMICOLON && P.tok != Scanner.RBRACE { if P.tok != Scanner.SEMICOLON && P.tok != Scanner.RBRACE {
ret.res = P.ParseExpressionList(); stat.res = P.ParseExpressionList();
} }
P.Ecart(); P.Ecart();
return ret; return stat;
} }
func (P *Parser) ParseControlFlowStat(tok int) { func (P *Parser) ParseControlFlowStat(tok int) *AST.ControlFlowStat {
P.Trace("ControlFlowStat"); P.Trace("ControlFlowStat");
stat := new(AST.ControlFlowStat);
stat.pos, stat.tok = P.pos, P.tok;
P.Expect(tok); P.Expect(tok);
if P.tok == Scanner.IDENT { if P.tok == Scanner.IDENT {
P.ParseIdent(); stat.label = P.ParseIdent();
} }
P.Ecart(); 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"); P.Trace("StatHeader");
var ( ctrl := new(AST.ControlClause);
init AST.Stat = AST.NIL; ctrl.init, ctrl.expr, ctrl.post = AST.NIL, AST.NIL, AST.NIL;
expr AST.Expr = AST.NIL;
post AST.Stat = AST.NIL;
)
has_init, has_expr, has_post := false, false, false;
P.Expect(keyword); P.Expect(keyword);
if P.tok != Scanner.LBRACE { if P.tok != Scanner.LBRACE {
if P.tok != Scanner.SEMICOLON { if P.tok != Scanner.SEMICOLON {
init = P.ParseSimpleStat(); ctrl.init = P.ParseSimpleStat();
has_init = true; ctrl.has_init = true;
} }
if P.tok == Scanner.SEMICOLON { if P.tok == Scanner.SEMICOLON {
P.Next(); P.Next();
if P.tok != Scanner.SEMICOLON && P.tok != Scanner.LBRACE {
ctrl.expr = P.ParseExpression();
ctrl.has_expr = true;
}
if keyword == Scanner.FOR { if keyword == Scanner.FOR {
if P.tok != Scanner.SEMICOLON {
expr = P.ParseExpression();
has_expr = true;
}
P.Expect(Scanner.SEMICOLON); P.Expect(Scanner.SEMICOLON);
if P.tok != Scanner.LBRACE { if P.tok != Scanner.LBRACE {
post = P.ParseSimpleStat(); ctrl.post = P.ParseSimpleStat();
has_post = true; ctrl.has_post = true;
}
} else {
if P.tok != Scanner.LBRACE {
expr = P.ParseExpression();
has_expr = true;
} }
} }
} else {
ctrl.expr, ctrl.has_expr = ctrl.init, ctrl.has_init;
ctrl.init, ctrl.has_init = AST.NIL, false;
} }
} }
P.Ecart(); P.Ecart();
return init, expr, post; return ctrl;
} }
func (P *Parser) ParseIfStat() *AST.IfStat { func (P *Parser) ParseIfStat() *AST.IfStat {
P.Trace("IfStat"); P.Trace("IfStat");
x := new(AST.IfStat); stat := new(AST.IfStat);
x.pos = P.pos; stat.pos = P.pos;
var dummy AST.Stat; stat.ctrl = P.ParseControlClause(Scanner.IF);
stat.then = P.ParseBlock();
x.init, x.cond, dummy = P.ParseStatHeader(Scanner.IF);
x.then = P.ParseBlock();
if P.tok == Scanner.ELSE { if P.tok == Scanner.ELSE {
P.Next(); P.Next();
b := new(AST.Block);
b.stats = AST.NewList();
if P.tok == Scanner.IF { if P.tok == Scanner.IF {
b.stats.Add(P.ParseIfStat()); stat.else_ = P.ParseIfStat();
} else { } else {
// TODO should be P.ParseBlock() // TODO: Should be P.ParseBlock().
b.stats.Add(P.ParseStatement()); stat.else_ = P.ParseStatement();
} }
x.else_ = b; stat.has_else = true;
} }
P.Ecart(); P.Ecart();
return x; return stat;
} }
...@@ -1014,7 +1006,7 @@ func (P *Parser) ParseForStat() *AST.ForStat { ...@@ -1014,7 +1006,7 @@ func (P *Parser) ParseForStat() *AST.ForStat {
stat := new(AST.ForStat); stat := new(AST.ForStat);
stat.pos = P.pos; stat.pos = P.pos;
P.ParseStatHeader(Scanner.FOR); stat.ctrl = P.ParseControlClause(Scanner.FOR);
stat.body = P.ParseBlock(); stat.body = P.ParseBlock();
P.Ecart(); P.Ecart();
...@@ -1065,10 +1057,8 @@ func (P *Parser) ParseSwitchStat() *AST.SwitchStat { ...@@ -1065,10 +1057,8 @@ func (P *Parser) ParseSwitchStat() *AST.SwitchStat {
stat := new(AST.SwitchStat); stat := new(AST.SwitchStat);
stat.pos = P.pos; stat.pos = P.pos;
stat.init = AST.NIL; stat.ctrl = P.ParseControlClause(Scanner.SWITCH);
stat.cases = AST.NewList(); stat.cases = AST.NewList();
P.ParseStatHeader(Scanner.SWITCH);
P.Expect(Scanner.LBRACE); P.Expect(Scanner.LBRACE);
for P.tok == Scanner.CASE || P.tok == Scanner.DEFAULT { for P.tok == Scanner.CASE || P.tok == Scanner.DEFAULT {
...@@ -1169,7 +1159,7 @@ func (P *Parser) TryStatement() (stat_ AST.Stat, ok_ bool) { ...@@ -1169,7 +1159,7 @@ func (P *Parser) TryStatement() (stat_ AST.Stat, ok_ bool) {
case Scanner.RETURN: case Scanner.RETURN:
stat = P.ParseReturnStat(); stat = P.ParseReturnStat();
case Scanner.BREAK, Scanner.CONTINUE, Scanner.GOTO: case Scanner.BREAK, Scanner.CONTINUE, Scanner.GOTO:
P.ParseControlFlowStat(P.tok); stat = P.ParseControlFlowStat(P.tok);
case Scanner.LBRACE: case Scanner.LBRACE:
stat = P.ParseBlock(); stat = P.ParseBlock();
case Scanner.IF: case Scanner.IF:
...@@ -1219,7 +1209,7 @@ func (P *Parser) ParseImportSpec() { ...@@ -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"); P.Trace("ConstSpec");
decl := new(AST.ConstDecl); decl := new(AST.ConstDecl);
...@@ -1237,7 +1227,7 @@ func (P *Parser) ParseConstSpec(exported bool) AST.Decl { ...@@ -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"); P.Trace("TypeSpec");
decl := new(AST.TypeDecl); decl := new(AST.TypeDecl);
...@@ -1249,7 +1239,7 @@ func (P *Parser) ParseTypeSpec(exported bool) AST.Decl { ...@@ -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"); P.Trace("VarSpec");
decl := new(AST.VarDecl); decl := new(AST.VarDecl);
...@@ -1270,7 +1260,7 @@ func (P *Parser) ParseVarSpec(exported bool) AST.Decl { ...@@ -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 { func (P *Parser) ParseSpec(exported bool, keyword int) AST.Decl {
var decl AST.Decl = AST.NIL; var decl AST.Decl = AST.NIL;
switch keyword { switch keyword {
...@@ -1333,13 +1323,14 @@ func (P *Parser) ParseFuncDecl(exported bool) *AST.FuncDecl { ...@@ -1333,13 +1323,14 @@ func (P *Parser) ParseFuncDecl(exported bool) *AST.FuncDecl {
var recv *AST.VarDeclList; var recv *AST.VarDeclList;
if P.tok == Scanner.LPAREN { if P.tok == Scanner.LPAREN {
recv_pos := P.pos; pos := P.pos;
recv := P.ParseParameters().at(0); tmp := P.ParseParameters();
/* if tmp.len() > 0 {
if n != 1 { recv = tmp.at(0);
P.Error(recv_pos, "must have exactly one receiver"); }
if recv.idents.len() != 1 {
P.Error(pos, "must have exactly one receiver");
} }
*/
} }
fun.ident = P.ParseIdent(); fun.ident = P.ParseIdent();
......
...@@ -8,7 +8,8 @@ import Scanner "scanner" ...@@ -8,7 +8,8 @@ import Scanner "scanner"
import AST "ast" import AST "ast"
type Printer /* implements AST.Visitor */ struct { // Printer implements AST.Visitor
type Printer struct {
indent int; indent int;
} }
...@@ -49,7 +50,7 @@ func (P *Printer) PrintList(p *AST.List) { ...@@ -49,7 +50,7 @@ func (P *Printer) PrintList(p *AST.List) {
// Basics // Basics
func (P *Printer) DoNil(x *AST.Nil) { func (P *Printer) DoNil(x *AST.Nil) {
P.String("?"); P.String("<NIL>");
} }
...@@ -162,7 +163,7 @@ func (P *Printer) DoFuncDecl(x *AST.FuncDecl) { ...@@ -162,7 +163,7 @@ func (P *Printer) DoFuncDecl(x *AST.FuncDecl) {
P.String("func "); P.String("func ");
if x.typ.recv != nil { if x.typ.recv != nil {
P.String("("); P.String("(");
P.PrintList(x.typ.recv.idents); P.DoVarDeclList(x.typ.recv);
P.String(") "); P.String(") ");
} }
P.DoIdent(x.ident); P.DoIdent(x.ident);
...@@ -193,6 +194,7 @@ func (P *Printer) DoDeclaration(x *AST.Declaration) { ...@@ -193,6 +194,7 @@ func (P *Printer) DoDeclaration(x *AST.Declaration) {
if i > 0 { if i > 0 {
P.NewLine(0); P.NewLine(0);
} }
//print("*** i = ", i, "\n");
P.Print(x.decls.at(i)); P.Print(x.decls.at(i));
} }
P.NewLine(-1); P.NewLine(-1);
...@@ -291,21 +293,38 @@ func (P *Printer) DoAssignment(x *AST.Assignment) { ...@@ -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) { func (P *Printer) DoIfStat(x *AST.IfStat) {
P.String("if "); P.String("if");
P.Print(x.init); P.PrintControlClause(x.ctrl);
P.String("; ");
P.Print(x.cond);
P.DoBlock(x.then); P.DoBlock(x.then);
if x.else_ != nil { if x.has_else {
P.String(" else "); P.String(" else ");
P.DoBlock(x.else_); P.Print(x.else_);
} }
} }
func (P *Printer) DoForStat(x *AST.ForStat) { func (P *Printer) DoForStat(x *AST.ForStat) {
P.String("for "); P.String("for");
P.PrintControlClause(x.ctrl);
P.DoBlock(x.body); P.DoBlock(x.body);
} }
...@@ -360,7 +379,8 @@ func (P *Printer) DoCaseClause(x *AST.CaseClause) { ...@@ -360,7 +379,8 @@ func (P *Printer) DoCaseClause(x *AST.CaseClause) {
func (P *Printer) DoSwitchStat(x *AST.SwitchStat) { func (P *Printer) DoSwitchStat(x *AST.SwitchStat) {
P.String("switch "); P.String("switch");
P.PrintControlClause(x.ctrl);
P.String("{"); P.String("{");
P.NewLine(0); P.NewLine(0);
for i := 0; i < x.cases.len(); i++ { for i := 0; i < x.cases.len(); i++ {
...@@ -385,6 +405,16 @@ func (P *Printer) DoIncDecStat(x *AST.IncDecStat) { ...@@ -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 // Program
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment