Commit cf4c37ca authored by Robert Griesemer's avatar Robert Griesemer

- more work on SimpleStat production

R=r
OCL=13461
CL=13461
parent b4902c5f
...@@ -162,6 +162,11 @@ func (L *List) at(i int) *Elem { ...@@ -162,6 +162,11 @@ func (L *List) at(i int) *Elem {
} }
func (L *List) Clear() {
L.len_, L.first, L.last = 0, nil, nil;
}
func (L *List) Add() *Elem { func (L *List) Add() *Elem {
L.len_++; L.len_++;
e := new(Elem); e := new(Elem);
...@@ -175,6 +180,11 @@ func (L *List) Add() *Elem { ...@@ -175,6 +180,11 @@ func (L *List) Add() *Elem {
} }
func (L *List) IntAt(i int) int {
return L.at(i).val;
}
func (L *List) StrAt(i int) string { func (L *List) StrAt(i int) string {
return L.at(i).str; return L.at(i).str;
} }
......
...@@ -127,7 +127,6 @@ func (P *Parser) Lookup(ident string) *Globals.Object { ...@@ -127,7 +127,6 @@ func (P *Parser) Lookup(ident string) *Globals.Object {
func (P *Parser) DeclareInScope(scope *Globals.Scope, obj *Globals.Object) { func (P *Parser) DeclareInScope(scope *Globals.Scope, obj *Globals.Object) {
if EnableSemanticTests && scope.Lookup(obj.ident) != nil { if EnableSemanticTests && scope.Lookup(obj.ident) != nil {
// TODO is this the correct error position?
P.Error(obj.pos, `"` + obj.ident + `" is declared already`); P.Error(obj.pos, `"` + obj.ident + `" is declared already`);
return; // don't insert it into the scope return; // don't insert it into the scope
} }
...@@ -648,16 +647,20 @@ func (P *Parser) ParseBlock() { ...@@ -648,16 +647,20 @@ func (P *Parser) ParseBlock() {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Expressions // Expressions
func (P *Parser) ParseExpressionList() { func (P *Parser) ParseExpressionList() *Globals.List {
P.Trace("ExpressionList"); P.Trace("ExpressionList");
list := Globals.NewList();
P.ParseExpression(); P.ParseExpression();
list.AddInt(0); // TODO fix this - add correct list element
for P.tok == Scanner.COMMA { for P.tok == Scanner.COMMA {
P.Next(); P.Next();
P.ParseExpression(); P.ParseExpression();
list.AddInt(0); // TODO fix this - add correct list element
} }
P.Ecart(); P.Ecart();
return list;
} }
...@@ -993,11 +996,30 @@ func (P *Parser) ParseExpression() { ...@@ -993,11 +996,30 @@ func (P *Parser) ParseExpression() {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Statements // Statements
func (P *Parser) ParseIdentOrExpr(nidents int) int { func (P *Parser) ConvertToExprList(pos_list, ident_list, expr_list *Globals.List) {
for p, q := pos_list.first, ident_list.first; q != nil; p, q = p.next, q.next {
pos, ident := p.val, q.str;
if EnableSemanticTests {
obj := P.Lookup(ident);
if obj == nil {
P.Error(pos, `"` + ident + `" is not declared`);
obj = Globals.NewObject(pos, Object.BAD, ident);
}
}
expr_list.AddInt(0); // TODO fix this - add correct expression
}
ident_list.Clear();
}
func (P *Parser) ParseIdentOrExpr(pos_list, ident_list, expr_list *Globals.List) {
P.Trace("IdentOrExpr"); P.Trace("IdentOrExpr");
if nidents >= 0 && P.tok == Scanner.IDENT {
pos := P.pos; pos_list.AddInt(P.pos);
ident := P.val; pos, ident := -1, "";
just_ident := false;
if expr_list.len_ == 0 /* only idents so far */ && P.tok == Scanner.IDENT {
pos, ident = P.pos, P.val;
P.Next(); P.Next();
switch P.tok { switch P.tok {
case Scanner.COMMA, case Scanner.COMMA,
...@@ -1015,31 +1037,34 @@ func (P *Parser) ParseIdentOrExpr(nidents int) int { ...@@ -1015,31 +1037,34 @@ func (P *Parser) ParseIdentOrExpr(nidents int) int {
Scanner.SHL_ASSIGN, Scanner.SHL_ASSIGN,
Scanner.SHR_ASSIGN: Scanner.SHR_ASSIGN:
// identifier is not part of a more complicated expression // identifier is not part of a more complicated expression
nidents++; just_ident = true;
default:
// assume identifier is part of a more complicated expression
P.ParseIdentExpression(pos, ident);
nidents = -nidents - 1;
} }
}
if just_ident {
ident_list.AddStr(ident);
} else { } else {
P.ParseExpression(); P.ConvertToExprList(pos_list, ident_list, expr_list);
if nidents > 0 { P.ParseIdentExpression(pos, ident);
nidents = -nidents; expr_list.AddInt(0); // TODO fix this - add correct expression
}
nidents--;
} }
P.Ecart(); P.Ecart();
return nidents;
} }
// temporary - will go away eventually func (P *Parser) ParseIdentOrExprList() (pos_list, ident_list, expr_list *Globals.List) {
func abs(x int) int { P.Trace("IdentOrExprList");
if x < 0 {
x = -x; pos_list, ident_list, expr_list = Globals.NewList(), Globals.NewList(), Globals.NewList();
P.ParseIdentOrExpr(pos_list, ident_list, expr_list);
for P.tok == Scanner.COMMA {
P.Next();
P.ParseIdentOrExpr(pos_list, ident_list, expr_list);
} }
return x;
P.Ecart();
return pos_list, ident_list, expr_list;
} }
...@@ -1051,31 +1076,38 @@ func (P *Parser) ParseSimpleStat() { ...@@ -1051,31 +1076,38 @@ func (P *Parser) ParseSimpleStat() {
// or simply an expression, without looking ahead. // or simply an expression, without looking ahead.
// Strategy: We parse an expression list, but simultaneously, as // Strategy: We parse an expression list, but simultaneously, as
// long as possible, maintain a list of identifiers which is converted // long as possible, maintain a list of identifiers which is converted
// into an expression list only if neccessary. // into an expression list only if neccessary. The result of
// TODO: maintain the lists // ParseIdentOrExprList is a list of ident/expr positions and either
// a non-empty list of identifiers or a non-empty list of expressions
nidents := P.ParseIdentOrExpr(0); // (but not both).
for P.tok == Scanner.COMMA { pos_list, ident_list, expr_list := P.ParseIdentOrExprList();
P.Next();
nidents = P.ParseIdentOrExpr(nidents);
}
switch P.tok { switch P.tok {
case Scanner.COLON: case Scanner.COLON:
// label declaration // label declaration
P.Next(); if EnableSemanticTests && ident_list.len_ != 1 {
if nidents != 1 {
// TODO provide exact error position
P.Error(P.pos, "illegal label declaration"); P.Error(P.pos, "illegal label declaration");
} }
P.Next();
case Scanner.DEFINE: case Scanner.DEFINE:
// variable declaration // variable declaration
if EnableSemanticTests && ident_list.len_ == 0 {
P.Error(P.pos, "illegal left-hand side for declaration");
}
P.Next(); P.Next();
P.ParseExpressionList(); pos := P.pos;
if nidents < 0 { val_list := P.ParseExpressionList();
// TODO provide exact error position if EnableSemanticTests && val_list.len_ != ident_list.len_ {
P.Error(P.pos, "illegal identifier list for declaration"); P.Error(pos, "number of expressions does not match number of variables");
}
// declare variables
if EnableSemanticTests {
for p, q := pos_list.first, ident_list.first; q != nil; p, q = p.next, q.next {
obj := Globals.NewObject(p.val, Object.VAR, q.str);
P.Declare(obj);
// TODO set correct types
}
} }
case Scanner.ASSIGN: fallthrough; case Scanner.ASSIGN: fallthrough;
...@@ -1089,18 +1121,21 @@ func (P *Parser) ParseSimpleStat() { ...@@ -1089,18 +1121,21 @@ func (P *Parser) ParseSimpleStat() {
case Scanner.XOR_ASSIGN: fallthrough; case Scanner.XOR_ASSIGN: fallthrough;
case Scanner.SHL_ASSIGN: fallthrough; case Scanner.SHL_ASSIGN: fallthrough;
case Scanner.SHR_ASSIGN: case Scanner.SHR_ASSIGN:
P.ConvertToExprList(pos_list, ident_list, expr_list);
P.Next(); P.Next();
P.ParseExpressionList(); pos := P.pos;
case Scanner.INC, Scanner.DEC: val_list := P.ParseExpressionList();
P.Next(); if EnableSemanticTests && val_list.len_ != expr_list.len_ {
if abs(nidents) != 1 { P.Error(pos, "number of expressions does not match number of variables");
// TODO provide exact error position
P.Error(P.pos, "too many expressions for '++' or '--'");
} }
default: default:
if abs(nidents) != 1 { P.ConvertToExprList(pos_list, ident_list, expr_list);
// TODO provide exact error position if EnableSemanticTests && expr_list.len_ != 1 {
P.Error(P.pos, "too many expressions for expression statement"); P.Error(P.pos, "no expression list allowed");
}
if P.tok == Scanner.INC || P.tok == Scanner.DEC {
P.Next();
} }
} }
......
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