Block struct;
Expr interface;
- StatImpl struct;
Decl struct;
)
var BadType = NewType(0, Scanner.ILLEGAL);
-// ----------------------------------------------------------------------------
-// Blocks
-//
-// Syntactic constructs of the form:
-//
-// "{" StatementList "}"
-// ":" StatementList
-
-type Block struct {
- Node;
- List *array.Array;
- End int; // position of closing "}" if present
-}
-
-
-func NewBlock(pos, tok int) *Block {
- assert(tok == Scanner.LBRACE || tok == Scanner.COLON);
- b := new(Block);
- b.Pos, b.Tok, b.List = pos, tok, array.New(0);
- return b;
-}
-
-
// ----------------------------------------------------------------------------
// Expressions
}
+// ----------------------------------------------------------------------------
+// Blocks
+//
+// Syntactic constructs of the form:
+//
+// "{" StatementList "}"
+// ":" StatementList
+
+type Block struct {
+ Node;
+ List *array.Array;
+ End int; // position of closing "}" if present
+}
+
+
+func NewBlock(pos, tok int) *Block {
+ assert(tok == Scanner.LBRACE || tok == Scanner.COLON);
+ b := new(Block);
+ b.Pos, b.Tok, b.List = pos, tok, array.New(0);
+ return b;
+}
+
+
// ----------------------------------------------------------------------------
// Statements
Tok int; // INC, DEC, RETURN, GO, DEFER
Expr Expr;
};
-
+
+ CompositeStat struct {
+ Body *Block;
+ };
+
IfStat struct {
Pos int; // position of "if"
Init Stat;
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;
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);
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); }
-// ----------------------------------------------------------------------------
-// Old style statements
-
-type StatImpl struct {
- Node;
- Init, Post *StatImpl;
- Expr Expr;
- Body *Block; // composite statement body
- Decl *Decl; // declaration statement
-}
-
-
-func NewStat(pos, tok int) *StatImpl {
- s := new(StatImpl);
- s.Pos, s.Tok = pos, tok;
- return s;
-}
-
-
-var OldBadStat = NewStat(0, Scanner.ILLEGAL);
-
-
// ----------------------------------------------------------------------------
// Declarations
func (P *Parser) TryType() *AST.Type;
func (P *Parser) ParseExpression(prec int) AST.Expr;
func (P *Parser) ParseStatement() AST.Stat;
-func (P *Parser) OldParseStatement() *AST.StatImpl;
func (P *Parser) ParseDeclaration() *AST.Decl;
// Blocks
-var newstat = flag.Bool("newstat", false, "use new statement parsing - work in progress");
-
-
func (P *Parser) ParseStatementList(list *array.Array) {
if P.verbose {
P.Trace("StatementList");
}
for P.tok != Scanner.CASE && P.tok != Scanner.DEFAULT && P.tok != Scanner.RBRACE && P.tok != Scanner.EOF {
- var s interface{};
- if *newstat {
- s = P.ParseStatement();
- } else {
- s = P.OldParseStatement();
- }
+ s := P.ParseStatement();
if s != nil {
// not the empty statement
list.Push(s);
// label declaration
pos := P.pos;
P.Next(); // consume ":"
+ P.opt_semi = true;
if AST.ExprLen(x) == 1 {
if label, is_ident := x.(*AST.Ident); is_ident {
return &AST.LabelDecl{pos, label};
}
-func (P *Parser) OldParseSimpleStat(range_ok bool) *AST.StatImpl {
- if P.verbose {
- P.Trace("SimpleStat");
- defer P.Ecart();
- }
-
- s := AST.OldBadStat;
- x := P.ParseExpressionList();
-
- switch P.tok {
- case Scanner.COLON:
- // label declaration
- s = AST.NewStat(P.pos, Scanner.COLON);
- s.Expr = x;
- if AST.ExprLen(x) != 1 {
- P.Error(x.Pos(), "illegal label declaration");
- }
- P.Next(); // consume ":"
- P.opt_semi = true;
-
- 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 = &AST.BadExpr{pos};
- if range_ok && P.tok == Scanner.RANGE {
- range_pos := P.pos;
- P.Next();
- y = P.ParseExpression(1);
- y = P.NewBinary(range_pos, Scanner.RANGE, nil, y);
- 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");
- }
- }
- s = AST.NewStat(x.Pos(), Scanner.EXPRSTAT);
- s.Expr = P.NewBinary(pos, tok, x, y);
-
- default:
- var pos, tok int;
- if P.tok == Scanner.INC || P.tok == Scanner.DEC {
- pos, tok = P.pos, P.tok;
- P.Next();
- } else {
- pos, tok = x.Pos(), Scanner.EXPRSTAT;
- }
- s = AST.NewStat(pos, tok);
- s.Expr = x;
- if AST.ExprLen(x) != 1 {
- P.Error(pos, "only one expression allowed");
- panic(); // fix position
- }
- }
-
- return s;
-}
-
-
func (P *Parser) ParseInvocationStat(keyword int) *AST.ExpressionStat {
if P.verbose {
P.Trace("InvocationStat");
}
-func (P *Parser) OldParseInvocationStat(keyword int) *AST.StatImpl {
- if P.verbose {
- P.Trace("InvocationStat");
- defer P.Ecart();
- }
-
- s := AST.NewStat(P.pos, keyword);
- P.Expect(keyword);
- s.Expr = P.ParseExpression(1);
-
- return s;
-}
-
-
func (P *Parser) ParseReturnStat() *AST.ExpressionStat {
if P.verbose {
P.Trace("ReturnStat");
}
-func (P *Parser) OldParseReturnStat() *AST.StatImpl {
- if P.verbose {
- P.Trace("ReturnStat");
- defer P.Ecart();
- }
-
- s := AST.NewStat(P.pos, Scanner.RETURN);
- P.Expect(Scanner.RETURN);
- if P.tok != Scanner.SEMICOLON && P.tok != Scanner.RBRACE {
- s.Expr = P.ParseExpressionList();
- }
-
- return s;
-}
-
-
-func (P *Parser) ParseControlFlowStat(tok int) *AST.StatImpl {
+func (P *Parser) ParseControlFlowStat(tok int) *AST.ControlFlowStat {
if P.verbose {
P.Trace("ControlFlowStat");
defer P.Ecart();
}
- s := AST.NewStat(P.pos, tok);
+ s := &AST.ControlFlowStat{P.pos, tok, nil};
P.Expect(tok);
if tok != Scanner.FALLTHROUGH && P.tok == Scanner.IDENT {
- s.Expr = P.ParseIdent(P.top_scope);
+ s.Label = P.ParseIdent(P.top_scope);
}
return s;
}
-func (P *Parser) OldParseControlClause(keyword int) *AST.StatImpl {
- if P.verbose {
- P.Trace("ControlClause");
- defer P.Ecart();
- }
-
- s := AST.NewStat(P.pos, keyword);
- P.Expect(keyword);
- if P.tok != Scanner.LBRACE {
- prev_lev := P.expr_lev;
- P.expr_lev = -1;
- if P.tok != Scanner.SEMICOLON {
- s.Init = P.OldParseSimpleStat(keyword == Scanner.FOR);
- // 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 {
- s.Expr = P.ParseExpression(1);
- }
- if keyword == Scanner.FOR {
- P.Expect(Scanner.SEMICOLON);
- if P.tok != Scanner.LBRACE {
- s.Post = P.OldParseSimpleStat(false);
- }
- }
- } else {
- if s.Init != nil { // guard in case of errors
- s.Expr, s.Init = s.Init.Expr, nil;
- }
- }
- P.expr_lev = prev_lev;
- }
-
- return s;
-}
-
-
func (P *Parser) ParseIfStat() *AST.IfStat {
if P.verbose {
P.Trace("IfStat");
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;
- */
+ body := AST.NewBlock(0, Scanner.LBRACE);
+ body.List.Push(else_);
+ else_ = &AST.CompositeStat{body};
}
} else {
P.Error(P.pos, "'if' or '{' expected - illegal 'else' branch");
}
-func (P *Parser) OldParseIfStat() *AST.StatImpl {
- if P.verbose {
- P.Trace("IfStat");
- defer P.Ecart();
- }
-
- P.OpenScope();
- s := P.OldParseControlClause(Scanner.IF);
- s.Body = P.ParseBlock(nil, Scanner.LBRACE);
- if P.tok == Scanner.ELSE {
- P.Next();
- s1 := AST.OldBadStat;
- if P.tok == Scanner.IF || P.tok == Scanner.LBRACE {
- s1 = P.OldParseStatement();
- } else if P.sixg {
- s1 = P.OldParseStatement();
- if s1 != nil {
- // not the empty statement
- assert(s1.Tok != Scanner.LBRACE);
- // wrap in a block since we don't have one
- 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");
- }
- s.Post = s1;
- }
- P.CloseScope();
-
- return s;
-}
-
-
func (P *Parser) ParseForStat() *AST.ForStat {
if P.verbose {
P.Trace("ForStat");
}
-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);
- P.CloseScope();
-
- return s;
-}
-
-
-func (P *Parser) ParseSwitchCase() *AST.StatImpl {
+func (P *Parser) ParseCaseClause() *AST.CaseClause {
if P.verbose {
- P.Trace("SwitchCase");
+ P.Trace("CaseClause");
defer P.Ecart();
}
- s := AST.NewStat(P.pos, P.tok);
+ // SwitchCase
+ pos := P.pos;
+ var expr AST.Expr;
if P.tok == Scanner.CASE {
P.Next();
- s.Expr = P.ParseExpressionList();
+ expr = P.ParseExpressionList();
} else {
P.Expect(Scanner.DEFAULT);
}
- return s;
-}
-
-
-func (P *Parser) ParseCaseClause() *AST.StatImpl {
- if P.verbose {
- P.Trace("CaseClause");
- defer P.Ecart();
- }
-
- s := P.ParseSwitchCase();
- s.Body = P.ParseBlock(nil, Scanner.COLON);
-
- return s;
+ return &AST.CaseClause{pos, expr, P.ParseBlock(nil, Scanner.COLON)};
}
}
-func (P *Parser) OldParseSwitchStat() *AST.StatImpl {
+func (P *Parser) ParseCommClause() *AST.CaseClause {
if P.verbose {
- P.Trace("SwitchStat");
- defer P.Ecart();
- }
-
- P.OpenScope();
- s := P.OldParseControlClause(Scanner.SWITCH);
- b := AST.NewBlock(P.pos, Scanner.LBRACE);
- P.Expect(Scanner.LBRACE);
- for P.tok != Scanner.RBRACE && P.tok != Scanner.EOF {
- b.List.Push(P.ParseCaseClause());
- }
- b.End = P.pos;
- P.Expect(Scanner.RBRACE);
- P.opt_semi = true;
- P.CloseScope();
- s.Body = b;
-
- return s;
-}
-
-
-func (P *Parser) ParseCommCase() *AST.StatImpl {
- if P.verbose {
- P.Trace("CommCase");
+ P.Trace("CommClause");
defer P.Ecart();
}
- s := AST.NewStat(P.pos, P.tok);
+ // CommCase
+ pos := P.pos;
+ var expr AST.Expr;
if P.tok == Scanner.CASE {
P.Next();
x := P.ParseExpression(1);
P.Expect(Scanner.ARROW); // use Expect() error handling
}
}
- s.Expr = x;
+ expr = x;
} else {
P.Expect(Scanner.DEFAULT);
}
- return s;
-}
-
-
-func (P *Parser) ParseCommClause() *AST.StatImpl {
- if P.verbose {
- P.Trace("CommClause");
- defer P.Ecart();
- }
-
- s := P.ParseCommCase();
- s.Body = P.ParseBlock(nil, Scanner.COLON);
-
- return s;
+ return &AST.CaseClause{pos, expr, P.ParseBlock(nil, Scanner.COLON)};
}
}
-func (P *Parser) OldParseSelectStat() *AST.StatImpl {
- if P.verbose {
- P.Trace("SelectStat");
- defer P.Ecart();
- }
-
- P.OpenScope();
- s := AST.NewStat(P.pos, Scanner.SELECT);
- P.Expect(Scanner.SELECT);
- b := AST.NewBlock(P.pos, Scanner.LBRACE);
- P.Expect(Scanner.LBRACE);
- for P.tok != Scanner.RBRACE && P.tok != Scanner.EOF {
- b.List.Push(P.ParseCommClause());
- }
- b.End = P.pos;
- P.Expect(Scanner.RBRACE);
- P.opt_semi = true;
- P.CloseScope();
- s.Body = b;
-
- return s;
-}
-
-
func (P *Parser) ParseStatement() AST.Stat {
if P.verbose {
P.Trace("Statement");
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.RETURN:
return P.ParseReturnStat();
case Scanner.BREAK, Scanner.CONTINUE, Scanner.GOTO, Scanner.FALLTHROUGH:
- s = P.ParseControlFlowStat(P.tok);
+ return P.ParseControlFlowStat(P.tok);
case Scanner.LBRACE:
- s = AST.NewStat(P.pos, Scanner.LBRACE);
- s.Body = P.ParseBlock(nil, Scanner.LBRACE);
+ return &AST.CompositeStat{P.ParseBlock(nil, Scanner.LBRACE)};
case Scanner.IF:
return P.ParseIfStat();
case Scanner.FOR:
}
-func (P *Parser) OldParseStatement() *AST.StatImpl {
- if P.verbose {
- P.Trace("Statement");
- defer P.Ecart();
- defer P.VerifyIndent(P.indent);
- }
-
- s := AST.OldBadStat;
- switch P.tok {
- case Scanner.CONST, Scanner.TYPE, Scanner.VAR:
- s = AST.NewStat(P.pos, P.tok);
- s.Decl = 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
- s = P.OldParseSimpleStat(false);
- case Scanner.GO, Scanner.DEFER:
- s = P.OldParseInvocationStat(P.tok);
- case Scanner.RETURN:
- s = P.OldParseReturnStat();
- 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:
- s = P.OldParseIfStat();
- case Scanner.FOR:
- s = P.OldParseForStat();
- case Scanner.SWITCH:
- s = P.OldParseSwitchStat();
- case Scanner.SELECT:
- s = P.OldParseSelectStat();
- default:
- // empty statement
- s = nil;
- }
-
- return s;
-}
-
-
// ----------------------------------------------------------------------------
// Declarations
}
-func (P *Printer) StatImpl(s *AST.StatImpl)
-
func (P *Printer) StatementList(list *array.Array) {
for i, n := 0, list.Len(); i < n; i++ {
P.newlines = 1; // for first entry
-
- 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();
- }
-
+ list.At(i).(AST.Stat).Visit(P);
P.newlines = 1;
P.state = inside_list;
}
}
-func (P *Printer) OldControlClause(s *AST.StatImpl) {
- has_post := s.Tok == Scanner.FOR && s.Post != nil; // post also used by "if"
-
- P.separator = blank;
- if s.Init == nil && !has_post {
- // no semicolons required
- if s.Expr != nil {
- P.Expr(s.Expr);
- }
- } else {
- // all semicolons required
- // (they are not separators, print them explicitly)
- if s.Init != nil {
- P.StatImpl(s.Init);
- P.separator = none;
- }
- P.String(0, ";");
- P.separator = blank;
- if s.Expr != nil {
- P.Expr(s.Expr);
- P.separator = none;
- }
- if s.Tok == Scanner.FOR {
- P.String(0, ";");
- P.separator = blank;
- if has_post {
- P.StatImpl(s.Post);
- }
- }
- }
- P.separator = blank;
-}
-
-
func (P *Printer) Declaration(d *AST.Decl, parenthesized bool);
-func (P *Printer) StatImpl(s *AST.StatImpl) {
- switch s.Tok {
- case Scanner.EXPRSTAT:
- // expression statement
- P.Expr(s.Expr);
- P.separator = semicolon;
-
- case Scanner.COLON:
- // label declaration
- P.indentation--;
- P.Expr(s.Expr);
- P.Token(s.Pos, s.Tok);
- P.indentation++;
- P.separator = none;
-
- case Scanner.CONST, Scanner.TYPE, Scanner.VAR:
- // declaration
- P.Declaration(s.Decl, false);
-
- case Scanner.INC, Scanner.DEC:
- P.Expr(s.Expr);
- P.Token(s.Pos, s.Tok);
- P.separator = semicolon;
-
- case Scanner.LBRACE:
- // block
- P.Block(s.Body, true);
-
- case Scanner.IF:
- P.String(s.Pos, "if");
- P.OldControlClause(s);
- P.Block(s.Body, true);
- if s.Post != nil {
- P.separator = blank;
- P.String(0, "else");
- P.separator = blank;
- P.StatImpl(s.Post);
- }
-
- case Scanner.FOR:
- P.String(s.Pos, "for");
- P.OldControlClause(s);
- P.Block(s.Body, true);
-
- case Scanner.SWITCH, Scanner.SELECT:
- P.Token(s.Pos, s.Tok);
- P.OldControlClause(s);
- P.Block(s.Body, false);
-
- case Scanner.CASE, Scanner.DEFAULT:
- P.Token(s.Pos, s.Tok);
- if s.Expr != nil {
- P.separator = blank;
- P.Expr(s.Expr);
- }
- // TODO: try to use P.Block instead
- // P.Block(s.Body, true);
- P.String(s.Body.Pos, ":");
- P.indentation++;
- P.StatementList(s.Body.List);
- P.indentation--;
- P.newlines = 1;
-
- case
- Scanner.GO, Scanner.DEFER, Scanner.RETURN, Scanner.FALLTHROUGH,
- Scanner.BREAK, Scanner.CONTINUE, Scanner.GOTO:
- P.Token(s.Pos, s.Tok);
- if s.Expr != nil {
- P.separator = blank;
- P.Expr(s.Expr);
- }
- P.separator = semicolon;
-
- default:
- P.Error(s.Pos, s.Tok, "stat");
- }
-}
-
func (P *Printer) DoBadStat(s *AST.BadStat) {
panic();
func (P *Printer) DoLabelDecl(s *AST.LabelDecl) {
- panic();
+ P.indentation--;
+ P.Expr(s.Label);
+ P.String(s.Pos, ":");
+ P.indentation++;
+ P.separator = none;
}
}
+func (P *Printer) DoCompositeStat(s *AST.CompositeStat) {
+ P.Block(s.Body, true);
+}
+
+
func (P *Printer) ControlClause(isForStat bool, init AST.Stat, expr AST.Expr, post AST.Stat) {
P.separator = blank;
if init == nil && post == nil {
}
+func (P *Printer) DoCaseClause(s *AST.CaseClause) {
+ if s.Expr != nil {
+ P.String(s.Pos, "case");
+ P.separator = blank;
+ P.Expr(s.Expr);
+ } else {
+ P.String(s.Pos, "default");
+ }
+ // TODO: try to use P.Block instead
+ // P.Block(s.Body, true);
+ P.String(s.Body.Pos, ":");
+ P.indentation++;
+ P.StatementList(s.Body.List);
+ P.indentation--;
+ P.newlines = 1;
+}
+
+
func (P *Printer) DoSwitchStat(s *AST.SwitchStat) {
P.String(s.Pos, "switch");
P.ControlClause(false, s.Init, s.Tag, nil);
func (P *Printer) DoSelectStat(s *AST.SelectStat) {
- panic();
+ P.String(s.Pos, "select");
+ P.separator = blank;
+ P.Block(s.Body, false);
}