- added more semantic checks - more to come
- distinguish float/int literals syntactically
- fixed a tracing bug
R=r
OCL=13906
CL=13906
diff --git a/usr/gri/gosrc/parser.go b/usr/gri/gosrc/parser.go
index 503a4cf..b5a5750 100644
--- a/usr/gri/gosrc/parser.go
+++ b/usr/gri/gosrc/parser.go
@@ -47,14 +47,14 @@
if P.verbose > 0 {
P.PrintIndent();
print msg, " {\n";
- P.indent++;
}
+ P.indent++;
}
func (P *Parser) Ecart() {
+ P.indent--;
if P.verbose > 0 {
- P.indent--;
P.PrintIndent();
print "}\n";
}
@@ -132,6 +132,9 @@
if !P.semantic_checks {
return;
}
+ if P.level > 0 {
+ panic "cannot declare objects in other packages";
+ }
obj.pnolev = P.level;
if scope.Lookup(obj.ident) != nil {
P.Error(obj.pos, `"` + obj.ident + `" is declared already`);
@@ -200,26 +203,25 @@
return obj;
}
- // obj != NULL: possibly a forward declaration.
+ // obj != NULL: possibly a forward declaration
if obj.kind != Object.FUNC {
P.Error(-1, `"` + ident + `" is declared already`);
- // Continue but do not insert this function into the scope.
+ // continue but do not insert this function into the scope
obj = Globals.NewObject(-1, Object.FUNC, ident);
obj.typ = typ;
// TODO do we need to set the primary type? probably...
return obj;
}
- // We have a function with the same name.
- /*
- if !EqualTypes(type, obj->type()) {
- this->Error("type of \"%s\" does not match its forward declaration", name.cstr());
- // Continue but do not insert this function into the scope.
- NewObject(Object::FUNC, name);
- obj->set_type(type);
+ // we have a function with the same name
+ if !Type.Equal(typ, obj.typ) {
+ P.Error(-1, `type of "` + ident + `" does not match its forward declaration`);
+ // continue but do not insert this function into the scope
+ obj = Globals.NewObject(-1, Object.FUNC, ident);
+ obj.typ = typ;
+ // TODO do we need to set the primary type? probably...
return obj;
}
- */
// We have a matching forward declaration. Use it.
return obj;
@@ -826,12 +828,10 @@
P.Trace("ExpressionList");
list := Globals.NewList();
- P.ParseExpression();
- list.AddInt(0); // TODO fix this - add correct list element
+ list.AddExpr(P.ParseExpression());
for P.tok == Scanner.COMMA {
P.Next();
- P.ParseExpression();
- list.AddInt(0); // TODO fix this - add correct list element
+ list.AddExpr(P.ParseExpression());
}
P.Ecart();
@@ -867,23 +867,36 @@
}
-func (P *Parser) ParseExpressionPair() {
- P.Trace("ExpressionPair");
-
- P.ParseExpression();
- P.Expect(Scanner.COLON);
- P.ParseExpression();
+func (P *Parser) ParseSingleExpressionList(list *Globals.List) {
+ P.Trace("SingleExpressionList");
+
+ list.AddExpr(P.ParseExpression());
+ for P.tok == Scanner.COMMA {
+ P.Next();
+ list.AddExpr(P.ParseExpression());
+ }
P.Ecart();
}
-func (P *Parser) ParseExpressionPairList() {
+func (P *Parser) ParseExpressionPair(list *Globals.List) {
+ P.Trace("ExpressionPair");
+
+ list.AddExpr(P.ParseExpression());
+ P.Expect(Scanner.COLON);
+ list.AddExpr(P.ParseExpression());
+
+ P.Ecart();
+}
+
+
+func (P *Parser) ParseExpressionPairList(list *Globals.List) {
P.Trace("ExpressionPairList");
- P.ParseExpressionPair();
+ P.ParseExpressionPair(list);
for (P.tok == Scanner.COMMA) {
- P.ParseExpressionPair();
+ P.ParseExpressionPair(list);
}
P.Ecart();
@@ -916,20 +929,21 @@
}
// TODO: should allow trailing ','
+ list := Globals.NewList();
if P.tok != paren {
- P.ParseExpression();
+ list.AddExpr(P.ParseExpression());
if P.tok == Scanner.COMMA {
P.Next();
if P.tok != paren {
- P.ParseExpressionList();
+ P.ParseSingleExpressionList(list);
}
} else if P.tok == Scanner.COLON {
P.Next();
- P.ParseExpression();
+ list.AddExpr(P.ParseExpression());
if P.tok == Scanner.COMMA {
P.Next();
if P.tok != paren {
- P.ParseExpressionPairList();
+ P.ParseExpressionPairList(list);
}
}
}
@@ -951,64 +965,110 @@
ident = P.val;
P.Next();
}
-
+
+ var res Globals.Expr = AST.Bad;
+
if pos >= 0 {
// TODO set these up properly in the Universe
if ident == "panic" || ident == "print" {
- P.ParseBuiltinCall();
- goto exit;
- }
-
- P.ParseQualifiedIdent(pos, ident);
- // TODO enable code below
- /*
- if obj.kind == Object.TYPE {
- P.ParseCompositeLit(obj.typ);
- }
- */
- goto exit;
- }
-
- switch P.tok {
- case Scanner.IDENT:
- panic "UNREACHABLE";
- case Scanner.LPAREN:
- P.Next();
- P.ParseExpression();
- P.Expect(Scanner.RPAREN);
- case Scanner.STRING: fallthrough;
- case Scanner.NUMBER: fallthrough;
- case Scanner.NIL: fallthrough;
- case Scanner.IOTA: fallthrough;
- case Scanner.TRUE: fallthrough;
- case Scanner.FALSE:
- P.Next();
- case Scanner.FUNC:
- P.ParseFunctionLit();
- case Scanner.NEW:
- P.ParseNew();
- default:
- typ := P.TryType();
- if typ != nil {
- P.ParseCompositeLit(typ);
+ res = P.ParseBuiltinCall();
+
} else {
- P.Error(P.pos, "operand expected");
- P.Next(); // make progress
+ obj := P.ParseQualifiedIdent(pos, ident);
+ if P.semantic_checks {
+ if obj.kind == Object.TYPE {
+ res = P.ParseCompositeLit(obj.typ);
+ } else {
+ res = AST.NewObject(obj);
+ }
+ }
}
- }
+
+ } else {
-exit:
+ switch P.tok {
+ case Scanner.IDENT:
+ panic "UNREACHABLE";
+
+ case Scanner.LPAREN:
+ P.Next();
+ res = P.ParseExpression();
+ P.Expect(Scanner.RPAREN);
+
+ case Scanner.INT:
+ x := AST.NewLiteral(Universe.int_t);
+ x.i = 42; // TODO set the right value
+ res = x;
+ P.Next();
+
+ case Scanner.FLOAT:
+ x := AST.NewLiteral(Universe.float_t);
+ x.f = 42.0; // TODO set the right value
+ res = x;
+ P.Next();
+
+ case Scanner.STRING:
+ x := AST.NewLiteral(Universe.string_t);
+ x.s = P.val; // TODO need to strip quotes, interpret string properly
+ res = x;
+ P.Next();
+
+ case Scanner.NIL:
+ P.Next();
+ res = AST.Nil;
+
+ case Scanner.IOTA:
+ x := AST.NewLiteral(Universe.int_t);
+ x.i = 42; // TODO set the right value
+ res = x;
+ P.Next();
+
+ case Scanner.TRUE:
+ P.Next();
+ res = AST.True;
+
+ case Scanner.FALSE:
+ P.Next();
+ res = AST.False;
+
+ case Scanner.FUNC:
+ res = P.ParseFunctionLit();
+
+ case Scanner.NEW:
+ res = P.ParseNew();
+
+ default:
+ typ := P.TryType();
+ if typ != nil {
+ res = P.ParseCompositeLit(typ);
+ } else {
+ P.Error(P.pos, "operand expected");
+ P.Next(); // make progress
+ }
+ }
+
+ }
+
P.Ecart();
- return nil;
+ return res;
}
-func (P *Parser) ParseSelectorOrTypeAssertion() Globals.Expr {
+func (P *Parser) ParseSelectorOrTypeAssertion(x Globals.Expr) Globals.Expr {
P.Trace("SelectorOrTypeAssertion");
-
+
+ pos := P.pos;
P.Expect(Scanner.PERIOD);
+ if P.semantic_checks {
+ typ := x.typ();
+ if typ.form != Type.STRUCT || typ.form != Type.INTERFACE {
+ P.Error(pos, `"." cannot be applied to this operand`);
+ }
+ }
+
if P.tok == Scanner.IDENT {
- P.ParseIdent();
+ ident := P.ParseIdent();
+
} else {
P.Expect(Scanner.LPAREN);
P.ParseType();
@@ -1016,11 +1076,11 @@
}
P.Ecart();
- return nil;
+ return x;
}
-func (P *Parser) ParseIndexOrSlice() Globals.Expr {
+func (P *Parser) ParseIndexOrSlice(x Globals.Expr) Globals.Expr {
P.Trace("IndexOrSlice");
P.Expect(Scanner.LBRACK);
@@ -1032,11 +1092,11 @@
P.Expect(Scanner.RBRACK);
P.Ecart();
- return nil;
+ return x;
}
-func (P *Parser) ParseCall() Globals.Expr {
+func (P *Parser) ParseCall(x Globals.Expr) Globals.Expr {
P.Trace("Call");
P.Expect(Scanner.LPAREN);
@@ -1046,30 +1106,26 @@
P.Expect(Scanner.RPAREN);
P.Ecart();
- return nil;
+ return x;
}
func (P *Parser) ParsePrimaryExpr(pos int, ident string) Globals.Expr {
P.Trace("PrimaryExpr");
- P.ParseOperand(pos, ident);
+ x := P.ParseOperand(pos, ident);
for {
switch P.tok {
- case Scanner.PERIOD:
- P.ParseSelectorOrTypeAssertion();
- case Scanner.LBRACK:
- P.ParseIndexOrSlice();
- case Scanner.LPAREN:
- P.ParseCall();
- default:
- P.Ecart();
- return nil;
+ case Scanner.PERIOD: x = P.ParseSelectorOrTypeAssertion(x);
+ case Scanner.LBRACK: x = P.ParseIndexOrSlice(x);
+ case Scanner.LPAREN: x = P.ParseCall(x);
+ default: goto exit;
}
}
-
+
+exit:
P.Ecart();
- return nil;
+ return x;
}
@@ -1944,10 +2000,10 @@
obj := P.ParseIdentDecl(Object.PACKAGE);
P.Optional(Scanner.SEMICOLON);
- { if P.level != 0 {
+ { P.OpenScope();
+ if P.level != 0 {
panic "incorrect scope level";
}
- P.OpenScope();
P.comp.Insert(Globals.NewPackage(P.S.filename, obj, P.top_scope));
if P.comp.pkg_ref != 1 {
@@ -1966,10 +2022,11 @@
P.ResolveUndefTypes();
P.MarkExports();
- P.CloseScope();
+
if P.level != 0 {
panic "incorrect scope level";
}
+ P.CloseScope();
}
P.CloseScope();