]> Cypherpunks repositories - gostls13.git/commitdiff
- more work on SimpleStat production
authorRobert Griesemer <gri@golang.org>
Fri, 25 Jul 2008 16:35:03 +0000 (09:35 -0700)
committerRobert Griesemer <gri@golang.org>
Fri, 25 Jul 2008 16:35:03 +0000 (09:35 -0700)
R=r
OCL=13461
CL=13461

usr/gri/gosrc/globals.go
usr/gri/gosrc/parser.go

index 9665cbdaf51edd8edc44f031f1ec4340bfe6df17..31dc1a351353e40444395f13920a0d043fe35fb0 100644 (file)
@@ -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 {
        L.len_++;
        e := new(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 {
        return L.at(i).str;
 }
index 05fc74239e7fc43e51f8a6adf37aa134298f48e8..4c9f70ffdf202bbd2de2c0b1ce0d87be13a1000b 100644 (file)
@@ -127,7 +127,6 @@ func (P *Parser) Lookup(ident string) *Globals.Object {
 
 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 @@ func (P *Parser) ParseBlock() {
 // ----------------------------------------------------------------------------
 // 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 @@ func (P *Parser) ParseExpression() {
 // ----------------------------------------------------------------------------
 // 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 @@ func (P *Parser) ParseIdentOrExpr(nidents int) int {
                        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;
                }
+       }
+
+       if just_ident {
+               ident_list.AddStr(ident);
        } else {
-               P.ParseExpression();
-               if nidents > 0 {
-                       nidents = -nidents;
-               }
-               nidents--;
+               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 @@ func (P *Parser) ParseSimpleStat() {
        // 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 @@ func (P *Parser) ParseSimpleStat() {
        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();
                }
        }