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:
parent
0b05e91f8b
commit
7c3a2c47b0
@ -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
|
||||
|
||||
|
@ -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
248
usr/gri/pretty/node.go
Normal 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
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user