blob: 023a0d85d09d738af014acf53f14fba5e4c33a6c [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 Griesemer835cd462008-07-07 17:27:14 -070015
16
Robert Griesemer7a799be2008-08-04 15:37:47 -070017export type Parser struct {
Robert Griesemerc3e9c7d2008-07-17 18:02:10 -070018 comp *Globals.Compilation;
Robert Griesemer1f465132008-07-30 17:36:03 -070019 semantic_checks bool;
Robert Griesemerc7fb27f2008-08-11 09:45:40 -070020 verbose bool;
21 indent uint;
Robert Griesemer835cd462008-07-07 17:27:14 -070022 S *Scanner.Scanner;
Robert Griesemer882ac632008-08-06 18:57:37 -070023 C *chan *Scanner.Token;
Robert Griesemer5a90ede2008-07-18 17:18:29 -070024
25 // 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 Griesemer687f3872008-08-05 18:52:37 -070053 P.indent++;
Robert Griesemerc40be3b2008-07-08 16:39:04 -070054}
55
56
57func (P *Parser) Ecart() {
Robert Griesemer687f3872008-08-05 18:52:37 -070058 P.indent--;
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 Griesemer882ac632008-08-06 18:57:37 -070067 if P.C == nil {
68 P.tok, P.pos, P.val = P.S.Scan();
69 } else {
70 t := <- P.C;
71 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 Griesemer882ac632008-08-06 18:57:37 -070080func (P *Parser) Open(comp *Globals.Compilation, S *Scanner.Scanner, C *chan *Scanner.Token) {
Robert Griesemerc3e9c7d2008-07-17 18:02:10 -070081 P.comp = comp;
Robert Griesemerbc13a1a2008-08-07 19:32:22 -070082 P.semantic_checks = comp.flags.ast;
Robert Griesemerc7fb27f2008-08-11 09:45:40 -070083 P.verbose = comp.flags.verbosity > 2;
Robert Griesemerc40be3b2008-07-08 16:39:04 -070084 P.indent = 0;
Robert Griesemer835cd462008-07-07 17:27:14 -070085 P.S = S;
Robert Griesemer882ac632008-08-06 18:57:37 -070086 P.C = C;
Robert Griesemer835cd462008-07-07 17:27:14 -070087 P.Next();
Robert Griesemer4b0b7d82008-07-29 19:02:49 -070088 P.level = 0;
Robert Griesemer230230c2008-07-14 18:06:41 -070089 P.top_scope = Universe.scope;
Robert Griesemerc7fb27f2008-08-11 09:45:40 -070090 P.forward_types = Globals.NewList();
Robert Griesemerc3e9c7d2008-07-17 18:02:10 -070091 P.exports = Globals.NewList();
Robert Griesemer835cd462008-07-07 17:27:14 -070092}
93
94
Robert Griesemer8be580e2008-07-10 14:42:33 -070095func (P *Parser) Error(pos int, msg string) {
96 P.S.Error(pos, msg);
Robert Griesemer835cd462008-07-07 17:27:14 -070097}
98
99
100func (P *Parser) Expect(tok int) {
Robert Griesemera6f87792008-07-15 15:37:14 -0700101 if P.tok != tok {
Robert Griesemer5a90ede2008-07-18 17:18:29 -0700102 P.Error(P.pos, "expected '" + Scanner.TokenName(tok) + "', found '" + Scanner.TokenName(P.tok) + "'");
Robert Griesemer835cd462008-07-07 17:27:14 -0700103 }
Robert Griesemera6f87792008-07-15 15:37:14 -0700104 P.Next(); // make progress in any case
Robert Griesemer835cd462008-07-07 17:27:14 -0700105}
106
107
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700108func (P *Parser) Optional(tok int) {
109 if P.tok == tok {
110 P.Next();
111 }
112}
113
114
Robert Griesemer230230c2008-07-14 18:06:41 -0700115// ----------------------------------------------------------------------------
Robert Griesemera6f87792008-07-15 15:37:14 -0700116// Scopes
Robert Griesemer230230c2008-07-14 18:06:41 -0700117
118func (P *Parser) OpenScope() {
119 P.top_scope = Globals.NewScope(P.top_scope);
120}
121
122
123func (P *Parser) CloseScope() {
124 P.top_scope = P.top_scope.parent;
125}
126
127
128func (P *Parser) Lookup(ident string) *Globals.Object {
129 for scope := P.top_scope; scope != nil; scope = scope.parent {
130 obj := scope.Lookup(ident);
131 if obj != nil {
132 return obj;
133 }
134 }
135 return nil;
136}
137
138
139func (P *Parser) DeclareInScope(scope *Globals.Scope, obj *Globals.Object) {
Robert Griesemer1f465132008-07-30 17:36:03 -0700140 if !P.semantic_checks {
Robert Griesemer4b0b7d82008-07-29 19:02:49 -0700141 return;
142 }
Robert Griesemer687f3872008-08-05 18:52:37 -0700143 if P.level > 0 {
Robert Griesemer683ded82008-08-11 21:20:42 -0700144 panic("cannot declare objects in other packages");
Robert Griesemer687f3872008-08-05 18:52:37 -0700145 }
Robert Griesemer4b0b7d82008-07-29 19:02:49 -0700146 obj.pnolev = P.level;
147 if scope.Lookup(obj.ident) != nil {
Robert Griesemera6f87792008-07-15 15:37:14 -0700148 P.Error(obj.pos, `"` + obj.ident + `" is declared already`);
Robert Griesemer230230c2008-07-14 18:06:41 -0700149 return; // don't insert it into the scope
150 }
151 scope.Insert(obj);
152}
153
154
155func (P *Parser) Declare(obj *Globals.Object) {
156 P.DeclareInScope(P.top_scope, obj);
157}
158
159
Robert Griesemer4b0b7d82008-07-29 19:02:49 -0700160func MakeFunctionType(sig *Globals.Scope, p0, r0 int, check_recv bool) *Globals.Type {
Robert Griesemer28547612008-08-05 15:20:58 -0700161 // Determine if we have a receiver or not.
162 // TODO do we still need this?
163 if p0 > 0 && check_recv {
164 // method
165 if p0 != 1 {
Robert Griesemer683ded82008-08-11 21:20:42 -0700166 panic("p0 != 1");
Robert Griesemer28547612008-08-05 15:20:58 -0700167 }
Robert Griesemer4b0b7d82008-07-29 19:02:49 -0700168 }
Robert Griesemer28547612008-08-05 15:20:58 -0700169
170 typ := Globals.NewType(Type.FUNCTION);
171 if p0 == 0 {
172 typ.flags = 0;
173 } else {
174 typ.flags = Type.RECV;
175 }
176 typ.len_ = r0 - p0;
177 typ.scope = sig;
178
179 // parameters are always exported (they can't be accessed w/o the function
180 // or function type being exported)
181 for p := sig.entries.first; p != nil; p = p.next {
182 p.obj.exported = true;
183 }
184
185 return typ;
Robert Griesemer4b0b7d82008-07-29 19:02:49 -0700186}
187
188
Robert Griesemerc7fb27f2008-08-11 09:45:40 -0700189func (P *Parser) DeclareFunc(pos int, ident string, typ *Globals.Type) *Globals.Object {
Robert Griesemer28547612008-08-05 15:20:58 -0700190 // determine scope
191 scope := P.top_scope;
192 if typ.flags & Type.RECV != 0 {
193 // method - declare in corresponding struct
194 if typ.scope.entries.len_ < 1 {
Robert Griesemer683ded82008-08-11 21:20:42 -0700195 panic("no recv in signature?");
Robert Griesemer28547612008-08-05 15:20:58 -0700196 }
197 recv_typ := typ.scope.entries.first.obj.typ;
198 if recv_typ.form == Type.POINTER {
199 recv_typ = recv_typ.elt;
200 }
201 scope = recv_typ.scope;
Robert Griesemer4b0b7d82008-07-29 19:02:49 -0700202 }
Robert Griesemer28547612008-08-05 15:20:58 -0700203
204 // declare the function
205 obj := scope.Lookup(ident);
206 if obj == nil {
Robert Griesemerc7fb27f2008-08-11 09:45:40 -0700207 obj = Globals.NewObject(pos, Object.FUNC, ident);
Robert Griesemer28547612008-08-05 15:20:58 -0700208 obj.typ = typ;
209 // TODO do we need to set the primary type? probably...
210 P.DeclareInScope(scope, obj);
211 return obj;
212 }
213
Robert Griesemer687f3872008-08-05 18:52:37 -0700214 // obj != NULL: possibly a forward declaration
Robert Griesemer28547612008-08-05 15:20:58 -0700215 if obj.kind != Object.FUNC {
216 P.Error(-1, `"` + ident + `" is declared already`);
Robert Griesemer687f3872008-08-05 18:52:37 -0700217 // continue but do not insert this function into the scope
Robert Griesemer28547612008-08-05 15:20:58 -0700218 obj = Globals.NewObject(-1, Object.FUNC, ident);
219 obj.typ = typ;
220 // TODO do we need to set the primary type? probably...
221 return obj;
222 }
223
Robert Griesemer687f3872008-08-05 18:52:37 -0700224 // we have a function with the same name
225 if !Type.Equal(typ, obj.typ) {
226 P.Error(-1, `type of "` + ident + `" does not match its forward declaration`);
227 // continue but do not insert this function into the scope
228 obj = Globals.NewObject(-1, Object.FUNC, ident);
229 obj.typ = typ;
230 // TODO do we need to set the primary type? probably...
Robert Griesemer28547612008-08-05 15:20:58 -0700231 return obj;
232 }
Robert Griesemer28547612008-08-05 15:20:58 -0700233
234 // We have a matching forward declaration. Use it.
235 return obj;
Robert Griesemer4b0b7d82008-07-29 19:02:49 -0700236}
237
238
Robert Griesemer230230c2008-07-14 18:06:41 -0700239// ----------------------------------------------------------------------------
Robert Griesemer0cee3022008-07-15 10:05:17 -0700240// Common productions
241
Robert Griesemer230230c2008-07-14 18:06:41 -0700242
Robert Griesemera6f87792008-07-15 15:37:14 -0700243func (P *Parser) TryType() *Globals.Type;
Robert Griesemer9761a6d2008-07-31 13:35:30 -0700244func (P *Parser) ParseExpression() Globals.Expr;
Robert Griesemer0cee3022008-07-15 10:05:17 -0700245func (P *Parser) TryStatement() bool;
246func (P *Parser) ParseDeclaration();
Robert Griesemer835cd462008-07-07 17:27:14 -0700247
248
Robert Griesemer58ba20b2008-08-11 20:40:37 -0700249func (P *Parser) ParseIdent(allow_keyword bool) (pos int, ident string) {
Robert Griesemera6f87792008-07-15 15:37:14 -0700250 P.Trace("Ident");
251
Robert Griesemer58ba20b2008-08-11 20:40:37 -0700252 pos, ident = P.pos, "";
253 // NOTE Can make this faster by not doing the keyword lookup in the
254 // scanner if we don't care about keywords.
255 if P.tok == Scanner.IDENT || allow_keyword && P.tok > Scanner.IDENT {
Robert Griesemer5a90ede2008-07-18 17:18:29 -0700256 ident = P.val;
Robert Griesemerc7fb27f2008-08-11 09:45:40 -0700257 if P.verbose {
Robert Griesemera6f87792008-07-15 15:37:14 -0700258 P.PrintIndent();
Robert Griesemer683ded82008-08-11 21:20:42 -0700259 print("Ident = \"", ident, "\"\n");
Robert Griesemera6f87792008-07-15 15:37:14 -0700260 }
261 P.Next();
262 } else {
263 P.Expect(Scanner.IDENT); // use Expect() error handling
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700264 }
Robert Griesemera6f87792008-07-15 15:37:14 -0700265
266 P.Ecart();
Robert Griesemerc7fb27f2008-08-11 09:45:40 -0700267 return pos, ident;
Robert Griesemera6f87792008-07-15 15:37:14 -0700268}
269
270
271func (P *Parser) ParseIdentDecl(kind int) *Globals.Object {
272 P.Trace("IdentDecl");
273
Robert Griesemer58ba20b2008-08-11 20:40:37 -0700274 pos, ident := P.ParseIdent(kind == Object.FIELD);
Robert Griesemerc7fb27f2008-08-11 09:45:40 -0700275 obj := Globals.NewObject(pos, kind, ident);
Robert Griesemera6f87792008-07-15 15:37:14 -0700276 P.Declare(obj);
277
278 P.Ecart();
279 return obj;
280}
281
282
283func (P *Parser) ParseIdentDeclList(kind int) *Globals.List {
284 P.Trace("IdentDeclList");
285
286 list := Globals.NewList();
287 list.AddObj(P.ParseIdentDecl(kind));
288 for P.tok == Scanner.COMMA {
289 P.Next();
290 list.AddObj(P.ParseIdentDecl(kind));
291 }
292
293 P.Ecart();
294 return list;
Robert Griesemer835cd462008-07-07 17:27:14 -0700295}
296
297
298func (P *Parser) ParseIdentList() {
299 P.Trace("IdentList");
Robert Griesemer58ba20b2008-08-11 20:40:37 -0700300 P.ParseIdent(false);
Robert Griesemer835cd462008-07-07 17:27:14 -0700301 for P.tok == Scanner.COMMA {
302 P.Next();
Robert Griesemer58ba20b2008-08-11 20:40:37 -0700303 P.ParseIdent(false);
Robert Griesemer835cd462008-07-07 17:27:14 -0700304 }
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700305 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700306}
307
308
Robert Griesemerf03deb32008-07-24 17:00:58 -0700309func (P *Parser) ParseQualifiedIdent(pos int, ident string) *Globals.Object {
Robert Griesemer835cd462008-07-07 17:27:14 -0700310 P.Trace("QualifiedIdent");
Robert Griesemera6f87792008-07-15 15:37:14 -0700311
Robert Griesemerf03deb32008-07-24 17:00:58 -0700312 if pos < 0 {
Robert Griesemer58ba20b2008-08-11 20:40:37 -0700313 pos, ident = P.ParseIdent(false);
Robert Griesemerf03deb32008-07-24 17:00:58 -0700314 }
315
Robert Griesemer1f465132008-07-30 17:36:03 -0700316 if P.semantic_checks {
Robert Griesemera6f87792008-07-15 15:37:14 -0700317 obj := P.Lookup(ident);
318 if obj == nil {
319 P.Error(pos, `"` + ident + `" is not declared`);
320 obj = Globals.NewObject(pos, Object.BAD, ident);
321 }
322
323 if obj.kind == Object.PACKAGE && P.tok == Scanner.PERIOD {
Robert Griesemer4b0b7d82008-07-29 19:02:49 -0700324 if obj.pnolev < 0 {
Robert Griesemer683ded82008-08-11 21:20:42 -0700325 panic("obj.pnolev < 0");
Robert Griesemer4b0b7d82008-07-29 19:02:49 -0700326 }
Robert Griesemer71d50b82008-08-04 10:19:36 -0700327 pkg := P.comp.pkg_list[obj.pnolev];
Robert Griesemer4b0b7d82008-07-29 19:02:49 -0700328 //if pkg.obj.ident != ident {
Robert Griesemer683ded82008-08-11 21:20:42 -0700329 // panic("pkg.obj.ident != ident");
Robert Griesemer4b0b7d82008-07-29 19:02:49 -0700330 //}
331 P.Next(); // consume "."
Robert Griesemer58ba20b2008-08-11 20:40:37 -0700332 pos, ident = P.ParseIdent(false);
Robert Griesemer4b0b7d82008-07-29 19:02:49 -0700333 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 }
Robert Griesemera6f87792008-07-15 15:37:14 -0700338 }
Robert Griesemer4b0b7d82008-07-29 19:02:49 -0700339
Robert Griesemera6f87792008-07-15 15:37:14 -0700340 P.Ecart();
341 return obj;
342
343 } else {
Robert Griesemera6f87792008-07-15 15:37:14 -0700344 if P.tok == Scanner.PERIOD {
345 P.Next();
Robert Griesemer58ba20b2008-08-11 20:40:37 -0700346 P.ParseIdent(false);
Robert Griesemera6f87792008-07-15 15:37:14 -0700347 }
348 P.Ecart();
349 return nil;
Robert Griesemer835cd462008-07-07 17:27:14 -0700350 }
351}
352
353
Robert Griesemer0cee3022008-07-15 10:05:17 -0700354// ----------------------------------------------------------------------------
355// Types
Robert Griesemer835cd462008-07-07 17:27:14 -0700356
Robert Griesemerfce91182008-07-29 12:03:06 -0700357func (P *Parser) ParseType() *Globals.Type {
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700358 P.Trace("Type");
Robert Griesemera6f87792008-07-15 15:37:14 -0700359
360 typ := P.TryType();
361 if typ == nil {
Robert Griesemer5a90ede2008-07-18 17:18:29 -0700362 P.Error(P.pos, "type expected");
Robert Griesemera6f87792008-07-15 15:37:14 -0700363 typ = Universe.bad_t;
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700364 }
Robert Griesemera6f87792008-07-15 15:37:14 -0700365
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700366 P.Ecart();
Robert Griesemera6f87792008-07-15 15:37:14 -0700367 return typ;
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700368}
369
370
Robert Griesemer9761a6d2008-07-31 13:35:30 -0700371func (P *Parser) ParseVarType() *Globals.Type {
372 P.Trace("VarType");
373
374 pos := P.pos;
375 typ := P.ParseType();
376
377 if P.semantic_checks {
378 switch typ.form {
379 case Type.ARRAY:
380 if P.comp.flags.sixg || typ.len_ >= 0 {
381 break;
382 }
383 // open arrays must be pointers
384 fallthrough;
385
386 case Type.MAP, Type.CHANNEL, Type.FUNCTION:
387 P.Error(pos, "must be pointer to this type");
388 typ = Universe.bad_t;
389 }
390 }
391
392 P.Ecart();
393 return typ;
394}
395
396
Robert Griesemera6f87792008-07-15 15:37:14 -0700397func (P *Parser) ParseTypeName() *Globals.Type {
Robert Griesemer0cee3022008-07-15 10:05:17 -0700398 P.Trace("TypeName");
Robert Griesemera6f87792008-07-15 15:37:14 -0700399
Robert Griesemer1f465132008-07-30 17:36:03 -0700400 if P.semantic_checks {
Robert Griesemerfce91182008-07-29 12:03:06 -0700401 pos := P.pos;
Robert Griesemerf03deb32008-07-24 17:00:58 -0700402 obj := P.ParseQualifiedIdent(-1, "");
Robert Griesemera6f87792008-07-15 15:37:14 -0700403 typ := obj.typ;
404 if obj.kind != Object.TYPE {
Robert Griesemerfce91182008-07-29 12:03:06 -0700405 P.Error(pos, "qualified identifier does not denote a type");
Robert Griesemera6f87792008-07-15 15:37:14 -0700406 typ = Universe.bad_t;
407 }
408 P.Ecart();
409 return typ;
410 } else {
Robert Griesemerf03deb32008-07-24 17:00:58 -0700411 P.ParseQualifiedIdent(-1, "");
Robert Griesemera6f87792008-07-15 15:37:14 -0700412 P.Ecart();
413 return Universe.bad_t;
414 }
Robert Griesemer0cee3022008-07-15 10:05:17 -0700415}
416
417
Robert Griesemera6f87792008-07-15 15:37:14 -0700418func (P *Parser) ParseArrayType() *Globals.Type {
Robert Griesemer835cd462008-07-07 17:27:14 -0700419 P.Trace("ArrayType");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700420
Robert Griesemer835cd462008-07-07 17:27:14 -0700421 P.Expect(Scanner.LBRACK);
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700422 typ := Globals.NewType(Type.ARRAY);
Robert Griesemer835cd462008-07-07 17:27:14 -0700423 if P.tok != Scanner.RBRACK {
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700424 // TODO set typ.len_
Robert Griesemer835cd462008-07-07 17:27:14 -0700425 P.ParseExpression();
426 }
427 P.Expect(Scanner.RBRACK);
Robert Griesemer9761a6d2008-07-31 13:35:30 -0700428 typ.elt = P.ParseVarType();
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700429 P.Ecart();
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700430
431 return typ;
Robert Griesemer835cd462008-07-07 17:27:14 -0700432}
433
434
Robert Griesemera6f87792008-07-15 15:37:14 -0700435func (P *Parser) ParseChannelType() *Globals.Type {
Robert Griesemer835cd462008-07-07 17:27:14 -0700436 P.Trace("ChannelType");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700437
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700438 P.Expect(Scanner.CHAN);
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700439 typ := Globals.NewType(Type.CHANNEL);
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700440 switch P.tok {
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700441 case Scanner.SEND:
442 typ.flags = Type.SEND;
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700443 P.Next();
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700444 case Scanner.RECV:
445 typ.flags = Type.RECV;
446 P.Next();
447 default:
448 typ.flags = Type.SEND + Type.RECV;
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700449 }
Robert Griesemer9761a6d2008-07-31 13:35:30 -0700450 typ.elt = P.ParseVarType();
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700451 P.Ecart();
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700452
453 return typ;
454}
455
456
Robert Griesemer58ba20b2008-08-11 20:40:37 -0700457func (P *Parser) ParseVarDeclList(kind int) {
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700458 P.Trace("VarDeclList");
459
Robert Griesemer58ba20b2008-08-11 20:40:37 -0700460 list := P.ParseIdentDeclList(kind);
Robert Griesemer9761a6d2008-07-31 13:35:30 -0700461 typ := P.ParseVarType();
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700462 for p := list.first; p != nil; p = p.next {
463 p.obj.typ = typ; // TODO should use/have set_type()
464 }
465
466 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700467}
468
469
Robert Griesemer835cd462008-07-07 17:27:14 -0700470func (P *Parser) ParseParameterList() {
471 P.Trace("ParameterList");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700472
Robert Griesemer58ba20b2008-08-11 20:40:37 -0700473 P.ParseVarDeclList(Object.VAR);
Robert Griesemer835cd462008-07-07 17:27:14 -0700474 for P.tok == Scanner.COMMA {
475 P.Next();
Robert Griesemer58ba20b2008-08-11 20:40:37 -0700476 P.ParseVarDeclList(Object.VAR);
Robert Griesemer835cd462008-07-07 17:27:14 -0700477 }
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700478
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700479 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700480}
481
482
483func (P *Parser) ParseParameters() {
484 P.Trace("Parameters");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700485
Robert Griesemer835cd462008-07-07 17:27:14 -0700486 P.Expect(Scanner.LPAREN);
487 if P.tok != Scanner.RPAREN {
488 P.ParseParameterList();
489 }
490 P.Expect(Scanner.RPAREN);
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700491
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700492 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700493}
494
495
Robert Griesemer1e9adf82008-07-09 10:45:04 -0700496func (P *Parser) TryResult() bool {
497 P.Trace("Result (try)");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700498
Robert Griesemer1e9adf82008-07-09 10:45:04 -0700499 res := false;
Robert Griesemer835cd462008-07-07 17:27:14 -0700500 if P.tok == Scanner.LPAREN {
501 // TODO: here we allow empty returns - should proably fix this
502 P.ParseParameters();
Robert Griesemer1e9adf82008-07-09 10:45:04 -0700503 res = true;
Robert Griesemer835cd462008-07-07 17:27:14 -0700504 } else {
Robert Griesemera6f87792008-07-15 15:37:14 -0700505 res = P.TryType() != nil;
Robert Griesemer835cd462008-07-07 17:27:14 -0700506 }
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700507 P.Ecart();
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700508
Robert Griesemer1e9adf82008-07-09 10:45:04 -0700509 return res;
510}
511
512
513// Anonymous signatures
514//
515// (params)
516// (params) type
517// (params) (results)
518// (recv) . (params)
519// (recv) . (params) type
520// (recv) . (params) (results)
521
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700522func (P *Parser) ParseAnonymousSignature() *Globals.Type {
Robert Griesemer1e9adf82008-07-09 10:45:04 -0700523 P.Trace("AnonymousSignature");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700524
Robert Griesemer230230c2008-07-14 18:06:41 -0700525 P.OpenScope();
Robert Griesemer6dd92ea2008-07-30 21:26:15 -0700526 P.level--;
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700527 sig := P.top_scope;
528 p0 := 0;
529
530 recv_pos := P.pos;
Robert Griesemer1e9adf82008-07-09 10:45:04 -0700531 P.ParseParameters();
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700532
Robert Griesemer1e9adf82008-07-09 10:45:04 -0700533 if P.tok == Scanner.PERIOD {
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700534 p0 = sig.entries.len_;
Robert Griesemer28547612008-08-05 15:20:58 -0700535 if P.semantic_checks && p0 != 1 {
Robert Griesemer30aa83c2008-09-02 17:26:00 -0700536 P.Error(recv_pos, "must have exactly one receiver");
Robert Griesemer683ded82008-08-11 21:20:42 -0700537 panic("UNIMPLEMENTED (ParseAnonymousSignature)");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700538 // TODO do something useful here
539 }
Robert Griesemer1e9adf82008-07-09 10:45:04 -0700540 P.Next();
541 P.ParseParameters();
542 }
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700543
544 r0 := sig.entries.len_;
Robert Griesemer1e9adf82008-07-09 10:45:04 -0700545 P.TryResult();
Robert Griesemer6dd92ea2008-07-30 21:26:15 -0700546 P.level++;
Robert Griesemer230230c2008-07-14 18:06:41 -0700547 P.CloseScope();
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700548
Robert Griesemer1e9adf82008-07-09 10:45:04 -0700549 P.Ecart();
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700550 return MakeFunctionType(sig, p0, r0, true);
Robert Griesemer835cd462008-07-07 17:27:14 -0700551}
552
553
554// Named signatures
555//
Robert Griesemerc7fb27f2008-08-11 09:45:40 -0700556// ident (params)
557// ident (params) type
558// ident (params) (results)
559// (recv) ident (params)
560// (recv) ident (params) type
561// (recv) ident (params) (results)
Robert Griesemer835cd462008-07-07 17:27:14 -0700562
Robert Griesemerc7fb27f2008-08-11 09:45:40 -0700563func (P *Parser) ParseNamedSignature() (pos int, ident string, typ *Globals.Type) {
Robert Griesemer835cd462008-07-07 17:27:14 -0700564 P.Trace("NamedSignature");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700565
Robert Griesemer230230c2008-07-14 18:06:41 -0700566 P.OpenScope();
Robert Griesemer6dd92ea2008-07-30 21:26:15 -0700567 P.level--;
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700568 sig := P.top_scope;
569 p0 := 0;
570
Robert Griesemer835cd462008-07-07 17:27:14 -0700571 if P.tok == Scanner.LPAREN {
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700572 recv_pos := P.pos;
Robert Griesemer835cd462008-07-07 17:27:14 -0700573 P.ParseParameters();
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700574 p0 = sig.entries.len_;
Robert Griesemer28547612008-08-05 15:20:58 -0700575 if P.semantic_checks && p0 != 1 {
Robert Griesemer683ded82008-08-11 21:20:42 -0700576 print("p0 = ", p0, "\n");
Robert Griesemer30aa83c2008-09-02 17:26:00 -0700577 P.Error(recv_pos, "must have exactly one receiver");
Robert Griesemer683ded82008-08-11 21:20:42 -0700578 panic("UNIMPLEMENTED (ParseNamedSignature)");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700579 // TODO do something useful here
580 }
Robert Griesemer835cd462008-07-07 17:27:14 -0700581 }
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700582
Robert Griesemer58ba20b2008-08-11 20:40:37 -0700583 pos, ident = P.ParseIdent(true);
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700584
Robert Griesemer835cd462008-07-07 17:27:14 -0700585 P.ParseParameters();
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700586
587 r0 := sig.entries.len_;
Robert Griesemer1e9adf82008-07-09 10:45:04 -0700588 P.TryResult();
Robert Griesemer6dd92ea2008-07-30 21:26:15 -0700589 P.level++;
Robert Griesemer230230c2008-07-14 18:06:41 -0700590 P.CloseScope();
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700591
Robert Griesemerfda1d162008-07-23 16:59:06 -0700592 P.Ecart();
Robert Griesemerc7fb27f2008-08-11 09:45:40 -0700593 return pos, ident, MakeFunctionType(sig, p0, r0, true);
Robert Griesemer835cd462008-07-07 17:27:14 -0700594}
595
596
Robert Griesemera6f87792008-07-15 15:37:14 -0700597func (P *Parser) ParseFunctionType() *Globals.Type {
Robert Griesemer0cee3022008-07-15 10:05:17 -0700598 P.Trace("FunctionType");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700599
Robert Griesemer0cee3022008-07-15 10:05:17 -0700600 P.Expect(Scanner.FUNC);
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700601 typ := P.ParseAnonymousSignature();
602
Robert Griesemer0cee3022008-07-15 10:05:17 -0700603 P.Ecart();
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700604 return typ;
Robert Griesemer0cee3022008-07-15 10:05:17 -0700605}
606
607
Robert Griesemer0abbb8c2008-08-01 13:33:31 -0700608func (P *Parser) ParseMethodDecl(recv_typ *Globals.Type) {
Robert Griesemer0cee3022008-07-15 10:05:17 -0700609 P.Trace("MethodDecl");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700610
Robert Griesemer58ba20b2008-08-11 20:40:37 -0700611 pos, ident := P.ParseIdent(true);
Robert Griesemer4b0b7d82008-07-29 19:02:49 -0700612 P.OpenScope();
Robert Griesemer6dd92ea2008-07-30 21:26:15 -0700613 P.level--;
Robert Griesemer4b0b7d82008-07-29 19:02:49 -0700614 sig := P.top_scope;
Robert Griesemer0abbb8c2008-08-01 13:33:31 -0700615
Robert Griesemer9761a6d2008-07-31 13:35:30 -0700616 // dummy receiver (give it a name so it won't conflict with unnamed result)
Robert Griesemer0abbb8c2008-08-01 13:33:31 -0700617 recv := Globals.NewObject(pos, Object.VAR, ".recv");
618 recv.typ = recv_typ;
619 sig.Insert(recv);
620
Robert Griesemer0cee3022008-07-15 10:05:17 -0700621 P.ParseParameters();
Robert Griesemer0abbb8c2008-08-01 13:33:31 -0700622
Robert Griesemer4b0b7d82008-07-29 19:02:49 -0700623 r0 := sig.entries.len_;
Robert Griesemer0cee3022008-07-15 10:05:17 -0700624 P.TryResult();
Robert Griesemer6dd92ea2008-07-30 21:26:15 -0700625 P.level++;
Robert Griesemer4b0b7d82008-07-29 19:02:49 -0700626 P.CloseScope();
Robert Griesemer0cee3022008-07-15 10:05:17 -0700627 P.Optional(Scanner.SEMICOLON);
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700628
Robert Griesemer9761a6d2008-07-31 13:35:30 -0700629 obj := Globals.NewObject(pos, Object.FUNC, ident);
630 obj.typ = MakeFunctionType(sig, 1, r0, true);
631 P.Declare(obj);
632
Robert Griesemer0cee3022008-07-15 10:05:17 -0700633 P.Ecart();
634}
635
636
Robert Griesemera6f87792008-07-15 15:37:14 -0700637func (P *Parser) ParseInterfaceType() *Globals.Type {
Robert Griesemer0cee3022008-07-15 10:05:17 -0700638 P.Trace("InterfaceType");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700639
Robert Griesemer0cee3022008-07-15 10:05:17 -0700640 P.Expect(Scanner.INTERFACE);
641 P.Expect(Scanner.LBRACE);
642 P.OpenScope();
Robert Griesemer6dd92ea2008-07-30 21:26:15 -0700643 P.level--;
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700644 typ := Globals.NewType(Type.INTERFACE);
645 typ.scope = P.top_scope;
Robert Griesemer58ba20b2008-08-11 20:40:37 -0700646 for P.tok >= Scanner.IDENT {
Robert Griesemer0abbb8c2008-08-01 13:33:31 -0700647 P.ParseMethodDecl(typ);
Robert Griesemer0cee3022008-07-15 10:05:17 -0700648 }
Robert Griesemer6dd92ea2008-07-30 21:26:15 -0700649 P.level++;
Robert Griesemer0cee3022008-07-15 10:05:17 -0700650 P.CloseScope();
Robert Griesemerf03deb32008-07-24 17:00:58 -0700651 P.Expect(Scanner.RBRACE);
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700652
Robert Griesemer0cee3022008-07-15 10:05:17 -0700653 P.Ecart();
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700654 return typ;
Robert Griesemer0cee3022008-07-15 10:05:17 -0700655}
656
657
Robert Griesemera6f87792008-07-15 15:37:14 -0700658func (P *Parser) ParseMapType() *Globals.Type {
Robert Griesemer0cee3022008-07-15 10:05:17 -0700659 P.Trace("MapType");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700660
Robert Griesemer0cee3022008-07-15 10:05:17 -0700661 P.Expect(Scanner.MAP);
662 P.Expect(Scanner.LBRACK);
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700663 typ := Globals.NewType(Type.MAP);
Robert Griesemer28547612008-08-05 15:20:58 -0700664 typ.aux = P.ParseVarType();
Robert Griesemer0cee3022008-07-15 10:05:17 -0700665 P.Expect(Scanner.RBRACK);
Robert Griesemer9761a6d2008-07-31 13:35:30 -0700666 typ.elt = P.ParseVarType();
Robert Griesemer0cee3022008-07-15 10:05:17 -0700667 P.Ecart();
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700668
669 return typ;
Robert Griesemer0cee3022008-07-15 10:05:17 -0700670}
671
672
Robert Griesemera6f87792008-07-15 15:37:14 -0700673func (P *Parser) ParseStructType() *Globals.Type {
Robert Griesemer0cee3022008-07-15 10:05:17 -0700674 P.Trace("StructType");
Robert Griesemera6f87792008-07-15 15:37:14 -0700675
Robert Griesemer0cee3022008-07-15 10:05:17 -0700676 P.Expect(Scanner.STRUCT);
677 P.Expect(Scanner.LBRACE);
678 P.OpenScope();
Robert Griesemer6dd92ea2008-07-30 21:26:15 -0700679 P.level--;
Robert Griesemera6f87792008-07-15 15:37:14 -0700680 typ := Globals.NewType(Type.STRUCT);
681 typ.scope = P.top_scope;
Robert Griesemer58ba20b2008-08-11 20:40:37 -0700682 for P.tok >= Scanner.IDENT {
683 P.ParseVarDeclList(Object.FIELD);
Robert Griesemer0cee3022008-07-15 10:05:17 -0700684 if P.tok != Scanner.RBRACE {
685 P.Expect(Scanner.SEMICOLON);
686 }
687 }
688 P.Optional(Scanner.SEMICOLON);
Robert Griesemer6dd92ea2008-07-30 21:26:15 -0700689 P.level++;
Robert Griesemer0cee3022008-07-15 10:05:17 -0700690 P.CloseScope();
691 P.Expect(Scanner.RBRACE);
Robert Griesemera6f87792008-07-15 15:37:14 -0700692
Robert Griesemer0cee3022008-07-15 10:05:17 -0700693 P.Ecart();
Robert Griesemera6f87792008-07-15 15:37:14 -0700694 return typ;
Robert Griesemer0cee3022008-07-15 10:05:17 -0700695}
696
697
Robert Griesemera6f87792008-07-15 15:37:14 -0700698func (P *Parser) ParsePointerType() *Globals.Type {
Robert Griesemer0cee3022008-07-15 10:05:17 -0700699 P.Trace("PointerType");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700700
Robert Griesemer0cee3022008-07-15 10:05:17 -0700701 P.Expect(Scanner.MUL);
Robert Griesemerfce91182008-07-29 12:03:06 -0700702 typ := Globals.NewType(Type.POINTER);
703
Robert Griesemerc7fb27f2008-08-11 09:45:40 -0700704 var elt *Globals.Type;
Robert Griesemer40c93a52008-08-11 18:44:41 -0700705 if P.semantic_checks {
706 if P.tok == Scanner.STRING && !P.comp.flags.sixg {
707 // implicit package.type forward declaration
708 // TODO eventually the scanner should strip the quotes
709 pkg_name := P.val[1 : len(P.val) - 1]; // strip quotes
710 pkg := P.comp.Lookup(pkg_name);
711 if pkg == nil {
712 // package doesn't exist yet - add it to the package list
713 obj := Globals.NewObject(P.pos, Object.PACKAGE, ".pkg");
714 pkg = Globals.NewPackage(pkg_name, obj, Globals.NewScope(nil));
715 pkg.key = ""; // mark as forward-declared package
716 P.comp.Insert(pkg);
717 } else {
718 // package exists already - must be forward declaration
719 if pkg.key != "" {
720 P.Error(P.pos, `cannot use implicit package forward declaration for imported package "` + P.val + `"`);
Robert Griesemer683ded82008-08-11 21:20:42 -0700721 panic("wrong package forward decl");
Robert Griesemer40c93a52008-08-11 18:44:41 -0700722 // TODO introduce dummy package so we can continue safely
723 }
724 }
725
726 P.Next(); // consume package name
727 P.Expect(Scanner.PERIOD);
Robert Griesemer58ba20b2008-08-11 20:40:37 -0700728 pos, ident := P.ParseIdent(false);
Robert Griesemer40c93a52008-08-11 18:44:41 -0700729 obj := pkg.scope.Lookup(ident);
730 if obj == nil {
731 elt = Globals.NewType(Type.FORWARD);
732 elt.scope = P.top_scope; // not really needed here, but for consistency
733 obj = Globals.NewObject(pos, Object.TYPE, ident);
734 obj.exported = true; // the type name must be visible
735 obj.typ = elt;
736 elt.obj = obj; // primary type object;
737 pkg.scope.Insert(obj);
738 obj.pnolev = pkg.obj.pnolev;
739 } else {
740 if obj.kind != Object.TYPE || obj.typ.form != Type.FORWARD {
Robert Griesemer683ded82008-08-11 21:20:42 -0700741 panic("inconsistency in package.type forward declaration");
Robert Griesemer40c93a52008-08-11 18:44:41 -0700742 }
743 elt = obj.typ;
744 }
745
746 } else if P.tok == Scanner.IDENT {
747 if P.Lookup(P.val) == nil {
748 // implicit type forward declaration
749 // create a named forward type
Robert Griesemer58ba20b2008-08-11 20:40:37 -0700750 pos, ident := P.ParseIdent(false);
Robert Griesemer40c93a52008-08-11 18:44:41 -0700751 obj := Globals.NewObject(pos, Object.TYPE, ident);
752 elt = Globals.NewType(Type.FORWARD);
753 obj.typ = elt;
754 elt.obj = obj; // primary type object;
755 // remember the current scope - resolving the forward
756 // type must find a matching declaration in this or a less nested scope
757 elt.scope = P.top_scope;
758
759 } else {
760 // type name
761 // (ParseType() (via TryType()) checks for forward types and complains,
762 // so call ParseTypeName() directly)
763 // we can only have a foward type here if we refer to the name of a
764 // yet incomplete type (i.e. if we are in the middle of a type's declaration)
765 elt = P.ParseTypeName();
766 }
767
768 // collect uses of pointer types referring to forward types
769 if elt.form == Type.FORWARD {
770 P.forward_types.AddTyp(typ);
771 }
Robert Griesemerc7fb27f2008-08-11 09:45:40 -0700772
Robert Griesemerfce91182008-07-29 12:03:06 -0700773 } else {
Robert Griesemer40c93a52008-08-11 18:44:41 -0700774 elt = P.ParseType();
Robert Griesemerfce91182008-07-29 12:03:06 -0700775 }
Robert Griesemer40c93a52008-08-11 18:44:41 -0700776
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700777 } else {
Robert Griesemerc7fb27f2008-08-11 09:45:40 -0700778 elt = P.ParseType();
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700779 }
780
Robert Griesemerc7fb27f2008-08-11 09:45:40 -0700781 typ.elt = elt;
782
Robert Griesemerfce91182008-07-29 12:03:06 -0700783 P.Ecart();
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700784 return typ;
Robert Griesemer0cee3022008-07-15 10:05:17 -0700785}
786
787
Robert Griesemera6f87792008-07-15 15:37:14 -0700788// Returns nil if no type was found.
789func (P *Parser) TryType() *Globals.Type {
Robert Griesemer0cee3022008-07-15 10:05:17 -0700790 P.Trace("Type (try)");
Robert Griesemera6f87792008-07-15 15:37:14 -0700791
Robert Griesemerfce91182008-07-29 12:03:06 -0700792 pos := P.pos;
Robert Griesemera6f87792008-07-15 15:37:14 -0700793 var typ *Globals.Type = nil;
Robert Griesemer0cee3022008-07-15 10:05:17 -0700794 switch P.tok {
Robert Griesemera6f87792008-07-15 15:37:14 -0700795 case Scanner.IDENT: typ = P.ParseTypeName();
796 case Scanner.LBRACK: typ = P.ParseArrayType();
797 case Scanner.CHAN: typ = P.ParseChannelType();
798 case Scanner.INTERFACE: typ = P.ParseInterfaceType();
799 case Scanner.FUNC: typ = P.ParseFunctionType();
800 case Scanner.MAP: typ = P.ParseMapType();
801 case Scanner.STRUCT: typ = P.ParseStructType();
802 case Scanner.MUL: typ = P.ParsePointerType();
Robert Griesemer0cee3022008-07-15 10:05:17 -0700803 }
Robert Griesemera6f87792008-07-15 15:37:14 -0700804
Robert Griesemerc7fb27f2008-08-11 09:45:40 -0700805 if typ != nil && typ.form == Type.FORWARD {
Robert Griesemerfce91182008-07-29 12:03:06 -0700806 P.Error(pos, "incomplete type");
807 }
808
Robert Griesemer0cee3022008-07-15 10:05:17 -0700809 P.Ecart();
Robert Griesemera6f87792008-07-15 15:37:14 -0700810 return typ;
Robert Griesemer0cee3022008-07-15 10:05:17 -0700811}
812
813
814// ----------------------------------------------------------------------------
815// Blocks
816
817func (P *Parser) ParseStatement() {
818 P.Trace("Statement");
819 if !P.TryStatement() {
Robert Griesemer5a90ede2008-07-18 17:18:29 -0700820 P.Error(P.pos, "statement expected");
Robert Griesemera6f87792008-07-15 15:37:14 -0700821 P.Next(); // make progress
Robert Griesemer0cee3022008-07-15 10:05:17 -0700822 }
823 P.Ecart();
824}
825
826
827func (P *Parser) ParseStatementList() {
828 P.Trace("StatementList");
829 for P.TryStatement() {
830 P.Optional(Scanner.SEMICOLON);
831 }
832 P.Ecart();
833}
834
835
Robert Griesemer4b0b7d82008-07-29 19:02:49 -0700836func (P *Parser) ParseBlock(sig *Globals.Scope) {
Robert Griesemer0cee3022008-07-15 10:05:17 -0700837 P.Trace("Block");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700838
Robert Griesemer0cee3022008-07-15 10:05:17 -0700839 P.Expect(Scanner.LBRACE);
840 P.OpenScope();
Robert Griesemer4b0b7d82008-07-29 19:02:49 -0700841 if sig != nil {
842 P.level--;
Robert Griesemer9761a6d2008-07-31 13:35:30 -0700843 // add copies of the formal parameters to the function scope
Robert Griesemer4b0b7d82008-07-29 19:02:49 -0700844 scope := P.top_scope;
845 for p := sig.entries.first; p != nil; p = p.next {
Robert Griesemer9761a6d2008-07-31 13:35:30 -0700846 scope.Insert(p.obj.Copy())
Robert Griesemer4b0b7d82008-07-29 19:02:49 -0700847 }
848 }
Robert Griesemer0cee3022008-07-15 10:05:17 -0700849 if P.tok != Scanner.RBRACE && P.tok != Scanner.SEMICOLON {
850 P.ParseStatementList();
851 }
852 P.Optional(Scanner.SEMICOLON);
Robert Griesemer4b0b7d82008-07-29 19:02:49 -0700853 if sig != nil {
854 P.level++;
855 }
Robert Griesemer0cee3022008-07-15 10:05:17 -0700856 P.CloseScope();
857 P.Expect(Scanner.RBRACE);
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700858
Robert Griesemer0cee3022008-07-15 10:05:17 -0700859 P.Ecart();
860}
861
862
863// ----------------------------------------------------------------------------
864// Expressions
865
Robert Griesemer333b70b2008-08-06 17:26:46 -0700866func (P *Parser) ParseExpressionList(list *Globals.List) {
Robert Griesemer0cee3022008-07-15 10:05:17 -0700867 P.Trace("ExpressionList");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700868
Robert Griesemer687f3872008-08-05 18:52:37 -0700869 list.AddExpr(P.ParseExpression());
Robert Griesemer0cee3022008-07-15 10:05:17 -0700870 for P.tok == Scanner.COMMA {
871 P.Next();
Robert Griesemer687f3872008-08-05 18:52:37 -0700872 list.AddExpr(P.ParseExpression());
Robert Griesemer0cee3022008-07-15 10:05:17 -0700873 }
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700874
Robert Griesemer0cee3022008-07-15 10:05:17 -0700875 P.Ecart();
Robert Griesemer333b70b2008-08-06 17:26:46 -0700876}
877
878
879func (P *Parser) ParseNewExpressionList() *Globals.List {
880 P.Trace("NewExpressionList");
881
882 list := Globals.NewList();
883 P.ParseExpressionList(list);
884
885 P.Ecart();
Robert Griesemercf4c37c2008-07-25 09:35:03 -0700886 return list;
Robert Griesemer0cee3022008-07-15 10:05:17 -0700887}
888
889
Robert Griesemer9761a6d2008-07-31 13:35:30 -0700890func (P *Parser) ParseNew() Globals.Expr {
Robert Griesemer0cee3022008-07-15 10:05:17 -0700891 P.Trace("New");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700892
Robert Griesemer0cee3022008-07-15 10:05:17 -0700893 P.Expect(Scanner.NEW);
894 P.Expect(Scanner.LPAREN);
895 P.ParseType();
Robert Griesemer333b70b2008-08-06 17:26:46 -0700896 args := Globals.NewList();
Robert Griesemer0cee3022008-07-15 10:05:17 -0700897 if P.tok == Scanner.COMMA {
898 P.Next();
Robert Griesemer333b70b2008-08-06 17:26:46 -0700899 P.ParseExpressionList(args)
Robert Griesemer0cee3022008-07-15 10:05:17 -0700900 }
901 P.Expect(Scanner.RPAREN);
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700902
Robert Griesemer0cee3022008-07-15 10:05:17 -0700903 P.Ecart();
Robert Griesemer9761a6d2008-07-31 13:35:30 -0700904 return nil;
Robert Griesemer0cee3022008-07-15 10:05:17 -0700905}
906
907
Robert Griesemer9761a6d2008-07-31 13:35:30 -0700908func (P *Parser) ParseFunctionLit() Globals.Expr {
Robert Griesemer0cee3022008-07-15 10:05:17 -0700909 P.Trace("FunctionLit");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700910
Robert Griesemer4b0b7d82008-07-29 19:02:49 -0700911 typ := P.ParseFunctionType();
912 P.ParseBlock(typ.scope);
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700913
Robert Griesemer0cee3022008-07-15 10:05:17 -0700914 P.Ecart();
Robert Griesemer9761a6d2008-07-31 13:35:30 -0700915 return nil;
Robert Griesemer0cee3022008-07-15 10:05:17 -0700916}
917
918
Robert Griesemer687f3872008-08-05 18:52:37 -0700919func (P *Parser) ParseExpressionPair(list *Globals.List) {
920 P.Trace("ExpressionPair");
921
922 list.AddExpr(P.ParseExpression());
923 P.Expect(Scanner.COLON);
924 list.AddExpr(P.ParseExpression());
925
926 P.Ecart();
927}
928
929
930func (P *Parser) ParseExpressionPairList(list *Globals.List) {
Robert Griesemerfda1d162008-07-23 16:59:06 -0700931 P.Trace("ExpressionPairList");
932
Robert Griesemer687f3872008-08-05 18:52:37 -0700933 P.ParseExpressionPair(list);
Robert Griesemerfda1d162008-07-23 16:59:06 -0700934 for (P.tok == Scanner.COMMA) {
Robert Griesemer687f3872008-08-05 18:52:37 -0700935 P.ParseExpressionPair(list);
Robert Griesemerfda1d162008-07-23 16:59:06 -0700936 }
937
938 P.Ecart();
939}
940
941
Robert Griesemer9761a6d2008-07-31 13:35:30 -0700942func (P *Parser) ParseCompositeLit(typ *Globals.Type) Globals.Expr {
Robert Griesemerfda1d162008-07-23 16:59:06 -0700943 P.Trace("CompositeLit");
944
945 // TODO I think we should use {} instead of () for
946 // composite literals to syntactically distinguish
947 // them from conversions. For now: allow both.
948 var paren int;
949 if P.tok == Scanner.LPAREN {
950 P.Next();
951 paren = Scanner.RPAREN;
952 } else {
953 P.Expect(Scanner.LBRACE);
954 paren = Scanner.RBRACE;
955 }
956
957 // TODO: should allow trailing ','
Robert Griesemer687f3872008-08-05 18:52:37 -0700958 list := Globals.NewList();
Robert Griesemerfda1d162008-07-23 16:59:06 -0700959 if P.tok != paren {
Robert Griesemer687f3872008-08-05 18:52:37 -0700960 list.AddExpr(P.ParseExpression());
Robert Griesemerfda1d162008-07-23 16:59:06 -0700961 if P.tok == Scanner.COMMA {
962 P.Next();
963 if P.tok != paren {
Robert Griesemer333b70b2008-08-06 17:26:46 -0700964 P.ParseExpressionList(list);
Robert Griesemerfda1d162008-07-23 16:59:06 -0700965 }
966 } else if P.tok == Scanner.COLON {
967 P.Next();
Robert Griesemer687f3872008-08-05 18:52:37 -0700968 list.AddExpr(P.ParseExpression());
Robert Griesemerfda1d162008-07-23 16:59:06 -0700969 if P.tok == Scanner.COMMA {
970 P.Next();
971 if P.tok != paren {
Robert Griesemer687f3872008-08-05 18:52:37 -0700972 P.ParseExpressionPairList(list);
Robert Griesemerfda1d162008-07-23 16:59:06 -0700973 }
974 }
975 }
976 }
977
978 P.Expect(paren);
979
980 P.Ecart();
Robert Griesemer9761a6d2008-07-31 13:35:30 -0700981 return nil;
Robert Griesemerfda1d162008-07-23 16:59:06 -0700982}
983
984
Robert Griesemer9761a6d2008-07-31 13:35:30 -0700985func (P *Parser) ParseOperand(pos int, ident string) Globals.Expr {
Robert Griesemer0cee3022008-07-15 10:05:17 -0700986 P.Trace("Operand");
Robert Griesemerf03deb32008-07-24 17:00:58 -0700987
988 if pos < 0 && P.tok == Scanner.IDENT {
989 // no look-ahead yet
990 pos = P.pos;
991 ident = P.val;
992 P.Next();
993 }
Robert Griesemer687f3872008-08-05 18:52:37 -0700994
995 var res Globals.Expr = AST.Bad;
996
Robert Griesemerf03deb32008-07-24 17:00:58 -0700997 if pos >= 0 {
Robert Griesemer683ded82008-08-11 21:20:42 -0700998 obj := P.ParseQualifiedIdent(pos, ident);
999 if P.semantic_checks {
1000 if obj.kind == Object.TYPE {
1001 res = P.ParseCompositeLit(obj.typ);
1002 } else {
1003 res = AST.NewObject(pos, obj);
Robert Griesemer687f3872008-08-05 18:52:37 -07001004 }
Robert Griesemerfda1d162008-07-23 16:59:06 -07001005 }
Robert Griesemer687f3872008-08-05 18:52:37 -07001006
1007 } else {
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001008
Robert Griesemer687f3872008-08-05 18:52:37 -07001009 switch P.tok {
1010 case Scanner.IDENT:
Robert Griesemer683ded82008-08-11 21:20:42 -07001011 panic("UNREACHABLE");
Robert Griesemer687f3872008-08-05 18:52:37 -07001012
1013 case Scanner.LPAREN:
1014 P.Next();
1015 res = P.ParseExpression();
1016 P.Expect(Scanner.RPAREN);
1017
1018 case Scanner.INT:
Robert Griesemer333b70b2008-08-06 17:26:46 -07001019 x := AST.NewLiteral(P.pos, Universe.int_t);
Robert Griesemer687f3872008-08-05 18:52:37 -07001020 x.i = 42; // TODO set the right value
1021 res = x;
1022 P.Next();
1023
1024 case Scanner.FLOAT:
Robert Griesemer333b70b2008-08-06 17:26:46 -07001025 x := AST.NewLiteral(P.pos, Universe.float_t);
Robert Griesemer687f3872008-08-05 18:52:37 -07001026 x.f = 42.0; // TODO set the right value
1027 res = x;
1028 P.Next();
1029
1030 case Scanner.STRING:
Robert Griesemer333b70b2008-08-06 17:26:46 -07001031 x := AST.NewLiteral(P.pos, Universe.string_t);
Robert Griesemer687f3872008-08-05 18:52:37 -07001032 x.s = P.val; // TODO need to strip quotes, interpret string properly
1033 res = x;
1034 P.Next();
1035
1036 case Scanner.NIL:
1037 P.Next();
1038 res = AST.Nil;
1039
1040 case Scanner.IOTA:
Robert Griesemer333b70b2008-08-06 17:26:46 -07001041 x := AST.NewLiteral(P.pos, Universe.int_t);
Robert Griesemer687f3872008-08-05 18:52:37 -07001042 x.i = 42; // TODO set the right value
1043 res = x;
1044 P.Next();
1045
1046 case Scanner.TRUE:
1047 P.Next();
1048 res = AST.True;
1049
1050 case Scanner.FALSE:
1051 P.Next();
1052 res = AST.False;
1053
1054 case Scanner.FUNC:
1055 res = P.ParseFunctionLit();
1056
1057 case Scanner.NEW:
1058 res = P.ParseNew();
1059
1060 default:
1061 typ := P.TryType();
1062 if typ != nil {
1063 res = P.ParseCompositeLit(typ);
1064 } else {
1065 P.Error(P.pos, "operand expected");
1066 P.Next(); // make progress
1067 }
1068 }
1069
1070 }
1071
Robert Griesemer0cee3022008-07-15 10:05:17 -07001072 P.Ecart();
Robert Griesemer687f3872008-08-05 18:52:37 -07001073 return res;
Robert Griesemer0cee3022008-07-15 10:05:17 -07001074}
1075
1076
Robert Griesemer687f3872008-08-05 18:52:37 -07001077func (P *Parser) ParseSelectorOrTypeAssertion(x Globals.Expr) Globals.Expr {
Robert Griesemer0cee3022008-07-15 10:05:17 -07001078 P.Trace("SelectorOrTypeAssertion");
Robert Griesemer687f3872008-08-05 18:52:37 -07001079
Robert Griesemer333b70b2008-08-06 17:26:46 -07001080 period_pos := P.pos;
Robert Griesemer0cee3022008-07-15 10:05:17 -07001081 P.Expect(Scanner.PERIOD);
Robert Griesemer687f3872008-08-05 18:52:37 -07001082
Robert Griesemer58ba20b2008-08-11 20:40:37 -07001083 if P.tok >= Scanner.IDENT {
1084 ident_pos, ident := P.ParseIdent(true);
Robert Griesemer687f3872008-08-05 18:52:37 -07001085
Robert Griesemer333b70b2008-08-06 17:26:46 -07001086 if P.semantic_checks {
1087 switch typ := x.typ(); typ.form {
1088 case Type.BAD:
1089 // ignore
1090 break;
1091 case Type.STRUCT, Type.INTERFACE:
1092 obj := typ.scope.Lookup(ident);
1093 if obj != nil {
1094 x = AST.NewSelector(x.pos(), obj.typ);
1095
1096 } else {
1097 P.Error(ident_pos, `no field/method "` + ident + `"`);
1098 x = AST.Bad;
1099 }
1100 default:
1101 P.Error(period_pos, `"." not applicable`);
1102 x = AST.Bad;
1103 }
1104 }
1105
Robert Griesemer0cee3022008-07-15 10:05:17 -07001106 } else {
1107 P.Expect(Scanner.LPAREN);
1108 P.ParseType();
1109 P.Expect(Scanner.RPAREN);
Robert Griesemer333b70b2008-08-06 17:26:46 -07001110
1111 if P.semantic_checks {
Robert Griesemer683ded82008-08-11 21:20:42 -07001112 panic("UNIMPLEMENTED");
Robert Griesemer333b70b2008-08-06 17:26:46 -07001113 }
Robert Griesemer0cee3022008-07-15 10:05:17 -07001114 }
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001115
Robert Griesemer0cee3022008-07-15 10:05:17 -07001116 P.Ecart();
Robert Griesemer687f3872008-08-05 18:52:37 -07001117 return x;
Robert Griesemer0cee3022008-07-15 10:05:17 -07001118}
1119
1120
Robert Griesemer687f3872008-08-05 18:52:37 -07001121func (P *Parser) ParseIndexOrSlice(x Globals.Expr) Globals.Expr {
Robert Griesemer0cee3022008-07-15 10:05:17 -07001122 P.Trace("IndexOrSlice");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001123
Robert Griesemer333b70b2008-08-06 17:26:46 -07001124 pos := P.pos;
Robert Griesemer0cee3022008-07-15 10:05:17 -07001125 P.Expect(Scanner.LBRACK);
Robert Griesemer333b70b2008-08-06 17:26:46 -07001126 i1 := P.ParseExpression();
1127 var i2 Globals.Expr;
Robert Griesemer0cee3022008-07-15 10:05:17 -07001128 if P.tok == Scanner.COLON {
1129 P.Next();
Robert Griesemer333b70b2008-08-06 17:26:46 -07001130 i2 := P.ParseExpression();
Robert Griesemer0cee3022008-07-15 10:05:17 -07001131 }
1132 P.Expect(Scanner.RBRACK);
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001133
Robert Griesemer333b70b2008-08-06 17:26:46 -07001134 if P.semantic_checks {
1135 switch typ := x.typ(); typ.form {
1136 case Type.BAD:
1137 // ignore
1138 break;
1139 case Type.STRING, Type.ARRAY:
Robert Griesemer683ded82008-08-11 21:20:42 -07001140 panic("UNIMPLEMENTED");
Robert Griesemer333b70b2008-08-06 17:26:46 -07001141
1142 case Type.MAP:
1143 if Type.Equal(typ.aux, i1.typ()) {
1144 // x = AST.NewSubscript(x, i1);
Robert Griesemer683ded82008-08-11 21:20:42 -07001145 panic("UNIMPLEMENTED");
Robert Griesemer333b70b2008-08-06 17:26:46 -07001146
1147 } else {
1148 P.Error(x.pos(), "map key type mismatch");
1149 x = AST.Bad;
1150 }
1151
1152 default:
1153 P.Error(pos, `"[]" not applicable`);
1154 x = AST.Bad;
1155 }
1156
1157 }
1158
Robert Griesemer0cee3022008-07-15 10:05:17 -07001159 P.Ecart();
Robert Griesemer687f3872008-08-05 18:52:37 -07001160 return x;
Robert Griesemer0cee3022008-07-15 10:05:17 -07001161}
1162
1163
Robert Griesemer687f3872008-08-05 18:52:37 -07001164func (P *Parser) ParseCall(x Globals.Expr) Globals.Expr {
Robert Griesemerf03deb32008-07-24 17:00:58 -07001165 P.Trace("Call");
Robert Griesemer333b70b2008-08-06 17:26:46 -07001166
Robert Griesemer0cee3022008-07-15 10:05:17 -07001167 P.Expect(Scanner.LPAREN);
Robert Griesemer333b70b2008-08-06 17:26:46 -07001168 args := Globals.NewList();
Robert Griesemer0cee3022008-07-15 10:05:17 -07001169 if P.tok != Scanner.RPAREN {
Robert Griesemer333b70b2008-08-06 17:26:46 -07001170 P.ParseExpressionList(args);
Robert Griesemer0cee3022008-07-15 10:05:17 -07001171 }
1172 P.Expect(Scanner.RPAREN);
Robert Griesemer333b70b2008-08-06 17:26:46 -07001173
1174 if P.semantic_checks {
Robert Griesemer683ded82008-08-11 21:20:42 -07001175 panic("UNIMPLEMENTED");
Robert Griesemer333b70b2008-08-06 17:26:46 -07001176 }
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001177
Robert Griesemer0cee3022008-07-15 10:05:17 -07001178 P.Ecart();
Robert Griesemer687f3872008-08-05 18:52:37 -07001179 return x;
Robert Griesemer0cee3022008-07-15 10:05:17 -07001180}
1181
1182
Robert Griesemer9761a6d2008-07-31 13:35:30 -07001183func (P *Parser) ParsePrimaryExpr(pos int, ident string) Globals.Expr {
Robert Griesemer0cee3022008-07-15 10:05:17 -07001184 P.Trace("PrimaryExpr");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001185
Robert Griesemer687f3872008-08-05 18:52:37 -07001186 x := P.ParseOperand(pos, ident);
Robert Griesemer0cee3022008-07-15 10:05:17 -07001187 for {
1188 switch P.tok {
Robert Griesemer687f3872008-08-05 18:52:37 -07001189 case Scanner.PERIOD: x = P.ParseSelectorOrTypeAssertion(x);
1190 case Scanner.LBRACK: x = P.ParseIndexOrSlice(x);
1191 case Scanner.LPAREN: x = P.ParseCall(x);
1192 default: goto exit;
Robert Griesemer0cee3022008-07-15 10:05:17 -07001193 }
1194 }
Robert Griesemer687f3872008-08-05 18:52:37 -07001195
1196exit:
Robert Griesemer0cee3022008-07-15 10:05:17 -07001197 P.Ecart();
Robert Griesemer687f3872008-08-05 18:52:37 -07001198 return x;
Robert Griesemer0cee3022008-07-15 10:05:17 -07001199}
Robert Griesemer835cd462008-07-07 17:27:14 -07001200
1201
Robert Griesemer333b70b2008-08-06 17:26:46 -07001202// TODO is this function needed?
1203func (P *Parser) ParsePrimaryExprList() *Globals.List {
Robert Griesemer835cd462008-07-07 17:27:14 -07001204 P.Trace("PrimaryExprList");
Robert Griesemer333b70b2008-08-06 17:26:46 -07001205
1206 list := Globals.NewList();
1207 list.AddExpr(P.ParsePrimaryExpr(-1, ""));
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001208 for P.tok == Scanner.COMMA {
1209 P.Next();
Robert Griesemer333b70b2008-08-06 17:26:46 -07001210 list.AddExpr(P.ParsePrimaryExpr(-1, ""));
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001211 }
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001212
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001213 P.Ecart();
Robert Griesemer333b70b2008-08-06 17:26:46 -07001214 return list;
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001215}
1216
1217
Robert Griesemer9761a6d2008-07-31 13:35:30 -07001218func (P *Parser) ParseUnaryExpr() Globals.Expr {
Robert Griesemer0cee3022008-07-15 10:05:17 -07001219 P.Trace("UnaryExpr");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001220
Robert Griesemer0cee3022008-07-15 10:05:17 -07001221 switch P.tok {
1222 case Scanner.ADD: fallthrough;
1223 case Scanner.SUB: fallthrough;
1224 case Scanner.NOT: fallthrough;
1225 case Scanner.XOR: fallthrough;
Robert Griesemer0cee3022008-07-15 10:05:17 -07001226 case Scanner.MUL: fallthrough;
Robert Griesemer0e676542008-07-16 17:00:48 -07001227 case Scanner.RECV: fallthrough;
Robert Griesemer0cee3022008-07-15 10:05:17 -07001228 case Scanner.AND:
1229 P.Next();
1230 P.ParseUnaryExpr();
1231 P.Ecart();
Robert Griesemer5a90ede2008-07-18 17:18:29 -07001232 return nil; // TODO fix this
Robert Griesemer0cee3022008-07-15 10:05:17 -07001233 }
Robert Griesemerf03deb32008-07-24 17:00:58 -07001234 P.ParsePrimaryExpr(-1, "");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001235
Robert Griesemer0cee3022008-07-15 10:05:17 -07001236 P.Ecart();
Robert Griesemer5a90ede2008-07-18 17:18:29 -07001237 return nil; // TODO fix this
Robert Griesemer0cee3022008-07-15 10:05:17 -07001238}
1239
1240
1241func Precedence(tok int) int {
1242 // TODO should use a map or array here for lookup
1243 switch tok {
1244 case Scanner.LOR:
1245 return 1;
1246 case Scanner.LAND:
1247 return 2;
Robert Griesemer0e676542008-07-16 17:00:48 -07001248 case Scanner.SEND, Scanner.RECV:
Robert Griesemer0cee3022008-07-15 10:05:17 -07001249 return 3;
Robert Griesemer0e676542008-07-16 17:00:48 -07001250 case Scanner.EQL, Scanner.NEQ, Scanner.LSS, Scanner.LEQ, Scanner.GTR, Scanner.GEQ:
Robert Griesemer0cee3022008-07-15 10:05:17 -07001251 return 4;
Robert Griesemer0e676542008-07-16 17:00:48 -07001252 case Scanner.ADD, Scanner.SUB, Scanner.OR, Scanner.XOR:
Robert Griesemer0cee3022008-07-15 10:05:17 -07001253 return 5;
Robert Griesemer0e676542008-07-16 17:00:48 -07001254 case Scanner.MUL, Scanner.QUO, Scanner.REM, Scanner.SHL, Scanner.SHR, Scanner.AND:
1255 return 6;
Robert Griesemer0cee3022008-07-15 10:05:17 -07001256 }
1257 return 0;
1258}
1259
1260
Robert Griesemer9761a6d2008-07-31 13:35:30 -07001261func (P *Parser) ParseBinaryExpr(pos int, ident string, prec1 int) Globals.Expr {
Robert Griesemer0cee3022008-07-15 10:05:17 -07001262 P.Trace("BinaryExpr");
Robert Griesemer5a90ede2008-07-18 17:18:29 -07001263
Robert Griesemer9761a6d2008-07-31 13:35:30 -07001264 var x Globals.Expr;
Robert Griesemerf03deb32008-07-24 17:00:58 -07001265 if pos >= 0 {
1266 x = P.ParsePrimaryExpr(pos, ident);
1267 } else {
1268 x = P.ParseUnaryExpr();
1269 }
Robert Griesemer0cee3022008-07-15 10:05:17 -07001270 for prec := Precedence(P.tok); prec >= prec1; prec-- {
1271 for Precedence(P.tok) == prec {
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001272 e := new(AST.BinaryExpr);
Robert Griesemerc7fb27f2008-08-11 09:45:40 -07001273 e.typ_ = Universe.bad_t; // TODO fix this
Robert Griesemer5a90ede2008-07-18 17:18:29 -07001274 e.op = P.tok; // TODO should we use tokens or separate operator constants?
1275 e.x = x;
Robert Griesemer0cee3022008-07-15 10:05:17 -07001276 P.Next();
Robert Griesemerf03deb32008-07-24 17:00:58 -07001277 e.y = P.ParseBinaryExpr(-1, "", prec + 1);
Robert Griesemer5a90ede2008-07-18 17:18:29 -07001278 x = e;
Robert Griesemer0cee3022008-07-15 10:05:17 -07001279 }
1280 }
Robert Griesemer5a90ede2008-07-18 17:18:29 -07001281
Robert Griesemer0cee3022008-07-15 10:05:17 -07001282 P.Ecart();
Robert Griesemer9761a6d2008-07-31 13:35:30 -07001283 return x;
Robert Griesemer0cee3022008-07-15 10:05:17 -07001284}
1285
1286
Robert Griesemer5fc79192008-07-25 11:27:13 -07001287// Expressions where the first token may be an identifier which has already
1288// been consumed. If the identifier is present, pos is the identifier position,
1289// otherwise pos must be < 0 (and ident is ignored).
Robert Griesemer9761a6d2008-07-31 13:35:30 -07001290func (P *Parser) ParseIdentExpression(pos int, ident string) Globals.Expr {
Robert Griesemerf03deb32008-07-24 17:00:58 -07001291 P.Trace("IdentExpression");
Robert Griesemer0cee3022008-07-15 10:05:17 -07001292 indent := P.indent;
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001293
Robert Griesemer9761a6d2008-07-31 13:35:30 -07001294 x := P.ParseBinaryExpr(pos, ident, 1);
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001295
Robert Griesemer0cee3022008-07-15 10:05:17 -07001296 if indent != P.indent {
Robert Griesemer683ded82008-08-11 21:20:42 -07001297 panic("imbalanced tracing code (Expression)");
Robert Griesemer0cee3022008-07-15 10:05:17 -07001298 }
1299 P.Ecart();
Robert Griesemer9761a6d2008-07-31 13:35:30 -07001300 return x;
Robert Griesemer0cee3022008-07-15 10:05:17 -07001301}
1302
1303
Robert Griesemer9761a6d2008-07-31 13:35:30 -07001304func (P *Parser) ParseExpression() Globals.Expr {
1305 P.Trace("Expression");
1306
1307 x := P.ParseIdentExpression(-1, "");
1308
Robert Griesemerf03deb32008-07-24 17:00:58 -07001309 P.Ecart();
Robert Griesemer9761a6d2008-07-31 13:35:30 -07001310 return x;
Robert Griesemerf03deb32008-07-24 17:00:58 -07001311}
1312
1313
Robert Griesemer0cee3022008-07-15 10:05:17 -07001314// ----------------------------------------------------------------------------
1315// Statements
1316
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001317func (P *Parser) ConvertToExprList(pos_list, ident_list, expr_list *Globals.List) {
1318 for p, q := pos_list.first, ident_list.first; q != nil; p, q = p.next, q.next {
1319 pos, ident := p.val, q.str;
Robert Griesemer1f465132008-07-30 17:36:03 -07001320 if P.semantic_checks {
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001321 obj := P.Lookup(ident);
1322 if obj == nil {
1323 P.Error(pos, `"` + ident + `" is not declared`);
1324 obj = Globals.NewObject(pos, Object.BAD, ident);
1325 }
1326 }
1327 expr_list.AddInt(0); // TODO fix this - add correct expression
1328 }
1329 ident_list.Clear();
1330}
1331
1332
1333func (P *Parser) ParseIdentOrExpr(pos_list, ident_list, expr_list *Globals.List) {
Robert Griesemerf03deb32008-07-24 17:00:58 -07001334 P.Trace("IdentOrExpr");
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001335
1336 pos_list.AddInt(P.pos);
1337 pos, ident := -1, "";
1338 just_ident := false;
1339 if expr_list.len_ == 0 /* only idents so far */ && P.tok == Scanner.IDENT {
1340 pos, ident = P.pos, P.val;
Robert Griesemerf03deb32008-07-24 17:00:58 -07001341 P.Next();
1342 switch P.tok {
1343 case Scanner.COMMA,
1344 Scanner.COLON,
1345 Scanner.DEFINE,
1346 Scanner.ASSIGN,
1347 Scanner.ADD_ASSIGN,
1348 Scanner.SUB_ASSIGN,
1349 Scanner.MUL_ASSIGN,
1350 Scanner.QUO_ASSIGN,
1351 Scanner.REM_ASSIGN,
1352 Scanner.AND_ASSIGN,
1353 Scanner.OR_ASSIGN,
1354 Scanner.XOR_ASSIGN,
1355 Scanner.SHL_ASSIGN,
1356 Scanner.SHR_ASSIGN:
1357 // identifier is not part of a more complicated expression
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001358 just_ident = true;
Robert Griesemerf03deb32008-07-24 17:00:58 -07001359 }
Robert Griesemerf03deb32008-07-24 17:00:58 -07001360 }
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001361
1362 if just_ident {
1363 ident_list.AddStr(ident);
1364 } else {
1365 P.ConvertToExprList(pos_list, ident_list, expr_list);
1366 P.ParseIdentExpression(pos, ident);
1367 expr_list.AddInt(0); // TODO fix this - add correct expression
1368 }
1369
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001370 P.Ecart();
Robert Griesemerf03deb32008-07-24 17:00:58 -07001371}
1372
1373
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001374func (P *Parser) ParseIdentOrExprList() (pos_list, ident_list, expr_list *Globals.List) {
1375 P.Trace("IdentOrExprList");
1376
1377 pos_list, ident_list, expr_list = Globals.NewList(), Globals.NewList(), Globals.NewList();
1378 P.ParseIdentOrExpr(pos_list, ident_list, expr_list);
1379 for P.tok == Scanner.COMMA {
1380 P.Next();
1381 P.ParseIdentOrExpr(pos_list, ident_list, expr_list);
Robert Griesemerf03deb32008-07-24 17:00:58 -07001382 }
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001383
1384 P.Ecart();
1385 return pos_list, ident_list, expr_list;
Robert Griesemer835cd462008-07-07 17:27:14 -07001386}
1387
1388
1389func (P *Parser) ParseSimpleStat() {
1390 P.Trace("SimpleStat");
Robert Griesemerf03deb32008-07-24 17:00:58 -07001391
1392 // If we see an identifier, we don't know if it's part of a
1393 // label declaration, (multiple) variable declaration, assignment,
1394 // or simply an expression, without looking ahead.
1395 // Strategy: We parse an expression list, but simultaneously, as
1396 // long as possible, maintain a list of identifiers which is converted
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001397 // into an expression list only if neccessary. The result of
1398 // ParseIdentOrExprList is a list of ident/expr positions and either
1399 // a non-empty list of identifiers or a non-empty list of expressions
1400 // (but not both).
1401 pos_list, ident_list, expr_list := P.ParseIdentOrExprList();
Robert Griesemerf03deb32008-07-24 17:00:58 -07001402
Robert Griesemer8e4ee002008-07-08 18:37:31 -07001403 switch P.tok {
Robert Griesemerf03deb32008-07-24 17:00:58 -07001404 case Scanner.COLON:
1405 // label declaration
Robert Griesemer1f465132008-07-30 17:36:03 -07001406 if P.semantic_checks && ident_list.len_ != 1 {
Robert Griesemerf03deb32008-07-24 17:00:58 -07001407 P.Error(P.pos, "illegal label declaration");
1408 }
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001409 P.Next();
Robert Griesemerf03deb32008-07-24 17:00:58 -07001410
1411 case Scanner.DEFINE:
1412 // variable declaration
Robert Griesemer1f465132008-07-30 17:36:03 -07001413 if P.semantic_checks && ident_list.len_ == 0 {
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001414 P.Error(P.pos, "illegal left-hand side for declaration");
1415 }
Robert Griesemerf03deb32008-07-24 17:00:58 -07001416 P.Next();
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001417 pos := P.pos;
Robert Griesemer333b70b2008-08-06 17:26:46 -07001418 val_list := P.ParseNewExpressionList();
Robert Griesemer1f465132008-07-30 17:36:03 -07001419 if P.semantic_checks && val_list.len_ != ident_list.len_ {
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001420 P.Error(pos, "number of expressions does not match number of variables");
1421 }
1422 // declare variables
Robert Griesemer1f465132008-07-30 17:36:03 -07001423 if P.semantic_checks {
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001424 for p, q := pos_list.first, ident_list.first; q != nil; p, q = p.next, q.next {
1425 obj := Globals.NewObject(p.val, Object.VAR, q.str);
1426 P.Declare(obj);
1427 // TODO set correct types
1428 }
Robert Griesemerf03deb32008-07-24 17:00:58 -07001429 }
1430
Robert Griesemer8e4ee002008-07-08 18:37:31 -07001431 case Scanner.ASSIGN: fallthrough;
Robert Griesemer8e4ee002008-07-08 18:37:31 -07001432 case Scanner.ADD_ASSIGN: fallthrough;
1433 case Scanner.SUB_ASSIGN: fallthrough;
1434 case Scanner.MUL_ASSIGN: fallthrough;
1435 case Scanner.QUO_ASSIGN: fallthrough;
1436 case Scanner.REM_ASSIGN: fallthrough;
1437 case Scanner.AND_ASSIGN: fallthrough;
1438 case Scanner.OR_ASSIGN: fallthrough;
1439 case Scanner.XOR_ASSIGN: fallthrough;
1440 case Scanner.SHL_ASSIGN: fallthrough;
1441 case Scanner.SHR_ASSIGN:
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001442 P.ConvertToExprList(pos_list, ident_list, expr_list);
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001443 P.Next();
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001444 pos := P.pos;
Robert Griesemer333b70b2008-08-06 17:26:46 -07001445 val_list := P.ParseNewExpressionList();
Robert Griesemer1f465132008-07-30 17:36:03 -07001446 if P.semantic_checks && val_list.len_ != expr_list.len_ {
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001447 P.Error(pos, "number of expressions does not match number of variables");
Robert Griesemerf03deb32008-07-24 17:00:58 -07001448 }
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001449
Robert Griesemerf03deb32008-07-24 17:00:58 -07001450 default:
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001451 P.ConvertToExprList(pos_list, ident_list, expr_list);
Robert Griesemer1f465132008-07-30 17:36:03 -07001452 if P.semantic_checks && expr_list.len_ != 1 {
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001453 P.Error(P.pos, "no expression list allowed");
1454 }
1455 if P.tok == Scanner.INC || P.tok == Scanner.DEC {
1456 P.Next();
Robert Griesemerf03deb32008-07-24 17:00:58 -07001457 }
Robert Griesemer835cd462008-07-07 17:27:14 -07001458 }
Robert Griesemerf03deb32008-07-24 17:00:58 -07001459
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001460 P.Ecart();
1461}
1462
1463
Robert Griesemer8e4ee002008-07-08 18:37:31 -07001464func (P *Parser) ParseGoStat() {
1465 P.Trace("GoStat");
Robert Griesemer9761a6d2008-07-31 13:35:30 -07001466
Robert Griesemer8e4ee002008-07-08 18:37:31 -07001467 P.Expect(Scanner.GO);
1468 P.ParseExpression();
Robert Griesemer9761a6d2008-07-31 13:35:30 -07001469
Robert Griesemer415397e2008-07-09 14:48:26 -07001470 P.Ecart();
Robert Griesemer8e4ee002008-07-08 18:37:31 -07001471}
1472
1473
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001474func (P *Parser) ParseReturnStat() {
1475 P.Trace("ReturnStat");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001476
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001477 P.Expect(Scanner.RETURN);
Robert Griesemer333b70b2008-08-06 17:26:46 -07001478 res := Globals.NewList();
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001479 if P.tok != Scanner.SEMICOLON && P.tok != Scanner.RBRACE {
Robert Griesemer333b70b2008-08-06 17:26:46 -07001480 P.ParseExpressionList(res);
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001481 }
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001482
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001483 P.Ecart();
1484}
1485
1486
Robert Griesemer8e4ee002008-07-08 18:37:31 -07001487func (P *Parser) ParseControlFlowStat(tok int) {
1488 P.Trace("ControlFlowStat");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001489
Robert Griesemer8e4ee002008-07-08 18:37:31 -07001490 P.Expect(tok);
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001491 if P.tok == Scanner.IDENT {
Robert Griesemer58ba20b2008-08-11 20:40:37 -07001492 P.ParseIdent(false);
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001493 }
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001494
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001495 P.Ecart();
1496}
1497
1498
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001499func (P *Parser) ParseIfStat() *AST.IfStat {
Robert Griesemer835cd462008-07-07 17:27:14 -07001500 P.Trace("IfStat");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001501
Robert Griesemer835cd462008-07-07 17:27:14 -07001502 P.Expect(Scanner.IF);
Robert Griesemer230230c2008-07-14 18:06:41 -07001503 P.OpenScope();
Robert Griesemer835cd462008-07-07 17:27:14 -07001504 if P.tok != Scanner.LBRACE {
Robert Griesemerae905982008-07-10 20:50:38 -07001505 if P.tok != Scanner.SEMICOLON {
1506 P.ParseSimpleStat();
1507 }
Robert Griesemer835cd462008-07-07 17:27:14 -07001508 if P.tok == Scanner.SEMICOLON {
Robert Griesemer8e4ee002008-07-08 18:37:31 -07001509 P.Next();
Robert Griesemerae905982008-07-10 20:50:38 -07001510 if P.tok != Scanner.LBRACE {
1511 P.ParseExpression();
1512 }
Robert Griesemer835cd462008-07-07 17:27:14 -07001513 }
1514 }
Robert Griesemer4b0b7d82008-07-29 19:02:49 -07001515 P.ParseBlock(nil);
Robert Griesemer835cd462008-07-07 17:27:14 -07001516 if P.tok == Scanner.ELSE {
1517 P.Next();
1518 if P.tok == Scanner.IF {
1519 P.ParseIfStat();
1520 } else {
1521 // TODO should be P.ParseBlock()
Robert Griesemer8e4ee002008-07-08 18:37:31 -07001522 P.ParseStatement();
Robert Griesemer835cd462008-07-07 17:27:14 -07001523 }
1524 }
Robert Griesemer230230c2008-07-14 18:06:41 -07001525 P.CloseScope();
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001526
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001527 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -07001528}
1529
1530
1531func (P *Parser) ParseForStat() {
1532 P.Trace("ForStat");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001533
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001534 P.Expect(Scanner.FOR);
Robert Griesemer230230c2008-07-14 18:06:41 -07001535 P.OpenScope();
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001536 if P.tok != Scanner.LBRACE {
1537 if P.tok != Scanner.SEMICOLON {
1538 P.ParseSimpleStat();
1539 }
1540 if P.tok == Scanner.SEMICOLON {
1541 P.Next();
1542 if P.tok != Scanner.SEMICOLON {
1543 P.ParseExpression();
1544 }
1545 P.Expect(Scanner.SEMICOLON);
1546 if P.tok != Scanner.LBRACE {
1547 P.ParseSimpleStat();
1548 }
1549 }
1550 }
Robert Griesemer4b0b7d82008-07-29 19:02:49 -07001551 P.ParseBlock(nil);
Robert Griesemer230230c2008-07-14 18:06:41 -07001552 P.CloseScope();
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001553
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001554 P.Ecart();
1555}
1556
1557
1558func (P *Parser) ParseCase() {
1559 P.Trace("Case");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001560
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001561 if P.tok == Scanner.CASE {
1562 P.Next();
Robert Griesemer333b70b2008-08-06 17:26:46 -07001563 list := Globals.NewList();
1564 P.ParseExpressionList(list);
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001565 } else {
1566 P.Expect(Scanner.DEFAULT);
1567 }
1568 P.Expect(Scanner.COLON);
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001569
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001570 P.Ecart();
1571}
1572
1573
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001574func (P *Parser) ParseCaseClause() {
1575 P.Trace("CaseClause");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001576
Robert Griesemer40c93a52008-08-11 18:44:41 -07001577 P.ParseCase();
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001578 if P.tok != Scanner.FALLTHROUGH && P.tok != Scanner.RBRACE {
1579 P.ParseStatementList();
Robert Griesemer8e4ee002008-07-08 18:37:31 -07001580 P.Optional(Scanner.SEMICOLON);
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001581 }
1582 if P.tok == Scanner.FALLTHROUGH {
1583 P.Next();
Robert Griesemer8e4ee002008-07-08 18:37:31 -07001584 P.Optional(Scanner.SEMICOLON);
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001585 }
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001586
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001587 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -07001588}
1589
1590
1591func (P *Parser) ParseSwitchStat() {
1592 P.Trace("SwitchStat");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001593
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001594 P.Expect(Scanner.SWITCH);
Robert Griesemer230230c2008-07-14 18:06:41 -07001595 P.OpenScope();
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001596 if P.tok != Scanner.LBRACE {
Robert Griesemerae905982008-07-10 20:50:38 -07001597 if P.tok != Scanner.SEMICOLON {
1598 P.ParseSimpleStat();
1599 }
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001600 if P.tok == Scanner.SEMICOLON {
Robert Griesemer8e4ee002008-07-08 18:37:31 -07001601 P.Next();
Robert Griesemerae905982008-07-10 20:50:38 -07001602 if P.tok != Scanner.LBRACE {
1603 P.ParseExpression();
1604 }
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001605 }
1606 }
1607 P.Expect(Scanner.LBRACE);
Robert Griesemerf03deb32008-07-24 17:00:58 -07001608 for P.tok == Scanner.CASE || P.tok == Scanner.DEFAULT {
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001609 P.ParseCaseClause();
1610 }
1611 P.Expect(Scanner.RBRACE);
Robert Griesemer230230c2008-07-14 18:06:41 -07001612 P.CloseScope();
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001613
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001614 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -07001615}
1616
1617
Robert Griesemercab94922008-07-09 14:01:17 -07001618func (P *Parser) ParseCommCase() {
1619 P.Trace("CommCase");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001620
Robert Griesemercab94922008-07-09 14:01:17 -07001621 if P.tok == Scanner.CASE {
1622 P.Next();
1623 if P.tok == Scanner.GTR {
1624 // send
1625 P.Next();
1626 P.ParseExpression();
1627 P.Expect(Scanner.EQL);
1628 P.ParseExpression();
1629 } else {
1630 // receive
1631 if P.tok != Scanner.LSS {
Robert Griesemer58ba20b2008-08-11 20:40:37 -07001632 P.ParseIdent(false);
Robert Griesemercab94922008-07-09 14:01:17 -07001633 P.Expect(Scanner.ASSIGN);
1634 }
1635 P.Expect(Scanner.LSS);
1636 P.ParseExpression();
1637 }
1638 } else {
1639 P.Expect(Scanner.DEFAULT);
1640 }
1641 P.Expect(Scanner.COLON);
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001642
Robert Griesemercab94922008-07-09 14:01:17 -07001643 P.Ecart();
1644}
1645
1646
1647func (P *Parser) ParseCommClause() {
1648 P.Trace("CommClause");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001649
Robert Griesemercab94922008-07-09 14:01:17 -07001650 P.ParseCommCase();
1651 if P.tok != Scanner.CASE && P.tok != Scanner.DEFAULT && P.tok != Scanner.RBRACE {
1652 P.ParseStatementList();
1653 P.Optional(Scanner.SEMICOLON);
1654 }
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001655
Robert Griesemercab94922008-07-09 14:01:17 -07001656 P.Ecart();
1657}
1658
1659
1660func (P *Parser) ParseRangeStat() bool {
1661 P.Trace("RangeStat");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001662
Robert Griesemercab94922008-07-09 14:01:17 -07001663 P.Expect(Scanner.RANGE);
1664 P.ParseIdentList();
1665 P.Expect(Scanner.DEFINE);
1666 P.ParseExpression();
Robert Griesemer4b0b7d82008-07-29 19:02:49 -07001667 P.ParseBlock(nil);
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001668
Robert Griesemercab94922008-07-09 14:01:17 -07001669 P.Ecart();
1670}
1671
1672
1673func (P *Parser) ParseSelectStat() bool {
1674 P.Trace("SelectStat");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001675
Robert Griesemercab94922008-07-09 14:01:17 -07001676 P.Expect(Scanner.SELECT);
1677 P.Expect(Scanner.LBRACE);
Robert Griesemerf03deb32008-07-24 17:00:58 -07001678 for P.tok != Scanner.RBRACE && P.tok != Scanner.EOF {
Robert Griesemercab94922008-07-09 14:01:17 -07001679 P.ParseCommClause();
1680 }
1681 P.Next();
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001682
Robert Griesemercab94922008-07-09 14:01:17 -07001683 P.Ecart();
1684}
1685
1686
Robert Griesemer8e4ee002008-07-08 18:37:31 -07001687func (P *Parser) TryStatement() bool {
1688 P.Trace("Statement (try)");
Robert Griesemer415397e2008-07-09 14:48:26 -07001689 indent := P.indent;
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001690
Robert Griesemer415397e2008-07-09 14:48:26 -07001691 res := true;
Robert Griesemer835cd462008-07-07 17:27:14 -07001692 switch P.tok {
1693 case Scanner.CONST: fallthrough;
1694 case Scanner.TYPE: fallthrough;
Robert Griesemerd9d5f3b2008-07-15 09:22:20 -07001695 case Scanner.VAR:
Robert Griesemer835cd462008-07-07 17:27:14 -07001696 P.ParseDeclaration();
Robert Griesemerd9d5f3b2008-07-15 09:22:20 -07001697 case Scanner.FUNC:
1698 // for now we do not allow local function declarations
1699 fallthrough;
Robert Griesemer6acdf3e2008-07-30 13:01:28 -07001700 case Scanner.MUL, Scanner.SEND, Scanner.RECV, Scanner.IDENT, Scanner.LPAREN:
Robert Griesemerf03deb32008-07-24 17:00:58 -07001701 P.ParseSimpleStat();
Robert Griesemer835cd462008-07-07 17:27:14 -07001702 case Scanner.GO:
Robert Griesemer8e4ee002008-07-08 18:37:31 -07001703 P.ParseGoStat();
Robert Griesemer835cd462008-07-07 17:27:14 -07001704 case Scanner.RETURN:
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001705 P.ParseReturnStat();
Robert Griesemer8e4ee002008-07-08 18:37:31 -07001706 case Scanner.BREAK, Scanner.CONTINUE, Scanner.GOTO:
1707 P.ParseControlFlowStat(P.tok);
Robert Griesemer835cd462008-07-07 17:27:14 -07001708 case Scanner.LBRACE:
Robert Griesemer4b0b7d82008-07-29 19:02:49 -07001709 P.ParseBlock(nil);
Robert Griesemer835cd462008-07-07 17:27:14 -07001710 case Scanner.IF:
1711 P.ParseIfStat();
1712 case Scanner.FOR:
1713 P.ParseForStat();
1714 case Scanner.SWITCH:
1715 P.ParseSwitchStat();
1716 case Scanner.RANGE:
Robert Griesemercab94922008-07-09 14:01:17 -07001717 P.ParseRangeStat();
Robert Griesemer835cd462008-07-07 17:27:14 -07001718 case Scanner.SELECT:
Robert Griesemercab94922008-07-09 14:01:17 -07001719 P.ParseSelectStat();
Robert Griesemer835cd462008-07-07 17:27:14 -07001720 default:
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001721 // no statement found
Robert Griesemer415397e2008-07-09 14:48:26 -07001722 res = false;
1723 }
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001724
Robert Griesemer415397e2008-07-09 14:48:26 -07001725 if indent != P.indent {
Robert Griesemer683ded82008-08-11 21:20:42 -07001726 panic("imbalanced tracing code (Statement)");
Robert Griesemer835cd462008-07-07 17:27:14 -07001727 }
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001728 P.Ecart();
Robert Griesemer415397e2008-07-09 14:48:26 -07001729 return res;
Robert Griesemer835cd462008-07-07 17:27:14 -07001730}
1731
1732
Robert Griesemer0cee3022008-07-15 10:05:17 -07001733// ----------------------------------------------------------------------------
1734// Declarations
1735
1736func (P *Parser) ParseImportSpec() {
1737 P.Trace("ImportSpec");
Robert Griesemera6f87792008-07-15 15:37:14 -07001738
Robert Griesemer4b0b7d82008-07-29 19:02:49 -07001739 var obj *Globals.Object = nil;
Robert Griesemer0cee3022008-07-15 10:05:17 -07001740 if P.tok == Scanner.PERIOD {
Robert Griesemer4b0b7d82008-07-29 19:02:49 -07001741 P.Error(P.pos, `"import ." not yet handled properly`);
Robert Griesemer0cee3022008-07-15 10:05:17 -07001742 P.Next();
1743 } else if P.tok == Scanner.IDENT {
Robert Griesemer4b0b7d82008-07-29 19:02:49 -07001744 obj = P.ParseIdentDecl(Object.PACKAGE);
Robert Griesemer0cee3022008-07-15 10:05:17 -07001745 }
Robert Griesemera6f87792008-07-15 15:37:14 -07001746
Robert Griesemer28547612008-08-05 15:20:58 -07001747 if P.semantic_checks && P.tok == Scanner.STRING {
Robert Griesemer4b0b7d82008-07-29 19:02:49 -07001748 // TODO eventually the scanner should strip the quotes
1749 pkg_name := P.val[1 : len(P.val) - 1]; // strip quotes
Robert Griesemerc7fb27f2008-08-11 09:45:40 -07001750 // TODO switch to indirect import once the compiler problems are fixed
1751 //pkg := Import.Import(P.comp, pkg_name);
1752 pkg := P.comp.env.Import(P.comp, pkg_name);
Robert Griesemer4b0b7d82008-07-29 19:02:49 -07001753 if pkg != nil {
Robert Griesemer6dd92ea2008-07-30 21:26:15 -07001754 pno := pkg.obj.pnolev; // preserve pno
Robert Griesemer4b0b7d82008-07-29 19:02:49 -07001755 if obj == nil {
1756 // use original package name
1757 obj = pkg.obj;
Robert Griesemer6dd92ea2008-07-30 21:26:15 -07001758 P.Declare(obj); // this changes (pkg.)obj.pnolev!
Robert Griesemer4b0b7d82008-07-29 19:02:49 -07001759 }
Robert Griesemer6dd92ea2008-07-30 21:26:15 -07001760 obj.pnolev = pno; // correct pno
Robert Griesemer4b0b7d82008-07-29 19:02:49 -07001761 } else {
1762 P.Error(P.pos, `import of "` + pkg_name + `" failed`);
Robert Griesemer0cee3022008-07-15 10:05:17 -07001763 }
1764 P.Next();
1765 } else {
Robert Griesemer4b0b7d82008-07-29 19:02:49 -07001766 P.Expect(Scanner.STRING); // use Expect() error handling
Robert Griesemer835cd462008-07-07 17:27:14 -07001767 }
Robert Griesemera6f87792008-07-15 15:37:14 -07001768
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001769 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -07001770}
1771
1772
Robert Griesemer5fc79192008-07-25 11:27:13 -07001773func (P *Parser) ParseConstSpec(exported bool) {
Robert Griesemer0cee3022008-07-15 10:05:17 -07001774 P.Trace("ConstSpec");
Robert Griesemera6f87792008-07-15 15:37:14 -07001775
1776 list := P.ParseIdentDeclList(Object.CONST);
1777 typ := P.TryType();
1778 if typ != nil {
1779 for p := list.first; p != nil; p = p.next {
Robert Griesemerc6eb85a2008-08-01 14:50:18 -07001780 p.obj.typ = typ;
Robert Griesemera6f87792008-07-15 15:37:14 -07001781 }
1782 }
Robert Griesemerc6eb85a2008-08-01 14:50:18 -07001783
Robert Griesemer0cee3022008-07-15 10:05:17 -07001784 if P.tok == Scanner.ASSIGN {
1785 P.Next();
Robert Griesemer333b70b2008-08-06 17:26:46 -07001786 P.ParseNewExpressionList();
Robert Griesemer835cd462008-07-07 17:27:14 -07001787 }
Robert Griesemera6f87792008-07-15 15:37:14 -07001788
Robert Griesemerc6eb85a2008-08-01 14:50:18 -07001789 if exported {
1790 for p := list.first; p != nil; p = p.next {
1791 p.obj.exported = true;
1792 }
1793 }
1794
Robert Griesemer0cee3022008-07-15 10:05:17 -07001795 P.Ecart();
1796}
1797
1798
Robert Griesemer5fc79192008-07-25 11:27:13 -07001799func (P *Parser) ParseTypeSpec(exported bool) {
Robert Griesemer0cee3022008-07-15 10:05:17 -07001800 P.Trace("TypeSpec");
Robert Griesemerc7fb27f2008-08-11 09:45:40 -07001801
Robert Griesemer40c93a52008-08-11 18:44:41 -07001802 var typ *Globals.Type;
Robert Griesemera6f87792008-07-15 15:37:14 -07001803
Robert Griesemer58ba20b2008-08-11 20:40:37 -07001804 pos, ident := P.ParseIdent(false);
Robert Griesemer40c93a52008-08-11 18:44:41 -07001805 obj := P.Lookup(ident);
Robert Griesemera6f87792008-07-15 15:37:14 -07001806
Robert Griesemer40c93a52008-08-11 18:44:41 -07001807 if !P.comp.flags.sixg && obj != nil {
1808 if obj.typ.form == Type.FORWARD {
1809 // imported forward-declared type
1810 if !exported {
Robert Griesemer683ded82008-08-11 21:20:42 -07001811 panic("foo");
Robert Griesemer40c93a52008-08-11 18:44:41 -07001812 }
1813 } else {
Robert Griesemer683ded82008-08-11 21:20:42 -07001814 panic("bar");
Robert Griesemer40c93a52008-08-11 18:44:41 -07001815 }
1816
1817 } else {
1818 // Immediately after declaration of the type name, the type is
1819 // considered forward-declared. It may be referred to from inside
1820 // the type specification only via a pointer type.
1821 typ = Globals.NewType(Type.FORWARD);
1822 typ.scope = P.top_scope; // not really needed here, but for consistency
1823
1824 obj = Globals.NewObject(pos, Object.TYPE, ident);
1825 obj.exported = exported;
1826 obj.typ = typ;
1827 typ.obj = obj; // primary type object
1828 P.Declare(obj);
1829 }
1830
Robert Griesemer0c374e92008-07-31 10:47:10 -07001831 // If the next token is an identifier and we have a legal program,
1832 // it must be a typename. In that case this declaration introduces
1833 // an alias type.
Robert Griesemerc7fb27f2008-08-11 09:45:40 -07001834 if P.tok == Scanner.IDENT {
1835 typ = Globals.NewType(Type.ALIAS);
1836 elt := P.ParseType(); // we want a complete type - don't shortcut to ParseTypeName()
1837 typ.elt = elt;
1838 if elt.form == Type.ALIAS {
1839 typ.aux = elt.aux; // the base type
1840 } else {
1841 typ.aux = elt;
1842 }
1843 } else {
1844 typ = P.ParseType();
1845 }
Robert Griesemerfce91182008-07-29 12:03:06 -07001846
Robert Griesemerc7fb27f2008-08-11 09:45:40 -07001847 obj.typ = typ;
1848 if typ.obj == nil {
1849 typ.obj = obj; // primary type object
1850 }
1851
1852 // if the type is exported, for now we export all fields
1853 // of structs and interfaces by default
1854 // TODO this needs to change eventually
1855 // Actually in 6g even types referred to are exported - sigh...
1856 if exported && (typ.form == Type.STRUCT || typ.form == Type.INTERFACE) {
1857 for p := typ.scope.entries.first; p != nil; p = p.next {
1858 p.obj.exported = true;
Robert Griesemer28547612008-08-05 15:20:58 -07001859 }
Robert Griesemera6f87792008-07-15 15:37:14 -07001860 }
1861
Robert Griesemer0cee3022008-07-15 10:05:17 -07001862 P.Ecart();
1863}
1864
1865
Robert Griesemer5fc79192008-07-25 11:27:13 -07001866func (P *Parser) ParseVarSpec(exported bool) {
Robert Griesemer0cee3022008-07-15 10:05:17 -07001867 P.Trace("VarSpec");
Robert Griesemera6f87792008-07-15 15:37:14 -07001868
1869 list := P.ParseIdentDeclList(Object.VAR);
Robert Griesemer0cee3022008-07-15 10:05:17 -07001870 if P.tok == Scanner.ASSIGN {
1871 P.Next();
Robert Griesemer333b70b2008-08-06 17:26:46 -07001872 P.ParseNewExpressionList();
Robert Griesemer0cee3022008-07-15 10:05:17 -07001873 } else {
Robert Griesemer9761a6d2008-07-31 13:35:30 -07001874 typ := P.ParseVarType();
Robert Griesemera6f87792008-07-15 15:37:14 -07001875 for p := list.first; p != nil; p = p.next {
Robert Griesemer9761a6d2008-07-31 13:35:30 -07001876 p.obj.typ = typ;
Robert Griesemera6f87792008-07-15 15:37:14 -07001877 }
Robert Griesemer0cee3022008-07-15 10:05:17 -07001878 if P.tok == Scanner.ASSIGN {
1879 P.Next();
Robert Griesemer333b70b2008-08-06 17:26:46 -07001880 P.ParseNewExpressionList();
Robert Griesemer0cee3022008-07-15 10:05:17 -07001881 }
1882 }
Robert Griesemera6f87792008-07-15 15:37:14 -07001883
Robert Griesemerc6eb85a2008-08-01 14:50:18 -07001884 if exported {
1885 for p := list.first; p != nil; p = p.next {
1886 p.obj.exported = true;
1887 }
1888 }
1889
Robert Griesemer0cee3022008-07-15 10:05:17 -07001890 P.Ecart();
1891}
1892
1893
Robert Griesemerfce91182008-07-29 12:03:06 -07001894// TODO With method variables, we wouldn't need this dispatch function.
1895func (P *Parser) ParseSpec(exported bool, keyword int) {
1896 switch keyword {
Robert Griesemer4b0b7d82008-07-29 19:02:49 -07001897 case Scanner.IMPORT: P.ParseImportSpec();
Robert Griesemerfce91182008-07-29 12:03:06 -07001898 case Scanner.CONST: P.ParseConstSpec(exported);
1899 case Scanner.TYPE: P.ParseTypeSpec(exported);
1900 case Scanner.VAR: P.ParseVarSpec(exported);
Robert Griesemer683ded82008-08-11 21:20:42 -07001901 default: panic("UNREACHABLE");
Robert Griesemerfce91182008-07-29 12:03:06 -07001902 }
1903}
1904
1905
1906func (P *Parser) ParseDecl(exported bool, keyword int) {
1907 P.Trace("Decl");
Robert Griesemera6f87792008-07-15 15:37:14 -07001908
Robert Griesemerfce91182008-07-29 12:03:06 -07001909 P.Expect(keyword);
Robert Griesemer0cee3022008-07-15 10:05:17 -07001910 if P.tok == Scanner.LPAREN {
1911 P.Next();
Robert Griesemerf03deb32008-07-24 17:00:58 -07001912 for P.tok == Scanner.IDENT {
Robert Griesemerfce91182008-07-29 12:03:06 -07001913 P.ParseSpec(exported, keyword);
Robert Griesemer0cee3022008-07-15 10:05:17 -07001914 if P.tok != Scanner.RPAREN {
Robert Griesemer4b0b7d82008-07-29 19:02:49 -07001915 // P.Expect(Scanner.SEMICOLON);
1916 P.Optional(Scanner.SEMICOLON); // TODO this seems wrong! (needed for math.go)
Robert Griesemer0cee3022008-07-15 10:05:17 -07001917 }
1918 }
1919 P.Next();
1920 } else {
Robert Griesemerfce91182008-07-29 12:03:06 -07001921 P.ParseSpec(exported, keyword);
Robert Griesemer0cee3022008-07-15 10:05:17 -07001922 }
Robert Griesemera6f87792008-07-15 15:37:14 -07001923
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001924 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -07001925}
1926
1927
Robert Griesemer5fc79192008-07-25 11:27:13 -07001928func (P *Parser) ParseFuncDecl(exported bool) {
Robert Griesemer835cd462008-07-07 17:27:14 -07001929 P.Trace("FuncDecl");
Robert Griesemera6f87792008-07-15 15:37:14 -07001930
Robert Griesemer835cd462008-07-07 17:27:14 -07001931 P.Expect(Scanner.FUNC);
Robert Griesemerc7fb27f2008-08-11 09:45:40 -07001932 pos, ident, typ := P.ParseNamedSignature();
1933 obj := P.DeclareFunc(pos, ident, typ); // need obj later for statements
Robert Griesemer6acdf3e2008-07-30 13:01:28 -07001934 obj.exported = exported;
Robert Griesemer835cd462008-07-07 17:27:14 -07001935 if P.tok == Scanner.SEMICOLON {
1936 // forward declaration
1937 P.Next();
1938 } else {
Robert Griesemer4b0b7d82008-07-29 19:02:49 -07001939 P.ParseBlock(typ.scope);
Robert Griesemer835cd462008-07-07 17:27:14 -07001940 }
Robert Griesemera6f87792008-07-15 15:37:14 -07001941
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001942 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -07001943}
1944
1945
1946func (P *Parser) ParseExportDecl() {
1947 P.Trace("ExportDecl");
Robert Griesemera6f87792008-07-15 15:37:14 -07001948
Robert Griesemer7a799be2008-08-04 15:37:47 -07001949 // TODO This is deprecated syntax and should go away eventually.
1950 // (Also at the moment the syntax is everything goes...)
Robert Griesemer5fc79192008-07-25 11:27:13 -07001951 //P.Expect(Scanner.EXPORT);
Robert Griesemer7a799be2008-08-04 15:37:47 -07001952
1953 if !P.comp.flags.sixg {
1954 P.Error(P.pos, "deprecated export syntax (use -6g to enable)");
1955 }
1956
Robert Griesemerf03deb32008-07-24 17:00:58 -07001957 has_paren := false;
Robert Griesemer33069d392008-07-09 10:16:33 -07001958 if P.tok == Scanner.LPAREN {
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001959 P.Next();
Robert Griesemerf03deb32008-07-24 17:00:58 -07001960 has_paren = true;
1961 }
1962 for P.tok == Scanner.IDENT {
Robert Griesemer58ba20b2008-08-11 20:40:37 -07001963 pos, ident := P.ParseIdent(false);
Robert Griesemerc7fb27f2008-08-11 09:45:40 -07001964 P.exports.AddStr(ident);
Robert Griesemerf03deb32008-07-24 17:00:58 -07001965 P.Optional(Scanner.COMMA); // TODO this seems wrong
1966 }
1967 if has_paren {
1968 P.Expect(Scanner.RPAREN)
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001969 }
Robert Griesemera6f87792008-07-15 15:37:14 -07001970
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001971 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -07001972}
1973
1974
1975func (P *Parser) ParseDeclaration() {
1976 P.Trace("Declaration");
Robert Griesemer415397e2008-07-09 14:48:26 -07001977 indent := P.indent;
Robert Griesemer5fc79192008-07-25 11:27:13 -07001978
1979 exported := false;
1980 if P.tok == Scanner.EXPORT {
Robert Griesemer4b0b7d82008-07-29 19:02:49 -07001981 if P.level == 0 {
1982 exported = true;
1983 } else {
1984 P.Error(P.pos, "local declarations cannot be exported");
1985 }
Robert Griesemer5fc79192008-07-25 11:27:13 -07001986 P.Next();
Robert Griesemer5fc79192008-07-25 11:27:13 -07001987 }
Robert Griesemer4b0b7d82008-07-29 19:02:49 -07001988
Robert Griesemer835cd462008-07-07 17:27:14 -07001989 switch P.tok {
Robert Griesemerfce91182008-07-29 12:03:06 -07001990 case Scanner.CONST, Scanner.TYPE, Scanner.VAR:
1991 P.ParseDecl(exported, P.tok);
Robert Griesemer835cd462008-07-07 17:27:14 -07001992 case Scanner.FUNC:
Robert Griesemer5fc79192008-07-25 11:27:13 -07001993 P.ParseFuncDecl(exported);
Robert Griesemer835cd462008-07-07 17:27:14 -07001994 case Scanner.EXPORT:
Robert Griesemer5fc79192008-07-25 11:27:13 -07001995 if exported {
1996 P.Error(P.pos, "cannot mark export declaration for export");
1997 }
1998 P.Next();
Robert Griesemer835cd462008-07-07 17:27:14 -07001999 P.ParseExportDecl();
2000 default:
Robert Griesemer5fc79192008-07-25 11:27:13 -07002001 if exported && (P.tok == Scanner.IDENT || P.tok == Scanner.LPAREN) {
2002 P.ParseExportDecl();
2003 } else {
2004 P.Error(P.pos, "declaration expected");
2005 P.Next(); // make progress
2006 }
Robert Griesemer835cd462008-07-07 17:27:14 -07002007 }
Robert Griesemer5fc79192008-07-25 11:27:13 -07002008
Robert Griesemer415397e2008-07-09 14:48:26 -07002009 if indent != P.indent {
Robert Griesemer683ded82008-08-11 21:20:42 -07002010 panic("imbalanced tracing code (Declaration)");
Robert Griesemer415397e2008-07-09 14:48:26 -07002011 }
Robert Griesemerc40be3b2008-07-08 16:39:04 -07002012 P.Ecart();
2013}
2014
2015
Robert Griesemer0cee3022008-07-15 10:05:17 -07002016// ----------------------------------------------------------------------------
2017// Program
Robert Griesemer835cd462008-07-07 17:27:14 -07002018
Robert Griesemerc7fb27f2008-08-11 09:45:40 -07002019func (P *Parser) ResolveForwardTypes() {
Robert Griesemer1f465132008-07-30 17:36:03 -07002020 if !P.semantic_checks {
Robert Griesemerfce91182008-07-29 12:03:06 -07002021 return;
2022 }
2023
Robert Griesemerc7fb27f2008-08-11 09:45:40 -07002024 for p := P.forward_types.first; p != nil; p = p.next {
Robert Griesemerfce91182008-07-29 12:03:06 -07002025 typ := p.typ;
2026 if typ.form != Type.POINTER {
Robert Griesemer683ded82008-08-11 21:20:42 -07002027 panic("unresolved types should be pointers only");
Robert Griesemerfce91182008-07-29 12:03:06 -07002028 }
Robert Griesemerc7fb27f2008-08-11 09:45:40 -07002029
2030 elt := typ.elt;
2031 if typ.elt.form != Type.FORWARD {
Robert Griesemer683ded82008-08-11 21:20:42 -07002032 panic("unresolved pointer should point to forward type");
Robert Griesemerfce91182008-07-29 12:03:06 -07002033 }
Robert Griesemerc7fb27f2008-08-11 09:45:40 -07002034
2035 obj := elt.obj;
2036 if obj.typ == elt {
2037 // actual forward declaration (as opposed to forward types introduced
2038 // during type declaration) - need to lookup the actual type object
2039 var elt_obj *Globals.Object;
2040 for scope := elt.scope; scope != nil && elt_obj == nil; scope = scope.parent {
2041 elt_obj = scope.Lookup(obj.ident);
2042 }
2043 // update the type object if we found one
2044 if elt_obj != nil {
2045 if elt_obj.kind == Object.TYPE {
2046 obj = elt_obj;
2047 } else {
2048 P.Error(obj.pos, `"` + obj.ident + `" does not denote a type`);
2049 }
2050 }
2051 }
2052
2053 // update the pointer type
Robert Griesemerfce91182008-07-29 12:03:06 -07002054 typ.elt = obj.typ;
Robert Griesemerc7fb27f2008-08-11 09:45:40 -07002055
2056 // TODO as long as we don't *use* a forward type, we are ok
2057 // => consider not reporting this as an error
2058 // (in a real forward declaration, the corresponding objects are not in a scope
2059 // and have incorrect pnolev)
2060 if typ.elt.form == Type.FORWARD {
2061 P.Error(obj.pos, `"` + obj.ident + `" is not declared after forward declaration`);
Robert Griesemerfce91182008-07-29 12:03:06 -07002062 }
2063 }
2064}
2065
2066
Robert Griesemerc3e9c7d2008-07-17 18:02:10 -07002067func (P *Parser) MarkExports() {
Robert Griesemer1f465132008-07-30 17:36:03 -07002068 if !P.semantic_checks {
Robert Griesemerc3e9c7d2008-07-17 18:02:10 -07002069 return;
2070 }
2071
2072 scope := P.top_scope;
2073 for p := P.exports.first; p != nil; p = p.next {
2074 obj := scope.Lookup(p.str);
2075 if obj != nil {
Robert Griesemerfce91182008-07-29 12:03:06 -07002076 obj.exported = true;
Robert Griesemerc3e9c7d2008-07-17 18:02:10 -07002077 // For now we export deep
2078 // TODO this should change eventually - we need selective export
2079 if obj.kind == Object.TYPE {
2080 typ := obj.typ;
2081 if typ.form == Type.STRUCT || typ.form == Type.INTERFACE {
2082 scope := typ.scope;
2083 for p := scope.entries.first; p != nil; p = p.next {
Robert Griesemerfce91182008-07-29 12:03:06 -07002084 p.obj.exported = true;
Robert Griesemerc3e9c7d2008-07-17 18:02:10 -07002085 }
2086 }
2087 }
2088 } else {
2089 // TODO need to report proper src position
Robert Griesemer1f465132008-07-30 17:36:03 -07002090 P.Error(-1, `"` + p.str + `" is not declared - cannot be exported`);
Robert Griesemerc3e9c7d2008-07-17 18:02:10 -07002091 }
2092 }
2093}
2094
2095
Robert Griesemer835cd462008-07-07 17:27:14 -07002096func (P *Parser) ParseProgram() {
2097 P.Trace("Program");
Robert Griesemerc3e9c7d2008-07-17 18:02:10 -07002098
Robert Griesemer230230c2008-07-14 18:06:41 -07002099 P.OpenScope();
Robert Griesemer835cd462008-07-07 17:27:14 -07002100 P.Expect(Scanner.PACKAGE);
Robert Griesemer71d50b82008-08-04 10:19:36 -07002101 obj := P.ParseIdentDecl(Object.PACKAGE);
Robert Griesemerafbf7172008-07-10 18:05:00 -07002102 P.Optional(Scanner.SEMICOLON);
2103
Robert Griesemer687f3872008-08-05 18:52:37 -07002104 { P.OpenScope();
2105 if P.level != 0 {
Robert Griesemer683ded82008-08-11 21:20:42 -07002106 panic("incorrect scope level");
Robert Griesemer6dd92ea2008-07-30 21:26:15 -07002107 }
Robert Griesemer997a9422008-08-04 13:27:05 -07002108
2109 P.comp.Insert(Globals.NewPackage(P.S.filename, obj, P.top_scope));
2110 if P.comp.pkg_ref != 1 {
Robert Griesemer683ded82008-08-11 21:20:42 -07002111 panic("should have exactly one package now");
Robert Griesemer997a9422008-08-04 13:27:05 -07002112 }
2113
Robert Griesemer230230c2008-07-14 18:06:41 -07002114 for P.tok == Scanner.IMPORT {
Robert Griesemer4b0b7d82008-07-29 19:02:49 -07002115 P.ParseDecl(false, Scanner.IMPORT);
Robert Griesemer230230c2008-07-14 18:06:41 -07002116 P.Optional(Scanner.SEMICOLON);
2117 }
2118
2119 for P.tok != Scanner.EOF {
2120 P.ParseDeclaration();
2121 P.Optional(Scanner.SEMICOLON);
2122 }
Robert Griesemerc3e9c7d2008-07-17 18:02:10 -07002123
Robert Griesemerc7fb27f2008-08-11 09:45:40 -07002124 P.ResolveForwardTypes();
Robert Griesemerc3e9c7d2008-07-17 18:02:10 -07002125 P.MarkExports();
Robert Griesemer687f3872008-08-05 18:52:37 -07002126
Robert Griesemer6dd92ea2008-07-30 21:26:15 -07002127 if P.level != 0 {
Robert Griesemer683ded82008-08-11 21:20:42 -07002128 panic("incorrect scope level");
Robert Griesemer6dd92ea2008-07-30 21:26:15 -07002129 }
Robert Griesemer687f3872008-08-05 18:52:37 -07002130 P.CloseScope();
Robert Griesemer835cd462008-07-07 17:27:14 -07002131 }
Robert Griesemerafbf7172008-07-10 18:05:00 -07002132
Robert Griesemer230230c2008-07-14 18:06:41 -07002133 P.CloseScope();
Robert Griesemerc40be3b2008-07-08 16:39:04 -07002134 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -07002135}