Commit f03deb33 authored by Robert Griesemer's avatar Robert Griesemer

- fixed several parser issues

R=r
OCL=13441
CL=13441
parent cb9b1038
......@@ -53,10 +53,10 @@ type Package struct {
type Elem struct {
next *Elem;
val int;
str string;
obj *Object;
typ *Type;
pkg *Package;
}
......@@ -190,6 +190,11 @@ func (L *List) TypAt(i int) *Type {
}
func (L *List) AddInt(val int) {
L.Add().val = val;
}
func (L *List) AddStr(str string) {
L.Add().str = str;
}
......
......@@ -7,10 +7,10 @@ package Object
import Globals "globals"
export BAD, CONST, TYPE, VAR, FUNC, PACKAGE, PTYPE
export BAD, CONST, TYPE, VAR, FUNC, PACKAGE, LABEL, PTYPE
const /* kind */ (
BAD = iota; // error handling
CONST; TYPE; VAR; FUNC; PACKAGE;
CONST; TYPE; VAR; FUNC; PACKAGE; LABEL;
PTYPE; // primary type (import/export only)
)
......
......@@ -208,12 +208,15 @@ func (P *Parser) ParseIdentList() {
}
func (P *Parser) ParseQualifiedIdent() *Globals.Object {
func (P *Parser) ParseQualifiedIdent(pos int, ident string) *Globals.Object {
P.Trace("QualifiedIdent");
if pos < 0 {
pos = P.pos;
ident = P.ParseIdent();
}
if EnableSemanticTests {
pos := P.pos;
ident := P.ParseIdent();
obj := P.Lookup(ident);
if obj == nil {
P.Error(pos, `"` + ident + `" is not declared`);
......@@ -229,7 +232,6 @@ func (P *Parser) ParseQualifiedIdent() *Globals.Object {
return obj;
} else {
P.ParseIdent();
if P.tok == Scanner.PERIOD {
P.Next();
P.ParseIdent();
......@@ -261,7 +263,7 @@ func (P *Parser) ParseTypeName() *Globals.Type {
P.Trace("TypeName");
if EnableSemanticTests {
obj := P.ParseQualifiedIdent();
obj := P.ParseQualifiedIdent(-1, "");
typ := obj.typ;
if obj.kind != Object.TYPE {
P.Error(obj.pos, `"` + obj.ident + `" is not a type`);
......@@ -270,7 +272,7 @@ func (P *Parser) ParseTypeName() *Globals.Type {
P.Ecart();
return typ;
} else {
P.ParseQualifiedIdent();
P.ParseQualifiedIdent(-1, "");
P.Ecart();
return Universe.bad_t;
}
......@@ -510,11 +512,11 @@ func (P *Parser) ParseInterfaceType() *Globals.Type {
P.OpenScope();
typ := Globals.NewType(Type.INTERFACE);
typ.scope = P.top_scope;
for P.tok != Scanner.RBRACE {
for P.tok == Scanner.IDENT {
P.ParseMethodDecl();
}
P.CloseScope();
P.Next();
P.Expect(Scanner.RBRACE);
P.Ecart();
return typ;
......@@ -708,6 +710,15 @@ func (P *Parser) ParseExpressionPairList() {
}
func (P *Parser) ParseBuiltinCall() {
P.Trace("BuiltinCall");
P.ParseExpressionList(); // TODO should be optional
P.Ecart();
}
func (P *Parser) ParseCompositeLit(typ *Globals.Type) {
P.Trace("CompositeLit");
......@@ -749,18 +760,36 @@ func (P *Parser) ParseCompositeLit(typ *Globals.Type) {
}
func (P *Parser) ParseOperand() {
func (P *Parser) ParseOperand(pos int, ident string) {
P.Trace("Operand");
switch P.tok {
case Scanner.IDENT:
P.ParseQualifiedIdent();
if pos < 0 && P.tok == Scanner.IDENT {
// no look-ahead yet
pos = P.pos;
ident = P.val;
P.Next();
}
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();
......@@ -786,6 +815,7 @@ func (P *Parser) ParseOperand() {
}
}
exit:
P.Ecart();
}
......@@ -821,8 +851,8 @@ func (P *Parser) ParseIndexOrSlice() {
}
func (P *Parser) ParseInvocation() {
P.Trace("Invocation");
func (P *Parser) ParseCall() {
P.Trace("Call");
P.Expect(Scanner.LPAREN);
if P.tok != Scanner.RPAREN {
......@@ -834,10 +864,10 @@ func (P *Parser) ParseInvocation() {
}
func (P *Parser) ParsePrimaryExpr() {
func (P *Parser) ParsePrimaryExpr(pos int, ident string) AST.Expr {
P.Trace("PrimaryExpr");
P.ParseOperand();
P.ParseOperand(pos, ident);
for {
switch P.tok {
case Scanner.PERIOD:
......@@ -845,24 +875,25 @@ func (P *Parser) ParsePrimaryExpr() {
case Scanner.LBRACK:
P.ParseIndexOrSlice();
case Scanner.LPAREN:
P.ParseInvocation();
P.ParseCall();
default:
P.Ecart();
return;
return nil;
}
}
P.Ecart();
return nil;
}
func (P *Parser) ParsePrimaryExprList() {
P.Trace("PrimaryExprList");
P.ParsePrimaryExpr();
P.ParsePrimaryExpr(-1, "");
for P.tok == Scanner.COMMA {
P.Next();
P.ParsePrimaryExpr();
P.ParsePrimaryExpr(-1, "");
}
P.Ecart();
......@@ -885,7 +916,7 @@ func (P *Parser) ParseUnaryExpr() AST.Expr {
P.Ecart();
return nil; // TODO fix this
}
P.ParsePrimaryExpr();
P.ParsePrimaryExpr(-1, "");
P.Ecart();
return nil; // TODO fix this
......@@ -912,10 +943,15 @@ func Precedence(tok int) int {
}
func (P *Parser) ParseBinaryExpr(prec1 int) AST.Expr {
func (P *Parser) ParseBinaryExpr(pos int, ident string, prec1 int) AST.Expr {
P.Trace("BinaryExpr");
x := P.ParseUnaryExpr();
var x AST.Expr;
if pos >= 0 {
x = P.ParsePrimaryExpr(pos, ident);
} else {
x = P.ParseUnaryExpr();
}
for prec := Precedence(P.tok); prec >= prec1; prec-- {
for Precedence(P.tok) == prec {
e := new(AST.BinaryExpr);
......@@ -923,7 +959,7 @@ func (P *Parser) ParseBinaryExpr(prec1 int) AST.Expr {
e.op = P.tok; // TODO should we use tokens or separate operator constants?
e.x = x;
P.Next();
e.y = P.ParseBinaryExpr(prec + 1);
e.y = P.ParseBinaryExpr(-1, "", prec + 1);
x = e;
}
}
......@@ -932,11 +968,13 @@ func (P *Parser) ParseBinaryExpr(prec1 int) AST.Expr {
}
func (P *Parser) ParseExpression() {
P.Trace("Expression");
// Expressions where the first token may be an
// identifier that has already been consumed.
func (P *Parser) ParseIdentExpression(pos int, ident string) {
P.Trace("IdentExpression");
indent := P.indent;
P.ParseBinaryExpr(1);
P.ParseBinaryExpr(pos, ident, 1);
if indent != P.indent {
panic "imbalanced tracing code (Expression)";
......@@ -945,32 +983,102 @@ func (P *Parser) ParseExpression() {
}
func (P *Parser) ParseExpression() {
P.Trace("Expression");
P.ParseIdentExpression(-1, "");
P.Ecart();
}
// ----------------------------------------------------------------------------
// Statements
func (P *Parser) ParseBuiltinStat() {
P.Trace("BuiltinStat");
P.Expect(Scanner.IDENT);
P.ParseExpressionList(); // TODO should be optional
func (P *Parser) ParseIdentOrExpr(nidents int) int {
P.Trace("IdentOrExpr");
if nidents >= 0 && P.tok == Scanner.IDENT {
pos := P.pos;
ident := P.val;
P.Next();
switch P.tok {
case Scanner.COMMA,
Scanner.COLON,
Scanner.DEFINE,
Scanner.ASSIGN,
Scanner.ADD_ASSIGN,
Scanner.SUB_ASSIGN,
Scanner.MUL_ASSIGN,
Scanner.QUO_ASSIGN,
Scanner.REM_ASSIGN,
Scanner.AND_ASSIGN,
Scanner.OR_ASSIGN,
Scanner.XOR_ASSIGN,
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;
}
} else {
P.ParseExpression();
if nidents > 0 {
nidents = -nidents;
}
nidents--;
}
P.Ecart();
return nidents;
}
// temporary - will go away eventually
func abs(x int) int {
if x < 0 {
x = -x;
}
return x;
}
func (P *Parser) ParseSimpleStat() {
P.Trace("SimpleStat");
P.ParseExpression();
if P.tok == Scanner.COLON {
// If we see an identifier, we don't know if it's part of a
// label declaration, (multiple) variable declaration, assignment,
// 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();
P.Ecart();
return;
nidents = P.ParseIdentOrExpr(nidents);
}
if P.tok == Scanner.COMMA {
switch P.tok {
case Scanner.COLON:
// label declaration
P.Next();
P.ParsePrimaryExprList();
if nidents != 1 {
// TODO provide exact error position
P.Error(P.pos, "illegal label declaration");
}
switch P.tok {
case Scanner.DEFINE:
// variable declaration
P.Next();
P.ParseExpressionList();
if nidents < 0 {
// TODO provide exact error position
P.Error(P.pos, "illegal identifier list for declaration");
}
case Scanner.ASSIGN: fallthrough;
case Scanner.DEFINE: fallthrough;
case Scanner.ADD_ASSIGN: fallthrough;
case Scanner.SUB_ASSIGN: fallthrough;
case Scanner.MUL_ASSIGN: fallthrough;
......@@ -983,11 +1091,19 @@ func (P *Parser) ParseSimpleStat() {
case Scanner.SHR_ASSIGN:
P.Next();
P.ParseExpressionList();
case Scanner.INC:
P.Next();
case Scanner.DEC:
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 '--'");
}
default:
if abs(nidents) != 1 {
// TODO provide exact error position
P.Error(P.pos, "too many expressions for expression statement");
}
}
P.Ecart();
}
......@@ -1144,7 +1260,7 @@ func (P *Parser) ParseSwitchStat() {
}
}
P.Expect(Scanner.LBRACE);
for P.tok != Scanner.RBRACE {
for P.tok == Scanner.CASE || P.tok == Scanner.DEFAULT {
P.ParseCaseClause();
}
P.Expect(Scanner.RBRACE);
......@@ -1214,7 +1330,7 @@ func (P *Parser) ParseSelectStat() bool {
P.Expect(Scanner.SELECT);
P.Expect(Scanner.LBRACE);
for P.tok != Scanner.RBRACE {
for P.tok != Scanner.RBRACE && P.tok != Scanner.EOF {
P.ParseCommClause();
}
P.Next();
......@@ -1236,16 +1352,8 @@ func (P *Parser) TryStatement() bool {
case Scanner.FUNC:
// for now we do not allow local function declarations
fallthrough;
case Scanner.SEND: fallthrough;
case Scanner.RECV:
P.ParseSimpleStat(); // send or receive
case Scanner.IDENT:
switch P.val {
case "print", "panic":
P.ParseBuiltinStat();
default:
case Scanner.MUL, Scanner.SEND, Scanner.RECV, Scanner.IDENT:
P.ParseSimpleStat();
}
case Scanner.GO:
P.ParseGoStat();
case Scanner.RETURN:
......@@ -1300,7 +1408,7 @@ func (P *Parser) ParseImportDecl() {
P.Expect(Scanner.IMPORT);
if P.tok == Scanner.LPAREN {
P.Next();
for P.tok != Scanner.RPAREN {
for P.tok != Scanner.RPAREN && P.tok != Scanner.EOF {
P.ParseImportSpec();
P.Optional(Scanner.SEMICOLON); // TODO this seems wrong
}
......@@ -1338,7 +1446,7 @@ func (P *Parser) ParseConstDecl() {
P.Expect(Scanner.CONST);
if P.tok == Scanner.LPAREN {
P.Next();
for P.tok != Scanner.RPAREN {
for P.tok == Scanner.IDENT {
P.ParseConstSpec();
if P.tok != Scanner.RPAREN {
P.Expect(Scanner.SEMICOLON);
......@@ -1390,7 +1498,7 @@ func (P *Parser) ParseTypeDecl() {
P.Expect(Scanner.TYPE);
if P.tok == Scanner.LPAREN {
P.Next();
for P.tok != Scanner.RPAREN {
for P.tok == Scanner.IDENT {
P.ParseTypeSpec();
if P.tok != Scanner.RPAREN {
P.Expect(Scanner.SEMICOLON);
......@@ -1433,7 +1541,7 @@ func (P *Parser) ParseVarDecl() {
P.Expect(Scanner.VAR);
if P.tok == Scanner.LPAREN {
P.Next();
for P.tok != Scanner.RPAREN {
for P.tok == Scanner.IDENT {
P.ParseVarSpec();
if P.tok != Scanner.RPAREN {
P.Expect(Scanner.SEMICOLON);
......@@ -1467,20 +1575,20 @@ func (P *Parser) ParseFuncDecl() {
func (P *Parser) ParseExportDecl() {
P.Trace("ExportDecl");
// TODO this needs to be clarified - the current syntax is
// "everything goes" - sigh...
P.Expect(Scanner.EXPORT);
has_paren := false;
if P.tok == Scanner.LPAREN {
P.Next();
for P.tok != Scanner.RPAREN {
P.exports.AddStr(P.ParseIdent());
P.Optional(Scanner.COMMA); // TODO this seems wrong
has_paren = true;
}
P.Next();
} else {
P.exports.AddStr(P.ParseIdent());
for P.tok == Scanner.COMMA {
P.Next();
for P.tok == Scanner.IDENT {
P.exports.AddStr(P.ParseIdent());
P.Optional(Scanner.COMMA); // TODO this seems wrong
}
if has_paren {
P.Expect(Scanner.RPAREN)
}
P.Ecart();
......
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