1
0
mirror of https://github.com/golang/go synced 2024-11-12 10:00:25 -07:00

- snapshot of pretty printer work

- accepts all Go code (use -s flag)
- complete rewrite of AST, AST building, and printing
  (as a result much more compact)
- printing severely screwed up at the moment, but should be
  fully working in 1 more day

R=r
DELTA=2118  (514 added, 980 deleted, 624 changed)
OCL=17161
CL=17161
This commit is contained in:
Robert Griesemer 2008-10-14 18:14:01 -07:00
parent 0b05e91f8b
commit 7c3a2c47b0
6 changed files with 917 additions and 1383 deletions

View File

@ -54,7 +54,11 @@ clean:
pretty.6: parser.6 printer.6 platform.6 scanner.6
parser.6: ast.6 scanner.6 utils.6 printer.6
printer.6: node.6 scanner.6
parser.6: scanner.6 utils.6 printer.6 node.6
node.6: scanner.6
scanner.6: utils.6 platform.6

View File

@ -1,525 +0,0 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package AST
// ----------------------------------------------------------------------------
// Visitor
type (
Nil struct;
Ident struct;
ArrayType struct;
StructType struct;
MapType struct;
ChannelType struct;
PointerType struct;
InterfaceType struct;
FunctionType struct;
VarDeclList struct;
ImportDecl struct;
ConstDecl struct;
TypeDecl struct;
VarDecl struct;
Declaration struct;
FuncDecl struct;
MethodDecl struct;
Selector struct;
Index struct;
Call struct;
Pair struct;
Binary struct;
Unary struct;
Literal struct;
CompositeLit struct;
FunctionLit struct;
Label struct;
Block struct;
ExprStat struct;
Assignment struct;
ControlClause struct;
IfStat struct;
ForStat struct;
CaseClause struct;
SwitchStat struct;
ReturnStat struct;
IncDecStat struct;
ControlFlowStat struct;
GoStat struct;
Program struct;
)
export type Visitor interface {
// Basics
DoNil(x *Nil);
DoIdent(x *Ident);
// Types
DoFunctionType(x *FunctionType);
DoArrayType(x *ArrayType);
DoStructType(x *StructType);
DoMapType(x *MapType);
DoChannelType(x *ChannelType);
DoInterfaceType(x *InterfaceType);
DoPointerType(x *PointerType);
// Declarations
DoImportDecl(x *ImportDecl);
DoConstDecl(x *ConstDecl);
DoTypeDecl(x *TypeDecl);
DoVarDecl(x *VarDecl);
DoVarDeclList(x *VarDeclList);
DoFuncDecl(x *FuncDecl);
DoMethodDecl(x *MethodDecl);
DoDeclaration(x *Declaration);
// Expressions
DoBinary(x *Binary);
DoUnary(x *Unary);
DoLiteral(x *Literal);
DoPair(x *Pair);
DoIndex(x *Index);
DoCall(x *Call);
DoSelector(x *Selector);
DoCompositeLit(x *CompositeLit);
DoFunctionLit(x *FunctionLit);
// Statements
DoLabel(x *Label);
DoBlock(x *Block);
DoExprStat(x *ExprStat);
DoAssignment(x *Assignment);
DoIfStat(x *IfStat);
DoForStat(x *ForStat);
DoCaseClause(x *CaseClause);
DoSwitchStat(x *SwitchStat);
DoReturnStat(x *ReturnStat);
DoIncDecStat(x *IncDecStat);
DoControlFlowStat(x *ControlFlowStat);
DoGoStat(x *GoStat);
// Program
DoProgram(x *Program);
}
// ----------------------------------------------------------------------------
// An AST Node
export type Node interface {
Visit(x Visitor);
}
// ----------------------------------------------------------------------------
// 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;
}
func (p *List) len() int {
if p == nil { return 0; }
return len(p.a);
}
func (p *List) at(i int) Node {
return p.a[i];
}
func (p *List) Add (x Node) {
a := p.a;
n := len(a);
if n == cap(a) {
b := new([] Node, 2*n);
for i := 0; i < n; i++ {
b[i] = a[i];
}
a = b;
}
a = a[0 : n + 1];
a[n] = x;
p.a = a;
}
export func NewList() *List {
p := new(List);
p.a = new([] Node, 10) [0 : 0];
return p;
}
// ----------------------------------------------------------------------------
// Basics
export type Nil struct {
// The Node "nil" value
}
export var NIL *Nil = new(Nil);
export type Ident struct {
pos int;
val string;
}
func (x *Nil) Visit(v Visitor) { v.DoNil(x); }
func (x *Ident) Visit(v Visitor) { v.DoIdent(x); }
// ----------------------------------------------------------------------------
// Types
export type Type interface {
Visit(x Visitor);
}
export type Expr interface {
Visit(x Visitor);
}
export type ArrayType struct {
pos int; // position of "["
len_ Expr;
elt Type;
}
export type StructType struct {
pos int; // position of "struct"
fields *List; // list of *VarDeclList
}
export type MapType struct {
pos int; // position of "map"
key, val Type;
}
export const /* chan mode */ (
FULL = iota;
RECV;
SEND;
)
export type ChannelType struct {
pos int; // position of "chan" or "<-" (if before "chan")
elt Type;
mode int;
}
export type PointerType struct {
pos int; // position of "*"
base Type;
}
export type InterfaceType struct {
pos int; // position of "interface"
methods *List; // list of *MethodDecl
}
export type FunctionType struct {
pos int; // position of "("
recv *VarDeclList;
params *List; // list of *VarDeclList
result *List; // list of *VarDeclList
}
func (x *FunctionType) Visit(v Visitor) { v.DoFunctionType(x); }
func (x *ArrayType) Visit(v Visitor) { v.DoArrayType(x); }
func (x *StructType) Visit(v Visitor) { v.DoStructType(x); }
func (x *MapType) Visit(v Visitor) { v.DoMapType(x); }
func (x *ChannelType) Visit(v Visitor) { v.DoChannelType(x); }
func (x *PointerType) Visit(v Visitor) { v.DoPointerType(x); }
func (x *InterfaceType) Visit(v Visitor) { v.DoInterfaceType(x); }
// ----------------------------------------------------------------------------
// Declarations
export type Decl interface {
Visit(x Visitor);
}
export type VarDeclList struct {
idents *List; // possibly nil
typ Type;
}
export type ImportDecl struct {
ident *Ident;
file string;
}
export type ConstDecl struct {
ident *Ident;
typ Type;
val Expr;
}
export type TypeDecl struct {
ident *Ident;
typ Type;
}
export type VarDecl struct {
idents *List;
typ Type;
vals *List;
}
export type Declaration struct {
pos int; // position of token
tok int;
decls *List;
}
export type FuncDecl struct {
pos int; // position of "func"
ident *Ident;
typ *FunctionType;
body *Block;
}
export type MethodDecl struct {
ident *Ident;
typ *FunctionType;
}
func (x *VarDeclList) Visit(v Visitor) { v.DoVarDeclList(x); }
func (x *ImportDecl) Visit(v Visitor) { v.DoImportDecl(x); }
func (x *ConstDecl) Visit(v Visitor) { v.DoConstDecl(x); }
func (x *TypeDecl) Visit(v Visitor) { v.DoTypeDecl(x); }
func (x *VarDecl) Visit(v Visitor) { v.DoVarDecl(x); }
func (x *FuncDecl) Visit(v Visitor) { v.DoFuncDecl(x); }
func (x *MethodDecl) Visit(v Visitor) { v.DoMethodDecl(x); }
func (x *Declaration) Visit(v Visitor) { v.DoDeclaration(x); }
// ----------------------------------------------------------------------------
// Expressions
export type Selector struct {
pos int; // position of "."
x Expr;
field string;
}
export type Index struct {
pos int; // position of "["
x Expr;
index Expr;
}
export type Call struct {
pos int; // position of "("
fun Expr;
args *List;
}
export type Pair struct {
pos int; // position of ":"
x, y Expr;
}
export type Binary struct {
pos int; // position of operator tok
tok int;
x, y Expr;
}
export type Unary struct {
pos int; // position of operator tok
tok int;
x Expr;
}
export type Literal struct {
pos int; // position of literal
tok int;
val string;
}
export type CompositeLit struct {
pos int; // position of "{"
typ Type;
vals *List // list of Expr
}
export type FunctionLit struct {
pos int; // position of "func"
typ *FunctionType;
body *Block;
}
func (x *Binary) Visit(v Visitor) { v.DoBinary(x); }
func (x *Unary) Visit(v Visitor) { v.DoUnary(x); }
func (x *Literal) Visit(v Visitor) { v.DoLiteral(x); }
func (x *Pair) Visit(v Visitor) { v.DoPair(x); }
func (x *Index) Visit(v Visitor) { v.DoIndex(x); }
func (x *Call) Visit(v Visitor) { v.DoCall(x); }
func (x *Selector) Visit(v Visitor) { v.DoSelector(x); }
func (x *CompositeLit) Visit(v Visitor) { v.DoCompositeLit(x); }
func (x *FunctionLit) Visit(v Visitor) { v.DoFunctionLit(x); }
// ----------------------------------------------------------------------------
// Statements
export type Stat interface {
Visit(x Visitor);
}
export type Label struct {
pos int; // position of ":"
ident Expr; // should be ident
}
export type Block struct {
pos int; // position of "{"
stats *List;
}
export type ExprStat struct {
expr Expr;
}
export type Assignment struct {
pos int; // position of assignment token
tok int;
lhs, rhs *List;
}
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"
ctrl *ControlClause;
then *Block;
else_ Stat;
has_else bool;
}
export type ForStat struct {
pos int; // position of "for"
ctrl *ControlClause;
body *Block;
}
export type CaseClause struct {
pos int; // position of "case" or "default"
exprs *List; // nil if default case
stats *List; // list of Stat
falls bool;
}
export type SwitchStat struct {
pos int; // position of "switch"
ctrl *ControlClause;
cases *List; // list of *CaseClause
}
export type ReturnStat struct {
pos int; // position of "return"
res *List; // list of Expr
}
export type IncDecStat struct {
pos int; // position of token
tok int;
expr Expr;
}
export type ControlFlowStat struct {
pos int; // position of token
tok int;
label *Ident; // nil, if no label
}
export type GoStat struct {
pos int; // position of "go"
expr Expr;
}
func (x *Block) Visit(v Visitor) { v.DoBlock(x); }
func (x *Label) Visit(v Visitor) { v.DoLabel(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); }
func (x *GoStat) Visit(v Visitor) { v.DoGoStat(x); }
// ----------------------------------------------------------------------------
// Program
export type Program struct {
pos int;
ident *Ident;
decls *List;
}
func (x *Program) Visit(v Visitor) { v.DoProgram(x); }

248
usr/gri/pretty/node.go Normal file
View File

@ -0,0 +1,248 @@
// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package Node
import Scanner "scanner"
type Node interface {}
type (
Type struct;
Expr struct;
Stat struct;
Decl struct;
)
// ----------------------------------------------------------------------------
// 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;
}
func (p *List) len() int {
if p == nil { return 0; }
return len(p.a);
}
func (p *List) at(i int) Node {
return p.a[i];
}
func (p *List) Add (x Node) {
a := p.a;
n := len(a);
if n == cap(a) {
b := new([] Node, 2*n);
for i := 0; i < n; i++ {
b[i] = a[i];
}
a = b;
}
a = a[0 : n + 1];
a[n] = x;
p.a = a;
}
/*
func (p *List) Print() {
print("(");
for i, n := 0, p.len(); i < n; i++ {
if i > 0 {
print(", ");
}
p.at(i).Print();
}
print(")");
}
*/
export func NewList() *List {
p := new(List);
p.a = new([] Node, 10) [0 : 0];
return p;
}
// ----------------------------------------------------------------------------
// Types
export const /* channel mode */ (
FULL = iota;
SEND;
RECV;
)
export type Type struct {
pos, tok int;
expr *Expr; // type name, array length
mode int; // channel mode
key *Type; // map key
elt *Type; // array element, map or channel value, or pointer base type
list *List; // struct fields, interface methods, function parameters
}
export func NewType(pos, tok int) *Type {
t := new(Type);
t.pos, t.tok = pos, tok;
return t;
}
// ----------------------------------------------------------------------------
// Expressions
//
// Expression pairs are represented as binary expressions with operator ":"
// Expression lists are represented as binary expressions with operator ","
export type Val struct {
i int;
f float;
s string;
t *Type;
}
export type Expr struct {
pos, tok int;
x, y *Expr; // binary (x, y) and unary (y) expressions
ident string; // identifiers
val *Val; // literals
}
func (x *Expr) len() int {
if x == nil {
return 0;
}
n := 1;
for ; x.tok == Scanner.COMMA; x = x.y {
n++;
}
return n;
}
/*
func (x *Expr) Print() {
switch {
case x == nil:
print("nil");
case x.val != nil:
print(x.val.s);
default:
if x.x == nil {
print(Scanner.TokenName(x.tok));
} else {
x.x.Print();
print(" ");
print(Scanner.TokenName(x.tok));
print(" ");
}
x.y.Print();
}
}
*/
export func NewExpr(pos, tok int, x, y *Expr) *Expr {
e := new(Expr);
e.pos, e.tok, e.x, e.y = pos, tok, x, y;
return e;
}
export func NewIdent(pos int, ident string) *Expr {
e := new(Expr);
e.pos, e.tok, e.ident = pos, Scanner.IDENT, ident;
return e;
}
export func NewVal(pos, tok int, val *Val) *Expr {
e := new(Expr);
e.pos, e.tok, e.val = pos, tok, val;
return e;
}
// ----------------------------------------------------------------------------
// Statements
export type Stat struct {
pos, tok int;
init *Stat;
expr *Expr;
post *Stat;
block *List;
decl *Decl;
}
export func NewStat(pos, tok int) *Stat {
s := new(Stat);
s.pos, s.tok = pos, tok;
return s;
}
// ----------------------------------------------------------------------------
// Declarations
export type VarDeclList struct {
}
func (d *VarDeclList) Print() {
}
export type Decl struct {
pos, tok int;
exported bool;
ident *Expr; // nil for ()-style declarations
typ *Type;
val *Expr;
// list of *Decl for ()-style declarations
// list of *Stat for func declarations (or nil for forward decl)
list *List;
}
export func NewDecl(pos, tok int, exported bool) *Decl {
d := new(Decl);
d.pos, d.tok, d.exported = pos, tok, exported;
return d;
}
// ----------------------------------------------------------------------------
// Program
export type Program struct {
pos int; // tok is Scanner.PACKAGE
ident *Expr;
decls *List;
}
export func NewProgram(pos int) *Program {
p := new(Program);
p.pos = pos;
return p;
}

File diff suppressed because it is too large Load Diff

View File

@ -7,7 +7,6 @@ package main
import Flag "flag"
import Platform "platform"
import Scanner "scanner"
import AST "ast" // should not be needed
import Parser "parser"
import Printer "printer"
@ -66,7 +65,8 @@ func main() {
}
if !silent.BVal() {
Printer.Print(prog);
var P Printer.Printer;
(&P).Program(prog);
}
}
}

View File

@ -5,11 +5,10 @@
package Printer
import Scanner "scanner"
import AST "ast"
import Node "node"
// Printer implements AST.Visitor
type Printer struct {
export type Printer struct {
level int; // true scope level
indent int; // indentation level
semi bool; // pending ";"
@ -57,302 +56,154 @@ func (P *Printer) CloseScope(paren string) {
}
func (P *Printer) Print(x AST.Node) {
outer := P.prec;
P.prec = 0;
x.Visit(P);
P.prec = outer;
}
func (P *Printer) PrintList(p *AST.List) {
for i := 0; i < p.len(); i++ {
if i > 0 {
P.String(", ");
}
P.Print(p.at(i));
}
}
// ----------------------------------------------------------------------------
// Basics
func (P *Printer) DoNil(x *AST.Nil) {
P.String("<NIL>");
}
func (P *Printer) DoIdent(x *AST.Ident) {
P.String(x.val);
}
// ----------------------------------------------------------------------------
// Types
func (P *Printer) DoFunctionType(x *AST.FunctionType) {
P.String("(");
P.PrintList(x.params);
P.String(")");
if x.result != nil {
P.String(" (");
P.PrintList(x.result);
P.String(")");
}
}
func (P *Printer) Expr(x *Node.Expr)
func (P *Printer) Type(t *Node.Type) {
switch t.tok {
case Scanner.IDENT:
P.Expr(t.expr);
func (P *Printer) DoArrayType(x *AST.ArrayType) {
P.String("[");
P.Print(x.len_);
P.String("] ");
P.Print(x.elt);
}
func (P *Printer) DoStructType(x *AST.StructType) {
P.String("struct ");
P.OpenScope("{");
for i := 0; i < x.fields.len(); i++ {
P.Print(x.fields.at(i));
P.newl, P.semi = true, true;
}
P.CloseScope("}");
}
func (P *Printer) DoMapType(x *AST.MapType) {
P.String("[");
P.Print(x.key);
P.String("] ");
P.Print(x.val);
}
func (P *Printer) DoChannelType(x *AST.ChannelType) {
switch x.mode {
case AST.FULL: P.String("chan ");
case AST.RECV: P.String("<-chan ");
case AST.SEND: P.String("chan <- ");
}
P.Print(x.elt);
}
func (P *Printer) DoInterfaceType(x *AST.InterfaceType) {
P.String("interface ");
P.OpenScope("{");
for i := 0; i < x.methods.len(); i++ {
P.Print(x.methods.at(i));
P.newl, P.semi = true, true;
}
P.CloseScope("}");
}
func (P *Printer) DoPointerType(x *AST.PointerType) {
P.String("*");
P.Print(x.base);
}
// ----------------------------------------------------------------------------
// Declarations
func (P *Printer) DoBlock(x *AST.Block);
func (P *Printer) DoImportDecl(x *AST.ImportDecl) {
if x.ident != nil {
P.Print(x.ident);
P.String(" ");
}
P.String(x.file);
}
func (P *Printer) DoConstDecl(x *AST.ConstDecl) {
P.Print(x.ident);
P.String(" ");
P.Print(x.typ);
P.String(" = ");
P.Print(x.val);
P.semi = true;
}
func (P *Printer) DoTypeDecl(x *AST.TypeDecl) {
P.Print(x.ident);
P.String(" ");
P.Print(x.typ);
P.semi = true;
}
func (P *Printer) DoVarDecl(x *AST.VarDecl) {
P.PrintList(x.idents);
P.String(" ");
P.Print(x.typ);
if x.vals != nil {
P.String(" = ");
P.PrintList(x.vals);
}
P.semi = true;
}
func (P *Printer) DoVarDeclList(x *AST.VarDeclList) {
if x.idents != nil {
P.PrintList(x.idents);
P.String(" ");
}
P.Print(x.typ);
}
func (P *Printer) DoFuncDecl(x *AST.FuncDecl) {
P.String("func ");
if x.typ.recv != nil {
P.String("(");
P.DoVarDeclList(x.typ.recv);
P.String(") ");
}
P.DoIdent(x.ident);
P.DoFunctionType(x.typ);
if x.body != nil {
P.String(" ");
P.DoBlock(x.body);
} else {
P.String(" ;");
}
P.NewLine();
P.NewLine();
}
func (P *Printer) DoMethodDecl(x *AST.MethodDecl) {
P.DoIdent(x.ident);
P.DoFunctionType(x.typ);
}
func (P *Printer) DoDeclaration(x *AST.Declaration) {
P.String(Scanner.TokenName(x.tok));
P.String(" ");
switch x.decls.len() {
case 0:
P.String("()");
case 1:
P.Print(x.decls.at(0));
default:
P.OpenScope(" (");
for i := 0; i < x.decls.len(); i++ {
P.Print(x.decls.at(i));
P.newl, P.semi = true, true;
case Scanner.LBRACK:
P.String("[");
if t.expr != nil {
P.Expr(t.expr);
}
P.CloseScope(")");
P.String("] ");
P.Type(t.elt);
case Scanner.STRUCT:
P.String("struct");
if t.list != nil {
P.OpenScope(" {");
/*
for i := 0; i < x.fields.len(); i++ {
P.Print(x.fields.at(i));
P.newl, P.semi = true, true;
}
*/
P.CloseScope("}");
}
case Scanner.MAP:
P.String("[");
P.Type(t.key);
P.String("] ");
P.Type(t.elt);
case Scanner.CHAN:
switch t.mode {
case Node.FULL: P.String("chan ");
case Node.RECV: P.String("<-chan ");
case Node.SEND: P.String("chan <- ");
}
P.Type(t.elt);
case Scanner.INTERFACE:
P.String("interface");
if t.list != nil {
P.OpenScope(" {");
/*
for i := 0; i < x.methods.len(); i++ {
P.Print(x.methods.at(i));
P.newl, P.semi = true, true;
}
*/
P.CloseScope("}");
}
case Scanner.MUL:
P.String("*");
P.Type(t.elt);
case Scanner.LPAREN:
P.String("(");
//P.PrintList(x.params);
P.String(")");
/*
if x.result != nil {
P.String(" (");
P.PrintList(x.result);
P.String(")");
}
*/
default:
panic("UNREACHABLE");
}
if P.level == 0 {
P.NewLine();
}
P.newl = true;
}
// ----------------------------------------------------------------------------
// Expressions
func (P *Printer) DoBinary(x *AST.Binary) {
outer := P.prec;
P.prec = Scanner.Precedence(x.tok);
if P.prec < outer {
print("(");
}
P.Print(x.x);
P.String(" " + Scanner.TokenName(x.tok) + " ");
P.Print(x.y);
if P.prec < outer {
print(")");
func (P *Printer) Val(tok int, val *Node.Val) {
P.String(val.s); // for now
}
func (P *Printer) Expr(x *Node.Expr) {
if x == nil {
return; // empty expression list
}
P.prec = outer;
}
switch x.tok {
case Scanner.IDENT:
P.String(x.ident);
case Scanner.INT, Scanner.STRING, Scanner.FLOAT:
P.Val(x.tok, x.val);
func (P *Printer) DoUnary(x *AST.Unary) {
P.String(Scanner.TokenName(x.tok));
P.Print(x.x);
}
func (P *Printer) DoLiteral(x *AST.Literal) {
P.String(x.val);
}
func (P *Printer) DoPair(x *AST.Pair) {
P.Print(x.x);
P.String(" : ");
P.Print(x.y);
}
func (P *Printer) DoIndex(x *AST.Index) {
P.Print(x.x);
P.String("[");
P.Print(x.index);
P.String("]");
}
func (P *Printer) DoCall(x *AST.Call) {
P.Print(x.fun);
P.String("(");
P.PrintList(x.args);
P.String(")");
}
func (P *Printer) DoSelector(x *AST.Selector) {
P.Print(x.x);
P.String(".");
P.String(x.field);
}
func (P *Printer) DoCompositeLit(x *AST.CompositeLit) {
P.Print(x.typ);
P.String("{");
P.PrintList(x.vals);
P.String("}");
}
func (P *Printer) DoFunctionLit(x *AST.FunctionLit) {
P.String("func ");
P.Print(x.typ);
P.String(" ");
P.Print(x.body);
case Scanner.LPAREN:
// calls
P.Expr(x.x);
P.String("(");
P.Expr(x.y);
P.String(")");
case Scanner.LBRACK:
P.Expr(x.x);
P.String("[");
P.Expr(x.y);
P.String("]");
default:
if x.x == nil {
// unary expression
P.String(Scanner.TokenName(x.tok));
P.Expr(x.y);
} else {
// binary expression: print ()'s if necessary
// TODO: pass precedence as parameter instead
outer := P.prec;
P.prec = Scanner.Precedence(x.tok);
if P.prec < outer {
print("(");
}
P.Expr(x.x);
if x.tok != Scanner.PERIOD && x.tok != Scanner.COMMA {
P.String(" ");
}
P.String(Scanner.TokenName(x.tok));
if x.tok != Scanner.PERIOD {
P.String(" ");
}
P.Expr(x.y);
if P.prec < outer {
print(")");
}
P.prec = outer;
}
}
}
// ----------------------------------------------------------------------------
// Statements
func (P *Printer) DoBlock(x *AST.Block) {
P.OpenScope("{");
for i := 0; i < x.stats.len(); i++ {
P.Print(x.stats.at(i));
P.newl = true;
}
P.CloseScope("}");
}
/*
func (P *Printer) DoLabel(x *AST.Label) {
P.indent--;
P.newl = true;
@ -376,28 +227,6 @@ 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.semi = true;
P.String("");
}
if x.has_expr {
P.String(" ");
P.Print(x.expr);
P.semi = false;
}
if x.has_post {
P.semi = true;
P.String(" ");
P.Print(x.post);
P.semi = false;
}
P.String(" ");
}
func (P *Printer) DoIfStat(x *AST.IfStat) {
P.String("if");
P.PrintControlClause(x.ctrl);
@ -408,101 +237,208 @@ func (P *Printer) DoIfStat(x *AST.IfStat) {
P.Print(x.else_);
}
}
*/
func (P *Printer) DoForStat(x *AST.ForStat) {
P.String("for");
P.PrintControlClause(x.ctrl);
P.DoBlock(x.body);
}
func (P *Printer) Stat(s *Node.Stat)
func (P *Printer) DoCaseClause(x *AST.CaseClause) {
if x.exprs != nil {
P.String("case ");
P.PrintList(x.exprs);
P.String(":");
} else {
P.String("default:");
}
P.OpenScope("");
for i := 0; i < x.stats.len(); i++ {
P.Print(x.stats.at(i));
func (P *Printer) StatementList(list *Node.List) {
for i, n := 0, list.len(); i < n; i++ {
P.Stat(list.at(i).(*Node.Stat));
P.newl = true;
}
if x.falls {
P.String("fallthrough");
}
P.CloseScope("");
}
func (P *Printer) DoSwitchStat(x *AST.SwitchStat) {
P.String("switch ");
P.PrintControlClause(x.ctrl);
func (P *Printer) Block(list *Node.List) {
P.OpenScope("{");
P.indent--;
for i := 0; i < x.cases.len(); i++ {
P.Print(x.cases.at(i));
}
P.indent++;
P.StatementList(list);
P.CloseScope("}");
}
func (P *Printer) DoReturnStat(x *AST.ReturnStat) {
P.String("return ");
P.PrintList(x.res);
P.semi = true;
}
func (P *Printer) DoIncDecStat(x *AST.IncDecStat) {
P.Print(x.expr);
P.String(Scanner.TokenName(x.tok));
P.semi = true;
}
func (P *Printer) DoControlFlowStat(x *AST.ControlFlowStat) {
P.String(Scanner.TokenName(x.tok));
if x.label != nil {
func (P *Printer) ControlClause(s *Node.Stat) {
if s.init != nil {
P.String(" ");
P.Print(x.label);
P.Stat(s.init);
P.semi = true;
P.String("");
}
P.semi = true;
if s.expr != nil {
P.String(" ");
P.Expr(s.expr);
P.semi = false;
}
if s.post != nil {
P.semi = true;
P.String(" ");
P.Stat(s.post);
P.semi = false;
}
P.String(" ");
}
func (P *Printer) DoGoStat(x *AST.GoStat) {
P.String("go ");
P.Print(x.expr);
P.semi = true;
func (P *Printer) Declaration(d *Node.Decl);
func (P *Printer) Stat(s *Node.Stat) {
if s == nil { // TODO remove this check
P.String("<nil stat>");
return;
}
switch s.tok {
case 0: // TODO use a real token const
P.Expr(s.expr);
P.semi = true;
case Scanner.CONST, Scanner.TYPE, Scanner.VAR:
P.Declaration(s.decl);
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:
P.String(Scanner.TokenName(s.tok));
P.String(" ");
P.Expr(s.expr);
P.semi = true;
case Scanner.INC, Scanner.DEC:
P.Expr(s.expr);
P.String(Scanner.TokenName(s.tok));
P.semi = true;
case Scanner.IF, Scanner.FOR, Scanner.SWITCH, Scanner.SELECT:
P.String(Scanner.TokenName(s.tok));
P.ControlClause(s);
P.Block(s.block);
case Scanner.CASE, Scanner.DEFAULT:
P.String(Scanner.TokenName(s.tok));
if s.expr != nil {
P.String(" ");
P.Expr(s.expr);
}
P.String(":");
P.OpenScope("");
P.StatementList(s.block);
P.CloseScope("");
case Scanner.GO, Scanner.RETURN, Scanner.BREAK, Scanner.CONTINUE, Scanner.GOTO:
P.String("go ");
P.Expr(s.expr);
P.semi = true;
default:
P.String("<stat>");
P.semi = true;
}
}
// ----------------------------------------------------------------------------
// Declarations
/*
func (P *Printer) DoImportDecl(x *AST.ImportDecl) {
if x.ident != nil {
P.Print(x.ident);
P.String(" ");
}
P.String(x.file);
}
func (P *Printer) DoFuncDecl(x *AST.FuncDecl) {
P.String("func ");
if x.typ.recv != nil {
P.String("(");
P.DoVarDeclList(x.typ.recv);
P.String(") ");
}
P.DoIdent(x.ident);
P.DoFunctionType(x.typ);
if x.body != nil {
P.String(" ");
P.DoBlock(x.body);
} else {
P.String(" ;");
}
P.NewLine();
P.NewLine();
}
func (P *Printer) DoMethodDecl(x *AST.MethodDecl) {
//P.DoIdent(x.ident);
//P.DoFunctionType(x.typ);
}
*/
func (P *Printer) Declaration(d *Node.Decl) {
if d.tok == Scanner.FUNC || d.ident == nil {
if d.exported {
P.String("export ");
}
P.String(Scanner.TokenName(d.tok));
P.String(" ");
}
if d.ident == nil {
switch d.list.len() {
case 0:
P.String("()");
case 1:
P.Declaration(d.list.at(0).(*Node.Decl));
default:
P.OpenScope("(");
for i := 0; i < d.list.len(); i++ {
P.Declaration(d.list.at(i).(*Node.Decl));
P.newl, P.semi = true, true;
}
P.CloseScope(")");
}
} else {
P.Expr(d.ident);
if d.typ != nil {
P.String(" ");
P.Type(d.typ);
}
if d.val != nil {
P.String(" = ");
P.Expr(d.val);
}
if d.list != nil {
if d.tok != Scanner.FUNC {
panic("must be a func declaration");
}
P.String(" ");
P.Block(d.list);
}
}
if P.level == 0 {
P.NewLine();
}
P.newl = true;
}
// ----------------------------------------------------------------------------
// Program
func (P *Printer) DoProgram(x *AST.Program) {
func (P *Printer) Program(p *Node.Program) {
P.String("package ");
P.DoIdent(x.ident);
P.Expr(p.ident);
P.NewLine();
for i := 0; i < x.decls.len(); i++ {
P.Print(x.decls.at(i));
for i := 0; i < p.decls.len(); i++ {
P.Declaration(p.decls.at(i));
}
P.newl = true;
P.String("");
}
// ----------------------------------------------------------------------------
// Driver
export func Print(x AST.Node) {
var P Printer;
(&P).Print(x);
print("\n");
}