summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr/gri/pretty/ast.go172
-rw-r--r--usr/gri/pretty/parser.go351
-rw-r--r--usr/gri/pretty/printer.go181
3 files changed, 517 insertions, 187 deletions
diff --git a/usr/gri/pretty/ast.go b/usr/gri/pretty/ast.go
index 6376ac929..037a07b26 100644
--- a/usr/gri/pretty/ast.go
+++ b/usr/gri/pretty/ast.go
@@ -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); }
// ----------------------------------------------------------------------------
diff --git a/usr/gri/pretty/parser.go b/usr/gri/pretty/parser.go
index 3aaacd082..8089b5612 100644
--- a/usr/gri/pretty/parser.go
+++ b/usr/gri/pretty/parser.go
@@ -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;
}
diff --git a/usr/gri/pretty/printer.go b/usr/gri/pretty/printer.go
index 8d6078211..902a2fa79 100644
--- a/usr/gri/pretty/printer.go
+++ b/usr/gri/pretty/printer.go
@@ -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