]> Cypherpunks repositories - gostls13.git/commitdiff
- more ast buidling and printing
authorRobert Griesemer <gri@golang.org>
Wed, 24 Sep 2008 22:50:28 +0000 (15:50 -0700)
committerRobert Griesemer <gri@golang.org>
Wed, 24 Sep 2008 22:50:28 +0000 (15:50 -0700)
- almost complete language reproduced

R=r
OCL=15801
CL=15801

usr/gri/pretty/ast.go
usr/gri/pretty/parser.go
usr/gri/pretty/printer.go

index 6376ac929fe8a79745b57838720f2647b85fb9e7..037a07b261ab184b6f2d9055d5b5fb684ff177fb 100644 (file)
@@ -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 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 {
+       pos int;  // position of "("
        recv *VarDeclList;
-       params *List;
-       result *List;
+       params *List;  // list of *VarDeclList
+       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 {
 
 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); }
 
 
 // ----------------------------------------------------------------------------
index 3aaacd0821f17f702c881660c85a9bfda35951a0..8089b561262a469e9a859dbda28f6dfe9ece2b47 100644 (file)
@@ -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) ParseIfStat() *AST.IfStat {
-       P.Trace("IfStat");
-
-       x := new(AST.IfStat);
-       x.pos, x.cond = P.pos, AST.NIL;
+func (P *Parser) ParseStatHeader(keyword int) (AST.Stat, AST.Expr, AST.Stat) {
+       P.Trace("StatHeader");
        
-       var init, cond AST.Node = AST.NIL, AST.NIL;
-       P.Expect(Scanner.IF);
-       P.OpenScope();
+       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 P.tok != Scanner.LBRACE {
-                               cond = P.ParseExpression();
+                       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 {
-                               cond = init;
-                               init = AST.NIL;
+                               if P.tok != Scanner.LBRACE {
+                                       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();
        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;
 }
 
 
index 8d6078211945096a72e89d889f63eda70ec970c7..902a2fa79a2a302d13ef954fc1fe3bca6a3e1201 100644 (file)
@@ -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) {
+/*
+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("{");
+       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.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