| // Copyright 2009 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package AST |
| |
| import ( |
| "vector"; |
| "token"; |
| SymbolTable "symboltable"; |
| ) |
| |
| |
| type ( |
| Block struct; |
| Expr interface; |
| Decl interface; |
| ) |
| |
| |
| // ---------------------------------------------------------------------------- |
| // Support |
| |
| func assert(pred bool) { |
| if !pred { |
| panic("assertion failed"); |
| } |
| } |
| |
| |
| // ---------------------------------------------------------------------------- |
| // All nodes have a source position and a token. |
| |
| type Node struct { |
| Pos int; // source position (< 0 => unknown position) |
| Tok int; // identifying token |
| } |
| |
| |
| // ---------------------------------------------------------------------------- |
| // Expressions |
| |
| const /* channel mode */ ( |
| FULL = iota; |
| SEND; |
| RECV; |
| ) |
| |
| |
| type ( |
| ExprVisitor interface; |
| Signature struct; |
| |
| Expr interface { |
| Pos() int; |
| Visit(v ExprVisitor); |
| }; |
| |
| BadExpr struct { |
| Pos_ int; |
| }; |
| |
| Ident struct { |
| Pos_ int; |
| Obj *SymbolTable.Object; |
| }; |
| |
| BinaryExpr struct { |
| Pos_ int; |
| Tok int; |
| X, Y Expr; |
| }; |
| |
| UnaryExpr struct { |
| Pos_ int; |
| Tok int; |
| X Expr; |
| }; |
| |
| BasicLit struct { |
| Pos_ int; |
| Tok int; |
| Val string |
| }; |
| |
| FunctionLit struct { |
| Pos_ int; // position of "func" |
| Typ *Signature; |
| Body *Block; |
| }; |
| |
| Group struct { |
| Pos_ int; // position of "(" |
| X Expr; |
| }; |
| |
| Selector struct { |
| Pos_ int; // position of "." |
| X Expr; |
| Sel *Ident; |
| }; |
| |
| TypeGuard struct { |
| Pos_ int; // position of "." |
| X Expr; |
| Typ Expr; |
| }; |
| |
| Index struct { |
| Pos_ int; // position of "[" |
| X, I Expr; |
| }; |
| |
| Call struct { |
| Pos_ int; // position of "(" or "{" |
| Tok int; |
| F, Args Expr |
| }; |
| |
| // Type literals are treated like expressions. |
| Ellipsis struct { // neither a type nor an expression |
| Pos_ int; |
| }; |
| |
| ArrayType struct { |
| Pos_ int; // position of "[" |
| Len Expr; |
| Elt Expr; |
| }; |
| |
| Field struct { |
| Idents []*Ident; |
| Typ Expr; |
| Tag Expr; // nil = no tag |
| }; |
| |
| StructType struct { |
| Pos_ int; // position of "struct" |
| Fields []*Field; |
| End int; // position of "}", End == 0 if forward declaration |
| }; |
| |
| PointerType struct { |
| Pos_ int; // position of "*" |
| Base Expr; |
| }; |
| |
| Signature struct { |
| Params []*Field; |
| Result []*Field; |
| }; |
| |
| FunctionType struct { |
| Pos_ int; // position of "func" |
| Sig *Signature; |
| }; |
| |
| InterfaceType struct { |
| Pos_ int; // position of "interface" |
| Methods []*Field; |
| End int; // position of "}", End == 0 if forward declaration |
| }; |
| |
| SliceType struct { |
| Pos_ int; // position of "[" |
| }; |
| |
| MapType struct { |
| Pos_ int; // position of "map" |
| Key Expr; |
| Val Expr; |
| }; |
| |
| ChannelType struct { |
| Pos_ int; // position of "chan" or "<-" |
| Mode int; |
| Val Expr; |
| }; |
| ) |
| |
| |
| type ExprVisitor interface { |
| DoBadExpr(x *BadExpr); |
| DoIdent(x *Ident); |
| DoBinaryExpr(x *BinaryExpr); |
| DoUnaryExpr(x *UnaryExpr); |
| DoBasicLit(x *BasicLit); |
| DoFunctionLit(x *FunctionLit); |
| DoGroup(x *Group); |
| DoSelector(x *Selector); |
| DoTypeGuard(x *TypeGuard); |
| DoIndex(x *Index); |
| DoCall(x *Call); |
| |
| DoEllipsis(x *Ellipsis); |
| DoArrayType(x *ArrayType); |
| DoStructType(x *StructType); |
| DoPointerType(x *PointerType); |
| DoFunctionType(x *FunctionType); |
| DoInterfaceType(x *InterfaceType); |
| DoSliceType(x *SliceType); |
| DoMapType(x *MapType); |
| DoChannelType(x *ChannelType); |
| } |
| |
| |
| // TODO replace these with an embedded field |
| func (x *BadExpr) Pos() int { return x.Pos_; } |
| func (x *Ident) Pos() int { return x.Pos_; } |
| func (x *BinaryExpr) Pos() int { return x.Pos_; } |
| func (x *UnaryExpr) Pos() int { return x.Pos_; } |
| func (x *BasicLit) Pos() int { return x.Pos_; } |
| func (x *FunctionLit) Pos() int { return x.Pos_; } |
| func (x *Group) Pos() int { return x.Pos_; } |
| func (x *Selector) Pos() int { return x.Pos_; } |
| func (x *TypeGuard) Pos() int { return x.Pos_; } |
| func (x *Index) Pos() int { return x.Pos_; } |
| func (x *Call) Pos() int { return x.Pos_; } |
| |
| func (x *Ellipsis) Pos() int { return x.Pos_; } |
| func (x *ArrayType) Pos() int { return x.Pos_; } |
| func (x *StructType) Pos() int { return x.Pos_; } |
| func (x *PointerType) Pos() int { return x.Pos_; } |
| func (x *FunctionType) Pos() int { return x.Pos_; } |
| func (x *InterfaceType) Pos() int { return x.Pos_; } |
| func (x *SliceType) Pos() int { return x.Pos_; } |
| func (x *MapType) Pos() int { return x.Pos_; } |
| func (x *ChannelType) Pos() int { return x.Pos_; } |
| |
| |
| func (x *BadExpr) Visit(v ExprVisitor) { v.DoBadExpr(x); } |
| func (x *Ident) Visit(v ExprVisitor) { v.DoIdent(x); } |
| func (x *BinaryExpr) Visit(v ExprVisitor) { v.DoBinaryExpr(x); } |
| func (x *UnaryExpr) Visit(v ExprVisitor) { v.DoUnaryExpr(x); } |
| func (x *BasicLit) Visit(v ExprVisitor) { v.DoBasicLit(x); } |
| func (x *FunctionLit) Visit(v ExprVisitor) { v.DoFunctionLit(x); } |
| func (x *Group) Visit(v ExprVisitor) { v.DoGroup(x); } |
| func (x *Selector) Visit(v ExprVisitor) { v.DoSelector(x); } |
| func (x *TypeGuard) Visit(v ExprVisitor) { v.DoTypeGuard(x); } |
| func (x *Index) Visit(v ExprVisitor) { v.DoIndex(x); } |
| func (x *Call) Visit(v ExprVisitor) { v.DoCall(x); } |
| |
| func (x *Ellipsis) Visit(v ExprVisitor) { v.DoEllipsis(x); } |
| func (x *ArrayType) Visit(v ExprVisitor) { v.DoArrayType(x); } |
| func (x *StructType) Visit(v ExprVisitor) { v.DoStructType(x); } |
| func (x *PointerType) Visit(v ExprVisitor) { v.DoPointerType(x); } |
| func (x *FunctionType) Visit(v ExprVisitor) { v.DoFunctionType(x); } |
| func (x *InterfaceType) Visit(v ExprVisitor) { v.DoInterfaceType(x); } |
| func (x *SliceType) Visit(v ExprVisitor) { v.DoSliceType(x); } |
| func (x *MapType) Visit(v ExprVisitor) { v.DoMapType(x); } |
| func (x *ChannelType) Visit(v ExprVisitor) { v.DoChannelType(x); } |
| |
| |
| |
| // Length of a comma-separated expression list. |
| func ExprLen(x Expr) int { |
| if x == nil { |
| return 0; |
| } |
| n := 1; |
| for { |
| if p, ok := x.(*BinaryExpr); ok && p.Tok == token.COMMA { |
| n++; |
| x = p.Y; |
| } else { |
| break; |
| } |
| } |
| return n; |
| } |
| |
| |
| func ExprAt(x Expr, i int) Expr { |
| for j := 0; j < i; j++ { |
| assert(x.(*BinaryExpr).Tok == token.COMMA); |
| x = x.(*BinaryExpr).Y; |
| } |
| if t, is_binary := x.(*BinaryExpr); is_binary && t.Tok == token.COMMA { |
| x = t.X; |
| } |
| return x; |
| } |
| |
| |
| // ---------------------------------------------------------------------------- |
| // Blocks |
| // |
| // Syntactic constructs of the form: |
| // |
| // "{" StatementList "}" |
| // ":" StatementList |
| |
| type Block struct { |
| Node; |
| List *vector.Vector; |
| End int; // position of closing "}" if present |
| } |
| |
| |
| func NewBlock(pos, tok int) *Block { |
| assert(tok == token.LBRACE || tok == token.COLON); |
| b := new(Block); |
| b.Pos, b.Tok, b.List = pos, tok, vector.New(0); |
| return b; |
| } |
| |
| |
| // ---------------------------------------------------------------------------- |
| // Statements |
| |
| type ( |
| StatVisitor interface; |
| |
| Stat interface { |
| Visit(v StatVisitor); |
| }; |
| |
| BadStat struct { |
| Pos int; |
| }; |
| |
| LabelDecl struct { |
| Pos int; // position of ":" |
| Label *Ident; |
| }; |
| |
| DeclarationStat struct { |
| Decl Decl; |
| }; |
| |
| ExpressionStat struct { |
| Pos int; // position of Tok |
| Tok int; // INC, DEC, RETURN, GO, DEFER |
| Expr Expr; |
| }; |
| |
| CompositeStat struct { |
| Body *Block; |
| }; |
| |
| IfStat struct { |
| Pos int; // position of "if" |
| Init Stat; |
| Cond Expr; |
| Body *Block; |
| Else Stat; |
| }; |
| |
| ForStat struct { |
| Pos int; // position of "for" |
| Init Stat; |
| Cond Expr; |
| Post Stat; |
| Body *Block; |
| }; |
| |
| CaseClause struct { |
| Pos int; // position for "case" or "default" |
| Expr Expr; // nil means default case |
| Body *Block; |
| }; |
| |
| SwitchStat struct { |
| Pos int; // position of "switch" |
| Init Stat; |
| Tag Expr; |
| Body *Block; |
| }; |
| |
| SelectStat struct { |
| Pos int; // position of "select" |
| Body *Block; |
| }; |
| |
| ControlFlowStat struct { |
| Pos int; // position of Tok |
| Tok int; // BREAK, CONTINUE, GOTO, FALLTHROUGH |
| Label *Ident; // if any, or nil |
| }; |
| |
| EmptyStat struct { |
| Pos int; // position of ";" |
| }; |
| ) |
| |
| |
| type StatVisitor interface { |
| DoBadStat(s *BadStat); |
| DoLabelDecl(s *LabelDecl); |
| DoDeclarationStat(s *DeclarationStat); |
| DoExpressionStat(s *ExpressionStat); |
| DoCompositeStat(s *CompositeStat); |
| DoIfStat(s *IfStat); |
| DoForStat(s *ForStat); |
| DoCaseClause(s *CaseClause); |
| DoSwitchStat(s *SwitchStat); |
| DoSelectStat(s *SelectStat); |
| DoControlFlowStat(s *ControlFlowStat); |
| DoEmptyStat(s *EmptyStat); |
| } |
| |
| |
| func (s *BadStat) Visit(v StatVisitor) { v.DoBadStat(s); } |
| func (s *LabelDecl) Visit(v StatVisitor) { v.DoLabelDecl(s); } |
| func (s *DeclarationStat) Visit(v StatVisitor) { v.DoDeclarationStat(s); } |
| func (s *ExpressionStat) Visit(v StatVisitor) { v.DoExpressionStat(s); } |
| func (s *CompositeStat) Visit(v StatVisitor) { v.DoCompositeStat(s); } |
| func (s *IfStat) Visit(v StatVisitor) { v.DoIfStat(s); } |
| func (s *ForStat) Visit(v StatVisitor) { v.DoForStat(s); } |
| func (s *CaseClause) Visit(v StatVisitor) { v.DoCaseClause(s); } |
| func (s *SwitchStat) Visit(v StatVisitor) { v.DoSwitchStat(s); } |
| func (s *SelectStat) Visit(v StatVisitor) { v.DoSelectStat(s); } |
| func (s *ControlFlowStat) Visit(v StatVisitor) { v.DoControlFlowStat(s); } |
| func (s *EmptyStat) Visit(v StatVisitor) { v.DoEmptyStat(s); } |
| |
| |
| // ---------------------------------------------------------------------------- |
| // Declarations |
| |
| type ( |
| DeclVisitor interface; |
| |
| Decl interface { |
| Visit(v DeclVisitor); |
| }; |
| |
| BadDecl struct { |
| Pos int; |
| }; |
| |
| ImportDecl struct { |
| Pos int; // if > 0: position of "import" |
| Ident *Ident; |
| Path Expr; |
| }; |
| |
| ConstDecl struct { |
| Pos int; // if > 0: position of "const" |
| Idents []*Ident; |
| Typ Expr; |
| Vals Expr; |
| }; |
| |
| TypeDecl struct { |
| Pos int; // if > 0: position of "type" |
| Ident *Ident; |
| Typ Expr; |
| }; |
| |
| VarDecl struct { |
| Pos int; // if > 0: position of "var" |
| Idents []*Ident; |
| Typ Expr; |
| Vals Expr; |
| }; |
| |
| FuncDecl struct { |
| Pos_ int; // position of "func" |
| Recv *Field; |
| Ident *Ident; |
| Sig *Signature; |
| Body *Block; |
| }; |
| |
| DeclList struct { |
| Pos int; // position of Tok |
| Tok int; |
| List []Decl; |
| End int; |
| }; |
| ) |
| |
| |
| type DeclVisitor interface { |
| DoBadDecl(d *BadDecl); |
| DoImportDecl(d *ImportDecl); |
| DoConstDecl(d *ConstDecl); |
| DoTypeDecl(d *TypeDecl); |
| DoVarDecl(d *VarDecl); |
| DoFuncDecl(d *FuncDecl); |
| DoDeclList(d *DeclList); |
| } |
| |
| |
| //func (d *Decl) Visit(v DeclVisitor) { v.DoDecl(d); } |
| func (d *BadDecl) Visit(v DeclVisitor) { v.DoBadDecl(d); } |
| func (d *ImportDecl) Visit(v DeclVisitor) { v.DoImportDecl(d); } |
| func (d *ConstDecl) Visit(v DeclVisitor) { v.DoConstDecl(d); } |
| func (d *TypeDecl) Visit(v DeclVisitor) { v.DoTypeDecl(d); } |
| func (d *VarDecl) Visit(v DeclVisitor) { v.DoVarDecl(d); } |
| func (d *FuncDecl) Visit(v DeclVisitor) { v.DoFuncDecl(d); } |
| func (d *DeclList) Visit(v DeclVisitor) { v.DoDeclList(d); } |
| |
| |
| // ---------------------------------------------------------------------------- |
| // Program |
| |
| type Comment struct { |
| Pos int; |
| Text string; |
| } |
| |
| |
| func NewComment(pos int, text string) *Comment { |
| c := new(Comment); |
| c.Pos, c.Text = pos, text; |
| return c; |
| } |
| |
| |
| type Program struct { |
| Pos int; // tok is token.PACKAGE |
| Ident Expr; |
| Decls []Decl; |
| Comments *vector.Vector; |
| } |
| |
| |
| func NewProgram(pos int) *Program { |
| p := new(Program); |
| p.Pos = pos; |
| return p; |
| } |