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 {
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,16 +391,23 @@ 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
......
......@@ -404,7 +404,7 @@ func (P *Parser) ParseMapType() *AST.MapType {
func (P *Parser) ParseStructType() *AST.StructType {
P.Trace("StructType");
typ := new(AST.StructType);
typ.pos = P.pos;
typ.fields = AST.NewList();
......@@ -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,10 +1057,8 @@ 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 {
......@@ -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
......
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