blob: 7d474275e48ec0fcdc63873517b2c20dd5b6b636 [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
7import Scanner "scanner"
Robert Griesemer230230c2008-07-14 18:06:41 -07008import Globals "globals"
Robert Griesemera6f87792008-07-15 15:37:14 -07009import Object "object"
10import Type "type"
Robert Griesemer230230c2008-07-14 18:06:41 -070011import Universe "universe"
Robert Griesemer5a90ede2008-07-18 17:18:29 -070012import AST "ast"
Robert Griesemer835cd462008-07-07 17:27:14 -070013
14
Robert Griesemera6f87792008-07-15 15:37:14 -070015// So I can submit and have a running parser for now...
16const EnableSemanticTests = false;
17
18
Robert Griesemer835cd462008-07-07 17:27:14 -070019export Parser
20type Parser struct {
Robert Griesemerc3e9c7d2008-07-17 18:02:10 -070021 comp *Globals.Compilation;
Robert Griesemerc40be3b2008-07-08 16:39:04 -070022 verbose, indent int;
Robert Griesemer835cd462008-07-07 17:27:14 -070023 S *Scanner.Scanner;
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 Griesemer230230c2008-07-14 18:06:41 -070031 top_scope *Globals.Scope;
Robert Griesemerfce91182008-07-29 12:03:06 -070032 undef_types *Globals.List;
Robert Griesemerc3e9c7d2008-07-17 18:02:10 -070033 exports *Globals.List;
Robert Griesemer835cd462008-07-07 17:27:14 -070034}
35
36
Robert Griesemera6f87792008-07-15 15:37:14 -070037// ----------------------------------------------------------------------------
38// Support functions
39
Robert Griesemerc40be3b2008-07-08 16:39:04 -070040func (P *Parser) PrintIndent() {
41 for i := P.indent; i > 0; i-- {
Robert Griesemer415397e2008-07-09 14:48:26 -070042 print ". ";
Robert Griesemerc40be3b2008-07-08 16:39:04 -070043 }
44}
45
46
47func (P *Parser) Trace(msg string) {
48 if P.verbose > 0 {
49 P.PrintIndent();
50 print msg, " {\n";
51 P.indent++;
52 }
53}
54
55
56func (P *Parser) Ecart() {
57 if P.verbose > 0 {
58 P.indent--;
59 P.PrintIndent();
60 print "}\n";
61 }
62}
63
64
65func (P *Parser) Next() {
Robert Griesemer5a90ede2008-07-18 17:18:29 -070066 P.tok, P.pos, P.val = P.S.Scan();
Robert Griesemerc40be3b2008-07-08 16:39:04 -070067 if P.verbose > 1 {
68 P.PrintIndent();
Robert Griesemer5a90ede2008-07-18 17:18:29 -070069 print "[", P.pos, "] ", Scanner.TokenName(P.tok), "\n";
Robert Griesemerc40be3b2008-07-08 16:39:04 -070070 }
71}
72
73
Robert Griesemerc3e9c7d2008-07-17 18:02:10 -070074func (P *Parser) Open(comp *Globals.Compilation, S *Scanner.Scanner, verbose int) {
75 P.comp = comp;
Robert Griesemer835cd462008-07-07 17:27:14 -070076 P.verbose = verbose;
Robert Griesemerc40be3b2008-07-08 16:39:04 -070077 P.indent = 0;
Robert Griesemer835cd462008-07-07 17:27:14 -070078 P.S = S;
79 P.Next();
Robert Griesemer230230c2008-07-14 18:06:41 -070080 P.top_scope = Universe.scope;
Robert Griesemerfce91182008-07-29 12:03:06 -070081 P.undef_types = Globals.NewList();
Robert Griesemerc3e9c7d2008-07-17 18:02:10 -070082 P.exports = Globals.NewList();
Robert Griesemer835cd462008-07-07 17:27:14 -070083}
84
85
Robert Griesemer8be580e2008-07-10 14:42:33 -070086func (P *Parser) Error(pos int, msg string) {
87 P.S.Error(pos, msg);
Robert Griesemer835cd462008-07-07 17:27:14 -070088}
89
90
91func (P *Parser) Expect(tok int) {
Robert Griesemera6f87792008-07-15 15:37:14 -070092 if P.tok != tok {
Robert Griesemer5a90ede2008-07-18 17:18:29 -070093 P.Error(P.pos, "expected '" + Scanner.TokenName(tok) + "', found '" + Scanner.TokenName(P.tok) + "'");
Robert Griesemer835cd462008-07-07 17:27:14 -070094 }
Robert Griesemera6f87792008-07-15 15:37:14 -070095 P.Next(); // make progress in any case
Robert Griesemer835cd462008-07-07 17:27:14 -070096}
97
98
Robert Griesemer8e4ee002008-07-08 18:37:31 -070099func (P *Parser) Optional(tok int) {
100 if P.tok == tok {
101 P.Next();
102 }
103}
104
105
Robert Griesemer230230c2008-07-14 18:06:41 -0700106// ----------------------------------------------------------------------------
Robert Griesemera6f87792008-07-15 15:37:14 -0700107// Scopes
Robert Griesemer230230c2008-07-14 18:06:41 -0700108
109func (P *Parser) OpenScope() {
110 P.top_scope = Globals.NewScope(P.top_scope);
111}
112
113
114func (P *Parser) CloseScope() {
115 P.top_scope = P.top_scope.parent;
116}
117
118
119func (P *Parser) Lookup(ident string) *Globals.Object {
120 for scope := P.top_scope; scope != nil; scope = scope.parent {
121 obj := scope.Lookup(ident);
122 if obj != nil {
123 return obj;
124 }
125 }
126 return nil;
127}
128
129
130func (P *Parser) DeclareInScope(scope *Globals.Scope, obj *Globals.Object) {
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700131 if EnableSemanticTests && scope.Lookup(obj.ident) != nil {
Robert Griesemera6f87792008-07-15 15:37:14 -0700132 P.Error(obj.pos, `"` + obj.ident + `" is declared already`);
Robert Griesemer230230c2008-07-14 18:06:41 -0700133 return; // don't insert it into the scope
134 }
135 scope.Insert(obj);
136}
137
138
139func (P *Parser) Declare(obj *Globals.Object) {
140 P.DeclareInScope(P.top_scope, obj);
141}
142
143
144// ----------------------------------------------------------------------------
Robert Griesemer0cee3022008-07-15 10:05:17 -0700145// Common productions
146
Robert Griesemer230230c2008-07-14 18:06:41 -0700147
Robert Griesemera6f87792008-07-15 15:37:14 -0700148func (P *Parser) TryType() *Globals.Type;
Robert Griesemer835cd462008-07-07 17:27:14 -0700149func (P *Parser) ParseExpression();
Robert Griesemer0cee3022008-07-15 10:05:17 -0700150func (P *Parser) TryStatement() bool;
151func (P *Parser) ParseDeclaration();
Robert Griesemer835cd462008-07-07 17:27:14 -0700152
153
Robert Griesemera6f87792008-07-15 15:37:14 -0700154func (P *Parser) ParseIdent() string {
155 P.Trace("Ident");
156
157 ident := "";
158 if P.tok == Scanner.IDENT {
Robert Griesemer5a90ede2008-07-18 17:18:29 -0700159 ident = P.val;
Robert Griesemera6f87792008-07-15 15:37:14 -0700160 if P.verbose > 0 {
161 P.PrintIndent();
162 print "Ident = \"", ident, "\"\n";
163 }
164 P.Next();
165 } else {
166 P.Expect(Scanner.IDENT); // use Expect() error handling
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700167 }
Robert Griesemera6f87792008-07-15 15:37:14 -0700168
169 P.Ecart();
170 return ident;
171}
172
173
174func (P *Parser) ParseIdentDecl(kind int) *Globals.Object {
175 P.Trace("IdentDecl");
176
Robert Griesemer5a90ede2008-07-18 17:18:29 -0700177 pos := P.pos;
Robert Griesemera6f87792008-07-15 15:37:14 -0700178 obj := Globals.NewObject(pos, kind, P.ParseIdent());
179 P.Declare(obj);
180
181 P.Ecart();
182 return obj;
183}
184
185
186func (P *Parser) ParseIdentDeclList(kind int) *Globals.List {
187 P.Trace("IdentDeclList");
188
189 list := Globals.NewList();
190 list.AddObj(P.ParseIdentDecl(kind));
191 for P.tok == Scanner.COMMA {
192 P.Next();
193 list.AddObj(P.ParseIdentDecl(kind));
194 }
195
196 P.Ecart();
197 return list;
Robert Griesemer835cd462008-07-07 17:27:14 -0700198}
199
200
201func (P *Parser) ParseIdentList() {
202 P.Trace("IdentList");
203 P.ParseIdent();
204 for P.tok == Scanner.COMMA {
205 P.Next();
206 P.ParseIdent();
207 }
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700208 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700209}
210
211
Robert Griesemerf03deb32008-07-24 17:00:58 -0700212func (P *Parser) ParseQualifiedIdent(pos int, ident string) *Globals.Object {
Robert Griesemer835cd462008-07-07 17:27:14 -0700213 P.Trace("QualifiedIdent");
Robert Griesemera6f87792008-07-15 15:37:14 -0700214
Robert Griesemerf03deb32008-07-24 17:00:58 -0700215 if pos < 0 {
216 pos = P.pos;
217 ident = P.ParseIdent();
218 }
219
Robert Griesemera6f87792008-07-15 15:37:14 -0700220 if EnableSemanticTests {
Robert Griesemera6f87792008-07-15 15:37:14 -0700221 obj := P.Lookup(ident);
222 if obj == nil {
223 P.Error(pos, `"` + ident + `" is not declared`);
224 obj = Globals.NewObject(pos, Object.BAD, ident);
225 }
226
227 if obj.kind == Object.PACKAGE && P.tok == Scanner.PERIOD {
228 panic "Qualified ident not complete yet";
229 P.Next();
230 P.ParseIdent();
231 }
232 P.Ecart();
233 return obj;
234
235 } else {
Robert Griesemera6f87792008-07-15 15:37:14 -0700236 if P.tok == Scanner.PERIOD {
237 P.Next();
238 P.ParseIdent();
239 }
240 P.Ecart();
241 return nil;
Robert Griesemer835cd462008-07-07 17:27:14 -0700242 }
243}
244
245
Robert Griesemer0cee3022008-07-15 10:05:17 -0700246// ----------------------------------------------------------------------------
247// Types
Robert Griesemer835cd462008-07-07 17:27:14 -0700248
Robert Griesemerfce91182008-07-29 12:03:06 -0700249func (P *Parser) ParseType() *Globals.Type {
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700250 P.Trace("Type");
Robert Griesemera6f87792008-07-15 15:37:14 -0700251
252 typ := P.TryType();
253 if typ == nil {
Robert Griesemer5a90ede2008-07-18 17:18:29 -0700254 P.Error(P.pos, "type expected");
Robert Griesemera6f87792008-07-15 15:37:14 -0700255 typ = Universe.bad_t;
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700256 }
Robert Griesemera6f87792008-07-15 15:37:14 -0700257
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700258 P.Ecart();
Robert Griesemera6f87792008-07-15 15:37:14 -0700259 return typ;
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700260}
261
262
Robert Griesemera6f87792008-07-15 15:37:14 -0700263func (P *Parser) ParseTypeName() *Globals.Type {
Robert Griesemer0cee3022008-07-15 10:05:17 -0700264 P.Trace("TypeName");
Robert Griesemera6f87792008-07-15 15:37:14 -0700265
266 if EnableSemanticTests {
Robert Griesemerfce91182008-07-29 12:03:06 -0700267 pos := P.pos;
Robert Griesemerf03deb32008-07-24 17:00:58 -0700268 obj := P.ParseQualifiedIdent(-1, "");
Robert Griesemera6f87792008-07-15 15:37:14 -0700269 typ := obj.typ;
270 if obj.kind != Object.TYPE {
Robert Griesemerfce91182008-07-29 12:03:06 -0700271 P.Error(pos, "qualified identifier does not denote a type");
Robert Griesemera6f87792008-07-15 15:37:14 -0700272 typ = Universe.bad_t;
273 }
274 P.Ecart();
275 return typ;
276 } else {
Robert Griesemerf03deb32008-07-24 17:00:58 -0700277 P.ParseQualifiedIdent(-1, "");
Robert Griesemera6f87792008-07-15 15:37:14 -0700278 P.Ecart();
279 return Universe.bad_t;
280 }
Robert Griesemer0cee3022008-07-15 10:05:17 -0700281}
282
283
Robert Griesemera6f87792008-07-15 15:37:14 -0700284func (P *Parser) ParseArrayType() *Globals.Type {
Robert Griesemer835cd462008-07-07 17:27:14 -0700285 P.Trace("ArrayType");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700286
Robert Griesemer835cd462008-07-07 17:27:14 -0700287 P.Expect(Scanner.LBRACK);
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700288 typ := Globals.NewType(Type.ARRAY);
Robert Griesemer835cd462008-07-07 17:27:14 -0700289 if P.tok != Scanner.RBRACK {
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700290 // TODO set typ.len_
Robert Griesemer835cd462008-07-07 17:27:14 -0700291 P.ParseExpression();
292 }
293 P.Expect(Scanner.RBRACK);
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700294 typ.elt = P.ParseType();
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700295 P.Ecart();
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700296
297 return typ;
Robert Griesemer835cd462008-07-07 17:27:14 -0700298}
299
300
Robert Griesemera6f87792008-07-15 15:37:14 -0700301func (P *Parser) ParseChannelType() *Globals.Type {
Robert Griesemer835cd462008-07-07 17:27:14 -0700302 P.Trace("ChannelType");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700303
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700304 P.Expect(Scanner.CHAN);
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700305 typ := Globals.NewType(Type.CHANNEL);
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700306 switch P.tok {
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700307 case Scanner.SEND:
308 typ.flags = Type.SEND;
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700309 P.Next();
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700310 case Scanner.RECV:
311 typ.flags = Type.RECV;
312 P.Next();
313 default:
314 typ.flags = Type.SEND + Type.RECV;
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700315 }
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700316 typ.elt = P.ParseType();
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700317 P.Ecart();
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700318
319 return typ;
320}
321
322
323func (P *Parser) ParseVarDeclList() {
324 P.Trace("VarDeclList");
325
326 list := P.ParseIdentDeclList(Object.VAR);
327 typ := P.ParseType(); // TODO should check completeness of types
328 for p := list.first; p != nil; p = p.next {
329 p.obj.typ = typ; // TODO should use/have set_type()
330 }
331
332 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700333}
334
335
Robert Griesemer835cd462008-07-07 17:27:14 -0700336func (P *Parser) ParseParameterSection() {
337 P.Trace("ParameterSection");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700338 P.ParseVarDeclList();
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700339 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700340}
341
342
343func (P *Parser) ParseParameterList() {
344 P.Trace("ParameterList");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700345
Robert Griesemer835cd462008-07-07 17:27:14 -0700346 P.ParseParameterSection();
347 for P.tok == Scanner.COMMA {
348 P.Next();
349 P.ParseParameterSection();
350 }
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700351
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700352 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700353}
354
355
356func (P *Parser) ParseParameters() {
357 P.Trace("Parameters");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700358
Robert Griesemer835cd462008-07-07 17:27:14 -0700359 P.Expect(Scanner.LPAREN);
360 if P.tok != Scanner.RPAREN {
361 P.ParseParameterList();
362 }
363 P.Expect(Scanner.RPAREN);
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700364
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700365 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700366}
367
368
Robert Griesemer1e9adf82008-07-09 10:45:04 -0700369func (P *Parser) TryResult() bool {
370 P.Trace("Result (try)");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700371
Robert Griesemer1e9adf82008-07-09 10:45:04 -0700372 res := false;
Robert Griesemer835cd462008-07-07 17:27:14 -0700373 if P.tok == Scanner.LPAREN {
374 // TODO: here we allow empty returns - should proably fix this
375 P.ParseParameters();
Robert Griesemer1e9adf82008-07-09 10:45:04 -0700376 res = true;
Robert Griesemer835cd462008-07-07 17:27:14 -0700377 } else {
Robert Griesemera6f87792008-07-15 15:37:14 -0700378 res = P.TryType() != nil;
Robert Griesemer835cd462008-07-07 17:27:14 -0700379 }
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700380 P.Ecart();
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700381
Robert Griesemer1e9adf82008-07-09 10:45:04 -0700382 return res;
383}
384
385
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700386func MakeFunctionType(sig *Globals.Scope, p0, r0 int, check_recv bool) *Globals.Type {
387 // Determine if we have a receiver or not.
388 if p0 > 0 && check_recv {
389 // method
390 if p0 != 1 {
391 panic "p0 != 1";
392 }
393 }
394 typ := Globals.NewType(Type.FUNCTION);
395 if p0 == 0 {
396 typ.flags = 0;
397 } else {
398 typ.flags = Type.RECV;
399 }
400 typ.len_ = r0 - p0;
401 typ.scope = sig;
402 return typ;
403}
404
405
Robert Griesemer1e9adf82008-07-09 10:45:04 -0700406// Anonymous signatures
407//
408// (params)
409// (params) type
410// (params) (results)
411// (recv) . (params)
412// (recv) . (params) type
413// (recv) . (params) (results)
414
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700415func (P *Parser) ParseAnonymousSignature() *Globals.Type {
Robert Griesemer1e9adf82008-07-09 10:45:04 -0700416 P.Trace("AnonymousSignature");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700417
Robert Griesemer230230c2008-07-14 18:06:41 -0700418 P.OpenScope();
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700419 sig := P.top_scope;
420 p0 := 0;
421
422 recv_pos := P.pos;
Robert Griesemer1e9adf82008-07-09 10:45:04 -0700423 P.ParseParameters();
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700424
Robert Griesemer1e9adf82008-07-09 10:45:04 -0700425 if P.tok == Scanner.PERIOD {
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700426 p0 = sig.entries.len_;
427 if (p0 != 1) {
428 P.Error(recv_pos, "must have exactly one receiver")
429 panic "UNIMPLEMENTED";
430 // TODO do something useful here
431 }
Robert Griesemer1e9adf82008-07-09 10:45:04 -0700432 P.Next();
433 P.ParseParameters();
434 }
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700435
436 r0 := sig.entries.len_;
Robert Griesemer1e9adf82008-07-09 10:45:04 -0700437 P.TryResult();
Robert Griesemer230230c2008-07-14 18:06:41 -0700438 P.CloseScope();
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700439
Robert Griesemer1e9adf82008-07-09 10:45:04 -0700440 P.Ecart();
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700441 return MakeFunctionType(sig, p0, r0, true);
Robert Griesemer835cd462008-07-07 17:27:14 -0700442}
443
444
445// Named signatures
446//
447// name (params)
448// name (params) type
449// name (params) (results)
450// (recv) name (params)
451// (recv) name (params) type
452// (recv) name (params) (results)
453
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700454func (P *Parser) ParseNamedSignature() (name string, typ *Globals.Type) {
Robert Griesemer835cd462008-07-07 17:27:14 -0700455 P.Trace("NamedSignature");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700456
Robert Griesemer230230c2008-07-14 18:06:41 -0700457 P.OpenScope();
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700458 sig := P.top_scope;
459 p0 := 0;
460
Robert Griesemer835cd462008-07-07 17:27:14 -0700461 if P.tok == Scanner.LPAREN {
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700462 recv_pos := P.pos;
Robert Griesemer835cd462008-07-07 17:27:14 -0700463 P.ParseParameters();
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700464 p0 = sig.entries.len_;
465 if (p0 != 1) {
466 print "p0 = ", p0, "\n";
467 P.Error(recv_pos, "must have exactly one receiver")
468 panic "UNIMPLEMENTED";
469 // TODO do something useful here
470 }
Robert Griesemer835cd462008-07-07 17:27:14 -0700471 }
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700472
473 name = P.ParseIdent();
474
Robert Griesemer835cd462008-07-07 17:27:14 -0700475 P.ParseParameters();
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700476
477 r0 := sig.entries.len_;
Robert Griesemer1e9adf82008-07-09 10:45:04 -0700478 P.TryResult();
Robert Griesemer230230c2008-07-14 18:06:41 -0700479 P.CloseScope();
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700480
Robert Griesemerfda1d162008-07-23 16:59:06 -0700481 P.Ecart();
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700482 return name, MakeFunctionType(sig, p0, r0, true);
Robert Griesemer835cd462008-07-07 17:27:14 -0700483}
484
485
Robert Griesemera6f87792008-07-15 15:37:14 -0700486func (P *Parser) ParseFunctionType() *Globals.Type {
Robert Griesemer0cee3022008-07-15 10:05:17 -0700487 P.Trace("FunctionType");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700488
Robert Griesemer0cee3022008-07-15 10:05:17 -0700489 P.Expect(Scanner.FUNC);
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700490 typ := P.ParseAnonymousSignature();
491
Robert Griesemer0cee3022008-07-15 10:05:17 -0700492 P.Ecart();
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700493 return typ;
Robert Griesemer0cee3022008-07-15 10:05:17 -0700494}
495
496
497func (P *Parser) ParseMethodDecl() {
498 P.Trace("MethodDecl");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700499
Robert Griesemer0cee3022008-07-15 10:05:17 -0700500 P.ParseIdent();
501 P.ParseParameters();
502 P.TryResult();
503 P.Optional(Scanner.SEMICOLON);
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700504
Robert Griesemer0cee3022008-07-15 10:05:17 -0700505 P.Ecart();
506}
507
508
Robert Griesemera6f87792008-07-15 15:37:14 -0700509func (P *Parser) ParseInterfaceType() *Globals.Type {
Robert Griesemer0cee3022008-07-15 10:05:17 -0700510 P.Trace("InterfaceType");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700511
Robert Griesemer0cee3022008-07-15 10:05:17 -0700512 P.Expect(Scanner.INTERFACE);
513 P.Expect(Scanner.LBRACE);
514 P.OpenScope();
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700515 typ := Globals.NewType(Type.INTERFACE);
516 typ.scope = P.top_scope;
Robert Griesemerf03deb32008-07-24 17:00:58 -0700517 for P.tok == Scanner.IDENT {
Robert Griesemer0cee3022008-07-15 10:05:17 -0700518 P.ParseMethodDecl();
519 }
520 P.CloseScope();
Robert Griesemerf03deb32008-07-24 17:00:58 -0700521 P.Expect(Scanner.RBRACE);
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700522
Robert Griesemer0cee3022008-07-15 10:05:17 -0700523 P.Ecart();
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700524 return typ;
Robert Griesemer0cee3022008-07-15 10:05:17 -0700525}
526
527
Robert Griesemera6f87792008-07-15 15:37:14 -0700528func (P *Parser) ParseMapType() *Globals.Type {
Robert Griesemer0cee3022008-07-15 10:05:17 -0700529 P.Trace("MapType");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700530
Robert Griesemer0cee3022008-07-15 10:05:17 -0700531 P.Expect(Scanner.MAP);
532 P.Expect(Scanner.LBRACK);
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700533 typ := Globals.NewType(Type.MAP);
534 typ.key = P.ParseType();
Robert Griesemer0cee3022008-07-15 10:05:17 -0700535 P.Expect(Scanner.RBRACK);
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700536 typ.elt = P.ParseType();
Robert Griesemer0cee3022008-07-15 10:05:17 -0700537 P.Ecart();
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700538
539 return typ;
Robert Griesemer0cee3022008-07-15 10:05:17 -0700540}
541
542
543func (P *Parser) ParseFieldDecl() {
544 P.Trace("FieldDecl");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700545 P.ParseVarDeclList();
Robert Griesemer0cee3022008-07-15 10:05:17 -0700546 P.Ecart();
547}
548
549
Robert Griesemera6f87792008-07-15 15:37:14 -0700550func (P *Parser) ParseStructType() *Globals.Type {
Robert Griesemer0cee3022008-07-15 10:05:17 -0700551 P.Trace("StructType");
Robert Griesemera6f87792008-07-15 15:37:14 -0700552
Robert Griesemer0cee3022008-07-15 10:05:17 -0700553 P.Expect(Scanner.STRUCT);
554 P.Expect(Scanner.LBRACE);
555 P.OpenScope();
Robert Griesemera6f87792008-07-15 15:37:14 -0700556 typ := Globals.NewType(Type.STRUCT);
557 typ.scope = P.top_scope;
558 for P.tok == Scanner.IDENT {
Robert Griesemer0cee3022008-07-15 10:05:17 -0700559 P.ParseFieldDecl();
560 if P.tok != Scanner.RBRACE {
561 P.Expect(Scanner.SEMICOLON);
562 }
563 }
564 P.Optional(Scanner.SEMICOLON);
565 P.CloseScope();
566 P.Expect(Scanner.RBRACE);
Robert Griesemera6f87792008-07-15 15:37:14 -0700567
Robert Griesemer0cee3022008-07-15 10:05:17 -0700568 P.Ecart();
Robert Griesemera6f87792008-07-15 15:37:14 -0700569 return typ;
Robert Griesemer0cee3022008-07-15 10:05:17 -0700570}
571
572
Robert Griesemera6f87792008-07-15 15:37:14 -0700573func (P *Parser) ParsePointerType() *Globals.Type {
Robert Griesemer0cee3022008-07-15 10:05:17 -0700574 P.Trace("PointerType");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700575
Robert Griesemer0cee3022008-07-15 10:05:17 -0700576 P.Expect(Scanner.MUL);
Robert Griesemerfce91182008-07-29 12:03:06 -0700577 typ := Globals.NewType(Type.POINTER);
578
579 if EnableSemanticTests {
580 if P.tok == Scanner.IDENT {
581 if P.Lookup(P.val) == nil {
582 // implicit forward declaration
583 // TODO very problematic: in which scope should the
584 // type object be declared? It's different if this
585 // is inside a struct or say in a var declaration.
586 // This code is only here for "compatibility" with 6g.
587 pos := P.pos;
588 obj := Globals.NewObject(pos, Object.TYPE, P.ParseIdent());
589 obj.typ = Globals.NewType(Type.UNDEF);
590 obj.typ.obj = obj; // primary type object
591 typ.elt = obj.typ;
592 // TODO obj should be declared, but scope is not clear
593 } else {
594 // type name
595 // (ParseType() doesn't permit incomplete types,
596 // so call ParseTypeName() here)
597 typ.elt = P.ParseTypeName();
598 }
599 } else {
600 typ.elt = P.ParseType();
601 }
602
603 // collect undefined pointer types
604 if typ.elt.form == Type.UNDEF {
605 P.undef_types.AddTyp(typ);
606 }
607
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700608 } else {
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700609 typ.elt = P.ParseType();
610 }
611
Robert Griesemerfce91182008-07-29 12:03:06 -0700612 P.Ecart();
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700613 return typ;
Robert Griesemer0cee3022008-07-15 10:05:17 -0700614}
615
616
Robert Griesemera6f87792008-07-15 15:37:14 -0700617// Returns nil if no type was found.
618func (P *Parser) TryType() *Globals.Type {
Robert Griesemer0cee3022008-07-15 10:05:17 -0700619 P.Trace("Type (try)");
Robert Griesemera6f87792008-07-15 15:37:14 -0700620
Robert Griesemerfce91182008-07-29 12:03:06 -0700621 pos := P.pos;
Robert Griesemera6f87792008-07-15 15:37:14 -0700622 var typ *Globals.Type = nil;
Robert Griesemer0cee3022008-07-15 10:05:17 -0700623 switch P.tok {
Robert Griesemera6f87792008-07-15 15:37:14 -0700624 case Scanner.IDENT: typ = P.ParseTypeName();
625 case Scanner.LBRACK: typ = P.ParseArrayType();
626 case Scanner.CHAN: typ = P.ParseChannelType();
627 case Scanner.INTERFACE: typ = P.ParseInterfaceType();
628 case Scanner.FUNC: typ = P.ParseFunctionType();
629 case Scanner.MAP: typ = P.ParseMapType();
630 case Scanner.STRUCT: typ = P.ParseStructType();
631 case Scanner.MUL: typ = P.ParsePointerType();
Robert Griesemer0cee3022008-07-15 10:05:17 -0700632 }
Robert Griesemera6f87792008-07-15 15:37:14 -0700633
Robert Griesemerfce91182008-07-29 12:03:06 -0700634 if typ != nil && typ.form == Type.UNDEF {
635 P.Error(pos, "incomplete type");
636 }
637
Robert Griesemer0cee3022008-07-15 10:05:17 -0700638 P.Ecart();
Robert Griesemera6f87792008-07-15 15:37:14 -0700639 return typ;
Robert Griesemer0cee3022008-07-15 10:05:17 -0700640}
641
642
643// ----------------------------------------------------------------------------
644// Blocks
645
646func (P *Parser) ParseStatement() {
647 P.Trace("Statement");
648 if !P.TryStatement() {
Robert Griesemer5a90ede2008-07-18 17:18:29 -0700649 P.Error(P.pos, "statement expected");
Robert Griesemera6f87792008-07-15 15:37:14 -0700650 P.Next(); // make progress
Robert Griesemer0cee3022008-07-15 10:05:17 -0700651 }
652 P.Ecart();
653}
654
655
656func (P *Parser) ParseStatementList() {
657 P.Trace("StatementList");
658 for P.TryStatement() {
659 P.Optional(Scanner.SEMICOLON);
660 }
661 P.Ecart();
662}
663
664
665func (P *Parser) ParseBlock() {
666 P.Trace("Block");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700667
Robert Griesemer0cee3022008-07-15 10:05:17 -0700668 P.Expect(Scanner.LBRACE);
669 P.OpenScope();
670 if P.tok != Scanner.RBRACE && P.tok != Scanner.SEMICOLON {
671 P.ParseStatementList();
672 }
673 P.Optional(Scanner.SEMICOLON);
674 P.CloseScope();
675 P.Expect(Scanner.RBRACE);
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700676
Robert Griesemer0cee3022008-07-15 10:05:17 -0700677 P.Ecart();
678}
679
680
681// ----------------------------------------------------------------------------
682// Expressions
683
Robert Griesemercf4c37c2008-07-25 09:35:03 -0700684func (P *Parser) ParseExpressionList() *Globals.List {
Robert Griesemer0cee3022008-07-15 10:05:17 -0700685 P.Trace("ExpressionList");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700686
Robert Griesemercf4c37c2008-07-25 09:35:03 -0700687 list := Globals.NewList();
Robert Griesemer0cee3022008-07-15 10:05:17 -0700688 P.ParseExpression();
Robert Griesemercf4c37c2008-07-25 09:35:03 -0700689 list.AddInt(0); // TODO fix this - add correct list element
Robert Griesemer0cee3022008-07-15 10:05:17 -0700690 for P.tok == Scanner.COMMA {
691 P.Next();
692 P.ParseExpression();
Robert Griesemercf4c37c2008-07-25 09:35:03 -0700693 list.AddInt(0); // TODO fix this - add correct list element
Robert Griesemer0cee3022008-07-15 10:05:17 -0700694 }
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700695
Robert Griesemer0cee3022008-07-15 10:05:17 -0700696 P.Ecart();
Robert Griesemercf4c37c2008-07-25 09:35:03 -0700697 return list;
Robert Griesemer0cee3022008-07-15 10:05:17 -0700698}
699
700
701func (P *Parser) ParseNew() {
702 P.Trace("New");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700703
Robert Griesemer0cee3022008-07-15 10:05:17 -0700704 P.Expect(Scanner.NEW);
705 P.Expect(Scanner.LPAREN);
706 P.ParseType();
707 if P.tok == Scanner.COMMA {
708 P.Next();
709 P.ParseExpressionList()
710 }
711 P.Expect(Scanner.RPAREN);
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700712
Robert Griesemer0cee3022008-07-15 10:05:17 -0700713 P.Ecart();
714}
715
716
717func (P *Parser) ParseFunctionLit() {
718 P.Trace("FunctionLit");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700719
Robert Griesemer0cee3022008-07-15 10:05:17 -0700720 P.ParseFunctionType();
721 P.ParseBlock();
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700722
Robert Griesemer0cee3022008-07-15 10:05:17 -0700723 P.Ecart();
724}
725
726
Robert Griesemerfda1d162008-07-23 16:59:06 -0700727func (P *Parser) ParseExpressionPair() {
728 P.Trace("ExpressionPair");
729
730 P.ParseExpression();
731 P.Expect(Scanner.COLON);
732 P.ParseExpression();
733
734 P.Ecart();
735}
736
737
738func (P *Parser) ParseExpressionPairList() {
739 P.Trace("ExpressionPairList");
740
741 P.ParseExpressionPair();
742 for (P.tok == Scanner.COMMA) {
743 P.ParseExpressionPair();
744 }
745
746 P.Ecart();
747}
748
749
Robert Griesemerf03deb32008-07-24 17:00:58 -0700750func (P *Parser) ParseBuiltinCall() {
751 P.Trace("BuiltinCall");
752
753 P.ParseExpressionList(); // TODO should be optional
754
755 P.Ecart();
756}
757
758
Robert Griesemerfda1d162008-07-23 16:59:06 -0700759func (P *Parser) ParseCompositeLit(typ *Globals.Type) {
760 P.Trace("CompositeLit");
761
762 // TODO I think we should use {} instead of () for
763 // composite literals to syntactically distinguish
764 // them from conversions. For now: allow both.
765 var paren int;
766 if P.tok == Scanner.LPAREN {
767 P.Next();
768 paren = Scanner.RPAREN;
769 } else {
770 P.Expect(Scanner.LBRACE);
771 paren = Scanner.RBRACE;
772 }
773
774 // TODO: should allow trailing ','
775 if P.tok != paren {
776 P.ParseExpression();
777 if P.tok == Scanner.COMMA {
778 P.Next();
779 if P.tok != paren {
780 P.ParseExpressionList();
781 }
782 } else if P.tok == Scanner.COLON {
783 P.Next();
784 P.ParseExpression();
785 if P.tok == Scanner.COMMA {
786 P.Next();
787 if P.tok != paren {
788 P.ParseExpressionPairList();
789 }
790 }
791 }
792 }
793
794 P.Expect(paren);
795
796 P.Ecart();
797}
798
799
Robert Griesemerf03deb32008-07-24 17:00:58 -0700800func (P *Parser) ParseOperand(pos int, ident string) {
Robert Griesemer0cee3022008-07-15 10:05:17 -0700801 P.Trace("Operand");
Robert Griesemerf03deb32008-07-24 17:00:58 -0700802
803 if pos < 0 && P.tok == Scanner.IDENT {
804 // no look-ahead yet
805 pos = P.pos;
806 ident = P.val;
807 P.Next();
808 }
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700809
Robert Griesemerf03deb32008-07-24 17:00:58 -0700810 if pos >= 0 {
811 // TODO set these up properly in the Universe
812 if ident == "panic" || ident == "print" {
813 P.ParseBuiltinCall();
814 goto exit;
815 }
816
817 P.ParseQualifiedIdent(pos, ident);
Robert Griesemerfda1d162008-07-23 16:59:06 -0700818 // TODO enable code below
819 /*
820 if obj.kind == Object.TYPE {
821 P.ParseCompositeLit(obj.typ);
822 }
823 */
Robert Griesemerf03deb32008-07-24 17:00:58 -0700824 goto exit;
825 }
826
827 switch P.tok {
828 case Scanner.IDENT:
829 panic "UNREACHABLE";
Robert Griesemer0cee3022008-07-15 10:05:17 -0700830 case Scanner.LPAREN:
831 P.Next();
832 P.ParseExpression();
833 P.Expect(Scanner.RPAREN);
834 case Scanner.STRING: fallthrough;
835 case Scanner.NUMBER: fallthrough;
836 case Scanner.NIL: fallthrough;
837 case Scanner.IOTA: fallthrough;
838 case Scanner.TRUE: fallthrough;
839 case Scanner.FALSE:
840 P.Next();
841 case Scanner.FUNC:
842 P.ParseFunctionLit();
843 case Scanner.NEW:
844 P.ParseNew();
845 default:
Robert Griesemerfda1d162008-07-23 16:59:06 -0700846 typ := P.TryType();
847 if typ != nil {
848 P.ParseCompositeLit(typ);
849 } else {
850 P.Error(P.pos, "operand expected");
851 P.Next(); // make progress
852 }
Robert Griesemer0cee3022008-07-15 10:05:17 -0700853 }
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700854
Robert Griesemerf03deb32008-07-24 17:00:58 -0700855exit:
Robert Griesemer0cee3022008-07-15 10:05:17 -0700856 P.Ecart();
857}
858
859
860func (P *Parser) ParseSelectorOrTypeAssertion() {
861 P.Trace("SelectorOrTypeAssertion");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700862
Robert Griesemer0cee3022008-07-15 10:05:17 -0700863 P.Expect(Scanner.PERIOD);
864 if P.tok == Scanner.IDENT {
865 P.ParseIdent();
866 } else {
867 P.Expect(Scanner.LPAREN);
868 P.ParseType();
869 P.Expect(Scanner.RPAREN);
870 }
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700871
Robert Griesemer0cee3022008-07-15 10:05:17 -0700872 P.Ecart();
873}
874
875
876func (P *Parser) ParseIndexOrSlice() {
877 P.Trace("IndexOrSlice");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700878
Robert Griesemer0cee3022008-07-15 10:05:17 -0700879 P.Expect(Scanner.LBRACK);
880 P.ParseExpression();
881 if P.tok == Scanner.COLON {
882 P.Next();
883 P.ParseExpression();
884 }
885 P.Expect(Scanner.RBRACK);
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700886
Robert Griesemer0cee3022008-07-15 10:05:17 -0700887 P.Ecart();
888}
889
890
Robert Griesemerf03deb32008-07-24 17:00:58 -0700891func (P *Parser) ParseCall() {
892 P.Trace("Call");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700893
Robert Griesemer0cee3022008-07-15 10:05:17 -0700894 P.Expect(Scanner.LPAREN);
895 if P.tok != Scanner.RPAREN {
896 P.ParseExpressionList();
897 }
898 P.Expect(Scanner.RPAREN);
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700899
Robert Griesemer0cee3022008-07-15 10:05:17 -0700900 P.Ecart();
901}
902
903
Robert Griesemerf03deb32008-07-24 17:00:58 -0700904func (P *Parser) ParsePrimaryExpr(pos int, ident string) AST.Expr {
Robert Griesemer0cee3022008-07-15 10:05:17 -0700905 P.Trace("PrimaryExpr");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700906
Robert Griesemerf03deb32008-07-24 17:00:58 -0700907 P.ParseOperand(pos, ident);
Robert Griesemer0cee3022008-07-15 10:05:17 -0700908 for {
909 switch P.tok {
910 case Scanner.PERIOD:
911 P.ParseSelectorOrTypeAssertion();
912 case Scanner.LBRACK:
913 P.ParseIndexOrSlice();
914 case Scanner.LPAREN:
Robert Griesemerf03deb32008-07-24 17:00:58 -0700915 P.ParseCall();
Robert Griesemer0cee3022008-07-15 10:05:17 -0700916 default:
917 P.Ecart();
Robert Griesemerf03deb32008-07-24 17:00:58 -0700918 return nil;
Robert Griesemer0cee3022008-07-15 10:05:17 -0700919 }
920 }
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700921
Robert Griesemer0cee3022008-07-15 10:05:17 -0700922 P.Ecart();
Robert Griesemerf03deb32008-07-24 17:00:58 -0700923 return nil;
Robert Griesemer0cee3022008-07-15 10:05:17 -0700924}
Robert Griesemer835cd462008-07-07 17:27:14 -0700925
926
927func (P *Parser) ParsePrimaryExprList() {
928 P.Trace("PrimaryExprList");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700929
Robert Griesemerf03deb32008-07-24 17:00:58 -0700930 P.ParsePrimaryExpr(-1, "");
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700931 for P.tok == Scanner.COMMA {
932 P.Next();
Robert Griesemerf03deb32008-07-24 17:00:58 -0700933 P.ParsePrimaryExpr(-1, "");
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700934 }
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700935
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700936 P.Ecart();
937}
938
939
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700940func (P *Parser) ParseUnaryExpr() AST.Expr {
Robert Griesemer0cee3022008-07-15 10:05:17 -0700941 P.Trace("UnaryExpr");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700942
Robert Griesemer0cee3022008-07-15 10:05:17 -0700943 switch P.tok {
944 case Scanner.ADD: fallthrough;
945 case Scanner.SUB: fallthrough;
946 case Scanner.NOT: fallthrough;
947 case Scanner.XOR: fallthrough;
Robert Griesemer0cee3022008-07-15 10:05:17 -0700948 case Scanner.MUL: fallthrough;
Robert Griesemer0e676542008-07-16 17:00:48 -0700949 case Scanner.RECV: fallthrough;
Robert Griesemer0cee3022008-07-15 10:05:17 -0700950 case Scanner.AND:
951 P.Next();
952 P.ParseUnaryExpr();
953 P.Ecart();
Robert Griesemer5a90ede2008-07-18 17:18:29 -0700954 return nil; // TODO fix this
Robert Griesemer0cee3022008-07-15 10:05:17 -0700955 }
Robert Griesemerf03deb32008-07-24 17:00:58 -0700956 P.ParsePrimaryExpr(-1, "");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700957
Robert Griesemer0cee3022008-07-15 10:05:17 -0700958 P.Ecart();
Robert Griesemer5a90ede2008-07-18 17:18:29 -0700959 return nil; // TODO fix this
Robert Griesemer0cee3022008-07-15 10:05:17 -0700960}
961
962
963func Precedence(tok int) int {
964 // TODO should use a map or array here for lookup
965 switch tok {
966 case Scanner.LOR:
967 return 1;
968 case Scanner.LAND:
969 return 2;
Robert Griesemer0e676542008-07-16 17:00:48 -0700970 case Scanner.SEND, Scanner.RECV:
Robert Griesemer0cee3022008-07-15 10:05:17 -0700971 return 3;
Robert Griesemer0e676542008-07-16 17:00:48 -0700972 case Scanner.EQL, Scanner.NEQ, Scanner.LSS, Scanner.LEQ, Scanner.GTR, Scanner.GEQ:
Robert Griesemer0cee3022008-07-15 10:05:17 -0700973 return 4;
Robert Griesemer0e676542008-07-16 17:00:48 -0700974 case Scanner.ADD, Scanner.SUB, Scanner.OR, Scanner.XOR:
Robert Griesemer0cee3022008-07-15 10:05:17 -0700975 return 5;
Robert Griesemer0e676542008-07-16 17:00:48 -0700976 case Scanner.MUL, Scanner.QUO, Scanner.REM, Scanner.SHL, Scanner.SHR, Scanner.AND:
977 return 6;
Robert Griesemer0cee3022008-07-15 10:05:17 -0700978 }
979 return 0;
980}
981
982
Robert Griesemerf03deb32008-07-24 17:00:58 -0700983func (P *Parser) ParseBinaryExpr(pos int, ident string, prec1 int) AST.Expr {
Robert Griesemer0cee3022008-07-15 10:05:17 -0700984 P.Trace("BinaryExpr");
Robert Griesemer5a90ede2008-07-18 17:18:29 -0700985
Robert Griesemerf03deb32008-07-24 17:00:58 -0700986 var x AST.Expr;
987 if pos >= 0 {
988 x = P.ParsePrimaryExpr(pos, ident);
989 } else {
990 x = P.ParseUnaryExpr();
991 }
Robert Griesemer0cee3022008-07-15 10:05:17 -0700992 for prec := Precedence(P.tok); prec >= prec1; prec-- {
993 for Precedence(P.tok) == prec {
Robert Griesemerb0ada5d2008-07-23 16:04:11 -0700994 e := new(AST.BinaryExpr);
Robert Griesemer5a90ede2008-07-18 17:18:29 -0700995 e.typ = Universe.undef_t; // TODO fix this
996 e.op = P.tok; // TODO should we use tokens or separate operator constants?
997 e.x = x;
Robert Griesemer0cee3022008-07-15 10:05:17 -0700998 P.Next();
Robert Griesemerf03deb32008-07-24 17:00:58 -0700999 e.y = P.ParseBinaryExpr(-1, "", prec + 1);
Robert Griesemer5a90ede2008-07-18 17:18:29 -07001000 x = e;
Robert Griesemer0cee3022008-07-15 10:05:17 -07001001 }
1002 }
Robert Griesemer5a90ede2008-07-18 17:18:29 -07001003
Robert Griesemer0cee3022008-07-15 10:05:17 -07001004 P.Ecart();
1005}
1006
1007
Robert Griesemer5fc79192008-07-25 11:27:13 -07001008// Expressions where the first token may be an identifier which has already
1009// been consumed. If the identifier is present, pos is the identifier position,
1010// otherwise pos must be < 0 (and ident is ignored).
Robert Griesemerf03deb32008-07-24 17:00:58 -07001011func (P *Parser) ParseIdentExpression(pos int, ident string) {
1012 P.Trace("IdentExpression");
Robert Griesemer0cee3022008-07-15 10:05:17 -07001013 indent := P.indent;
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001014
Robert Griesemerf03deb32008-07-24 17:00:58 -07001015 P.ParseBinaryExpr(pos, ident, 1);
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001016
Robert Griesemer0cee3022008-07-15 10:05:17 -07001017 if indent != P.indent {
Robert Griesemerfda1d162008-07-23 16:59:06 -07001018 panic "imbalanced tracing code (Expression)";
Robert Griesemer0cee3022008-07-15 10:05:17 -07001019 }
1020 P.Ecart();
1021}
1022
1023
Robert Griesemerf03deb32008-07-24 17:00:58 -07001024func (P *Parser) ParseExpression() {
1025 P.Trace("Expression");
1026 P.ParseIdentExpression(-1, "");
1027 P.Ecart();
1028}
1029
1030
Robert Griesemer0cee3022008-07-15 10:05:17 -07001031// ----------------------------------------------------------------------------
1032// Statements
1033
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001034func (P *Parser) ConvertToExprList(pos_list, ident_list, expr_list *Globals.List) {
1035 for p, q := pos_list.first, ident_list.first; q != nil; p, q = p.next, q.next {
1036 pos, ident := p.val, q.str;
1037 if EnableSemanticTests {
1038 obj := P.Lookup(ident);
1039 if obj == nil {
1040 P.Error(pos, `"` + ident + `" is not declared`);
1041 obj = Globals.NewObject(pos, Object.BAD, ident);
1042 }
1043 }
1044 expr_list.AddInt(0); // TODO fix this - add correct expression
1045 }
1046 ident_list.Clear();
1047}
1048
1049
1050func (P *Parser) ParseIdentOrExpr(pos_list, ident_list, expr_list *Globals.List) {
Robert Griesemerf03deb32008-07-24 17:00:58 -07001051 P.Trace("IdentOrExpr");
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001052
1053 pos_list.AddInt(P.pos);
1054 pos, ident := -1, "";
1055 just_ident := false;
1056 if expr_list.len_ == 0 /* only idents so far */ && P.tok == Scanner.IDENT {
1057 pos, ident = P.pos, P.val;
Robert Griesemerf03deb32008-07-24 17:00:58 -07001058 P.Next();
1059 switch P.tok {
1060 case Scanner.COMMA,
1061 Scanner.COLON,
1062 Scanner.DEFINE,
1063 Scanner.ASSIGN,
1064 Scanner.ADD_ASSIGN,
1065 Scanner.SUB_ASSIGN,
1066 Scanner.MUL_ASSIGN,
1067 Scanner.QUO_ASSIGN,
1068 Scanner.REM_ASSIGN,
1069 Scanner.AND_ASSIGN,
1070 Scanner.OR_ASSIGN,
1071 Scanner.XOR_ASSIGN,
1072 Scanner.SHL_ASSIGN,
1073 Scanner.SHR_ASSIGN:
1074 // identifier is not part of a more complicated expression
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001075 just_ident = true;
Robert Griesemerf03deb32008-07-24 17:00:58 -07001076 }
Robert Griesemerf03deb32008-07-24 17:00:58 -07001077 }
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001078
1079 if just_ident {
1080 ident_list.AddStr(ident);
1081 } else {
1082 P.ConvertToExprList(pos_list, ident_list, expr_list);
1083 P.ParseIdentExpression(pos, ident);
1084 expr_list.AddInt(0); // TODO fix this - add correct expression
1085 }
1086
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001087 P.Ecart();
Robert Griesemerf03deb32008-07-24 17:00:58 -07001088}
1089
1090
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001091func (P *Parser) ParseIdentOrExprList() (pos_list, ident_list, expr_list *Globals.List) {
1092 P.Trace("IdentOrExprList");
1093
1094 pos_list, ident_list, expr_list = Globals.NewList(), Globals.NewList(), Globals.NewList();
1095 P.ParseIdentOrExpr(pos_list, ident_list, expr_list);
1096 for P.tok == Scanner.COMMA {
1097 P.Next();
1098 P.ParseIdentOrExpr(pos_list, ident_list, expr_list);
Robert Griesemerf03deb32008-07-24 17:00:58 -07001099 }
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001100
1101 P.Ecart();
1102 return pos_list, ident_list, expr_list;
Robert Griesemer835cd462008-07-07 17:27:14 -07001103}
1104
1105
1106func (P *Parser) ParseSimpleStat() {
1107 P.Trace("SimpleStat");
Robert Griesemerf03deb32008-07-24 17:00:58 -07001108
1109 // If we see an identifier, we don't know if it's part of a
1110 // label declaration, (multiple) variable declaration, assignment,
1111 // or simply an expression, without looking ahead.
1112 // Strategy: We parse an expression list, but simultaneously, as
1113 // long as possible, maintain a list of identifiers which is converted
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001114 // into an expression list only if neccessary. The result of
1115 // ParseIdentOrExprList is a list of ident/expr positions and either
1116 // a non-empty list of identifiers or a non-empty list of expressions
1117 // (but not both).
1118 pos_list, ident_list, expr_list := P.ParseIdentOrExprList();
Robert Griesemerf03deb32008-07-24 17:00:58 -07001119
Robert Griesemer8e4ee002008-07-08 18:37:31 -07001120 switch P.tok {
Robert Griesemerf03deb32008-07-24 17:00:58 -07001121 case Scanner.COLON:
1122 // label declaration
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001123 if EnableSemanticTests && ident_list.len_ != 1 {
Robert Griesemerf03deb32008-07-24 17:00:58 -07001124 P.Error(P.pos, "illegal label declaration");
1125 }
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001126 P.Next();
Robert Griesemerf03deb32008-07-24 17:00:58 -07001127
1128 case Scanner.DEFINE:
1129 // variable declaration
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001130 if EnableSemanticTests && ident_list.len_ == 0 {
1131 P.Error(P.pos, "illegal left-hand side for declaration");
1132 }
Robert Griesemerf03deb32008-07-24 17:00:58 -07001133 P.Next();
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001134 pos := P.pos;
1135 val_list := P.ParseExpressionList();
1136 if EnableSemanticTests && val_list.len_ != ident_list.len_ {
1137 P.Error(pos, "number of expressions does not match number of variables");
1138 }
1139 // declare variables
1140 if EnableSemanticTests {
1141 for p, q := pos_list.first, ident_list.first; q != nil; p, q = p.next, q.next {
1142 obj := Globals.NewObject(p.val, Object.VAR, q.str);
1143 P.Declare(obj);
1144 // TODO set correct types
1145 }
Robert Griesemerf03deb32008-07-24 17:00:58 -07001146 }
1147
Robert Griesemer8e4ee002008-07-08 18:37:31 -07001148 case Scanner.ASSIGN: fallthrough;
Robert Griesemer8e4ee002008-07-08 18:37:31 -07001149 case Scanner.ADD_ASSIGN: fallthrough;
1150 case Scanner.SUB_ASSIGN: fallthrough;
1151 case Scanner.MUL_ASSIGN: fallthrough;
1152 case Scanner.QUO_ASSIGN: fallthrough;
1153 case Scanner.REM_ASSIGN: fallthrough;
1154 case Scanner.AND_ASSIGN: fallthrough;
1155 case Scanner.OR_ASSIGN: fallthrough;
1156 case Scanner.XOR_ASSIGN: fallthrough;
1157 case Scanner.SHL_ASSIGN: fallthrough;
1158 case Scanner.SHR_ASSIGN:
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001159 P.ConvertToExprList(pos_list, ident_list, expr_list);
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001160 P.Next();
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001161 pos := P.pos;
1162 val_list := P.ParseExpressionList();
1163 if EnableSemanticTests && val_list.len_ != expr_list.len_ {
1164 P.Error(pos, "number of expressions does not match number of variables");
Robert Griesemerf03deb32008-07-24 17:00:58 -07001165 }
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001166
Robert Griesemerf03deb32008-07-24 17:00:58 -07001167 default:
Robert Griesemercf4c37c2008-07-25 09:35:03 -07001168 P.ConvertToExprList(pos_list, ident_list, expr_list);
1169 if EnableSemanticTests && expr_list.len_ != 1 {
1170 P.Error(P.pos, "no expression list allowed");
1171 }
1172 if P.tok == Scanner.INC || P.tok == Scanner.DEC {
1173 P.Next();
Robert Griesemerf03deb32008-07-24 17:00:58 -07001174 }
Robert Griesemer835cd462008-07-07 17:27:14 -07001175 }
Robert Griesemerf03deb32008-07-24 17:00:58 -07001176
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001177 P.Ecart();
1178}
1179
1180
Robert Griesemer8e4ee002008-07-08 18:37:31 -07001181func (P *Parser) ParseGoStat() {
1182 P.Trace("GoStat");
1183 P.Expect(Scanner.GO);
1184 P.ParseExpression();
Robert Griesemer415397e2008-07-09 14:48:26 -07001185 P.Ecart();
Robert Griesemer8e4ee002008-07-08 18:37:31 -07001186}
1187
1188
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001189func (P *Parser) ParseReturnStat() {
1190 P.Trace("ReturnStat");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001191
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001192 P.Expect(Scanner.RETURN);
1193 if P.tok != Scanner.SEMICOLON && P.tok != Scanner.RBRACE {
1194 P.ParseExpressionList();
1195 }
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001196
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001197 P.Ecart();
1198}
1199
1200
Robert Griesemer8e4ee002008-07-08 18:37:31 -07001201func (P *Parser) ParseControlFlowStat(tok int) {
1202 P.Trace("ControlFlowStat");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001203
Robert Griesemer8e4ee002008-07-08 18:37:31 -07001204 P.Expect(tok);
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001205 if P.tok == Scanner.IDENT {
1206 P.ParseIdent();
1207 }
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001208
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001209 P.Ecart();
1210}
1211
1212
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001213func (P *Parser) ParseIfStat() *AST.IfStat {
Robert Griesemer835cd462008-07-07 17:27:14 -07001214 P.Trace("IfStat");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001215
Robert Griesemer835cd462008-07-07 17:27:14 -07001216 P.Expect(Scanner.IF);
Robert Griesemer230230c2008-07-14 18:06:41 -07001217 P.OpenScope();
Robert Griesemer835cd462008-07-07 17:27:14 -07001218 if P.tok != Scanner.LBRACE {
Robert Griesemerae905982008-07-10 20:50:38 -07001219 if P.tok != Scanner.SEMICOLON {
1220 P.ParseSimpleStat();
1221 }
Robert Griesemer835cd462008-07-07 17:27:14 -07001222 if P.tok == Scanner.SEMICOLON {
Robert Griesemer8e4ee002008-07-08 18:37:31 -07001223 P.Next();
Robert Griesemerae905982008-07-10 20:50:38 -07001224 if P.tok != Scanner.LBRACE {
1225 P.ParseExpression();
1226 }
Robert Griesemer835cd462008-07-07 17:27:14 -07001227 }
1228 }
1229 P.ParseBlock();
1230 if P.tok == Scanner.ELSE {
1231 P.Next();
1232 if P.tok == Scanner.IF {
1233 P.ParseIfStat();
1234 } else {
1235 // TODO should be P.ParseBlock()
Robert Griesemer8e4ee002008-07-08 18:37:31 -07001236 P.ParseStatement();
Robert Griesemer835cd462008-07-07 17:27:14 -07001237 }
1238 }
Robert Griesemer230230c2008-07-14 18:06:41 -07001239 P.CloseScope();
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001240
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001241 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -07001242}
1243
1244
1245func (P *Parser) ParseForStat() {
1246 P.Trace("ForStat");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001247
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001248 P.Expect(Scanner.FOR);
Robert Griesemer230230c2008-07-14 18:06:41 -07001249 P.OpenScope();
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001250 if P.tok != Scanner.LBRACE {
1251 if P.tok != Scanner.SEMICOLON {
1252 P.ParseSimpleStat();
1253 }
1254 if P.tok == Scanner.SEMICOLON {
1255 P.Next();
1256 if P.tok != Scanner.SEMICOLON {
1257 P.ParseExpression();
1258 }
1259 P.Expect(Scanner.SEMICOLON);
1260 if P.tok != Scanner.LBRACE {
1261 P.ParseSimpleStat();
1262 }
1263 }
1264 }
1265 P.ParseBlock();
Robert Griesemer230230c2008-07-14 18:06:41 -07001266 P.CloseScope();
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001267
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001268 P.Ecart();
1269}
1270
1271
1272func (P *Parser) ParseCase() {
1273 P.Trace("Case");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001274
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001275 if P.tok == Scanner.CASE {
1276 P.Next();
1277 P.ParseExpressionList();
1278 } else {
1279 P.Expect(Scanner.DEFAULT);
1280 }
1281 P.Expect(Scanner.COLON);
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001282
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001283 P.Ecart();
1284}
1285
1286
1287func (P *Parser) ParseCaseList() {
1288 P.Trace("CaseList");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001289
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001290 P.ParseCase();
1291 for P.tok == Scanner.CASE || P.tok == Scanner.DEFAULT {
1292 P.ParseCase();
1293 }
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001294
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001295 P.Ecart();
1296}
1297
1298
1299func (P *Parser) ParseCaseClause() {
1300 P.Trace("CaseClause");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001301
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001302 P.ParseCaseList();
1303 if P.tok != Scanner.FALLTHROUGH && P.tok != Scanner.RBRACE {
1304 P.ParseStatementList();
Robert Griesemer8e4ee002008-07-08 18:37:31 -07001305 P.Optional(Scanner.SEMICOLON);
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001306 }
1307 if P.tok == Scanner.FALLTHROUGH {
1308 P.Next();
Robert Griesemer8e4ee002008-07-08 18:37:31 -07001309 P.Optional(Scanner.SEMICOLON);
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001310 }
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001311
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001312 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -07001313}
1314
1315
1316func (P *Parser) ParseSwitchStat() {
1317 P.Trace("SwitchStat");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001318
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001319 P.Expect(Scanner.SWITCH);
Robert Griesemer230230c2008-07-14 18:06:41 -07001320 P.OpenScope();
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001321 if P.tok != Scanner.LBRACE {
Robert Griesemerae905982008-07-10 20:50:38 -07001322 if P.tok != Scanner.SEMICOLON {
1323 P.ParseSimpleStat();
1324 }
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001325 if P.tok == Scanner.SEMICOLON {
Robert Griesemer8e4ee002008-07-08 18:37:31 -07001326 P.Next();
Robert Griesemerae905982008-07-10 20:50:38 -07001327 if P.tok != Scanner.LBRACE {
1328 P.ParseExpression();
1329 }
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001330 }
1331 }
1332 P.Expect(Scanner.LBRACE);
Robert Griesemerf03deb32008-07-24 17:00:58 -07001333 for P.tok == Scanner.CASE || P.tok == Scanner.DEFAULT {
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001334 P.ParseCaseClause();
1335 }
1336 P.Expect(Scanner.RBRACE);
Robert Griesemer230230c2008-07-14 18:06:41 -07001337 P.CloseScope();
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001338
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001339 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -07001340}
1341
1342
Robert Griesemercab94922008-07-09 14:01:17 -07001343func (P *Parser) ParseCommCase() {
1344 P.Trace("CommCase");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001345
Robert Griesemercab94922008-07-09 14:01:17 -07001346 if P.tok == Scanner.CASE {
1347 P.Next();
1348 if P.tok == Scanner.GTR {
1349 // send
1350 P.Next();
1351 P.ParseExpression();
1352 P.Expect(Scanner.EQL);
1353 P.ParseExpression();
1354 } else {
1355 // receive
1356 if P.tok != Scanner.LSS {
1357 P.ParseIdent();
1358 P.Expect(Scanner.ASSIGN);
1359 }
1360 P.Expect(Scanner.LSS);
1361 P.ParseExpression();
1362 }
1363 } else {
1364 P.Expect(Scanner.DEFAULT);
1365 }
1366 P.Expect(Scanner.COLON);
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001367
Robert Griesemercab94922008-07-09 14:01:17 -07001368 P.Ecart();
1369}
1370
1371
1372func (P *Parser) ParseCommClause() {
1373 P.Trace("CommClause");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001374
Robert Griesemercab94922008-07-09 14:01:17 -07001375 P.ParseCommCase();
1376 if P.tok != Scanner.CASE && P.tok != Scanner.DEFAULT && P.tok != Scanner.RBRACE {
1377 P.ParseStatementList();
1378 P.Optional(Scanner.SEMICOLON);
1379 }
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001380
Robert Griesemercab94922008-07-09 14:01:17 -07001381 P.Ecart();
1382}
1383
1384
1385func (P *Parser) ParseRangeStat() bool {
1386 P.Trace("RangeStat");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001387
Robert Griesemercab94922008-07-09 14:01:17 -07001388 P.Expect(Scanner.RANGE);
1389 P.ParseIdentList();
1390 P.Expect(Scanner.DEFINE);
1391 P.ParseExpression();
1392 P.ParseBlock();
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001393
Robert Griesemercab94922008-07-09 14:01:17 -07001394 P.Ecart();
1395}
1396
1397
1398func (P *Parser) ParseSelectStat() bool {
1399 P.Trace("SelectStat");
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001400
Robert Griesemercab94922008-07-09 14:01:17 -07001401 P.Expect(Scanner.SELECT);
1402 P.Expect(Scanner.LBRACE);
Robert Griesemerf03deb32008-07-24 17:00:58 -07001403 for P.tok != Scanner.RBRACE && P.tok != Scanner.EOF {
Robert Griesemercab94922008-07-09 14:01:17 -07001404 P.ParseCommClause();
1405 }
1406 P.Next();
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001407
Robert Griesemercab94922008-07-09 14:01:17 -07001408 P.Ecart();
1409}
1410
1411
Robert Griesemer8e4ee002008-07-08 18:37:31 -07001412func (P *Parser) TryStatement() bool {
1413 P.Trace("Statement (try)");
Robert Griesemer415397e2008-07-09 14:48:26 -07001414 indent := P.indent;
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001415
Robert Griesemer415397e2008-07-09 14:48:26 -07001416 res := true;
Robert Griesemer835cd462008-07-07 17:27:14 -07001417 switch P.tok {
1418 case Scanner.CONST: fallthrough;
1419 case Scanner.TYPE: fallthrough;
Robert Griesemerd9d5f3b2008-07-15 09:22:20 -07001420 case Scanner.VAR:
Robert Griesemer835cd462008-07-07 17:27:14 -07001421 P.ParseDeclaration();
Robert Griesemerd9d5f3b2008-07-15 09:22:20 -07001422 case Scanner.FUNC:
1423 // for now we do not allow local function declarations
1424 fallthrough;
Robert Griesemerf03deb32008-07-24 17:00:58 -07001425 case Scanner.MUL, Scanner.SEND, Scanner.RECV, Scanner.IDENT:
1426 P.ParseSimpleStat();
Robert Griesemer835cd462008-07-07 17:27:14 -07001427 case Scanner.GO:
Robert Griesemer8e4ee002008-07-08 18:37:31 -07001428 P.ParseGoStat();
Robert Griesemer835cd462008-07-07 17:27:14 -07001429 case Scanner.RETURN:
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001430 P.ParseReturnStat();
Robert Griesemer8e4ee002008-07-08 18:37:31 -07001431 case Scanner.BREAK, Scanner.CONTINUE, Scanner.GOTO:
1432 P.ParseControlFlowStat(P.tok);
Robert Griesemer835cd462008-07-07 17:27:14 -07001433 case Scanner.LBRACE:
1434 P.ParseBlock();
1435 case Scanner.IF:
1436 P.ParseIfStat();
1437 case Scanner.FOR:
1438 P.ParseForStat();
1439 case Scanner.SWITCH:
1440 P.ParseSwitchStat();
1441 case Scanner.RANGE:
Robert Griesemercab94922008-07-09 14:01:17 -07001442 P.ParseRangeStat();
Robert Griesemer835cd462008-07-07 17:27:14 -07001443 case Scanner.SELECT:
Robert Griesemercab94922008-07-09 14:01:17 -07001444 P.ParseSelectStat();
Robert Griesemer835cd462008-07-07 17:27:14 -07001445 default:
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001446 // no statement found
Robert Griesemer415397e2008-07-09 14:48:26 -07001447 res = false;
1448 }
Robert Griesemerb0ada5d2008-07-23 16:04:11 -07001449
Robert Griesemer415397e2008-07-09 14:48:26 -07001450 if indent != P.indent {
Robert Griesemerfda1d162008-07-23 16:59:06 -07001451 panic "imbalanced tracing code (Statement)"
Robert Griesemer835cd462008-07-07 17:27:14 -07001452 }
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001453 P.Ecart();
Robert Griesemer415397e2008-07-09 14:48:26 -07001454 return res;
Robert Griesemer835cd462008-07-07 17:27:14 -07001455}
1456
1457
Robert Griesemer0cee3022008-07-15 10:05:17 -07001458// ----------------------------------------------------------------------------
1459// Declarations
1460
1461func (P *Parser) ParseImportSpec() {
1462 P.Trace("ImportSpec");
Robert Griesemera6f87792008-07-15 15:37:14 -07001463
Robert Griesemer0cee3022008-07-15 10:05:17 -07001464 if P.tok == Scanner.PERIOD {
1465 P.Next();
1466 } else if P.tok == Scanner.IDENT {
1467 P.Next();
1468 }
1469 P.Expect(Scanner.STRING);
Robert Griesemera6f87792008-07-15 15:37:14 -07001470
Robert Griesemer0cee3022008-07-15 10:05:17 -07001471 P.Ecart();
1472}
1473
1474
1475func (P *Parser) ParseImportDecl() {
1476 P.Trace("ImportDecl");
Robert Griesemera6f87792008-07-15 15:37:14 -07001477
Robert Griesemer0cee3022008-07-15 10:05:17 -07001478 P.Expect(Scanner.IMPORT);
1479 if P.tok == Scanner.LPAREN {
1480 P.Next();
Robert Griesemerf03deb32008-07-24 17:00:58 -07001481 for P.tok != Scanner.RPAREN && P.tok != Scanner.EOF {
Robert Griesemer0cee3022008-07-15 10:05:17 -07001482 P.ParseImportSpec();
1483 P.Optional(Scanner.SEMICOLON); // TODO this seems wrong
1484 }
1485 P.Next();
1486 } else {
1487 P.ParseImportSpec();
Robert Griesemer835cd462008-07-07 17:27:14 -07001488 }
Robert Griesemera6f87792008-07-15 15:37:14 -07001489
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001490 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -07001491}
1492
1493
Robert Griesemer5fc79192008-07-25 11:27:13 -07001494func (P *Parser) ParseConstSpec(exported bool) {
Robert Griesemer0cee3022008-07-15 10:05:17 -07001495 P.Trace("ConstSpec");
Robert Griesemera6f87792008-07-15 15:37:14 -07001496
1497 list := P.ParseIdentDeclList(Object.CONST);
1498 typ := P.TryType();
1499 if typ != nil {
1500 for p := list.first; p != nil; p = p.next {
Robert Griesemerfce91182008-07-29 12:03:06 -07001501 p.obj.exported = exported;
Robert Griesemera6f87792008-07-15 15:37:14 -07001502 p.obj.typ = typ; // TODO should use/have set_type()!
1503 }
1504 }
Robert Griesemer0cee3022008-07-15 10:05:17 -07001505 if P.tok == Scanner.ASSIGN {
1506 P.Next();
Robert Griesemera6f87792008-07-15 15:37:14 -07001507 P.ParseExpressionList();
Robert Griesemer835cd462008-07-07 17:27:14 -07001508 }
Robert Griesemera6f87792008-07-15 15:37:14 -07001509
Robert Griesemer0cee3022008-07-15 10:05:17 -07001510 P.Ecart();
1511}
1512
1513
Robert Griesemer5fc79192008-07-25 11:27:13 -07001514func (P *Parser) ParseTypeSpec(exported bool) {
Robert Griesemer0cee3022008-07-15 10:05:17 -07001515 P.Trace("TypeSpec");
Robert Griesemera6f87792008-07-15 15:37:14 -07001516
Robert Griesemer5a90ede2008-07-18 17:18:29 -07001517 pos := P.pos;
Robert Griesemera6f87792008-07-15 15:37:14 -07001518 ident := P.ParseIdent();
1519 obj := P.top_scope.Lookup(ident); // only lookup in top scope!
1520 if obj != nil {
Robert Griesemerfce91182008-07-29 12:03:06 -07001521 // name already declared - ok if forward declared type
Robert Griesemera6f87792008-07-15 15:37:14 -07001522 if obj.kind != Object.TYPE || obj.typ.form != Type.UNDEF {
1523 // TODO use obj.pos to refer to decl pos in error msg!
1524 P.Error(pos, `"` + ident + `" is declared already`);
1525 }
1526 } else {
1527 obj = Globals.NewObject(pos, Object.TYPE, ident);
Robert Griesemerfce91182008-07-29 12:03:06 -07001528 obj.exported = exported;
1529 obj.typ = Globals.NewType(Type.UNDEF);
1530 obj.typ.obj = obj; // primary type object
1531 P.Declare(obj);
Robert Griesemera6f87792008-07-15 15:37:14 -07001532 }
1533
Robert Griesemerfce91182008-07-29 12:03:06 -07001534 typ := P.TryType(); // nil if we have an explicit forward declaration
1535
Robert Griesemera6f87792008-07-15 15:37:14 -07001536 if typ != nil {
Robert Griesemerfce91182008-07-29 12:03:06 -07001537 obj.typ = typ;
Robert Griesemera6f87792008-07-15 15:37:14 -07001538 if typ.obj == nil {
1539 typ.obj = obj; // primary type object
1540 }
1541 }
1542
Robert Griesemer0cee3022008-07-15 10:05:17 -07001543 P.Ecart();
1544}
1545
1546
Robert Griesemer5fc79192008-07-25 11:27:13 -07001547func (P *Parser) ParseVarSpec(exported bool) {
Robert Griesemer0cee3022008-07-15 10:05:17 -07001548 P.Trace("VarSpec");
Robert Griesemera6f87792008-07-15 15:37:14 -07001549
1550 list := P.ParseIdentDeclList(Object.VAR);
Robert Griesemer0cee3022008-07-15 10:05:17 -07001551 if P.tok == Scanner.ASSIGN {
1552 P.Next();
1553 P.ParseExpressionList();
1554 } else {
Robert Griesemera6f87792008-07-15 15:37:14 -07001555 typ := P.ParseType();
1556 for p := list.first; p != nil; p = p.next {
1557 p.obj.typ = typ; // TODO should use/have set_type()!
1558 }
Robert Griesemer0cee3022008-07-15 10:05:17 -07001559 if P.tok == Scanner.ASSIGN {
1560 P.Next();
1561 P.ParseExpressionList();
1562 }
1563 }
Robert Griesemera6f87792008-07-15 15:37:14 -07001564
Robert Griesemer0cee3022008-07-15 10:05:17 -07001565 P.Ecart();
1566}
1567
1568
Robert Griesemerfce91182008-07-29 12:03:06 -07001569// TODO With method variables, we wouldn't need this dispatch function.
1570func (P *Parser) ParseSpec(exported bool, keyword int) {
1571 switch keyword {
1572 case Scanner.CONST: P.ParseConstSpec(exported);
1573 case Scanner.TYPE: P.ParseTypeSpec(exported);
1574 case Scanner.VAR: P.ParseVarSpec(exported);
1575 default: panic "UNREACHABLE";
1576 }
1577}
1578
1579
1580func (P *Parser) ParseDecl(exported bool, keyword int) {
1581 P.Trace("Decl");
Robert Griesemera6f87792008-07-15 15:37:14 -07001582
Robert Griesemerfce91182008-07-29 12:03:06 -07001583 P.Expect(keyword);
Robert Griesemer0cee3022008-07-15 10:05:17 -07001584 if P.tok == Scanner.LPAREN {
1585 P.Next();
Robert Griesemerf03deb32008-07-24 17:00:58 -07001586 for P.tok == Scanner.IDENT {
Robert Griesemerfce91182008-07-29 12:03:06 -07001587 P.ParseSpec(exported, keyword);
Robert Griesemer0cee3022008-07-15 10:05:17 -07001588 if P.tok != Scanner.RPAREN {
1589 P.Expect(Scanner.SEMICOLON);
1590 }
1591 }
1592 P.Next();
1593 } else {
Robert Griesemerfce91182008-07-29 12:03:06 -07001594 P.ParseSpec(exported, keyword);
Robert Griesemer0cee3022008-07-15 10:05:17 -07001595 }
Robert Griesemera6f87792008-07-15 15:37:14 -07001596
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001597 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -07001598}
1599
1600
Robert Griesemer5fc79192008-07-25 11:27:13 -07001601func (P *Parser) ParseFuncDecl(exported bool) {
Robert Griesemer835cd462008-07-07 17:27:14 -07001602 P.Trace("FuncDecl");
Robert Griesemera6f87792008-07-15 15:37:14 -07001603
Robert Griesemer835cd462008-07-07 17:27:14 -07001604 P.Expect(Scanner.FUNC);
1605 P.ParseNamedSignature();
1606 if P.tok == Scanner.SEMICOLON {
1607 // forward declaration
1608 P.Next();
1609 } else {
1610 P.ParseBlock();
1611 }
Robert Griesemera6f87792008-07-15 15:37:14 -07001612
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001613 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -07001614}
1615
1616
1617func (P *Parser) ParseExportDecl() {
1618 P.Trace("ExportDecl");
Robert Griesemera6f87792008-07-15 15:37:14 -07001619
Robert Griesemerf03deb32008-07-24 17:00:58 -07001620 // TODO this needs to be clarified - the current syntax is
1621 // "everything goes" - sigh...
Robert Griesemer5fc79192008-07-25 11:27:13 -07001622 //P.Expect(Scanner.EXPORT);
Robert Griesemerf03deb32008-07-24 17:00:58 -07001623 has_paren := false;
Robert Griesemer33069d392008-07-09 10:16:33 -07001624 if P.tok == Scanner.LPAREN {
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001625 P.Next();
Robert Griesemerf03deb32008-07-24 17:00:58 -07001626 has_paren = true;
1627 }
1628 for P.tok == Scanner.IDENT {
Robert Griesemerc3e9c7d2008-07-17 18:02:10 -07001629 P.exports.AddStr(P.ParseIdent());
Robert Griesemerf03deb32008-07-24 17:00:58 -07001630 P.Optional(Scanner.COMMA); // TODO this seems wrong
1631 }
1632 if has_paren {
1633 P.Expect(Scanner.RPAREN)
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001634 }
Robert Griesemera6f87792008-07-15 15:37:14 -07001635
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001636 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -07001637}
1638
1639
1640func (P *Parser) ParseDeclaration() {
1641 P.Trace("Declaration");
Robert Griesemer415397e2008-07-09 14:48:26 -07001642 indent := P.indent;
Robert Griesemer5fc79192008-07-25 11:27:13 -07001643
1644 exported := false;
1645 if P.tok == Scanner.EXPORT {
1646 P.Next();
1647 exported = true;
1648 }
Robert Griesemer835cd462008-07-07 17:27:14 -07001649 switch P.tok {
Robert Griesemerfce91182008-07-29 12:03:06 -07001650 case Scanner.CONST, Scanner.TYPE, Scanner.VAR:
1651 P.ParseDecl(exported, P.tok);
Robert Griesemer835cd462008-07-07 17:27:14 -07001652 case Scanner.FUNC:
Robert Griesemer5fc79192008-07-25 11:27:13 -07001653 P.ParseFuncDecl(exported);
Robert Griesemer835cd462008-07-07 17:27:14 -07001654 case Scanner.EXPORT:
Robert Griesemer5fc79192008-07-25 11:27:13 -07001655 if exported {
1656 P.Error(P.pos, "cannot mark export declaration for export");
1657 }
1658 P.Next();
Robert Griesemer835cd462008-07-07 17:27:14 -07001659 P.ParseExportDecl();
1660 default:
Robert Griesemer5fc79192008-07-25 11:27:13 -07001661 if exported && (P.tok == Scanner.IDENT || P.tok == Scanner.LPAREN) {
1662 P.ParseExportDecl();
1663 } else {
1664 P.Error(P.pos, "declaration expected");
1665 P.Next(); // make progress
1666 }
Robert Griesemer835cd462008-07-07 17:27:14 -07001667 }
Robert Griesemer5fc79192008-07-25 11:27:13 -07001668
Robert Griesemer415397e2008-07-09 14:48:26 -07001669 if indent != P.indent {
Robert Griesemerfda1d162008-07-23 16:59:06 -07001670 panic "imbalanced tracing code (Declaration)"
Robert Griesemer415397e2008-07-09 14:48:26 -07001671 }
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001672 P.Ecart();
1673}
1674
1675
Robert Griesemer0cee3022008-07-15 10:05:17 -07001676// ----------------------------------------------------------------------------
1677// Program
Robert Griesemer835cd462008-07-07 17:27:14 -07001678
Robert Griesemerfce91182008-07-29 12:03:06 -07001679func (P *Parser) ResolveUndefTypes() {
1680 if !EnableSemanticTests {
1681 return;
1682 }
1683
1684 for p := P.undef_types.first; p != nil; p = p.next {
1685 typ := p.typ;
1686 if typ.form != Type.POINTER {
1687 panic "unresolved types should be pointers only";
1688 }
1689 if typ.elt.form != Type.UNDEF {
1690 panic "unresolved pointer should point to undefined type";
1691 }
1692 obj := typ.elt.obj;
1693 typ.elt = obj.typ;
1694 if typ.elt.form == Type.UNDEF {
1695 P.Error(obj.pos, `"` + obj.ident + `" is not declared`);
1696 }
1697 }
1698}
1699
1700
Robert Griesemerc3e9c7d2008-07-17 18:02:10 -07001701func (P *Parser) MarkExports() {
1702 if !EnableSemanticTests {
1703 return;
1704 }
1705
1706 scope := P.top_scope;
1707 for p := P.exports.first; p != nil; p = p.next {
1708 obj := scope.Lookup(p.str);
1709 if obj != nil {
Robert Griesemerfce91182008-07-29 12:03:06 -07001710 obj.exported = true;
Robert Griesemerc3e9c7d2008-07-17 18:02:10 -07001711 // For now we export deep
1712 // TODO this should change eventually - we need selective export
1713 if obj.kind == Object.TYPE {
1714 typ := obj.typ;
1715 if typ.form == Type.STRUCT || typ.form == Type.INTERFACE {
1716 scope := typ.scope;
1717 for p := scope.entries.first; p != nil; p = p.next {
Robert Griesemerfce91182008-07-29 12:03:06 -07001718 p.obj.exported = true;
Robert Griesemerc3e9c7d2008-07-17 18:02:10 -07001719 }
1720 }
1721 }
1722 } else {
1723 // TODO need to report proper src position
1724 P.Error(0, `"` + p.str + `" is not declared - cannot be exported`);
1725 }
1726 }
1727}
1728
1729
Robert Griesemer835cd462008-07-07 17:27:14 -07001730func (P *Parser) ParseProgram() {
1731 P.Trace("Program");
Robert Griesemerc3e9c7d2008-07-17 18:02:10 -07001732
Robert Griesemer230230c2008-07-14 18:06:41 -07001733 P.OpenScope();
Robert Griesemer835cd462008-07-07 17:27:14 -07001734 P.Expect(Scanner.PACKAGE);
Robert Griesemerc3e9c7d2008-07-17 18:02:10 -07001735 pkg := P.comp.pkgs[0];
1736 pkg.obj = P.ParseIdentDecl(Object.PACKAGE);
Robert Griesemerafbf7172008-07-10 18:05:00 -07001737 P.Optional(Scanner.SEMICOLON);
1738
Robert Griesemer230230c2008-07-14 18:06:41 -07001739 { P.OpenScope();
Robert Griesemerc3e9c7d2008-07-17 18:02:10 -07001740 pkg.scope = P.top_scope;
Robert Griesemer230230c2008-07-14 18:06:41 -07001741 for P.tok == Scanner.IMPORT {
1742 P.ParseImportDecl();
1743 P.Optional(Scanner.SEMICOLON);
1744 }
1745
1746 for P.tok != Scanner.EOF {
1747 P.ParseDeclaration();
1748 P.Optional(Scanner.SEMICOLON);
1749 }
Robert Griesemerc3e9c7d2008-07-17 18:02:10 -07001750
Robert Griesemerfce91182008-07-29 12:03:06 -07001751 P.ResolveUndefTypes();
Robert Griesemerc3e9c7d2008-07-17 18:02:10 -07001752 P.MarkExports();
Robert Griesemer230230c2008-07-14 18:06:41 -07001753 P.CloseScope();
Robert Griesemer835cd462008-07-07 17:27:14 -07001754 }
Robert Griesemerafbf7172008-07-10 18:05:00 -07001755
Robert Griesemer230230c2008-07-14 18:06:41 -07001756 P.CloseScope();
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001757 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -07001758}