blob: dc80cb878726cd1bfa03e686c1b93537604b1d54 [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 Griesemer835cd462008-07-07 17:27:14 -070012
13
Robert Griesemera6f87792008-07-15 15:37:14 -070014// So I can submit and have a running parser for now...
15const EnableSemanticTests = false;
16
17
Robert Griesemer835cd462008-07-07 17:27:14 -070018export Parser
19type Parser struct {
Robert Griesemerc40be3b2008-07-08 16:39:04 -070020 verbose, indent int;
Robert Griesemer835cd462008-07-07 17:27:14 -070021 S *Scanner.Scanner;
22 tok int; // one token look-ahead
23 beg, end int; // token position
Robert Griesemerc40be3b2008-07-08 16:39:04 -070024 ident string; // last ident seen
Robert Griesemer230230c2008-07-14 18:06:41 -070025 top_scope *Globals.Scope;
Robert Griesemer835cd462008-07-07 17:27:14 -070026}
27
28
Robert Griesemera6f87792008-07-15 15:37:14 -070029// ----------------------------------------------------------------------------
30// Support functions
31
Robert Griesemerc40be3b2008-07-08 16:39:04 -070032func (P *Parser) PrintIndent() {
33 for i := P.indent; i > 0; i-- {
Robert Griesemer415397e2008-07-09 14:48:26 -070034 print ". ";
Robert Griesemerc40be3b2008-07-08 16:39:04 -070035 }
36}
37
38
39func (P *Parser) Trace(msg string) {
40 if P.verbose > 0 {
41 P.PrintIndent();
42 print msg, " {\n";
43 P.indent++;
44 }
45}
46
47
48func (P *Parser) Ecart() {
49 if P.verbose > 0 {
50 P.indent--;
51 P.PrintIndent();
52 print "}\n";
53 }
54}
55
56
57func (P *Parser) Next() {
58 P.tok, P.beg, P.end = P.S.Scan();
59 if P.tok == Scanner.IDENT {
60 P.ident = P.S.src[P.beg : P.end];
61 }
62 if P.verbose > 1 {
63 P.PrintIndent();
Robert Griesemera6f87792008-07-15 15:37:14 -070064 print "[", P.beg, "] ", Scanner.TokenName(P.tok), "\n";
Robert Griesemerc40be3b2008-07-08 16:39:04 -070065 }
66}
67
68
69func (P *Parser) Open(S *Scanner.Scanner, verbose int) {
Robert Griesemer835cd462008-07-07 17:27:14 -070070 P.verbose = verbose;
Robert Griesemerc40be3b2008-07-08 16:39:04 -070071 P.indent = 0;
Robert Griesemer835cd462008-07-07 17:27:14 -070072 P.S = S;
73 P.Next();
Robert Griesemer230230c2008-07-14 18:06:41 -070074 P.top_scope = Universe.scope;
Robert Griesemer835cd462008-07-07 17:27:14 -070075}
76
77
Robert Griesemer8be580e2008-07-10 14:42:33 -070078func (P *Parser) Error(pos int, msg string) {
79 P.S.Error(pos, msg);
Robert Griesemer835cd462008-07-07 17:27:14 -070080}
81
82
83func (P *Parser) Expect(tok int) {
Robert Griesemera6f87792008-07-15 15:37:14 -070084 if P.tok != tok {
Robert Griesemer8be580e2008-07-10 14:42:33 -070085 P.Error(P.beg, "expected '" + Scanner.TokenName(tok) + "', found '" + Scanner.TokenName(P.tok) + "'");
Robert Griesemer835cd462008-07-07 17:27:14 -070086 }
Robert Griesemera6f87792008-07-15 15:37:14 -070087 P.Next(); // make progress in any case
Robert Griesemer835cd462008-07-07 17:27:14 -070088}
89
90
Robert Griesemer8e4ee002008-07-08 18:37:31 -070091func (P *Parser) Optional(tok int) {
92 if P.tok == tok {
93 P.Next();
94 }
95}
96
97
Robert Griesemer230230c2008-07-14 18:06:41 -070098// ----------------------------------------------------------------------------
Robert Griesemera6f87792008-07-15 15:37:14 -070099// Scopes
Robert Griesemer230230c2008-07-14 18:06:41 -0700100
101func (P *Parser) OpenScope() {
102 P.top_scope = Globals.NewScope(P.top_scope);
103}
104
105
106func (P *Parser) CloseScope() {
107 P.top_scope = P.top_scope.parent;
108}
109
110
111func (P *Parser) Lookup(ident string) *Globals.Object {
112 for scope := P.top_scope; scope != nil; scope = scope.parent {
113 obj := scope.Lookup(ident);
114 if obj != nil {
115 return obj;
116 }
117 }
118 return nil;
119}
120
121
122func (P *Parser) DeclareInScope(scope *Globals.Scope, obj *Globals.Object) {
Robert Griesemera6f87792008-07-15 15:37:14 -0700123 if !EnableSemanticTests {
124 return;
125 }
126
Robert Griesemer230230c2008-07-14 18:06:41 -0700127 if scope.Lookup(obj.ident) != nil {
128 // TODO is this the correct error position?
Robert Griesemera6f87792008-07-15 15:37:14 -0700129 P.Error(obj.pos, `"` + obj.ident + `" is declared already`);
Robert Griesemer230230c2008-07-14 18:06:41 -0700130 return; // don't insert it into the scope
131 }
132 scope.Insert(obj);
133}
134
135
136func (P *Parser) Declare(obj *Globals.Object) {
137 P.DeclareInScope(P.top_scope, obj);
138}
139
140
141// ----------------------------------------------------------------------------
Robert Griesemer0cee3022008-07-15 10:05:17 -0700142// Common productions
143
Robert Griesemer230230c2008-07-14 18:06:41 -0700144
Robert Griesemera6f87792008-07-15 15:37:14 -0700145func (P *Parser) TryType() *Globals.Type;
Robert Griesemer835cd462008-07-07 17:27:14 -0700146func (P *Parser) ParseExpression();
Robert Griesemer0cee3022008-07-15 10:05:17 -0700147func (P *Parser) TryStatement() bool;
148func (P *Parser) ParseDeclaration();
Robert Griesemer835cd462008-07-07 17:27:14 -0700149
150
Robert Griesemera6f87792008-07-15 15:37:14 -0700151func (P *Parser) ParseIdent() string {
152 P.Trace("Ident");
153
154 ident := "";
155 if P.tok == Scanner.IDENT {
156 ident = P.ident;
157 if P.verbose > 0 {
158 P.PrintIndent();
159 print "Ident = \"", ident, "\"\n";
160 }
161 P.Next();
162 } else {
163 P.Expect(Scanner.IDENT); // use Expect() error handling
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700164 }
Robert Griesemera6f87792008-07-15 15:37:14 -0700165
166 P.Ecart();
167 return ident;
168}
169
170
171func (P *Parser) ParseIdentDecl(kind int) *Globals.Object {
172 P.Trace("IdentDecl");
173
174 pos := P.beg;
175 obj := Globals.NewObject(pos, kind, P.ParseIdent());
176 P.Declare(obj);
177
178 P.Ecart();
179 return obj;
180}
181
182
183func (P *Parser) ParseIdentDeclList(kind int) *Globals.List {
184 P.Trace("IdentDeclList");
185
186 list := Globals.NewList();
187 list.AddObj(P.ParseIdentDecl(kind));
188 for P.tok == Scanner.COMMA {
189 P.Next();
190 list.AddObj(P.ParseIdentDecl(kind));
191 }
192
193 P.Ecart();
194 return list;
Robert Griesemer835cd462008-07-07 17:27:14 -0700195}
196
197
198func (P *Parser) ParseIdentList() {
199 P.Trace("IdentList");
200 P.ParseIdent();
201 for P.tok == Scanner.COMMA {
202 P.Next();
203 P.ParseIdent();
204 }
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700205 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700206}
207
208
Robert Griesemera6f87792008-07-15 15:37:14 -0700209func (P *Parser) ParseQualifiedIdent() *Globals.Object {
Robert Griesemer835cd462008-07-07 17:27:14 -0700210 P.Trace("QualifiedIdent");
Robert Griesemera6f87792008-07-15 15:37:14 -0700211
212 if EnableSemanticTests {
213 pos := P.beg;
214 ident := P.ParseIdent();
215 obj := P.Lookup(ident);
216 if obj == nil {
217 P.Error(pos, `"` + ident + `" is not declared`);
218 obj = Globals.NewObject(pos, Object.BAD, ident);
219 }
220
221 if obj.kind == Object.PACKAGE && P.tok == Scanner.PERIOD {
222 panic "Qualified ident not complete yet";
223 P.Next();
224 P.ParseIdent();
225 }
226 P.Ecart();
227 return obj;
228
229 } else {
Robert Griesemer835cd462008-07-07 17:27:14 -0700230 P.ParseIdent();
Robert Griesemera6f87792008-07-15 15:37:14 -0700231 if P.tok == Scanner.PERIOD {
232 P.Next();
233 P.ParseIdent();
234 }
235 P.Ecart();
236 return nil;
Robert Griesemer835cd462008-07-07 17:27:14 -0700237 }
238}
239
240
Robert Griesemer0cee3022008-07-15 10:05:17 -0700241// ----------------------------------------------------------------------------
242// Types
Robert Griesemer835cd462008-07-07 17:27:14 -0700243
Robert Griesemera6f87792008-07-15 15:37:14 -0700244func (P *Parser) ParseType() *Globals.Type{
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700245 P.Trace("Type");
Robert Griesemera6f87792008-07-15 15:37:14 -0700246
247 typ := P.TryType();
248 if typ == nil {
Robert Griesemer8be580e2008-07-10 14:42:33 -0700249 P.Error(P.beg, "type expected");
Robert Griesemera6f87792008-07-15 15:37:14 -0700250 typ = Universe.bad_t;
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700251 }
Robert Griesemera6f87792008-07-15 15:37:14 -0700252
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700253 P.Ecart();
Robert Griesemera6f87792008-07-15 15:37:14 -0700254 return typ;
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700255}
256
257
Robert Griesemera6f87792008-07-15 15:37:14 -0700258func (P *Parser) ParseTypeName() *Globals.Type {
Robert Griesemer0cee3022008-07-15 10:05:17 -0700259 P.Trace("TypeName");
Robert Griesemera6f87792008-07-15 15:37:14 -0700260
261 if EnableSemanticTests {
262 obj := P.ParseQualifiedIdent();
263 typ := obj.typ;
264 if obj.kind != Object.TYPE {
265 P.Error(obj.pos, `"` + obj.ident + `" is not a type`);
266 typ = Universe.bad_t;
267 }
268 P.Ecart();
269 return typ;
270 } else {
271 P.ParseQualifiedIdent();
272 P.Ecart();
273 return Universe.bad_t;
274 }
Robert Griesemer0cee3022008-07-15 10:05:17 -0700275}
276
277
Robert Griesemera6f87792008-07-15 15:37:14 -0700278func (P *Parser) ParseArrayType() *Globals.Type {
Robert Griesemer835cd462008-07-07 17:27:14 -0700279 P.Trace("ArrayType");
280 P.Expect(Scanner.LBRACK);
281 if P.tok != Scanner.RBRACK {
282 P.ParseExpression();
283 }
284 P.Expect(Scanner.RBRACK);
285 P.ParseType();
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700286 P.Ecart();
Robert Griesemera6f87792008-07-15 15:37:14 -0700287 return Universe.bad_t;
Robert Griesemer835cd462008-07-07 17:27:14 -0700288}
289
290
Robert Griesemera6f87792008-07-15 15:37:14 -0700291func (P *Parser) ParseChannelType() *Globals.Type {
Robert Griesemer835cd462008-07-07 17:27:14 -0700292 P.Trace("ChannelType");
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700293 P.Expect(Scanner.CHAN);
294 switch P.tok {
295 case Scanner.LSS: fallthrough
296 case Scanner.GTR:
297 P.Next();
298 }
299 P.ParseType();
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700300 P.Ecart();
Robert Griesemera6f87792008-07-15 15:37:14 -0700301 return Universe.bad_t;
Robert Griesemer835cd462008-07-07 17:27:14 -0700302}
303
304
Robert Griesemer835cd462008-07-07 17:27:14 -0700305func (P *Parser) ParseParameterSection() {
306 P.Trace("ParameterSection");
307 P.ParseIdentList();
308 P.ParseType();
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700309 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700310}
311
312
313func (P *Parser) ParseParameterList() {
314 P.Trace("ParameterList");
315 P.ParseParameterSection();
316 for P.tok == Scanner.COMMA {
317 P.Next();
318 P.ParseParameterSection();
319 }
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700320 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700321}
322
323
324func (P *Parser) ParseParameters() {
325 P.Trace("Parameters");
326 P.Expect(Scanner.LPAREN);
327 if P.tok != Scanner.RPAREN {
328 P.ParseParameterList();
329 }
330 P.Expect(Scanner.RPAREN);
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700331 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700332}
333
334
Robert Griesemer1e9adf82008-07-09 10:45:04 -0700335func (P *Parser) TryResult() bool {
336 P.Trace("Result (try)");
337 res := false;
Robert Griesemer835cd462008-07-07 17:27:14 -0700338 if P.tok == Scanner.LPAREN {
339 // TODO: here we allow empty returns - should proably fix this
340 P.ParseParameters();
Robert Griesemer1e9adf82008-07-09 10:45:04 -0700341 res = true;
Robert Griesemer835cd462008-07-07 17:27:14 -0700342 } else {
Robert Griesemera6f87792008-07-15 15:37:14 -0700343 res = P.TryType() != nil;
Robert Griesemer835cd462008-07-07 17:27:14 -0700344 }
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700345 P.Ecart();
Robert Griesemer1e9adf82008-07-09 10:45:04 -0700346 return res;
347}
348
349
350// Anonymous signatures
351//
352// (params)
353// (params) type
354// (params) (results)
355// (recv) . (params)
356// (recv) . (params) type
357// (recv) . (params) (results)
358
359func (P *Parser) ParseAnonymousSignature() {
360 P.Trace("AnonymousSignature");
Robert Griesemer230230c2008-07-14 18:06:41 -0700361 P.OpenScope();
Robert Griesemer1e9adf82008-07-09 10:45:04 -0700362 P.ParseParameters();
363 if P.tok == Scanner.PERIOD {
364 P.Next();
365 P.ParseParameters();
366 }
367 P.TryResult();
Robert Griesemer230230c2008-07-14 18:06:41 -0700368 P.CloseScope();
Robert Griesemer1e9adf82008-07-09 10:45:04 -0700369 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700370}
371
372
373// Named signatures
374//
375// name (params)
376// name (params) type
377// name (params) (results)
378// (recv) name (params)
379// (recv) name (params) type
380// (recv) name (params) (results)
381
382func (P *Parser) ParseNamedSignature() {
383 P.Trace("NamedSignature");
Robert Griesemer230230c2008-07-14 18:06:41 -0700384 P.OpenScope();
Robert Griesemer835cd462008-07-07 17:27:14 -0700385 if P.tok == Scanner.LPAREN {
386 P.ParseParameters();
387 }
Robert Griesemer835cd462008-07-07 17:27:14 -0700388 P.ParseIdent(); // function name
Robert Griesemer835cd462008-07-07 17:27:14 -0700389 P.ParseParameters();
Robert Griesemer1e9adf82008-07-09 10:45:04 -0700390 P.TryResult();
Robert Griesemer230230c2008-07-14 18:06:41 -0700391 P.CloseScope();
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700392 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700393}
394
395
Robert Griesemera6f87792008-07-15 15:37:14 -0700396func (P *Parser) ParseFunctionType() *Globals.Type {
Robert Griesemer0cee3022008-07-15 10:05:17 -0700397 P.Trace("FunctionType");
398 P.Expect(Scanner.FUNC);
399 P.ParseAnonymousSignature();
400 P.Ecart();
Robert Griesemera6f87792008-07-15 15:37:14 -0700401 return Universe.bad_t;
Robert Griesemer0cee3022008-07-15 10:05:17 -0700402}
403
404
405func (P *Parser) ParseMethodDecl() {
406 P.Trace("MethodDecl");
407 P.ParseIdent();
408 P.ParseParameters();
409 P.TryResult();
410 P.Optional(Scanner.SEMICOLON);
411 P.Ecart();
412}
413
414
Robert Griesemera6f87792008-07-15 15:37:14 -0700415func (P *Parser) ParseInterfaceType() *Globals.Type {
Robert Griesemer0cee3022008-07-15 10:05:17 -0700416 P.Trace("InterfaceType");
417 P.Expect(Scanner.INTERFACE);
418 P.Expect(Scanner.LBRACE);
419 P.OpenScope();
420 for P.tok != Scanner.RBRACE {
421 P.ParseMethodDecl();
422 }
423 P.CloseScope();
424 P.Next();
425 P.Ecart();
Robert Griesemera6f87792008-07-15 15:37:14 -0700426 return Universe.bad_t;
Robert Griesemer0cee3022008-07-15 10:05:17 -0700427}
428
429
Robert Griesemera6f87792008-07-15 15:37:14 -0700430func (P *Parser) ParseMapType() *Globals.Type {
Robert Griesemer0cee3022008-07-15 10:05:17 -0700431 P.Trace("MapType");
432 P.Expect(Scanner.MAP);
433 P.Expect(Scanner.LBRACK);
434 P.ParseType();
435 P.Expect(Scanner.RBRACK);
436 P.ParseType();
437 P.Ecart();
Robert Griesemera6f87792008-07-15 15:37:14 -0700438 return Universe.bad_t;
Robert Griesemer0cee3022008-07-15 10:05:17 -0700439}
440
441
442func (P *Parser) ParseFieldDecl() {
443 P.Trace("FieldDecl");
Robert Griesemera6f87792008-07-15 15:37:14 -0700444
445 list := P.ParseIdentDeclList(Object.VAR);
446 typ := P.ParseType(); // TODO should check completeness of types
447 for p := list.first; p != nil; p = p.next {
448 p.obj.typ = typ; // TODO should use/have set_type()
449 }
450
Robert Griesemer0cee3022008-07-15 10:05:17 -0700451 P.Ecart();
452}
453
454
Robert Griesemera6f87792008-07-15 15:37:14 -0700455func (P *Parser) ParseStructType() *Globals.Type {
Robert Griesemer0cee3022008-07-15 10:05:17 -0700456 P.Trace("StructType");
Robert Griesemera6f87792008-07-15 15:37:14 -0700457
Robert Griesemer0cee3022008-07-15 10:05:17 -0700458 P.Expect(Scanner.STRUCT);
459 P.Expect(Scanner.LBRACE);
460 P.OpenScope();
Robert Griesemera6f87792008-07-15 15:37:14 -0700461 typ := Globals.NewType(Type.STRUCT);
462 typ.scope = P.top_scope;
463 for P.tok == Scanner.IDENT {
Robert Griesemer0cee3022008-07-15 10:05:17 -0700464 P.ParseFieldDecl();
465 if P.tok != Scanner.RBRACE {
466 P.Expect(Scanner.SEMICOLON);
467 }
468 }
469 P.Optional(Scanner.SEMICOLON);
470 P.CloseScope();
471 P.Expect(Scanner.RBRACE);
Robert Griesemera6f87792008-07-15 15:37:14 -0700472
Robert Griesemer0cee3022008-07-15 10:05:17 -0700473 P.Ecart();
Robert Griesemera6f87792008-07-15 15:37:14 -0700474 return typ;
Robert Griesemer0cee3022008-07-15 10:05:17 -0700475}
476
477
Robert Griesemera6f87792008-07-15 15:37:14 -0700478func (P *Parser) ParsePointerType() *Globals.Type {
Robert Griesemer0cee3022008-07-15 10:05:17 -0700479 P.Trace("PointerType");
480 P.Expect(Scanner.MUL);
481 P.ParseType();
482 P.Ecart();
Robert Griesemera6f87792008-07-15 15:37:14 -0700483 return Universe.bad_t;
Robert Griesemer0cee3022008-07-15 10:05:17 -0700484}
485
486
Robert Griesemera6f87792008-07-15 15:37:14 -0700487// Returns nil if no type was found.
488func (P *Parser) TryType() *Globals.Type {
Robert Griesemer0cee3022008-07-15 10:05:17 -0700489 P.Trace("Type (try)");
Robert Griesemera6f87792008-07-15 15:37:14 -0700490
491 var typ *Globals.Type = nil;
Robert Griesemer0cee3022008-07-15 10:05:17 -0700492 switch P.tok {
Robert Griesemera6f87792008-07-15 15:37:14 -0700493 case Scanner.IDENT: typ = P.ParseTypeName();
494 case Scanner.LBRACK: typ = P.ParseArrayType();
495 case Scanner.CHAN: typ = P.ParseChannelType();
496 case Scanner.INTERFACE: typ = P.ParseInterfaceType();
497 case Scanner.FUNC: typ = P.ParseFunctionType();
498 case Scanner.MAP: typ = P.ParseMapType();
499 case Scanner.STRUCT: typ = P.ParseStructType();
500 case Scanner.MUL: typ = P.ParsePointerType();
Robert Griesemer0cee3022008-07-15 10:05:17 -0700501 }
Robert Griesemera6f87792008-07-15 15:37:14 -0700502
Robert Griesemer0cee3022008-07-15 10:05:17 -0700503 P.Ecart();
Robert Griesemera6f87792008-07-15 15:37:14 -0700504 return typ;
Robert Griesemer0cee3022008-07-15 10:05:17 -0700505}
506
507
508// ----------------------------------------------------------------------------
509// Blocks
510
511func (P *Parser) ParseStatement() {
512 P.Trace("Statement");
513 if !P.TryStatement() {
514 P.Error(P.beg, "statement expected");
Robert Griesemera6f87792008-07-15 15:37:14 -0700515 P.Next(); // make progress
Robert Griesemer0cee3022008-07-15 10:05:17 -0700516 }
517 P.Ecart();
518}
519
520
521func (P *Parser) ParseStatementList() {
522 P.Trace("StatementList");
523 for P.TryStatement() {
524 P.Optional(Scanner.SEMICOLON);
525 }
526 P.Ecart();
527}
528
529
530func (P *Parser) ParseBlock() {
531 P.Trace("Block");
532 P.Expect(Scanner.LBRACE);
533 P.OpenScope();
534 if P.tok != Scanner.RBRACE && P.tok != Scanner.SEMICOLON {
535 P.ParseStatementList();
536 }
537 P.Optional(Scanner.SEMICOLON);
538 P.CloseScope();
539 P.Expect(Scanner.RBRACE);
540 P.Ecart();
541}
542
543
544// ----------------------------------------------------------------------------
545// Expressions
546
547func (P *Parser) ParseExpressionList() {
548 P.Trace("ExpressionList");
549 P.ParseExpression();
550 for P.tok == Scanner.COMMA {
551 P.Next();
552 P.ParseExpression();
553 }
554 P.Ecart();
555}
556
557
558func (P *Parser) ParseNew() {
559 P.Trace("New");
560 P.Expect(Scanner.NEW);
561 P.Expect(Scanner.LPAREN);
562 P.ParseType();
563 if P.tok == Scanner.COMMA {
564 P.Next();
565 P.ParseExpressionList()
566 }
567 P.Expect(Scanner.RPAREN);
568 P.Ecart();
569}
570
571
572func (P *Parser) ParseFunctionLit() {
573 P.Trace("FunctionLit");
574 P.ParseFunctionType();
575 P.ParseBlock();
576 P.Ecart();
577}
578
579
580func (P *Parser) ParseOperand() {
581 P.Trace("Operand");
582 switch P.tok {
583 case Scanner.IDENT:
584 P.ParseQualifiedIdent();
585 case Scanner.LPAREN:
586 P.Next();
587 P.ParseExpression();
588 P.Expect(Scanner.RPAREN);
589 case Scanner.STRING: fallthrough;
590 case Scanner.NUMBER: fallthrough;
591 case Scanner.NIL: fallthrough;
592 case Scanner.IOTA: fallthrough;
593 case Scanner.TRUE: fallthrough;
594 case Scanner.FALSE:
595 P.Next();
596 case Scanner.FUNC:
597 P.ParseFunctionLit();
598 case Scanner.NEW:
599 P.ParseNew();
600 default:
601 P.Error(P.beg, "operand expected");
Robert Griesemera6f87792008-07-15 15:37:14 -0700602 P.Next(); // make progress
Robert Griesemer0cee3022008-07-15 10:05:17 -0700603 }
604 P.Ecart();
605}
606
607
608func (P *Parser) ParseSelectorOrTypeAssertion() {
609 P.Trace("SelectorOrTypeAssertion");
610 P.Expect(Scanner.PERIOD);
611 if P.tok == Scanner.IDENT {
612 P.ParseIdent();
613 } else {
614 P.Expect(Scanner.LPAREN);
615 P.ParseType();
616 P.Expect(Scanner.RPAREN);
617 }
618 P.Ecart();
619}
620
621
622func (P *Parser) ParseIndexOrSlice() {
623 P.Trace("IndexOrSlice");
624 P.Expect(Scanner.LBRACK);
625 P.ParseExpression();
626 if P.tok == Scanner.COLON {
627 P.Next();
628 P.ParseExpression();
629 }
630 P.Expect(Scanner.RBRACK);
631 P.Ecart();
632}
633
634
635func (P *Parser) ParseInvocation() {
636 P.Trace("Invocation");
637 P.Expect(Scanner.LPAREN);
638 if P.tok != Scanner.RPAREN {
639 P.ParseExpressionList();
640 }
641 P.Expect(Scanner.RPAREN);
642 P.Ecart();
643}
644
645
646func (P *Parser) ParsePrimaryExpr() {
647 P.Trace("PrimaryExpr");
648 P.ParseOperand();
649 for {
650 switch P.tok {
651 case Scanner.PERIOD:
652 P.ParseSelectorOrTypeAssertion();
653 case Scanner.LBRACK:
654 P.ParseIndexOrSlice();
655 case Scanner.LPAREN:
656 P.ParseInvocation();
657 default:
658 P.Ecart();
659 return;
660 }
661 }
662 P.Ecart();
663}
Robert Griesemer835cd462008-07-07 17:27:14 -0700664
665
666func (P *Parser) ParsePrimaryExprList() {
667 P.Trace("PrimaryExprList");
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700668 P.ParsePrimaryExpr();
669 for P.tok == Scanner.COMMA {
670 P.Next();
671 P.ParsePrimaryExpr();
672 }
673 P.Ecart();
674}
675
676
Robert Griesemer0cee3022008-07-15 10:05:17 -0700677func (P *Parser) ParseUnaryExpr() {
678 P.Trace("UnaryExpr");
679 switch P.tok {
680 case Scanner.ADD: fallthrough;
681 case Scanner.SUB: fallthrough;
682 case Scanner.NOT: fallthrough;
683 case Scanner.XOR: fallthrough;
684 case Scanner.LSS: fallthrough;
685 case Scanner.GTR: fallthrough;
686 case Scanner.MUL: fallthrough;
687 case Scanner.AND:
688 P.Next();
689 P.ParseUnaryExpr();
690 P.Ecart();
691 return;
692 }
693 P.ParsePrimaryExpr();
694 P.Ecart();
695}
696
697
698func Precedence(tok int) int {
699 // TODO should use a map or array here for lookup
700 switch tok {
701 case Scanner.LOR:
702 return 1;
703 case Scanner.LAND:
704 return 2;
705 case Scanner.EQL, Scanner.NEQ, Scanner.LSS, Scanner.LEQ, Scanner.GTR, Scanner.GEQ:
706 return 3;
707 case Scanner.ADD, Scanner.SUB, Scanner.OR, Scanner.XOR:
708 return 4;
709 case Scanner.MUL, Scanner.QUO, Scanner.REM, Scanner.SHL, Scanner.SHR, Scanner.AND:
710 return 5;
711 }
712 return 0;
713}
714
715
716func (P *Parser) ParseBinaryExpr(prec1 int) {
717 P.Trace("BinaryExpr");
718 P.ParseUnaryExpr();
719 for prec := Precedence(P.tok); prec >= prec1; prec-- {
720 for Precedence(P.tok) == prec {
721 P.Next();
722 P.ParseBinaryExpr(prec + 1);
723 }
724 }
725 P.Ecart();
726}
727
728
729func (P *Parser) ParseExpression() {
730 P.Trace("Expression");
731 indent := P.indent;
732 P.ParseBinaryExpr(1);
733 if indent != P.indent {
734 panic "imbalanced tracing code";
735 }
736 P.Ecart();
737}
738
739
740// ----------------------------------------------------------------------------
741// Statements
742
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700743func (P *Parser) ParseBuiltinStat() {
744 P.Trace("BuiltinStat");
745 P.Expect(Scanner.IDENT);
746 P.ParseExpressionList(); // TODO should be optional
747 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700748}
749
750
751func (P *Parser) ParseSimpleStat() {
752 P.Trace("SimpleStat");
753 P.ParseExpression();
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700754 if P.tok == Scanner.COLON {
Robert Griesemer835cd462008-07-07 17:27:14 -0700755 P.Next();
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700756 P.Ecart();
757 return;
758 }
759 if P.tok == Scanner.COMMA {
Robert Griesemer835cd462008-07-07 17:27:14 -0700760 P.Next();
761 P.ParsePrimaryExprList();
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700762 }
763 switch P.tok {
764 case Scanner.ASSIGN: fallthrough;
765 case Scanner.DEFINE: fallthrough;
766 case Scanner.ADD_ASSIGN: fallthrough;
767 case Scanner.SUB_ASSIGN: fallthrough;
768 case Scanner.MUL_ASSIGN: fallthrough;
769 case Scanner.QUO_ASSIGN: fallthrough;
770 case Scanner.REM_ASSIGN: fallthrough;
771 case Scanner.AND_ASSIGN: fallthrough;
772 case Scanner.OR_ASSIGN: fallthrough;
773 case Scanner.XOR_ASSIGN: fallthrough;
774 case Scanner.SHL_ASSIGN: fallthrough;
775 case Scanner.SHR_ASSIGN:
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700776 P.Next();
777 P.ParseExpressionList();
Robert Griesemer835cd462008-07-07 17:27:14 -0700778 case Scanner.INC:
779 P.Next();
780 case Scanner.DEC:
781 P.Next();
782 }
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700783 P.Ecart();
784}
785
786
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700787func (P *Parser) ParseGoStat() {
788 P.Trace("GoStat");
789 P.Expect(Scanner.GO);
790 P.ParseExpression();
Robert Griesemer415397e2008-07-09 14:48:26 -0700791 P.Ecart();
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700792}
793
794
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700795func (P *Parser) ParseReturnStat() {
796 P.Trace("ReturnStat");
797 P.Expect(Scanner.RETURN);
798 if P.tok != Scanner.SEMICOLON && P.tok != Scanner.RBRACE {
799 P.ParseExpressionList();
800 }
801 P.Ecart();
802}
803
804
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700805func (P *Parser) ParseControlFlowStat(tok int) {
806 P.Trace("ControlFlowStat");
807 P.Expect(tok);
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700808 if P.tok == Scanner.IDENT {
809 P.ParseIdent();
810 }
811 P.Ecart();
812}
813
814
Robert Griesemer835cd462008-07-07 17:27:14 -0700815func (P *Parser) ParseIfStat() {
816 P.Trace("IfStat");
817 P.Expect(Scanner.IF);
Robert Griesemer230230c2008-07-14 18:06:41 -0700818 P.OpenScope();
Robert Griesemer835cd462008-07-07 17:27:14 -0700819 if P.tok != Scanner.LBRACE {
Robert Griesemerae905982008-07-10 20:50:38 -0700820 if P.tok != Scanner.SEMICOLON {
821 P.ParseSimpleStat();
822 }
Robert Griesemer835cd462008-07-07 17:27:14 -0700823 if P.tok == Scanner.SEMICOLON {
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700824 P.Next();
Robert Griesemerae905982008-07-10 20:50:38 -0700825 if P.tok != Scanner.LBRACE {
826 P.ParseExpression();
827 }
Robert Griesemer835cd462008-07-07 17:27:14 -0700828 }
829 }
830 P.ParseBlock();
831 if P.tok == Scanner.ELSE {
832 P.Next();
833 if P.tok == Scanner.IF {
834 P.ParseIfStat();
835 } else {
836 // TODO should be P.ParseBlock()
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700837 P.ParseStatement();
Robert Griesemer835cd462008-07-07 17:27:14 -0700838 }
839 }
Robert Griesemer230230c2008-07-14 18:06:41 -0700840 P.CloseScope();
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700841 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700842}
843
844
845func (P *Parser) ParseForStat() {
846 P.Trace("ForStat");
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700847 P.Expect(Scanner.FOR);
Robert Griesemer230230c2008-07-14 18:06:41 -0700848 P.OpenScope();
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700849 if P.tok != Scanner.LBRACE {
850 if P.tok != Scanner.SEMICOLON {
851 P.ParseSimpleStat();
852 }
853 if P.tok == Scanner.SEMICOLON {
854 P.Next();
855 if P.tok != Scanner.SEMICOLON {
856 P.ParseExpression();
857 }
858 P.Expect(Scanner.SEMICOLON);
859 if P.tok != Scanner.LBRACE {
860 P.ParseSimpleStat();
861 }
862 }
863 }
864 P.ParseBlock();
Robert Griesemer230230c2008-07-14 18:06:41 -0700865 P.CloseScope();
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700866 P.Ecart();
867}
868
869
870func (P *Parser) ParseCase() {
871 P.Trace("Case");
872 if P.tok == Scanner.CASE {
873 P.Next();
874 P.ParseExpressionList();
875 } else {
876 P.Expect(Scanner.DEFAULT);
877 }
878 P.Expect(Scanner.COLON);
879 P.Ecart();
880}
881
882
883func (P *Parser) ParseCaseList() {
884 P.Trace("CaseList");
885 P.ParseCase();
886 for P.tok == Scanner.CASE || P.tok == Scanner.DEFAULT {
887 P.ParseCase();
888 }
889 P.Ecart();
890}
891
892
893func (P *Parser) ParseCaseClause() {
894 P.Trace("CaseClause");
895 P.ParseCaseList();
896 if P.tok != Scanner.FALLTHROUGH && P.tok != Scanner.RBRACE {
897 P.ParseStatementList();
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700898 P.Optional(Scanner.SEMICOLON);
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700899 }
900 if P.tok == Scanner.FALLTHROUGH {
901 P.Next();
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700902 P.Optional(Scanner.SEMICOLON);
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700903 }
904 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700905}
906
907
908func (P *Parser) ParseSwitchStat() {
909 P.Trace("SwitchStat");
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700910 P.Expect(Scanner.SWITCH);
Robert Griesemer230230c2008-07-14 18:06:41 -0700911 P.OpenScope();
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700912 if P.tok != Scanner.LBRACE {
Robert Griesemerae905982008-07-10 20:50:38 -0700913 if P.tok != Scanner.SEMICOLON {
914 P.ParseSimpleStat();
915 }
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700916 if P.tok == Scanner.SEMICOLON {
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700917 P.Next();
Robert Griesemerae905982008-07-10 20:50:38 -0700918 if P.tok != Scanner.LBRACE {
919 P.ParseExpression();
920 }
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700921 }
922 }
923 P.Expect(Scanner.LBRACE);
924 for P.tok != Scanner.RBRACE {
925 P.ParseCaseClause();
926 }
927 P.Expect(Scanner.RBRACE);
Robert Griesemer230230c2008-07-14 18:06:41 -0700928 P.CloseScope();
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700929 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700930}
931
932
Robert Griesemercab94922008-07-09 14:01:17 -0700933func (P *Parser) ParseCommCase() {
934 P.Trace("CommCase");
935 if P.tok == Scanner.CASE {
936 P.Next();
937 if P.tok == Scanner.GTR {
938 // send
939 P.Next();
940 P.ParseExpression();
941 P.Expect(Scanner.EQL);
942 P.ParseExpression();
943 } else {
944 // receive
945 if P.tok != Scanner.LSS {
946 P.ParseIdent();
947 P.Expect(Scanner.ASSIGN);
948 }
949 P.Expect(Scanner.LSS);
950 P.ParseExpression();
951 }
952 } else {
953 P.Expect(Scanner.DEFAULT);
954 }
955 P.Expect(Scanner.COLON);
956 P.Ecart();
957}
958
959
960func (P *Parser) ParseCommClause() {
961 P.Trace("CommClause");
962 P.ParseCommCase();
963 if P.tok != Scanner.CASE && P.tok != Scanner.DEFAULT && P.tok != Scanner.RBRACE {
964 P.ParseStatementList();
965 P.Optional(Scanner.SEMICOLON);
966 }
967 P.Ecart();
968}
969
970
971func (P *Parser) ParseRangeStat() bool {
972 P.Trace("RangeStat");
973 P.Expect(Scanner.RANGE);
974 P.ParseIdentList();
975 P.Expect(Scanner.DEFINE);
976 P.ParseExpression();
977 P.ParseBlock();
978 P.Ecart();
979}
980
981
982func (P *Parser) ParseSelectStat() bool {
983 P.Trace("SelectStat");
984 P.Expect(Scanner.SELECT);
985 P.Expect(Scanner.LBRACE);
986 for P.tok != Scanner.RBRACE {
987 P.ParseCommClause();
988 }
989 P.Next();
990 P.Ecart();
991}
992
993
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700994func (P *Parser) TryStatement() bool {
995 P.Trace("Statement (try)");
Robert Griesemer415397e2008-07-09 14:48:26 -0700996 indent := P.indent;
997 res := true;
Robert Griesemer835cd462008-07-07 17:27:14 -0700998 switch P.tok {
999 case Scanner.CONST: fallthrough;
1000 case Scanner.TYPE: fallthrough;
Robert Griesemerd9d5f3b2008-07-15 09:22:20 -07001001 case Scanner.VAR:
Robert Griesemer835cd462008-07-07 17:27:14 -07001002 P.ParseDeclaration();
Robert Griesemerd9d5f3b2008-07-15 09:22:20 -07001003 case Scanner.FUNC:
1004 // for now we do not allow local function declarations
1005 fallthrough;
Robert Griesemera6f87792008-07-15 15:37:14 -07001006 case Scanner.LSS: fallthrough;
Robert Griesemer8e4ee002008-07-08 18:37:31 -07001007 case Scanner.GTR:
Robert Griesemera6f87792008-07-15 15:37:14 -07001008 P.ParseSimpleStat(); // send or receive
Robert Griesemer835cd462008-07-07 17:27:14 -07001009 case Scanner.IDENT:
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001010 switch P.ident {
1011 case "print", "panic":
1012 P.ParseBuiltinStat();
1013 default:
1014 P.ParseSimpleStat();
1015 }
Robert Griesemer835cd462008-07-07 17:27:14 -07001016 case Scanner.GO:
Robert Griesemer8e4ee002008-07-08 18:37:31 -07001017 P.ParseGoStat();
Robert Griesemer835cd462008-07-07 17:27:14 -07001018 case Scanner.RETURN:
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001019 P.ParseReturnStat();
Robert Griesemer8e4ee002008-07-08 18:37:31 -07001020 case Scanner.BREAK, Scanner.CONTINUE, Scanner.GOTO:
1021 P.ParseControlFlowStat(P.tok);
Robert Griesemer835cd462008-07-07 17:27:14 -07001022 case Scanner.LBRACE:
1023 P.ParseBlock();
1024 case Scanner.IF:
1025 P.ParseIfStat();
1026 case Scanner.FOR:
1027 P.ParseForStat();
1028 case Scanner.SWITCH:
1029 P.ParseSwitchStat();
1030 case Scanner.RANGE:
Robert Griesemercab94922008-07-09 14:01:17 -07001031 P.ParseRangeStat();
Robert Griesemer835cd462008-07-07 17:27:14 -07001032 case Scanner.SELECT:
Robert Griesemercab94922008-07-09 14:01:17 -07001033 P.ParseSelectStat();
Robert Griesemer835cd462008-07-07 17:27:14 -07001034 default:
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001035 // no statement found
Robert Griesemer415397e2008-07-09 14:48:26 -07001036 res = false;
1037 }
1038 if indent != P.indent {
1039 panic "imbalanced tracing code"
Robert Griesemer835cd462008-07-07 17:27:14 -07001040 }
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001041 P.Ecart();
Robert Griesemer415397e2008-07-09 14:48:26 -07001042 return res;
Robert Griesemer835cd462008-07-07 17:27:14 -07001043}
1044
1045
Robert Griesemer0cee3022008-07-15 10:05:17 -07001046// ----------------------------------------------------------------------------
1047// Declarations
1048
1049func (P *Parser) ParseImportSpec() {
1050 P.Trace("ImportSpec");
Robert Griesemera6f87792008-07-15 15:37:14 -07001051
Robert Griesemer0cee3022008-07-15 10:05:17 -07001052 if P.tok == Scanner.PERIOD {
1053 P.Next();
1054 } else if P.tok == Scanner.IDENT {
1055 P.Next();
1056 }
1057 P.Expect(Scanner.STRING);
Robert Griesemera6f87792008-07-15 15:37:14 -07001058
Robert Griesemer0cee3022008-07-15 10:05:17 -07001059 P.Ecart();
1060}
1061
1062
1063func (P *Parser) ParseImportDecl() {
1064 P.Trace("ImportDecl");
Robert Griesemera6f87792008-07-15 15:37:14 -07001065
Robert Griesemer0cee3022008-07-15 10:05:17 -07001066 P.Expect(Scanner.IMPORT);
1067 if P.tok == Scanner.LPAREN {
1068 P.Next();
1069 for P.tok != Scanner.RPAREN {
1070 P.ParseImportSpec();
1071 P.Optional(Scanner.SEMICOLON); // TODO this seems wrong
1072 }
1073 P.Next();
1074 } else {
1075 P.ParseImportSpec();
Robert Griesemer835cd462008-07-07 17:27:14 -07001076 }
Robert Griesemera6f87792008-07-15 15:37:14 -07001077
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001078 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -07001079}
1080
1081
Robert Griesemer0cee3022008-07-15 10:05:17 -07001082func (P *Parser) ParseConstSpec() {
1083 P.Trace("ConstSpec");
Robert Griesemera6f87792008-07-15 15:37:14 -07001084
1085 list := P.ParseIdentDeclList(Object.CONST);
1086 typ := P.TryType();
1087 if typ != nil {
1088 for p := list.first; p != nil; p = p.next {
1089 p.obj.typ = typ; // TODO should use/have set_type()!
1090 }
1091 }
Robert Griesemer0cee3022008-07-15 10:05:17 -07001092 if P.tok == Scanner.ASSIGN {
1093 P.Next();
Robert Griesemera6f87792008-07-15 15:37:14 -07001094 P.ParseExpressionList();
Robert Griesemer835cd462008-07-07 17:27:14 -07001095 }
Robert Griesemera6f87792008-07-15 15:37:14 -07001096
Robert Griesemer0cee3022008-07-15 10:05:17 -07001097 P.Ecart();
1098}
1099
1100
1101func (P *Parser) ParseConstDecl() {
1102 P.Trace("ConstDecl");
Robert Griesemera6f87792008-07-15 15:37:14 -07001103
Robert Griesemer0cee3022008-07-15 10:05:17 -07001104 P.Expect(Scanner.CONST);
1105 if P.tok == Scanner.LPAREN {
1106 P.Next();
1107 for P.tok != Scanner.RPAREN {
1108 P.ParseConstSpec();
1109 if P.tok != Scanner.RPAREN {
1110 P.Expect(Scanner.SEMICOLON);
1111 }
1112 }
1113 P.Next();
1114 } else {
1115 P.ParseConstSpec();
1116 }
Robert Griesemera6f87792008-07-15 15:37:14 -07001117
Robert Griesemer0cee3022008-07-15 10:05:17 -07001118 P.Ecart();
1119}
1120
1121
1122func (P *Parser) ParseTypeSpec() {
1123 P.Trace("TypeSpec");
Robert Griesemera6f87792008-07-15 15:37:14 -07001124
1125 pos := P.beg;
1126 ident := P.ParseIdent();
1127 obj := P.top_scope.Lookup(ident); // only lookup in top scope!
1128 if obj != nil {
1129 // ok if forward declared type
1130 if obj.kind != Object.TYPE || obj.typ.form != Type.UNDEF {
1131 // TODO use obj.pos to refer to decl pos in error msg!
1132 P.Error(pos, `"` + ident + `" is declared already`);
1133 }
1134 } else {
1135 obj = Globals.NewObject(pos, Object.TYPE, ident);
1136 obj.typ = Universe.undef_t; // TODO fix this
1137 P.top_scope.Insert(obj);
1138 }
1139
1140 typ := P.TryType(); // no type if we have a forward decl
1141 if typ != nil {
1142 // TODO what about the name of incomplete types?
1143 obj.typ = typ; // TODO should use/have set_typ()!
1144 if typ.obj == nil {
1145 typ.obj = obj; // primary type object
1146 }
1147 }
1148
Robert Griesemer0cee3022008-07-15 10:05:17 -07001149 P.Ecart();
1150}
1151
1152
1153func (P *Parser) ParseTypeDecl() {
1154 P.Trace("TypeDecl");
Robert Griesemera6f87792008-07-15 15:37:14 -07001155
Robert Griesemer0cee3022008-07-15 10:05:17 -07001156 P.Expect(Scanner.TYPE);
1157 if P.tok == Scanner.LPAREN {
1158 P.Next();
1159 for P.tok != Scanner.RPAREN {
1160 P.ParseTypeSpec();
1161 if P.tok != Scanner.RPAREN {
1162 P.Expect(Scanner.SEMICOLON);
1163 }
1164 }
1165 P.Next();
1166 } else {
1167 P.ParseTypeSpec();
1168 }
Robert Griesemera6f87792008-07-15 15:37:14 -07001169
Robert Griesemer0cee3022008-07-15 10:05:17 -07001170 P.Ecart();
1171}
1172
1173
1174func (P *Parser) ParseVarSpec() {
1175 P.Trace("VarSpec");
Robert Griesemera6f87792008-07-15 15:37:14 -07001176
1177 list := P.ParseIdentDeclList(Object.VAR);
Robert Griesemer0cee3022008-07-15 10:05:17 -07001178 if P.tok == Scanner.ASSIGN {
1179 P.Next();
1180 P.ParseExpressionList();
1181 } else {
Robert Griesemera6f87792008-07-15 15:37:14 -07001182 typ := P.ParseType();
1183 for p := list.first; p != nil; p = p.next {
1184 p.obj.typ = typ; // TODO should use/have set_type()!
1185 }
Robert Griesemer0cee3022008-07-15 10:05:17 -07001186 if P.tok == Scanner.ASSIGN {
1187 P.Next();
1188 P.ParseExpressionList();
1189 }
1190 }
Robert Griesemera6f87792008-07-15 15:37:14 -07001191
Robert Griesemer0cee3022008-07-15 10:05:17 -07001192 P.Ecart();
1193}
1194
1195
1196func (P *Parser) ParseVarDecl() {
1197 P.Trace("VarDecl");
Robert Griesemera6f87792008-07-15 15:37:14 -07001198
Robert Griesemer0cee3022008-07-15 10:05:17 -07001199 P.Expect(Scanner.VAR);
1200 if P.tok == Scanner.LPAREN {
1201 P.Next();
1202 for P.tok != Scanner.RPAREN {
1203 P.ParseVarSpec();
1204 if P.tok != Scanner.RPAREN {
1205 P.Expect(Scanner.SEMICOLON);
1206 }
1207 }
1208 P.Next();
1209 } else {
1210 P.ParseVarSpec();
1211 }
Robert Griesemera6f87792008-07-15 15:37:14 -07001212
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001213 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -07001214}
1215
1216
1217func (P *Parser) ParseFuncDecl() {
1218 P.Trace("FuncDecl");
Robert Griesemera6f87792008-07-15 15:37:14 -07001219
Robert Griesemer835cd462008-07-07 17:27:14 -07001220 P.Expect(Scanner.FUNC);
1221 P.ParseNamedSignature();
1222 if P.tok == Scanner.SEMICOLON {
1223 // forward declaration
1224 P.Next();
1225 } else {
1226 P.ParseBlock();
1227 }
Robert Griesemera6f87792008-07-15 15:37:14 -07001228
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001229 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -07001230}
1231
1232
1233func (P *Parser) ParseExportDecl() {
1234 P.Trace("ExportDecl");
Robert Griesemera6f87792008-07-15 15:37:14 -07001235
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001236 P.Expect(Scanner.EXPORT);
Robert Griesemer33069d392008-07-09 10:16:33 -07001237 if P.tok == Scanner.LPAREN {
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001238 P.Next();
Robert Griesemer33069d392008-07-09 10:16:33 -07001239 for P.tok != Scanner.RPAREN {
1240 P.ParseIdent();
1241 P.Optional(Scanner.COMMA); // TODO this seems wrong
1242 }
1243 P.Next();
1244 } else {
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001245 P.ParseIdent();
Robert Griesemer33069d392008-07-09 10:16:33 -07001246 for P.tok == Scanner.COMMA {
1247 P.Next();
1248 P.ParseIdent();
1249 }
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001250 }
Robert Griesemera6f87792008-07-15 15:37:14 -07001251
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001252 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -07001253}
1254
1255
1256func (P *Parser) ParseDeclaration() {
1257 P.Trace("Declaration");
Robert Griesemera6f87792008-07-15 15:37:14 -07001258
Robert Griesemer415397e2008-07-09 14:48:26 -07001259 indent := P.indent;
Robert Griesemer835cd462008-07-07 17:27:14 -07001260 switch P.tok {
1261 case Scanner.CONST:
1262 P.ParseConstDecl();
1263 case Scanner.TYPE:
1264 P.ParseTypeDecl();
1265 case Scanner.VAR:
1266 P.ParseVarDecl();
1267 case Scanner.FUNC:
1268 P.ParseFuncDecl();
1269 case Scanner.EXPORT:
1270 P.ParseExportDecl();
1271 default:
Robert Griesemer8be580e2008-07-10 14:42:33 -07001272 P.Error(P.beg, "declaration expected");
Robert Griesemera6f87792008-07-15 15:37:14 -07001273 P.Next(); // make progress
Robert Griesemer835cd462008-07-07 17:27:14 -07001274 }
Robert Griesemer415397e2008-07-09 14:48:26 -07001275 if indent != P.indent {
1276 panic "imbalanced tracing code"
1277 }
Robert Griesemera6f87792008-07-15 15:37:14 -07001278
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001279 P.Ecart();
1280}
1281
1282
Robert Griesemer0cee3022008-07-15 10:05:17 -07001283// ----------------------------------------------------------------------------
1284// Program
Robert Griesemer835cd462008-07-07 17:27:14 -07001285
1286func (P *Parser) ParseProgram() {
1287 P.Trace("Program");
Robert Griesemer230230c2008-07-14 18:06:41 -07001288 P.OpenScope();
Robert Griesemer835cd462008-07-07 17:27:14 -07001289 P.Expect(Scanner.PACKAGE);
1290 P.ParseIdent();
Robert Griesemerafbf7172008-07-10 18:05:00 -07001291 P.Optional(Scanner.SEMICOLON);
1292
Robert Griesemer230230c2008-07-14 18:06:41 -07001293 { P.OpenScope();
1294 for P.tok == Scanner.IMPORT {
1295 P.ParseImportDecl();
1296 P.Optional(Scanner.SEMICOLON);
1297 }
1298
1299 for P.tok != Scanner.EOF {
1300 P.ParseDeclaration();
1301 P.Optional(Scanner.SEMICOLON);
1302 }
1303 P.CloseScope();
Robert Griesemer835cd462008-07-07 17:27:14 -07001304 }
Robert Griesemerafbf7172008-07-10 18:05:00 -07001305
Robert Griesemer230230c2008-07-14 18:06:41 -07001306 P.CloseScope();
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001307 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -07001308}