// Copyright 2009 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package Parser import Utils "utils" import Scanner "scanner" import Globals "globals" import Object "object" import Type "type" import Universe "universe" import Import "import" import AST "ast" export type Parser struct { comp *Globals.Compilation; semantic_checks bool; verbose bool; indent uint; S *Scanner.Scanner; C *chan *Scanner.Token; // Token tok int; // one token look-ahead pos int; // token source position val string; // token value (for IDENT, NUMBER, STRING only) // Semantic analysis level int; // 0 = global scope, -1 = function/struct scope of global functions/structs, etc. top_scope *Globals.Scope; forward_types *Globals.List; exports *Globals.List; } // ---------------------------------------------------------------------------- // Support functions func (P *Parser) PrintIndent() { for i := P.indent; i > 0; i-- { print(". "); } } func (P *Parser) Trace(msg string) { if P.verbose { P.PrintIndent(); print(msg, " {\n"); } P.indent++; } func (P *Parser) Ecart() { P.indent--; if P.verbose { P.PrintIndent(); print("}\n"); } } func (P *Parser) Next() { if P.C == nil { P.tok, P.pos, P.val = P.S.Scan(); } else { t := <- P.C; P.tok, P.pos, P.val = t.tok, t.pos, t.val; } if P.verbose { P.PrintIndent(); print("[", P.pos, "] ", Scanner.TokenName(P.tok), "\n"); } } func (P *Parser) Open(comp *Globals.Compilation, S *Scanner.Scanner, C *chan *Scanner.Token) { P.comp = comp; P.semantic_checks = comp.flags.ast; P.verbose = comp.flags.verbosity > 2; P.indent = 0; P.S = S; P.C = C; P.Next(); P.level = 0; P.top_scope = Universe.scope; P.forward_types = Globals.NewList(); P.exports = Globals.NewList(); } func (P *Parser) Error(pos int, msg string) { P.S.Error(pos, msg); } func (P *Parser) Expect(tok int) { if P.tok != tok { P.Error(P.pos, "expected '" + Scanner.TokenName(tok) + "', found '" + Scanner.TokenName(P.tok) + "'"); } P.Next(); // make progress in any case } func (P *Parser) Optional(tok int) { if P.tok == tok { P.Next(); } } // ---------------------------------------------------------------------------- // Scopes func (P *Parser) OpenScope() { P.top_scope = Globals.NewScope(P.top_scope); } func (P *Parser) CloseScope() { P.top_scope = P.top_scope.parent; } func (P *Parser) Lookup(ident string) *Globals.Object { for scope := P.top_scope; scope != nil; scope = scope.parent { obj := scope.Lookup(ident); if obj != nil { return obj; } } return nil; } func (P *Parser) DeclareInScope(scope *Globals.Scope, obj *Globals.Object) { 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`); return; // don't insert it into the scope } scope.Insert(obj); } func (P *Parser) Declare(obj *Globals.Object) { P.DeclareInScope(P.top_scope, obj); } func MakeFunctionType(sig *Globals.Scope, p0, r0 int, check_recv bool) *Globals.Type { // Determine if we have a receiver or not. // TODO do we still need this? if p0 > 0 && check_recv { // method if p0 != 1 { panic("p0 != 1"); } } typ := Globals.NewType(Type.FUNCTION); if p0 == 0 { typ.flags = 0; } else { typ.flags = Type.RECV; } typ.len_ = r0 - p0; typ.scope = sig; // parameters are always exported (they can't be accessed w/o the function // or function type being exported) for p := sig.entries.first; p != nil; p = p.next { p.obj.exported = true; } return typ; } func (P *Parser) DeclareFunc(pos int, ident string, typ *Globals.Type) *Globals.Object { // determine scope scope := P.top_scope; if typ.flags & Type.RECV != 0 { // method - declare in corresponding struct if typ.scope.entries.len_ < 1 { panic("no recv in signature?"); } recv_typ := typ.scope.entries.first.obj.typ; if recv_typ.form == Type.POINTER { recv_typ = recv_typ.elt; } scope = recv_typ.scope; } // declare the function obj := scope.Lookup(ident); if obj == nil { obj = Globals.NewObject(pos, Object.FUNC, ident); obj.typ = typ; // TODO do we need to set the primary type? probably... P.DeclareInScope(scope, obj); return obj; } // 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 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 !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; } // ---------------------------------------------------------------------------- // Common productions func (P *Parser) TryType() *Globals.Type; func (P *Parser) ParseExpression() Globals.Expr; func (P *Parser) TryStatement() bool; func (P *Parser) ParseDeclaration(); func (P *Parser) ParseIdent(allow_keyword bool) (pos int, ident string) { P.Trace("Ident"); pos, ident = P.pos, ""; // NOTE Can make this faster by not doing the keyword lookup in the // scanner if we don't care about keywords. if P.tok == Scanner.IDENT || allow_keyword && P.tok > Scanner.IDENT { ident = P.val; if P.verbose { P.PrintIndent(); print("Ident = \"", ident, "\"\n"); } P.Next(); } else { P.Expect(Scanner.IDENT); // use Expect() error handling } P.Ecart(); return pos, ident; } func (P *Parser) ParseIdentDecl(kind int) *Globals.Object { P.Trace("IdentDecl"); pos, ident := P.ParseIdent(kind == Object.FIELD); obj := Globals.NewObject(pos, kind, ident); P.Declare(obj); P.Ecart(); return obj; } func (P *Parser) ParseIdentDeclList(kind int) *Globals.List { P.Trace("IdentDeclList"); list := Globals.NewList(); list.AddObj(P.ParseIdentDecl(kind)); for P.tok == Scanner.COMMA { P.Next(); list.AddObj(P.ParseIdentDecl(kind)); } P.Ecart(); return list; } func (P *Parser) ParseIdentList() { P.Trace("IdentList"); P.ParseIdent(false); for P.tok == Scanner.COMMA { P.Next(); P.ParseIdent(false); } P.Ecart(); } func (P *Parser) ParseQualifiedIdent(pos int, ident string) *Globals.Object { P.Trace("QualifiedIdent"); if pos < 0 { pos, ident = P.ParseIdent(false); } if P.semantic_checks { obj := P.Lookup(ident); if obj == nil { P.Error(pos, `"` + ident + `" is not declared`); obj = Globals.NewObject(pos, Object.BAD, ident); } if obj.kind == Object.PACKAGE && P.tok == Scanner.PERIOD { if obj.pnolev < 0 { panic("obj.pnolev < 0"); } pkg := P.comp.pkg_list[obj.pnolev]; //if pkg.obj.ident != ident { // panic("pkg.obj.ident != ident"); //} P.Next(); // consume "." pos, ident = P.ParseIdent(false); obj = pkg.scope.Lookup(ident); if obj == nil { P.Error(pos, `"` + ident + `" is not declared in package "` + pkg.obj.ident + `"`); obj = Globals.NewObject(pos, Object.BAD, ident); } } P.Ecart(); return obj; } else { if P.tok == Scanner.PERIOD { P.Next(); P.ParseIdent(false); } P.Ecart(); return nil; } } // ---------------------------------------------------------------------------- // Types func (P *Parser) ParseType() *Globals.Type { P.Trace("Type"); typ := P.TryType(); if typ == nil { P.Error(P.pos, "type expected"); typ = Universe.bad_t; } P.Ecart(); return typ; } func (P *Parser) ParseVarType() *Globals.Type { P.Trace("VarType"); pos := P.pos; typ := P.ParseType(); if P.semantic_checks { switch typ.form { case Type.ARRAY: if P.comp.flags.sixg || typ.len_ >= 0 { break; } // open arrays must be pointers fallthrough; case Type.MAP, Type.CHANNEL, Type.FUNCTION: P.Error(pos, "must be pointer to this type"); typ = Universe.bad_t; } } P.Ecart(); return typ; } func (P *Parser) ParseTypeName() *Globals.Type { P.Trace("TypeName"); if P.semantic_checks { pos := P.pos; obj := P.ParseQualifiedIdent(-1, ""); typ := obj.typ; if obj.kind != Object.TYPE { P.Error(pos, "qualified identifier does not denote a type"); typ = Universe.bad_t; } P.Ecart(); return typ; } else { P.ParseQualifiedIdent(-1, ""); P.Ecart(); return Universe.bad_t; } } func (P *Parser) ParseArrayType() *Globals.Type { P.Trace("ArrayType"); P.Expect(Scanner.LBRACK); typ := Globals.NewType(Type.ARRAY); if P.tok != Scanner.RBRACK { // TODO set typ.len_ P.ParseExpression(); } P.Expect(Scanner.RBRACK); typ.elt = P.ParseVarType(); P.Ecart(); return typ; } func (P *Parser) ParseChannelType() *Globals.Type { P.Trace("ChannelType"); P.Expect(Scanner.CHAN); typ := Globals.NewType(Type.CHANNEL); switch P.tok { case Scanner.SEND: typ.flags = Type.SEND; P.Next(); case Scanner.RECV: typ.flags = Type.RECV; P.Next(); default: typ.flags = Type.SEND + Type.RECV; } typ.elt = P.ParseVarType(); P.Ecart(); return typ; } func (P *Parser) ParseVarDeclList(kind int) { P.Trace("VarDeclList"); list := P.ParseIdentDeclList(kind); typ := P.ParseVarType(); for p := list.first; p != nil; p = p.next { p.obj.typ = typ; // TODO should use/have set_type() } P.Ecart(); } func (P *Parser) ParseParameterList() { P.Trace("ParameterList"); P.ParseVarDeclList(Object.VAR); for P.tok == Scanner.COMMA { P.Next(); P.ParseVarDeclList(Object.VAR); } P.Ecart(); } func (P *Parser) ParseParameters() { P.Trace("Parameters"); P.Expect(Scanner.LPAREN); if P.tok != Scanner.RPAREN { P.ParseParameterList(); } P.Expect(Scanner.RPAREN); P.Ecart(); } func (P *Parser) TryResult() bool { P.Trace("Result (try)"); res := false; if P.tok == Scanner.LPAREN { // TODO: here we allow empty returns - should proably fix this P.ParseParameters(); res = true; } else { res = P.TryType() != nil; } P.Ecart(); return res; } // Anonymous signatures // // (params) // (params) type // (params) (results) // (recv) . (params) // (recv) . (params) type // (recv) . (params) (results) func (P *Parser) ParseAnonymousSignature() *Globals.Type { P.Trace("AnonymousSignature"); P.OpenScope(); P.level--; sig := P.top_scope; p0 := 0; recv_pos := P.pos; P.ParseParameters(); if P.tok == Scanner.PERIOD { p0 = sig.entries.len_; if P.semantic_checks && p0 != 1 { P.Error(recv_pos, "must have exactly one receiver") panic("UNIMPLEMENTED (ParseAnonymousSignature)"); // TODO do something useful here } P.Next(); P.ParseParameters(); } r0 := sig.entries.len_; P.TryResult(); P.level++; P.CloseScope(); P.Ecart(); return MakeFunctionType(sig, p0, r0, true); } // Named signatures // // ident (params) // ident (params) type // ident (params) (results) // (recv) ident (params) // (recv) ident (params) type // (recv) ident (params) (results) func (P *Parser) ParseNamedSignature() (pos int, ident string, typ *Globals.Type) { P.Trace("NamedSignature"); P.OpenScope(); P.level--; sig := P.top_scope; p0 := 0; if P.tok == Scanner.LPAREN { recv_pos := P.pos; P.ParseParameters(); p0 = sig.entries.len_; if P.semantic_checks && p0 != 1 { print("p0 = ", p0, "\n"); P.Error(recv_pos, "must have exactly one receiver") panic("UNIMPLEMENTED (ParseNamedSignature)"); // TODO do something useful here } } pos, ident = P.ParseIdent(true); P.ParseParameters(); r0 := sig.entries.len_; P.TryResult(); P.level++; P.CloseScope(); P.Ecart(); return pos, ident, MakeFunctionType(sig, p0, r0, true); } func (P *Parser) ParseFunctionType() *Globals.Type { P.Trace("FunctionType"); P.Expect(Scanner.FUNC); typ := P.ParseAnonymousSignature(); P.Ecart(); return typ; } func (P *Parser) ParseMethodDecl(recv_typ *Globals.Type) { P.Trace("MethodDecl"); pos, ident := P.ParseIdent(true); P.OpenScope(); P.level--; sig := P.top_scope; // dummy receiver (give it a name so it won't conflict with unnamed result) recv := Globals.NewObject(pos, Object.VAR, ".recv"); recv.typ = recv_typ; sig.Insert(recv); P.ParseParameters(); r0 := sig.entries.len_; P.TryResult(); P.level++; P.CloseScope(); P.Optional(Scanner.SEMICOLON); obj := Globals.NewObject(pos, Object.FUNC, ident); obj.typ = MakeFunctionType(sig, 1, r0, true); P.Declare(obj); P.Ecart(); } func (P *Parser) ParseInterfaceType() *Globals.Type { P.Trace("InterfaceType"); P.Expect(Scanner.INTERFACE); P.Expect(Scanner.LBRACE); P.OpenScope(); P.level--; typ := Globals.NewType(Type.INTERFACE); typ.scope = P.top_scope; for P.tok >= Scanner.IDENT { P.ParseMethodDecl(typ); } P.level++; P.CloseScope(); P.Expect(Scanner.RBRACE); P.Ecart(); return typ; } func (P *Parser) ParseMapType() *Globals.Type { P.Trace("MapType"); P.Expect(Scanner.MAP); P.Expect(Scanner.LBRACK); typ := Globals.NewType(Type.MAP); typ.aux = P.ParseVarType(); P.Expect(Scanner.RBRACK); typ.elt = P.ParseVarType(); P.Ecart(); return typ; } func (P *Parser) ParseStructType() *Globals.Type { P.Trace("StructType"); P.Expect(Scanner.STRUCT); P.Expect(Scanner.LBRACE); P.OpenScope(); P.level--; typ := Globals.NewType(Type.STRUCT); typ.scope = P.top_scope; for P.tok >= Scanner.IDENT { P.ParseVarDeclList(Object.FIELD); if P.tok != Scanner.RBRACE { P.Expect(Scanner.SEMICOLON); } } P.Optional(Scanner.SEMICOLON); P.level++; P.CloseScope(); P.Expect(Scanner.RBRACE); P.Ecart(); return typ; } func (P *Parser) ParsePointerType() *Globals.Type { P.Trace("PointerType"); P.Expect(Scanner.MUL); typ := Globals.NewType(Type.POINTER); var elt *Globals.Type; if P.semantic_checks { if P.tok == Scanner.STRING && !P.comp.flags.sixg { // implicit package.type forward declaration // TODO eventually the scanner should strip the quotes pkg_name := P.val[1 : len(P.val) - 1]; // strip quotes pkg := P.comp.Lookup(pkg_name); if pkg == nil { // package doesn't exist yet - add it to the package list obj := Globals.NewObject(P.pos, Object.PACKAGE, ".pkg"); pkg = Globals.NewPackage(pkg_name, obj, Globals.NewScope(nil)); pkg.key = ""; // mark as forward-declared package P.comp.Insert(pkg); } else { // package exists already - must be forward declaration if pkg.key != "" { P.Error(P.pos, `cannot use implicit package forward declaration for imported package "` + P.val + `"`); panic("wrong package forward decl"); // TODO introduce dummy package so we can continue safely } } P.Next(); // consume package name P.Expect(Scanner.PERIOD); pos, ident := P.ParseIdent(false); obj := pkg.scope.Lookup(ident); if obj == nil { elt = Globals.NewType(Type.FORWARD); elt.scope = P.top_scope; // not really needed here, but for consistency obj = Globals.NewObject(pos, Object.TYPE, ident); obj.exported = true; // the type name must be visible obj.typ = elt; elt.obj = obj; // primary type object; pkg.scope.Insert(obj); obj.pnolev = pkg.obj.pnolev; } else { if obj.kind != Object.TYPE || obj.typ.form != Type.FORWARD { panic("inconsistency in package.type forward declaration"); } elt = obj.typ; } } else if P.tok == Scanner.IDENT { if P.Lookup(P.val) == nil { // implicit type forward declaration // create a named forward type pos, ident := P.ParseIdent(false); obj := Globals.NewObject(pos, Object.TYPE, ident); elt = Globals.NewType(Type.FORWARD); obj.typ = elt; elt.obj = obj; // primary type object; // remember the current scope - resolving the forward // type must find a matching declaration in this or a less nested scope elt.scope = P.top_scope; } else { // type name // (ParseType() (via TryType()) checks for forward types and complains, // so call ParseTypeName() directly) // we can only have a foward type here if we refer to the name of a // yet incomplete type (i.e. if we are in the middle of a type's declaration) elt = P.ParseTypeName(); } // collect uses of pointer types referring to forward types if elt.form == Type.FORWARD { P.forward_types.AddTyp(typ); } } else { elt = P.ParseType(); } } else { elt = P.ParseType(); } typ.elt = elt; P.Ecart(); return typ; } // Returns nil if no type was found. func (P *Parser) TryType() *Globals.Type { P.Trace("Type (try)"); pos := P.pos; var typ *Globals.Type = nil; switch P.tok { case Scanner.IDENT: typ = P.ParseTypeName(); case Scanner.LBRACK: typ = P.ParseArrayType(); case Scanner.CHAN: typ = P.ParseChannelType(); case Scanner.INTERFACE: typ = P.ParseInterfaceType(); case Scanner.FUNC: typ = P.ParseFunctionType(); case Scanner.MAP: typ = P.ParseMapType(); case Scanner.STRUCT: typ = P.ParseStructType(); case Scanner.MUL: typ = P.ParsePointerType(); } if typ != nil && typ.form == Type.FORWARD { P.Error(pos, "incomplete type"); } P.Ecart(); return typ; } // ---------------------------------------------------------------------------- // Blocks func (P *Parser) ParseStatement() { P.Trace("Statement"); if !P.TryStatement() { P.Error(P.pos, "statement expected"); P.Next(); // make progress } P.Ecart(); } func (P *Parser) ParseStatementList() { P.Trace("StatementList"); for P.TryStatement() { P.Optional(Scanner.SEMICOLON); } P.Ecart(); } func (P *Parser) ParseBlock(sig *Globals.Scope) { P.Trace("Block"); P.Expect(Scanner.LBRACE); P.OpenScope(); if sig != nil { P.level--; // add copies of the formal parameters to the function scope scope := P.top_scope; for p := sig.entries.first; p != nil; p = p.next { scope.Insert(p.obj.Copy()) } } if P.tok != Scanner.RBRACE && P.tok != Scanner.SEMICOLON { P.ParseStatementList(); } P.Optional(Scanner.SEMICOLON); if sig != nil { P.level++; } P.CloseScope(); P.Expect(Scanner.RBRACE); P.Ecart(); } // ---------------------------------------------------------------------------- // Expressions func (P *Parser) ParseExpressionList(list *Globals.List) { P.Trace("ExpressionList"); list.AddExpr(P.ParseExpression()); for P.tok == Scanner.COMMA { P.Next(); list.AddExpr(P.ParseExpression()); } P.Ecart(); } func (P *Parser) ParseNewExpressionList() *Globals.List { P.Trace("NewExpressionList"); list := Globals.NewList(); P.ParseExpressionList(list); P.Ecart(); return list; } func (P *Parser) ParseNew() Globals.Expr { P.Trace("New"); P.Expect(Scanner.NEW); P.Expect(Scanner.LPAREN); P.ParseType(); args := Globals.NewList(); if P.tok == Scanner.COMMA { P.Next(); P.ParseExpressionList(args) } P.Expect(Scanner.RPAREN); P.Ecart(); return nil; } func (P *Parser) ParseFunctionLit() Globals.Expr { P.Trace("FunctionLit"); typ := P.ParseFunctionType(); P.ParseBlock(typ.scope); P.Ecart(); return nil; } 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(list); for (P.tok == Scanner.COMMA) { P.ParseExpressionPair(list); } P.Ecart(); } func (P *Parser) ParseCompositeLit(typ *Globals.Type) Globals.Expr { P.Trace("CompositeLit"); // TODO I think we should use {} instead of () for // composite literals to syntactically distinguish // them from conversions. For now: allow both. var paren int; if P.tok == Scanner.LPAREN { P.Next(); paren = Scanner.RPAREN; } else { P.Expect(Scanner.LBRACE); paren = Scanner.RBRACE; } // TODO: should allow trailing ',' list := Globals.NewList(); if P.tok != paren { list.AddExpr(P.ParseExpression()); if P.tok == Scanner.COMMA { P.Next(); if P.tok != paren { P.ParseExpressionList(list); } } else if P.tok == Scanner.COLON { P.Next(); list.AddExpr(P.ParseExpression()); if P.tok == Scanner.COMMA { P.Next(); if P.tok != paren { P.ParseExpressionPairList(list); } } } } P.Expect(paren); P.Ecart(); return nil; } func (P *Parser) ParseOperand(pos int, ident string) Globals.Expr { P.Trace("Operand"); if pos < 0 && P.tok == Scanner.IDENT { // no look-ahead yet pos = P.pos; ident = P.val; P.Next(); } var res Globals.Expr = AST.Bad; if pos >= 0 { obj := P.ParseQualifiedIdent(pos, ident); if P.semantic_checks { if obj.kind == Object.TYPE { res = P.ParseCompositeLit(obj.typ); } else { res = AST.NewObject(pos, obj); } } } else { 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(P.pos, Universe.int_t); x.i = 42; // TODO set the right value res = x; P.Next(); case Scanner.FLOAT: x := AST.NewLiteral(P.pos, Universe.float_t); x.f = 42.0; // TODO set the right value res = x; P.Next(); case Scanner.STRING: x := AST.NewLiteral(P.pos, 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(P.pos, 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 res; } func (P *Parser) ParseSelectorOrTypeAssertion(x Globals.Expr) Globals.Expr { P.Trace("SelectorOrTypeAssertion"); period_pos := P.pos; P.Expect(Scanner.PERIOD); if P.tok >= Scanner.IDENT { ident_pos, ident := P.ParseIdent(true); if P.semantic_checks { switch typ := x.typ(); typ.form { case Type.BAD: // ignore break; case Type.STRUCT, Type.INTERFACE: obj := typ.scope.Lookup(ident); if obj != nil { x = AST.NewSelector(x.pos(), obj.typ); } else { P.Error(ident_pos, `no field/method "` + ident + `"`); x = AST.Bad; } default: P.Error(period_pos, `"." not applicable`); x = AST.Bad; } } } else { P.Expect(Scanner.LPAREN); P.ParseType(); P.Expect(Scanner.RPAREN); if P.semantic_checks { panic("UNIMPLEMENTED"); } } P.Ecart(); return x; } func (P *Parser) ParseIndexOrSlice(x Globals.Expr) Globals.Expr { P.Trace("IndexOrSlice"); pos := P.pos; P.Expect(Scanner.LBRACK); i1 := P.ParseExpression(); var i2 Globals.Expr; if P.tok == Scanner.COLON { P.Next(); i2 := P.ParseExpression(); } P.Expect(Scanner.RBRACK); if P.semantic_checks { switch typ := x.typ(); typ.form { case Type.BAD: // ignore break; case Type.STRING, Type.ARRAY: panic("UNIMPLEMENTED"); case Type.MAP: if Type.Equal(typ.aux, i1.typ()) { // x = AST.NewSubscript(x, i1); panic("UNIMPLEMENTED"); } else { P.Error(x.pos(), "map key type mismatch"); x = AST.Bad; } default: P.Error(pos, `"[]" not applicable`); x = AST.Bad; } } P.Ecart(); return x; } func (P *Parser) ParseCall(x Globals.Expr) Globals.Expr { P.Trace("Call"); P.Expect(Scanner.LPAREN); args := Globals.NewList(); if P.tok != Scanner.RPAREN { P.ParseExpressionList(args); } P.Expect(Scanner.RPAREN); if P.semantic_checks { panic("UNIMPLEMENTED"); } P.Ecart(); return x; } func (P *Parser) ParsePrimaryExpr(pos int, ident string) Globals.Expr { P.Trace("PrimaryExpr"); x := P.ParseOperand(pos, ident); for { switch P.tok { 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 x; } // TODO is this function needed? func (P *Parser) ParsePrimaryExprList() *Globals.List { P.Trace("PrimaryExprList"); list := Globals.NewList(); list.AddExpr(P.ParsePrimaryExpr(-1, "")); for P.tok == Scanner.COMMA { P.Next(); list.AddExpr(P.ParsePrimaryExpr(-1, "")); } P.Ecart(); return list; } func (P *Parser) ParseUnaryExpr() Globals.Expr { P.Trace("UnaryExpr"); switch P.tok { case Scanner.ADD: fallthrough; case Scanner.SUB: fallthrough; case Scanner.NOT: fallthrough; case Scanner.XOR: fallthrough; case Scanner.MUL: fallthrough; case Scanner.RECV: fallthrough; case Scanner.AND: P.Next(); P.ParseUnaryExpr(); P.Ecart(); return nil; // TODO fix this } P.ParsePrimaryExpr(-1, ""); P.Ecart(); return nil; // TODO fix this } func Precedence(tok int) int { // TODO should use a map or array here for lookup switch tok { case Scanner.LOR: return 1; case Scanner.LAND: return 2; case Scanner.SEND, Scanner.RECV: return 3; case Scanner.EQL, Scanner.NEQ, Scanner.LSS, Scanner.LEQ, Scanner.GTR, Scanner.GEQ: return 4; case Scanner.ADD, Scanner.SUB, Scanner.OR, Scanner.XOR: return 5; case Scanner.MUL, Scanner.QUO, Scanner.REM, Scanner.SHL, Scanner.SHR, Scanner.AND: return 6; } return 0; } func (P *Parser) ParseBinaryExpr(pos int, ident string, prec1 int) Globals.Expr { P.Trace("BinaryExpr"); var x Globals.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); e.typ_ = Universe.bad_t; // TODO fix this e.op = P.tok; // TODO should we use tokens or separate operator constants? e.x = x; P.Next(); e.y = P.ParseBinaryExpr(-1, "", prec + 1); x = e; } } P.Ecart(); return x; } // Expressions where the first token may be an identifier which has already // been consumed. If the identifier is present, pos is the identifier position, // otherwise pos must be < 0 (and ident is ignored). func (P *Parser) ParseIdentExpression(pos int, ident string) Globals.Expr { P.Trace("IdentExpression"); indent := P.indent; x := P.ParseBinaryExpr(pos, ident, 1); if indent != P.indent { panic("imbalanced tracing code (Expression)"); } P.Ecart(); return x; } func (P *Parser) ParseExpression() Globals.Expr { P.Trace("Expression"); x := P.ParseIdentExpression(-1, ""); P.Ecart(); return x; } // ---------------------------------------------------------------------------- // Statements 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 P.semantic_checks { 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"); 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, 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 just_ident = true; } } 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(); } 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); } P.Ecart(); return pos_list, ident_list, expr_list; } func (P *Parser) ParseSimpleStat() { P.Trace("SimpleStat"); // 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. 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 if P.semantic_checks && ident_list.len_ != 1 { P.Error(P.pos, "illegal label declaration"); } P.Next(); case Scanner.DEFINE: // variable declaration if P.semantic_checks && ident_list.len_ == 0 { P.Error(P.pos, "illegal left-hand side for declaration"); } P.Next(); pos := P.pos; val_list := P.ParseNewExpressionList(); if P.semantic_checks && val_list.len_ != ident_list.len_ { P.Error(pos, "number of expressions does not match number of variables"); } // declare variables if P.semantic_checks { 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; case Scanner.ADD_ASSIGN: fallthrough; case Scanner.SUB_ASSIGN: fallthrough; case Scanner.MUL_ASSIGN: fallthrough; case Scanner.QUO_ASSIGN: fallthrough; case Scanner.REM_ASSIGN: fallthrough; case Scanner.AND_ASSIGN: fallthrough; case Scanner.OR_ASSIGN: fallthrough; case Scanner.XOR_ASSIGN: fallthrough; case Scanner.SHL_ASSIGN: fallthrough; case Scanner.SHR_ASSIGN: P.ConvertToExprList(pos_list, ident_list, expr_list); P.Next(); pos := P.pos; val_list := P.ParseNewExpressionList(); if P.semantic_checks && val_list.len_ != expr_list.len_ { P.Error(pos, "number of expressions does not match number of variables"); } default: P.ConvertToExprList(pos_list, ident_list, expr_list); if P.semantic_checks && expr_list.len_ != 1 { P.Error(P.pos, "no expression list allowed"); } if P.tok == Scanner.INC || P.tok == Scanner.DEC { P.Next(); } } P.Ecart(); } func (P *Parser) ParseGoStat() { P.Trace("GoStat"); P.Expect(Scanner.GO); P.ParseExpression(); P.Ecart(); } func (P *Parser) ParseReturnStat() { P.Trace("ReturnStat"); P.Expect(Scanner.RETURN); res := Globals.NewList(); if P.tok != Scanner.SEMICOLON && P.tok != Scanner.RBRACE { P.ParseExpressionList(res); } P.Ecart(); } func (P *Parser) ParseControlFlowStat(tok int) { P.Trace("ControlFlowStat"); P.Expect(tok); if P.tok == Scanner.IDENT { P.ParseIdent(false); } P.Ecart(); } func (P *Parser) ParseIfStat() *AST.IfStat { P.Trace("IfStat"); P.Expect(Scanner.IF); P.OpenScope(); if P.tok != Scanner.LBRACE { if P.tok != Scanner.SEMICOLON { P.ParseSimpleStat(); } if P.tok == Scanner.SEMICOLON { P.Next(); if P.tok != Scanner.LBRACE { P.ParseExpression(); } } } P.ParseBlock(nil); if P.tok == Scanner.ELSE { P.Next(); if P.tok == Scanner.IF { P.ParseIfStat(); } else { // TODO should be P.ParseBlock() P.ParseStatement(); } } P.CloseScope(); P.Ecart(); } func (P *Parser) ParseForStat() { P.Trace("ForStat"); P.Expect(Scanner.FOR); P.OpenScope(); if P.tok != Scanner.LBRACE { if P.tok != Scanner.SEMICOLON { P.ParseSimpleStat(); } if P.tok == Scanner.SEMICOLON { P.Next(); if P.tok != Scanner.SEMICOLON { P.ParseExpression(); } P.Expect(Scanner.SEMICOLON); if P.tok != Scanner.LBRACE { P.ParseSimpleStat(); } } } P.ParseBlock(nil); P.CloseScope(); P.Ecart(); } func (P *Parser) ParseCase() { P.Trace("Case"); if P.tok == Scanner.CASE { P.Next(); list := Globals.NewList(); P.ParseExpressionList(list); } else { P.Expect(Scanner.DEFAULT); } P.Expect(Scanner.COLON); P.Ecart(); } func (P *Parser) ParseCaseClause() { P.Trace("CaseClause"); P.ParseCase(); if P.tok != Scanner.FALLTHROUGH && P.tok != Scanner.RBRACE { P.ParseStatementList(); P.Optional(Scanner.SEMICOLON); } if P.tok == Scanner.FALLTHROUGH { P.Next(); P.Optional(Scanner.SEMICOLON); } P.Ecart(); } func (P *Parser) ParseSwitchStat() { P.Trace("SwitchStat"); P.Expect(Scanner.SWITCH); P.OpenScope(); if P.tok != Scanner.LBRACE { if P.tok != Scanner.SEMICOLON { P.ParseSimpleStat(); } if P.tok == Scanner.SEMICOLON { P.Next(); if P.tok != Scanner.LBRACE { P.ParseExpression(); } } } P.Expect(Scanner.LBRACE); for P.tok == Scanner.CASE || P.tok == Scanner.DEFAULT { P.ParseCaseClause(); } P.Expect(Scanner.RBRACE); P.CloseScope(); P.Ecart(); } func (P *Parser) ParseCommCase() { P.Trace("CommCase"); if P.tok == Scanner.CASE { P.Next(); if P.tok == Scanner.GTR { // send P.Next(); P.ParseExpression(); P.Expect(Scanner.EQL); P.ParseExpression(); } else { // receive if P.tok != Scanner.LSS { P.ParseIdent(false); P.Expect(Scanner.ASSIGN); } P.Expect(Scanner.LSS); P.ParseExpression(); } } else { P.Expect(Scanner.DEFAULT); } P.Expect(Scanner.COLON); P.Ecart(); } func (P *Parser) ParseCommClause() { P.Trace("CommClause"); P.ParseCommCase(); if P.tok != Scanner.CASE && P.tok != Scanner.DEFAULT && P.tok != Scanner.RBRACE { P.ParseStatementList(); P.Optional(Scanner.SEMICOLON); } P.Ecart(); } func (P *Parser) ParseRangeStat() bool { P.Trace("RangeStat"); P.Expect(Scanner.RANGE); P.ParseIdentList(); P.Expect(Scanner.DEFINE); P.ParseExpression(); P.ParseBlock(nil); P.Ecart(); } func (P *Parser) ParseSelectStat() bool { P.Trace("SelectStat"); P.Expect(Scanner.SELECT); P.Expect(Scanner.LBRACE); for P.tok != Scanner.RBRACE && P.tok != Scanner.EOF { P.ParseCommClause(); } P.Next(); P.Ecart(); } func (P *Parser) TryStatement() bool { P.Trace("Statement (try)"); indent := P.indent; res := true; switch P.tok { case Scanner.CONST: fallthrough; case Scanner.TYPE: fallthrough; case Scanner.VAR: P.ParseDeclaration(); case Scanner.FUNC: // for now we do not allow local function declarations fallthrough; case Scanner.MUL, Scanner.SEND, Scanner.RECV, Scanner.IDENT, Scanner.LPAREN: P.ParseSimpleStat(); case Scanner.GO: P.ParseGoStat(); case Scanner.RETURN: P.ParseReturnStat(); case Scanner.BREAK, Scanner.CONTINUE, Scanner.GOTO: P.ParseControlFlowStat(P.tok); case Scanner.LBRACE: P.ParseBlock(nil); case Scanner.IF: P.ParseIfStat(); case Scanner.FOR: P.ParseForStat(); case Scanner.SWITCH: P.ParseSwitchStat(); case Scanner.RANGE: P.ParseRangeStat(); case Scanner.SELECT: P.ParseSelectStat(); default: // no statement found res = false; } if indent != P.indent { panic("imbalanced tracing code (Statement)"); } P.Ecart(); return res; } // ---------------------------------------------------------------------------- // Declarations func (P *Parser) ParseImportSpec() { P.Trace("ImportSpec"); var obj *Globals.Object = nil; if P.tok == Scanner.PERIOD { P.Error(P.pos, `"import ." not yet handled properly`); P.Next(); } else if P.tok == Scanner.IDENT { obj = P.ParseIdentDecl(Object.PACKAGE); } if P.semantic_checks && P.tok == Scanner.STRING { // TODO eventually the scanner should strip the quotes pkg_name := P.val[1 : len(P.val) - 1]; // strip quotes // TODO switch to indirect import once the compiler problems are fixed //pkg := Import.Import(P.comp, pkg_name); pkg := P.comp.env.Import(P.comp, pkg_name); if pkg != nil { pno := pkg.obj.pnolev; // preserve pno if obj == nil { // use original package name obj = pkg.obj; P.Declare(obj); // this changes (pkg.)obj.pnolev! } obj.pnolev = pno; // correct pno } else { P.Error(P.pos, `import of "` + pkg_name + `" failed`); } P.Next(); } else { P.Expect(Scanner.STRING); // use Expect() error handling } P.Ecart(); } func (P *Parser) ParseConstSpec(exported bool) { P.Trace("ConstSpec"); list := P.ParseIdentDeclList(Object.CONST); typ := P.TryType(); if typ != nil { for p := list.first; p != nil; p = p.next { p.obj.typ = typ; } } if P.tok == Scanner.ASSIGN { P.Next(); P.ParseNewExpressionList(); } if exported { for p := list.first; p != nil; p = p.next { p.obj.exported = true; } } P.Ecart(); } func (P *Parser) ParseTypeSpec(exported bool) { P.Trace("TypeSpec"); var typ *Globals.Type; pos, ident := P.ParseIdent(false); obj := P.Lookup(ident); if !P.comp.flags.sixg && obj != nil { if obj.typ.form == Type.FORWARD { // imported forward-declared type if !exported { panic("foo"); } } else { panic("bar"); } } else { // Immediately after declaration of the type name, the type is // considered forward-declared. It may be referred to from inside // the type specification only via a pointer type. typ = Globals.NewType(Type.FORWARD); typ.scope = P.top_scope; // not really needed here, but for consistency obj = Globals.NewObject(pos, Object.TYPE, ident); obj.exported = exported; obj.typ = typ; typ.obj = obj; // primary type object P.Declare(obj); } // If the next token is an identifier and we have a legal program, // it must be a typename. In that case this declaration introduces // an alias type. if P.tok == Scanner.IDENT { typ = Globals.NewType(Type.ALIAS); elt := P.ParseType(); // we want a complete type - don't shortcut to ParseTypeName() typ.elt = elt; if elt.form == Type.ALIAS { typ.aux = elt.aux; // the base type } else { typ.aux = elt; } } else { typ = P.ParseType(); } obj.typ = typ; if typ.obj == nil { typ.obj = obj; // primary type object } // if the type is exported, for now we export all fields // of structs and interfaces by default // TODO this needs to change eventually // Actually in 6g even types referred to are exported - sigh... if exported && (typ.form == Type.STRUCT || typ.form == Type.INTERFACE) { for p := typ.scope.entries.first; p != nil; p = p.next { p.obj.exported = true; } } P.Ecart(); } func (P *Parser) ParseVarSpec(exported bool) { P.Trace("VarSpec"); list := P.ParseIdentDeclList(Object.VAR); if P.tok == Scanner.ASSIGN { P.Next(); P.ParseNewExpressionList(); } else { typ := P.ParseVarType(); for p := list.first; p != nil; p = p.next { p.obj.typ = typ; } if P.tok == Scanner.ASSIGN { P.Next(); P.ParseNewExpressionList(); } } if exported { for p := list.first; p != nil; p = p.next { p.obj.exported = true; } } P.Ecart(); } // TODO With method variables, we wouldn't need this dispatch function. func (P *Parser) ParseSpec(exported bool, keyword int) { switch keyword { case Scanner.IMPORT: P.ParseImportSpec(); case Scanner.CONST: P.ParseConstSpec(exported); case Scanner.TYPE: P.ParseTypeSpec(exported); case Scanner.VAR: P.ParseVarSpec(exported); default: panic("UNREACHABLE"); } } func (P *Parser) ParseDecl(exported bool, keyword int) { P.Trace("Decl"); P.Expect(keyword); if P.tok == Scanner.LPAREN { P.Next(); for P.tok == Scanner.IDENT { P.ParseSpec(exported, keyword); if P.tok != Scanner.RPAREN { // P.Expect(Scanner.SEMICOLON); P.Optional(Scanner.SEMICOLON); // TODO this seems wrong! (needed for math.go) } } P.Next(); } else { P.ParseSpec(exported, keyword); } P.Ecart(); } func (P *Parser) ParseFuncDecl(exported bool) { P.Trace("FuncDecl"); P.Expect(Scanner.FUNC); pos, ident, typ := P.ParseNamedSignature(); obj := P.DeclareFunc(pos, ident, typ); // need obj later for statements obj.exported = exported; if P.tok == Scanner.SEMICOLON { // forward declaration P.Next(); } else { P.ParseBlock(typ.scope); } P.Ecart(); } func (P *Parser) ParseExportDecl() { P.Trace("ExportDecl"); // TODO This is deprecated syntax and should go away eventually. // (Also at the moment the syntax is everything goes...) //P.Expect(Scanner.EXPORT); if !P.comp.flags.sixg { P.Error(P.pos, "deprecated export syntax (use -6g to enable)"); } has_paren := false; if P.tok == Scanner.LPAREN { P.Next(); has_paren = true; } for P.tok == Scanner.IDENT { pos, ident := P.ParseIdent(false); P.exports.AddStr(ident); P.Optional(Scanner.COMMA); // TODO this seems wrong } if has_paren { P.Expect(Scanner.RPAREN) } P.Ecart(); } func (P *Parser) ParseDeclaration() { P.Trace("Declaration"); indent := P.indent; exported := false; if P.tok == Scanner.EXPORT { if P.level == 0 { exported = true; } else { P.Error(P.pos, "local declarations cannot be exported"); } P.Next(); } switch P.tok { case Scanner.CONST, Scanner.TYPE, Scanner.VAR: P.ParseDecl(exported, P.tok); case Scanner.FUNC: P.ParseFuncDecl(exported); case Scanner.EXPORT: if exported { P.Error(P.pos, "cannot mark export declaration for export"); } P.Next(); P.ParseExportDecl(); default: if exported && (P.tok == Scanner.IDENT || P.tok == Scanner.LPAREN) { P.ParseExportDecl(); } else { P.Error(P.pos, "declaration expected"); P.Next(); // make progress } } if indent != P.indent { panic("imbalanced tracing code (Declaration)"); } P.Ecart(); } // ---------------------------------------------------------------------------- // Program func (P *Parser) ResolveForwardTypes() { if !P.semantic_checks { return; } for p := P.forward_types.first; p != nil; p = p.next { typ := p.typ; if typ.form != Type.POINTER { panic("unresolved types should be pointers only"); } elt := typ.elt; if typ.elt.form != Type.FORWARD { panic("unresolved pointer should point to forward type"); } obj := elt.obj; if obj.typ == elt { // actual forward declaration (as opposed to forward types introduced // during type declaration) - need to lookup the actual type object var elt_obj *Globals.Object; for scope := elt.scope; scope != nil && elt_obj == nil; scope = scope.parent { elt_obj = scope.Lookup(obj.ident); } // update the type object if we found one if elt_obj != nil { if elt_obj.kind == Object.TYPE { obj = elt_obj; } else { P.Error(obj.pos, `"` + obj.ident + `" does not denote a type`); } } } // update the pointer type typ.elt = obj.typ; // TODO as long as we don't *use* a forward type, we are ok // => consider not reporting this as an error // (in a real forward declaration, the corresponding objects are not in a scope // and have incorrect pnolev) if typ.elt.form == Type.FORWARD { P.Error(obj.pos, `"` + obj.ident + `" is not declared after forward declaration`); } } } func (P *Parser) MarkExports() { if !P.semantic_checks { return; } scope := P.top_scope; for p := P.exports.first; p != nil; p = p.next { obj := scope.Lookup(p.str); if obj != nil { obj.exported = true; // For now we export deep // TODO this should change eventually - we need selective export if obj.kind == Object.TYPE { typ := obj.typ; if typ.form == Type.STRUCT || typ.form == Type.INTERFACE { scope := typ.scope; for p := scope.entries.first; p != nil; p = p.next { p.obj.exported = true; } } } } else { // TODO need to report proper src position P.Error(-1, `"` + p.str + `" is not declared - cannot be exported`); } } } func (P *Parser) ParseProgram() { P.Trace("Program"); P.OpenScope(); P.Expect(Scanner.PACKAGE); obj := P.ParseIdentDecl(Object.PACKAGE); P.Optional(Scanner.SEMICOLON); { P.OpenScope(); if P.level != 0 { panic("incorrect scope level"); } P.comp.Insert(Globals.NewPackage(P.S.filename, obj, P.top_scope)); if P.comp.pkg_ref != 1 { panic("should have exactly one package now"); } for P.tok == Scanner.IMPORT { P.ParseDecl(false, Scanner.IMPORT); P.Optional(Scanner.SEMICOLON); } for P.tok != Scanner.EOF { P.ParseDeclaration(); P.Optional(Scanner.SEMICOLON); } P.ResolveForwardTypes(); P.MarkExports(); if P.level != 0 { panic("incorrect scope level"); } P.CloseScope(); } P.CloseScope(); P.Ecart(); }