Commit 1595a194 authored by Robert Griesemer's avatar Robert Griesemer

today's snapshot: steps towards using interfaces for statements in ast

R=r
OCL=24380
CL=24380
parent 6aabf31a
...@@ -18,7 +18,7 @@ type ( ...@@ -18,7 +18,7 @@ type (
Block struct; Block struct;
Expr interface; Expr interface;
Stat struct; StatImpl struct;
Decl struct; Decl struct;
) )
...@@ -350,11 +350,11 @@ func NewBlock(pos, tok int) *Block { ...@@ -350,11 +350,11 @@ func NewBlock(pos, tok int) *Block {
// Expressions // Expressions
type ( type (
Visitor interface; ExprVisitor interface;
Expr interface { Expr interface {
Pos() int; Pos() int;
Visit(v Visitor); Visit(v ExprVisitor);
}; };
BadExpr struct { BadExpr struct {
...@@ -421,7 +421,7 @@ type ( ...@@ -421,7 +421,7 @@ type (
) )
type Visitor interface { type ExprVisitor interface {
DoBadExpr(x *BadExpr); DoBadExpr(x *BadExpr);
DoIdent(x *Ident); DoIdent(x *Ident);
DoBinaryExpr(x *BinaryExpr); DoBinaryExpr(x *BinaryExpr);
...@@ -451,18 +451,18 @@ func (x *Index) Pos() int { return x.Pos_; } ...@@ -451,18 +451,18 @@ func (x *Index) Pos() int { return x.Pos_; }
func (x *Call) Pos() int { return x.Pos_; } func (x *Call) Pos() int { return x.Pos_; }
func (x *BadExpr) Visit(v Visitor) { v.DoBadExpr(x); } func (x *BadExpr) Visit(v ExprVisitor) { v.DoBadExpr(x); }
func (x *Ident) Visit(v Visitor) { v.DoIdent(x); } func (x *Ident) Visit(v ExprVisitor) { v.DoIdent(x); }
func (x *BinaryExpr) Visit(v Visitor) { v.DoBinaryExpr(x); } func (x *BinaryExpr) Visit(v ExprVisitor) { v.DoBinaryExpr(x); }
func (x *UnaryExpr) Visit(v Visitor) { v.DoUnaryExpr(x); } func (x *UnaryExpr) Visit(v ExprVisitor) { v.DoUnaryExpr(x); }
func (x *BasicLit) Visit(v Visitor) { v.DoBasicLit(x); } func (x *BasicLit) Visit(v ExprVisitor) { v.DoBasicLit(x); }
func (x *FunctionLit) Visit(v Visitor) { v.DoFunctionLit(x); } func (x *FunctionLit) Visit(v ExprVisitor) { v.DoFunctionLit(x); }
func (x *CompositeLit) Visit(v Visitor) { v.DoCompositeLit(x); } func (x *CompositeLit) Visit(v ExprVisitor) { v.DoCompositeLit(x); }
func (x *TypeLit) Visit(v Visitor) { v.DoTypeLit(x); } func (x *TypeLit) Visit(v ExprVisitor) { v.DoTypeLit(x); }
func (x *Selector) Visit(v Visitor) { v.DoSelector(x); } func (x *Selector) Visit(v ExprVisitor) { v.DoSelector(x); }
func (x *TypeGuard) Visit(v Visitor) { v.DoTypeGuard(x); } func (x *TypeGuard) Visit(v ExprVisitor) { v.DoTypeGuard(x); }
func (x *Index) Visit(v Visitor) { v.DoIndex(x); } func (x *Index) Visit(v ExprVisitor) { v.DoIndex(x); }
func (x *Call) Visit(v Visitor) { v.DoCall(x); } func (x *Call) Visit(v ExprVisitor) { v.DoCall(x); }
...@@ -518,23 +518,112 @@ func (t *Type) Nfields() int { ...@@ -518,23 +518,112 @@ func (t *Type) Nfields() int {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Statements // Statements
type Stat struct { 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;
};
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;
};
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
};
)
type StatVisitor interface {
DoBadStat(s *BadStat);
DoLabelDecl(s *LabelDecl);
DoDeclarationStat(s *DeclarationStat);
DoExpressionStat(s *ExpressionStat);
DoIfStat(s *IfStat);
DoForStat(s *ForStat);
DoSwitchStat(s *SwitchStat);
DoSelectStat(s *SelectStat);
DoControlFlowStat(s *ControlFlowStat);
}
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 *IfStat) Visit(v StatVisitor) { v.DoIfStat(s); }
func (s *ForStat) Visit(v StatVisitor) { v.DoForStat(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); }
// ----------------------------------------------------------------------------
// Old style statements
type StatImpl struct {
Node; Node;
Init, Post *Stat; Init, Post *StatImpl;
Expr Expr; Expr Expr;
Body *Block; // composite statement body Body *Block; // composite statement body
Decl *Decl; // declaration statement Decl *Decl; // declaration statement
} }
func NewStat(pos, tok int) *Stat { func NewStat(pos, tok int) *StatImpl {
s := new(Stat); s := new(StatImpl);
s.Pos, s.Tok = pos, tok; s.Pos, s.Tok = pos, tok;
return s; return s;
} }
var BadStat = NewStat(0, Scanner.ILLEGAL); var OldBadStat = NewStat(0, Scanner.ILLEGAL);
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
package Parser package Parser
import ( import (
"flag";
"fmt"; "fmt";
"array"; "array";
Scanner "scanner"; Scanner "scanner";
...@@ -83,6 +84,13 @@ func (P *Parser) Ecart() { ...@@ -83,6 +84,13 @@ func (P *Parser) Ecart() {
} }
func (P *Parser) VerifyIndent(indent uint) {
if indent != P.indent {
panic("imbalanced tracing code");
}
}
func (P *Parser) Next0() { func (P *Parser) Next0() {
if P.tokchan == nil { if P.tokchan == nil {
P.pos, P.tok, P.val = P.scanner.Scan(); P.pos, P.tok, P.val = P.scanner.Scan();
...@@ -247,7 +255,8 @@ func (P *Parser) NewBinary(pos, tok int, x, y AST.Expr) *AST.BinaryExpr { ...@@ -247,7 +255,8 @@ func (P *Parser) NewBinary(pos, tok int, x, y AST.Expr) *AST.BinaryExpr {
func (P *Parser) TryType() *AST.Type; func (P *Parser) TryType() *AST.Type;
func (P *Parser) ParseExpression(prec int) AST.Expr; func (P *Parser) ParseExpression(prec int) AST.Expr;
func (P *Parser) ParseStatement() *AST.Stat; func (P *Parser) ParseStatement() AST.Stat;
func (P *Parser) OldParseStatement() *AST.StatImpl;
func (P *Parser) ParseDeclaration() *AST.Decl; func (P *Parser) ParseDeclaration() *AST.Decl;
...@@ -746,14 +755,24 @@ func (P *Parser) TryType() *AST.Type { ...@@ -746,14 +755,24 @@ func (P *Parser) TryType() *AST.Type {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Blocks // Blocks
var newstat = flag.Bool("newstat", false, "use new statement parsing - work in progress");
func (P *Parser) ParseStatementList(list *array.Array) { func (P *Parser) ParseStatementList(list *array.Array) {
if P.verbose { if P.verbose {
P.Trace("StatementList"); P.Trace("StatementList");
defer P.Ecart(); defer P.Ecart();
defer P.VerifyIndent(P.indent);
} }
for P.tok != Scanner.CASE && P.tok != Scanner.DEFAULT && P.tok != Scanner.RBRACE && P.tok != Scanner.EOF { for P.tok != Scanner.CASE && P.tok != Scanner.DEFAULT && P.tok != Scanner.RBRACE && P.tok != Scanner.EOF {
s := P.ParseStatement(); var s interface{};
if *newstat {
s = P.ParseStatement();
} else {
s = P.OldParseStatement();
}
if s != nil { if s != nil {
// not the empty statement // not the empty statement
list.Push(s); list.Push(s);
...@@ -1133,31 +1152,93 @@ func (P *Parser) ParseExpression(prec int) AST.Expr { ...@@ -1133,31 +1152,93 @@ func (P *Parser) ParseExpression(prec int) AST.Expr {
if P.verbose { if P.verbose {
P.Trace("Expression"); P.Trace("Expression");
defer P.Ecart(); defer P.Ecart();
defer P.VerifyIndent(P.indent);
} }
indent := P.indent;
if prec < 0 { if prec < 0 {
panic("precedence must be >= 0"); panic("precedence must be >= 0");
} }
x := P.NoType(P.ParseBinaryExpr(prec));
if indent != P.indent {
panic("imbalanced tracing code (Expression)");
}
return x; return P.NoType(P.ParseBinaryExpr(prec));
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Statements // Statements
func (P *Parser) ParseSimpleStat(range_ok bool) *AST.Stat { func (P *Parser) ParseSimpleStat(range_ok bool) AST.Stat {
if P.verbose {
P.Trace("SimpleStat");
defer P.Ecart();
}
x := P.ParseExpressionList();
switch P.tok {
case Scanner.COLON:
// label declaration
pos := P.pos;
P.Next(); // consume ":"
if AST.ExprLen(x) == 1 {
if label, is_ident := x.(*AST.Ident); is_ident {
return &AST.LabelDecl{pos, label};
}
}
P.Error(x.Pos(), "illegal label declaration");
return nil;
case
Scanner.DEFINE, Scanner.ASSIGN, Scanner.ADD_ASSIGN,
Scanner.SUB_ASSIGN, Scanner.MUL_ASSIGN, Scanner.QUO_ASSIGN,
Scanner.REM_ASSIGN, Scanner.AND_ASSIGN, Scanner.OR_ASSIGN,
Scanner.XOR_ASSIGN, Scanner.SHL_ASSIGN, Scanner.SHR_ASSIGN:
// declaration/assignment
pos, tok := P.pos, P.tok;
P.Next();
var y AST.Expr;
if range_ok && P.tok == Scanner.RANGE {
range_pos := P.pos;
P.Next();
y = &AST.UnaryExpr{range_pos, Scanner.RANGE, P.ParseExpression(1)};
if tok != Scanner.DEFINE && tok != Scanner.ASSIGN {
P.Error(pos, "expected '=' or ':=', found '" + Scanner.TokenString(tok) + "'");
}
} else {
y = P.ParseExpressionList();
if xl, yl := AST.ExprLen(x), AST.ExprLen(y); xl > 1 && yl > 1 && xl != yl {
P.Error(x.Pos(), "arity of lhs doesn't match rhs");
}
}
// TODO changed ILLEGAL -> NONE
return &AST.ExpressionStat{x.Pos(), Scanner.ILLEGAL, P.NewBinary(pos, tok, x, y)};
default:
if AST.ExprLen(x) != 1 {
P.Error(x.Pos(), "only one expression allowed");
}
if P.tok == Scanner.INC || P.tok == Scanner.DEC {
s := &AST.ExpressionStat{P.pos, P.tok, x};
P.Next(); // consume "++" or "--"
return s;
}
// TODO changed ILLEGAL -> NONE
return &AST.ExpressionStat{x.Pos(), Scanner.ILLEGAL, x};
}
unreachable();
return nil;
}
func (P *Parser) OldParseSimpleStat(range_ok bool) *AST.StatImpl {
if P.verbose { if P.verbose {
P.Trace("SimpleStat"); P.Trace("SimpleStat");
defer P.Ecart(); defer P.Ecart();
} }
s := AST.BadStat; s := AST.OldBadStat;
x := P.ParseExpressionList(); x := P.ParseExpressionList();
switch P.tok { switch P.tok {
...@@ -1180,7 +1261,7 @@ func (P *Parser) ParseSimpleStat(range_ok bool) *AST.Stat { ...@@ -1180,7 +1261,7 @@ func (P *Parser) ParseSimpleStat(range_ok bool) *AST.Stat {
pos, tok := P.pos, P.tok; pos, tok := P.pos, P.tok;
P.Next(); P.Next();
var y AST.Expr = &AST.BadExpr{pos}; var y AST.Expr = &AST.BadExpr{pos};
if P.tok == Scanner.RANGE { if range_ok && P.tok == Scanner.RANGE {
range_pos := P.pos; range_pos := P.pos;
P.Next(); P.Next();
y = P.ParseExpression(1); y = P.ParseExpression(1);
...@@ -1197,14 +1278,6 @@ func (P *Parser) ParseSimpleStat(range_ok bool) *AST.Stat { ...@@ -1197,14 +1278,6 @@ func (P *Parser) ParseSimpleStat(range_ok bool) *AST.Stat {
s = AST.NewStat(x.Pos(), Scanner.EXPRSTAT); s = AST.NewStat(x.Pos(), Scanner.EXPRSTAT);
s.Expr = P.NewBinary(pos, tok, x, y); s.Expr = P.NewBinary(pos, tok, x, y);
case Scanner.RANGE:
pos := P.pos;
P.Next();
y := P.ParseExpression(1);
y = &AST.UnaryExpr{pos, Scanner.RANGE, y};
s = AST.NewStat(x.Pos(), Scanner.EXPRSTAT);
s.Expr = P.NewBinary(pos, Scanner.DEFINE, x, y);
default: default:
var pos, tok int; var pos, tok int;
if P.tok == Scanner.INC || P.tok == Scanner.DEC { if P.tok == Scanner.INC || P.tok == Scanner.DEC {
...@@ -1225,7 +1298,19 @@ func (P *Parser) ParseSimpleStat(range_ok bool) *AST.Stat { ...@@ -1225,7 +1298,19 @@ func (P *Parser) ParseSimpleStat(range_ok bool) *AST.Stat {
} }
func (P *Parser) ParseInvocationStat(keyword int) *AST.Stat { func (P *Parser) ParseInvocationStat(keyword int) *AST.ExpressionStat {
if P.verbose {
P.Trace("InvocationStat");
defer P.Ecart();
}
pos := P.pos;
P.Expect(keyword);
return &AST.ExpressionStat{pos, keyword, P.ParseExpression(1)};
}
func (P *Parser) OldParseInvocationStat(keyword int) *AST.StatImpl {
if P.verbose { if P.verbose {
P.Trace("InvocationStat"); P.Trace("InvocationStat");
defer P.Ecart(); defer P.Ecart();
...@@ -1239,7 +1324,24 @@ func (P *Parser) ParseInvocationStat(keyword int) *AST.Stat { ...@@ -1239,7 +1324,24 @@ func (P *Parser) ParseInvocationStat(keyword int) *AST.Stat {
} }
func (P *Parser) ParseReturnStat() *AST.Stat { func (P *Parser) ParseReturnStat() *AST.ExpressionStat {
if P.verbose {
P.Trace("ReturnStat");
defer P.Ecart();
}
pos := P.pos;
P.Expect(Scanner.RETURN);
var x AST.Expr;
if P.tok != Scanner.SEMICOLON && P.tok != Scanner.RBRACE {
x = P.ParseExpressionList();
}
return &AST.ExpressionStat{pos, Scanner.RETURN, x};
}
func (P *Parser) OldParseReturnStat() *AST.StatImpl {
if P.verbose { if P.verbose {
P.Trace("ReturnStat"); P.Trace("ReturnStat");
defer P.Ecart(); defer P.Ecart();
...@@ -1255,7 +1357,7 @@ func (P *Parser) ParseReturnStat() *AST.Stat { ...@@ -1255,7 +1357,7 @@ func (P *Parser) ParseReturnStat() *AST.Stat {
} }
func (P *Parser) ParseControlFlowStat(tok int) *AST.Stat { func (P *Parser) ParseControlFlowStat(tok int) *AST.StatImpl {
if P.verbose { if P.verbose {
P.Trace("ControlFlowStat"); P.Trace("ControlFlowStat");
defer P.Ecart(); defer P.Ecart();
...@@ -1271,7 +1373,47 @@ func (P *Parser) ParseControlFlowStat(tok int) *AST.Stat { ...@@ -1271,7 +1373,47 @@ func (P *Parser) ParseControlFlowStat(tok int) *AST.Stat {
} }
func (P *Parser) ParseControlClause(keyword int) *AST.Stat { func (P *Parser) ParseControlClause(isForStat bool) (init AST.Stat, expr AST.Expr, post AST.Stat) {
if P.verbose {
P.Trace("ControlClause");
defer P.Ecart();
}
if P.tok != Scanner.LBRACE {
prev_lev := P.expr_lev;
P.expr_lev = -1;
if P.tok != Scanner.SEMICOLON {
init = P.ParseSimpleStat(isForStat);
// TODO check for range clause and exit if found
}
if P.tok == Scanner.SEMICOLON {
P.Next();
if P.tok != Scanner.SEMICOLON && P.tok != Scanner.LBRACE {
expr = P.ParseExpression(1);
}
if isForStat {
P.Expect(Scanner.SEMICOLON);
if P.tok != Scanner.LBRACE {
post = P.ParseSimpleStat(false);
}
}
} else {
if init != nil { // guard in case of errors
if s, is_expr_stat := init.(*AST.ExpressionStat); is_expr_stat {
expr, init = s.Expr, nil;
} else {
P.Error(0, "illegal control clause");
}
}
}
P.expr_lev = prev_lev;
}
return init, expr, post;
}
func (P *Parser) OldParseControlClause(keyword int) *AST.StatImpl {
if P.verbose { if P.verbose {
P.Trace("ControlClause"); P.Trace("ControlClause");
defer P.Ecart(); defer P.Ecart();
...@@ -1283,7 +1425,7 @@ func (P *Parser) ParseControlClause(keyword int) *AST.Stat { ...@@ -1283,7 +1425,7 @@ func (P *Parser) ParseControlClause(keyword int) *AST.Stat {
prev_lev := P.expr_lev; prev_lev := P.expr_lev;
P.expr_lev = -1; P.expr_lev = -1;
if P.tok != Scanner.SEMICOLON { if P.tok != Scanner.SEMICOLON {
s.Init = P.ParseSimpleStat(keyword == Scanner.FOR); s.Init = P.OldParseSimpleStat(keyword == Scanner.FOR);
// TODO check for range clause and exit if found // TODO check for range clause and exit if found
} }
if P.tok == Scanner.SEMICOLON { if P.tok == Scanner.SEMICOLON {
...@@ -1294,7 +1436,7 @@ func (P *Parser) ParseControlClause(keyword int) *AST.Stat { ...@@ -1294,7 +1436,7 @@ func (P *Parser) ParseControlClause(keyword int) *AST.Stat {
if keyword == Scanner.FOR { if keyword == Scanner.FOR {
P.Expect(Scanner.SEMICOLON); P.Expect(Scanner.SEMICOLON);
if P.tok != Scanner.LBRACE { if P.tok != Scanner.LBRACE {
s.Post = P.ParseSimpleStat(false); s.Post = P.OldParseSimpleStat(false);
} }
} }
} else { } else {
...@@ -1309,22 +1451,61 @@ func (P *Parser) ParseControlClause(keyword int) *AST.Stat { ...@@ -1309,22 +1451,61 @@ func (P *Parser) ParseControlClause(keyword int) *AST.Stat {
} }
func (P *Parser) ParseIfStat() *AST.Stat { func (P *Parser) ParseIfStat() *AST.IfStat {
if P.verbose {
P.Trace("IfStat");
defer P.Ecart();
}
P.OpenScope();
pos := P.pos;
P.Expect(Scanner.IF);
init, cond, dummy := P.ParseControlClause(false);
body := P.ParseBlock(nil, Scanner.LBRACE);
var else_ AST.Stat;
if P.tok == Scanner.ELSE {
P.Next();
if P.tok == Scanner.IF || P.tok == Scanner.LBRACE {
else_ = P.ParseStatement();
} else if P.sixg {
else_ = P.ParseStatement();
if else_ != nil {
// not the empty statement
// wrap in a block since we don't have one
panic();
/*
b := AST.NewStat(s1.Pos, Scanner.LBRACE);
b.Body = AST.NewBlock(s1.Pos, Scanner.LBRACE);
b.Body.List.Push(s1);
s1 = b;
*/
}
} else {
P.Error(P.pos, "'if' or '{' expected - illegal 'else' branch");
}
}
P.CloseScope();
return &AST.IfStat{pos, init, cond, body, else_ };
}
func (P *Parser) OldParseIfStat() *AST.StatImpl {
if P.verbose { if P.verbose {
P.Trace("IfStat"); P.Trace("IfStat");
defer P.Ecart(); defer P.Ecart();
} }
P.OpenScope(); P.OpenScope();
s := P.ParseControlClause(Scanner.IF); s := P.OldParseControlClause(Scanner.IF);
s.Body = P.ParseBlock(nil, Scanner.LBRACE); s.Body = P.ParseBlock(nil, Scanner.LBRACE);
if P.tok == Scanner.ELSE { if P.tok == Scanner.ELSE {
P.Next(); P.Next();
s1 := AST.BadStat; s1 := AST.OldBadStat;
if P.tok == Scanner.IF || P.tok == Scanner.LBRACE { if P.tok == Scanner.IF || P.tok == Scanner.LBRACE {
s1 = P.ParseStatement(); s1 = P.OldParseStatement();
} else if P.sixg { } else if P.sixg {
s1 = P.ParseStatement(); s1 = P.OldParseStatement();
if s1 != nil { if s1 != nil {
// not the empty statement // not the empty statement
assert(s1.Tok != Scanner.LBRACE); assert(s1.Tok != Scanner.LBRACE);
...@@ -1345,14 +1526,31 @@ func (P *Parser) ParseIfStat() *AST.Stat { ...@@ -1345,14 +1526,31 @@ func (P *Parser) ParseIfStat() *AST.Stat {
} }
func (P *Parser) ParseForStat() *AST.Stat { func (P *Parser) ParseForStat() *AST.ForStat {
if P.verbose { if P.verbose {
P.Trace("ForStat"); P.Trace("ForStat");
defer P.Ecart(); defer P.Ecart();
} }
P.OpenScope(); P.OpenScope();
s := P.ParseControlClause(Scanner.FOR); pos := P.pos;
P.Expect(Scanner.FOR);
init, cond, post := P.ParseControlClause(true);
body := P.ParseBlock(nil, Scanner.LBRACE);
P.CloseScope();
return &AST.ForStat{pos, init, cond, post, body};
}
func (P *Parser) OldParseForStat() *AST.StatImpl {
if P.verbose {
P.Trace("ForStat");
defer P.Ecart();
}
P.OpenScope();
s := P.OldParseControlClause(Scanner.FOR);
s.Body = P.ParseBlock(nil, Scanner.LBRACE); s.Body = P.ParseBlock(nil, Scanner.LBRACE);
P.CloseScope(); P.CloseScope();
...@@ -1360,7 +1558,7 @@ func (P *Parser) ParseForStat() *AST.Stat { ...@@ -1360,7 +1558,7 @@ func (P *Parser) ParseForStat() *AST.Stat {
} }
func (P *Parser) ParseSwitchCase() *AST.Stat { func (P *Parser) ParseSwitchCase() *AST.StatImpl {
if P.verbose { if P.verbose {
P.Trace("SwitchCase"); P.Trace("SwitchCase");
defer P.Ecart(); defer P.Ecart();
...@@ -1378,7 +1576,7 @@ func (P *Parser) ParseSwitchCase() *AST.Stat { ...@@ -1378,7 +1576,7 @@ func (P *Parser) ParseSwitchCase() *AST.Stat {
} }
func (P *Parser) ParseCaseClause() *AST.Stat { func (P *Parser) ParseCaseClause() *AST.StatImpl {
if P.verbose { if P.verbose {
P.Trace("CaseClause"); P.Trace("CaseClause");
defer P.Ecart(); defer P.Ecart();
...@@ -1391,14 +1589,38 @@ func (P *Parser) ParseCaseClause() *AST.Stat { ...@@ -1391,14 +1589,38 @@ func (P *Parser) ParseCaseClause() *AST.Stat {
} }
func (P *Parser) ParseSwitchStat() *AST.Stat { func (P *Parser) ParseSwitchStat() *AST.SwitchStat {
if P.verbose {
P.Trace("SwitchStat");
defer P.Ecart();
}
P.OpenScope();
pos := P.pos;
P.Expect(Scanner.SWITCH);
init, tag, post := P.ParseControlClause(false);
body := AST.NewBlock(P.pos, Scanner.LBRACE);
P.Expect(Scanner.LBRACE);
for P.tok != Scanner.RBRACE && P.tok != Scanner.EOF {
body.List.Push(P.ParseCaseClause());
}
body.End = P.pos;
P.Expect(Scanner.RBRACE);
P.opt_semi = true;
P.CloseScope();
return &AST.SwitchStat{pos, init, tag, body};
}
func (P *Parser) OldParseSwitchStat() *AST.StatImpl {
if P.verbose { if P.verbose {
P.Trace("SwitchStat"); P.Trace("SwitchStat");
defer P.Ecart(); defer P.Ecart();
} }
P.OpenScope(); P.OpenScope();
s := P.ParseControlClause(Scanner.SWITCH); s := P.OldParseControlClause(Scanner.SWITCH);
b := AST.NewBlock(P.pos, Scanner.LBRACE); b := AST.NewBlock(P.pos, Scanner.LBRACE);
P.Expect(Scanner.LBRACE); P.Expect(Scanner.LBRACE);
for P.tok != Scanner.RBRACE && P.tok != Scanner.EOF { for P.tok != Scanner.RBRACE && P.tok != Scanner.EOF {
...@@ -1414,7 +1636,7 @@ func (P *Parser) ParseSwitchStat() *AST.Stat { ...@@ -1414,7 +1636,7 @@ func (P *Parser) ParseSwitchStat() *AST.Stat {
} }
func (P *Parser) ParseCommCase() *AST.Stat { func (P *Parser) ParseCommCase() *AST.StatImpl {
if P.verbose { if P.verbose {
P.Trace("CommCase"); P.Trace("CommCase");
defer P.Ecart(); defer P.Ecart();
...@@ -1443,7 +1665,7 @@ func (P *Parser) ParseCommCase() *AST.Stat { ...@@ -1443,7 +1665,7 @@ func (P *Parser) ParseCommCase() *AST.Stat {
} }
func (P *Parser) ParseCommClause() *AST.Stat { func (P *Parser) ParseCommClause() *AST.StatImpl {
if P.verbose { if P.verbose {
P.Trace("CommClause"); P.Trace("CommClause");
defer P.Ecart(); defer P.Ecart();
...@@ -1456,12 +1678,36 @@ func (P *Parser) ParseCommClause() *AST.Stat { ...@@ -1456,12 +1678,36 @@ func (P *Parser) ParseCommClause() *AST.Stat {
} }
func (P *Parser) ParseSelectStat() *AST.Stat { func (P *Parser) ParseSelectStat() *AST.SelectStat {
if P.verbose { if P.verbose {
P.Trace("SelectStat"); P.Trace("SelectStat");
defer P.Ecart(); defer P.Ecart();
} }
P.OpenScope();
pos := P.pos;
P.Expect(Scanner.SELECT);
body := AST.NewBlock(P.pos, Scanner.LBRACE);
P.Expect(Scanner.LBRACE);
for P.tok != Scanner.RBRACE && P.tok != Scanner.EOF {
body.List.Push(P.ParseCommClause());
}
body.End = P.pos;
P.Expect(Scanner.RBRACE);
P.opt_semi = true;
P.CloseScope();
return &AST.SelectStat{pos, body};
}
func (P *Parser) OldParseSelectStat() *AST.StatImpl {
if P.verbose {
P.Trace("SelectStat");
defer P.Ecart();
}
P.OpenScope();
s := AST.NewStat(P.pos, Scanner.SELECT); s := AST.NewStat(P.pos, Scanner.SELECT);
P.Expect(Scanner.SELECT); P.Expect(Scanner.SELECT);
b := AST.NewBlock(P.pos, Scanner.LBRACE); b := AST.NewBlock(P.pos, Scanner.LBRACE);
...@@ -1472,20 +1718,66 @@ func (P *Parser) ParseSelectStat() *AST.Stat { ...@@ -1472,20 +1718,66 @@ func (P *Parser) ParseSelectStat() *AST.Stat {
b.End = P.pos; b.End = P.pos;
P.Expect(Scanner.RBRACE); P.Expect(Scanner.RBRACE);
P.opt_semi = true; P.opt_semi = true;
P.CloseScope();
s.Body = b; s.Body = b;
return s; return s;
} }
func (P *Parser) ParseStatement() *AST.Stat { func (P *Parser) ParseStatement() AST.Stat {
if P.verbose { if P.verbose {
P.Trace("Statement"); P.Trace("Statement");
defer P.Ecart(); defer P.Ecart();
defer P.VerifyIndent(P.indent);
}
s := AST.OldBadStat;
switch P.tok {
case Scanner.CONST, Scanner.TYPE, Scanner.VAR:
return &AST.DeclarationStat{P.ParseDeclaration()};
case Scanner.FUNC:
// for now we do not allow local function declarations,
// instead we assume this starts a function literal
fallthrough;
case
// only the tokens that are legal top-level expression starts
Scanner.IDENT, Scanner.INT, Scanner.FLOAT, Scanner.STRING, Scanner.LPAREN, // operand
Scanner.LBRACK, Scanner.STRUCT, // composite type
Scanner.MUL, Scanner.AND, Scanner.ARROW: // unary
return P.ParseSimpleStat(false);
case Scanner.GO, Scanner.DEFER:
return P.ParseInvocationStat(P.tok);
case Scanner.RETURN:
return P.ParseReturnStat();
case Scanner.BREAK, Scanner.CONTINUE, Scanner.GOTO, Scanner.FALLTHROUGH:
s = P.ParseControlFlowStat(P.tok);
case Scanner.LBRACE:
s = AST.NewStat(P.pos, Scanner.LBRACE);
s.Body = P.ParseBlock(nil, Scanner.LBRACE);
case Scanner.IF:
return P.ParseIfStat();
case Scanner.FOR:
return P.ParseForStat();
case Scanner.SWITCH:
return P.ParseSwitchStat();
case Scanner.SELECT:
return P.ParseSelectStat();
}
// empty statement
return nil;
}
func (P *Parser) OldParseStatement() *AST.StatImpl {
if P.verbose {
P.Trace("Statement");
defer P.Ecart();
defer P.VerifyIndent(P.indent);
} }
indent := P.indent;
s := AST.BadStat; s := AST.OldBadStat;
switch P.tok { switch P.tok {
case Scanner.CONST, Scanner.TYPE, Scanner.VAR: case Scanner.CONST, Scanner.TYPE, Scanner.VAR:
s = AST.NewStat(P.pos, P.tok); s = AST.NewStat(P.pos, P.tok);
...@@ -1499,32 +1791,29 @@ func (P *Parser) ParseStatement() *AST.Stat { ...@@ -1499,32 +1791,29 @@ func (P *Parser) ParseStatement() *AST.Stat {
Scanner.IDENT, Scanner.INT, Scanner.FLOAT, Scanner.STRING, Scanner.LPAREN, // operand Scanner.IDENT, Scanner.INT, Scanner.FLOAT, Scanner.STRING, Scanner.LPAREN, // operand
Scanner.LBRACK, Scanner.STRUCT, // composite type Scanner.LBRACK, Scanner.STRUCT, // composite type
Scanner.MUL, Scanner.AND, Scanner.ARROW: // unary Scanner.MUL, Scanner.AND, Scanner.ARROW: // unary
s = P.ParseSimpleStat(false); s = P.OldParseSimpleStat(false);
case Scanner.GO, Scanner.DEFER: case Scanner.GO, Scanner.DEFER:
s = P.ParseInvocationStat(P.tok); s = P.OldParseInvocationStat(P.tok);
case Scanner.RETURN: case Scanner.RETURN:
s = P.ParseReturnStat(); s = P.OldParseReturnStat();
case Scanner.BREAK, Scanner.CONTINUE, Scanner.GOTO, Scanner.FALLTHROUGH: case Scanner.BREAK, Scanner.CONTINUE, Scanner.GOTO, Scanner.FALLTHROUGH:
s = P.ParseControlFlowStat(P.tok); s = P.ParseControlFlowStat(P.tok);
case Scanner.LBRACE: case Scanner.LBRACE:
s = AST.NewStat(P.pos, Scanner.LBRACE); s = AST.NewStat(P.pos, Scanner.LBRACE);
s.Body = P.ParseBlock(nil, Scanner.LBRACE); s.Body = P.ParseBlock(nil, Scanner.LBRACE);
case Scanner.IF: case Scanner.IF:
s = P.ParseIfStat(); s = P.OldParseIfStat();
case Scanner.FOR: case Scanner.FOR:
s = P.ParseForStat(); s = P.OldParseForStat();
case Scanner.SWITCH: case Scanner.SWITCH:
s = P.ParseSwitchStat(); s = P.OldParseSwitchStat();
case Scanner.SELECT: case Scanner.SELECT:
s = P.ParseSelectStat(); s = P.OldParseSelectStat();
default: default:
// empty statement // empty statement
s = nil; s = nil;
} }
if indent != P.indent {
panic("imbalanced tracing code (Statement)");
}
return s; return s;
} }
...@@ -1719,6 +2008,7 @@ func (P *Parser) ParseDeclaration() *AST.Decl { ...@@ -1719,6 +2008,7 @@ func (P *Parser) ParseDeclaration() *AST.Decl {
if P.verbose { if P.verbose {
P.Trace("Declaration"); P.Trace("Declaration");
defer P.Ecart(); defer P.Ecart();
defer P.VerifyIndent(P.indent);
} }
indent := P.indent; indent := P.indent;
...@@ -1734,9 +2024,6 @@ func (P *Parser) ParseDeclaration() *AST.Decl { ...@@ -1734,9 +2024,6 @@ func (P *Parser) ParseDeclaration() *AST.Decl {
P.Next(); // make progress P.Next(); // make progress
} }
if indent != P.indent {
panic("imbalanced tracing code (Declaration)");
}
return d; return d;
} }
......
...@@ -371,9 +371,8 @@ func (P *Printer) Token(pos int, tok int) { ...@@ -371,9 +371,8 @@ func (P *Printer) Token(pos int, tok int) {
func (P *Printer) Error(pos int, tok int, msg string) { func (P *Printer) Error(pos int, tok int, msg string) {
P.String(0, "<"); fmt.Printf("\ninternal printing error: pos = %d, tok = %s, %s\n", pos, Scanner.TokenString(tok), msg);
P.Token(pos, tok); panic();
P.String(0, " " + msg + ">");
} }
...@@ -723,12 +722,25 @@ func (P *Printer) Expr(x AST.Expr) { ...@@ -723,12 +722,25 @@ func (P *Printer) Expr(x AST.Expr) {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Statements // Statements
func (P *Printer) Stat(s *AST.Stat) func (P *Printer) Stat(s AST.Stat) {
s.Visit(P);
}
func (P *Printer) StatImpl(s *AST.StatImpl)
func (P *Printer) StatementList(list *array.Array) { func (P *Printer) StatementList(list *array.Array) {
for i, n := 0, list.Len(); i < n; i++ { for i, n := 0, list.Len(); i < n; i++ {
P.newlines = 1; // for first entry P.newlines = 1; // for first entry
P.Stat(list.At(i).(*AST.Stat));
if s, is_StatImpl := list.At(i).(*AST.StatImpl); is_StatImpl {
P.StatImpl(s);
} else if s, is_Stat := list.At(i).(AST.Stat); is_Stat {
s.Visit(P);
} else {
panic();
}
P.newlines = 1; P.newlines = 1;
P.state = inside_list; P.state = inside_list;
} }
...@@ -757,7 +769,7 @@ func (P *Printer) Block(b *AST.Block, indent bool) { ...@@ -757,7 +769,7 @@ func (P *Printer) Block(b *AST.Block, indent bool) {
} }
func (P *Printer) ControlClause(s *AST.Stat) { func (P *Printer) OldControlClause(s *AST.StatImpl) {
has_post := s.Tok == Scanner.FOR && s.Post != nil; // post also used by "if" has_post := s.Tok == Scanner.FOR && s.Post != nil; // post also used by "if"
P.separator = blank; P.separator = blank;
...@@ -770,7 +782,7 @@ func (P *Printer) ControlClause(s *AST.Stat) { ...@@ -770,7 +782,7 @@ func (P *Printer) ControlClause(s *AST.Stat) {
// all semicolons required // all semicolons required
// (they are not separators, print them explicitly) // (they are not separators, print them explicitly)
if s.Init != nil { if s.Init != nil {
P.Stat(s.Init); P.StatImpl(s.Init);
P.separator = none; P.separator = none;
} }
P.String(0, ";"); P.String(0, ";");
...@@ -783,7 +795,7 @@ func (P *Printer) ControlClause(s *AST.Stat) { ...@@ -783,7 +795,7 @@ func (P *Printer) ControlClause(s *AST.Stat) {
P.String(0, ";"); P.String(0, ";");
P.separator = blank; P.separator = blank;
if has_post { if has_post {
P.Stat(s.Post); P.StatImpl(s.Post);
} }
} }
} }
...@@ -793,7 +805,7 @@ func (P *Printer) ControlClause(s *AST.Stat) { ...@@ -793,7 +805,7 @@ func (P *Printer) ControlClause(s *AST.Stat) {
func (P *Printer) Declaration(d *AST.Decl, parenthesized bool); func (P *Printer) Declaration(d *AST.Decl, parenthesized bool);
func (P *Printer) Stat(s *AST.Stat) { func (P *Printer) StatImpl(s *AST.StatImpl) {
switch s.Tok { switch s.Tok {
case Scanner.EXPRSTAT: case Scanner.EXPRSTAT:
// expression statement // expression statement
...@@ -823,23 +835,23 @@ func (P *Printer) Stat(s *AST.Stat) { ...@@ -823,23 +835,23 @@ func (P *Printer) Stat(s *AST.Stat) {
case Scanner.IF: case Scanner.IF:
P.String(s.Pos, "if"); P.String(s.Pos, "if");
P.ControlClause(s); P.OldControlClause(s);
P.Block(s.Body, true); P.Block(s.Body, true);
if s.Post != nil { if s.Post != nil {
P.separator = blank; P.separator = blank;
P.String(0, "else"); P.String(0, "else");
P.separator = blank; P.separator = blank;
P.Stat(s.Post); P.StatImpl(s.Post);
} }
case Scanner.FOR: case Scanner.FOR:
P.String(s.Pos, "for"); P.String(s.Pos, "for");
P.ControlClause(s); P.OldControlClause(s);
P.Block(s.Body, true); P.Block(s.Body, true);
case Scanner.SWITCH, Scanner.SELECT: case Scanner.SWITCH, Scanner.SELECT:
P.Token(s.Pos, s.Tok); P.Token(s.Pos, s.Tok);
P.ControlClause(s); P.OldControlClause(s);
P.Block(s.Body, false); P.Block(s.Body, false);
case Scanner.CASE, Scanner.DEFAULT: case Scanner.CASE, Scanner.DEFAULT:
...@@ -872,6 +884,116 @@ func (P *Printer) Stat(s *AST.Stat) { ...@@ -872,6 +884,116 @@ func (P *Printer) Stat(s *AST.Stat) {
} }
func (P *Printer) DoBadStat(s *AST.BadStat) {
panic();
}
func (P *Printer) DoLabelDecl(s *AST.LabelDecl) {
panic();
}
func (P *Printer) DoDeclarationStat(s *AST.DeclarationStat) {
P.Declaration(s.Decl, false);
}
func (P *Printer) DoExpressionStat(s *AST.ExpressionStat) {
switch s.Tok {
case Scanner.ILLEGAL:
P.Expr(s.Expr);
case Scanner.INC, Scanner.DEC:
P.Expr(s.Expr);
P.Token(s.Pos, s.Tok);
case Scanner.RETURN, Scanner.GO, Scanner.DEFER:
P.Token(s.Pos, s.Tok);
if s.Expr != nil {
P.separator = blank;
P.Expr(s.Expr);
}
default:
P.Error(s.Pos, s.Tok, "DoExpressionStat");
unreachable();
}
P.separator = semicolon;
}
func (P *Printer) ControlClause(isForStat bool, init AST.Stat, expr AST.Expr, post AST.Stat) {
P.separator = blank;
if init == nil && post == nil {
// no semicolons required
if expr != nil {
P.Expr(expr);
}
} else {
// all semicolons required
// (they are not separators, print them explicitly)
if init != nil {
P.Stat(init);
P.separator = none;
}
P.String(0, ";");
P.separator = blank;
if expr != nil {
P.Expr(expr);
P.separator = none;
}
if isForStat {
P.String(0, ";");
P.separator = blank;
if post != nil {
P.Stat(post);
}
}
}
P.separator = blank;
}
func (P *Printer) DoIfStat(s *AST.IfStat) {
P.String(s.Pos, "if");
P.ControlClause(false, s.Init, s.Cond, nil);
P.Block(s.Body, true);
if s.Else != nil {
P.separator = blank;
P.String(0, "else");
P.separator = blank;
P.Stat(s.Else);
}
}
func (P *Printer) DoForStat(s *AST.ForStat) {
P.String(s.Pos, "for");
P.ControlClause(true, s.Init, s.Cond, s.Post);
P.Block(s.Body, true);
}
func (P *Printer) DoSwitchStat(s *AST.SwitchStat) {
P.String(s.Pos, "switch");
P.ControlClause(false, s.Init, s.Tag, nil);
P.Block(s.Body, false);
}
func (P *Printer) DoSelectStat(s *AST.SelectStat) {
panic();
}
func (P *Printer) DoControlFlowStat(s *AST.ControlFlowStat) {
P.Token(s.Pos, s.Tok);
if s.Label != nil {
P.separator = blank;
P.Expr(s.Label);
}
P.separator = semicolon;
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Declarations // Declarations
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment