- more work on SimpleStat production
R=r
OCL=13461
CL=13461
diff --git a/usr/gri/gosrc/parser.go b/usr/gri/gosrc/parser.go
index 05fc742..4c9f70f 100644
--- a/usr/gri/gosrc/parser.go
+++ b/usr/gri/gosrc/parser.go
@@ -127,7 +127,6 @@
func (P *Parser) DeclareInScope(scope *Globals.Scope, obj *Globals.Object) {
if EnableSemanticTests && scope.Lookup(obj.ident) != nil {
- // TODO is this the correct error position?
P.Error(obj.pos, `"` + obj.ident + `" is declared already`);
return; // don't insert it into the scope
}
@@ -648,16 +647,20 @@
// ----------------------------------------------------------------------------
// Expressions
-func (P *Parser) ParseExpressionList() {
+func (P *Parser) ParseExpressionList() *Globals.List {
P.Trace("ExpressionList");
+ list := Globals.NewList();
P.ParseExpression();
+ list.AddInt(0); // TODO fix this - add correct list element
for P.tok == Scanner.COMMA {
P.Next();
P.ParseExpression();
+ list.AddInt(0); // TODO fix this - add correct list element
}
P.Ecart();
+ return list;
}
@@ -993,11 +996,30 @@
// ----------------------------------------------------------------------------
// 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");
- if nidents >= 0 && P.tok == Scanner.IDENT {
- pos := P.pos;
- ident := P.val;
+
+ pos_list.AddInt(P.pos);
+ 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();
switch P.tok {
case Scanner.COMMA,
@@ -1015,31 +1037,34 @@
Scanner.SHL_ASSIGN,
Scanner.SHR_ASSIGN:
// identifier is not part of a more complicated expression
- nidents++;
-
- default:
- // assume identifier is part of a more complicated expression
- P.ParseIdentExpression(pos, ident);
- nidents = -nidents - 1;
+ just_ident = true;
}
- } else {
- P.ParseExpression();
- if nidents > 0 {
- nidents = -nidents;
- }
- nidents--;
}
+
+ if just_ident {
+ ident_list.AddStr(ident);
+ } else {
+ P.ConvertToExprList(pos_list, ident_list, expr_list);
+ P.ParseIdentExpression(pos, ident);
+ expr_list.AddInt(0); // TODO fix this - add correct expression
+ }
+
P.Ecart();
- return nidents;
}
-// temporary - will go away eventually
-func abs(x int) int {
- if x < 0 {
- x = -x;
+func (P *Parser) ParseIdentOrExprList() (pos_list, ident_list, expr_list *Globals.List) {
+ P.Trace("IdentOrExprList");
+
+ 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 @@
// or simply an expression, without looking ahead.
// Strategy: We parse an expression list, but simultaneously, as
// long as possible, maintain a list of identifiers which is converted
- // into an expression list only if neccessary.
- // TODO: maintain the lists
-
- nidents := P.ParseIdentOrExpr(0);
- for P.tok == Scanner.COMMA {
- P.Next();
- nidents = P.ParseIdentOrExpr(nidents);
- }
+ // into an expression list only if neccessary. The result of
+ // ParseIdentOrExprList is a list of ident/expr positions and either
+ // a non-empty list of identifiers or a non-empty list of expressions
+ // (but not both).
+ pos_list, ident_list, expr_list := P.ParseIdentOrExprList();
switch P.tok {
case Scanner.COLON:
// label declaration
- P.Next();
- if nidents != 1 {
- // TODO provide exact error position
+ if EnableSemanticTests && ident_list.len_ != 1 {
P.Error(P.pos, "illegal label declaration");
}
+ P.Next();
case Scanner.DEFINE:
// variable declaration
+ if EnableSemanticTests && ident_list.len_ == 0 {
+ P.Error(P.pos, "illegal left-hand side for declaration");
+ }
P.Next();
- P.ParseExpressionList();
- if nidents < 0 {
- // TODO provide exact error position
- P.Error(P.pos, "illegal identifier list for declaration");
+ pos := P.pos;
+ val_list := P.ParseExpressionList();
+ if EnableSemanticTests && val_list.len_ != ident_list.len_ {
+ 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;
@@ -1089,18 +1121,21 @@
case Scanner.XOR_ASSIGN: fallthrough;
case Scanner.SHL_ASSIGN: fallthrough;
case Scanner.SHR_ASSIGN:
+ P.ConvertToExprList(pos_list, ident_list, expr_list);
P.Next();
- P.ParseExpressionList();
- case Scanner.INC, Scanner.DEC:
- P.Next();
- if abs(nidents) != 1 {
- // TODO provide exact error position
- P.Error(P.pos, "too many expressions for '++' or '--'");
+ pos := P.pos;
+ val_list := P.ParseExpressionList();
+ if EnableSemanticTests && val_list.len_ != expr_list.len_ {
+ P.Error(pos, "number of expressions does not match number of variables");
}
+
default:
- if abs(nidents) != 1 {
- // TODO provide exact error position
- P.Error(P.pos, "too many expressions for expression statement");
+ P.ConvertToExprList(pos_list, ident_list, expr_list);
+ if EnableSemanticTests && expr_list.len_ != 1 {
+ P.Error(P.pos, "no expression list allowed");
+ }
+ if P.tok == Scanner.INC || P.tok == Scanner.DEC {
+ P.Next();
}
}