case Scanner.COLON:
// label declaration
if x.len() == 1 {
+ s = Node.NewStat(P.pos, Scanner.COLON);
+ s.expr = x;
} else {
P.Error(P.pos, "illegal label declaration");
}
} else {
P.Error(P.pos, "more then one operand");
}
- P.Next();
+ P.Next(); // consume "++" or "--"
} else {
s = Node.NewStat(P.pos, 0); // TODO give this a token value
if x.len() == 1 {
s := Node.NewStat(P.pos, tok);
P.Expect(tok);
- if P.tok == Scanner.IDENT {
+ if tok != Scanner.FALLTHROUGH && P.tok == Scanner.IDENT {
s.expr = P.ParseIdent();
}
if P.tok == Scanner.IF {
s.post = P.ParseIfStat();
} else {
- s.post = P.ParseStatement();
+ // For 6g compliance - should really be P.ParseBlock()
+ t := P.ParseStatement();
+ if t.tok != Scanner.LBRACE {
+ // wrap in a block if we don't have one
+ t1 := Node.NewStat(P.pos, Scanner.LBRACE);
+ t1.block = Node.NewList();
+ t1.block.Add(t);
+ t = t1;
+ }
+ s.post = t;
}
}
}
-func (P *Parser) ParseFallthroughStat() *Node.Stat {
- P.Trace("FallthroughStat");
-
- s := Node.NewStat(P.pos, Scanner.FALLTHROUGH);
- P.Expect(Scanner.FALLTHROUGH);
-
- P.Ecart();
- return s;
-}
-
-
func (P *Parser) ParseRangeStat() *Node.Stat {
P.Trace("RangeStat");
s = Node.NewStat(P.pos, P.tok);
s.decl = P.ParseDeclaration();
case Scanner.FUNC:
- // for now we do not allow local function declarations
+ // 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
s = P.ParseGoStat();
case Scanner.RETURN:
s = P.ParseReturnStat();
- case Scanner.BREAK, Scanner.CONTINUE, Scanner.GOTO:
+ case Scanner.BREAK, Scanner.CONTINUE, Scanner.GOTO, Scanner.FALLTHROUGH:
s = P.ParseControlFlowStat(P.tok);
case Scanner.LBRACE:
s = Node.NewStat(P.pos, Scanner.LBRACE);
s = P.ParseRangeStat();
case Scanner.SELECT:
s = P.ParseSelectStat();
- case Scanner.FALLTHROUGH:
- s = P.ParseFallthroughStat();
default:
P.ParseEmptyStat(); // for complete tracing output only
}
level int; // true scope level
indent int; // indentation level
semi bool; // pending ";"
- newl bool; // pending "\n"
+ newl int; // pending "\n"'s
}
if P.semi && P.level > 0 { // no semicolons at level 0
print(";");
}
- if P.newl {
- print("\n");
+
+ if P.newl > 0 {
+ for i := P.newl; i > 0; i-- {
+ print("\n");
+ }
for i := P.indent; i > 0; i-- {
print("\t");
}
}
+
print(s);
- P.newl, P.semi = false, false;
+
+ P.semi, P.newl = false, 0;
}
}
-func (P *Printer) NewLine() { // explicit "\n"
- print("\n");
- P.semi, P.newl = false, true;
-}
-
-
func (P *Printer) OpenScope(paren string) {
- P.semi, P.newl = false, false;
+ P.semi, P.newl = false, 0;
P.String(0, paren);
P.level++;
P.indent++;
- P.newl = true;
+ P.newl = 1;
}
P.semi = false;
P.String(0, paren);
P.level--;
- P.semi, P.newl = false, true;
+ P.semi, P.newl = false, 1;
}
if i > 0 {
if prev == Scanner.TYPE {
P.String(0, ";");
- P.newl = true;
+ P.newl = 1;
} else if prev == x.tok {
P.String(0, ", ");
} else {
P.Expr(x);
prev = x.tok;
}
- P.newl = true;
+ P.newl = 1;
}
func (P *Printer) StatementList(list *Node.List) {
for i, n := 0, list.len(); i < n; i++ {
P.Stat(list.at(i).(*Node.Stat));
- P.newl = true;
+ P.newl = 1;
}
}
switch s.tok {
case 0: // TODO use a real token const
+ // expression statement
P.Expr(s.expr);
P.semi = true;
+ case Scanner.COLON:
+ // label declaration
+ P.indent--;
+ P.Expr(s.expr);
+ P.Token(s.pos, s.tok);
+ P.indent++;
+ P.semi = false;
+
case Scanner.CONST, Scanner.TYPE, Scanner.VAR:
+ // declaration
P.Declaration(s.decl, false);
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:
+ // assignment
P.Expr(s.lhs);
P.Blank();
P.Token(s.pos, s.tok);
P.semi = true;
case Scanner.LBRACE:
+ // block
P.Block(s.block, true);
case Scanner.IF:
P.ControlClause(s);
P.Block(s.block, true);
if s.post != nil {
- P.newl = false;
+ P.newl = 0;
P.String(0, " else ");
P.Stat(s.post);
}
P.StatementList(s.block);
P.CloseScope("");
- case Scanner.GO, Scanner.RETURN, Scanner.BREAK, Scanner.CONTINUE, Scanner.GOTO:
+ case Scanner.GO, Scanner.RETURN, Scanner.FALLTHROUGH, Scanner.BREAK, Scanner.CONTINUE, Scanner.GOTO:
P.Token(s.pos, s.tok);
- P.Blank();
- P.Expr(s.expr);
+ if s.expr != nil {
+ P.Blank();
+ P.Expr(s.expr);
+ }
P.semi = true;
default:
P.OpenScope("(");
for i := 0; i < d.list.len(); i++ {
P.Declaration(d.list.at(i).(*Node.Decl), true);
- P.newl, P.semi = true, true;
+ P.semi, P.newl = true, 1;
}
P.CloseScope(")");
} else {
P.Expr(d.ident);
+
if d.typ != nil {
P.Blank();
P.Type(d.typ);
}
+
if d.val != nil {
if d.tok == Scanner.IMPORT {
P.Blank();
}
P.Expr(d.val);
}
+
if d.list != nil {
if d.tok != Scanner.FUNC {
panic("must be a func declaration");
P.Block(d.list, true);
}
}
+
+ P.newl = 1;
+ // extra newline after a function declaration
+ if d.tok == Scanner.FUNC {
+ P.newl++;
+ }
+
// extra newline at the top level
if P.level == 0 {
- P.NewLine();
+ P.newl++;
}
-
- P.newl = true;
}
func (P *Printer) Program(p *Node.Program) {
P.String(p.pos, "package ");
P.Expr(p.ident);
- P.NewLine();
+ P.newl = 2;
for i := 0; i < p.decls.len(); i++ {
P.Declaration(p.decls.at(i), false);
}
- P.newl = true;
+ P.newl = 1;
P.String(0, ""); // flush
}