Commit 7c3a2c47 authored by Robert Griesemer's avatar Robert Griesemer

- 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
parent 0b05e91f
......@@ -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
......
// 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); }
// 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;
}
......@@ -5,7 +5,7 @@
package Parser
import Scanner "scanner"
import AST "ast"
import Node "node"
export type Parser struct {
......@@ -43,12 +43,12 @@ func (P *Parser) Trace(msg string) {
P.PrintIndent();
print(msg, " {\n");
}
P.indent++; // always, so proper identation is always checked
P.indent++; // always check proper identation
}
func (P *Parser) Ecart() {
P.indent--; // always, so proper identation is always checked
P.indent--; // always check proper identation
if P.verbose {
P.PrintIndent();
print("}\n");
......@@ -105,22 +105,21 @@ func (P *Parser) OptSemicolon() {
// ----------------------------------------------------------------------------
// Common productions
func (P *Parser) TryType() (typ AST.Type, ok bool);
func (P *Parser) ParseExpression() AST.Expr;
func (P *Parser) ParseStatement() AST.Stat;
func (P *Parser) ParseDeclaration() AST.Node;
func (P *Parser) TryType() *Node.Type;
func (P *Parser) ParseExpression() *Node.Expr;
func (P *Parser) ParseStatement() *Node.Stat;
func (P *Parser) ParseDeclaration() *Node.Decl;
func (P *Parser) ParseIdent() *AST.Ident {
func (P *Parser) ParseIdent() *Node.Expr {
P.Trace("Ident");
ident := new(AST.Ident);
ident.pos, ident.val = P.pos, "";
var x *Node.Expr;
if P.tok == Scanner.IDENT {
ident.val = P.val;
x = Node.NewIdent(P.pos, P.val);
if P.verbose {
P.PrintIndent();
print("Ident = \"", ident.val, "\"\n");
print("Ident = \"", x.val, "\"\n");
}
P.Next();
} else {
......@@ -128,14 +127,14 @@ func (P *Parser) ParseIdent() *AST.Ident {
}
P.Ecart();
return ident;
return x;
}
func (P *Parser) ParseIdentList() *AST.List {
func (P *Parser) ParseIdentList() *Node.List {
P.Trace("IdentList");
list := AST.NewList();
list := Node.NewList();
list.Add(P.ParseIdent());
for P.tok == Scanner.COMMA {
P.Next();
......@@ -147,35 +146,14 @@ func (P *Parser) ParseIdentList() *AST.List {
}
func (P *Parser) ParseQualifiedIdent() AST.Expr {
P.Trace("QualifiedIdent");
ident := P.ParseIdent();
var qident AST.Expr = ident;
for P.tok == Scanner.PERIOD {
pos := P.pos;
P.Next();
y := P.ParseIdent();
z := new(AST.Selector);
z.pos, z.x, z.field = pos, qident, y.val;
qident = z;
}
P.Ecart();
return qident;
}
// ----------------------------------------------------------------------------
// Types
func (P *Parser) ParseType() AST.Type {
func (P *Parser) ParseType() *Node.Type {
P.Trace("Type");
typ, ok := P.TryType();
if !ok {
typ := P.TryType();
if typ == nil {
P.Error(P.pos, "type expected");
}
......@@ -184,7 +162,7 @@ func (P *Parser) ParseType() AST.Type {
}
func (P *Parser) ParseVarType() AST.Type {
func (P *Parser) ParseVarType() *Node.Type {
P.Trace("VarType");
typ := P.ParseType();
......@@ -194,91 +172,97 @@ func (P *Parser) ParseVarType() AST.Type {
}
func (P *Parser) ParseTypeName() AST.Type {
func (P *Parser) ParseQualifiedIdent() *Node.Expr {
P.Trace("QualifiedIdent");
x := P.ParseIdent();
for P.tok == Scanner.PERIOD {
pos := P.pos;
P.Next();
y := P.ParseIdent();
x = Node.NewExpr(pos, Scanner.PERIOD, x, y);
}
P.Ecart();
return x;
}
func (P *Parser) ParseTypeName() *Node.Type {
P.Trace("TypeName");
typ := P.ParseQualifiedIdent();
t := Node.NewType(P.pos, P.tok);
t.expr = P.ParseQualifiedIdent();
P.Ecart();
return typ;
return t;
}
func (P *Parser) ParseArrayType() *AST.ArrayType {
func (P *Parser) ParseArrayType() *Node.Type {
P.Trace("ArrayType");
typ := new(AST.ArrayType);
typ.pos = P.pos;
typ.len_ = AST.NIL;
t := Node.NewType(P.pos, Scanner.LBRACK);
P.Expect(Scanner.LBRACK);
if P.tok != Scanner.RBRACK {
// TODO set typ.len
typ.len_ = P.ParseExpression();
t.expr = P.ParseExpression();
}
P.Expect(Scanner.RBRACK);
typ.elt = P.ParseType();
t.elt = P.ParseType();
P.Ecart();
return typ;
return t;
}
func (P *Parser) ParseChannelType() *AST.ChannelType {
func (P *Parser) ParseChannelType() *Node.Type {
P.Trace("ChannelType");
typ := new(AST.ChannelType);
typ.pos = P.pos;
typ.mode = AST.FULL;
t := Node.NewType(P.pos, Scanner.CHAN);
t.mode = Node.FULL;
if P.tok == Scanner.CHAN {
P.Next();
if P.tok == Scanner.ARROW {
P.Next();
typ.mode = AST.SEND;
t.mode = Node.SEND;
}
} else {
P.Expect(Scanner.ARROW);
P.Expect(Scanner.CHAN);
typ.mode = AST.RECV;
t.mode = Node.RECV;
}
typ.elt = P.ParseVarType();
t.elt = P.ParseVarType();
P.Ecart();
return typ;
return t;
}
func (P *Parser) ParseVarDeclList() *AST.VarDeclList {
func (P *Parser) ParseVarDeclList() *Node.VarDeclList {
P.Trace("VarDeclList");
vars := new(AST.VarDeclList);
vars.idents = AST.NewList();
vars.typ = AST.NIL;
vars.idents.Add(P.ParseType());
list := new(Node.VarDeclList);
P.ParseType();
for P.tok == Scanner.COMMA {
P.Next();
vars.idents.Add(P.ParseType());
P.ParseType();
}
var ok bool;
vars.typ, ok = P.TryType();
typ := P.TryType();
if !ok {
if typ == nil {
// we must have a list of types
}
P.Ecart();
return vars;
return list;
}
// Returns a list of *AST.VarDeclList or Type
func (P *Parser) ParseParameterList() *AST.List {
func (P *Parser) ParseParameterList() *Node.List {
P.Trace("ParameterList");
list := AST.NewList();
list := Node.NewList();
list.Add(P.ParseVarDeclList());
for P.tok == Scanner.COMMA {
P.Next();
......@@ -290,11 +274,10 @@ func (P *Parser) ParseParameterList() *AST.List {
}
// Returns a list of AST.VarDeclList
func (P *Parser) ParseParameters() *AST.List {
func (P *Parser) ParseParameters() *Node.List {
P.Trace("Parameters");
var list *AST.List;
var list *Node.List;
P.Expect(Scanner.LPAREN);
if P.tok != Scanner.RPAREN {
list = P.ParseParameterList();
......@@ -322,25 +305,18 @@ func (P *Parser) ParseResultList() {
}
func (P *Parser) ParseResult() *AST.List {
func (P *Parser) ParseResult() *Node.List {
P.Trace("Result");
var result *AST.List;
var list *Node.List;
if P.tok == Scanner.LPAREN {
result = P.ParseParameters();
list = P.ParseParameters();
} else {
typ, ok := P.TryType();
if ok {
vars := new(AST.VarDeclList);
vars.typ = typ;
list := AST.NewList();
list.Add(vars);
result = list;
}
typ := P.TryType();
}
P.Ecart();
return result;
return list;
}
......@@ -350,44 +326,38 @@ func (P *Parser) ParseResult() *AST.List {
// (params) type
// (params) (results)
func (P *Parser) ParseFunctionType() *AST.FunctionType {
func (P *Parser) ParseFunctionType() *Node.Type {
P.Trace("FunctionType");
typ := new(AST.FunctionType);
typ.pos = P.pos;
typ.params = P.ParseParameters();
typ.result = P.ParseResult();
t := Node.NewType(P.pos, Scanner.LPAREN);
t.list = P.ParseParameters();
P.ParseResult();
P.Ecart();
return typ;
return t;
}
func (P *Parser) ParseMethodDecl() *AST.MethodDecl {
func (P *Parser) ParseMethodDecl() *Node.Decl {
P.Trace("MethodDecl");
decl := new(AST.MethodDecl);
decl.ident = P.ParseIdent();
decl.typ = P.ParseFunctionType();
P.ParseIdent();
P.ParseFunctionType();
P.Ecart();
return decl;
return nil;
}
func (P *Parser) ParseInterfaceType() *AST.InterfaceType {
func (P *Parser) ParseInterfaceType() *Node.Type {
P.Trace("InterfaceType");
typ := new(AST.InterfaceType);
typ.pos = P.pos;
typ.methods = AST.NewList();
t := Node.NewType(P.pos, Scanner.INTERFACE);
P.Expect(Scanner.INTERFACE);
if P.tok == Scanner.LBRACE {
P.Next();
for P.tok == Scanner.IDENT {
typ.methods.Add(P.ParseMethodDecl());
P.ParseMethodDecl();
if P.tok != Scanner.RBRACE {
P.Expect(Scanner.SEMICOLON);
}
......@@ -396,40 +366,35 @@ func (P *Parser) ParseInterfaceType() *AST.InterfaceType {
}
P.Ecart();
return typ;
return t;
}
func (P *Parser) ParseMapType() *AST.MapType {
func (P *Parser) ParseMapType() *Node.Type {
P.Trace("MapType");
typ := new(AST.MapType);
typ.pos = P.pos;
t := Node.NewType(P.pos, Scanner.MAP);
P.Expect(Scanner.MAP);
P.Expect(Scanner.LBRACK);
typ.key = P.ParseVarType();
t.key = P.ParseVarType();
P.Expect(Scanner.RBRACK);
typ.val = P.ParseVarType();
t.elt = P.ParseVarType();
P.Ecart();
return typ;
return t;
}
func (P *Parser) ParseStructType() *AST.StructType {
func (P *Parser) ParseStructType() *Node.Type {
P.Trace("StructType");
typ := new(AST.StructType);
typ.pos = P.pos;
typ.fields = AST.NewList();
t := Node.NewType(P.pos, Scanner.STRUCT);
P.Expect(Scanner.STRUCT);
if P.tok == Scanner.LBRACE {
P.Next();
t.list = Node.NewList();
for P.tok == Scanner.IDENT {
typ.fields.Add(P.ParseVarDeclList());
t.list.Add(P.ParseVarDeclList());
if P.tok != Scanner.RBRACE {
P.Expect(Scanner.SEMICOLON);
}
......@@ -439,56 +404,52 @@ func (P *Parser) ParseStructType() *AST.StructType {
}
P.Ecart();
return typ;
return t;
}
func (P *Parser) ParsePointerType() *AST.PointerType {
func (P *Parser) ParsePointerType() *Node.Type {
P.Trace("PointerType");
typ := new(AST.PointerType);
typ.pos = P.pos;
typ := Node.NewType(P.pos, Scanner.MUL);
P.Expect(Scanner.MUL);
typ.base = P.ParseType();
typ.elt = P.ParseType();
P.Ecart();
return typ;
}
// Returns false if no type was found.
func (P *Parser) TryType() (typ_ AST.Type, ok_ bool) {
// Returns nil if no type was found.
func (P *Parser) TryType() *Node.Type {
P.Trace("Type (try)");
var typ AST.Type = AST.NIL;
found := true;
var t *Node.Type;
switch P.tok {
case Scanner.IDENT: typ = P.ParseTypeName();
case Scanner.LBRACK: typ = P.ParseArrayType();
case Scanner.CHAN, Scanner.ARROW: typ = P.ParseChannelType();
case Scanner.INTERFACE: typ = P.ParseInterfaceType();
case Scanner.LPAREN: typ = P.ParseFunctionType();
case Scanner.MAP: typ = P.ParseMapType();
case Scanner.STRUCT: typ = P.ParseStructType();
case Scanner.MUL: typ = P.ParsePointerType();
default: found = false;
case Scanner.IDENT: t = P.ParseTypeName();
case Scanner.LBRACK: t = P.ParseArrayType();
case Scanner.CHAN, Scanner.ARROW: t = P.ParseChannelType();
case Scanner.INTERFACE: t = P.ParseInterfaceType();
case Scanner.LPAREN: t = P.ParseFunctionType();
case Scanner.MAP: t = P.ParseMapType();
case Scanner.STRUCT: t = P.ParseStructType();
case Scanner.MUL: t = P.ParsePointerType();
}
P.Ecart();
return typ, found;
return t;
}
// ----------------------------------------------------------------------------
// Blocks
func (P *Parser) ParseStatementList() *AST.List {
func (P *Parser) ParseStatementList() *Node.List {
P.Trace("StatementList");
stats := AST.NewList();
list := Node.NewList();
for P.tok != Scanner.CASE && P.tok != Scanner.DEFAULT && P.tok != Scanner.RBRACE && P.tok != Scanner.EOF {
stats.Add(P.ParseStatement());
list.Add(P.ParseStatement());
if P.tok == Scanner.SEMICOLON {
P.Next();
} else if P.opt_semi {
......@@ -499,134 +460,95 @@ func (P *Parser) ParseStatementList() *AST.List {
}
P.Ecart();
return stats;
return list;
}
func (P *Parser) ParseBlock() *AST.Block {
func (P *Parser) ParseBlock() *Node.List {
P.Trace("Block");
block := new(AST.Block);
block.pos = P.pos;
var s *Node.List;
P.Expect(Scanner.LBRACE);
if P.tok != Scanner.RBRACE {
block.stats = P.ParseStatementList();
s = P.ParseStatementList();
}
P.OptSemicolon();
P.Expect(Scanner.RBRACE);
P.opt_semi = true;
P.Ecart();
return block;
return s;
}
// ----------------------------------------------------------------------------
// Expressions
func (P *Parser) ParseExpressionList(list *AST.List) {
// TODO: Make this non-recursive.
func (P *Parser) ParseExpressionList() *Node.Expr {
P.Trace("ExpressionList");
list.Add(P.ParseExpression());
for P.tok == Scanner.COMMA {
x := P.ParseExpression();
if P.tok == Scanner.COMMA {
pos := P.pos;
P.Next();
list.Add(P.ParseExpression());
y := P.ParseExpressionList();
x = Node.NewExpr(pos, Scanner.COMMA, x, y);
}
P.Ecart();
return x;
}
func (P *Parser) ParseNewExpressionList() *AST.List {
list := AST.NewList();
P.ParseExpressionList(list);
return list;
}
func (P *Parser) ParseFunctionLit() *AST.FunctionLit {
func (P *Parser) ParseFunctionLit() *Node.Expr {
P.Trace("FunctionLit");
fun := new(AST.FunctionLit);
fun.pos = P.pos;
P.Expect(Scanner.FUNC);
fun.typ = P.ParseFunctionType();
P.ParseFunctionType();
P.scope_lev++;
fun.body = P.ParseBlock();
P.ParseBlock();
P.scope_lev--;
P.Ecart();
return fun;
return nil;
}
func (P *Parser) ParseExpressionPair() AST.Expr {
P.Trace("ExpressionPair");
p := new(AST.Pair);
p.x = P.ParseExpression();
p.pos = P.pos;
P.Expect(Scanner.COLON);
p.y = P.ParseExpression();
P.Ecart();
return p;
}
func (P *Parser) ParseExpressionPairList(list *AST.List) {
P.Trace("ExpressionPairList");
list.Add(P.ParseExpressionPair());
for P.tok == Scanner.COMMA {
P.Next();
list.Add(P.ParseExpressionPair());
}
P.Ecart();
}
func (P *Parser) ParseOperand() AST.Expr {
func (P *Parser) ParseOperand() *Node.Expr {
P.Trace("Operand");
var op AST.Expr;
var x *Node.Expr;
switch P.tok {
case Scanner.IDENT:
op = P.ParseIdent();
x = P.ParseIdent();
case Scanner.LPAREN:
P.Next();
P.expr_lev++;
op = P.ParseExpression();
x = P.ParseExpression();
P.expr_lev--;
P.Expect(Scanner.RPAREN);
case Scanner.INT, Scanner.FLOAT:
lit := new(AST.Literal);
lit.pos, lit.tok, lit.val = P.pos, P.tok, P.val;
op = lit;
val := new(Node.Val);
val.s = P.val;
x = Node.NewVal(P.pos, P.tok, val);
P.Next();
case Scanner.STRING:
lit := new(AST.Literal);
lit.pos, lit.tok = P.pos, P.tok;
for P.tok == Scanner.STRING {
lit.val += P.val;
P.Next();
val := new(Node.Val);
val.s = P.val;
x = Node.NewVal(P.pos, Scanner.STRING, val);
for P.Next(); P.tok == Scanner.STRING; P.Next() {
val.s += P.val;
}
op = lit;
case Scanner.FUNC:
op = P.ParseFunctionLit();
P.ParseFunctionLit();
default:
typ, ok := P.TryType();
if ok {
op = typ;
typ := P.TryType();
if typ != nil {
break;
}
......@@ -635,22 +557,19 @@ func (P *Parser) ParseOperand() AST.Expr {
}
P.Ecart();
return op;
return x;
}
func (P *Parser) ParseSelectorOrTypeGuard(x AST.Expr) AST.Expr {
func (P *Parser) ParseSelectorOrTypeGuard(x *Node.Expr) *Node.Expr {
P.Trace("SelectorOrTypeGuard");
pos := P.pos;
P.Expect(Scanner.PERIOD);
if P.tok == Scanner.IDENT {
ident := P.ParseIdent();
z := new(AST.Selector);
z.pos, z.x, z.field = pos, x, ident.val;
x = z;
y := P.ParseIdent();
x = Node.NewExpr(pos, Scanner.PERIOD, x, y);
} else {
P.Expect(Scanner.LPAREN);
......@@ -663,99 +582,92 @@ func (P *Parser) ParseSelectorOrTypeGuard(x AST.Expr) AST.Expr {
}
func (P *Parser) ParseIndexOrSlice(x AST.Expr) AST.Expr {
// mode = 0: single or pair accepted
// mode = 1: single only accepted
// mode = 2: pair only accepted
func (P *Parser) ParseExpressionPair(mode int) *Node.Expr {
P.Trace("ExpressionPair");
x := P.ParseExpression();
if mode == 0 && P.tok == Scanner.COLON || mode == 2 {
pos := P.pos;
P.Expect(Scanner.COLON);
y := P.ParseExpression();
x = Node.NewExpr(pos, Scanner.COLON, x, y);
}
P.Ecart();
return x;
}
func (P *Parser) ParseIndex(x *Node.Expr) *Node.Expr {
P.Trace("IndexOrSlice");
pos := P.pos;
P.Expect(Scanner.LBRACK);
i := P.ParseExpression();
if P.tok == Scanner.COLON {
P.Next();
j := P.ParseExpression();
// TODO: handle this case
}
i := P.ParseExpressionPair(0);
P.Expect(Scanner.RBRACK);
z := new(AST.Index);
z.pos, z.x, z.index = pos, x, i;
P.Ecart();
return z;
return Node.NewExpr(pos, Scanner.LBRACK, x, i);
}
func (P *Parser) ParseCall(x AST.Expr) *AST.Call {
func (P *Parser) ParseCall(x *Node.Expr) *Node.Expr {
P.Trace("Call");
call := new(AST.Call);
call.pos = P.pos;
call.fun = x;
call.args = nil;
x = Node.NewExpr(P.pos, Scanner.LPAREN, x, nil);
P.Expect(Scanner.LPAREN);
if P.tok != Scanner.RPAREN {
call.args = P.ParseNewExpressionList();
x.y = P.ParseExpressionList();
}
P.Expect(Scanner.RPAREN);
P.Ecart();
return call;
return x;
}
func (P *Parser) ParseCompositeLit(typ AST.Type) AST.Expr {
func (P *Parser) ParseCompositeLit() {
P.Trace("CompositeLit");
lit := new(AST.CompositeLit);
lit.pos = P.pos;
lit.typ = typ;
lit.vals = AST.NewList();
mode := 0;
P.Expect(Scanner.LBRACE);
if P.tok != Scanner.RBRACE {
x := P.ParseExpression();
if P.tok == Scanner.COMMA {
P.Next();
lit.vals.Add(x);
if P.tok != Scanner.RBRACE {
P.ParseExpressionList(lit.vals);
for P.tok != Scanner.RBRACE && P.tok != Scanner.EOF {
x := P.ParseExpressionPair(mode);
if mode == 0 {
// first expression determines mode
if x.tok == Scanner.COLON {
mode = 2;
} else {
mode = 1;
}
}
} else if P.tok == Scanner.COLON {
p := new(AST.Pair);
p.pos = P.pos;
p.x = x;
P.Next();
p.y = P.ParseExpression();
lit.vals.Add(p);
if P.tok == Scanner.COMMA {
P.Next();
if P.tok != Scanner.RBRACE {
P.ParseExpressionPairList(lit.vals);
}
}
} else {
lit.vals.Add(x);
break;
}
}
P.Expect(Scanner.RBRACE);
P.Ecart();
return lit;
}
func (P *Parser) ParsePrimaryExpr() AST.Expr {
func (P *Parser) ParsePrimaryExpr() *Node.Expr {
P.Trace("PrimaryExpr");
x := P.ParseOperand();
for {
switch P.tok {
case Scanner.PERIOD: x = P.ParseSelectorOrTypeGuard(x);
case Scanner.LBRACK: x = P.ParseIndexOrSlice(x);
case Scanner.LBRACK: x = P.ParseIndex(x);
case Scanner.LPAREN: x = P.ParseCall(x);
case Scanner.LBRACE:
if P.expr_lev > 0 {
x = P.ParseCompositeLit(x);
P.ParseCompositeLit();
} else {
goto exit;
}
......@@ -769,10 +681,10 @@ exit:
}
func (P *Parser) ParseUnaryExpr() AST.Expr {
func (P *Parser) ParseUnaryExpr() *Node.Expr {
P.Trace("UnaryExpr");
var x AST.Expr = AST.NIL;
var x *Node.Expr;
switch P.tok {
case
Scanner.ADD, Scanner.SUB,
......@@ -782,10 +694,7 @@ func (P *Parser) ParseUnaryExpr() AST.Expr {
pos, tok := P.pos, P.tok;
P.Next();
y := P.ParseUnaryExpr();
z := new(AST.Unary);
z.pos, z.tok, z.x = pos, tok, y;
x = z;
x = Node.NewExpr(pos, tok, nil, y);
default:
x = P.ParsePrimaryExpr();
......@@ -796,7 +705,7 @@ func (P *Parser) ParseUnaryExpr() AST.Expr {
}
func (P *Parser) ParseBinaryExpr(prec1 int) AST.Expr {
func (P *Parser) ParseBinaryExpr(prec1 int) *Node.Expr {
P.Trace("BinaryExpr");
x := P.ParseUnaryExpr();
......@@ -805,10 +714,7 @@ func (P *Parser) ParseBinaryExpr(prec1 int) AST.Expr {
pos, tok := P.pos, P.tok;
P.Next();
y := P.ParseBinaryExpr(prec + 1);
z := new(AST.Binary);
z.pos, z.tok, z.x, z.y = pos, tok, x, y;
x = z;
x = Node.NewExpr(pos, tok, x, y);
}
}
......@@ -817,7 +723,7 @@ func (P *Parser) ParseBinaryExpr(prec1 int) AST.Expr {
}
func (P *Parser) ParseExpression() AST.Expr {
func (P *Parser) ParseExpression() *Node.Expr {
P.Trace("Expression");
indent := P.indent;
......@@ -826,7 +732,6 @@ func (P *Parser) ParseExpression() AST.Expr {
if indent != P.indent {
panic("imbalanced tracing code (Expression)");
}
P.Ecart();
return x;
}
......@@ -835,244 +740,211 @@ func (P *Parser) ParseExpression() AST.Expr {
// ----------------------------------------------------------------------------
// Statements
func (P *Parser) ParseSimpleStat() AST.Stat {
func (P *Parser) ParseSimpleStat() *Node.Stat {
P.Trace("SimpleStat");
var stat AST.Stat = AST.NIL;
x := P.ParseNewExpressionList();
var s *Node.Stat;
list := P.ParseExpressionList();
switch P.tok {
case Scanner.COLON:
// label declaration
l := new(AST.Label);
l.pos = P.pos;
if x.len() == 1 {
l.ident = x.at(0);
if list.len() == 1 {
} else {
P.Error(P.pos, "illegal label declaration");
l.ident = AST.NIL;
}
P.Next(); // consume ":"
P.opt_semi = true;
stat = l;
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:
pos, tok := P.pos, P.tok;
s = Node.NewStat(P.pos, P.tok);
P.Next();
y := P.ParseNewExpressionList();
a := new(AST.Assignment);
a.pos, a.tok, a.lhs, a.rhs = pos, tok, x, y;
stat = a;
s.expr = P.ParseExpressionList();
default:
if P.tok == Scanner.INC || P.tok == Scanner.DEC {
s := new(AST.IncDecStat);
s.pos, s.tok = P.pos, P.tok;
if x.len() == 1 {
s.expr = x.at(0);
s = Node.NewStat(P.pos, P.tok);
if list.len() == 1 {
s.expr = list;
} else {
P.Error(P.pos, "more then one operand");
}
P.Next();
stat = s;
} else {
s := new(AST.ExprStat);
if x != nil && x.len() > 0 {
s.expr = x.at(0);
s = Node.NewStat(P.pos, 0); // TODO give this a token value
if list.len() == 1 {
s.expr = list;
} else {
// this is a syntax error
s.expr = AST.NIL;
P.Error(P.pos, "syntax error");
}
stat = s;
}
}
P.Ecart();
return stat;
return s;
}
func (P *Parser) ParseGoStat() *AST.GoStat {
func (P *Parser) ParseGoStat() *Node.Stat {
P.Trace("GoStat");
stat := new(AST.GoStat);
stat.pos = P.pos;
s := Node.NewStat(P.pos, Scanner.GO);
P.Expect(Scanner.GO);
stat.expr = P.ParseExpression();
s.expr = P.ParseExpression();
P.Ecart();
return stat;
return s;
}
func (P *Parser) ParseReturnStat() *AST.ReturnStat {
func (P *Parser) ParseReturnStat() *Node.Stat {
P.Trace("ReturnStat");
stat := new(AST.ReturnStat);
stat.pos = P.pos;
s := Node.NewStat(P.pos, Scanner.RETURN);
P.Expect(Scanner.RETURN);
if P.tok != Scanner.SEMICOLON && P.tok != Scanner.RBRACE {
stat.res = P.ParseNewExpressionList();
s.expr = P.ParseExpressionList();
}
P.Ecart();
return stat;
return s;
}
func (P *Parser) ParseControlFlowStat(tok int) *AST.ControlFlowStat {
func (P *Parser) ParseControlFlowStat(tok int) *Node.Stat {
P.Trace("ControlFlowStat");
stat := new(AST.ControlFlowStat);
stat.pos, stat.tok = P.pos, P.tok;
s := Node.NewStat(P.pos, tok);
P.Expect(tok);
if P.tok == Scanner.IDENT {
stat.label = P.ParseIdent();
s.expr = P.ParseIdent();
}
P.Ecart();
return stat;
return s;
}
func (P *Parser) ParseControlClause(keyword int) *AST.ControlClause {
func (P *Parser) ParseControlClause(keyword int) *Node.Stat {
P.Trace("StatHeader");
ctrl := new(AST.ControlClause);
ctrl.init, ctrl.expr, ctrl.post = AST.NIL, AST.NIL, AST.NIL;
s := Node.NewStat(P.pos, keyword);
P.Expect(keyword);
if P.tok != Scanner.LBRACE {
prev_lev := P.expr_lev;
P.expr_lev = 0;
if P.tok != Scanner.SEMICOLON {
ctrl.init = P.ParseSimpleStat();
ctrl.has_init = true;
s.init = P.ParseSimpleStat();
}
if P.tok == Scanner.SEMICOLON {
P.Next();
if P.tok != Scanner.SEMICOLON && P.tok != Scanner.LBRACE {
ctrl.expr = P.ParseExpression();
ctrl.has_expr = true;
s.expr = P.ParseExpression();
}
if keyword == Scanner.FOR {
P.Expect(Scanner.SEMICOLON);
if P.tok != Scanner.LBRACE {
ctrl.post = P.ParseSimpleStat();
ctrl.has_post = true;
s.post = P.ParseSimpleStat();
}
}
} else {
ctrl.expr, ctrl.has_expr = ctrl.init, ctrl.has_init;
ctrl.init, ctrl.has_init = AST.NIL, false;
if s.init != nil { // guard in case of errors
s.expr, s.init = s.init.expr, nil;
}
}
P.expr_lev = prev_lev;
}
P.Ecart();
return ctrl;
return s;
}
func (P *Parser) ParseIfStat() *AST.IfStat {
func (P *Parser) ParseIfStat() *Node.Stat {
P.Trace("IfStat");
stat := new(AST.IfStat);
stat.pos = P.pos;
stat.ctrl = P.ParseControlClause(Scanner.IF);
stat.then = P.ParseBlock();
s := P.ParseControlClause(Scanner.IF);
s.block = P.ParseBlock();
if P.tok == Scanner.ELSE {
P.Next();
if P.tok == Scanner.IF {
stat.else_ = P.ParseIfStat();
P.ParseIfStat();
} else {
// TODO: Should be P.ParseBlock().
stat.else_ = P.ParseStatement();
P.ParseStatement();
}
stat.has_else = true;
}
P.Ecart();
return stat;
return s;
}
func (P *Parser) ParseForStat() *AST.ForStat {
func (P *Parser) ParseForStat() *Node.Stat {
P.Trace("ForStat");
stat := new(AST.ForStat);
stat.pos = P.pos;
stat.ctrl = P.ParseControlClause(Scanner.FOR);
stat.body = P.ParseBlock();
s := P.ParseControlClause(Scanner.FOR);
s.block = P.ParseBlock();
P.Ecart();
return stat;
return s;
}
func (P *Parser) ParseCase() *AST.CaseClause {
func (P *Parser) ParseCase() *Node.Stat {
P.Trace("Case");
clause := new(AST.CaseClause);
clause.pos = P.pos;
s := Node.NewStat(P.pos, P.tok);
if P.tok == Scanner.CASE {
P.Next();
clause.exprs = P.ParseNewExpressionList();
s.expr = P.ParseExpressionList();
} else {
P.Expect(Scanner.DEFAULT);
}
P.Expect(Scanner.COLON);
P.Ecart();
return clause;
return s;
}
func (P *Parser) ParseCaseClause() *AST.CaseClause {
func (P *Parser) ParseCaseClause() *Node.Stat {
P.Trace("CaseClause");
clause := P.ParseCase();
s := P.ParseCase();
if P.tok != Scanner.CASE && P.tok != Scanner.DEFAULT && P.tok != Scanner.RBRACE {
clause.stats = P.ParseStatementList();
s.block = P.ParseStatementList();
}
P.Ecart();
return clause;
return s;
}
func (P *Parser) ParseSwitchStat() *AST.SwitchStat {
func (P *Parser) ParseSwitchStat() *Node.Stat {
P.Trace("SwitchStat");
stat := new(AST.SwitchStat);
stat.pos = P.pos;
stat.ctrl = P.ParseControlClause(Scanner.SWITCH);
stat.cases = AST.NewList();
s := P.ParseControlClause(Scanner.SWITCH);
s.block = Node.NewList();
P.Expect(Scanner.LBRACE);
for P.tok != Scanner.RBRACE && P.tok != Scanner.EOF {
stat.cases.Add(P.ParseCaseClause());
s.block.Add(P.ParseCaseClause());
}
P.Expect(Scanner.RBRACE);
P.opt_semi = true;
P.Ecart();
return stat;
return s;
}
func (P *Parser) ParseCommCase() {
func (P *Parser) ParseCommCase() *Node.Stat {
P.Trace("CommCase");
s := Node.NewStat(P.pos, Scanner.CASE);
if P.tok == Scanner.CASE {
P.Next();
P.ParseExpression();
......@@ -1087,42 +959,49 @@ func (P *Parser) ParseCommCase() {
P.Expect(Scanner.COLON);
P.Ecart();
return s;
}
func (P *Parser) ParseCommClause() {
func (P *Parser) ParseCommClause() *Node.Stat {
P.Trace("CommClause");
P.ParseCommCase();
s := P.ParseCommCase();
if P.tok != Scanner.CASE && P.tok != Scanner.DEFAULT && P.tok != Scanner.RBRACE {
P.ParseStatementList();
s.block = P.ParseStatementList();
}
P.Ecart();
return s;
}
func (P *Parser) ParseSelectStat() {
func (P *Parser) ParseSelectStat() *Node.Stat {
P.Trace("SelectStat");
s := Node.NewStat(P.pos, Scanner.SELECT);
s.block = Node.NewList();
P.Expect(Scanner.SELECT);
P.Expect(Scanner.LBRACE);
for P.tok != Scanner.RBRACE && P.tok != Scanner.EOF {
P.ParseCommClause();
s.block.Add(P.ParseCommClause());
}
P.Expect(Scanner.RBRACE);
P.opt_semi = true;
P.Ecart();
return s;
}
func (P *Parser) ParseFallthroughStat() {
func (P *Parser) ParseFallthroughStat() *Node.Stat {
P.Trace("FallthroughStat");
s := Node.NewStat(P.pos, Scanner.FALLTHROUGH);
P.Expect(Scanner.FALLTHROUGH);
P.Ecart();
return s;
}
......@@ -1132,27 +1011,30 @@ func (P *Parser) ParseEmptyStat() {
}
func (P *Parser) ParseRangeStat() {
func (P *Parser) ParseRangeStat() *Node.Stat {
P.Trace("RangeStat");
s := Node.NewStat(P.pos, Scanner.RANGE);
P.Expect(Scanner.RANGE);
P.ParseIdentList();
P.Expect(Scanner.DEFINE);
P.ParseExpression();
P.ParseBlock();
s.expr = P.ParseExpression();
s.block = P.ParseBlock();
P.Ecart();;
P.Ecart();
return s;
}
func (P *Parser) ParseStatement() AST.Stat {
func (P *Parser) ParseStatement() *Node.Stat {
P.Trace("Statement");
indent := P.indent;
var stat AST.Stat = AST.NIL;
var s *Node.Stat;
switch P.tok {
case Scanner.CONST, Scanner.TYPE, Scanner.VAR:
stat = P.ParseDeclaration();
s = Node.NewStat(P.pos, P.tok);
s.decl = P.ParseDeclaration();
case Scanner.FUNC:
// for now we do not allow local function declarations
fallthrough;
......@@ -1161,27 +1043,28 @@ func (P *Parser) ParseStatement() AST.Stat {
Scanner.IDENT, Scanner.INT, Scanner.FLOAT, Scanner.STRING, Scanner.LPAREN, // operand
Scanner.LBRACK, Scanner.STRUCT, // composite type
Scanner.MUL, Scanner.AND, Scanner.ARROW: // unary
stat = P.ParseSimpleStat();
s = P.ParseSimpleStat();
case Scanner.GO:
stat = P.ParseGoStat();
s = P.ParseGoStat();
case Scanner.RETURN:
stat = P.ParseReturnStat();
s = P.ParseReturnStat();
case Scanner.BREAK, Scanner.CONTINUE, Scanner.GOTO:
stat = P.ParseControlFlowStat(P.tok);
s = P.ParseControlFlowStat(P.tok);
case Scanner.LBRACE:
stat = P.ParseBlock();
s = Node.NewStat(P.pos, Scanner.LBRACE);
s.block = P.ParseBlock();
case Scanner.IF:
stat = P.ParseIfStat();
s = P.ParseIfStat();
case Scanner.FOR:
stat = P.ParseForStat();
s = P.ParseForStat();
case Scanner.SWITCH:
stat = P.ParseSwitchStat();
s = P.ParseSwitchStat();
case Scanner.RANGE:
P.ParseRangeStat();
s = P.ParseRangeStat();
case Scanner.SELECT:
P.ParseSelectStat();
s = P.ParseSelectStat();
case Scanner.FALLTHROUGH:
P.ParseFallthroughStat();
s = P.ParseFallthroughStat();
default:
P.ParseEmptyStat(); // for complete tracing output only
}
......@@ -1190,94 +1073,88 @@ func (P *Parser) ParseStatement() AST.Stat {
panic("imbalanced tracing code (Statement)");
}
P.Ecart();
return stat;
return s;
}
// ----------------------------------------------------------------------------
// Declarations
func (P *Parser) ParseImportSpec() *AST.ImportDecl {
func (P *Parser) ParseImportSpec() *Node.Decl {
P.Trace("ImportSpec");
decl := new(AST.ImportDecl);
d := Node.NewDecl(P.pos, Scanner.IMPORT, false);
if P.tok == Scanner.PERIOD {
P.Error(P.pos, `"import ." not yet handled properly`);
P.Next();
} else if P.tok == Scanner.IDENT {
decl.ident = P.ParseIdent();
d.ident = P.ParseIdent();
}
if P.tok == Scanner.STRING {
// TODO eventually the scanner should strip the quotes
decl.file = P.val;
P.Next();
} else {
P.Expect(Scanner.STRING); // use Expect() error handling
}
P.Ecart();
return decl;
return d;
}
func (P *Parser) ParseConstSpec(exported bool) *AST.ConstDecl {
func (P *Parser) ParseConstSpec(exported bool) *Node.Decl {
P.Trace("ConstSpec");
decl := new(AST.ConstDecl);
decl.ident = P.ParseIdent();
var ok bool;
decl.typ, ok = P.TryType();
decl.val = AST.NIL;
d := Node.NewDecl(P.pos, Scanner.CONST, exported);
d.ident = P.ParseIdent();
d.typ = P.TryType();
if P.tok == Scanner.ASSIGN {
P.Next();
decl.val = P.ParseExpression();
d.val = P.ParseExpression();
}
P.Ecart();
return decl;
return d;
}
func (P *Parser) ParseTypeSpec(exported bool) *AST.TypeDecl {
func (P *Parser) ParseTypeSpec(exported bool) *Node.Decl {
P.Trace("TypeSpec");
decl := new(AST.TypeDecl);
decl.ident = P.ParseIdent();
decl.typ = P.ParseType();
d := Node.NewDecl(P.pos, Scanner.TYPE, exported);
d.ident = P.ParseIdent();
d.typ = P.ParseType();
P.opt_semi = true;
P.Ecart();
return decl;
return d;
}
func (P *Parser) ParseVarSpec(exported bool) *AST.VarDecl {
func (P *Parser) ParseVarSpec(exported bool) *Node.Decl {
P.Trace("VarSpec");
decl := new(AST.VarDecl);
decl.idents = P.ParseIdentList();
d := Node.NewDecl(P.pos, Scanner.VAR, exported);
P.ParseIdentList();
if P.tok == Scanner.ASSIGN {
P.Next();
decl.typ = AST.NIL;
decl.vals = P.ParseNewExpressionList();
P.ParseExpressionList();
} else {
decl.typ = P.ParseVarType();
P.ParseVarType();
if P.tok == Scanner.ASSIGN {
P.Next();
decl.vals = P.ParseNewExpressionList();
P.ParseExpressionList();
}
}
P.Ecart();
return decl;
return d;
}
// 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) *Node.Decl {
switch keyword {
case Scanner.IMPORT: return P.ParseImportSpec();
case Scanner.CONST: return P.ParseConstSpec(exported);
......@@ -1285,22 +1162,21 @@ func (P *Parser) ParseSpec(exported bool, keyword int) AST.Decl {
case Scanner.VAR: return P.ParseVarSpec(exported);
}
panic("UNREACHABLE");
return AST.NIL;
return nil;
}
func (P *Parser) ParseDecl(exported bool, keyword int) *AST.Declaration {
func (P *Parser) ParseDecl(exported bool, keyword int) *Node.Decl {
P.Trace("Decl");
decl := new(AST.Declaration);
decl.decls = AST.NewList();
decl.pos, decl.tok = P.pos, P.tok;
var d *Node.Decl;
P.Expect(keyword);
if P.tok == Scanner.LPAREN {
P.Next();
d = Node.NewDecl(P.pos, keyword, exported);
d.list = Node.NewList();
for P.tok != Scanner.RPAREN && P.tok != Scanner.EOF {
decl.decls.Add(P.ParseSpec(exported, keyword));
d.list.Add(P.ParseSpec(exported, keyword));
if P.tok == Scanner.SEMICOLON {
P.Next();
} else {
......@@ -1311,11 +1187,11 @@ func (P *Parser) ParseDecl(exported bool, keyword int) *AST.Declaration {
P.opt_semi = true;
} else {
decl.decls.Add(P.ParseSpec(exported, keyword));
d = P.ParseSpec(exported, keyword);
}
P.Ecart();
return decl;
return d;
}
......@@ -1328,39 +1204,37 @@ func (P *Parser) ParseDecl(exported bool, keyword int) *AST.Declaration {
// func (recv) ident (params) type
// func (recv) ident (params) (results)
func (P *Parser) ParseFunctionDecl(exported bool) *AST.FuncDecl {
func (P *Parser) ParseFunctionDecl(exported bool) *Node.Decl {
P.Trace("FunctionDecl");
fun := new(AST.FuncDecl);
fun.pos = P.pos;
d := Node.NewDecl(P.pos, Scanner.FUNC, exported);
P.Expect(Scanner.FUNC);
var recv *AST.VarDeclList;
if P.tok == Scanner.LPAREN {
pos := P.pos;
tmp := P.ParseParameters();
P.ParseParameters();
/*
if tmp.len() > 0 {
recv = tmp.at(0);
//recv = tmp.at(0);
}
*/
/*
if recv.idents.len() != 1 {
P.Error(pos, "must have exactly one receiver");
//P.Error(pos, "must have exactly one receiver");
}
*/
}
fun.ident = P.ParseIdent();
fun.typ = P.ParseFunctionType();
fun.typ.recv = recv;
d.ident = P.ParseIdent();
d.typ = P.ParseFunctionType();
if P.tok == Scanner.LBRACE {
P.scope_lev++;
fun.body = P.ParseBlock();
d.list = P.ParseBlock();
P.scope_lev--;
}
P.Ecart();
return fun;
return d;
}
......@@ -1377,7 +1251,7 @@ func (P *Parser) ParseExportDecl() {
has_paren = true;
}
for P.tok == Scanner.IDENT {
ident := P.ParseIdent();
P.ParseIdent();
if P.tok == Scanner.COMMA {
P.Next(); // TODO this seems wrong
}
......@@ -1390,11 +1264,11 @@ func (P *Parser) ParseExportDecl() {
}
func (P *Parser) ParseDeclaration() AST.Node {
func (P *Parser) ParseDeclaration() *Node.Decl {
P.Trace("Declaration");
indent := P.indent;
var node AST.Node;
var d *Node.Decl;
exported := false;
if P.tok == Scanner.EXPORT {
......@@ -1408,9 +1282,9 @@ func (P *Parser) ParseDeclaration() AST.Node {
switch P.tok {
case Scanner.CONST, Scanner.TYPE, Scanner.VAR:
node = P.ParseDecl(exported, P.tok);
d = P.ParseDecl(exported, P.tok);
case Scanner.FUNC:
node = P.ParseFunctionDecl(exported);
d = P.ParseFunctionDecl(exported);
case Scanner.EXPORT:
if exported {
P.Error(P.pos, "cannot mark export declaration for export");
......@@ -1430,34 +1304,31 @@ func (P *Parser) ParseDeclaration() AST.Node {
panic("imbalanced tracing code (Declaration)");
}
P.Ecart();
return node;
return d;
}
// ----------------------------------------------------------------------------
// Program
func (P *Parser) ParseProgram() *AST.Program {
func (P *Parser) ParseProgram() *Node.Program {
P.Trace("Program");
pos := P.pos;
p := Node.NewProgram(P.pos);
P.Expect(Scanner.PACKAGE);
ident := P.ParseIdent();
p.ident = P.ParseIdent();
decls := AST.NewList();
p.decls = Node.NewList();
for P.tok == Scanner.IMPORT {
decls.Add(P.ParseDecl(false, Scanner.IMPORT));
p.decls.Add(P.ParseDecl(false, Scanner.IMPORT));
P.OptSemicolon();
}
for P.tok != Scanner.EOF {
decls.Add(P.ParseDeclaration());
p.decls.Add(P.ParseDeclaration());
P.OptSemicolon();
}
P.Ecart();
x := new(AST.Program);
x.pos, x.ident, x.decls = pos, ident, decls;
return x;
return p;
}
......@@ -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) {
case Scanner.LBRACK:
P.String("[");
P.Print(x.len_);
if t.expr != nil {
P.Expr(t.expr);
}
P.String("] ");
P.Print(x.elt);
}
P.Type(t.elt);
func (P *Printer) DoStructType(x *AST.StructType) {
P.String("struct ");
P.OpenScope("{");
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("}");
}
}
func (P *Printer) DoMapType(x *AST.MapType) {
case Scanner.MAP:
P.String("[");
P.Print(x.key);
P.Type(t.key);
P.String("] ");
P.Print(x.val);
}
P.Type(t.elt);
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 <- ");
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.Print(x.elt);
}
P.Type(t.elt);
func (P *Printer) DoInterfaceType(x *AST.InterfaceType) {
P.String("interface ");
P.OpenScope("{");
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("}");
}
}
func (P *Printer) DoPointerType(x *AST.PointerType) {
case Scanner.MUL:
P.String("*");
P.Print(x.base);
}
// ----------------------------------------------------------------------------
// Declarations
func (P *Printer) DoBlock(x *AST.Block);
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(")");
}
*/
func (P *Printer) DoImportDecl(x *AST.ImportDecl) {
if x.ident != nil {
P.Print(x.ident);
P.String(" ");
default:
panic("UNREACHABLE");
}
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;
}
// ----------------------------------------------------------------------------
// Expressions
func (P *Printer) DoTypeDecl(x *AST.TypeDecl) {
P.Print(x.ident);
P.String(" ");
P.Print(x.typ);
P.semi = true;
func (P *Printer) Val(tok int, val *Node.Val) {
P.String(val.s); // for now
}
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);
func (P *Printer) Expr(x *Node.Expr) {
if x == nil {
return; // empty expression list
}
P.semi = true;
}
switch x.tok {
case Scanner.IDENT:
P.String(x.ident);
func (P *Printer) DoVarDeclList(x *AST.VarDeclList) {
if x.idents != nil {
P.PrintList(x.idents);
P.String(" ");
}
P.Print(x.typ);
}
case Scanner.INT, Scanner.STRING, Scanner.FLOAT:
P.Val(x.tok, x.val);
func (P *Printer) DoFuncDecl(x *AST.FuncDecl) {
P.String("func ");
if x.typ.recv != nil {
case Scanner.LPAREN:
// calls
P.Expr(x.x);
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);
}
P.Expr(x.y);
P.String(")");
case Scanner.LBRACK:
P.Expr(x.x);
P.String("[");
P.Expr(x.y);
P.String("]");
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;
}
P.CloseScope(")");
}
if P.level == 0 {
P.NewLine();
}
P.newl = true;
}
// ----------------------------------------------------------------------------
// Expressions
func (P *Printer) DoBinary(x *AST.Binary) {
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.Print(x.x);
P.String(" " + Scanner.TokenName(x.tok) + " ");
P.Print(x.y);
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;
}
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);
}
}
}
// ----------------------------------------------------------------------------
// 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,133 +227,218 @@ func (P *Printer) DoAssignment(x *AST.Assignment) {
}
func (P *Printer) PrintControlClause(x *AST.ControlClause) {
if x.has_init {
func (P *Printer) DoIfStat(x *AST.IfStat) {
P.String("if");
P.PrintControlClause(x.ctrl);
P.DoBlock(x.then);
if x.has_else {
P.newl = false;
P.String(" else ");
P.Print(x.else_);
}
}
*/
func (P *Printer) Stat(s *Node.Stat)
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;
}
}
func (P *Printer) Block(list *Node.List) {
P.OpenScope("{");
P.StatementList(list);
P.CloseScope("}");
}
func (P *Printer) ControlClause(s *Node.Stat) {
if s.init != nil {
P.String(" ");
P.Print(x.init);
P.Stat(s.init);
P.semi = true;
P.String("");
}
if x.has_expr {
if s.expr != nil {
P.String(" ");
P.Print(x.expr);
P.Expr(s.expr);
P.semi = false;
}
if x.has_post {
if s.post != nil {
P.semi = true;
P.String(" ");
P.Print(x.post);
P.Stat(s.post);
P.semi = false;
}
P.String(" ");
}
func (P *Printer) DoIfStat(x *AST.IfStat) {
P.String("if");
P.PrintControlClause(x.ctrl);
P.DoBlock(x.then);
if x.has_else {
P.newl = false;
P.String(" else ");
P.Print(x.else_);
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);
func (P *Printer) DoForStat(x *AST.ForStat) {
P.String("for");
P.PrintControlClause(x.ctrl);
P.DoBlock(x.body);
}
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;
func (P *Printer) DoCaseClause(x *AST.CaseClause) {
if x.exprs != nil {
P.String("case ");
P.PrintList(x.exprs);
P.String(":");
} else {
P.String("default:");
}
case Scanner.IF, Scanner.FOR, Scanner.SWITCH, Scanner.SELECT:
P.String(Scanner.TokenName(s.tok));
P.ControlClause(s);
P.Block(s.block);
P.OpenScope("");
for i := 0; i < x.stats.len(); i++ {
P.Print(x.stats.at(i));
P.newl = true;
}
if x.falls {
P.String("fallthrough");
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;
func (P *Printer) DoSwitchStat(x *AST.SwitchStat) {
P.String("switch ");
P.PrintControlClause(x.ctrl);
P.OpenScope("{");
P.indent--;
for i := 0; i < x.cases.len(); i++ {
P.Print(x.cases.at(i));
default:
P.String("<stat>");
P.semi = true;
}
P.indent++;
P.CloseScope("}");
}
func (P *Printer) DoReturnStat(x *AST.ReturnStat) {
P.String("return ");
P.PrintList(x.res);
P.semi = true;
}
// ----------------------------------------------------------------------------
// Declarations
func (P *Printer) DoIncDecStat(x *AST.IncDecStat) {
P.Print(x.expr);
P.String(Scanner.TokenName(x.tok));
P.semi = true;
/*
func (P *Printer) DoImportDecl(x *AST.ImportDecl) {
if x.ident != nil {
P.Print(x.ident);
P.String(" ");
}
P.String(x.file);
}
func (P *Printer) DoControlFlowStat(x *AST.ControlFlowStat) {
P.String(Scanner.TokenName(x.tok));
if x.label != nil {
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.Print(x.label);
P.DoBlock(x.body);
} else {
P.String(" ;");
}
P.semi = true;
P.NewLine();
P.NewLine();
}
func (P *Printer) DoGoStat(x *AST.GoStat) {
P.String("go ");
P.Print(x.expr);
P.semi = true;
func (P *Printer) DoMethodDecl(x *AST.MethodDecl) {
//P.DoIdent(x.ident);
//P.DoFunctionType(x.typ);
}
*/
// ----------------------------------------------------------------------------
// Program
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(" ");
}
func (P *Printer) DoProgram(x *AST.Program) {
P.String("package ");
P.DoIdent(x.ident);
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();
for i := 0; i < x.decls.len(); i++ {
P.Print(x.decls.at(i));
}
P.newl = true;
P.String("");
}
// ----------------------------------------------------------------------------
// Driver
// Program
export func Print(x AST.Node) {
var P Printer;
(&P).Print(x);
print("\n");
func (P *Printer) Program(p *Node.Program) {
P.String("package ");
P.Expr(p.ident);
P.NewLine();
for i := 0; i < p.decls.len(); i++ {
P.Declaration(p.decls.at(i));
}
P.newl = true;
P.String("");
}
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