]> Cypherpunks repositories - gostls13.git/commitdiff
- fixed semicolon handling in pretty printer
authorRobert Griesemer <gri@golang.org>
Wed, 1 Oct 2008 01:50:29 +0000 (18:50 -0700)
committerRobert Griesemer <gri@golang.org>
Wed, 1 Oct 2008 01:50:29 +0000 (18:50 -0700)
- some scanner cleanup
- new pretty-printed code can be compiled again (for some files)

R=r
OCL=16272
CL=16272

usr/gri/pretty/parser.go
usr/gri/pretty/printer.go
usr/gri/pretty/scanner.go

index 67ce5445ecd07a83ad24b387efe3c3bcc5e90352..d9a3d31da2e3585322a0116eb1808384548ae9d0 100644 (file)
@@ -14,9 +14,9 @@ export type Parser struct {
        scanner *Scanner.Scanner;
        tokchan *<-chan *Scanner.Token;
        
-       // Token
-       tok int;  // one token look-ahead
+       // Scanner.Token
        pos int;  // token source position
+       tok int;  // one token look-ahead
        val string;  // token value (for IDENT, NUMBER, STRING only)
 
        // Nesting level
@@ -54,7 +54,7 @@ func (P *Parser) Ecart() {
 
 func (P *Parser) Next() {
        if P.tokchan == nil {
-               P.tok, P.pos, P.val = P.scanner.Scan();
+               P.pos, P.tok, P.val = P.scanner.Scan();
        } else {
                t := <-P.tokchan;
                P.tok, P.pos, P.val = t.tok, t.pos, t.val;
@@ -336,22 +336,22 @@ func (P *Parser) ParseResultList() {
 func (P *Parser) ParseResult() *AST.List {
        P.Trace("Result");
        
+       var result *AST.List;
        if P.tok == Scanner.LPAREN {
-               P.Next();
-               P.ParseResultList();
-               for P.tok == Scanner.COMMA {
-                       P.Next();
-                       P.ParseResultList();
-               }
-               P.Expect(Scanner.RPAREN);
-
+               result = P.ParseParameters();
        } else {
-               // anonymous result
-               P.TryType();
+               typ, ok := P.TryType();
+               if ok {
+                       vars := new(AST.VarDeclList);
+                       vars.typ = typ;
+                       list := AST.NewList();
+                       list.Add(vars);
+                       result = list;
+               }
        }
 
        P.Ecart();
-       return nil
+       return result;
 }
 
 
@@ -1008,11 +1008,7 @@ func (P *Parser) ParseControlClause(keyword int) *AST.ControlClause {
                                }
                        }
                } else {
-                       //ctrl.expr, ctrl.has_expr = ctrl.init, ctrl.has_init;
-                       
-                       ctrl.expr = ctrl.init;
-                       ctrl.has_expr = ctrl.has_init;
-                       
+                       ctrl.expr, ctrl.has_expr = ctrl.init, ctrl.has_init;
                        ctrl.init, ctrl.has_init = AST.NIL, false;
                }
        }
index 747655d22f94bda5cc61a32615e25db2a309abff..5a6af888787020a5d6d1bb4c5e1d47e3fb2adc52 100644 (file)
@@ -10,25 +10,50 @@ import AST "ast"
 
 // Printer implements AST.Visitor
 type Printer struct {
-       indent int;
+       level int;  // true scope level
+       indent int;  // indentation level
+       semi bool;  // pending ";"
+       newl bool;  // pending "\n"
        prec int;  // operator precedence
 }
 
 
-func (P *Printer) NewLine(delta int) {
-       P.indent += delta;
-       if P.indent < 0 {
-               panic("negative indent");
+func (P *Printer) String(s string) {
+       if P.semi && P.level > 0 {  // no semicolons at level 0
+               print(";");
        }
-       print("\n");
-       for i := P.indent; i > 0; i-- {
-               print("\t");
+       if P.newl {
+               print("\n");
+               for i := P.indent; i > 0; i-- {
+                       print("\t");
+               }
        }
+       print(s);
+       P.newl, P.semi = false, false;
 }
 
 
-func (P *Printer) String(s string) {
-       print(s);
+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.String(paren);
+       P.level++;
+       P.indent++;
+       P.newl = true;
+}
+
+
+func (P *Printer) CloseScope(paren string) {
+       P.level--;
+       P.indent--;
+       P.newl = true;
+       P.String(paren);
+       P.semi, P.newl = false, true;
 }
 
 
@@ -70,6 +95,11 @@ func (P *Printer) DoFunctionType(x *AST.FunctionType) {
        P.String("(");
        P.PrintList(x.params);
        P.String(")");
+       if x.result != nil {
+               P.String(" (");
+               P.PrintList(x.result);
+               P.String(")");
+       }
 }
 
 
@@ -82,19 +112,13 @@ func (P *Printer) DoArrayType(x *AST.ArrayType) {
 
 
 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("struct ");
+       P.OpenScope("{");
+       for i := 0; i < x.fields.len(); i++ {
+               P.Print(x.fields.at(i));
+               P.newl, P.semi = true, true;
        }
-       P.String("}");
+       P.CloseScope("}");
 }
 
 
@@ -117,19 +141,13 @@ func (P *Printer) DoChannelType(x *AST.ChannelType) {
 
 
 func (P *Printer) DoInterfaceType(x *AST.InterfaceType) {
-       P.String("interface {");
-       if x.methods.len() > 0 {
-               P.NewLine(1);
-               for i := 0; i < x.methods.len(); i++ {
-                       if i > 0 {
-                               P.NewLine(0);
-                       }
-                       P.Print(x.methods.at(i));
-                       P.String(";");
-               }
-               P.NewLine(-1);
+       P.String("interface ");
+       P.OpenScope("{");
+       for i := 0; i < x.methods.len(); i++ {
+               P.Print(x.methods.at(i));
+               P.newl, P.semi = true, true;
        }
-       P.String("}");
+       P.CloseScope("}");
 }
 
 
@@ -160,6 +178,7 @@ func (P *Printer) DoConstDecl(x *AST.ConstDecl) {
        P.Print(x.typ);
        P.String(" = ");
        P.Print(x.val);
+       P.semi = true;
 }
 
 
@@ -167,6 +186,7 @@ func (P *Printer) DoTypeDecl(x *AST.TypeDecl) {
        P.Print(x.ident);
        P.String(" ");
        P.Print(x.typ);
+       P.semi = true;
 }
 
 
@@ -178,6 +198,7 @@ func (P *Printer) DoVarDecl(x *AST.VarDecl) {
                P.String(" = ");
                P.PrintList(x.vals);
        }
+       P.semi = true;
 }
 
 
@@ -199,15 +220,13 @@ func (P *Printer) DoFuncDecl(x *AST.FuncDecl) {
        }
        P.DoIdent(x.ident);
        P.DoFunctionType(x.typ);
-       P.String(" ");
        if x.body != nil {
                P.DoBlock(x.body);
        } else {
-               P.String(";");
+               P.String(" ;");
        }
-       P.NewLine(0);
-       P.NewLine(0);
-       P.NewLine(0);
+       P.NewLine();
+       P.NewLine();
 }
 
 
@@ -226,19 +245,17 @@ func (P *Printer) DoDeclaration(x *AST.Declaration) {
        case 1:
                P.Print(x.decls.at(0));
        default:
-               P.String("(");
-               P.NewLine(1);
+               P.OpenScope(" (");
                for i := 0; i < x.decls.len(); i++ {
-                       if i > 0 {
-                               P.NewLine(0);
-                       }
                        P.Print(x.decls.at(i));
-                       P.String(";");
+                       P.newl, P.semi = true, true;
                }
-               P.NewLine(-1);
-               P.String(")");
+               P.CloseScope(")");
+       }
+       if P.level == 0 {
+               P.NewLine();
        }
-       P.NewLine(0);
+       P.newl = true;
 }
 
 
@@ -326,23 +343,18 @@ func (P *Printer) DoFunctionLit(x *AST.FunctionLit) {
 // Statements
 
 func (P *Printer) DoBlock(x *AST.Block) {
-       P.String("{");
-       if x.stats != nil {
-               P.NewLine(1);
-               for i := 0; i < x.stats.len(); i++ {
-                       if i > 0 {
-                               P.NewLine(0);
-                       }
-                       P.Print(x.stats.at(i));
-               }
-               P.NewLine(-1);
+       P.OpenScope("{");
+       for i := 0; i < x.stats.len(); i++ {
+               P.Print(x.stats.at(i));
+               P.newl = true;
        }
-       P.String("}");
+       P.CloseScope("}");
 }
 
 
 func (P *Printer) DoLabel(x *AST.Label) {
-       P.NewLine(-1);
+       P.indent--;
+       P.newl = true;
        P.Print(x.ident);
        P.String(":");
        P.indent++;
@@ -351,7 +363,7 @@ func (P *Printer) DoLabel(x *AST.Label) {
 
 func (P *Printer) DoExprStat(x *AST.ExprStat) {
        P.Print(x.expr);
-       //P.String(";");
+       P.semi = true;
 }
 
 
@@ -359,7 +371,7 @@ func (P *Printer) DoAssignment(x *AST.Assignment) {
        P.PrintList(x.lhs);
        P.String(" " + Scanner.TokenName(x.tok) + " ");
        P.PrintList(x.rhs);
-       //P.String(";");
+       P.semi = true;
 }
 
 
@@ -367,15 +379,19 @@ func (P *Printer) PrintControlClause(x *AST.ControlClause) {
        if x.has_init {
                P.String(" ");
                P.Print(x.init);
-               P.String(";");
+               P.semi = true;
+               P.String("");
        }
        if x.has_expr {
                P.String(" ");
                P.Print(x.expr);
+               P.semi = false;
        }
        if x.has_post {
-               P.String("; ");
+               P.semi = true;
+               P.String(" ");
                P.Print(x.post);
+               P.semi = false;
        }
        P.String(" ");
 }
@@ -386,6 +402,7 @@ func (P *Printer) DoIfStat(x *AST.IfStat) {
        P.PrintControlClause(x.ctrl);
        P.DoBlock(x.then);
        if x.has_else {
+               P.newl = false;
                P.String(" else ");
                P.Print(x.else_);
        }
@@ -399,19 +416,6 @@ func (P *Printer) DoForStat(x *AST.ForStat) {
 }
 
 
-/*
-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 ");
@@ -421,57 +425,42 @@ func (P *Printer) DoCaseClause(x *AST.CaseClause) {
                P.String("default:");
        }
        
-       n := x.stats.len();
-       m := n;
-       if x.falls {
-               m++;
+       P.OpenScope("");
+       for i := 0; i < x.stats.len(); i++ {
+               P.Print(x.stats.at(i));
+               P.newl = true;
        }
-       
-       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);
+       if x.falls {
+               P.String("fallthrough");
        }
+       P.CloseScope("");
 }
 
 
 func (P *Printer) DoSwitchStat(x *AST.SwitchStat) {
-       P.String("switch");
+       P.String("switch ");
        P.PrintControlClause(x.ctrl);
-       P.String("{");
-       P.NewLine(0);
+       P.OpenScope("{");
+       P.indent--;
        for i := 0; i < x.cases.len(); i++ {
                P.Print(x.cases.at(i));
        }
-       P.NewLine(0);
-       P.String("}");
+       P.indent++;
+       P.CloseScope("}");
 }
 
 
 func (P *Printer) DoReturnStat(x *AST.ReturnStat) {
        P.String("return ");
        P.PrintList(x.res);
-       P.String(";");
+       P.semi = true;
 }
 
 
 func (P *Printer) DoIncDecStat(x *AST.IncDecStat) {
        P.Print(x.expr);
        P.String(Scanner.TokenName(x.tok));
-       //P.String(";");
+       P.semi = true;
 }
 
 
@@ -481,14 +470,14 @@ func (P *Printer) DoControlFlowStat(x *AST.ControlFlowStat) {
                P.String(" ");
                P.Print(x.label);
        }
-       P.String(";");
+       P.semi = true;
 }
 
 
 func (P *Printer) DoGoStat(x *AST.GoStat) {
        P.String("go ");
        P.Print(x.expr);
-       P.String(";");
+       P.semi = true;
 }
 
 
@@ -498,10 +487,12 @@ func (P *Printer) DoGoStat(x *AST.GoStat) {
 func (P *Printer) DoProgram(x *AST.Program) {
        P.String("package ");
        P.DoIdent(x.ident);
-       P.NewLine(0);
+       P.NewLine();
        for i := 0; i < x.decls.len(); i++ {
                P.Print(x.decls.at(i));
        }
+       P.newl = true;
+       P.String("");
 }
 
 
index 02f5e56fe985fa37869cfd0342eef1420ceba68a..841f6eb621ec484902815d94b11a34b2d998eaa4 100644 (file)
@@ -10,54 +10,25 @@ import Utils "utils"
 
 export const (
        ILLEGAL = iota;
-       EOF;
+
        IDENT;
        INT;
        FLOAT;
        STRING;
+       EOF;
 
-       COMMA;
-       COLON;
-       SEMICOLON;
-       PERIOD;
-
-       LPAREN;
-       RPAREN;
-       LBRACK;
-       RBRACK;
-       LBRACE;
-       RBRACE;
-       
-       ASSIGN;
-       DEFINE;
-       
-       INC;
-       DEC;
-       NOT;
-       
-       AND;
-       OR;
-       XOR;
-       
        ADD;
        SUB;
        MUL;
        QUO;
        REM;
        
-       EQL;
-       NEQ;
-       LSS;
-       LEQ;
-       GTR;
-       GEQ;
-
+       AND;
+       OR;
+       XOR;
        SHL;
        SHR;
        
-       ARROW;
-       HASH;
-
        ADD_ASSIGN;
        SUB_ASSIGN;
        MUL_ASSIGN;
@@ -67,13 +38,40 @@ export const (
        AND_ASSIGN;
        OR_ASSIGN;
        XOR_ASSIGN;
-       
        SHL_ASSIGN;
        SHR_ASSIGN;
 
        LAND;
        LOR;
+       ARROW;
+       INC;
+       DEC;
        
+       EQL;
+       NEQ;
+       LSS;
+       LEQ;
+       GTR;
+       GEQ;
+
+       ASSIGN;
+       DEFINE;
+       NOT;
+       ELLIPSIS;
+       HASH;
+       
+       LPAREN;
+       RPAREN;
+       LBRACK;
+       RBRACK;
+       LBRACE;
+       RBRACE;
+       
+       COMMA;
+       SEMICOLON;
+       COLON;
+       PERIOD;
+
        // keywords
        KEYWORDS_BEG;
        BREAK;
@@ -81,21 +79,25 @@ export const (
        CHAN;
        CONST;
        CONTINUE;
+       
        DEFAULT;
        ELSE;
        EXPORT;
        FALLTHROUGH;
        FOR;
+       
        FUNC;
        GO;
        GOTO;
        IF;
        IMPORT;
+       
        INTERFACE;
        MAP;
        PACKAGE;
        RANGE;
        RETURN;
+       
        SELECT;
        STRUCT;
        SWITCH;
@@ -105,61 +107,28 @@ export const (
 )
 
 
-var Keywords *map [string] int;
-var VerboseMsgs bool;  // error message customization
-
-
 export func TokenName(tok int) string {
        switch (tok) {
-       case ILLEGAL: return "illegal";
-       case EOF: return "eof";
-       case IDENT: return "ident";
-       case INT: return "int";
-       case FLOAT: return "float";
-       case STRING: return "string";
-
-       case COMMA: return ",";
-       case COLON: return ":";
-       case SEMICOLON: return ";";
-       case PERIOD: return ".";
-
-       case LPAREN: return "(";
-       case RPAREN: return ")";
-       case LBRACK: return "[";
-       case RBRACK: return "]";
-       case LBRACE: return "LBRACE";
-       case RBRACE: return "RBRACE";
-
-       case ASSIGN: return "=";
-       case DEFINE: return ":=";
+       case ILLEGAL: return "ILLEGAL";
        
-       case INC: return "++";
-       case DEC: return "--";
-       case NOT: return "!";
+       case IDENT: return "IDENT";
+       case INT: return "INT";
+       case FLOAT: return "FLOAT";
+       case STRING: return "STRING";
+       case EOF: return "EOF";
 
-       case AND: return "&";
-       case OR: return "|";
-       case XOR: return "^";
-       
        case ADD: return "+";
        case SUB: return "-";
        case MUL: return "*";
        case QUO: return "/";
        case REM: return "%";
        
-       case EQL: return "==";
-       case NEQ: return "!=";
-       case LSS: return "<";
-       case LEQ: return "<=";
-       case GTR: return ">";
-       case GEQ: return ">=";
-
+       case AND: return "&";
+       case OR: return "|";
+       case XOR: return "^";
        case SHL: return "<<";
        case SHR: return ">>";
        
-       case ARROW: return "<-";
-       case HASH: return "#";
-
        case ADD_ASSIGN: return "+=";
        case SUB_ASSIGN: return "-=";
        case MUL_ASSIGN: return "+=";
@@ -169,33 +138,64 @@ export func TokenName(tok int) string {
        case AND_ASSIGN: return "&=";
        case OR_ASSIGN: return "|=";
        case XOR_ASSIGN: return "^=";
-
        case SHL_ASSIGN: return "<<=";
        case SHR_ASSIGN: return ">>=";
 
        case LAND: return "&&";
        case LOR: return "||";
+       case ARROW: return "<-";
+       case INC: return "++";
+       case DEC: return "--";
+
+       case EQL: return "==";
+       case NEQ: return "!=";
+       case LSS: return "<";
+       case LEQ: return "<=";
+       case GTR: return ">";
+       case GEQ: return ">=";
+
+       case ASSIGN: return "=";
+       case DEFINE: return ":=";
+       case NOT: return "!";
+       case ELLIPSIS: return "...";
+       case HASH: return "#";
+
+       case LPAREN: return "(";
+       case RPAREN: return ")";
+       case LBRACK: return "[";
+       case RBRACK: return "]";
+       case LBRACE: return "LBRACE";
+       case RBRACE: return "RBRACE";
+
+       case COMMA: return ",";
+       case SEMICOLON: return ";";
+       case COLON: return ":";
+       case PERIOD: return ".";
 
        case BREAK: return "break";
        case CASE: return "case";
        case CHAN: return "chan";
        case CONST: return "const";
        case CONTINUE: return "continue";
+
        case DEFAULT: return "default";
        case ELSE: return "else";
        case EXPORT: return "export";
        case FALLTHROUGH: return "fallthrough";
        case FOR: return "for";
+
        case FUNC: return "func";
        case GO: return "go";
        case GOTO: return "goto";
        case IF: return "if";
        case IMPORT: return "import";
+
        case INTERFACE: return "interface";
        case MAP: return "map";
        case PACKAGE: return "package";
        case RANGE: return "range";
        case RETURN: return "return";
+
        case SELECT: return "select";
        case STRUCT: return "struct";
        case SWITCH: return "switch";
@@ -203,7 +203,7 @@ export func TokenName(tok int) string {
        case VAR: return "var";
        }
        
-       return "???";
+       panic("UNREACHABLE");
 }
 
 
@@ -227,10 +227,14 @@ export func Precedence(tok int) int {
 }
 
 
+var Keywords *map [string] int;
+var VerboseMsgs bool;  // error message customization
+
+
 func init() {
        Keywords = new(map [string] int);
        
-       for i := KEYWORDS_BEG; i <= KEYWORDS_END; i++ {
+       for i := KEYWORDS_BEG + 1; i < KEYWORDS_END; i++ {
          Keywords[TokenName(i)] = i;
        }
        
@@ -277,7 +281,6 @@ export type Scanner struct {
 
 // Read the next Unicode char into S.ch.
 // S.ch < 0 means end-of-file.
-//
 func (S *Scanner) Next() {
        const (
                Bit1 = 7;
@@ -718,12 +721,12 @@ func (S *Scanner) Select4(tok0, tok1, ch2, tok2, tok3 int) int {
 }
 
 
-func (S *Scanner) Scan() (tok, pos int, val string) {
+func (S *Scanner) Scan() (pos, tok int, val string) {
        S.SkipWhitespace();
        
        ch := S.ch;
-       tok = ILLEGAL;
        pos = S.chpos;
+       tok = ILLEGAL;
        
        switch {
        case is_letter(ch): tok, val = S.ScanIdentifier();
@@ -739,6 +742,12 @@ func (S *Scanner) Scan() (tok, pos int, val string) {
                case '.':
                        if digit_val(S.ch) < 10 {
                                tok, val = S.ScanNumber(true);
+                       } else if S.ch == '.' {
+                               S.Next();
+                               if S.ch == '.' {
+                                       S.Next();
+                                       tok = ELLIPSIS;
+                               }
                        } else {
                                tok = PERIOD;
                        }
@@ -782,7 +791,7 @@ func (S *Scanner) Scan() (tok, pos int, val string) {
                }
        }
        
-       return tok, pos, val;
+       return pos, tok, val;
 }
 
 
@@ -798,7 +807,7 @@ func (S *Scanner) TokenStream() *<-chan *Token {
        go func(S *Scanner, ch *chan <- *Token) {
                for {
                        t := new(Token);
-                       t.tok, t.pos, t.val = S.Scan();
+                       t.pos, t.tok, t.val = S.Scan();
                        ch <- t;
                        if t.tok == EOF {
                                break;