From: Robert Griesemer Date: Fri, 25 Jul 2008 16:35:03 +0000 (-0700) Subject: - more work on SimpleStat production X-Git-Tag: weekly.2009-11-06~3431 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=cf4c37cac334851697d76010e3730f90f63e5494;p=gostls13.git - more work on SimpleStat production R=r OCL=13461 CL=13461 --- diff --git a/usr/gri/gosrc/globals.go b/usr/gri/gosrc/globals.go index 9665cbdaf5..31dc1a3513 100644 --- a/usr/gri/gosrc/globals.go +++ b/usr/gri/gosrc/globals.go @@ -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; } diff --git a/usr/gri/gosrc/parser.go b/usr/gri/gosrc/parser.go index 05fc74239e..4c9f70ffdf 100644 --- a/usr/gri/gosrc/parser.go +++ b/usr/gri/gosrc/parser.go @@ -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(); } }