blob: 49b0f6ab2545f14ce163a8f20f59cd96ad58a96e [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"
8
9
10export Parser
11type Parser struct {
Robert Griesemerc40be3b2008-07-08 16:39:04 -070012 verbose, indent int;
Robert Griesemer835cd462008-07-07 17:27:14 -070013 S *Scanner.Scanner;
14 tok int; // one token look-ahead
15 beg, end int; // token position
Robert Griesemerc40be3b2008-07-08 16:39:04 -070016 ident string; // last ident seen
Robert Griesemer835cd462008-07-07 17:27:14 -070017}
18
19
Robert Griesemerc40be3b2008-07-08 16:39:04 -070020func (P *Parser) PrintIndent() {
21 for i := P.indent; i > 0; i-- {
Robert Griesemer415397e2008-07-09 14:48:26 -070022 print ". ";
Robert Griesemerc40be3b2008-07-08 16:39:04 -070023 }
24}
25
26
27func (P *Parser) Trace(msg string) {
28 if P.verbose > 0 {
29 P.PrintIndent();
30 print msg, " {\n";
31 P.indent++;
32 }
33}
34
35
36func (P *Parser) Ecart() {
37 if P.verbose > 0 {
38 P.indent--;
39 P.PrintIndent();
40 print "}\n";
41 }
42}
43
44
45func (P *Parser) Next() {
46 P.tok, P.beg, P.end = P.S.Scan();
47 if P.tok == Scanner.IDENT {
48 P.ident = P.S.src[P.beg : P.end];
49 }
50 if P.verbose > 1 {
51 P.PrintIndent();
52 print Scanner.TokenName(P.tok), "\n";
53 }
54}
55
56
57func (P *Parser) Open(S *Scanner.Scanner, verbose int) {
Robert Griesemer835cd462008-07-07 17:27:14 -070058 P.verbose = verbose;
Robert Griesemerc40be3b2008-07-08 16:39:04 -070059 P.indent = 0;
Robert Griesemer835cd462008-07-07 17:27:14 -070060 P.S = S;
61 P.Next();
62}
63
64
Robert Griesemer8be580e2008-07-10 14:42:33 -070065func (P *Parser) Error(pos int, msg string) {
66 P.S.Error(pos, msg);
Robert Griesemer8e4ee002008-07-08 18:37:31 -070067 P.Next(); // make progress
Robert Griesemer835cd462008-07-07 17:27:14 -070068}
69
70
71func (P *Parser) Expect(tok int) {
Robert Griesemer8e4ee002008-07-08 18:37:31 -070072 if P.tok == tok {
73 P.Next()
74 } else {
Robert Griesemer8be580e2008-07-10 14:42:33 -070075 P.Error(P.beg, "expected '" + Scanner.TokenName(tok) + "', found '" + Scanner.TokenName(P.tok) + "'");
Robert Griesemer835cd462008-07-07 17:27:14 -070076 }
Robert Griesemer835cd462008-07-07 17:27:14 -070077}
78
79
Robert Griesemer8e4ee002008-07-08 18:37:31 -070080func (P *Parser) Optional(tok int) {
81 if P.tok == tok {
82 P.Next();
83 }
84}
85
86
87func (P *Parser) TryType() bool;
Robert Griesemer835cd462008-07-07 17:27:14 -070088func (P *Parser) ParseExpression();
89
90
91func (P *Parser) ParseIdent() {
Robert Griesemerc40be3b2008-07-08 16:39:04 -070092 if P.verbose > 0 {
93 P.PrintIndent();
94 print "Ident = \"", P.ident, "\"\n";
95 }
Robert Griesemer835cd462008-07-07 17:27:14 -070096 P.Expect(Scanner.IDENT);
97}
98
99
100func (P *Parser) ParseIdentList() {
101 P.Trace("IdentList");
102 P.ParseIdent();
103 for P.tok == Scanner.COMMA {
104 P.Next();
105 P.ParseIdent();
106 }
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700107 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700108}
109
110
111func (P *Parser) ParseQualifiedIdent() {
112 P.Trace("QualifiedIdent");
113 P.ParseIdent();
114 if P.tok == Scanner.PERIOD {
115 P.Next();
116 P.ParseIdent();
117 }
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700118 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700119}
120
121
122func (P *Parser) ParseTypeName() {
123 P.Trace("TypeName");
124 P.ParseQualifiedIdent();
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700125 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700126}
127
128
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700129func (P *Parser) ParseType() {
130 P.Trace("Type");
131 if !P.TryType() {
Robert Griesemer8be580e2008-07-10 14:42:33 -0700132 P.Error(P.beg, "type expected");
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700133 }
134 P.Ecart();
135}
136
137
Robert Griesemer835cd462008-07-07 17:27:14 -0700138func (P *Parser) ParseArrayType() {
139 P.Trace("ArrayType");
140 P.Expect(Scanner.LBRACK);
141 if P.tok != Scanner.RBRACK {
142 P.ParseExpression();
143 }
144 P.Expect(Scanner.RBRACK);
145 P.ParseType();
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700146 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700147}
148
149
150func (P *Parser) ParseChannelType() {
151 P.Trace("ChannelType");
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700152 P.Expect(Scanner.CHAN);
153 switch P.tok {
154 case Scanner.LSS: fallthrough
155 case Scanner.GTR:
156 P.Next();
157 }
158 P.ParseType();
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700159 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700160}
161
162
Robert Griesemer1e9adf82008-07-09 10:45:04 -0700163func (P *Parser) ParseParameters();
164func (P *Parser) TryResult() bool;
165
166
167func (P *Parser) ParseMethodDecl() {
168 P.Trace("MethodDecl");
169 P.ParseIdent();
170 P.ParseParameters();
171 P.TryResult();
172 P.Optional(Scanner.SEMICOLON);
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700173 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700174}
175
176
Robert Griesemer1e9adf82008-07-09 10:45:04 -0700177func (P *Parser) ParseInterfaceType() {
178 P.Trace("InterfaceType");
179 P.Expect(Scanner.INTERFACE);
180 P.Expect(Scanner.LBRACE);
181 for P.tok != Scanner.RBRACE {
182 P.ParseMethodDecl();
183 }
184 P.Next();
185 P.Ecart();
186}
187
188
189func (P *Parser) ParseAnonymousSignature();
190
191
Robert Griesemer835cd462008-07-07 17:27:14 -0700192func (P *Parser) ParseFunctionType() {
193 P.Trace("FunctionType");
Robert Griesemer1e9adf82008-07-09 10:45:04 -0700194 P.Expect(Scanner.FUNC);
195 P.ParseAnonymousSignature();
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700196 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700197}
198
199
200func (P *Parser) ParseMapType() {
201 P.Trace("MapType");
202 P.Expect(Scanner.MAP);
203 P.Expect(Scanner.LBRACK);
204 P.ParseType();
205 P.Expect(Scanner.RBRACK);
206 P.ParseType();
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700207 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700208}
209
210
211func (P *Parser) ParseFieldDecl() {
212 P.Trace("FieldDecl");
213 P.ParseIdentList();
214 P.ParseType();
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700215 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700216}
217
218
219func (P *Parser) ParseStructType() {
220 P.Trace("StructType");
221 P.Expect(Scanner.STRUCT);
222 P.Expect(Scanner.LBRACE);
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700223 for P.tok != Scanner.RBRACE {
Robert Griesemer835cd462008-07-07 17:27:14 -0700224 P.ParseFieldDecl();
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700225 if P.tok != Scanner.RBRACE {
226 P.Expect(Scanner.SEMICOLON);
Robert Griesemer835cd462008-07-07 17:27:14 -0700227 }
228 }
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700229 P.Optional(Scanner.SEMICOLON);
Robert Griesemer835cd462008-07-07 17:27:14 -0700230 P.Expect(Scanner.RBRACE);
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700231 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700232}
233
234
235func (P *Parser) ParsePointerType() {
236 P.Trace("PointerType");
237 P.Expect(Scanner.MUL);
238 P.ParseType();
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700239 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700240}
241
242
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700243func (P *Parser) TryType() bool {
244 P.Trace("Type (try)");
Robert Griesemer835cd462008-07-07 17:27:14 -0700245 switch P.tok {
246 case Scanner.IDENT:
247 P.ParseTypeName();
248 case Scanner.LBRACK:
249 P.ParseArrayType();
250 case Scanner.CHAN:
251 P.ParseChannelType();
252 case Scanner.INTERFACE:
253 P.ParseInterfaceType();
254 case Scanner.FUNC:
255 P.ParseFunctionType();
256 case Scanner.MAP:
257 P.ParseMapType();
258 case Scanner.STRUCT:
259 P.ParseStructType();
260 case Scanner.MUL:
261 P.ParsePointerType();
262 default:
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700263 P.Ecart();
264 return false;
Robert Griesemer835cd462008-07-07 17:27:14 -0700265 }
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700266 P.Ecart();
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700267 return true;
Robert Griesemer835cd462008-07-07 17:27:14 -0700268}
269
270
271func (P *Parser) ParseImportSpec() {
272 P.Trace("ImportSpec");
273 if P.tok == Scanner.PERIOD {
274 P.Next();
275 } else if P.tok == Scanner.IDENT {
276 P.Next();
277 }
278 P.Expect(Scanner.STRING);
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700279 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700280}
281
282
283func (P *Parser) ParseImportDecl() {
284 P.Trace("ImportDecl");
285 P.Expect(Scanner.IMPORT);
286 if P.tok == Scanner.LPAREN {
Robert Griesemer33069d392008-07-09 10:16:33 -0700287 P.Next();
288 for P.tok != Scanner.RPAREN {
Robert Griesemer835cd462008-07-07 17:27:14 -0700289 P.ParseImportSpec();
Robert Griesemer33069d392008-07-09 10:16:33 -0700290 P.Optional(Scanner.SEMICOLON); // TODO this seems wrong
Robert Griesemer835cd462008-07-07 17:27:14 -0700291 }
Robert Griesemer33069d392008-07-09 10:16:33 -0700292 P.Next();
Robert Griesemer835cd462008-07-07 17:27:14 -0700293 } else {
294 P.ParseImportSpec();
295 }
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700296 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700297}
298
299
300func (P *Parser) ParseExpressionList() {
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700301 P.Trace("ExpressionList");
Robert Griesemer835cd462008-07-07 17:27:14 -0700302 P.ParseExpression();
303 for P.tok == Scanner.COMMA {
304 P.Next();
305 P.ParseExpression();
306 }
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700307 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700308}
309
310
311func (P *Parser) ParseConstSpec() {
312 P.Trace("ConstSpec");
313 P.ParseIdent();
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700314 P.TryType();
Robert Griesemer835cd462008-07-07 17:27:14 -0700315 if P.tok == Scanner.ASSIGN {
316 P.Next();
317 P.ParseExpression();
318 }
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700319 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700320}
321
322
323func (P *Parser) ParseConstDecl() {
324 P.Trace("ConstDecl");
325 P.Expect(Scanner.CONST);
326 if P.tok == Scanner.LPAREN {
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700327 P.Next();
328 for P.tok != Scanner.RPAREN {
Robert Griesemer835cd462008-07-07 17:27:14 -0700329 P.ParseConstSpec();
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700330 if P.tok != Scanner.RPAREN {
331 P.Expect(Scanner.SEMICOLON);
332 }
Robert Griesemer835cd462008-07-07 17:27:14 -0700333 }
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700334 P.Next();
Robert Griesemer835cd462008-07-07 17:27:14 -0700335 } else {
336 P.ParseConstSpec();
337 }
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700338 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700339}
340
341
342func (P *Parser) ParseTypeSpec() {
343 P.Trace("TypeSpec");
344 P.ParseIdent();
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700345 P.TryType();
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700346 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700347}
348
349
350func (P *Parser) ParseTypeDecl() {
351 P.Trace("TypeDecl");
352 P.Expect(Scanner.TYPE);
353 if P.tok == Scanner.LPAREN {
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700354 P.Next();
355 for P.tok != Scanner.RPAREN {
Robert Griesemer835cd462008-07-07 17:27:14 -0700356 P.ParseTypeSpec();
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700357 if P.tok != Scanner.RPAREN {
358 P.Expect(Scanner.SEMICOLON);
359 }
Robert Griesemer835cd462008-07-07 17:27:14 -0700360 }
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700361 P.Next();
Robert Griesemer835cd462008-07-07 17:27:14 -0700362 } else {
363 P.ParseTypeSpec();
364 }
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700365 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700366}
367
368
369func (P *Parser) ParseVarSpec() {
370 P.Trace("VarSpec");
371 P.ParseIdentList();
372 if P.tok == Scanner.ASSIGN {
373 P.Next();
374 P.ParseExpressionList();
375 } else {
376 P.ParseType();
377 if P.tok == Scanner.ASSIGN {
378 P.Next();
379 P.ParseExpressionList();
380 }
381 }
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700382 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700383}
384
385
386func (P *Parser) ParseVarDecl() {
387 P.Trace("VarDecl");
388 P.Expect(Scanner.VAR);
389 if P.tok == Scanner.LPAREN {
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700390 P.Next();
391 for P.tok != Scanner.RPAREN {
Robert Griesemer835cd462008-07-07 17:27:14 -0700392 P.ParseVarSpec();
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700393 if P.tok != Scanner.RPAREN {
394 P.Expect(Scanner.SEMICOLON);
395 }
Robert Griesemer835cd462008-07-07 17:27:14 -0700396 }
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700397 P.Next();
Robert Griesemer835cd462008-07-07 17:27:14 -0700398 } else {
399 P.ParseVarSpec();
400 }
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700401 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700402}
403
404
405func (P *Parser) ParseParameterSection() {
406 P.Trace("ParameterSection");
407 P.ParseIdentList();
408 P.ParseType();
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700409 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700410}
411
412
413func (P *Parser) ParseParameterList() {
414 P.Trace("ParameterList");
415 P.ParseParameterSection();
416 for P.tok == Scanner.COMMA {
417 P.Next();
418 P.ParseParameterSection();
419 }
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700420 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700421}
422
423
424func (P *Parser) ParseParameters() {
425 P.Trace("Parameters");
426 P.Expect(Scanner.LPAREN);
427 if P.tok != Scanner.RPAREN {
428 P.ParseParameterList();
429 }
430 P.Expect(Scanner.RPAREN);
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700431 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700432}
433
434
Robert Griesemer1e9adf82008-07-09 10:45:04 -0700435func (P *Parser) TryResult() bool {
436 P.Trace("Result (try)");
437 res := false;
Robert Griesemer835cd462008-07-07 17:27:14 -0700438 if P.tok == Scanner.LPAREN {
439 // TODO: here we allow empty returns - should proably fix this
440 P.ParseParameters();
Robert Griesemer1e9adf82008-07-09 10:45:04 -0700441 res = true;
Robert Griesemer835cd462008-07-07 17:27:14 -0700442 } else {
Robert Griesemer1e9adf82008-07-09 10:45:04 -0700443 res = P.TryType();
Robert Griesemer835cd462008-07-07 17:27:14 -0700444 }
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700445 P.Ecart();
Robert Griesemer1e9adf82008-07-09 10:45:04 -0700446 return res;
447}
448
449
450// Anonymous signatures
451//
452// (params)
453// (params) type
454// (params) (results)
455// (recv) . (params)
456// (recv) . (params) type
457// (recv) . (params) (results)
458
459func (P *Parser) ParseAnonymousSignature() {
460 P.Trace("AnonymousSignature");
461 P.ParseParameters();
462 if P.tok == Scanner.PERIOD {
463 P.Next();
464 P.ParseParameters();
465 }
466 P.TryResult();
467 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700468}
469
470
471// Named signatures
472//
473// name (params)
474// name (params) type
475// name (params) (results)
476// (recv) name (params)
477// (recv) name (params) type
478// (recv) name (params) (results)
479
480func (P *Parser) ParseNamedSignature() {
481 P.Trace("NamedSignature");
482 if P.tok == Scanner.LPAREN {
483 P.ParseParameters();
484 }
Robert Griesemer835cd462008-07-07 17:27:14 -0700485 P.ParseIdent(); // function name
Robert Griesemer835cd462008-07-07 17:27:14 -0700486 P.ParseParameters();
Robert Griesemer1e9adf82008-07-09 10:45:04 -0700487 P.TryResult();
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700488 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700489}
490
491
492func (P *Parser) ParseDeclaration();
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700493func (P *Parser) TryStatement() bool;
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700494func (P *Parser) ParseStatementList();
Robert Griesemer835cd462008-07-07 17:27:14 -0700495func (P *Parser) ParseBlock();
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700496func (P *Parser) ParsePrimaryExpr();
Robert Griesemer835cd462008-07-07 17:27:14 -0700497
498
499func (P *Parser) ParsePrimaryExprList() {
500 P.Trace("PrimaryExprList");
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700501 P.ParsePrimaryExpr();
502 for P.tok == Scanner.COMMA {
503 P.Next();
504 P.ParsePrimaryExpr();
505 }
506 P.Ecart();
507}
508
509
510func (P *Parser) ParseBuiltinStat() {
511 P.Trace("BuiltinStat");
512 P.Expect(Scanner.IDENT);
513 P.ParseExpressionList(); // TODO should be optional
514 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700515}
516
517
518func (P *Parser) ParseSimpleStat() {
519 P.Trace("SimpleStat");
520 P.ParseExpression();
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700521 if P.tok == Scanner.COLON {
Robert Griesemer835cd462008-07-07 17:27:14 -0700522 P.Next();
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700523 P.Ecart();
524 return;
525 }
526 if P.tok == Scanner.COMMA {
Robert Griesemer835cd462008-07-07 17:27:14 -0700527 P.Next();
528 P.ParsePrimaryExprList();
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700529 }
530 switch P.tok {
531 case Scanner.ASSIGN: fallthrough;
532 case Scanner.DEFINE: fallthrough;
533 case Scanner.ADD_ASSIGN: fallthrough;
534 case Scanner.SUB_ASSIGN: fallthrough;
535 case Scanner.MUL_ASSIGN: fallthrough;
536 case Scanner.QUO_ASSIGN: fallthrough;
537 case Scanner.REM_ASSIGN: fallthrough;
538 case Scanner.AND_ASSIGN: fallthrough;
539 case Scanner.OR_ASSIGN: fallthrough;
540 case Scanner.XOR_ASSIGN: fallthrough;
541 case Scanner.SHL_ASSIGN: fallthrough;
542 case Scanner.SHR_ASSIGN:
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700543 P.Next();
544 P.ParseExpressionList();
Robert Griesemer835cd462008-07-07 17:27:14 -0700545 case Scanner.INC:
546 P.Next();
547 case Scanner.DEC:
548 P.Next();
549 }
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700550 P.Ecart();
551}
552
553
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700554func (P *Parser) ParseGoStat() {
555 P.Trace("GoStat");
556 P.Expect(Scanner.GO);
557 P.ParseExpression();
Robert Griesemer415397e2008-07-09 14:48:26 -0700558 P.Ecart();
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700559}
560
561
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700562func (P *Parser) ParseReturnStat() {
563 P.Trace("ReturnStat");
564 P.Expect(Scanner.RETURN);
565 if P.tok != Scanner.SEMICOLON && P.tok != Scanner.RBRACE {
566 P.ParseExpressionList();
567 }
568 P.Ecart();
569}
570
571
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700572func (P *Parser) ParseControlFlowStat(tok int) {
573 P.Trace("ControlFlowStat");
574 P.Expect(tok);
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700575 if P.tok == Scanner.IDENT {
576 P.ParseIdent();
577 }
578 P.Ecart();
579}
580
581
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700582func (P *Parser) ParseStatement() {
583 P.Trace("Statement");
584 if !P.TryStatement() {
Robert Griesemer8be580e2008-07-10 14:42:33 -0700585 P.Error(P.beg, "statement expected");
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700586 }
587 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700588}
589
590
591func (P *Parser) ParseIfStat() {
592 P.Trace("IfStat");
593 P.Expect(Scanner.IF);
594 if P.tok != Scanner.LBRACE {
595 P.ParseSimpleStat();
596 if P.tok == Scanner.SEMICOLON {
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700597 P.Next();
Robert Griesemer835cd462008-07-07 17:27:14 -0700598 P.ParseExpression();
599 }
600 }
601 P.ParseBlock();
602 if P.tok == Scanner.ELSE {
603 P.Next();
604 if P.tok == Scanner.IF {
605 P.ParseIfStat();
606 } else {
607 // TODO should be P.ParseBlock()
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700608 P.ParseStatement();
Robert Griesemer835cd462008-07-07 17:27:14 -0700609 }
610 }
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700611 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700612}
613
614
615func (P *Parser) ParseForStat() {
616 P.Trace("ForStat");
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700617 P.Expect(Scanner.FOR);
618 if P.tok != Scanner.LBRACE {
619 if P.tok != Scanner.SEMICOLON {
620 P.ParseSimpleStat();
621 }
622 if P.tok == Scanner.SEMICOLON {
623 P.Next();
624 if P.tok != Scanner.SEMICOLON {
625 P.ParseExpression();
626 }
627 P.Expect(Scanner.SEMICOLON);
628 if P.tok != Scanner.LBRACE {
629 P.ParseSimpleStat();
630 }
631 }
632 }
633 P.ParseBlock();
634 P.Ecart();
635}
636
637
638func (P *Parser) ParseCase() {
639 P.Trace("Case");
640 if P.tok == Scanner.CASE {
641 P.Next();
642 P.ParseExpressionList();
643 } else {
644 P.Expect(Scanner.DEFAULT);
645 }
646 P.Expect(Scanner.COLON);
647 P.Ecart();
648}
649
650
651func (P *Parser) ParseCaseList() {
652 P.Trace("CaseList");
653 P.ParseCase();
654 for P.tok == Scanner.CASE || P.tok == Scanner.DEFAULT {
655 P.ParseCase();
656 }
657 P.Ecart();
658}
659
660
661func (P *Parser) ParseCaseClause() {
662 P.Trace("CaseClause");
663 P.ParseCaseList();
664 if P.tok != Scanner.FALLTHROUGH && P.tok != Scanner.RBRACE {
665 P.ParseStatementList();
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700666 P.Optional(Scanner.SEMICOLON);
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700667 }
668 if P.tok == Scanner.FALLTHROUGH {
669 P.Next();
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700670 P.Optional(Scanner.SEMICOLON);
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700671 }
672 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700673}
674
675
676func (P *Parser) ParseSwitchStat() {
677 P.Trace("SwitchStat");
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700678 P.Expect(Scanner.SWITCH);
679 if P.tok != Scanner.LBRACE {
680 P.ParseSimpleStat();
681 if P.tok == Scanner.SEMICOLON {
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700682 P.Next();
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700683 P.ParseExpression();
684 }
685 }
686 P.Expect(Scanner.LBRACE);
687 for P.tok != Scanner.RBRACE {
688 P.ParseCaseClause();
689 }
690 P.Expect(Scanner.RBRACE);
691 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700692}
693
694
Robert Griesemercab94922008-07-09 14:01:17 -0700695func (P *Parser) ParseCommCase() {
696 P.Trace("CommCase");
697 if P.tok == Scanner.CASE {
698 P.Next();
699 if P.tok == Scanner.GTR {
700 // send
701 P.Next();
702 P.ParseExpression();
703 P.Expect(Scanner.EQL);
704 P.ParseExpression();
705 } else {
706 // receive
707 if P.tok != Scanner.LSS {
708 P.ParseIdent();
709 P.Expect(Scanner.ASSIGN);
710 }
711 P.Expect(Scanner.LSS);
712 P.ParseExpression();
713 }
714 } else {
715 P.Expect(Scanner.DEFAULT);
716 }
717 P.Expect(Scanner.COLON);
718 P.Ecart();
719}
720
721
722func (P *Parser) ParseCommClause() {
723 P.Trace("CommClause");
724 P.ParseCommCase();
725 if P.tok != Scanner.CASE && P.tok != Scanner.DEFAULT && P.tok != Scanner.RBRACE {
726 P.ParseStatementList();
727 P.Optional(Scanner.SEMICOLON);
728 }
729 P.Ecart();
730}
731
732
733func (P *Parser) ParseRangeStat() bool {
734 P.Trace("RangeStat");
735 P.Expect(Scanner.RANGE);
736 P.ParseIdentList();
737 P.Expect(Scanner.DEFINE);
738 P.ParseExpression();
739 P.ParseBlock();
740 P.Ecart();
741}
742
743
744func (P *Parser) ParseSelectStat() bool {
745 P.Trace("SelectStat");
746 P.Expect(Scanner.SELECT);
747 P.Expect(Scanner.LBRACE);
748 for P.tok != Scanner.RBRACE {
749 P.ParseCommClause();
750 }
751 P.Next();
752 P.Ecart();
753}
754
755
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700756func (P *Parser) TryStatement() bool {
757 P.Trace("Statement (try)");
Robert Griesemer415397e2008-07-09 14:48:26 -0700758 indent := P.indent;
759 res := true;
Robert Griesemer835cd462008-07-07 17:27:14 -0700760 switch P.tok {
761 case Scanner.CONST: fallthrough;
762 case Scanner.TYPE: fallthrough;
763 case Scanner.VAR: fallthrough;
764 case Scanner.FUNC:
765 P.ParseDeclaration();
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700766 case Scanner.GTR:
767 P.ParseSimpleStat(); // send
Robert Griesemer835cd462008-07-07 17:27:14 -0700768 case Scanner.IDENT:
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700769 switch P.ident {
770 case "print", "panic":
771 P.ParseBuiltinStat();
772 default:
773 P.ParseSimpleStat();
774 }
Robert Griesemer835cd462008-07-07 17:27:14 -0700775 case Scanner.GO:
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700776 P.ParseGoStat();
Robert Griesemer835cd462008-07-07 17:27:14 -0700777 case Scanner.RETURN:
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700778 P.ParseReturnStat();
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700779 case Scanner.BREAK, Scanner.CONTINUE, Scanner.GOTO:
780 P.ParseControlFlowStat(P.tok);
Robert Griesemer835cd462008-07-07 17:27:14 -0700781 case Scanner.LBRACE:
782 P.ParseBlock();
783 case Scanner.IF:
784 P.ParseIfStat();
785 case Scanner.FOR:
786 P.ParseForStat();
787 case Scanner.SWITCH:
788 P.ParseSwitchStat();
789 case Scanner.RANGE:
Robert Griesemercab94922008-07-09 14:01:17 -0700790 P.ParseRangeStat();
Robert Griesemer835cd462008-07-07 17:27:14 -0700791 case Scanner.SELECT:
Robert Griesemercab94922008-07-09 14:01:17 -0700792 P.ParseSelectStat();
Robert Griesemer835cd462008-07-07 17:27:14 -0700793 default:
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700794 // no statement found
Robert Griesemer415397e2008-07-09 14:48:26 -0700795 res = false;
796 }
797 if indent != P.indent {
798 panic "imbalanced tracing code"
Robert Griesemer835cd462008-07-07 17:27:14 -0700799 }
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700800 P.Ecart();
Robert Griesemer415397e2008-07-09 14:48:26 -0700801 return res;
Robert Griesemer835cd462008-07-07 17:27:14 -0700802}
803
804
805func (P *Parser) ParseStatementList() {
806 P.Trace("StatementList");
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700807 for P.TryStatement() {
808 P.Optional(Scanner.SEMICOLON);
Robert Griesemer835cd462008-07-07 17:27:14 -0700809 }
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700810 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700811}
812
813
814func (P *Parser) ParseBlock() {
815 P.Trace("Block");
816 P.Expect(Scanner.LBRACE);
817 if P.tok != Scanner.RBRACE && P.tok != Scanner.SEMICOLON {
818 P.ParseStatementList();
819 }
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700820 P.Optional(Scanner.SEMICOLON);
Robert Griesemer835cd462008-07-07 17:27:14 -0700821 P.Expect(Scanner.RBRACE);
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700822 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700823}
824
825
826func (P *Parser) ParseFuncDecl() {
827 P.Trace("FuncDecl");
828 P.Expect(Scanner.FUNC);
829 P.ParseNamedSignature();
830 if P.tok == Scanner.SEMICOLON {
831 // forward declaration
832 P.Next();
833 } else {
834 P.ParseBlock();
835 }
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700836 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700837}
838
839
840func (P *Parser) ParseExportDecl() {
841 P.Trace("ExportDecl");
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700842 P.Expect(Scanner.EXPORT);
Robert Griesemer33069d392008-07-09 10:16:33 -0700843 if P.tok == Scanner.LPAREN {
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700844 P.Next();
Robert Griesemer33069d392008-07-09 10:16:33 -0700845 for P.tok != Scanner.RPAREN {
846 P.ParseIdent();
847 P.Optional(Scanner.COMMA); // TODO this seems wrong
848 }
849 P.Next();
850 } else {
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700851 P.ParseIdent();
Robert Griesemer33069d392008-07-09 10:16:33 -0700852 for P.tok == Scanner.COMMA {
853 P.Next();
854 P.ParseIdent();
855 }
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700856 }
857 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700858}
859
860
861func (P *Parser) ParseDeclaration() {
862 P.Trace("Declaration");
Robert Griesemer415397e2008-07-09 14:48:26 -0700863 indent := P.indent;
Robert Griesemer835cd462008-07-07 17:27:14 -0700864 switch P.tok {
865 case Scanner.CONST:
866 P.ParseConstDecl();
867 case Scanner.TYPE:
868 P.ParseTypeDecl();
869 case Scanner.VAR:
870 P.ParseVarDecl();
871 case Scanner.FUNC:
872 P.ParseFuncDecl();
873 case Scanner.EXPORT:
874 P.ParseExportDecl();
875 default:
Robert Griesemer8be580e2008-07-10 14:42:33 -0700876 P.Error(P.beg, "declaration expected");
Robert Griesemer835cd462008-07-07 17:27:14 -0700877 }
Robert Griesemer415397e2008-07-09 14:48:26 -0700878 if indent != P.indent {
879 panic "imbalanced tracing code"
880 }
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700881 P.Ecart();
882}
883
884
885func (P *Parser) ParseNew() {
886 P.Trace("New");
887 P.Expect(Scanner.NEW);
888 P.Expect(Scanner.LPAREN);
889 P.ParseType();
890 if P.tok == Scanner.COMMA {
891 P.Next();
892 P.ParseExpressionList()
893 }
894 P.Expect(Scanner.RPAREN);
895 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700896}
897
898
899func (P *Parser) ParseOperand() {
900 P.Trace("Operand");
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700901 switch P.tok {
902 case Scanner.IDENT:
903 P.ParseQualifiedIdent();
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700904 case Scanner.LPAREN:
905 P.Next();
906 P.ParseExpression();
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700907 P.Expect(Scanner.RPAREN);
Robert Griesemer33069d392008-07-09 10:16:33 -0700908 case Scanner.STRING: fallthrough;
909 case Scanner.NUMBER: fallthrough;
Robert Griesemer8e4ee002008-07-08 18:37:31 -0700910 case Scanner.NIL: fallthrough;
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700911 case Scanner.IOTA: fallthrough;
912 case Scanner.TRUE: fallthrough;
913 case Scanner.FALSE:
914 P.Next();
915 case Scanner.NEW:
916 P.ParseNew();
917 default:
Robert Griesemer8be580e2008-07-10 14:42:33 -0700918 P.Error(P.beg, "operand expected");
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700919 }
920 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700921}
922
923
924func (P *Parser) ParseSelectorOrTypeAssertion() {
925 P.Trace("SelectorOrTypeAssertion");
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700926 P.Expect(Scanner.PERIOD);
927 if P.tok == Scanner.IDENT {
928 P.ParseIdent();
929 } else {
930 P.Expect(Scanner.LPAREN);
931 P.ParseType();
932 P.Expect(Scanner.RPAREN);
933 }
934 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700935}
936
937
938func (P *Parser) ParseIndexOrSlice() {
939 P.Trace("IndexOrSlice");
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700940 P.Expect(Scanner.LBRACK);
941 P.ParseExpression();
942 if P.tok == Scanner.COLON {
943 P.Next();
944 P.ParseExpression();
945 }
946 P.Expect(Scanner.RBRACK);
947 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700948}
949
950
951func (P *Parser) ParseInvocation() {
952 P.Trace("Invocation");
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700953 P.Expect(Scanner.LPAREN);
954 if P.tok != Scanner.RPAREN {
955 P.ParseExpressionList();
956 }
957 P.Expect(Scanner.RPAREN);
958 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700959}
960
961
962func (P *Parser) ParsePrimaryExpr() {
963 P.Trace("PrimaryExpr");
964 P.ParseOperand();
965 for {
966 switch P.tok {
967 case Scanner.PERIOD:
968 P.ParseSelectorOrTypeAssertion();
969 case Scanner.LBRACK:
970 P.ParseIndexOrSlice();
971 case Scanner.LPAREN:
972 P.ParseInvocation();
973 default:
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700974 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700975 return;
976 }
977 }
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700978 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700979}
980
981
982func (P *Parser) ParseUnaryExpr() {
983 P.Trace("UnaryExpr");
984 switch P.tok {
985 case Scanner.ADD: fallthrough;
986 case Scanner.SUB: fallthrough;
987 case Scanner.NOT: fallthrough;
988 case Scanner.XOR: fallthrough;
989 case Scanner.LSS: fallthrough;
990 case Scanner.GTR: fallthrough;
991 case Scanner.MUL: fallthrough;
992 case Scanner.AND:
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700993 P.Next();
Robert Griesemer835cd462008-07-07 17:27:14 -0700994 P.ParseUnaryExpr();
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700995 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -0700996 return;
997 }
998 P.ParsePrimaryExpr();
Robert Griesemerc40be3b2008-07-08 16:39:04 -0700999 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -07001000}
1001
1002
Robert Griesemer415397e2008-07-09 14:48:26 -07001003func Precedence(tok int) int {
1004 // TODO should use a map or array here for lookup
1005 switch tok {
Robert Griesemer8be580e2008-07-10 14:42:33 -07001006 case Scanner.LOR:
Robert Griesemer415397e2008-07-09 14:48:26 -07001007 return 1;
Robert Griesemer8be580e2008-07-10 14:42:33 -07001008 case Scanner.LAND:
Robert Griesemer415397e2008-07-09 14:48:26 -07001009 return 2;
1010 case Scanner.EQL, Scanner.NEQ, Scanner.LSS, Scanner.LEQ, Scanner.GTR, Scanner.GEQ:
1011 return 3;
1012 case Scanner.ADD, Scanner.SUB, Scanner.OR, Scanner.XOR:
1013 return 4;
1014 case Scanner.MUL, Scanner.QUO, Scanner.REM, Scanner.SHL, Scanner.SHR, Scanner.AND:
1015 return 5;
1016 }
1017 return 0;
1018}
1019
1020
1021func (P *Parser) ParseBinaryExpr(prec1 int) {
1022 P.Trace("BinaryExpr");
Robert Griesemer835cd462008-07-07 17:27:14 -07001023 P.ParseUnaryExpr();
Robert Griesemer415397e2008-07-09 14:48:26 -07001024 for prec := Precedence(P.tok); prec >= prec1; prec-- {
1025 for Precedence(P.tok) == prec {
Robert Griesemer8e4ee002008-07-08 18:37:31 -07001026 P.Next();
Robert Griesemer415397e2008-07-09 14:48:26 -07001027 P.ParseBinaryExpr(prec + 1);
Robert Griesemer835cd462008-07-07 17:27:14 -07001028 }
1029 }
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001030 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -07001031}
1032
1033
Robert Griesemer835cd462008-07-07 17:27:14 -07001034func (P *Parser) ParseExpression() {
1035 P.Trace("Expression");
Robert Griesemer415397e2008-07-09 14:48:26 -07001036 indent := P.indent;
1037 P.ParseBinaryExpr(1);
1038 if indent != P.indent {
1039 panic "imbalanced tracing code";
1040 }
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001041 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -07001042}
1043
1044
1045func (P *Parser) ParseProgram() {
1046 P.Trace("Program");
1047 P.Expect(Scanner.PACKAGE);
1048 P.ParseIdent();
1049 for P.tok == Scanner.IMPORT {
1050 P.ParseImportDecl();
Robert Griesemer8e4ee002008-07-08 18:37:31 -07001051 P.Optional(Scanner.SEMICOLON);
Robert Griesemer835cd462008-07-07 17:27:14 -07001052 }
1053 for P.tok != Scanner.EOF {
1054 P.ParseDeclaration();
Robert Griesemer8e4ee002008-07-08 18:37:31 -07001055 P.Optional(Scanner.SEMICOLON);
Robert Griesemer835cd462008-07-07 17:27:14 -07001056 }
Robert Griesemerc40be3b2008-07-08 16:39:04 -07001057 P.Ecart();
Robert Griesemer835cd462008-07-07 17:27:14 -07001058}