mirror of https://github.com/golang/go.git
- more missing constructs added
- removed excessive ";"'s - no ()'s around expressions where not needed - parser.go now reproduced and parseable again R=r OCL=15881 CL=15881
This commit is contained in:
parent
b70d42f323
commit
8415280699
|
|
@ -23,11 +23,13 @@ export type Visitor interface {
|
|||
DoPointerType(x *PointerType);
|
||||
|
||||
// Declarations
|
||||
DoImportDecl(x *ImportDecl);
|
||||
DoConstDecl(x *ConstDecl);
|
||||
DoTypeDecl(x *TypeDecl);
|
||||
DoVarDecl(x *VarDecl);
|
||||
DoVarDeclList(x *VarDeclList);
|
||||
DoFuncDecl(x *FuncDecl);
|
||||
DoMethodDecl(x *MethodDecl);
|
||||
DoDeclaration(x *Declaration);
|
||||
|
||||
// Expressions
|
||||
|
|
@ -40,6 +42,7 @@ export type Visitor interface {
|
|||
DoSelector(x *Selector);
|
||||
|
||||
// Statements
|
||||
DoLabel(x *Label);
|
||||
DoBlock(x *Block);
|
||||
DoExprStat(x *ExprStat);
|
||||
DoAssignment(x *Assignment);
|
||||
|
|
@ -50,7 +53,8 @@ export type Visitor interface {
|
|||
DoReturnStat(x *ReturnStat);
|
||||
DoIncDecStat(x *IncDecStat);
|
||||
DoControlFlowStat(x *ControlFlowStat);
|
||||
|
||||
DoGoStat(x *GoStat);
|
||||
|
||||
// Program
|
||||
DoProgram(x *Program);
|
||||
}
|
||||
|
|
@ -71,7 +75,7 @@ export type Node interface {
|
|||
// Thus, empty lists can be represented by nil.
|
||||
|
||||
export type List struct {
|
||||
a *[] Node
|
||||
a *[] Node;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -176,6 +180,8 @@ export type PointerType struct {
|
|||
|
||||
|
||||
export type InterfaceType struct {
|
||||
pos int; // position of "interface"
|
||||
methods *List; // list of *MethodDecl
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -210,6 +216,12 @@ export type VarDeclList struct {
|
|||
}
|
||||
|
||||
|
||||
export type ImportDecl struct {
|
||||
ident *Ident;
|
||||
file string;
|
||||
}
|
||||
|
||||
|
||||
export type ConstDecl struct {
|
||||
ident *Ident;
|
||||
typ Type;
|
||||
|
|
@ -245,11 +257,19 @@ export type FuncDecl struct {
|
|||
}
|
||||
|
||||
|
||||
export type MethodDecl struct {
|
||||
ident *Ident;
|
||||
typ *FunctionType;
|
||||
}
|
||||
|
||||
|
||||
func (x *VarDeclList) Visit(v Visitor) { v.DoVarDeclList(x); }
|
||||
func (x *ImportDecl) Visit(v Visitor) { v.DoImportDecl(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 *MethodDecl) Visit(v Visitor) { v.DoMethodDecl(x); }
|
||||
func (x *Declaration) Visit(v Visitor) { v.DoDeclaration(x); }
|
||||
|
||||
|
||||
|
|
@ -321,6 +341,12 @@ export type Stat interface {
|
|||
}
|
||||
|
||||
|
||||
export type Label struct {
|
||||
pos int; // position of ":"
|
||||
ident Expr; // should be ident
|
||||
}
|
||||
|
||||
|
||||
export type Block struct {
|
||||
pos int; // position of "{"
|
||||
stats *List;
|
||||
|
|
@ -398,7 +424,14 @@ export type ControlFlowStat struct {
|
|||
}
|
||||
|
||||
|
||||
export type GoStat struct {
|
||||
pos int; // position of "go"
|
||||
expr Expr;
|
||||
}
|
||||
|
||||
|
||||
func (x *Block) Visit(v Visitor) { v.DoBlock(x); }
|
||||
func (x *Label) Visit(v Visitor) { v.DoLabel(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); }
|
||||
|
|
@ -408,6 +441,8 @@ 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); }
|
||||
func (x *ControlFlowStat) Visit(v Visitor) { v.DoControlFlowStat(x); }
|
||||
func (x *GoStat) Visit(v Visitor) { v.DoGoStat(x); }
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Program
|
||||
|
|
|
|||
|
|
@ -251,12 +251,12 @@ func (P *Parser) ParseChannelType() *AST.ChannelType {
|
|||
func (P *Parser) ParseVarDeclList() *AST.VarDeclList {
|
||||
P.Trace("VarDeclList");
|
||||
|
||||
res := new(AST.VarDeclList);
|
||||
res.idents = P.ParseIdentList();
|
||||
res.typ = P.ParseVarType();
|
||||
vars := new(AST.VarDeclList);
|
||||
vars.idents = P.ParseIdentList();
|
||||
vars.typ = P.ParseVarType();
|
||||
|
||||
P.Ecart();
|
||||
return res;
|
||||
return vars;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -355,33 +355,39 @@ func (P *Parser) ParseFunctionType() *AST.FunctionType {
|
|||
}
|
||||
|
||||
|
||||
func (P *Parser) ParseMethodDecl() {
|
||||
func (P *Parser) ParseMethodDecl() *AST.MethodDecl {
|
||||
P.Trace("MethodDecl");
|
||||
|
||||
ident := P.ParseIdent();
|
||||
P.ParseFunctionType();
|
||||
decl := new(AST.MethodDecl);
|
||||
decl.ident = P.ParseIdent();
|
||||
decl.typ = P.ParseFunctionType();
|
||||
P.Optional(Scanner.SEMICOLON);
|
||||
|
||||
P.Ecart();
|
||||
return decl;
|
||||
}
|
||||
|
||||
|
||||
func (P *Parser) ParseInterfaceType() *AST.InterfaceType {
|
||||
P.Trace("InterfaceType");
|
||||
|
||||
typ := new(AST.InterfaceType);
|
||||
typ.pos = P.pos;
|
||||
typ.methods = AST.NewList();
|
||||
|
||||
P.Expect(Scanner.INTERFACE);
|
||||
P.Expect(Scanner.LBRACE);
|
||||
P.OpenScope();
|
||||
P.level--;
|
||||
for P.tok >= Scanner.IDENT {
|
||||
P.ParseMethodDecl();
|
||||
for P.tok == Scanner.IDENT {
|
||||
typ.methods.Add(P.ParseMethodDecl());
|
||||
}
|
||||
P.level++;
|
||||
P.CloseScope();
|
||||
P.Expect(Scanner.RBRACE);
|
||||
|
||||
P.Ecart();
|
||||
return nil;
|
||||
return typ;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -413,7 +419,7 @@ func (P *Parser) ParseStructType() *AST.StructType {
|
|||
P.Expect(Scanner.LBRACE);
|
||||
P.OpenScope();
|
||||
P.level--;
|
||||
for P.tok >= Scanner.IDENT {
|
||||
for P.tok == Scanner.IDENT {
|
||||
typ.fields.Add(P.ParseVarDeclList());
|
||||
if P.tok != Scanner.RBRACE {
|
||||
P.Expect(Scanner.SEMICOLON);
|
||||
|
|
@ -505,23 +511,21 @@ func (P *Parser) ParseStatementList() *AST.List {
|
|||
func (P *Parser) ParseBlock() *AST.Block {
|
||||
P.Trace("Block");
|
||||
|
||||
pos := P.pos;
|
||||
block := new(AST.Block);
|
||||
block.pos = P.pos;
|
||||
|
||||
P.Expect(Scanner.LBRACE);
|
||||
P.OpenScope();
|
||||
|
||||
var stats *AST.List;
|
||||
if P.tok != Scanner.RBRACE && P.tok != Scanner.SEMICOLON {
|
||||
stats = P.ParseStatementList();
|
||||
block.stats = P.ParseStatementList();
|
||||
}
|
||||
P.Optional(Scanner.SEMICOLON);
|
||||
P.CloseScope();
|
||||
P.Expect(Scanner.RBRACE);
|
||||
|
||||
P.Ecart();
|
||||
|
||||
x := new(AST.Block);
|
||||
x.pos, x.stats = pos, stats;
|
||||
return x;
|
||||
return block;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -619,36 +623,37 @@ func (P *Parser) ParseCompositeLit() AST.Expr {
|
|||
func (P *Parser) ParseOperand() AST.Expr {
|
||||
P.Trace("Operand");
|
||||
|
||||
var z AST.Expr;
|
||||
var op AST.Expr;
|
||||
|
||||
switch P.tok {
|
||||
case Scanner.IDENT:
|
||||
z = P.ParseIdent();
|
||||
op = P.ParseIdent();
|
||||
|
||||
case Scanner.LPAREN:
|
||||
P.Next();
|
||||
z = P.ParseExpression();
|
||||
op = P.ParseExpression();
|
||||
P.Expect(Scanner.RPAREN);
|
||||
|
||||
case Scanner.INT, Scanner.FLOAT, Scanner.STRING:
|
||||
x := new(AST.Literal);
|
||||
x.pos, x.tok, x.val = P.pos, P.tok, P.val;
|
||||
z = x;
|
||||
lit := new(AST.Literal);
|
||||
lit.pos, lit.tok, lit.val = P.pos, P.tok, P.val;
|
||||
op = lit;
|
||||
P.Next();
|
||||
|
||||
case Scanner.FUNC:
|
||||
z = P.ParseFunctionLit();
|
||||
op = P.ParseFunctionLit();
|
||||
|
||||
case Scanner.HASH:
|
||||
P.Next();
|
||||
P.ParseType();
|
||||
P.ParseCompositeLit();
|
||||
z = nil;
|
||||
op = AST.NIL;
|
||||
|
||||
default:
|
||||
if P.tok != Scanner.IDENT {
|
||||
typ, ok := P.TryType();
|
||||
if ok {
|
||||
z = P.ParseCompositeLit();
|
||||
op = P.ParseCompositeLit();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -658,7 +663,7 @@ func (P *Parser) ParseOperand() AST.Expr {
|
|||
}
|
||||
|
||||
P.Ecart();
|
||||
return z;
|
||||
return op;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -789,32 +794,12 @@ func (P *Parser) ParseUnaryExpr() AST.Expr {
|
|||
}
|
||||
|
||||
|
||||
func Precedence(tok int) int {
|
||||
// TODO should use a map or array here for lookup
|
||||
switch tok {
|
||||
case Scanner.LOR:
|
||||
return 1;
|
||||
case Scanner.LAND:
|
||||
return 2;
|
||||
case Scanner.ARROW:
|
||||
return 3;
|
||||
case Scanner.EQL, Scanner.NEQ, Scanner.LSS, Scanner.LEQ, Scanner.GTR, Scanner.GEQ:
|
||||
return 4;
|
||||
case Scanner.ADD, Scanner.SUB, Scanner.OR, Scanner.XOR:
|
||||
return 5;
|
||||
case Scanner.MUL, Scanner.QUO, Scanner.REM, Scanner.SHL, Scanner.SHR, Scanner.AND:
|
||||
return 6;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
func (P *Parser) ParseBinaryExpr(prec1 int) AST.Expr {
|
||||
P.Trace("BinaryExpr");
|
||||
|
||||
x := P.ParseUnaryExpr();
|
||||
for prec := Precedence(P.tok); prec >= prec1; prec-- {
|
||||
for Precedence(P.tok) == prec {
|
||||
for prec := Scanner.Precedence(P.tok); prec >= prec1; prec-- {
|
||||
for Scanner.Precedence(P.tok) == prec {
|
||||
pos, tok := P.pos, P.tok;
|
||||
P.Next();
|
||||
y := P.ParseBinaryExpr(prec + 1);
|
||||
|
|
@ -857,7 +842,16 @@ func (P *Parser) ParseSimpleStat() AST.Stat {
|
|||
switch P.tok {
|
||||
case Scanner.COLON:
|
||||
// label declaration
|
||||
l := new(AST.Label);
|
||||
l.pos = P.pos;
|
||||
if x.len() == 1 {
|
||||
l.ident = x.at(0);
|
||||
} else {
|
||||
P.Error(P.pos, "illegal label declaration");
|
||||
l.ident = AST.NIL;
|
||||
}
|
||||
P.Next(); // consume ":"
|
||||
stat = l;
|
||||
|
||||
case
|
||||
Scanner.DEFINE, Scanner.ASSIGN, Scanner.ADD_ASSIGN,
|
||||
|
|
@ -867,9 +861,9 @@ func (P *Parser) ParseSimpleStat() AST.Stat {
|
|||
pos, tok := P.pos, P.tok;
|
||||
P.Next();
|
||||
y := P.ParseExpressionList();
|
||||
asgn := new(AST.Assignment);
|
||||
asgn.pos, asgn.tok, asgn.lhs, asgn.rhs = pos, tok, x, y;
|
||||
stat = asgn;
|
||||
a := new(AST.Assignment);
|
||||
a.pos, a.tok, a.lhs, a.rhs = pos, tok, x, y;
|
||||
stat = a;
|
||||
|
||||
default:
|
||||
if P.tok == Scanner.INC || P.tok == Scanner.DEC {
|
||||
|
|
@ -883,14 +877,14 @@ func (P *Parser) ParseSimpleStat() AST.Stat {
|
|||
P.Next();
|
||||
stat = s;
|
||||
} else {
|
||||
xstat := new(AST.ExprStat);
|
||||
s := new(AST.ExprStat);
|
||||
if x != nil && x.len() > 0 {
|
||||
xstat.expr = x.at(0);
|
||||
s.expr = x.at(0);
|
||||
} else {
|
||||
// this is a syntax error
|
||||
xstat.expr = AST.NIL;
|
||||
s.expr = AST.NIL;
|
||||
}
|
||||
stat = xstat;
|
||||
stat = s;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -899,13 +893,17 @@ func (P *Parser) ParseSimpleStat() AST.Stat {
|
|||
}
|
||||
|
||||
|
||||
func (P *Parser) ParseGoStat() {
|
||||
func (P *Parser) ParseGoStat() *AST.GoStat {
|
||||
P.Trace("GoStat");
|
||||
|
||||
stat := new(AST.GoStat);
|
||||
stat.pos = P.pos;
|
||||
|
||||
P.Expect(Scanner.GO);
|
||||
P.ParseExpression();
|
||||
stat.expr = P.ParseExpression();
|
||||
|
||||
P.Ecart();
|
||||
return stat;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1155,7 +1153,7 @@ func (P *Parser) TryStatement() (stat_ AST.Stat, ok_ bool) {
|
|||
case Scanner.MUL, Scanner.ARROW, Scanner.IDENT, Scanner.LPAREN:
|
||||
stat = P.ParseSimpleStat();
|
||||
case Scanner.GO:
|
||||
P.ParseGoStat();
|
||||
stat = P.ParseGoStat();
|
||||
case Scanner.RETURN:
|
||||
stat = P.ParseReturnStat();
|
||||
case Scanner.BREAK, Scanner.CONTINUE, Scanner.GOTO:
|
||||
|
|
@ -1188,24 +1186,28 @@ func (P *Parser) TryStatement() (stat_ AST.Stat, ok_ bool) {
|
|||
// ----------------------------------------------------------------------------
|
||||
// Declarations
|
||||
|
||||
func (P *Parser) ParseImportSpec() {
|
||||
func (P *Parser) ParseImportSpec() *AST.ImportDecl {
|
||||
P.Trace("ImportSpec");
|
||||
|
||||
decl := new(AST.ImportDecl);
|
||||
|
||||
if P.tok == Scanner.PERIOD {
|
||||
P.Error(P.pos, `"import ." not yet handled properly`);
|
||||
P.Next();
|
||||
} else if P.tok == Scanner.IDENT {
|
||||
P.ParseIdent();
|
||||
decl.ident = P.ParseIdent();
|
||||
}
|
||||
|
||||
if P.tok == Scanner.STRING {
|
||||
// TODO eventually the scanner should strip the quotes
|
||||
decl.file = P.val;
|
||||
P.Next();
|
||||
} else {
|
||||
P.Expect(Scanner.STRING); // use Expect() error handling
|
||||
}
|
||||
|
||||
P.Ecart();
|
||||
return decl;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1262,15 +1264,14 @@ func (P *Parser) ParseVarSpec(exported bool) *AST.VarDecl {
|
|||
|
||||
// TODO Replace this by using function pointers derived from methods.
|
||||
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: decl = P.ParseConstSpec(exported);
|
||||
case Scanner.TYPE: decl = P.ParseTypeSpec(exported);
|
||||
case Scanner.VAR: decl = P.ParseVarSpec(exported);
|
||||
default: panic("UNREACHABLE");
|
||||
case Scanner.IMPORT: return P.ParseImportSpec();
|
||||
case Scanner.CONST: return P.ParseConstSpec(exported);
|
||||
case Scanner.TYPE: return P.ParseTypeSpec(exported);
|
||||
case Scanner.VAR: return P.ParseVarSpec(exported);
|
||||
}
|
||||
return decl;
|
||||
panic("UNREACHABLE");
|
||||
return AST.NIL;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1440,7 +1441,7 @@ func (P *Parser) ParseProgram() *AST.Program {
|
|||
}
|
||||
|
||||
for P.tok == Scanner.IMPORT {
|
||||
P.ParseDecl(false, Scanner.IMPORT);
|
||||
decls.Add(P.ParseDecl(false, Scanner.IMPORT));
|
||||
P.Optional(Scanner.SEMICOLON);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -40,11 +40,14 @@ func main() {
|
|||
|
||||
src, ok := Platform.ReadSourceFile(src_file);
|
||||
if !ok {
|
||||
print("cannot open ", src_file, "\n");
|
||||
return;
|
||||
}
|
||||
print("cannot open ", src_file, "\n");
|
||||
sys.exit(1);
|
||||
}
|
||||
|
||||
if silent.BVal() {
|
||||
print("- ", src_file, "\n");
|
||||
}
|
||||
|
||||
print("- ", src_file, "\n");
|
||||
scanner := new(Scanner.Scanner);
|
||||
scanner.Open(src_file, src);
|
||||
|
||||
|
|
@ -57,6 +60,11 @@ func main() {
|
|||
parser.Open(verbose.BVal(), scanner, tstream);
|
||||
|
||||
prog := parser.ParseProgram();
|
||||
|
||||
if scanner.nerrors > 0 {
|
||||
sys.exit(1);
|
||||
}
|
||||
|
||||
if !silent.BVal() {
|
||||
Printer.Print(prog);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import AST "ast"
|
|||
// Printer implements AST.Visitor
|
||||
type Printer struct {
|
||||
indent int;
|
||||
prec int; // operator precedence
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -32,7 +33,10 @@ func (P *Printer) String(s string) {
|
|||
|
||||
|
||||
func (P *Printer) Print(x AST.Node) {
|
||||
outer := P.prec;
|
||||
P.prec = 0;
|
||||
x.Visit(P);
|
||||
P.prec = outer;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -63,14 +67,9 @@ func (P *Printer) DoIdent(x *AST.Ident) {
|
|||
// Types
|
||||
|
||||
func (P *Printer) DoFunctionType(x *AST.FunctionType) {
|
||||
/*
|
||||
if x.recv != nil {
|
||||
P.DoVarDeclList(x.recv);
|
||||
}
|
||||
*/
|
||||
P.String("(");
|
||||
P.PrintList(x.params);
|
||||
P.String(") ");
|
||||
P.String(")");
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -100,6 +99,10 @@ func (P *Printer) DoStructType(x *AST.StructType) {
|
|||
|
||||
|
||||
func (P *Printer) DoMapType(x *AST.MapType) {
|
||||
P.String("[");
|
||||
P.Print(x.key);
|
||||
P.String("] ");
|
||||
P.Print(x.val);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -110,6 +113,19 @@ 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("}");
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -125,6 +141,15 @@ func (P *Printer) DoPointerType(x *AST.PointerType) {
|
|||
func (P *Printer) DoBlock(x *AST.Block);
|
||||
|
||||
|
||||
func (P *Printer) DoImportDecl(x *AST.ImportDecl) {
|
||||
if x.ident != nil {
|
||||
P.Print(x.ident);
|
||||
P.String(" ");
|
||||
}
|
||||
P.String(x.file);
|
||||
}
|
||||
|
||||
|
||||
func (P *Printer) DoConstDecl(x *AST.ConstDecl) {
|
||||
P.Print(x.ident);
|
||||
P.String(" ");
|
||||
|
|
@ -168,6 +193,7 @@ 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 {
|
||||
|
|
@ -179,6 +205,12 @@ func (P *Printer) DoFuncDecl(x *AST.FuncDecl) {
|
|||
}
|
||||
|
||||
|
||||
func (P *Printer) DoMethodDecl(x *AST.MethodDecl) {
|
||||
P.DoIdent(x.ident);
|
||||
P.DoFunctionType(x.typ);
|
||||
}
|
||||
|
||||
|
||||
func (P *Printer) DoDeclaration(x *AST.Declaration) {
|
||||
P.String(Scanner.TokenName(x.tok));
|
||||
P.String(" ");
|
||||
|
|
@ -208,11 +240,22 @@ func (P *Printer) DoDeclaration(x *AST.Declaration) {
|
|||
// Expressions
|
||||
|
||||
func (P *Printer) DoBinary(x *AST.Binary) {
|
||||
print("(");
|
||||
outer := P.prec;
|
||||
P.prec = Scanner.Precedence(x.tok);
|
||||
|
||||
if P.prec < outer {
|
||||
print("(");
|
||||
}
|
||||
|
||||
P.Print(x.x);
|
||||
P.String(" " + Scanner.TokenName(x.tok) + " ");
|
||||
P.Print(x.y);
|
||||
print(")");
|
||||
|
||||
if P.prec < outer {
|
||||
print(")");
|
||||
}
|
||||
|
||||
P.prec = outer;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -261,27 +304,30 @@ func (P *Printer) DoSelector(x *AST.Selector) {
|
|||
// Statements
|
||||
|
||||
func (P *Printer) DoBlock(x *AST.Block) {
|
||||
if x == nil || x.stats == nil {
|
||||
P.NewLine(0);
|
||||
return;
|
||||
}
|
||||
|
||||
P.String("{");
|
||||
P.NewLine(1);
|
||||
for i := 0; i < x.stats.len(); i++ {
|
||||
if i > 0 {
|
||||
P.NewLine(0);
|
||||
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.Print(x.stats.at(i));
|
||||
P.NewLine(-1);
|
||||
}
|
||||
P.NewLine(-1);
|
||||
P.String("}");
|
||||
}
|
||||
|
||||
|
||||
func (P *Printer) DoLabel(x *AST.Label) {
|
||||
P.Print(x.ident);
|
||||
P.String(":");
|
||||
}
|
||||
|
||||
|
||||
func (P *Printer) DoExprStat(x *AST.ExprStat) {
|
||||
P.Print(x.expr);
|
||||
P.String(";");
|
||||
//P.String(";");
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -289,7 +335,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.String(";");
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -401,7 +447,7 @@ func (P *Printer) DoReturnStat(x *AST.ReturnStat) {
|
|||
func (P *Printer) DoIncDecStat(x *AST.IncDecStat) {
|
||||
P.Print(x.expr);
|
||||
P.String(Scanner.TokenName(x.tok));
|
||||
P.String(";");
|
||||
//P.String(";");
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -415,6 +461,13 @@ func (P *Printer) DoControlFlowStat(x *AST.ControlFlowStat) {
|
|||
}
|
||||
|
||||
|
||||
func (P *Printer) DoGoStat(x *AST.GoStat) {
|
||||
P.String("go ");
|
||||
P.Print(x.expr);
|
||||
P.String(";");
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Program
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import Utils "utils"
|
|||
export const (
|
||||
ILLEGAL = iota;
|
||||
EOF;
|
||||
IDENT;
|
||||
INT;
|
||||
FLOAT;
|
||||
STRING;
|
||||
|
|
@ -73,9 +74,6 @@ export const (
|
|||
LAND;
|
||||
LOR;
|
||||
|
||||
// IDENT must be immediately before keywords
|
||||
IDENT;
|
||||
|
||||
// keywords
|
||||
KEYWORDS_BEG;
|
||||
BREAK;
|
||||
|
|
@ -115,6 +113,7 @@ 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";
|
||||
|
|
@ -177,8 +176,6 @@ export func TokenName(tok int) string {
|
|||
case LAND: return "&&";
|
||||
case LOR: return "||";
|
||||
|
||||
case IDENT: return "ident";
|
||||
|
||||
case BREAK: return "break";
|
||||
case CASE: return "case";
|
||||
case CHAN: return "chan";
|
||||
|
|
@ -210,6 +207,26 @@ export func TokenName(tok int) string {
|
|||
}
|
||||
|
||||
|
||||
export func Precedence(tok int) int {
|
||||
// TODO should use a map or array here for lookup
|
||||
switch tok {
|
||||
case LOR:
|
||||
return 1;
|
||||
case LAND:
|
||||
return 2;
|
||||
case ARROW:
|
||||
return 3;
|
||||
case EQL, NEQ, LSS, LEQ, GTR, GEQ:
|
||||
return 4;
|
||||
case ADD, SUB, OR, XOR:
|
||||
return 5;
|
||||
case MUL, QUO, REM, SHL, SHR, AND:
|
||||
return 6;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
func init() {
|
||||
Keywords = new(map [string] int);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue