blob: a6064316cad67ae76c8c9a70c527d7c03d3ce562 [file] [log] [blame]
Robert Griesemer835cd462008-07-07 17:27:14 -07001// Copyright 2009 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package Parser
6
Robert Griesemer4b0b7d82008-07-29 19:02:49 -07007import Utils "utils"
Robert Griesemer835cd462008-07-07 17:27:14 -07008import Scanner "scanner"
Robert Griesemer230230c2008-07-14 18:06:41 -07009import Globals "globals"
Robert Griesemera6f87792008-07-15 15:37:14 -070010import Object "object"
11import Type "type"
Robert Griesemer230230c2008-07-14 18:06:41 -070012import Universe "universe"
Robert Griesemer4b0b7d82008-07-29 19:02:49 -070013import Import "import"
Robert Griesemer5a90ede2008-07-18 17:18:29 -070014import AST "ast"
Robert Griesemeraf065a02009-01-06 16:26:45 -080015import Expr "expr"
Robert Griesemer835cd462008-07-07 17:27:14 -070016
17
Russ Cox839a6842009-01-20 14:40:40 -080018type Parser struct {
Robert Griesemerc3e9c7d2008-07-17 18:02:10 -070019 comp *Globals.Compilation;
Robert Griesemerc7fb27f2008-08-11 09:45:40 -070020 verbose bool;
21 indent uint;
Robert Griesemeraf065a02009-01-06 16:26:45 -080022 scanner *Scanner.Scanner;
23 tokchan chan *Scanner.Token;
Russ Cox839a6842009-01-20 14:40:40 -080024
Robert Griesemer5a90ede2008-07-18 17:18:29 -070025 // Token
Robert Griesemer835cd462008-07-07 17:27:14 -070026 tok int; // one token look-ahead
Robert Griesemer5a90ede2008-07-18 17:18:29 -070027 pos int; // token source position
28 val string; // token value (for IDENT, NUMBER, STRING only)
29
30 // Semantic analysis
Robert Griesemer6dd92ea2008-07-30 21:26:15 -070031 level int; // 0 = global scope, -1 = function/struct scope of global functions/structs, etc.
Robert Griesemer230230c2008-07-14 18:06:41 -070032 top_scope *Globals.Scope;
Robert Griesemerc7fb27f2008-08-11 09:45:40 -070033 forward_types *Globals.List;
Robert Griesemerc3e9c7d2008-07-17 18:02:10 -070034 exports *Globals.List;
Robert Griesemer835cd462008-07-07 17:27:14 -070035}
36
37
Robert Griesemera6f87792008-07-15 15:37:14 -070038// ----------------------------------------------------------------------------
39// Support functions
40
Robert Griesemerc40be3b2008-07-08 16:39:04 -070041func (P *Parser) PrintIndent() {
42 for i := P.indent; i > 0; i-- {
Robert Griesemer683ded82008-08-11 21:20:42 -070043 print(". ");
Robert Griesemerc40be3b2008-07-08 16:39:04 -070044 }
45}
46
47
48func (P *Parser) Trace(msg string) {
Robert Griesemerc7fb27f2008-08-11 09:45:40 -070049 if P.verbose {
Robert Griesemerc40be3b2008-07-08 16:39:04 -070050 P.PrintIndent();
Robert Griesemer683ded82008-08-11 21:20:42 -070051 print(msg, " {\n");
Robert Griesemerc40be3b2008-07-08 16:39:04 -070052 }
Robert Griesemeraf065a02009-01-06 16:26:45 -080053 P.indent++; // always, so proper identation is always checked
Robert Griesemerc40be3b2008-07-08 16:39:04 -070054}
55
56
57func (P *Parser) Ecart() {
Robert Griesemeraf065a02009-01-06 16:26:45 -080058 P.indent--; // always, so proper identation is always checked
Robert Griesemerc7fb27f2008-08-11 09:45:40 -070059 if P.verbose {
Robert Griesemerc40be3b2008-07-08 16:39:04 -070060 P.PrintIndent();
Robert Griesemer683ded82008-08-11 21:20:42 -070061 print("}\n");
Robert Griesemerc40be3b2008-07-08 16:39:04 -070062 }
63}
64
65
66func (P *Parser) Next() {
Robert Griesemeraf065a02009-01-06 16:26:45 -080067 if P.tokchan == nil {
68 P.tok, P.pos, P.val = P.scanner.Scan();
Robert Griesemer882ac632008-08-06 18:57:37 -070069 } else {
Robert Griesemeraf065a02009-01-06 16:26:45 -080070 t := <- P.tokchan;
Robert Griesemer882ac632008-08-06 18:57:37 -070071 P.tok, P.pos, P.val = t.tok, t.pos, t.val;
72 }
Robert Griesemerc7fb27f2008-08-11 09:45:40 -070073 if P.verbose {
Robert Griesemerc40be3b2008-07-08 16:39:04 -070074 P.PrintIndent();
Robert Griesemer683ded82008-08-11 21:20:42 -070075 print("[", P.pos, "] ", Scanner.TokenName(P.tok), "\n");
Robert Griesemerc40be3b2008-07-08 16:39:04 -070076 }
77}
78
79
Robert Griesemeraf065a02009-01-06 16:26:45 -080080func (P *Parser) Open(comp *Globals.Compilation, scanner *Scanner.Scanner, tokchan chan *Scanner.Token) {
Robert Griesemerc3e9c7d2008-07-17 18:02:10 -070081 P.comp = comp;
Robert Griesemerc7fb27f2008-08-11 09:45:40 -070082 P.verbose = comp.flags.verbosity > 2;
Robert Griesemerc40be3b2008-07-08 16:39:04 -070083 P.indent = 0;
Robert Griesemeraf065a02009-01-06 16:26:45 -080084 P.scanner = scanner;
85 P.tokchan = tokchan;
Robert Griesemer835cd462008-07-07 17:27:14 -070086 P.Next();
Robert Griesemer4b0b7d82008-07-29 19:02:49 -070087 P.level = 0;
Robert Griesemer230230c2008-07-14 18:06:41 -070088 P.top_scope = Universe.scope;
Robert Griesemerc7fb27f2008-08-11 09:45:40 -070089 P.forward_types = Globals.NewList();
Robert Griesemerc3e9c7d2008-07-17 18:02:10 -070090 P.exports = Globals.NewList();
Robert Griesemer835cd462008-07-07 17:27:14 -070091}
92
93
Robert Griesemer8be580e2008-07-10 14:42:33 -070094func (P *Parser) Error(pos int, msg string) {
Robert Griesemeraf065a02009-01-06 16:26:45 -080095 P.scanner.Error(pos, msg);
Robert Griesemer835cd462008-07-07 17:27:14 -070096}
97
98
99func (P *Parser) Expect(tok int) {
Robert Griesemera6f87792008-07-15 15:37:14 -0700100 if P.tok != tok {
Robert Griesemer5a90ede2008-07-18 17:18:29 -0700101 P.Error(P.pos, "expected '" + Scanner.TokenName(tok) + "', found '" + Scanner.TokenName(P.tok) + "'");
Robert Griesemer835cd462008-07-07 17:27:14 -0700102 }
Robert Griesemera6f87792008-07-15 15:37:14 -0700103 P.Next(); // make progress in any case
Robert Griesemer835cd462008-07-07 17:27:14 -0700104}
105
106
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700107func (P *Parser) Optional(tok int) {
108 if P.tok == tok {
109 P.Next();
110 }
111}
112
113
Robert Griesemer230230c2008-07-14 18:06:41 -0700114// ----------------------------------------------------------------------------
Robert Griesemera6f87792008-07-15 15:37:14 -0700115// Scopes
Robert Griesemer230230c2008-07-14 18:06:41 -0700116
117func (P *Parser) OpenScope() {
118 P.top_scope = Globals.NewScope(P.top_scope);
119}
120
121
122func (P *Parser) CloseScope() {
123 P.top_scope = P.top_scope.parent;
124}
125
126
127func (P *Parser) Lookup(ident string) *Globals.Object {
128 for scope := P.top_scope; scope != nil; scope = scope.parent {
129 obj := scope.Lookup(ident);
130 if obj != nil {
131 return obj;
132 }
133 }
134 return nil;
135}
136
137
138func (P *Parser) DeclareInScope(scope *Globals.Scope, obj *Globals.Object) {
Robert Griesemer687f3872008-08-05 18:52:37 -0700139 if P.level > 0 {
Robert Griesemer683ded82008-08-11 21:20:42 -0700140 panic("cannot declare objects in other packages");
Robert Griesemer687f3872008-08-05 18:52:37 -0700141 }
Robert Griesemer4b0b7d82008-07-29 19:02:49 -0700142 obj.pnolev = P.level;
143 if scope.Lookup(obj.ident) != nil {
Robert Griesemera6f87792008-07-15 15:37:14 -0700144 P.Error(obj.pos, `"` + obj.ident + `" is declared already`);
Robert Griesemer230230c2008-07-14 18:06:41 -0700145 return; // don't insert it into the scope
146 }
147 scope.Insert(obj);
148}
149
150
151func (P *Parser) Declare(obj *Globals.Object) {
152 P.DeclareInScope(P.top_scope, obj);
153}
154
155
Robert Griesemeraf065a02009-01-06 16:26:45 -0800156func MakeFunctionType(sig *Globals.Scope, p0, r0 int) *Globals.Type {
157 form := Type.FUNCTION;
158 if p0 == 1 {
159 form = Type.METHOD;
160 } else {
161 if p0 != 0 {
162 panic("incorrect p0");
Robert Griesemer28547612008-08-05 15:20:58 -0700163 }
Robert Griesemer4b0b7d82008-07-29 19:02:49 -0700164 }
Robert Griesemeraf065a02009-01-06 16:26:45 -0800165 typ := Globals.NewType(form);
166 typ.len = r0 - p0;
Robert Griesemer28547612008-08-05 15:20:58 -0700167 typ.scope = sig;
168
Robert Griesemeraf065a02009-01-06 16:26:45 -0800169 // set result type
170 if sig.entries.len - r0 == 1 {
171 // exactly one result value
172 typ.elt = sig.entries.last.obj.typ;
173 } else {
174 // 0 or >1 result values - create a tuple referring to this type
175 tup := Globals.NewType(Type.TUPLE);
176 tup.elt = typ;
177 typ.elt = tup;
178 }
179
180 // parameters/results are always exported (they can't be accessed
181 // w/o the function or function type being exported)
Robert Griesemer28547612008-08-05 15:20:58 -0700182 for p := sig.entries.first; p != nil; p = p.next {
183 p.obj.exported = true;
184 }
185
186 return typ;
Robert Griesemer4b0b7d82008-07-29 19:02:49 -0700187}
188
189
Robert Griesemerc7fb27f2008-08-11 09:45:40 -0700190func (P *Parser) DeclareFunc(pos int, ident string, typ *Globals.Type) *Globals.Object {
Robert Griesemer28547612008-08-05 15:20:58 -0700191 // determine scope
192 scope := P.top_scope;
Robert Griesemeraf065a02009-01-06 16:26:45 -0800193 if typ.form == Type.METHOD {
194 // declare in corresponding struct
195 if typ.scope.entries.len < 1 {
Robert Griesemer683ded82008-08-11 21:20:42 -0700196 panic("no recv in signature?");
Robert Griesemer28547612008-08-05 15:20:58 -0700197 }
198 recv_typ := typ.scope.entries.first.obj.typ;
199 if recv_typ.form == Type.POINTER {
200 recv_typ = recv_typ.elt;
201 }
202 scope = recv_typ.scope;
Robert Griesemer4b0b7d82008-07-29 19:02:49 -0700203 }
Robert Griesemer28547612008-08-05 15:20:58 -0700204
205 // declare the function
206 obj := scope.Lookup(ident);
207 if obj == nil {
Robert Griesemerc7fb27f2008-08-11 09:45:40 -0700208 obj = Globals.NewObject(pos, Object.FUNC, ident);
Robert Griesemer28547612008-08-05 15:20:58 -0700209 obj.typ = typ;
210 // TODO do we need to set the primary type? probably...
211 P.DeclareInScope(scope, obj);
212 return obj;
213 }
214
Robert Griesemer687f3872008-08-05 18:52:37 -0700215 // obj != NULL: possibly a forward declaration
Robert Griesemer28547612008-08-05 15:20:58 -0700216 if obj.kind != Object.FUNC {
Robert Griesemeraf065a02009-01-06 16:26:45 -0800217 P.Error(pos, `"` + ident + `" is declared already`);
Robert Griesemer687f3872008-08-05 18:52:37 -0700218 // continue but do not insert this function into the scope
Robert Griesemer28547612008-08-05 15:20:58 -0700219 obj = Globals.NewObject(-1, Object.FUNC, ident);
220 obj.typ = typ;
221 // TODO do we need to set the primary type? probably...
222 return obj;
223 }
224
Robert Griesemer687f3872008-08-05 18:52:37 -0700225 // we have a function with the same name
226 if !Type.Equal(typ, obj.typ) {
227 P.Error(-1, `type of "` + ident + `" does not match its forward declaration`);
228 // continue but do not insert this function into the scope
229 obj = Globals.NewObject(-1, Object.FUNC, ident);
230 obj.typ = typ;
231 // TODO do we need to set the primary type? probably...
Russ Cox08ca30b2008-12-19 03:05:37 -0800232 return obj;
Robert Griesemer28547612008-08-05 15:20:58 -0700233 }
Robert Griesemer28547612008-08-05 15:20:58 -0700234
235 // We have a matching forward declaration. Use it.
236 return obj;
Robert Griesemer4b0b7d82008-07-29 19:02:49 -0700237}
238
239
Robert Griesemer230230c2008-07-14 18:06:41 -0700240// ----------------------------------------------------------------------------
Robert Griesemer0cee3022008-07-15 10:05:17 -0700241// Common productions
242
Robert Griesemer230230c2008-07-14 18:06:41 -0700243
Robert Griesemera6f87792008-07-15 15:37:14 -0700244func (P *Parser) TryType() *Globals.Type;
Robert Griesemer9761a6d2008-07-31 13:35:30 -0700245func (P *Parser) ParseExpression() Globals.Expr;
Robert Griesemer0cee3022008-07-15 10:05:17 -0700246func (P *Parser) TryStatement() bool;
247func (P *Parser) ParseDeclaration();
Robert Griesemer835cd462008-07-07 17:27:14 -0700248
249
Robert Griesemer58ba20b2008-08-11 20:40:37 -0700250func (P *Parser) ParseIdent(allow_keyword bool) (pos int, ident string) {
Robert Griesemera6f87792008-07-15 15:37:14 -0700251 P.Trace("Ident");
252
Robert Griesemer58ba20b2008-08-11 20:40:37 -0700253 pos, ident = P.pos, "";
254 // NOTE Can make this faster by not doing the keyword lookup in the
255 // scanner if we don't care about keywords.
256 if P.tok == Scanner.IDENT || allow_keyword && P.tok > Scanner.IDENT {
Robert Griesemer5a90ede2008-07-18 17:18:29 -0700257 ident = P.val;
Robert Griesemerc7fb27f2008-08-11 09:45:40 -0700258 if P.verbose {
Robert Griesemera6f87792008-07-15 15:37:14 -0700259 P.PrintIndent();
Robert Griesemer683ded82008-08-11 21:20:42 -0700260 print("Ident = \"", ident, "\"\n");
Robert Griesemera6f87792008-07-15 15:37:14 -0700261 }
262 P.Next();
263 } else {
264 P.Expect(Scanner.IDENT); // use Expect() error handling
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700265 }
Russ Cox08ca30b2008-12-19 03:05:37 -0800266
Robert Griesemera6f87792008-07-15 15:37:14 -0700267 P.Ecart();
Robert Griesemerc7fb27f2008-08-11 09:45:40 -0700268 return pos, ident;
Robert Griesemera6f87792008-07-15 15:37:14 -0700269}
270
271
272func (P *Parser) ParseIdentDecl(kind int) *Globals.Object {
273 P.Trace("IdentDecl");
Russ Cox08ca30b2008-12-19 03:05:37 -0800274
Robert Griesemer58ba20b2008-08-11 20:40:37 -0700275 pos, ident := P.ParseIdent(kind == Object.FIELD);
Robert Griesemerc7fb27f2008-08-11 09:45:40 -0700276 obj := Globals.NewObject(pos, kind, ident);
Robert Griesemera6f87792008-07-15 15:37:14 -0700277 P.Declare(obj);
Russ Cox08ca30b2008-12-19 03:05:37 -0800278
Robert Griesemera6f87792008-07-15 15:37:14 -0700279 P.Ecart();
280 return obj;
281}
282
283
284func (P *Parser) ParseIdentDeclList(kind int) *Globals.List {
285 P.Trace("IdentDeclList");
Russ Cox08ca30b2008-12-19 03:05:37 -0800286
Robert Griesemera6f87792008-07-15 15:37:14 -0700287 list := Globals.NewList();
288 list.AddObj(P.ParseIdentDecl(kind));
289 for P.tok == Scanner.COMMA {
290 P.Next();
291 list.AddObj(P.ParseIdentDecl(kind));
292 }
Russ Cox08ca30b2008-12-19 03:05:37 -0800293
Robert Griesemera6f87792008-07-15 15:37:14 -0700294 P.Ecart();
295 return list;
Robert Griesemer835cd462008-07-07 17:27:14 -0700296}
297
298
299func (P *Parser) ParseIdentList() {
300 P.Trace("IdentList");
Robert Griesemer58ba20b2008-08-11 20:40:37 -0700301 P.ParseIdent(false);
Robert Griesemer835cd462008-07-07 17:27:14 -0700302 for P.tok == Scanner.COMMA {
303 P.Next();
Robert Griesemer58ba20b2008-08-11 20:40:37 -0700304 P.ParseIdent(false);
Robert Griesemer835cd462008-07-07 17:27:14 -0700305 }
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700306 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700307}
308
309
Robert Griesemerf03deb32008-07-24 17:00:58 -0700310func (P *Parser) ParseQualifiedIdent(pos int, ident string) *Globals.Object {
Robert Griesemer835cd462008-07-07 17:27:14 -0700311 P.Trace("QualifiedIdent");
Robert Griesemera6f87792008-07-15 15:37:14 -0700312
Robert Griesemerf03deb32008-07-24 17:00:58 -0700313 if pos < 0 {
Robert Griesemer58ba20b2008-08-11 20:40:37 -0700314 pos, ident = P.ParseIdent(false);
Robert Griesemerf03deb32008-07-24 17:00:58 -0700315 }
Russ Cox08ca30b2008-12-19 03:05:37 -0800316
Robert Griesemeraf065a02009-01-06 16:26:45 -0800317 obj := P.Lookup(ident);
318 if obj == nil {
319 P.Error(pos, `"` + ident + `" is not declared`);
320 obj = Globals.NewObject(pos, Object.BAD, ident);
Robert Griesemer835cd462008-07-07 17:27:14 -0700321 }
Russ Cox08ca30b2008-12-19 03:05:37 -0800322
Robert Griesemeraf065a02009-01-06 16:26:45 -0800323 if obj.kind == Object.PACKAGE && P.tok == Scanner.PERIOD {
324 if obj.pnolev < 0 {
325 panic("obj.pnolev < 0");
326 }
327 pkg := P.comp.pkg_list[obj.pnolev];
328 //if pkg.obj.ident != ident {
329 // panic("pkg.obj.ident != ident");
330 //}
331 P.Next(); // consume "."
332 pos, ident = P.ParseIdent(false);
333 obj = pkg.scope.Lookup(ident);
334 if obj == nil {
335 P.Error(pos, `"` + ident + `" is not declared in package "` + pkg.obj.ident + `"`);
336 obj = Globals.NewObject(pos, Object.BAD, ident);
337 }
338 }
339
340 P.Ecart();
341 return obj;
Robert Griesemer835cd462008-07-07 17:27:14 -0700342}
343
344
Robert Griesemer0cee3022008-07-15 10:05:17 -0700345// ----------------------------------------------------------------------------
346// Types
Robert Griesemer835cd462008-07-07 17:27:14 -0700347
Robert Griesemerfce91182008-07-29 12:03:06 -0700348func (P *Parser) ParseType() *Globals.Type {
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700349 P.Trace("Type");
Russ Cox08ca30b2008-12-19 03:05:37 -0800350
Robert Griesemera6f87792008-07-15 15:37:14 -0700351 typ := P.TryType();
352 if typ == nil {
Robert Griesemer5a90ede2008-07-18 17:18:29 -0700353 P.Error(P.pos, "type expected");
Robert Griesemera6f87792008-07-15 15:37:14 -0700354 typ = Universe.bad_t;
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700355 }
Russ Cox08ca30b2008-12-19 03:05:37 -0800356
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700357 P.Ecart();
Robert Griesemera6f87792008-07-15 15:37:14 -0700358 return typ;
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700359}
360
361
Robert Griesemer9761a6d2008-07-31 13:35:30 -0700362func (P *Parser) ParseVarType() *Globals.Type {
363 P.Trace("VarType");
Russ Cox08ca30b2008-12-19 03:05:37 -0800364
Robert Griesemer9761a6d2008-07-31 13:35:30 -0700365 pos := P.pos;
366 typ := P.ParseType();
Russ Cox08ca30b2008-12-19 03:05:37 -0800367
Robert Griesemeraf065a02009-01-06 16:26:45 -0800368 switch typ.form {
369 case Type.ARRAY:
370 if P.comp.flags.sixg || typ.len >= 0 {
371 break;
Robert Griesemer9761a6d2008-07-31 13:35:30 -0700372 }
Robert Griesemeraf065a02009-01-06 16:26:45 -0800373 // open arrays must be pointers
374 fallthrough;
Russ Cox839a6842009-01-20 14:40:40 -0800375
Robert Griesemeraf065a02009-01-06 16:26:45 -0800376 case Type.MAP, Type.CHANNEL, Type.FUNCTION:
377 P.Error(pos, "must be pointer to this type");
378 typ = Universe.bad_t;
Robert Griesemer9761a6d2008-07-31 13:35:30 -0700379 }
Russ Cox08ca30b2008-12-19 03:05:37 -0800380
Robert Griesemer9761a6d2008-07-31 13:35:30 -0700381 P.Ecart();
382 return typ;
383}
384
385
Robert Griesemera6f87792008-07-15 15:37:14 -0700386func (P *Parser) ParseTypeName() *Globals.Type {
Robert Griesemer0cee3022008-07-15 10:05:17 -0700387 P.Trace("TypeName");
Russ Cox08ca30b2008-12-19 03:05:37 -0800388
Robert Griesemeraf065a02009-01-06 16:26:45 -0800389 pos := P.pos;
390 obj := P.ParseQualifiedIdent(-1, "");
391 typ := obj.typ;
392 if obj.kind != Object.TYPE {
393 P.Error(pos, "qualified identifier does not denote a type");
394 typ = Universe.bad_t;
Robert Griesemera6f87792008-07-15 15:37:14 -0700395 }
Russ Cox08ca30b2008-12-19 03:05:37 -0800396
Robert Griesemeraf065a02009-01-06 16:26:45 -0800397 P.Ecart();
398 return typ;
Robert Griesemer0cee3022008-07-15 10:05:17 -0700399}
400
401
Robert Griesemera6f87792008-07-15 15:37:14 -0700402func (P *Parser) ParseArrayType() *Globals.Type {
Robert Griesemer835cd462008-07-07 17:27:14 -0700403 P.Trace("ArrayType");
Russ Cox08ca30b2008-12-19 03:05:37 -0800404
Robert Griesemer835cd462008-07-07 17:27:14 -0700405 P.Expect(Scanner.LBRACK);
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700406 typ := Globals.NewType(Type.ARRAY);
Robert Griesemer835cd462008-07-07 17:27:14 -0700407 if P.tok != Scanner.RBRACK {
Robert Griesemeraf065a02009-01-06 16:26:45 -0800408 // TODO set typ.len
Robert Griesemer835cd462008-07-07 17:27:14 -0700409 P.ParseExpression();
410 }
411 P.Expect(Scanner.RBRACK);
Robert Griesemer9761a6d2008-07-31 13:35:30 -0700412 typ.elt = P.ParseVarType();
Robert Griesemera456463892008-09-17 13:05:39 -0700413
Russ Cox08ca30b2008-12-19 03:05:37 -0800414 P.Ecart();
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700415 return typ;
Robert Griesemer835cd462008-07-07 17:27:14 -0700416}
417
418
Robert Griesemera6f87792008-07-15 15:37:14 -0700419func (P *Parser) ParseChannelType() *Globals.Type {
Robert Griesemer835cd462008-07-07 17:27:14 -0700420 P.Trace("ChannelType");
Russ Cox08ca30b2008-12-19 03:05:37 -0800421
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700422 typ := Globals.NewType(Type.CHANNEL);
Robert Griesemera456463892008-09-17 13:05:39 -0700423 if P.tok == Scanner.CHAN {
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700424 P.Next();
Robert Griesemera456463892008-09-17 13:05:39 -0700425 if P.tok == Scanner.ARROW {
Robert Griesemeraf065a02009-01-06 16:26:45 -0800426 typ.aux = Type.SEND;
Robert Griesemera456463892008-09-17 13:05:39 -0700427 P.Next();
428 } else {
Robert Griesemeraf065a02009-01-06 16:26:45 -0800429 typ.aux = Type.SEND + Type.RECV;
Robert Griesemera456463892008-09-17 13:05:39 -0700430 }
431 } else {
432 P.Expect(Scanner.ARROW);
433 P.Expect(Scanner.CHAN);
Robert Griesemeraf065a02009-01-06 16:26:45 -0800434 typ.aux = Type.RECV;
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700435 }
Robert Griesemer9761a6d2008-07-31 13:35:30 -0700436 typ.elt = P.ParseVarType();
Robert Griesemera456463892008-09-17 13:05:39 -0700437
Russ Cox08ca30b2008-12-19 03:05:37 -0800438 P.Ecart();
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700439 return typ;
440}
441
442
Robert Griesemer58ba20b2008-08-11 20:40:37 -0700443func (P *Parser) ParseVarDeclList(kind int) {
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700444 P.Trace("VarDeclList");
Russ Cox08ca30b2008-12-19 03:05:37 -0800445
Robert Griesemer58ba20b2008-08-11 20:40:37 -0700446 list := P.ParseIdentDeclList(kind);
Robert Griesemer9761a6d2008-07-31 13:35:30 -0700447 typ := P.ParseVarType();
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700448 for p := list.first; p != nil; p = p.next {
449 p.obj.typ = typ; // TODO should use/have set_type()
450 }
Russ Cox08ca30b2008-12-19 03:05:37 -0800451
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700452 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700453}
454
455
Robert Griesemer835cd462008-07-07 17:27:14 -0700456func (P *Parser) ParseParameterList() {
457 P.Trace("ParameterList");
Russ Cox08ca30b2008-12-19 03:05:37 -0800458
Robert Griesemer58ba20b2008-08-11 20:40:37 -0700459 P.ParseVarDeclList(Object.VAR);
Robert Griesemer835cd462008-07-07 17:27:14 -0700460 for P.tok == Scanner.COMMA {
461 P.Next();
Robert Griesemer58ba20b2008-08-11 20:40:37 -0700462 P.ParseVarDeclList(Object.VAR);
Robert Griesemer835cd462008-07-07 17:27:14 -0700463 }
Russ Cox08ca30b2008-12-19 03:05:37 -0800464
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700465 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700466}
467
468
469func (P *Parser) ParseParameters() {
470 P.Trace("Parameters");
Russ Cox08ca30b2008-12-19 03:05:37 -0800471
Robert Griesemer835cd462008-07-07 17:27:14 -0700472 P.Expect(Scanner.LPAREN);
473 if P.tok != Scanner.RPAREN {
474 P.ParseParameterList();
475 }
476 P.Expect(Scanner.RPAREN);
Russ Cox08ca30b2008-12-19 03:05:37 -0800477
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700478 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700479}
480
481
Robert Griesemeraf065a02009-01-06 16:26:45 -0800482func (P *Parser) ParseResult() {
483 P.Trace("Result");
Russ Cox08ca30b2008-12-19 03:05:37 -0800484
Robert Griesemer835cd462008-07-07 17:27:14 -0700485 if P.tok == Scanner.LPAREN {
Robert Griesemeraf065a02009-01-06 16:26:45 -0800486 // one or more named results
Robert Griesemer835cd462008-07-07 17:27:14 -0700487 // TODO: here we allow empty returns - should proably fix this
488 P.ParseParameters();
Russ Cox08ca30b2008-12-19 03:05:37 -0800489
Robert Griesemeraf065a02009-01-06 16:26:45 -0800490 } else {
491 // anonymous result
492 pos := P.pos;
493 typ := P.TryType();
494 if typ != nil {
495 obj := Globals.NewObject(pos, Object.VAR, ".res");
496 obj.typ = typ;
497 P.Declare(obj);
498 }
499 }
500
501 P.Ecart();
Robert Griesemer1e9adf82008-07-09 10:45:04 -0700502}
503
504
Robert Griesemeraf065a02009-01-06 16:26:45 -0800505// Signatures
Robert Griesemer1e9adf82008-07-09 10:45:04 -0700506//
Robert Griesemeraf065a02009-01-06 16:26:45 -0800507// (params)
508// (params) type
509// (params) (results)
Robert Griesemer1e9adf82008-07-09 10:45:04 -0700510
Robert Griesemeraf065a02009-01-06 16:26:45 -0800511func (P *Parser) ParseSignature() *Globals.Type {
512 P.Trace("Signature");
Russ Cox08ca30b2008-12-19 03:05:37 -0800513
Robert Griesemer230230c2008-07-14 18:06:41 -0700514 P.OpenScope();
Robert Griesemer6dd92ea2008-07-30 21:26:15 -0700515 P.level--;
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700516 sig := P.top_scope;
Russ Cox08ca30b2008-12-19 03:05:37 -0800517
Robert Griesemer1e9adf82008-07-09 10:45:04 -0700518 P.ParseParameters();
Robert Griesemeraf065a02009-01-06 16:26:45 -0800519 r0 := sig.entries.len;
520 P.ParseResult();
Russ Cox08ca30b2008-12-19 03:05:37 -0800521
Robert Griesemer6dd92ea2008-07-30 21:26:15 -0700522 P.level++;
Robert Griesemer230230c2008-07-14 18:06:41 -0700523 P.CloseScope();
Russ Cox08ca30b2008-12-19 03:05:37 -0800524
Robert Griesemer1e9adf82008-07-09 10:45:04 -0700525 P.Ecart();
Robert Griesemeraf065a02009-01-06 16:26:45 -0800526 return MakeFunctionType(sig, 0, r0);
Robert Griesemer835cd462008-07-07 17:27:14 -0700527}
528
529
530// Named signatures
531//
Robert Griesemerc7fb27f2008-08-11 09:45:40 -0700532// ident (params)
533// ident (params) type
534// ident (params) (results)
535// (recv) ident (params)
536// (recv) ident (params) type
537// (recv) ident (params) (results)
Robert Griesemer835cd462008-07-07 17:27:14 -0700538
Robert Griesemerc7fb27f2008-08-11 09:45:40 -0700539func (P *Parser) ParseNamedSignature() (pos int, ident string, typ *Globals.Type) {
Robert Griesemer835cd462008-07-07 17:27:14 -0700540 P.Trace("NamedSignature");
Russ Cox08ca30b2008-12-19 03:05:37 -0800541
Robert Griesemer230230c2008-07-14 18:06:41 -0700542 P.OpenScope();
Robert Griesemer6dd92ea2008-07-30 21:26:15 -0700543 P.level--;
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700544 sig := P.top_scope;
545 p0 := 0;
546
Robert Griesemer835cd462008-07-07 17:27:14 -0700547 if P.tok == Scanner.LPAREN {
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700548 recv_pos := P.pos;
Robert Griesemer835cd462008-07-07 17:27:14 -0700549 P.ParseParameters();
Robert Griesemeraf065a02009-01-06 16:26:45 -0800550 p0 = sig.entries.len;
551 if p0 != 1 {
Robert Griesemer683ded82008-08-11 21:20:42 -0700552 print("p0 = ", p0, "\n");
Robert Griesemer30aa83c2008-09-02 17:26:00 -0700553 P.Error(recv_pos, "must have exactly one receiver");
Robert Griesemer683ded82008-08-11 21:20:42 -0700554 panic("UNIMPLEMENTED (ParseNamedSignature)");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700555 // TODO do something useful here
556 }
Robert Griesemer835cd462008-07-07 17:27:14 -0700557 }
Russ Cox08ca30b2008-12-19 03:05:37 -0800558
Robert Griesemer58ba20b2008-08-11 20:40:37 -0700559 pos, ident = P.ParseIdent(true);
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700560
Robert Griesemer835cd462008-07-07 17:27:14 -0700561 P.ParseParameters();
Russ Cox08ca30b2008-12-19 03:05:37 -0800562
Robert Griesemeraf065a02009-01-06 16:26:45 -0800563 r0 := sig.entries.len;
564 P.ParseResult();
Robert Griesemer6dd92ea2008-07-30 21:26:15 -0700565 P.level++;
Robert Griesemer230230c2008-07-14 18:06:41 -0700566 P.CloseScope();
Russ Cox08ca30b2008-12-19 03:05:37 -0800567
Robert Griesemerfda1d162008-07-23 16:59:06 -0700568 P.Ecart();
Robert Griesemeraf065a02009-01-06 16:26:45 -0800569 return pos, ident, MakeFunctionType(sig, p0, r0);
Robert Griesemer835cd462008-07-07 17:27:14 -0700570}
571
572
Robert Griesemera6f87792008-07-15 15:37:14 -0700573func (P *Parser) ParseFunctionType() *Globals.Type {
Robert Griesemer0cee3022008-07-15 10:05:17 -0700574 P.Trace("FunctionType");
Russ Cox08ca30b2008-12-19 03:05:37 -0800575
Robert Griesemeraf065a02009-01-06 16:26:45 -0800576 typ := P.ParseSignature();
Russ Cox08ca30b2008-12-19 03:05:37 -0800577
Robert Griesemer0cee3022008-07-15 10:05:17 -0700578 P.Ecart();
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700579 return typ;
Robert Griesemer0cee3022008-07-15 10:05:17 -0700580}
581
582
Robert Griesemer0abbb8c2008-08-01 13:33:31 -0700583func (P *Parser) ParseMethodDecl(recv_typ *Globals.Type) {
Robert Griesemer0cee3022008-07-15 10:05:17 -0700584 P.Trace("MethodDecl");
Russ Cox08ca30b2008-12-19 03:05:37 -0800585
Robert Griesemer58ba20b2008-08-11 20:40:37 -0700586 pos, ident := P.ParseIdent(true);
Robert Griesemer4b0b7d82008-07-29 19:02:49 -0700587 P.OpenScope();
Robert Griesemer6dd92ea2008-07-30 21:26:15 -0700588 P.level--;
Robert Griesemer4b0b7d82008-07-29 19:02:49 -0700589 sig := P.top_scope;
Russ Cox08ca30b2008-12-19 03:05:37 -0800590
Robert Griesemer9761a6d2008-07-31 13:35:30 -0700591 // dummy receiver (give it a name so it won't conflict with unnamed result)
Robert Griesemer0abbb8c2008-08-01 13:33:31 -0700592 recv := Globals.NewObject(pos, Object.VAR, ".recv");
593 recv.typ = recv_typ;
594 sig.Insert(recv);
Russ Cox08ca30b2008-12-19 03:05:37 -0800595
Robert Griesemer0cee3022008-07-15 10:05:17 -0700596 P.ParseParameters();
Russ Cox08ca30b2008-12-19 03:05:37 -0800597
Robert Griesemeraf065a02009-01-06 16:26:45 -0800598 r0 := sig.entries.len;
599 P.ParseResult();
Robert Griesemer6dd92ea2008-07-30 21:26:15 -0700600 P.level++;
Robert Griesemer4b0b7d82008-07-29 19:02:49 -0700601 P.CloseScope();
Robert Griesemer0cee3022008-07-15 10:05:17 -0700602 P.Optional(Scanner.SEMICOLON);
Russ Cox08ca30b2008-12-19 03:05:37 -0800603
Robert Griesemer9761a6d2008-07-31 13:35:30 -0700604 obj := Globals.NewObject(pos, Object.FUNC, ident);
Robert Griesemeraf065a02009-01-06 16:26:45 -0800605 obj.typ = MakeFunctionType(sig, 1, r0);
Robert Griesemer9761a6d2008-07-31 13:35:30 -0700606 P.Declare(obj);
Russ Cox08ca30b2008-12-19 03:05:37 -0800607
Robert Griesemer0cee3022008-07-15 10:05:17 -0700608 P.Ecart();
609}
610
611
Robert Griesemera6f87792008-07-15 15:37:14 -0700612func (P *Parser) ParseInterfaceType() *Globals.Type {
Robert Griesemer0cee3022008-07-15 10:05:17 -0700613 P.Trace("InterfaceType");
Russ Cox08ca30b2008-12-19 03:05:37 -0800614
Robert Griesemer0cee3022008-07-15 10:05:17 -0700615 P.Expect(Scanner.INTERFACE);
616 P.Expect(Scanner.LBRACE);
617 P.OpenScope();
Robert Griesemer6dd92ea2008-07-30 21:26:15 -0700618 P.level--;
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700619 typ := Globals.NewType(Type.INTERFACE);
620 typ.scope = P.top_scope;
Robert Griesemer58ba20b2008-08-11 20:40:37 -0700621 for P.tok >= Scanner.IDENT {
Robert Griesemer0abbb8c2008-08-01 13:33:31 -0700622 P.ParseMethodDecl(typ);
Robert Griesemer0cee3022008-07-15 10:05:17 -0700623 }
Robert Griesemer6dd92ea2008-07-30 21:26:15 -0700624 P.level++;
Robert Griesemer0cee3022008-07-15 10:05:17 -0700625 P.CloseScope();
Robert Griesemerf03deb32008-07-24 17:00:58 -0700626 P.Expect(Scanner.RBRACE);
Russ Cox08ca30b2008-12-19 03:05:37 -0800627
Robert Griesemer0cee3022008-07-15 10:05:17 -0700628 P.Ecart();
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700629 return typ;
Robert Griesemer0cee3022008-07-15 10:05:17 -0700630}
631
632
Robert Griesemera6f87792008-07-15 15:37:14 -0700633func (P *Parser) ParseMapType() *Globals.Type {
Robert Griesemer0cee3022008-07-15 10:05:17 -0700634 P.Trace("MapType");
Russ Cox08ca30b2008-12-19 03:05:37 -0800635
Robert Griesemer0cee3022008-07-15 10:05:17 -0700636 P.Expect(Scanner.MAP);
637 P.Expect(Scanner.LBRACK);
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700638 typ := Globals.NewType(Type.MAP);
Robert Griesemeraf065a02009-01-06 16:26:45 -0800639 typ.key = P.ParseVarType();
Robert Griesemer0cee3022008-07-15 10:05:17 -0700640 P.Expect(Scanner.RBRACK);
Robert Griesemer9761a6d2008-07-31 13:35:30 -0700641 typ.elt = P.ParseVarType();
Robert Griesemer0cee3022008-07-15 10:05:17 -0700642 P.Ecart();
Russ Cox08ca30b2008-12-19 03:05:37 -0800643
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700644 return typ;
Robert Griesemer0cee3022008-07-15 10:05:17 -0700645}
646
647
Robert Griesemera6f87792008-07-15 15:37:14 -0700648func (P *Parser) ParseStructType() *Globals.Type {
Robert Griesemer0cee3022008-07-15 10:05:17 -0700649 P.Trace("StructType");
Russ Cox08ca30b2008-12-19 03:05:37 -0800650
Robert Griesemer0cee3022008-07-15 10:05:17 -0700651 P.Expect(Scanner.STRUCT);
652 P.Expect(Scanner.LBRACE);
653 P.OpenScope();
Robert Griesemer6dd92ea2008-07-30 21:26:15 -0700654 P.level--;
Robert Griesemera6f87792008-07-15 15:37:14 -0700655 typ := Globals.NewType(Type.STRUCT);
656 typ.scope = P.top_scope;
Robert Griesemer58ba20b2008-08-11 20:40:37 -0700657 for P.tok >= Scanner.IDENT {
658 P.ParseVarDeclList(Object.FIELD);
Robert Griesemer0cee3022008-07-15 10:05:17 -0700659 if P.tok != Scanner.RBRACE {
660 P.Expect(Scanner.SEMICOLON);
661 }
662 }
663 P.Optional(Scanner.SEMICOLON);
Robert Griesemer6dd92ea2008-07-30 21:26:15 -0700664 P.level++;
Robert Griesemer0cee3022008-07-15 10:05:17 -0700665 P.CloseScope();
666 P.Expect(Scanner.RBRACE);
Russ Cox08ca30b2008-12-19 03:05:37 -0800667
Robert Griesemer0cee3022008-07-15 10:05:17 -0700668 P.Ecart();
Robert Griesemera6f87792008-07-15 15:37:14 -0700669 return typ;
Robert Griesemer0cee3022008-07-15 10:05:17 -0700670}
671
672
Robert Griesemera6f87792008-07-15 15:37:14 -0700673func (P *Parser) ParsePointerType() *Globals.Type {
Robert Griesemer0cee3022008-07-15 10:05:17 -0700674 P.Trace("PointerType");
Russ Cox08ca30b2008-12-19 03:05:37 -0800675
Robert Griesemer0cee3022008-07-15 10:05:17 -0700676 P.Expect(Scanner.MUL);
Robert Griesemerfce91182008-07-29 12:03:06 -0700677 typ := Globals.NewType(Type.POINTER);
Russ Cox08ca30b2008-12-19 03:05:37 -0800678
Robert Griesemerc7fb27f2008-08-11 09:45:40 -0700679 var elt *Globals.Type;
Robert Griesemeraf065a02009-01-06 16:26:45 -0800680 if P.tok == Scanner.STRING && !P.comp.flags.sixg {
681 // implicit package.type forward declaration
682 // TODO eventually the scanner should strip the quotes
683 pkg_name := P.val[1 : len(P.val) - 1]; // strip quotes
684 pkg := P.comp.Lookup(pkg_name);
685 if pkg == nil {
686 // package doesn't exist yet - add it to the package list
687 obj := Globals.NewObject(P.pos, Object.PACKAGE, ".pkg");
688 pkg = Globals.NewPackage(pkg_name, obj, Globals.NewScope(nil));
689 pkg.key = ""; // mark as forward-declared package
690 P.comp.Insert(pkg);
691 } else {
692 // package exists already - must be forward declaration
693 if pkg.key != "" {
694 P.Error(P.pos, `cannot use implicit package forward declaration for imported package "` + P.val + `"`);
695 panic("wrong package forward decl");
696 // TODO introduce dummy package so we can continue safely
Robert Griesemer40c93a52008-08-11 18:44:41 -0700697 }
Robert Griesemeraf065a02009-01-06 16:26:45 -0800698 }
Russ Cox839a6842009-01-20 14:40:40 -0800699
Robert Griesemeraf065a02009-01-06 16:26:45 -0800700 P.Next(); // consume package name
701 P.Expect(Scanner.PERIOD);
702 pos, ident := P.ParseIdent(false);
703 obj := pkg.scope.Lookup(ident);
704 if obj == nil {
705 elt = Globals.NewType(Type.FORWARD);
706 elt.scope = P.top_scope; // not really needed here, but for consistency
707 obj = Globals.NewObject(pos, Object.TYPE, ident);
708 obj.exported = true; // the type name must be visible
709 obj.typ = elt;
710 elt.obj = obj; // primary type object;
711 pkg.scope.Insert(obj);
712 obj.pnolev = pkg.obj.pnolev;
713 } else {
714 if obj.kind != Object.TYPE || obj.typ.form != Type.FORWARD {
715 panic("inconsistency in package.type forward declaration");
716 }
717 elt = obj.typ;
718 }
Russ Cox839a6842009-01-20 14:40:40 -0800719
Robert Griesemeraf065a02009-01-06 16:26:45 -0800720 } else if P.tok == Scanner.IDENT {
721 if P.Lookup(P.val) == nil {
722 // implicit type forward declaration
Russ Cox839a6842009-01-20 14:40:40 -0800723 // create a named forward type
Robert Griesemer58ba20b2008-08-11 20:40:37 -0700724 pos, ident := P.ParseIdent(false);
Robert Griesemeraf065a02009-01-06 16:26:45 -0800725 obj := Globals.NewObject(pos, Object.TYPE, ident);
726 elt = Globals.NewType(Type.FORWARD);
727 obj.typ = elt;
728 elt.obj = obj; // primary type object;
729 // remember the current scope - resolving the forward
730 // type must find a matching declaration in this or a less nested scope
731 elt.scope = P.top_scope;
Russ Cox08ca30b2008-12-19 03:05:37 -0800732
Russ Cox08ca30b2008-12-19 03:05:37 -0800733 // create a named forward type
Russ Cox08ca30b2008-12-19 03:05:37 -0800734
Robert Griesemerfce91182008-07-29 12:03:06 -0700735 } else {
Robert Griesemeraf065a02009-01-06 16:26:45 -0800736 // type name
737 // (ParseType() (via TryType()) checks for forward types and complains,
738 // so call ParseTypeName() directly)
739 // we can only have a foward type here if we refer to the name of a
740 // yet incomplete type (i.e. if we are in the middle of a type's declaration)
741 elt = P.ParseTypeName();
742 }
743
744 // collect uses of pointer types referring to forward types
745 if elt.form == Type.FORWARD {
746 P.forward_types.AddTyp(typ);
Robert Griesemerfce91182008-07-29 12:03:06 -0700747 }
Russ Cox08ca30b2008-12-19 03:05:37 -0800748
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700749 } else {
Robert Griesemerc7fb27f2008-08-11 09:45:40 -0700750 elt = P.ParseType();
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700751 }
752
Robert Griesemeraf065a02009-01-06 16:26:45 -0800753
Robert Griesemerc7fb27f2008-08-11 09:45:40 -0700754 typ.elt = elt;
Russ Cox08ca30b2008-12-19 03:05:37 -0800755
Robert Griesemerfce91182008-07-29 12:03:06 -0700756 P.Ecart();
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700757 return typ;
Robert Griesemer0cee3022008-07-15 10:05:17 -0700758}
759
760
Robert Griesemera6f87792008-07-15 15:37:14 -0700761// Returns nil if no type was found.
762func (P *Parser) TryType() *Globals.Type {
Robert Griesemer0cee3022008-07-15 10:05:17 -0700763 P.Trace("Type (try)");
Russ Cox08ca30b2008-12-19 03:05:37 -0800764
Robert Griesemerfce91182008-07-29 12:03:06 -0700765 pos := P.pos;
Robert Griesemera6f87792008-07-15 15:37:14 -0700766 var typ *Globals.Type = nil;
Robert Griesemer0cee3022008-07-15 10:05:17 -0700767 switch P.tok {
Robert Griesemera6f87792008-07-15 15:37:14 -0700768 case Scanner.IDENT: typ = P.ParseTypeName();
769 case Scanner.LBRACK: typ = P.ParseArrayType();
Robert Griesemera456463892008-09-17 13:05:39 -0700770 case Scanner.CHAN, Scanner.ARROW: typ = P.ParseChannelType();
Robert Griesemera6f87792008-07-15 15:37:14 -0700771 case Scanner.INTERFACE: typ = P.ParseInterfaceType();
Robert Griesemer47809082008-09-08 13:26:52 -0700772 case Scanner.LPAREN: typ = P.ParseFunctionType();
Robert Griesemera6f87792008-07-15 15:37:14 -0700773 case Scanner.MAP: typ = P.ParseMapType();
774 case Scanner.STRUCT: typ = P.ParseStructType();
775 case Scanner.MUL: typ = P.ParsePointerType();
Robert Griesemer0cee3022008-07-15 10:05:17 -0700776 }
Robert Griesemera6f87792008-07-15 15:37:14 -0700777
Robert Griesemerc7fb27f2008-08-11 09:45:40 -0700778 if typ != nil && typ.form == Type.FORWARD {
Robert Griesemerfce91182008-07-29 12:03:06 -0700779 P.Error(pos, "incomplete type");
780 }
781
Robert Griesemer0cee3022008-07-15 10:05:17 -0700782 P.Ecart();
Robert Griesemera6f87792008-07-15 15:37:14 -0700783 return typ;
Robert Griesemer0cee3022008-07-15 10:05:17 -0700784}
785
786
787// ----------------------------------------------------------------------------
788// Blocks
789
790func (P *Parser) ParseStatement() {
791 P.Trace("Statement");
792 if !P.TryStatement() {
Robert Griesemer5a90ede2008-07-18 17:18:29 -0700793 P.Error(P.pos, "statement expected");
Robert Griesemera6f87792008-07-15 15:37:14 -0700794 P.Next(); // make progress
Robert Griesemer0cee3022008-07-15 10:05:17 -0700795 }
796 P.Ecart();
797}
798
799
800func (P *Parser) ParseStatementList() {
801 P.Trace("StatementList");
802 for P.TryStatement() {
803 P.Optional(Scanner.SEMICOLON);
804 }
805 P.Ecart();
806}
807
808
Robert Griesemer4b0b7d82008-07-29 19:02:49 -0700809func (P *Parser) ParseBlock(sig *Globals.Scope) {
Robert Griesemer0cee3022008-07-15 10:05:17 -0700810 P.Trace("Block");
Russ Cox08ca30b2008-12-19 03:05:37 -0800811
Robert Griesemer0cee3022008-07-15 10:05:17 -0700812 P.Expect(Scanner.LBRACE);
813 P.OpenScope();
Robert Griesemer4b0b7d82008-07-29 19:02:49 -0700814 if sig != nil {
815 P.level--;
Robert Griesemer9761a6d2008-07-31 13:35:30 -0700816 // add copies of the formal parameters to the function scope
Robert Griesemer4b0b7d82008-07-29 19:02:49 -0700817 scope := P.top_scope;
818 for p := sig.entries.first; p != nil; p = p.next {
Robert Griesemer9761a6d2008-07-31 13:35:30 -0700819 scope.Insert(p.obj.Copy())
Robert Griesemer4b0b7d82008-07-29 19:02:49 -0700820 }
821 }
Robert Griesemer0cee3022008-07-15 10:05:17 -0700822 if P.tok != Scanner.RBRACE && P.tok != Scanner.SEMICOLON {
823 P.ParseStatementList();
824 }
825 P.Optional(Scanner.SEMICOLON);
Robert Griesemer4b0b7d82008-07-29 19:02:49 -0700826 if sig != nil {
827 P.level++;
828 }
Robert Griesemer0cee3022008-07-15 10:05:17 -0700829 P.CloseScope();
830 P.Expect(Scanner.RBRACE);
Russ Cox08ca30b2008-12-19 03:05:37 -0800831
Robert Griesemer0cee3022008-07-15 10:05:17 -0700832 P.Ecart();
833}
834
835
836// ----------------------------------------------------------------------------
837// Expressions
838
Robert Griesemer333b70b2008-08-06 17:26:46 -0700839func (P *Parser) ParseExpressionList(list *Globals.List) {
Robert Griesemer0cee3022008-07-15 10:05:17 -0700840 P.Trace("ExpressionList");
Russ Cox08ca30b2008-12-19 03:05:37 -0800841
Robert Griesemer687f3872008-08-05 18:52:37 -0700842 list.AddExpr(P.ParseExpression());
Robert Griesemer0cee3022008-07-15 10:05:17 -0700843 for P.tok == Scanner.COMMA {
844 P.Next();
Robert Griesemer687f3872008-08-05 18:52:37 -0700845 list.AddExpr(P.ParseExpression());
Robert Griesemer0cee3022008-07-15 10:05:17 -0700846 }
Russ Cox08ca30b2008-12-19 03:05:37 -0800847
Robert Griesemer0cee3022008-07-15 10:05:17 -0700848 P.Ecart();
Robert Griesemer333b70b2008-08-06 17:26:46 -0700849}
850
851
852func (P *Parser) ParseNewExpressionList() *Globals.List {
853 P.Trace("NewExpressionList");
Russ Cox08ca30b2008-12-19 03:05:37 -0800854
Robert Griesemer333b70b2008-08-06 17:26:46 -0700855 list := Globals.NewList();
856 P.ParseExpressionList(list);
Russ Cox08ca30b2008-12-19 03:05:37 -0800857
Robert Griesemer333b70b2008-08-06 17:26:46 -0700858 P.Ecart();
Robert Griesemercf4c37c2008-07-25 09:35:03 -0700859 return list;
Robert Griesemer0cee3022008-07-15 10:05:17 -0700860}
861
862
Robert Griesemer9761a6d2008-07-31 13:35:30 -0700863func (P *Parser) ParseFunctionLit() Globals.Expr {
Robert Griesemer0cee3022008-07-15 10:05:17 -0700864 P.Trace("FunctionLit");
Russ Cox08ca30b2008-12-19 03:05:37 -0800865
Robert Griesemer47809082008-09-08 13:26:52 -0700866 P.Expect(Scanner.FUNC);
Robert Griesemer4b0b7d82008-07-29 19:02:49 -0700867 typ := P.ParseFunctionType();
868 P.ParseBlock(typ.scope);
Russ Cox08ca30b2008-12-19 03:05:37 -0800869
Robert Griesemer0cee3022008-07-15 10:05:17 -0700870 P.Ecart();
Robert Griesemer9761a6d2008-07-31 13:35:30 -0700871 return nil;
Robert Griesemer0cee3022008-07-15 10:05:17 -0700872}
873
874
Robert Griesemer687f3872008-08-05 18:52:37 -0700875func (P *Parser) ParseExpressionPair(list *Globals.List) {
876 P.Trace("ExpressionPair");
877
878 list.AddExpr(P.ParseExpression());
879 P.Expect(Scanner.COLON);
880 list.AddExpr(P.ParseExpression());
Russ Cox08ca30b2008-12-19 03:05:37 -0800881
Robert Griesemer687f3872008-08-05 18:52:37 -0700882 P.Ecart();
883}
884
885
886func (P *Parser) ParseExpressionPairList(list *Globals.List) {
Robert Griesemerfda1d162008-07-23 16:59:06 -0700887 P.Trace("ExpressionPairList");
888
Robert Griesemer687f3872008-08-05 18:52:37 -0700889 P.ParseExpressionPair(list);
Robert Griesemerfda1d162008-07-23 16:59:06 -0700890 for (P.tok == Scanner.COMMA) {
Robert Griesemer687f3872008-08-05 18:52:37 -0700891 P.ParseExpressionPair(list);
Robert Griesemerfda1d162008-07-23 16:59:06 -0700892 }
Russ Cox08ca30b2008-12-19 03:05:37 -0800893
Robert Griesemerfda1d162008-07-23 16:59:06 -0700894 P.Ecart();
895}
896
897
Robert Griesemer9761a6d2008-07-31 13:35:30 -0700898func (P *Parser) ParseCompositeLit(typ *Globals.Type) Globals.Expr {
Robert Griesemerfda1d162008-07-23 16:59:06 -0700899 P.Trace("CompositeLit");
Russ Cox08ca30b2008-12-19 03:05:37 -0800900
Robert Griesemera456463892008-09-17 13:05:39 -0700901 P.Expect(Scanner.LBRACE);
Robert Griesemerfda1d162008-07-23 16:59:06 -0700902 // TODO: should allow trailing ','
Robert Griesemer687f3872008-08-05 18:52:37 -0700903 list := Globals.NewList();
Robert Griesemera456463892008-09-17 13:05:39 -0700904 if P.tok != Scanner.RBRACE {
Robert Griesemer687f3872008-08-05 18:52:37 -0700905 list.AddExpr(P.ParseExpression());
Robert Griesemerfda1d162008-07-23 16:59:06 -0700906 if P.tok == Scanner.COMMA {
907 P.Next();
Robert Griesemera456463892008-09-17 13:05:39 -0700908 if P.tok != Scanner.RBRACE {
Robert Griesemer333b70b2008-08-06 17:26:46 -0700909 P.ParseExpressionList(list);
Robert Griesemerfda1d162008-07-23 16:59:06 -0700910 }
911 } else if P.tok == Scanner.COLON {
912 P.Next();
Robert Griesemer687f3872008-08-05 18:52:37 -0700913 list.AddExpr(P.ParseExpression());
Robert Griesemerfda1d162008-07-23 16:59:06 -0700914 if P.tok == Scanner.COMMA {
915 P.Next();
Robert Griesemera456463892008-09-17 13:05:39 -0700916 if P.tok != Scanner.RBRACE {
Robert Griesemer687f3872008-08-05 18:52:37 -0700917 P.ParseExpressionPairList(list);
Robert Griesemerfda1d162008-07-23 16:59:06 -0700918 }
919 }
920 }
921 }
Robert Griesemera456463892008-09-17 13:05:39 -0700922 P.Expect(Scanner.RBRACE);
Robert Griesemerfda1d162008-07-23 16:59:06 -0700923
924 P.Ecart();
Robert Griesemer9761a6d2008-07-31 13:35:30 -0700925 return nil;
Robert Griesemerfda1d162008-07-23 16:59:06 -0700926}
927
928
Robert Griesemer9761a6d2008-07-31 13:35:30 -0700929func (P *Parser) ParseOperand(pos int, ident string) Globals.Expr {
Robert Griesemer0cee3022008-07-15 10:05:17 -0700930 P.Trace("Operand");
Robert Griesemerf03deb32008-07-24 17:00:58 -0700931
932 if pos < 0 && P.tok == Scanner.IDENT {
933 // no look-ahead yet
934 pos = P.pos;
935 ident = P.val;
936 P.Next();
937 }
Robert Griesemer687f3872008-08-05 18:52:37 -0700938
939 var res Globals.Expr = AST.Bad;
940
Robert Griesemerf03deb32008-07-24 17:00:58 -0700941 if pos >= 0 {
Robert Griesemeraf065a02009-01-06 16:26:45 -0800942 // we have an identifier
Robert Griesemer683ded82008-08-11 21:20:42 -0700943 obj := P.ParseQualifiedIdent(pos, ident);
Robert Griesemeraf065a02009-01-06 16:26:45 -0800944 if obj.kind == Object.TYPE && P.tok == Scanner.LBRACE {
945 res = P.ParseCompositeLit(obj.typ);
946 } else {
947 res = AST.NewObject(pos, obj);
Robert Griesemerfda1d162008-07-23 16:59:06 -0700948 }
Robert Griesemer687f3872008-08-05 18:52:37 -0700949
950 } else {
Russ Cox08ca30b2008-12-19 03:05:37 -0800951
Robert Griesemer687f3872008-08-05 18:52:37 -0700952 switch P.tok {
953 case Scanner.IDENT:
Robert Griesemer683ded82008-08-11 21:20:42 -0700954 panic("UNREACHABLE");
Russ Cox08ca30b2008-12-19 03:05:37 -0800955
Robert Griesemer687f3872008-08-05 18:52:37 -0700956 case Scanner.LPAREN:
957 P.Next();
958 res = P.ParseExpression();
959 P.Expect(Scanner.RPAREN);
Russ Cox08ca30b2008-12-19 03:05:37 -0800960
Robert Griesemer687f3872008-08-05 18:52:37 -0700961 case Scanner.INT:
Robert Griesemer333b70b2008-08-06 17:26:46 -0700962 x := AST.NewLiteral(P.pos, Universe.int_t);
Robert Griesemer687f3872008-08-05 18:52:37 -0700963 x.i = 42; // TODO set the right value
964 res = x;
965 P.Next();
966
967 case Scanner.FLOAT:
Robert Griesemer333b70b2008-08-06 17:26:46 -0700968 x := AST.NewLiteral(P.pos, Universe.float_t);
Robert Griesemer687f3872008-08-05 18:52:37 -0700969 x.f = 42.0; // TODO set the right value
970 res = x;
971 P.Next();
972
973 case Scanner.STRING:
Robert Griesemer333b70b2008-08-06 17:26:46 -0700974 x := AST.NewLiteral(P.pos, Universe.string_t);
Robert Griesemer687f3872008-08-05 18:52:37 -0700975 x.s = P.val; // TODO need to strip quotes, interpret string properly
976 res = x;
977 P.Next();
978
Robert Griesemer687f3872008-08-05 18:52:37 -0700979 case Scanner.FUNC:
980 res = P.ParseFunctionLit();
Robert Griesemer687f3872008-08-05 18:52:37 -0700981 default:
982 typ := P.TryType();
983 if typ != nil {
984 res = P.ParseCompositeLit(typ);
985 } else {
986 P.Error(P.pos, "operand expected");
987 P.Next(); // make progress
988 }
989 }
Russ Cox08ca30b2008-12-19 03:05:37 -0800990
Robert Griesemer687f3872008-08-05 18:52:37 -0700991 }
992
Robert Griesemer0cee3022008-07-15 10:05:17 -0700993 P.Ecart();
Robert Griesemer687f3872008-08-05 18:52:37 -0700994 return res;
Robert Griesemer0cee3022008-07-15 10:05:17 -0700995}
996
997
Robert Griesemer687f3872008-08-05 18:52:37 -0700998func (P *Parser) ParseSelectorOrTypeAssertion(x Globals.Expr) Globals.Expr {
Robert Griesemer0cee3022008-07-15 10:05:17 -0700999 P.Trace("SelectorOrTypeAssertion");
Robert Griesemer687f3872008-08-05 18:52:37 -07001000
Robert Griesemer0cee3022008-07-15 10:05:17 -07001001 P.Expect(Scanner.PERIOD);
Robert Griesemeraf065a02009-01-06 16:26:45 -08001002 pos := P.pos;
Russ Cox839a6842009-01-20 14:40:40 -08001003
Robert Griesemer58ba20b2008-08-11 20:40:37 -07001004 if P.tok >= Scanner.IDENT {
Robert Griesemeraf065a02009-01-06 16:26:45 -08001005 pos, selector := P.ParseIdent(true);
1006 x = Expr.Select(P.comp, x, pos, selector);
Robert Griesemer0cee3022008-07-15 10:05:17 -07001007 } else {
1008 P.Expect(Scanner.LPAREN);
Robert Griesemeraf065a02009-01-06 16:26:45 -08001009 typ := P.ParseType();
Robert Griesemer0cee3022008-07-15 10:05:17 -07001010 P.Expect(Scanner.RPAREN);
Robert Griesemeraf065a02009-01-06 16:26:45 -08001011 x = Expr.AssertType(P.comp, x, pos, typ);
Robert Griesemer0cee3022008-07-15 10:05:17 -07001012 }
Russ Cox08ca30b2008-12-19 03:05:37 -08001013
Robert Griesemer0cee3022008-07-15 10:05:17 -07001014 P.Ecart();
Robert Griesemer687f3872008-08-05 18:52:37 -07001015 return x;
Robert Griesemer0cee3022008-07-15 10:05:17 -07001016}
1017
1018
Robert Griesemer687f3872008-08-05 18:52:37 -07001019func (P *Parser) ParseIndexOrSlice(x Globals.Expr) Globals.Expr {
Robert Griesemer0cee3022008-07-15 10:05:17 -07001020 P.Trace("IndexOrSlice");
Russ Cox08ca30b2008-12-19 03:05:37 -08001021
Robert Griesemer0cee3022008-07-15 10:05:17 -07001022 P.Expect(Scanner.LBRACK);
Robert Griesemeraf065a02009-01-06 16:26:45 -08001023 i := P.ParseExpression();
Robert Griesemer0cee3022008-07-15 10:05:17 -07001024 if P.tok == Scanner.COLON {
1025 P.Next();
Robert Griesemeraf065a02009-01-06 16:26:45 -08001026 j := P.ParseExpression();
1027 x = Expr.Slice(P.comp, x, i, j);
1028 } else {
1029 x = Expr.Index(P.comp, x, i);
Robert Griesemer0cee3022008-07-15 10:05:17 -07001030 }
1031 P.Expect(Scanner.RBRACK);
Russ Cox08ca30b2008-12-19 03:05:37 -08001032
Robert Griesemer0cee3022008-07-15 10:05:17 -07001033 P.Ecart();
Robert Griesemer687f3872008-08-05 18:52:37 -07001034 return x;
Robert Griesemer0cee3022008-07-15 10:05:17 -07001035}
1036
1037
Robert Griesemer687f3872008-08-05 18:52:37 -07001038func (P *Parser) ParseCall(x Globals.Expr) Globals.Expr {
Robert Griesemerf03deb32008-07-24 17:00:58 -07001039 P.Trace("Call");
Robert Griesemer333b70b2008-08-06 17:26:46 -07001040
Robert Griesemer0cee3022008-07-15 10:05:17 -07001041 P.Expect(Scanner.LPAREN);
Robert Griesemer333b70b2008-08-06 17:26:46 -07001042 args := Globals.NewList();
Robert Griesemer0cee3022008-07-15 10:05:17 -07001043 if P.tok != Scanner.RPAREN {
Robert Griesemer333b70b2008-08-06 17:26:46 -07001044 P.ParseExpressionList(args);
Robert Griesemer0cee3022008-07-15 10:05:17 -07001045 }
1046 P.Expect(Scanner.RPAREN);
Robert Griesemeraf065a02009-01-06 16:26:45 -08001047 x = Expr.Call(P.comp, x, args);
Russ Cox08ca30b2008-12-19 03:05:37 -08001048
Robert Griesemer0cee3022008-07-15 10:05:17 -07001049 P.Ecart();
Robert Griesemer687f3872008-08-05 18:52:37 -07001050 return x;
Robert Griesemer0cee3022008-07-15 10:05:17 -07001051}
1052
1053
Robert Griesemer9761a6d2008-07-31 13:35:30 -07001054func (P *Parser) ParsePrimaryExpr(pos int, ident string) Globals.Expr {
Robert Griesemer0cee3022008-07-15 10:05:17 -07001055 P.Trace("PrimaryExpr");
Russ Cox08ca30b2008-12-19 03:05:37 -08001056
Robert Griesemer687f3872008-08-05 18:52:37 -07001057 x := P.ParseOperand(pos, ident);
Robert Griesemer0cee3022008-07-15 10:05:17 -07001058 for {
1059 switch P.tok {
Robert Griesemer687f3872008-08-05 18:52:37 -07001060 case Scanner.PERIOD: x = P.ParseSelectorOrTypeAssertion(x);
1061 case Scanner.LBRACK: x = P.ParseIndexOrSlice(x);
1062 case Scanner.LPAREN: x = P.ParseCall(x);
1063 default: goto exit;
Robert Griesemer0cee3022008-07-15 10:05:17 -07001064 }
1065 }
Robert Griesemer687f3872008-08-05 18:52:37 -07001066
1067exit:
Robert Griesemer0cee3022008-07-15 10:05:17 -07001068 P.Ecart();
Robert Griesemer687f3872008-08-05 18:52:37 -07001069 return x;
Robert Griesemer0cee3022008-07-15 10:05:17 -07001070}
Robert Griesemer835cd462008-07-07 17:27:14 -07001071
1072
Robert Griesemer333b70b2008-08-06 17:26:46 -07001073// TODO is this function needed?
1074func (P *Parser) ParsePrimaryExprList() *Globals.List {
Robert Griesemer835cd462008-07-07 17:27:14 -07001075 P.Trace("PrimaryExprList");
Robert Griesemer333b70b2008-08-06 17:26:46 -07001076
1077 list := Globals.NewList();
1078 list.AddExpr(P.ParsePrimaryExpr(-1, ""));
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001079 for P.tok == Scanner.COMMA {
1080 P.Next();
Robert Griesemer333b70b2008-08-06 17:26:46 -07001081 list.AddExpr(P.ParsePrimaryExpr(-1, ""));
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001082 }
Russ Cox08ca30b2008-12-19 03:05:37 -08001083
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001084 P.Ecart();
Robert Griesemer333b70b2008-08-06 17:26:46 -07001085 return list;
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001086}
1087
1088
Robert Griesemer9761a6d2008-07-31 13:35:30 -07001089func (P *Parser) ParseUnaryExpr() Globals.Expr {
Robert Griesemer0cee3022008-07-15 10:05:17 -07001090 P.Trace("UnaryExpr");
Russ Cox08ca30b2008-12-19 03:05:37 -08001091
Robert Griesemer0cee3022008-07-15 10:05:17 -07001092 switch P.tok {
1093 case Scanner.ADD: fallthrough;
1094 case Scanner.SUB: fallthrough;
1095 case Scanner.NOT: fallthrough;
1096 case Scanner.XOR: fallthrough;
Robert Griesemer0cee3022008-07-15 10:05:17 -07001097 case Scanner.MUL: fallthrough;
Robert Griesemera456463892008-09-17 13:05:39 -07001098 case Scanner.ARROW: fallthrough;
Robert Griesemer0cee3022008-07-15 10:05:17 -07001099 case Scanner.AND:
1100 P.Next();
Robert Griesemeraf065a02009-01-06 16:26:45 -08001101 x := P.ParseUnaryExpr();
Robert Griesemer0cee3022008-07-15 10:05:17 -07001102 P.Ecart();
Robert Griesemeraf065a02009-01-06 16:26:45 -08001103 return x; // TODO fix this
Robert Griesemer0cee3022008-07-15 10:05:17 -07001104 }
Russ Cox839a6842009-01-20 14:40:40 -08001105
Robert Griesemeraf065a02009-01-06 16:26:45 -08001106 x := P.ParsePrimaryExpr(-1, "");
Russ Cox08ca30b2008-12-19 03:05:37 -08001107
Robert Griesemer0cee3022008-07-15 10:05:17 -07001108 P.Ecart();
Robert Griesemeraf065a02009-01-06 16:26:45 -08001109 return x; // TODO fix this
Robert Griesemer0cee3022008-07-15 10:05:17 -07001110}
1111
1112
1113func Precedence(tok int) int {
1114 // TODO should use a map or array here for lookup
1115 switch tok {
1116 case Scanner.LOR:
1117 return 1;
1118 case Scanner.LAND:
1119 return 2;
Robert Griesemera456463892008-09-17 13:05:39 -07001120 case Scanner.ARROW:
Robert Griesemer0cee3022008-07-15 10:05:17 -07001121 return 3;
Robert Griesemer0e676542008-07-16 17:00:48 -07001122 case Scanner.EQL, Scanner.NEQ, Scanner.LSS, Scanner.LEQ, Scanner.GTR, Scanner.GEQ:
Robert Griesemer0cee3022008-07-15 10:05:17 -07001123 return 4;
Robert Griesemer0e676542008-07-16 17:00:48 -07001124 case Scanner.ADD, Scanner.SUB, Scanner.OR, Scanner.XOR:
Robert Griesemer0cee3022008-07-15 10:05:17 -07001125 return 5;
Robert Griesemer0e676542008-07-16 17:00:48 -07001126 case Scanner.MUL, Scanner.QUO, Scanner.REM, Scanner.SHL, Scanner.SHR, Scanner.AND:
1127 return 6;
Robert Griesemer0cee3022008-07-15 10:05:17 -07001128 }
1129 return 0;
1130}
1131
1132
Robert Griesemer9761a6d2008-07-31 13:35:30 -07001133func (P *Parser) ParseBinaryExpr(pos int, ident string, prec1 int) Globals.Expr {
Robert Griesemer0cee3022008-07-15 10:05:17 -07001134 P.Trace("BinaryExpr");
Russ Cox08ca30b2008-12-19 03:05:37 -08001135
Robert Griesemer9761a6d2008-07-31 13:35:30 -07001136 var x Globals.Expr;
Robert Griesemerf03deb32008-07-24 17:00:58 -07001137 if pos >= 0 {
1138 x = P.ParsePrimaryExpr(pos, ident);
1139 } else {
1140 x = P.ParseUnaryExpr();
1141 }
Robert Griesemeraf065a02009-01-06 16:26:45 -08001142
Robert Griesemer0cee3022008-07-15 10:05:17 -07001143 for prec := Precedence(P.tok); prec >= prec1; prec-- {
1144 for Precedence(P.tok) == prec {
1145 P.Next();
Robert Griesemeraf065a02009-01-06 16:26:45 -08001146 y := P.ParseBinaryExpr(-1, "", prec + 1);
1147 x = Expr.BinaryExpr(P.comp, x, y);
Robert Griesemer0cee3022008-07-15 10:05:17 -07001148 }
1149 }
Russ Cox08ca30b2008-12-19 03:05:37 -08001150
Robert Griesemer0cee3022008-07-15 10:05:17 -07001151 P.Ecart();
Robert Griesemer9761a6d2008-07-31 13:35:30 -07001152 return x;
Robert Griesemer0cee3022008-07-15 10:05:17 -07001153}
1154
1155
Robert Griesemer5fc79192008-07-25 11:27:13 -07001156// Expressions where the first token may be an identifier which has already
1157// been consumed. If the identifier is present, pos is the identifier position,
1158// otherwise pos must be < 0 (and ident is ignored).
Robert Griesemer9761a6d2008-07-31 13:35:30 -07001159func (P *Parser) ParseIdentExpression(pos int, ident string) Globals.Expr {
Robert Griesemerf03deb32008-07-24 17:00:58 -07001160 P.Trace("IdentExpression");
Robert Griesemer0cee3022008-07-15 10:05:17 -07001161 indent := P.indent;
Russ Cox08ca30b2008-12-19 03:05:37 -08001162
Robert Griesemer9761a6d2008-07-31 13:35:30 -07001163 x := P.ParseBinaryExpr(pos, ident, 1);
Russ Cox08ca30b2008-12-19 03:05:37 -08001164
Robert Griesemer0cee3022008-07-15 10:05:17 -07001165 if indent != P.indent {
Robert Griesemer683ded82008-08-11 21:20:42 -07001166 panic("imbalanced tracing code (Expression)");
Robert Griesemer0cee3022008-07-15 10:05:17 -07001167 }
1168 P.Ecart();
Robert Griesemer9761a6d2008-07-31 13:35:30 -07001169 return x;
Robert Griesemer0cee3022008-07-15 10:05:17 -07001170}
1171
1172
Robert Griesemer9761a6d2008-07-31 13:35:30 -07001173func (P *Parser) ParseExpression() Globals.Expr {
1174 P.Trace("Expression");
Russ Cox08ca30b2008-12-19 03:05:37 -08001175
Robert Griesemer9761a6d2008-07-31 13:35:30 -07001176 x := P.ParseIdentExpression(-1, "");
1177
Robert Griesemerf03deb32008-07-24 17:00:58 -07001178 P.Ecart();
Robert Griesemer9761a6d2008-07-31 13:35:30 -07001179 return x;
Robert Griesemerf03deb32008-07-24 17:00:58 -07001180}
1181
1182
Robert Griesemer0cee3022008-07-15 10:05:17 -07001183// ----------------------------------------------------------------------------
1184// Statements
1185
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001186func (P *Parser) ConvertToExprList(pos_list, ident_list, expr_list *Globals.List) {
Robert Griesemeraf065a02009-01-06 16:26:45 -08001187 if pos_list.len != ident_list.len {
1188 panic("inconsistent lists");
1189 }
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001190 for p, q := pos_list.first, ident_list.first; q != nil; p, q = p.next, q.next {
1191 pos, ident := p.val, q.str;
Robert Griesemeraf065a02009-01-06 16:26:45 -08001192 obj := P.Lookup(ident);
1193 if obj == nil {
1194 P.Error(pos, `"` + ident + `" is not declared`);
1195 obj = Globals.NewObject(pos, Object.BAD, ident);
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001196 }
Robert Griesemeraf065a02009-01-06 16:26:45 -08001197 expr_list.AddExpr(AST.NewObject(pos, obj));
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001198 }
Robert Griesemeraf065a02009-01-06 16:26:45 -08001199 pos_list.Clear();
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001200 ident_list.Clear();
1201}
1202
1203
1204func (P *Parser) ParseIdentOrExpr(pos_list, ident_list, expr_list *Globals.List) {
Robert Griesemerf03deb32008-07-24 17:00:58 -07001205 P.Trace("IdentOrExpr");
Russ Cox08ca30b2008-12-19 03:05:37 -08001206
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001207 pos, ident := -1, "";
1208 just_ident := false;
Robert Griesemeraf065a02009-01-06 16:26:45 -08001209 if expr_list.len == 0 /* only idents so far */ && P.tok == Scanner.IDENT {
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001210 pos, ident = P.pos, P.val;
Robert Griesemerf03deb32008-07-24 17:00:58 -07001211 P.Next();
1212 switch P.tok {
1213 case Scanner.COMMA,
1214 Scanner.COLON,
1215 Scanner.DEFINE,
1216 Scanner.ASSIGN,
1217 Scanner.ADD_ASSIGN,
1218 Scanner.SUB_ASSIGN,
1219 Scanner.MUL_ASSIGN,
1220 Scanner.QUO_ASSIGN,
1221 Scanner.REM_ASSIGN,
1222 Scanner.AND_ASSIGN,
1223 Scanner.OR_ASSIGN,
1224 Scanner.XOR_ASSIGN,
1225 Scanner.SHL_ASSIGN,
1226 Scanner.SHR_ASSIGN:
Robert Griesemeraf065a02009-01-06 16:26:45 -08001227 // identifier is *not* part of a more complicated expression
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001228 just_ident = true;
Robert Griesemerf03deb32008-07-24 17:00:58 -07001229 }
Robert Griesemerf03deb32008-07-24 17:00:58 -07001230 }
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001231
1232 if just_ident {
Robert Griesemeraf065a02009-01-06 16:26:45 -08001233 pos_list.AddInt(pos);
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001234 ident_list.AddStr(ident);
1235 } else {
1236 P.ConvertToExprList(pos_list, ident_list, expr_list);
Robert Griesemeraf065a02009-01-06 16:26:45 -08001237 expr_list.AddExpr(P.ParseIdentExpression(pos, ident));
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001238 }
Russ Cox08ca30b2008-12-19 03:05:37 -08001239
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001240 P.Ecart();
Robert Griesemerf03deb32008-07-24 17:00:58 -07001241}
1242
1243
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001244func (P *Parser) ParseIdentOrExprList() (pos_list, ident_list, expr_list *Globals.List) {
1245 P.Trace("IdentOrExprList");
Russ Cox08ca30b2008-12-19 03:05:37 -08001246
Robert Griesemeraf065a02009-01-06 16:26:45 -08001247 pos_list, ident_list = Globals.NewList(), Globals.NewList(); // "pairs" of (pos, ident)
1248 expr_list = Globals.NewList();
Russ Cox839a6842009-01-20 14:40:40 -08001249
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001250 P.ParseIdentOrExpr(pos_list, ident_list, expr_list);
1251 for P.tok == Scanner.COMMA {
1252 P.Next();
1253 P.ParseIdentOrExpr(pos_list, ident_list, expr_list);
Robert Griesemerf03deb32008-07-24 17:00:58 -07001254 }
Russ Cox08ca30b2008-12-19 03:05:37 -08001255
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001256 P.Ecart();
1257 return pos_list, ident_list, expr_list;
Robert Griesemer835cd462008-07-07 17:27:14 -07001258}
1259
1260
Robert Griesemeraf065a02009-01-06 16:26:45 -08001261// Compute the number of individual values provided by the expression list.
1262func (P *Parser) ListArity(list *Globals.List) int {
1263 if list.len == 1 {
1264 x := list.ExprAt(0);
1265 if x.op() == AST.CALL {
1266 panic("UNIMPLEMENTED");
1267 }
1268 return 1;
1269 } else {
1270 for p := list.first; p != nil; p = p.next {
1271 x := p.expr;
1272 if x.op() == AST.CALL {
1273 panic("UNIMPLEMENTED");
1274 }
1275 }
1276 }
1277 panic("UNREACHABLE");
1278}
1279
1280
Robert Griesemer835cd462008-07-07 17:27:14 -07001281func (P *Parser) ParseSimpleStat() {
1282 P.Trace("SimpleStat");
Russ Cox08ca30b2008-12-19 03:05:37 -08001283
Robert Griesemerf03deb32008-07-24 17:00:58 -07001284 // If we see an identifier, we don't know if it's part of a
1285 // label declaration, (multiple) variable declaration, assignment,
1286 // or simply an expression, without looking ahead.
1287 // Strategy: We parse an expression list, but simultaneously, as
1288 // long as possible, maintain a list of identifiers which is converted
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001289 // into an expression list only if neccessary. The result of
Robert Griesemeraf065a02009-01-06 16:26:45 -08001290 // ParseIdentOrExprList is a pair of non-empty lists of identfiers and
1291 // their respective source positions, or a non-empty list of expressions
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001292 // (but not both).
1293 pos_list, ident_list, expr_list := P.ParseIdentOrExprList();
Russ Cox08ca30b2008-12-19 03:05:37 -08001294
Robert Griesemer8e4ee002008-07-08 18:37:31 -07001295 switch P.tok {
Robert Griesemerf03deb32008-07-24 17:00:58 -07001296 case Scanner.COLON:
1297 // label declaration
Robert Griesemeraf065a02009-01-06 16:26:45 -08001298 if ident_list.len == 1 {
1299 obj := Globals.NewObject(pos_list.first.val, Object.LABEL, ident_list.first.str);
1300 P.Declare(obj);
1301 } else {
Robert Griesemerf03deb32008-07-24 17:00:58 -07001302 P.Error(P.pos, "illegal label declaration");
1303 }
Robert Griesemeraf065a02009-01-06 16:26:45 -08001304 P.Next(); // consume ":"
Russ Cox08ca30b2008-12-19 03:05:37 -08001305
Robert Griesemerf03deb32008-07-24 17:00:58 -07001306 case Scanner.DEFINE:
1307 // variable declaration
Robert Griesemeraf065a02009-01-06 16:26:45 -08001308 if ident_list.len == 0 {
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001309 P.Error(P.pos, "illegal left-hand side for declaration");
1310 }
Robert Griesemeraf065a02009-01-06 16:26:45 -08001311 P.Next(); // consume ":="
Robert Griesemer333b70b2008-08-06 17:26:46 -07001312 val_list := P.ParseNewExpressionList();
Robert Griesemeraf065a02009-01-06 16:26:45 -08001313 if val_list.len != ident_list.len {
1314 P.Error(val_list.first.expr.pos(), "number of expressions does not match number of variables");
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001315 }
1316 // declare variables
Robert Griesemeraf065a02009-01-06 16:26:45 -08001317 for p, q := pos_list.first, ident_list.first; q != nil; p, q = p.next, q.next {
1318 obj := Globals.NewObject(p.val, Object.VAR, q.str);
1319 P.Declare(obj);
1320 // TODO set correct types
1321 obj.typ = Universe.bad_t; // for now
Robert Griesemerf03deb32008-07-24 17:00:58 -07001322 }
Russ Cox08ca30b2008-12-19 03:05:37 -08001323
Robert Griesemer8e4ee002008-07-08 18:37:31 -07001324 case Scanner.ASSIGN: fallthrough;
Robert Griesemer8e4ee002008-07-08 18:37:31 -07001325 case Scanner.ADD_ASSIGN: fallthrough;
1326 case Scanner.SUB_ASSIGN: fallthrough;
1327 case Scanner.MUL_ASSIGN: fallthrough;
1328 case Scanner.QUO_ASSIGN: fallthrough;
1329 case Scanner.REM_ASSIGN: fallthrough;
1330 case Scanner.AND_ASSIGN: fallthrough;
1331 case Scanner.OR_ASSIGN: fallthrough;
1332 case Scanner.XOR_ASSIGN: fallthrough;
1333 case Scanner.SHL_ASSIGN: fallthrough;
1334 case Scanner.SHR_ASSIGN:
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001335 P.ConvertToExprList(pos_list, ident_list, expr_list);
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001336 P.Next();
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001337 pos := P.pos;
Robert Griesemer333b70b2008-08-06 17:26:46 -07001338 val_list := P.ParseNewExpressionList();
Russ Cox839a6842009-01-20 14:40:40 -08001339
Robert Griesemeraf065a02009-01-06 16:26:45 -08001340 // assign variables
1341 if val_list.len == 1 && val_list.first.expr.typ().form == Type.TUPLE {
1342 panic("UNIMPLEMENTED");
1343 } else {
1344 var p, q *Globals.Elem;
1345 for p, q = expr_list.first, val_list.first; p != nil && q != nil; p, q = p.next, q.next {
Russ Cox839a6842009-01-20 14:40:40 -08001346
Robert Griesemeraf065a02009-01-06 16:26:45 -08001347 }
1348 if p != nil || q != nil {
1349 P.Error(pos, "number of expressions does not match number of variables");
1350 }
Robert Griesemerf03deb32008-07-24 17:00:58 -07001351 }
Russ Cox08ca30b2008-12-19 03:05:37 -08001352
Robert Griesemerf03deb32008-07-24 17:00:58 -07001353 default:
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001354 P.ConvertToExprList(pos_list, ident_list, expr_list);
Robert Griesemeraf065a02009-01-06 16:26:45 -08001355 if expr_list.len != 1 {
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001356 P.Error(P.pos, "no expression list allowed");
1357 }
1358 if P.tok == Scanner.INC || P.tok == Scanner.DEC {
1359 P.Next();
Robert Griesemerf03deb32008-07-24 17:00:58 -07001360 }
Robert Griesemer835cd462008-07-07 17:27:14 -07001361 }
Russ Cox08ca30b2008-12-19 03:05:37 -08001362
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001363 P.Ecart();
1364}
1365
1366
Robert Griesemer8e4ee002008-07-08 18:37:31 -07001367func (P *Parser) ParseGoStat() {
1368 P.Trace("GoStat");
Russ Cox08ca30b2008-12-19 03:05:37 -08001369
Robert Griesemer8e4ee002008-07-08 18:37:31 -07001370 P.Expect(Scanner.GO);
1371 P.ParseExpression();
Russ Cox08ca30b2008-12-19 03:05:37 -08001372
Robert Griesemer415397e2008-07-09 14:48:26 -07001373 P.Ecart();
Robert Griesemer8e4ee002008-07-08 18:37:31 -07001374}
1375
1376
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001377func (P *Parser) ParseReturnStat() {
1378 P.Trace("ReturnStat");
Russ Cox08ca30b2008-12-19 03:05:37 -08001379
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001380 P.Expect(Scanner.RETURN);
Robert Griesemer333b70b2008-08-06 17:26:46 -07001381 res := Globals.NewList();
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001382 if P.tok != Scanner.SEMICOLON && P.tok != Scanner.RBRACE {
Robert Griesemer333b70b2008-08-06 17:26:46 -07001383 P.ParseExpressionList(res);
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001384 }
Russ Cox08ca30b2008-12-19 03:05:37 -08001385
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001386 P.Ecart();
1387}
1388
1389
Robert Griesemer8e4ee002008-07-08 18:37:31 -07001390func (P *Parser) ParseControlFlowStat(tok int) {
1391 P.Trace("ControlFlowStat");
Russ Cox08ca30b2008-12-19 03:05:37 -08001392
Robert Griesemer8e4ee002008-07-08 18:37:31 -07001393 P.Expect(tok);
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001394 if P.tok == Scanner.IDENT {
Robert Griesemer58ba20b2008-08-11 20:40:37 -07001395 P.ParseIdent(false);
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001396 }
Russ Cox08ca30b2008-12-19 03:05:37 -08001397
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001398 P.Ecart();
1399}
1400
1401
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001402func (P *Parser) ParseIfStat() *AST.IfStat {
Robert Griesemer835cd462008-07-07 17:27:14 -07001403 P.Trace("IfStat");
Russ Cox08ca30b2008-12-19 03:05:37 -08001404
Robert Griesemer835cd462008-07-07 17:27:14 -07001405 P.Expect(Scanner.IF);
Robert Griesemer230230c2008-07-14 18:06:41 -07001406 P.OpenScope();
Robert Griesemer835cd462008-07-07 17:27:14 -07001407 if P.tok != Scanner.LBRACE {
Robert Griesemerae905982008-07-10 20:50:38 -07001408 if P.tok != Scanner.SEMICOLON {
1409 P.ParseSimpleStat();
1410 }
Robert Griesemer835cd462008-07-07 17:27:14 -07001411 if P.tok == Scanner.SEMICOLON {
Robert Griesemer8e4ee002008-07-08 18:37:31 -07001412 P.Next();
Robert Griesemerae905982008-07-10 20:50:38 -07001413 if P.tok != Scanner.LBRACE {
1414 P.ParseExpression();
1415 }
Robert Griesemer835cd462008-07-07 17:27:14 -07001416 }
1417 }
Robert Griesemer4b0b7d82008-07-29 19:02:49 -07001418 P.ParseBlock(nil);
Robert Griesemer835cd462008-07-07 17:27:14 -07001419 if P.tok == Scanner.ELSE {
1420 P.Next();
1421 if P.tok == Scanner.IF {
1422 P.ParseIfStat();
1423 } else {
1424 // TODO should be P.ParseBlock()
Robert Griesemer8e4ee002008-07-08 18:37:31 -07001425 P.ParseStatement();
Robert Griesemer835cd462008-07-07 17:27:14 -07001426 }
1427 }
Robert Griesemer230230c2008-07-14 18:06:41 -07001428 P.CloseScope();
Russ Cox08ca30b2008-12-19 03:05:37 -08001429
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001430 P.Ecart();
Robert Griesemer0ba1db72008-09-11 15:38:22 -07001431 return nil;
Robert Griesemer835cd462008-07-07 17:27:14 -07001432}
1433
1434
1435func (P *Parser) ParseForStat() {
1436 P.Trace("ForStat");
Russ Cox08ca30b2008-12-19 03:05:37 -08001437
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001438 P.Expect(Scanner.FOR);
Robert Griesemer230230c2008-07-14 18:06:41 -07001439 P.OpenScope();
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001440 if P.tok != Scanner.LBRACE {
1441 if P.tok != Scanner.SEMICOLON {
1442 P.ParseSimpleStat();
1443 }
1444 if P.tok == Scanner.SEMICOLON {
1445 P.Next();
1446 if P.tok != Scanner.SEMICOLON {
1447 P.ParseExpression();
1448 }
1449 P.Expect(Scanner.SEMICOLON);
1450 if P.tok != Scanner.LBRACE {
1451 P.ParseSimpleStat();
1452 }
1453 }
1454 }
Robert Griesemer4b0b7d82008-07-29 19:02:49 -07001455 P.ParseBlock(nil);
Robert Griesemer230230c2008-07-14 18:06:41 -07001456 P.CloseScope();
Russ Cox08ca30b2008-12-19 03:05:37 -08001457
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001458 P.Ecart();
1459}
1460
1461
1462func (P *Parser) ParseCase() {
1463 P.Trace("Case");
Russ Cox08ca30b2008-12-19 03:05:37 -08001464
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001465 if P.tok == Scanner.CASE {
1466 P.Next();
Robert Griesemer333b70b2008-08-06 17:26:46 -07001467 list := Globals.NewList();
1468 P.ParseExpressionList(list);
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001469 } else {
1470 P.Expect(Scanner.DEFAULT);
1471 }
1472 P.Expect(Scanner.COLON);
Russ Cox08ca30b2008-12-19 03:05:37 -08001473
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001474 P.Ecart();
1475}
1476
1477
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001478func (P *Parser) ParseCaseClause() {
1479 P.Trace("CaseClause");
Russ Cox08ca30b2008-12-19 03:05:37 -08001480
Robert Griesemer40c93a52008-08-11 18:44:41 -07001481 P.ParseCase();
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001482 if P.tok != Scanner.FALLTHROUGH && P.tok != Scanner.RBRACE {
1483 P.ParseStatementList();
Robert Griesemer8e4ee002008-07-08 18:37:31 -07001484 P.Optional(Scanner.SEMICOLON);
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001485 }
1486 if P.tok == Scanner.FALLTHROUGH {
1487 P.Next();
Robert Griesemer8e4ee002008-07-08 18:37:31 -07001488 P.Optional(Scanner.SEMICOLON);
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001489 }
Russ Cox08ca30b2008-12-19 03:05:37 -08001490
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001491 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -07001492}
1493
1494
1495func (P *Parser) ParseSwitchStat() {
1496 P.Trace("SwitchStat");
Russ Cox08ca30b2008-12-19 03:05:37 -08001497
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001498 P.Expect(Scanner.SWITCH);
Robert Griesemer230230c2008-07-14 18:06:41 -07001499 P.OpenScope();
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001500 if P.tok != Scanner.LBRACE {
Robert Griesemerae905982008-07-10 20:50:38 -07001501 if P.tok != Scanner.SEMICOLON {
1502 P.ParseSimpleStat();
1503 }
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001504 if P.tok == Scanner.SEMICOLON {
Robert Griesemer8e4ee002008-07-08 18:37:31 -07001505 P.Next();
Robert Griesemerae905982008-07-10 20:50:38 -07001506 if P.tok != Scanner.LBRACE {
1507 P.ParseExpression();
1508 }
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001509 }
1510 }
1511 P.Expect(Scanner.LBRACE);
Robert Griesemerf03deb32008-07-24 17:00:58 -07001512 for P.tok == Scanner.CASE || P.tok == Scanner.DEFAULT {
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001513 P.ParseCaseClause();
1514 }
1515 P.Expect(Scanner.RBRACE);
Robert Griesemer230230c2008-07-14 18:06:41 -07001516 P.CloseScope();
Russ Cox08ca30b2008-12-19 03:05:37 -08001517
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001518 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -07001519}
1520
1521
Robert Griesemercab94922008-07-09 14:01:17 -07001522func (P *Parser) ParseCommCase() {
1523 P.Trace("CommCase");
Russ Cox08ca30b2008-12-19 03:05:37 -08001524
Robert Griesemercab94922008-07-09 14:01:17 -07001525 if P.tok == Scanner.CASE {
1526 P.Next();
1527 if P.tok == Scanner.GTR {
1528 // send
1529 P.Next();
1530 P.ParseExpression();
1531 P.Expect(Scanner.EQL);
1532 P.ParseExpression();
1533 } else {
1534 // receive
1535 if P.tok != Scanner.LSS {
Robert Griesemer58ba20b2008-08-11 20:40:37 -07001536 P.ParseIdent(false);
Robert Griesemercab94922008-07-09 14:01:17 -07001537 P.Expect(Scanner.ASSIGN);
1538 }
1539 P.Expect(Scanner.LSS);
1540 P.ParseExpression();
1541 }
1542 } else {
1543 P.Expect(Scanner.DEFAULT);
1544 }
1545 P.Expect(Scanner.COLON);
Russ Cox08ca30b2008-12-19 03:05:37 -08001546
Robert Griesemercab94922008-07-09 14:01:17 -07001547 P.Ecart();
1548}
1549
1550
1551func (P *Parser) ParseCommClause() {
1552 P.Trace("CommClause");
Russ Cox08ca30b2008-12-19 03:05:37 -08001553
Robert Griesemercab94922008-07-09 14:01:17 -07001554 P.ParseCommCase();
1555 if P.tok != Scanner.CASE && P.tok != Scanner.DEFAULT && P.tok != Scanner.RBRACE {
1556 P.ParseStatementList();
1557 P.Optional(Scanner.SEMICOLON);
1558 }
Russ Cox08ca30b2008-12-19 03:05:37 -08001559
Robert Griesemercab94922008-07-09 14:01:17 -07001560 P.Ecart();
1561}
1562
1563
Robert Griesemer0ba1db72008-09-11 15:38:22 -07001564func (P *Parser) ParseRangeStat() {
Robert Griesemercab94922008-07-09 14:01:17 -07001565 P.Trace("RangeStat");
Russ Cox08ca30b2008-12-19 03:05:37 -08001566
Robert Griesemercab94922008-07-09 14:01:17 -07001567 P.Expect(Scanner.RANGE);
1568 P.ParseIdentList();
1569 P.Expect(Scanner.DEFINE);
1570 P.ParseExpression();
Robert Griesemer4b0b7d82008-07-29 19:02:49 -07001571 P.ParseBlock(nil);
Russ Cox08ca30b2008-12-19 03:05:37 -08001572
Robert Griesemercab94922008-07-09 14:01:17 -07001573 P.Ecart();
1574}
1575
1576
Robert Griesemer0ba1db72008-09-11 15:38:22 -07001577func (P *Parser) ParseSelectStat() {
Robert Griesemercab94922008-07-09 14:01:17 -07001578 P.Trace("SelectStat");
Russ Cox08ca30b2008-12-19 03:05:37 -08001579
Robert Griesemercab94922008-07-09 14:01:17 -07001580 P.Expect(Scanner.SELECT);
1581 P.Expect(Scanner.LBRACE);
Robert Griesemerf03deb32008-07-24 17:00:58 -07001582 for P.tok != Scanner.RBRACE && P.tok != Scanner.EOF {
Robert Griesemercab94922008-07-09 14:01:17 -07001583 P.ParseCommClause();
1584 }
1585 P.Next();
Russ Cox08ca30b2008-12-19 03:05:37 -08001586
Robert Griesemercab94922008-07-09 14:01:17 -07001587 P.Ecart();
1588}
1589
1590
Robert Griesemer8e4ee002008-07-08 18:37:31 -07001591func (P *Parser) TryStatement() bool {
1592 P.Trace("Statement (try)");
Robert Griesemer415397e2008-07-09 14:48:26 -07001593 indent := P.indent;
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001594
Robert Griesemer415397e2008-07-09 14:48:26 -07001595 res := true;
Robert Griesemer835cd462008-07-07 17:27:14 -07001596 switch P.tok {
1597 case Scanner.CONST: fallthrough;
1598 case Scanner.TYPE: fallthrough;
Robert Griesemerd9d5f3b2008-07-15 09:22:20 -07001599 case Scanner.VAR:
Robert Griesemer835cd462008-07-07 17:27:14 -07001600 P.ParseDeclaration();
Robert Griesemerd9d5f3b2008-07-15 09:22:20 -07001601 case Scanner.FUNC:
1602 // for now we do not allow local function declarations
1603 fallthrough;
Robert Griesemera456463892008-09-17 13:05:39 -07001604 case Scanner.MUL, Scanner.ARROW, Scanner.IDENT, Scanner.LPAREN:
Robert Griesemerf03deb32008-07-24 17:00:58 -07001605 P.ParseSimpleStat();
Robert Griesemer835cd462008-07-07 17:27:14 -07001606 case Scanner.GO:
Robert Griesemer8e4ee002008-07-08 18:37:31 -07001607 P.ParseGoStat();
Robert Griesemer835cd462008-07-07 17:27:14 -07001608 case Scanner.RETURN:
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001609 P.ParseReturnStat();
Robert Griesemer8e4ee002008-07-08 18:37:31 -07001610 case Scanner.BREAK, Scanner.CONTINUE, Scanner.GOTO:
1611 P.ParseControlFlowStat(P.tok);
Robert Griesemer835cd462008-07-07 17:27:14 -07001612 case Scanner.LBRACE:
Robert Griesemer4b0b7d82008-07-29 19:02:49 -07001613 P.ParseBlock(nil);
Robert Griesemer835cd462008-07-07 17:27:14 -07001614 case Scanner.IF:
1615 P.ParseIfStat();
1616 case Scanner.FOR:
1617 P.ParseForStat();
1618 case Scanner.SWITCH:
1619 P.ParseSwitchStat();
1620 case Scanner.RANGE:
Robert Griesemercab94922008-07-09 14:01:17 -07001621 P.ParseRangeStat();
Robert Griesemer835cd462008-07-07 17:27:14 -07001622 case Scanner.SELECT:
Robert Griesemercab94922008-07-09 14:01:17 -07001623 P.ParseSelectStat();
Robert Griesemer835cd462008-07-07 17:27:14 -07001624 default:
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001625 // no statement found
Robert Griesemer415397e2008-07-09 14:48:26 -07001626 res = false;
1627 }
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001628
Robert Griesemer415397e2008-07-09 14:48:26 -07001629 if indent != P.indent {
Robert Griesemer683ded82008-08-11 21:20:42 -07001630 panic("imbalanced tracing code (Statement)");
Robert Griesemer835cd462008-07-07 17:27:14 -07001631 }
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001632 P.Ecart();
Robert Griesemer415397e2008-07-09 14:48:26 -07001633 return res;
Robert Griesemer835cd462008-07-07 17:27:14 -07001634}
1635
1636
Robert Griesemer0cee3022008-07-15 10:05:17 -07001637// ----------------------------------------------------------------------------
1638// Declarations
1639
1640func (P *Parser) ParseImportSpec() {
1641 P.Trace("ImportSpec");
Russ Cox08ca30b2008-12-19 03:05:37 -08001642
Robert Griesemer4b0b7d82008-07-29 19:02:49 -07001643 var obj *Globals.Object = nil;
Robert Griesemer0cee3022008-07-15 10:05:17 -07001644 if P.tok == Scanner.PERIOD {
Robert Griesemer4b0b7d82008-07-29 19:02:49 -07001645 P.Error(P.pos, `"import ." not yet handled properly`);
Robert Griesemer0cee3022008-07-15 10:05:17 -07001646 P.Next();
1647 } else if P.tok == Scanner.IDENT {
Robert Griesemer4b0b7d82008-07-29 19:02:49 -07001648 obj = P.ParseIdentDecl(Object.PACKAGE);
Robert Griesemer0cee3022008-07-15 10:05:17 -07001649 }
Russ Cox08ca30b2008-12-19 03:05:37 -08001650
Robert Griesemeraf065a02009-01-06 16:26:45 -08001651 if P.tok == Scanner.STRING {
Robert Griesemer4b0b7d82008-07-29 19:02:49 -07001652 // TODO eventually the scanner should strip the quotes
1653 pkg_name := P.val[1 : len(P.val) - 1]; // strip quotes
Robert Griesemerc7fb27f2008-08-11 09:45:40 -07001654 pkg := P.comp.env.Import(P.comp, pkg_name);
Robert Griesemer4b0b7d82008-07-29 19:02:49 -07001655 if pkg != nil {
Robert Griesemer6dd92ea2008-07-30 21:26:15 -07001656 pno := pkg.obj.pnolev; // preserve pno
Robert Griesemer4b0b7d82008-07-29 19:02:49 -07001657 if obj == nil {
1658 // use original package name
1659 obj = pkg.obj;
Robert Griesemer6dd92ea2008-07-30 21:26:15 -07001660 P.Declare(obj); // this changes (pkg.)obj.pnolev!
Robert Griesemer4b0b7d82008-07-29 19:02:49 -07001661 }
Robert Griesemeraf065a02009-01-06 16:26:45 -08001662 obj.pnolev = pno; // reset pno
Robert Griesemer4b0b7d82008-07-29 19:02:49 -07001663 } else {
1664 P.Error(P.pos, `import of "` + pkg_name + `" failed`);
Robert Griesemer0cee3022008-07-15 10:05:17 -07001665 }
1666 P.Next();
1667 } else {
Robert Griesemer4b0b7d82008-07-29 19:02:49 -07001668 P.Expect(Scanner.STRING); // use Expect() error handling
Robert Griesemer835cd462008-07-07 17:27:14 -07001669 }
Russ Cox08ca30b2008-12-19 03:05:37 -08001670
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001671 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -07001672}
1673
1674
Robert Griesemer5fc79192008-07-25 11:27:13 -07001675func (P *Parser) ParseConstSpec(exported bool) {
Robert Griesemer0cee3022008-07-15 10:05:17 -07001676 P.Trace("ConstSpec");
Russ Cox08ca30b2008-12-19 03:05:37 -08001677
Robert Griesemera6f87792008-07-15 15:37:14 -07001678 list := P.ParseIdentDeclList(Object.CONST);
1679 typ := P.TryType();
1680 if typ != nil {
1681 for p := list.first; p != nil; p = p.next {
Robert Griesemerc6eb85a2008-08-01 14:50:18 -07001682 p.obj.typ = typ;
Robert Griesemera6f87792008-07-15 15:37:14 -07001683 }
1684 }
Russ Cox08ca30b2008-12-19 03:05:37 -08001685
Robert Griesemer0cee3022008-07-15 10:05:17 -07001686 if P.tok == Scanner.ASSIGN {
1687 P.Next();
Robert Griesemer333b70b2008-08-06 17:26:46 -07001688 P.ParseNewExpressionList();
Robert Griesemer835cd462008-07-07 17:27:14 -07001689 }
Russ Cox08ca30b2008-12-19 03:05:37 -08001690
Robert Griesemerc6eb85a2008-08-01 14:50:18 -07001691 if exported {
1692 for p := list.first; p != nil; p = p.next {
1693 p.obj.exported = true;
1694 }
1695 }
Russ Cox08ca30b2008-12-19 03:05:37 -08001696
Robert Griesemer0cee3022008-07-15 10:05:17 -07001697 P.Ecart();
1698}
1699
1700
Robert Griesemer5fc79192008-07-25 11:27:13 -07001701func (P *Parser) ParseTypeSpec(exported bool) {
Robert Griesemer0cee3022008-07-15 10:05:17 -07001702 P.Trace("TypeSpec");
Robert Griesemerc7fb27f2008-08-11 09:45:40 -07001703
Robert Griesemer40c93a52008-08-11 18:44:41 -07001704 var typ *Globals.Type;
Russ Cox08ca30b2008-12-19 03:05:37 -08001705
Robert Griesemer58ba20b2008-08-11 20:40:37 -07001706 pos, ident := P.ParseIdent(false);
Robert Griesemer40c93a52008-08-11 18:44:41 -07001707 obj := P.Lookup(ident);
Russ Cox08ca30b2008-12-19 03:05:37 -08001708
Robert Griesemer40c93a52008-08-11 18:44:41 -07001709 if !P.comp.flags.sixg && obj != nil {
1710 if obj.typ.form == Type.FORWARD {
1711 // imported forward-declared type
1712 if !exported {
Robert Griesemer683ded82008-08-11 21:20:42 -07001713 panic("foo");
Robert Griesemer40c93a52008-08-11 18:44:41 -07001714 }
1715 } else {
Robert Griesemer683ded82008-08-11 21:20:42 -07001716 panic("bar");
Robert Griesemer40c93a52008-08-11 18:44:41 -07001717 }
Russ Cox08ca30b2008-12-19 03:05:37 -08001718
Robert Griesemer40c93a52008-08-11 18:44:41 -07001719 } else {
1720 // Immediately after declaration of the type name, the type is
1721 // considered forward-declared. It may be referred to from inside
1722 // the type specification only via a pointer type.
1723 typ = Globals.NewType(Type.FORWARD);
1724 typ.scope = P.top_scope; // not really needed here, but for consistency
1725
1726 obj = Globals.NewObject(pos, Object.TYPE, ident);
1727 obj.exported = exported;
1728 obj.typ = typ;
1729 typ.obj = obj; // primary type object
1730 P.Declare(obj);
1731 }
1732
Robert Griesemer0c374e92008-07-31 10:47:10 -07001733 // If the next token is an identifier and we have a legal program,
1734 // it must be a typename. In that case this declaration introduces
1735 // an alias type.
Robert Griesemerc7fb27f2008-08-11 09:45:40 -07001736 if P.tok == Scanner.IDENT {
1737 typ = Globals.NewType(Type.ALIAS);
1738 elt := P.ParseType(); // we want a complete type - don't shortcut to ParseTypeName()
1739 typ.elt = elt;
1740 if elt.form == Type.ALIAS {
Robert Griesemeraf065a02009-01-06 16:26:45 -08001741 typ.key = elt.key; // the base type
Robert Griesemerc7fb27f2008-08-11 09:45:40 -07001742 } else {
Robert Griesemeraf065a02009-01-06 16:26:45 -08001743 typ.key = elt;
Robert Griesemerc7fb27f2008-08-11 09:45:40 -07001744 }
1745 } else {
1746 typ = P.ParseType();
1747 }
Robert Griesemerfce91182008-07-29 12:03:06 -07001748
Robert Griesemerc7fb27f2008-08-11 09:45:40 -07001749 obj.typ = typ;
1750 if typ.obj == nil {
1751 typ.obj = obj; // primary type object
1752 }
Russ Cox08ca30b2008-12-19 03:05:37 -08001753
Robert Griesemerc7fb27f2008-08-11 09:45:40 -07001754 // if the type is exported, for now we export all fields
1755 // of structs and interfaces by default
1756 // TODO this needs to change eventually
1757 // Actually in 6g even types referred to are exported - sigh...
1758 if exported && (typ.form == Type.STRUCT || typ.form == Type.INTERFACE) {
1759 for p := typ.scope.entries.first; p != nil; p = p.next {
1760 p.obj.exported = true;
Robert Griesemer28547612008-08-05 15:20:58 -07001761 }
Robert Griesemera6f87792008-07-15 15:37:14 -07001762 }
Russ Cox08ca30b2008-12-19 03:05:37 -08001763
Robert Griesemer0cee3022008-07-15 10:05:17 -07001764 P.Ecart();
1765}
1766
1767
Robert Griesemer5fc79192008-07-25 11:27:13 -07001768func (P *Parser) ParseVarSpec(exported bool) {
Robert Griesemer0cee3022008-07-15 10:05:17 -07001769 P.Trace("VarSpec");
Russ Cox08ca30b2008-12-19 03:05:37 -08001770
Robert Griesemera6f87792008-07-15 15:37:14 -07001771 list := P.ParseIdentDeclList(Object.VAR);
Robert Griesemer0cee3022008-07-15 10:05:17 -07001772 if P.tok == Scanner.ASSIGN {
1773 P.Next();
Robert Griesemer333b70b2008-08-06 17:26:46 -07001774 P.ParseNewExpressionList();
Robert Griesemer0cee3022008-07-15 10:05:17 -07001775 } else {
Robert Griesemer9761a6d2008-07-31 13:35:30 -07001776 typ := P.ParseVarType();
Robert Griesemera6f87792008-07-15 15:37:14 -07001777 for p := list.first; p != nil; p = p.next {
Robert Griesemer9761a6d2008-07-31 13:35:30 -07001778 p.obj.typ = typ;
Robert Griesemera6f87792008-07-15 15:37:14 -07001779 }
Robert Griesemer0cee3022008-07-15 10:05:17 -07001780 if P.tok == Scanner.ASSIGN {
1781 P.Next();
Robert Griesemer333b70b2008-08-06 17:26:46 -07001782 P.ParseNewExpressionList();
Robert Griesemer0cee3022008-07-15 10:05:17 -07001783 }
1784 }
Russ Cox08ca30b2008-12-19 03:05:37 -08001785
Robert Griesemerc6eb85a2008-08-01 14:50:18 -07001786 if exported {
1787 for p := list.first; p != nil; p = p.next {
1788 p.obj.exported = true;
1789 }
1790 }
Russ Cox08ca30b2008-12-19 03:05:37 -08001791
Robert Griesemer0cee3022008-07-15 10:05:17 -07001792 P.Ecart();
1793}
1794
1795
Robert Griesemerfce91182008-07-29 12:03:06 -07001796// TODO With method variables, we wouldn't need this dispatch function.
1797func (P *Parser) ParseSpec(exported bool, keyword int) {
1798 switch keyword {
Robert Griesemer4b0b7d82008-07-29 19:02:49 -07001799 case Scanner.IMPORT: P.ParseImportSpec();
Robert Griesemerfce91182008-07-29 12:03:06 -07001800 case Scanner.CONST: P.ParseConstSpec(exported);
1801 case Scanner.TYPE: P.ParseTypeSpec(exported);
1802 case Scanner.VAR: P.ParseVarSpec(exported);
Robert Griesemer683ded82008-08-11 21:20:42 -07001803 default: panic("UNREACHABLE");
Robert Griesemerfce91182008-07-29 12:03:06 -07001804 }
1805}
1806
1807
1808func (P *Parser) ParseDecl(exported bool, keyword int) {
1809 P.Trace("Decl");
Russ Cox08ca30b2008-12-19 03:05:37 -08001810
Robert Griesemerfce91182008-07-29 12:03:06 -07001811 P.Expect(keyword);
Robert Griesemer0cee3022008-07-15 10:05:17 -07001812 if P.tok == Scanner.LPAREN {
1813 P.Next();
Robert Griesemerf03deb32008-07-24 17:00:58 -07001814 for P.tok == Scanner.IDENT {
Robert Griesemerfce91182008-07-29 12:03:06 -07001815 P.ParseSpec(exported, keyword);
Robert Griesemer0cee3022008-07-15 10:05:17 -07001816 if P.tok != Scanner.RPAREN {
Robert Griesemer4b0b7d82008-07-29 19:02:49 -07001817 // P.Expect(Scanner.SEMICOLON);
1818 P.Optional(Scanner.SEMICOLON); // TODO this seems wrong! (needed for math.go)
Robert Griesemer0cee3022008-07-15 10:05:17 -07001819 }
1820 }
1821 P.Next();
1822 } else {
Robert Griesemerfce91182008-07-29 12:03:06 -07001823 P.ParseSpec(exported, keyword);
Robert Griesemer0cee3022008-07-15 10:05:17 -07001824 }
Russ Cox08ca30b2008-12-19 03:05:37 -08001825
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001826 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -07001827}
1828
1829
Robert Griesemer5fc79192008-07-25 11:27:13 -07001830func (P *Parser) ParseFuncDecl(exported bool) {
Robert Griesemer835cd462008-07-07 17:27:14 -07001831 P.Trace("FuncDecl");
Russ Cox08ca30b2008-12-19 03:05:37 -08001832
Robert Griesemer835cd462008-07-07 17:27:14 -07001833 P.Expect(Scanner.FUNC);
Robert Griesemerc7fb27f2008-08-11 09:45:40 -07001834 pos, ident, typ := P.ParseNamedSignature();
1835 obj := P.DeclareFunc(pos, ident, typ); // need obj later for statements
Robert Griesemer6acdf3e2008-07-30 13:01:28 -07001836 obj.exported = exported;
Robert Griesemer835cd462008-07-07 17:27:14 -07001837 if P.tok == Scanner.SEMICOLON {
1838 // forward declaration
1839 P.Next();
1840 } else {
Robert Griesemer4b0b7d82008-07-29 19:02:49 -07001841 P.ParseBlock(typ.scope);
Robert Griesemer835cd462008-07-07 17:27:14 -07001842 }
Russ Cox08ca30b2008-12-19 03:05:37 -08001843
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001844 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -07001845}
1846
1847
1848func (P *Parser) ParseExportDecl() {
1849 P.Trace("ExportDecl");
Russ Cox08ca30b2008-12-19 03:05:37 -08001850
Robert Griesemer7a799be2008-08-04 15:37:47 -07001851 // TODO This is deprecated syntax and should go away eventually.
1852 // (Also at the moment the syntax is everything goes...)
Robert Griesemer5fc79192008-07-25 11:27:13 -07001853 //P.Expect(Scanner.EXPORT);
Robert Griesemer7a799be2008-08-04 15:37:47 -07001854
1855 if !P.comp.flags.sixg {
1856 P.Error(P.pos, "deprecated export syntax (use -6g to enable)");
1857 }
Russ Cox08ca30b2008-12-19 03:05:37 -08001858
Robert Griesemerf03deb32008-07-24 17:00:58 -07001859 has_paren := false;
Robert Griesemer33069d392008-07-09 10:16:33 -07001860 if P.tok == Scanner.LPAREN {
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001861 P.Next();
Robert Griesemerf03deb32008-07-24 17:00:58 -07001862 has_paren = true;
1863 }
1864 for P.tok == Scanner.IDENT {
Robert Griesemer58ba20b2008-08-11 20:40:37 -07001865 pos, ident := P.ParseIdent(false);
Robert Griesemerc7fb27f2008-08-11 09:45:40 -07001866 P.exports.AddStr(ident);
Robert Griesemerf03deb32008-07-24 17:00:58 -07001867 P.Optional(Scanner.COMMA); // TODO this seems wrong
1868 }
1869 if has_paren {
1870 P.Expect(Scanner.RPAREN)
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001871 }
Russ Cox08ca30b2008-12-19 03:05:37 -08001872
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001873 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -07001874}
1875
1876
1877func (P *Parser) ParseDeclaration() {
1878 P.Trace("Declaration");
Robert Griesemer415397e2008-07-09 14:48:26 -07001879 indent := P.indent;
Russ Cox08ca30b2008-12-19 03:05:37 -08001880
Robert Griesemer5fc79192008-07-25 11:27:13 -07001881 exported := false;
1882 if P.tok == Scanner.EXPORT {
Robert Griesemer4b0b7d82008-07-29 19:02:49 -07001883 if P.level == 0 {
1884 exported = true;
1885 } else {
1886 P.Error(P.pos, "local declarations cannot be exported");
1887 }
Robert Griesemer5fc79192008-07-25 11:27:13 -07001888 P.Next();
Robert Griesemer5fc79192008-07-25 11:27:13 -07001889 }
Russ Cox08ca30b2008-12-19 03:05:37 -08001890
Robert Griesemer835cd462008-07-07 17:27:14 -07001891 switch P.tok {
Robert Griesemerfce91182008-07-29 12:03:06 -07001892 case Scanner.CONST, Scanner.TYPE, Scanner.VAR:
1893 P.ParseDecl(exported, P.tok);
Robert Griesemer835cd462008-07-07 17:27:14 -07001894 case Scanner.FUNC:
Robert Griesemer5fc79192008-07-25 11:27:13 -07001895 P.ParseFuncDecl(exported);
Robert Griesemer835cd462008-07-07 17:27:14 -07001896 case Scanner.EXPORT:
Robert Griesemer5fc79192008-07-25 11:27:13 -07001897 if exported {
1898 P.Error(P.pos, "cannot mark export declaration for export");
1899 }
1900 P.Next();
Robert Griesemer835cd462008-07-07 17:27:14 -07001901 P.ParseExportDecl();
1902 default:
Robert Griesemer5fc79192008-07-25 11:27:13 -07001903 if exported && (P.tok == Scanner.IDENT || P.tok == Scanner.LPAREN) {
1904 P.ParseExportDecl();
1905 } else {
1906 P.Error(P.pos, "declaration expected");
1907 P.Next(); // make progress
1908 }
Robert Griesemer835cd462008-07-07 17:27:14 -07001909 }
Russ Cox08ca30b2008-12-19 03:05:37 -08001910
Robert Griesemer415397e2008-07-09 14:48:26 -07001911 if indent != P.indent {
Robert Griesemer683ded82008-08-11 21:20:42 -07001912 panic("imbalanced tracing code (Declaration)");
Robert Griesemer415397e2008-07-09 14:48:26 -07001913 }
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001914 P.Ecart();
1915}
1916
1917
Robert Griesemer0cee3022008-07-15 10:05:17 -07001918// ----------------------------------------------------------------------------
1919// Program
Robert Griesemer835cd462008-07-07 17:27:14 -07001920
Robert Griesemerc7fb27f2008-08-11 09:45:40 -07001921func (P *Parser) ResolveForwardTypes() {
Robert Griesemerc7fb27f2008-08-11 09:45:40 -07001922 for p := P.forward_types.first; p != nil; p = p.next {
Robert Griesemerfce91182008-07-29 12:03:06 -07001923 typ := p.typ;
1924 if typ.form != Type.POINTER {
Robert Griesemer683ded82008-08-11 21:20:42 -07001925 panic("unresolved types should be pointers only");
Robert Griesemerfce91182008-07-29 12:03:06 -07001926 }
Russ Cox08ca30b2008-12-19 03:05:37 -08001927
Robert Griesemerc7fb27f2008-08-11 09:45:40 -07001928 elt := typ.elt;
1929 if typ.elt.form != Type.FORWARD {
Robert Griesemer683ded82008-08-11 21:20:42 -07001930 panic("unresolved pointer should point to forward type");
Robert Griesemerfce91182008-07-29 12:03:06 -07001931 }
Russ Cox08ca30b2008-12-19 03:05:37 -08001932
Robert Griesemerc7fb27f2008-08-11 09:45:40 -07001933 obj := elt.obj;
1934 if obj.typ == elt {
1935 // actual forward declaration (as opposed to forward types introduced
1936 // during type declaration) - need to lookup the actual type object
1937 var elt_obj *Globals.Object;
1938 for scope := elt.scope; scope != nil && elt_obj == nil; scope = scope.parent {
1939 elt_obj = scope.Lookup(obj.ident);
1940 }
1941 // update the type object if we found one
1942 if elt_obj != nil {
1943 if elt_obj.kind == Object.TYPE {
1944 obj = elt_obj;
1945 } else {
1946 P.Error(obj.pos, `"` + obj.ident + `" does not denote a type`);
1947 }
1948 }
1949 }
1950
1951 // update the pointer type
Robert Griesemerfce91182008-07-29 12:03:06 -07001952 typ.elt = obj.typ;
Russ Cox08ca30b2008-12-19 03:05:37 -08001953
Robert Griesemerc7fb27f2008-08-11 09:45:40 -07001954 // TODO as long as we don't *use* a forward type, we are ok
1955 // => consider not reporting this as an error
1956 // (in a real forward declaration, the corresponding objects are not in a scope
1957 // and have incorrect pnolev)
1958 if typ.elt.form == Type.FORWARD {
1959 P.Error(obj.pos, `"` + obj.ident + `" is not declared after forward declaration`);
Robert Griesemerfce91182008-07-29 12:03:06 -07001960 }
1961 }
1962}
1963
1964
Robert Griesemerc3e9c7d2008-07-17 18:02:10 -07001965func (P *Parser) MarkExports() {
Robert Griesemerc3e9c7d2008-07-17 18:02:10 -07001966 scope := P.top_scope;
1967 for p := P.exports.first; p != nil; p = p.next {
1968 obj := scope.Lookup(p.str);
1969 if obj != nil {
Robert Griesemerfce91182008-07-29 12:03:06 -07001970 obj.exported = true;
Robert Griesemerc3e9c7d2008-07-17 18:02:10 -07001971 // For now we export deep
1972 // TODO this should change eventually - we need selective export
1973 if obj.kind == Object.TYPE {
1974 typ := obj.typ;
1975 if typ.form == Type.STRUCT || typ.form == Type.INTERFACE {
1976 scope := typ.scope;
1977 for p := scope.entries.first; p != nil; p = p.next {
Robert Griesemerfce91182008-07-29 12:03:06 -07001978 p.obj.exported = true;
Robert Griesemerc3e9c7d2008-07-17 18:02:10 -07001979 }
1980 }
1981 }
1982 } else {
1983 // TODO need to report proper src position
Robert Griesemer1f465132008-07-30 17:36:03 -07001984 P.Error(-1, `"` + p.str + `" is not declared - cannot be exported`);
Robert Griesemerc3e9c7d2008-07-17 18:02:10 -07001985 }
1986 }
1987}
1988
1989
Robert Griesemer835cd462008-07-07 17:27:14 -07001990func (P *Parser) ParseProgram() {
1991 P.Trace("Program");
Russ Cox08ca30b2008-12-19 03:05:37 -08001992
Robert Griesemer230230c2008-07-14 18:06:41 -07001993 P.OpenScope();
Robert Griesemer835cd462008-07-07 17:27:14 -07001994 P.Expect(Scanner.PACKAGE);
Robert Griesemer71d50b82008-08-04 10:19:36 -07001995 obj := P.ParseIdentDecl(Object.PACKAGE);
Robert Griesemerafbf7172008-07-10 18:05:00 -07001996 P.Optional(Scanner.SEMICOLON);
Russ Cox08ca30b2008-12-19 03:05:37 -08001997
Robert Griesemer687f3872008-08-05 18:52:37 -07001998 { P.OpenScope();
1999 if P.level != 0 {
Robert Griesemer683ded82008-08-11 21:20:42 -07002000 panic("incorrect scope level");
Robert Griesemer6dd92ea2008-07-30 21:26:15 -07002001 }
Russ Cox08ca30b2008-12-19 03:05:37 -08002002
Robert Griesemeraf065a02009-01-06 16:26:45 -08002003 P.comp.Insert(Globals.NewPackage(P.scanner.filename, obj, P.top_scope));
Robert Griesemer997a9422008-08-04 13:27:05 -07002004 if P.comp.pkg_ref != 1 {
Robert Griesemer683ded82008-08-11 21:20:42 -07002005 panic("should have exactly one package now");
Robert Griesemer997a9422008-08-04 13:27:05 -07002006 }
2007
Robert Griesemeraf065a02009-01-06 16:26:45 -08002008 if P.comp.flags.sixg {
2009 // automatically import package sys
2010 pkg := P.comp.env.Import(P.comp, "sys");
2011 if pkg != nil {
2012 pno := pkg.obj.pnolev; // preserve pno
2013 P.Declare(pkg.obj); // this changes pkg.obj.pnolev!
2014 pkg.obj.pnolev = pno; // reset pno
2015 } else {
2016 P.Error(P.pos, `pre-import of package "sys" failed`);
2017 }
2018 }
Russ Cox839a6842009-01-20 14:40:40 -08002019
Robert Griesemer230230c2008-07-14 18:06:41 -07002020 for P.tok == Scanner.IMPORT {
Robert Griesemer4b0b7d82008-07-29 19:02:49 -07002021 P.ParseDecl(false, Scanner.IMPORT);
Robert Griesemer230230c2008-07-14 18:06:41 -07002022 P.Optional(Scanner.SEMICOLON);
2023 }
Russ Cox08ca30b2008-12-19 03:05:37 -08002024
Robert Griesemer230230c2008-07-14 18:06:41 -07002025 for P.tok != Scanner.EOF {
2026 P.ParseDeclaration();
2027 P.Optional(Scanner.SEMICOLON);
2028 }
Russ Cox08ca30b2008-12-19 03:05:37 -08002029
Robert Griesemerc7fb27f2008-08-11 09:45:40 -07002030 P.ResolveForwardTypes();
Robert Griesemerc3e9c7d2008-07-17 18:02:10 -07002031 P.MarkExports();
Russ Cox08ca30b2008-12-19 03:05:37 -08002032
Robert Griesemer6dd92ea2008-07-30 21:26:15 -07002033 if P.level != 0 {
Robert Griesemer683ded82008-08-11 21:20:42 -07002034 panic("incorrect scope level");
Robert Griesemer6dd92ea2008-07-30 21:26:15 -07002035 }
Robert Griesemer687f3872008-08-05 18:52:37 -07002036 P.CloseScope();
Robert Griesemer835cd462008-07-07 17:27:14 -07002037 }
Russ Cox08ca30b2008-12-19 03:05:37 -08002038
Robert Griesemer230230c2008-07-14 18:06:41 -07002039 P.CloseScope();
Robert Griesemerc40be3b2008-07-08 16:39:04 -07002040 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -07002041}