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