Commit c5a29a6d authored by Robert Griesemer's avatar Robert Griesemer

- more ast buidling and printing

- almost complete language reproduced

R=r
OCL=15801
CL=15801
parent afd04fdb
...@@ -15,10 +15,20 @@ export type Visitor interface { ...@@ -15,10 +15,20 @@ export type Visitor interface {
// Types // Types
DoFunctionType(x *FunctionType); DoFunctionType(x *FunctionType);
DoArrayType(x *ArrayType);
DoStructType(x *StructType);
DoMapType(x *MapType);
DoChannelType(x *ChannelType);
DoInterfaceType(x *InterfaceType);
DoPointerType(x *PointerType);
// Declarations // Declarations
//DoVarDeclList(x *VarDeclList); DoConstDecl(x *ConstDecl);
DoTypeDecl(x *TypeDecl);
DoVarDecl(x *VarDecl);
DoVarDeclList(x *VarDeclList);
DoFuncDecl(x *FuncDecl); DoFuncDecl(x *FuncDecl);
DoDeclaration(x *Declaration);
// Expressions // Expressions
DoBinary(x *Binary); DoBinary(x *Binary);
...@@ -35,8 +45,10 @@ export type Visitor interface { ...@@ -35,8 +45,10 @@ export type Visitor interface {
DoAssignment(x *Assignment); DoAssignment(x *Assignment);
DoIfStat(x *IfStat); DoIfStat(x *IfStat);
DoForStat(x *ForStat); DoForStat(x *ForStat);
DoSwitch(x *Switch); DoCaseClause(x *CaseClause);
DoReturn(x *Return); DoSwitchStat(x *SwitchStat);
DoReturnStat(x *ReturnStat);
DoIncDecStat(x *IncDecStat);
// Program // Program
DoProgram(x *Program); DoProgram(x *Program);
...@@ -60,6 +72,7 @@ export type List struct { ...@@ -60,6 +72,7 @@ export type List struct {
func (p *List) len() int { func (p *List) len() int {
if p == nil { return 0; }
return len(p.a); return len(p.a);
} }
...@@ -122,14 +135,61 @@ export type Type interface { ...@@ -122,14 +135,61 @@ export type Type interface {
} }
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 type ChannelType struct {
pos int; // position of "chan" or "<-" (if before "chan")
elt Type;
}
export type PointerType struct {
pos int; // position of "*"
base Type;
}
export type InterfaceType struct {
}
export type FunctionType struct { export type FunctionType struct {
pos int; // position of "("
recv *VarDeclList; recv *VarDeclList;
params *List; params *List; // list of *VarDeclList
result *List; result *List; // list of *VarDeclList
} }
func (x *FunctionType) Visit(v Visitor) { v.DoFunctionType(x); } 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); }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
...@@ -142,73 +202,99 @@ export type Decl interface { ...@@ -142,73 +202,99 @@ export type Decl interface {
export type VarDeclList struct { export type VarDeclList struct {
idents *List; idents *List;
typ *Node; typ Type;
}
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 { export type FuncDecl struct {
pos int; pos int; // position of "func"
ident *Ident; ident *Ident;
typ *FunctionType; typ *FunctionType;
body *Block; body *Block;
} }
func (x *VarDeclList) Visit(v Visitor) { /*v.DoVarDeclList(x);*/ } func (x *VarDeclList) Visit(v Visitor) { v.DoVarDeclList(x); }
func (x *FuncDecl) Visit(v Visitor) { v.DoFuncDecl(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 *Declaration) Visit(v Visitor) { v.DoDeclaration(x); }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Expressions // Expressions
export type Expr interface {
Visit(x Visitor);
}
export type Selector struct { export type Selector struct {
pos int; pos int; // position of "."
x Expr; x Expr;
field string; field string;
} }
export type Index struct { export type Index struct {
pos int; pos int; // position of "["
x Expr; x Expr;
index Expr; index Expr;
} }
export type Call struct { export type Call struct {
pos int; pos int; // position of "("
fun Expr; fun Expr;
args *List; args *List;
} }
export type Pair struct { export type Pair struct {
pos int; pos int; // position of ":"
x, y Expr; x, y Expr;
} }
export type Binary struct { export type Binary struct {
pos int; pos int; // position of operator tok
tok int; tok int;
x, y Expr; x, y Expr;
} }
export type Unary struct { export type Unary struct {
pos int; pos int; // position of operator tok
tok int; tok int;
x Expr; x Expr;
} }
export type Literal struct { export type Literal struct {
pos int; pos int; // position of literal
tok int; tok int;
val string; val string;
} }
...@@ -232,7 +318,7 @@ export type Stat interface { ...@@ -232,7 +318,7 @@ export type Stat interface {
export type Block struct { export type Block struct {
pos int; pos int; // position of "{"
stats *List; stats *List;
} }
...@@ -243,14 +329,14 @@ export type ExprStat struct { ...@@ -243,14 +329,14 @@ export type ExprStat struct {
export type Assignment struct { export type Assignment struct {
pos int; pos int; // position of assignment token
tok int; tok int;
lhs, rhs *List; lhs, rhs *List;
} }
export type IfStat struct { export type IfStat struct {
pos int; pos int; // position of "if"
init Stat; init Stat;
cond Expr; cond Expr;
then, else_ *Block; then, else_ *Block;
...@@ -258,28 +344,52 @@ export type IfStat struct { ...@@ -258,28 +344,52 @@ export type IfStat struct {
export type ForStat struct { export type ForStat struct {
pos int; pos int; // position of "for"
init Stat;
cond Expr;
post Stat;
body *Block; body *Block;
} }
export type Switch struct { 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 Return struct { export type SwitchStat struct {
pos int; pos int; // position of "switch"
init Stat;
tag Expr;
cases *List; // list of *CaseClause
}
export type ReturnStat struct {
pos int; // position of "return"
res *List; res *List;
} }
export type IncDecStat struct {
pos int; // position of token
tok int;
expr Expr;
}
func (x *Block) Visit(v Visitor) { v.DoBlock(x); } func (x *Block) Visit(v Visitor) { v.DoBlock(x); }
func (x *ExprStat) Visit(v Visitor) { v.DoExprStat(x); } func (x *ExprStat) Visit(v Visitor) { v.DoExprStat(x); }
func (x *Assignment) Visit(v Visitor) { v.DoAssignment(x); } func (x *Assignment) Visit(v Visitor) { v.DoAssignment(x); }
func (x *IfStat) Visit(v Visitor) { v.DoIfStat(x); } func (x *IfStat) Visit(v Visitor) { v.DoIfStat(x); }
func (x *ForStat) Visit(v Visitor) { v.DoForStat(x); } func (x *ForStat) Visit(v Visitor) { v.DoForStat(x); }
func (x *Switch) Visit(v Visitor) { v.DoSwitch(x); } func (x *CaseClause) Visit(v Visitor) { v.DoCaseClause(x); }
func (x *Return) Visit(v Visitor) { v.DoReturn(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); }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
......
...@@ -110,10 +110,10 @@ func (P *Parser) CloseScope() { ...@@ -110,10 +110,10 @@ func (P *Parser) CloseScope() {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Common productions // Common productions
func (P *Parser) TryType() bool; func (P *Parser) TryType() (AST.Type, bool);
func (P *Parser) ParseExpression() AST.Expr; func (P *Parser) ParseExpression() AST.Expr;
func (P *Parser) TryStatement() (AST.Stat, bool); func (P *Parser) TryStatement() (AST.Stat, bool);
func (P *Parser) ParseDeclaration() AST.Decl; func (P *Parser) ParseDeclaration() AST.Node;
func (P *Parser) ParseIdent() *AST.Ident { func (P *Parser) ParseIdent() *AST.Ident {
...@@ -152,22 +152,18 @@ func (P *Parser) ParseIdentList() *AST.List { ...@@ -152,22 +152,18 @@ func (P *Parser) ParseIdentList() *AST.List {
} }
func (P *Parser) ParseQualifiedIdent(ident *AST.Ident) AST.Expr { func (P *Parser) ParseQualifiedIdent() AST.Expr {
P.Trace("QualifiedIdent"); P.Trace("QualifiedIdent");
if ident == nil { var x AST.Expr = P.ParseIdent();
ident = P.ParseIdent();
}
var x AST.Expr = ident;
if P.tok == Scanner.PERIOD { if P.tok == Scanner.PERIOD {
P.Next(); pos := P.pos;
ident2 := P.ParseIdent(); P.Next();
y := P.ParseIdent();
z := new(AST.Selector);
z.pos, z.x, z.field = ident.pos, ident, ident2.val; z := new(AST.Selector);
x = z; z.pos, z.x, z.field = pos, x, y.val;
x = z;
} }
P.Ecart(); P.Ecart();
...@@ -178,55 +174,64 @@ func (P *Parser) ParseQualifiedIdent(ident *AST.Ident) AST.Expr { ...@@ -178,55 +174,64 @@ func (P *Parser) ParseQualifiedIdent(ident *AST.Ident) AST.Expr {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Types // Types
func (P *Parser) ParseType() { func (P *Parser) ParseType() AST.Type {
P.Trace("Type"); P.Trace("Type");
typ := P.TryType(); typ, ok := P.TryType();
if !typ { if !ok {
P.Error(P.pos, "type expected"); P.Error(P.pos, "type expected");
} }
P.Ecart(); P.Ecart();
return typ;
} }
func (P *Parser) ParseVarType() { func (P *Parser) ParseVarType() AST.Type {
P.Trace("VarType"); P.Trace("VarType");
P.ParseType(); typ := P.ParseType();
P.Ecart(); P.Ecart();
return typ;
} }
func (P *Parser) ParseTypeName() AST.Expr { func (P *Parser) ParseTypeName() AST.Type {
P.Trace("TypeName"); P.Trace("TypeName");
x := P.ParseQualifiedIdent(nil); typ := P.ParseQualifiedIdent();
P.Ecart(); P.Ecart();
return x; return typ;
} }
func (P *Parser) ParseArrayType() { func (P *Parser) ParseArrayType() *AST.ArrayType {
P.Trace("ArrayType"); P.Trace("ArrayType");
typ := new(AST.ArrayType);
typ.pos = P.pos;
P.Expect(Scanner.LBRACK); P.Expect(Scanner.LBRACK);
if P.tok != Scanner.RBRACK { if P.tok != Scanner.RBRACK {
// TODO set typ.len // TODO set typ.len
P.ParseExpression(); typ.len_ = P.ParseExpression();
} }
P.Expect(Scanner.RBRACK); P.Expect(Scanner.RBRACK);
P.ParseType(); typ.elt = P.ParseType();
P.Ecart(); P.Ecart();
return typ;
} }
func (P *Parser) ParseChannelType() { func (P *Parser) ParseChannelType() *AST.ChannelType {
P.Trace("ChannelType"); P.Trace("ChannelType");
typ := new(AST.ChannelType);
typ.pos = P.pos;
if P.tok == Scanner.CHAN { if P.tok == Scanner.CHAN {
P.Next(); P.Next();
if P.tok == Scanner.ARROW { if P.tok == Scanner.ARROW {
...@@ -236,9 +241,10 @@ func (P *Parser) ParseChannelType() { ...@@ -236,9 +241,10 @@ func (P *Parser) ParseChannelType() {
P.Expect(Scanner.ARROW); P.Expect(Scanner.ARROW);
P.Expect(Scanner.CHAN); P.Expect(Scanner.CHAN);
} }
P.ParseVarType(); typ.elt = P.ParseVarType();
P.Ecart(); P.Ecart();
return typ;
} }
...@@ -247,7 +253,7 @@ func (P *Parser) ParseVarDeclList() *AST.VarDeclList { ...@@ -247,7 +253,7 @@ func (P *Parser) ParseVarDeclList() *AST.VarDeclList {
res := new(AST.VarDeclList); res := new(AST.VarDeclList);
res.idents = P.ParseIdentList(); res.idents = P.ParseIdentList();
P.ParseVarType(); res.typ = P.ParseVarType();
P.Ecart(); P.Ecart();
return res; return res;
...@@ -337,6 +343,7 @@ func (P *Parser) ParseFunctionType() *AST.FunctionType { ...@@ -337,6 +343,7 @@ func (P *Parser) ParseFunctionType() *AST.FunctionType {
P.level--; P.level--;
typ := new(AST.FunctionType); typ := new(AST.FunctionType);
typ.pos = P.pos;
typ.params = P.ParseParameters(); typ.params = P.ParseParameters();
typ.result = P.ParseResult(); typ.result = P.ParseResult();
...@@ -359,7 +366,7 @@ func (P *Parser) ParseMethodDecl() { ...@@ -359,7 +366,7 @@ func (P *Parser) ParseMethodDecl() {
} }
func (P *Parser) ParseInterfaceType() { func (P *Parser) ParseInterfaceType() *AST.InterfaceType {
P.Trace("InterfaceType"); P.Trace("InterfaceType");
P.Expect(Scanner.INTERFACE); P.Expect(Scanner.INTERFACE);
...@@ -374,31 +381,40 @@ func (P *Parser) ParseInterfaceType() { ...@@ -374,31 +381,40 @@ func (P *Parser) ParseInterfaceType() {
P.Expect(Scanner.RBRACE); P.Expect(Scanner.RBRACE);
P.Ecart(); P.Ecart();
return nil;
} }
func (P *Parser) ParseMapType() { func (P *Parser) ParseMapType() *AST.MapType {
P.Trace("MapType"); P.Trace("MapType");
typ := new(AST.MapType);
typ.pos = P.pos;
P.Expect(Scanner.MAP); P.Expect(Scanner.MAP);
P.Expect(Scanner.LBRACK); P.Expect(Scanner.LBRACK);
P.ParseVarType(); typ.key = P.ParseVarType();
P.Expect(Scanner.RBRACK); P.Expect(Scanner.RBRACK);
P.ParseVarType(); typ.val = P.ParseVarType();
P.Ecart(); P.Ecart();
return typ;
} }
func (P *Parser) ParseStructType() { func (P *Parser) ParseStructType() *AST.StructType {
P.Trace("StructType"); P.Trace("StructType");
typ := new(AST.StructType);
typ.pos = P.pos;
typ.fields = AST.NewList();
P.Expect(Scanner.STRUCT); P.Expect(Scanner.STRUCT);
P.Expect(Scanner.LBRACE); P.Expect(Scanner.LBRACE);
P.OpenScope(); P.OpenScope();
P.level--; P.level--;
for P.tok >= Scanner.IDENT { for P.tok >= Scanner.IDENT {
P.ParseVarDeclList(); typ.fields.Add(P.ParseVarDeclList());
if P.tok != Scanner.RBRACE { if P.tok != Scanner.RBRACE {
P.Expect(Scanner.SEMICOLON); P.Expect(Scanner.SEMICOLON);
} }
...@@ -409,38 +425,44 @@ func (P *Parser) ParseStructType() { ...@@ -409,38 +425,44 @@ func (P *Parser) ParseStructType() {
P.Expect(Scanner.RBRACE); P.Expect(Scanner.RBRACE);
P.Ecart(); P.Ecart();
return typ;
} }
func (P *Parser) ParsePointerType() { func (P *Parser) ParsePointerType() *AST.PointerType {
P.Trace("PointerType"); P.Trace("PointerType");
typ := new(AST.PointerType);
typ.pos = P.pos;
P.Expect(Scanner.MUL); P.Expect(Scanner.MUL);
P.ParseType(); typ.base = P.ParseType();
P.Ecart(); P.Ecart();
return typ;
} }
// Returns false if no type was found. // Returns false if no type was found.
func (P *Parser) TryType() bool { func (P *Parser) TryType() (AST.Type, bool) {
P.Trace("Type (try)"); P.Trace("Type (try)");
var typ AST.Type = AST.NIL;
found := true; found := true;
switch P.tok { switch P.tok {
case Scanner.IDENT: P.ParseTypeName(); case Scanner.IDENT: typ = P.ParseTypeName();
case Scanner.LBRACK: P.ParseArrayType(); case Scanner.LBRACK: typ = P.ParseArrayType();
case Scanner.CHAN, Scanner.ARROW: P.ParseChannelType(); case Scanner.CHAN, Scanner.ARROW: typ = P.ParseChannelType();
case Scanner.INTERFACE: P.ParseInterfaceType(); case Scanner.INTERFACE: typ = P.ParseInterfaceType();
case Scanner.LPAREN: P.ParseFunctionType(); case Scanner.LPAREN: typ = P.ParseFunctionType();
case Scanner.MAP: P.ParseMapType(); case Scanner.MAP: typ = P.ParseMapType();
case Scanner.STRUCT: P.ParseStructType(); case Scanner.STRUCT: typ = P.ParseStructType();
case Scanner.MUL: P.ParsePointerType(); case Scanner.MUL: typ = P.ParsePointerType();
default: found = false; default: found = false;
} }
P.Ecart(); P.Ecart();
return found; return typ, found;
} }
...@@ -623,12 +645,16 @@ func (P *Parser) ParseOperand() AST.Expr { ...@@ -623,12 +645,16 @@ func (P *Parser) ParseOperand() AST.Expr {
z = nil; z = nil;
default: default:
if P.tok != Scanner.IDENT && P.TryType() { if P.tok != Scanner.IDENT {
z = P.ParseCompositeLit(); typ, ok := P.TryType();
} else { if ok {
P.Error(P.pos, "operand expected"); z = P.ParseCompositeLit();
P.Next(); // make progress break;
}
} }
P.Error(P.pos, "operand expected");
P.Next(); // make progress
} }
P.Ecart(); P.Ecart();
...@@ -693,12 +719,17 @@ func (P *Parser) ParseCall(x AST.Expr) AST.Expr { ...@@ -693,12 +719,17 @@ func (P *Parser) ParseCall(x AST.Expr) AST.Expr {
// - exclude "("'s because function types are not allowed and they indicate an expression // - exclude "("'s because function types are not allowed and they indicate an expression
// - still a problem for "new(*T)" (the "*") // - still a problem for "new(*T)" (the "*")
// - possibility: make "new" a keyword again (or disallow "*" types in new) // - possibility: make "new" a keyword again (or disallow "*" types in new)
if P.tok != Scanner.IDENT && P.tok != Scanner.LPAREN && P.TryType() { if P.tok != Scanner.IDENT && P.tok != Scanner.LPAREN {
if P.tok == Scanner.COMMA { typ, ok := P.TryType();
P.Next(); if ok {
if P.tok != Scanner.RPAREN { if P.tok == Scanner.COMMA {
args = P.ParseExpressionList(); P.Next();
if P.tok != Scanner.RPAREN {
args = P.ParseExpressionList();
}
} }
} else {
args = P.ParseExpressionList();
} }
} else { } else {
args = P.ParseExpressionList(); args = P.ParseExpressionList();
...@@ -842,7 +873,15 @@ func (P *Parser) ParseSimpleStat() AST.Stat { ...@@ -842,7 +873,15 @@ func (P *Parser) ParseSimpleStat() AST.Stat {
default: default:
if P.tok == Scanner.INC || P.tok == Scanner.DEC { 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);
} else {
P.Error(P.pos, "more then one operand");
}
P.Next(); P.Next();
stat = s;
} else { } else {
xstat := new(AST.ExprStat); xstat := new(AST.ExprStat);
if x != nil && x.len() > 0 { if x != nil && x.len() > 0 {
...@@ -870,10 +909,10 @@ func (P *Parser) ParseGoStat() { ...@@ -870,10 +909,10 @@ func (P *Parser) ParseGoStat() {
} }
func (P *Parser) ParseReturnStat() *AST.Return { func (P *Parser) ParseReturnStat() *AST.ReturnStat {
P.Trace("ReturnStat"); P.Trace("ReturnStat");
ret := new(AST.Return); ret := new(AST.ReturnStat);
ret.pos = P.pos; ret.pos = P.pos;
P.Expect(Scanner.RETURN); P.Expect(Scanner.RETURN);
...@@ -898,30 +937,57 @@ func (P *Parser) ParseControlFlowStat(tok int) { ...@@ -898,30 +937,57 @@ func (P *Parser) ParseControlFlowStat(tok int) {
} }
func (P *Parser) ParseIfStat() *AST.IfStat { func (P *Parser) ParseStatHeader(keyword int) (AST.Stat, AST.Expr, AST.Stat) {
P.Trace("IfStat"); P.Trace("StatHeader");
x := new(AST.IfStat);
x.pos, x.cond = P.pos, AST.NIL;
var init, cond AST.Node = AST.NIL, AST.NIL; var (
P.Expect(Scanner.IF); init AST.Stat = AST.NIL;
P.OpenScope(); expr AST.Expr = AST.NIL;
post AST.Stat = AST.NIL;
)
has_init, has_expr, has_post := false, false, false;
P.Expect(keyword);
if P.tok != Scanner.LBRACE { if P.tok != Scanner.LBRACE {
if P.tok != Scanner.SEMICOLON { if P.tok != Scanner.SEMICOLON {
init = P.ParseSimpleStat(); init = P.ParseSimpleStat();
has_init = true;
} }
if P.tok == Scanner.SEMICOLON { if P.tok == Scanner.SEMICOLON {
P.Next(); P.Next();
if P.tok != Scanner.LBRACE { if keyword == Scanner.FOR {
cond = P.ParseExpression(); if P.tok != Scanner.SEMICOLON {
expr = P.ParseExpression();
has_expr = true;
}
P.Expect(Scanner.SEMICOLON);
if P.tok != Scanner.LBRACE {
post = P.ParseSimpleStat();
has_post = true;
}
} else { } else {
cond = init; if P.tok != Scanner.LBRACE {
init = AST.NIL; expr = P.ParseExpression();
has_expr = true;
}
} }
} }
} }
x.init, x.cond = init, cond;
P.Ecart();
return init, expr, post;
}
func (P *Parser) ParseIfStat() *AST.IfStat {
P.Trace("IfStat");
x := new(AST.IfStat);
x.pos = P.pos;
var dummy AST.Stat;
x.init, x.cond, dummy = P.ParseStatHeader(Scanner.IF);
x.then = P.ParseBlock(); x.then = P.ParseBlock();
if P.tok == Scanner.ELSE { if P.tok == Scanner.ELSE {
...@@ -936,7 +1002,6 @@ func (P *Parser) ParseIfStat() *AST.IfStat { ...@@ -936,7 +1002,6 @@ func (P *Parser) ParseIfStat() *AST.IfStat {
} }
x.else_ = b; x.else_ = b;
} }
P.CloseScope();
P.Ecart(); P.Ecart();
return x; return x;
...@@ -949,87 +1014,70 @@ func (P *Parser) ParseForStat() *AST.ForStat { ...@@ -949,87 +1014,70 @@ func (P *Parser) ParseForStat() *AST.ForStat {
stat := new(AST.ForStat); stat := new(AST.ForStat);
stat.pos = P.pos; stat.pos = P.pos;
P.Expect(Scanner.FOR); P.ParseStatHeader(Scanner.FOR);
P.OpenScope();
if P.tok != Scanner.LBRACE {
if P.tok != Scanner.SEMICOLON {
P.ParseSimpleStat();
}
if P.tok == Scanner.SEMICOLON {
P.Next();
if P.tok != Scanner.SEMICOLON {
P.ParseExpression();
}
P.Expect(Scanner.SEMICOLON);
if P.tok != Scanner.LBRACE {
P.ParseSimpleStat();
}
}
}
stat.body = P.ParseBlock(); stat.body = P.ParseBlock();
P.CloseScope();
P.Ecart(); P.Ecart();
return stat; return stat;
} }
func (P *Parser) ParseCase() { func (P *Parser) ParseCase() *AST.CaseClause {
P.Trace("Case"); P.Trace("Case");
clause := new(AST.CaseClause);
clause.pos = P.pos;
if P.tok == Scanner.CASE { if P.tok == Scanner.CASE {
P.Next(); P.Next();
P.ParseExpressionList(); clause.exprs = P.ParseExpressionList();
} else { } else {
P.Expect(Scanner.DEFAULT); P.Expect(Scanner.DEFAULT);
} }
P.Expect(Scanner.COLON); P.Expect(Scanner.COLON);
P.Ecart(); P.Ecart();
return clause;
} }
func (P *Parser) ParseCaseClause() { func (P *Parser) ParseCaseClause() *AST.CaseClause {
P.Trace("CaseClause"); P.Trace("CaseClause");
P.ParseCase(); clause := P.ParseCase();
if P.tok != Scanner.FALLTHROUGH && P.tok != Scanner.RBRACE { if P.tok != Scanner.FALLTHROUGH && P.tok != Scanner.RBRACE {
P.ParseStatementList(); clause.stats = P.ParseStatementList();
P.Optional(Scanner.SEMICOLON); P.Optional(Scanner.SEMICOLON);
} }
if P.tok == Scanner.FALLTHROUGH { if P.tok == Scanner.FALLTHROUGH {
P.Next(); P.Next();
clause.falls = true;
P.Optional(Scanner.SEMICOLON); P.Optional(Scanner.SEMICOLON);
} }
P.Ecart(); P.Ecart();
return clause;
} }
func (P *Parser) ParseSwitchStat() { func (P *Parser) ParseSwitchStat() *AST.SwitchStat {
P.Trace("SwitchStat"); P.Trace("SwitchStat");
P.Expect(Scanner.SWITCH); stat := new(AST.SwitchStat);
P.OpenScope(); stat.pos = P.pos;
if P.tok != Scanner.LBRACE { stat.init = AST.NIL;
if P.tok != Scanner.SEMICOLON { stat.cases = AST.NewList();
P.ParseSimpleStat();
} P.ParseStatHeader(Scanner.SWITCH);
if P.tok == Scanner.SEMICOLON {
P.Next();
if P.tok != Scanner.LBRACE {
P.ParseExpression();
}
}
}
P.Expect(Scanner.LBRACE); P.Expect(Scanner.LBRACE);
for P.tok == Scanner.CASE || P.tok == Scanner.DEFAULT { for P.tok == Scanner.CASE || P.tok == Scanner.DEFAULT {
P.ParseCaseClause(); stat.cases.Add(P.ParseCaseClause());
} }
P.Expect(Scanner.RBRACE); P.Expect(Scanner.RBRACE);
P.CloseScope();
P.Ecart(); P.Ecart();
return stat;
} }
...@@ -1109,10 +1157,8 @@ func (P *Parser) TryStatement() (AST.Stat, bool) { ...@@ -1109,10 +1157,8 @@ func (P *Parser) TryStatement() (AST.Stat, bool) {
var stat AST.Stat = AST.NIL; var stat AST.Stat = AST.NIL;
res := true; res := true;
switch P.tok { switch P.tok {
case Scanner.CONST: fallthrough; case Scanner.CONST, Scanner.TYPE, Scanner.VAR:
case Scanner.TYPE: fallthrough; stat = P.ParseDeclaration();
case Scanner.VAR:
P.ParseDeclaration();
case Scanner.FUNC: case Scanner.FUNC:
// for now we do not allow local function declarations // for now we do not allow local function declarations
fallthrough; fallthrough;
...@@ -1131,7 +1177,7 @@ func (P *Parser) TryStatement() (AST.Stat, bool) { ...@@ -1131,7 +1177,7 @@ func (P *Parser) TryStatement() (AST.Stat, bool) {
case Scanner.FOR: case Scanner.FOR:
stat = P.ParseForStat(); stat = P.ParseForStat();
case Scanner.SWITCH: case Scanner.SWITCH:
P.ParseSwitchStat(); stat = P.ParseSwitchStat();
case Scanner.RANGE: case Scanner.RANGE:
P.ParseRangeStat(); P.ParseRangeStat();
case Scanner.SELECT: case Scanner.SELECT:
...@@ -1173,70 +1219,83 @@ func (P *Parser) ParseImportSpec() { ...@@ -1173,70 +1219,83 @@ func (P *Parser) ParseImportSpec() {
} }
func (P *Parser) ParseConstSpec(exported bool) { func (P *Parser) ParseConstSpec(exported bool) AST.Decl {
P.Trace("ConstSpec"); P.Trace("ConstSpec");
list := P.ParseIdent(); decl := new(AST.ConstDecl);
P.TryType(); decl.ident = P.ParseIdent();
var ok bool;
decl.typ, ok = P.TryType();
if P.tok == Scanner.ASSIGN { if P.tok == Scanner.ASSIGN {
P.Next(); P.Next();
P.ParseExpressionList(); decl.val = P.ParseExpression();
} }
P.Ecart(); P.Ecart();
return decl;
} }
func (P *Parser) ParseTypeSpec(exported bool) { func (P *Parser) ParseTypeSpec(exported bool) AST.Decl {
P.Trace("TypeSpec"); P.Trace("TypeSpec");
ident := P.ParseIdent(); decl := new(AST.TypeDecl);
P.ParseType(); decl.ident = P.ParseIdent();
decl.typ = P.ParseType();
P.Ecart(); P.Ecart();
return decl;
} }
func (P *Parser) ParseVarSpec(exported bool) { func (P *Parser) ParseVarSpec(exported bool) AST.Decl {
P.Trace("VarSpec"); P.Trace("VarSpec");
P.ParseIdentList(); decl := new(AST.VarDecl);
decl.idents = P.ParseIdentList();
if P.tok == Scanner.ASSIGN { if P.tok == Scanner.ASSIGN {
P.Next(); P.Next();
P.ParseExpressionList(); decl.vals = P.ParseExpressionList();
} else { } else {
P.ParseVarType(); decl.typ = P.ParseVarType();
if P.tok == Scanner.ASSIGN { if P.tok == Scanner.ASSIGN {
P.Next(); P.Next();
P.ParseExpressionList(); decl.vals = P.ParseExpressionList();
} }
} }
P.Ecart(); P.Ecart();
return decl;
} }
// TODO With method variables, we wouldn't need this dispatch function. // TODO With method variables, we wouldn't need this dispatch function.
func (P *Parser) ParseSpec(exported bool, keyword int) { func (P *Parser) ParseSpec(exported bool, keyword int) AST.Decl {
var decl AST.Decl = AST.NIL;
switch keyword { switch keyword {
case Scanner.IMPORT: P.ParseImportSpec(); case Scanner.IMPORT: P.ParseImportSpec();
case Scanner.CONST: P.ParseConstSpec(exported); case Scanner.CONST: decl = P.ParseConstSpec(exported);
case Scanner.TYPE: P.ParseTypeSpec(exported); case Scanner.TYPE: decl = P.ParseTypeSpec(exported);
case Scanner.VAR: P.ParseVarSpec(exported); case Scanner.VAR: decl = P.ParseVarSpec(exported);
default: panic("UNREACHABLE"); default: panic("UNREACHABLE");
} }
return decl;
} }
func (P *Parser) ParseDecl(exported bool, keyword int) { func (P *Parser) ParseDecl(exported bool, keyword int) *AST.Declaration {
P.Trace("Decl"); P.Trace("Decl");
decl := new(AST.Declaration);
decl.decls = AST.NewList();
decl.pos, decl.tok = P.pos, P.tok;
P.Expect(keyword); P.Expect(keyword);
if P.tok == Scanner.LPAREN { if P.tok == Scanner.LPAREN {
P.Next(); P.Next();
for P.tok != Scanner.RPAREN { for P.tok != Scanner.RPAREN {
P.ParseSpec(exported, keyword); decl.decls.Add(P.ParseSpec(exported, keyword));
if P.tok != Scanner.RPAREN { if P.tok != Scanner.RPAREN {
// P.Expect(Scanner.SEMICOLON); // P.Expect(Scanner.SEMICOLON);
P.Optional(Scanner.SEMICOLON); // TODO this seems wrong! (needed for math.go) P.Optional(Scanner.SEMICOLON); // TODO this seems wrong! (needed for math.go)
...@@ -1244,10 +1303,11 @@ func (P *Parser) ParseDecl(exported bool, keyword int) { ...@@ -1244,10 +1303,11 @@ func (P *Parser) ParseDecl(exported bool, keyword int) {
} }
P.Next(); // consume ")" P.Next(); // consume ")"
} else { } else {
P.ParseSpec(exported, keyword); decl.decls.Add(P.ParseSpec(exported, keyword));
} }
P.Ecart(); P.Ecart();
return decl;
} }
...@@ -1326,10 +1386,12 @@ func (P *Parser) ParseExportDecl() { ...@@ -1326,10 +1386,12 @@ func (P *Parser) ParseExportDecl() {
} }
func (P *Parser) ParseDeclaration() AST.Decl { func (P *Parser) ParseDeclaration() AST.Node {
P.Trace("Declaration"); P.Trace("Declaration");
indent := P.indent; indent := P.indent;
var node AST.Node;
exported := false; exported := false;
if P.tok == Scanner.EXPORT { if P.tok == Scanner.EXPORT {
if P.level == 0 { if P.level == 0 {
...@@ -1340,12 +1402,11 @@ func (P *Parser) ParseDeclaration() AST.Decl { ...@@ -1340,12 +1402,11 @@ func (P *Parser) ParseDeclaration() AST.Decl {
P.Next(); P.Next();
} }
var x AST.Decl = AST.NIL;
switch P.tok { switch P.tok {
case Scanner.CONST, Scanner.TYPE, Scanner.VAR: case Scanner.CONST, Scanner.TYPE, Scanner.VAR:
P.ParseDecl(exported, P.tok); node = P.ParseDecl(exported, P.tok);
case Scanner.FUNC: case Scanner.FUNC:
x = P.ParseFuncDecl(exported); node = P.ParseFuncDecl(exported);
case Scanner.EXPORT: case Scanner.EXPORT:
if exported { if exported {
P.Error(P.pos, "cannot mark export declaration for export"); P.Error(P.pos, "cannot mark export declaration for export");
...@@ -1365,7 +1426,7 @@ func (P *Parser) ParseDeclaration() AST.Decl { ...@@ -1365,7 +1426,7 @@ func (P *Parser) ParseDeclaration() AST.Decl {
panic("imbalanced tracing code (Declaration)"); panic("imbalanced tracing code (Declaration)");
} }
P.Ecart(); P.Ecart();
return x; return node;
} }
......
...@@ -36,13 +36,11 @@ func (P *Printer) Print(x AST.Node) { ...@@ -36,13 +36,11 @@ func (P *Printer) Print(x AST.Node) {
func (P *Printer) PrintList(p *AST.List) { func (P *Printer) PrintList(p *AST.List) {
if p != nil { for i := 0; i < p.len(); i++ {
for i := 0; i < p.len(); i++ { if i > 0 {
if i > 0 { P.String(", ");
P.String(", ");
}
P.Print(p.at(i));
} }
P.Print(p.at(i));
} }
} }
...@@ -52,7 +50,6 @@ func (P *Printer) PrintList(p *AST.List) { ...@@ -52,7 +50,6 @@ func (P *Printer) PrintList(p *AST.List) {
func (P *Printer) DoNil(x *AST.Nil) { func (P *Printer) DoNil(x *AST.Nil) {
P.String("?"); P.String("?");
P.NewLine(0);
} }
...@@ -76,14 +73,89 @@ func (P *Printer) DoFunctionType(x *AST.FunctionType) { ...@@ -76,14 +73,89 @@ func (P *Printer) DoFunctionType(x *AST.FunctionType) {
} }
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 {");
if x.fields.len() > 0 {
P.NewLine(1);
for i := 0; i < x.fields.len(); i++ {
if i > 0 {
P.NewLine(0);
}
P.Print(x.fields.at(i));
P.String(";");
}
P.NewLine(-1);
}
P.String("}");
}
func (P *Printer) DoMapType(x *AST.MapType) {
}
func (P *Printer) DoChannelType(x *AST.ChannelType) {
P.String("chan ");
P.Print(x.elt);
}
func (P *Printer) DoInterfaceType(x *AST.InterfaceType) {
}
func (P *Printer) DoPointerType(x *AST.PointerType) {
P.String("*");
P.Print(x.base);
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Declarations // Declarations
func (P *Printer) DoBlock(x *AST.Block); func (P *Printer) DoBlock(x *AST.Block);
//func (P *Printer) DoVarDeclList(x *VarDeclList) { func (P *Printer) DoConstDecl(x *AST.ConstDecl) {
//} P.Print(x.ident);
P.String(" ");
P.Print(x.typ);
P.String(" = ");
P.Print(x.val);
}
func (P *Printer) DoTypeDecl(x *AST.TypeDecl) {
P.Print(x.ident);
P.String(" ");
P.Print(x.typ);
}
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) DoVarDeclList(x *AST.VarDeclList) {
P.PrintList(x.idents);
P.String(" ");
P.Print(x.typ);
}
func (P *Printer) DoFuncDecl(x *AST.FuncDecl) { func (P *Printer) DoFuncDecl(x *AST.FuncDecl) {
...@@ -106,6 +178,30 @@ func (P *Printer) DoFuncDecl(x *AST.FuncDecl) { ...@@ -106,6 +178,30 @@ func (P *Printer) DoFuncDecl(x *AST.FuncDecl) {
} }
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.String("(");
P.NewLine(1);
for i := 0; i < x.decls.len(); i++ {
if i > 0 {
P.NewLine(0);
}
P.Print(x.decls.at(i));
}
P.NewLine(-1);
P.String(")");
}
P.NewLine(0);
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Expressions // Expressions
...@@ -214,18 +310,81 @@ func (P *Printer) DoForStat(x *AST.ForStat) { ...@@ -214,18 +310,81 @@ func (P *Printer) DoForStat(x *AST.ForStat) {
} }
func (P *Printer) DoSwitch(x *AST.Switch) { /*
func AnalyzeCase(x *AST.SwitchStat) bool {
for i := 0; i < x.cases.len(); i++ {
clause := x.cases.at(i).(AST.CaseClause);
if clause.stats.len() > 1 {
return false;
}
}
return 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:");
}
n := x.stats.len();
m := n;
if x.falls {
m++;
}
if m == 0 {
P.NewLine(0);
} else {
P.NewLine(1);
for i := 0; i < n; i++ {
if i > 0 {
P.NewLine(0);
}
P.Print(x.stats.at(i));
}
if x.falls {
if n > 0 {
P.NewLine(0);
}
P.String("fallthrough;");
}
P.NewLine(-1);
}
}
func (P *Printer) DoSwitchStat(x *AST.SwitchStat) {
P.String("switch "); P.String("switch ");
P.String("{");
P.NewLine(0);
for i := 0; i < x.cases.len(); i++ {
P.Print(x.cases.at(i));
}
P.NewLine(0);
P.String("}");
} }
func (P *Printer) DoReturn(x *AST.Return) { func (P *Printer) DoReturnStat(x *AST.ReturnStat) {
P.String("return "); P.String("return ");
P.PrintList(x.res); P.PrintList(x.res);
P.String(";"); P.String(";");
} }
func (P *Printer) DoIncDecStat(x *AST.IncDecStat) {
P.Print(x.expr);
P.String(Scanner.TokenName(x.tok));
P.String(";");
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Program // Program
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment