Commit 84152806 authored by Robert Griesemer's avatar Robert Griesemer

- 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
parent b70d42f3
......@@ -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);
......
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