Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(194)

Side by Side Diff: appengine/cmd/dm/distributor/impl/jobsim/parser/parser.go

Issue 1537883002: Initial distributor implementation (Closed) Base URL: https://chromium.googlesource.com/external/github.com/luci/luci-go@master
Patch Set: work in progress Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 package parser
6
7 import (
8 "bytes"
9 "errors"
10 "fmt"
11 "io"
12 "io/ioutil"
13 "os"
14 "regexp"
15 "strconv"
16 "strings"
17 "time"
18 "unicode"
19 "unicode/utf8"
20 )
21
22 type retriesHolder uint64
23 type identityHolder uint64
24
25 var whitespaceRE = regexp.MustCompile("#[^\n]*\n|\\s+")
26
27 // CleanPhrase removes all whitespace and comments from a phrase in preparation
28 // for parsing it. The parsers defined in this package only operate on cleaned
29 // phrases, and will fail to parse if you provide a phrase with whitespace.
30 func CleanPhrase(p string) string {
31 return whitespaceRE.ReplaceAllLiteralString(p, "")
32 }
33
34 // ParsePhrase is a convenience function for the parser functions in this
35 // package to return a typed Phrase object as the result of a string.
36 func ParsePhrase(p string) (Phrase, error) {
37 ret, err := Parse("<string>", []byte(p))
38 if err != nil {
39 return nil, err
40 }
41 return ret.(Phrase), nil
42 }
43
44 var g = &grammar{
45 rules: []*rule{
46 {
47 name: "Overall",
48 pos: position{line: 32, col: 1, offset: 946},
49 expr: &choiceExpr{
50 pos: position{line: 32, col: 11, offset: 956},
51 alternatives: []interface{}{
52 &actionExpr{
53 pos: position{line: 32, col: 11, offset: 956},
54 run: (*parser).callonOverall2,
55 expr: &seqExpr{
56 pos: position{line: 32, col: 11, offset: 956},
57 exprs: []interface{}{
58 &labeledExpr{
59 pos: p osition{line: 32, col: 11, offset: 956},
60 label: " p",
61 expr: &r uleRefExpr{
62 pos: position{line: 32, col: 13, offset: 958},
63 name: "Phrase",
64 },
65 },
66 &notExpr{
67 pos: pos ition{line: 32, col: 20, offset: 965},
68 expr: &a nyMatcher{
69 line: 32, col: 21, offset: 966,
70 },
71 },
72 },
73 },
74 },
75 &actionExpr{
76 pos: position{line: 34, col: 5, offset: 990},
77 run: (*parser).callonOverall8,
78 expr: &seqExpr{
79 pos: position{line: 34, col: 5, offset: 990},
80 exprs: []interface{}{
81 &labeledExpr{
82 pos: p osition{line: 34, col: 5, offset: 990},
83 label: " p",
84 expr: &r uleRefExpr{
85 pos: position{line: 34, col: 7, offset: 992},
86 name: "Phrase",
87 },
88 },
89 &labeledExpr{
90 pos: p osition{line: 34, col: 14, offset: 999},
91 label: " ext",
92 expr: &r uleRefExpr{
93 pos: position{line: 34, col: 18, offset: 1003},
94 name: "Extra",
95 },
96 },
97 },
98 },
99 },
100 &actionExpr{
101 pos: position{line: 36, col: 5, offset: 1073},
102 run: (*parser).callonOverall14,
103 expr: &notExpr{
104 pos: position{line: 36, col: 5, offset: 1073},
105 expr: &anyMatcher{
106 line: 36, col: 6 , offset: 1074,
107 },
108 },
109 },
110 &actionExpr{
111 pos: position{line: 38, col: 5, offset: 1123},
112 run: (*parser).callonOverall17,
113 expr: &labeledExpr{
114 pos: position{line: 38 , col: 5, offset: 1123},
115 label: "ext",
116 expr: &ruleRefExpr{
117 pos: position{l ine: 38, col: 9, offset: 1127},
118 name: "Extra",
119 },
120 },
121 },
122 },
123 },
124 },
125 {
126 name: "Extra",
127 pos: position{line: 42, col: 1, offset: 1200},
128 expr: &actionExpr{
129 pos: position{line: 42, col: 9, offset: 1208},
130 run: (*parser).callonExtra1,
131 expr: &zeroOrMoreExpr{
132 pos: position{line: 42, col: 9, offset: 1208},
133 expr: &anyMatcher{
134 line: 42, col: 9, offset: 1208,
135 },
136 },
137 },
138 },
139 {
140 name: "Phrase",
141 pos: position{line: 46, col: 1, offset: 1245},
142 expr: &choiceExpr{
143 pos: position{line: 46, col: 10, offset: 1254},
144 alternatives: []interface{}{
145 &actionExpr{
146 pos: position{line: 46, col: 10, offset: 1254},
147 run: (*parser).callonPhrase2,
148 expr: &labeledExpr{
149 pos: position{line: 46 , col: 10, offset: 1254},
150 label: "ret",
151 expr: &ruleRefExpr{
152 pos: position{l ine: 46, col: 14, offset: 1258},
153 name: "ReturnSta ge",
154 },
155 },
156 },
157 &actionExpr{
158 pos: position{line: 48, col: 5, offset: 1310},
159 run: (*parser).callonPhrase5,
160 expr: &seqExpr{
161 pos: position{line: 48, col: 5, offset: 1310},
162 exprs: []interface{}{
163 &labeledExpr{
164 pos: p osition{line: 48, col: 5, offset: 1310},
165 label: " first",
166 expr: &r uleRefExpr{
167 pos: position{line: 48, col: 11, offset: 1316},
168 name: "Stage",
169 },
170 },
171 &labeledExpr{
172 pos: p osition{line: 48, col: 17, offset: 1322},
173 label: " middleI",
174 expr: &z eroOrMoreExpr{
175 pos: position{line: 48, col: 25, offset: 1330},
176 expr: &seqExpr{
177 pos: position{line: 48, col: 26, offset: 1331},
178 exprs: []interface{}{
179 &litMatcher{
180 pos: position{line: 48, col: 26, offset: 1331},
181 val: ",",
182 ignoreCase: false,
183 },
184 &ruleRefExpr{
185 pos: position{line: 48, col: 30, offset: 1335},
186 name: "Stage",
187 },
188 },
189 },
190 },
191 },
192 &labeledExpr{
193 pos: p osition{line: 48, col: 38, offset: 1343},
194 label: " retI",
195 expr: &z eroOrOneExpr{
196 pos: position{line: 48, col: 43, offset: 1348},
197 expr: &seqExpr{
198 pos: position{line: 48, col: 44, offset: 1349},
199 exprs: []interface{}{
200 &litMatcher{
201 pos: position{line: 48, col: 44, offset: 1349},
202 val: ",",
203 ignoreCase: false,
204 },
205 &ruleRefExpr{
206 pos: position{line: 48, col: 48, offset: 1353},
207 name: "ReturnStage",
208 },
209 },
210 },
211 },
212 },
213 },
214 },
215 },
216 &actionExpr{
217 pos: position{line: 70, col: 5, offset: 1791},
218 run: (*parser).callonPhrase19,
219 expr: &seqExpr{
220 pos: position{line: 70, col: 5, offset: 1791},
221 exprs: []interface{}{
222 &litMatcher{
223 pos: position{line: 70, col: 5, offset: 1791},
224 val: ",",
225 ignoreCa se: false,
226 },
227 &zeroOrMoreExpr{
228 pos: pos ition{line: 70, col: 9, offset: 1795},
229 expr: &a nyMatcher{
230 line: 70, col: 9, offset: 1795,
231 },
232 },
233 },
234 },
235 },
236 },
237 },
238 },
239 {
240 name: "Stage",
241 pos: position{line: 74, col: 1, offset: 1868},
242 expr: &actionExpr{
243 pos: position{line: 74, col: 9, offset: 1876},
244 run: (*parser).callonStage1,
245 expr: &labeledExpr{
246 pos: position{line: 74, col: 9, offset : 1876},
247 label: "s",
248 expr: &choiceExpr{
249 pos: position{line: 74, col: 12, offset: 1879},
250 alternatives: []interface{}{
251 &ruleRefExpr{
252 pos: position{l ine: 74, col: 12, offset: 1879},
253 name: "FailureSt age",
254 },
255 &ruleRefExpr{
256 pos: position{l ine: 74, col: 27, offset: 1894},
257 name: "StallStag e",
258 },
259 &ruleRefExpr{
260 pos: position{l ine: 74, col: 40, offset: 1907},
261 name: "DepsStage ",
262 },
263 },
264 },
265 },
266 },
267 },
268 {
269 name: "FailureStage",
270 pos: position{line: 78, col: 1, offset: 1939},
271 expr: &actionExpr{
272 pos: position{line: 78, col: 16, offset: 1954},
273 run: (*parser).callonFailureStage1,
274 expr: &seqExpr{
275 pos: position{line: 78, col: 16, offset: 1954},
276 exprs: []interface{}{
277 &litMatcher{
278 pos: position{lin e: 78, col: 16, offset: 1954},
279 val: "%",
280 ignoreCase: false,
281 },
282 &labeledExpr{
283 pos: position{line: 78 , col: 20, offset: 1958},
284 label: "num",
285 expr: &ruleRefExpr{
286 pos: position{l ine: 78, col: 24, offset: 1962},
287 name: "Num",
288 },
289 },
290 },
291 },
292 },
293 },
294 {
295 name: "StallStage",
296 pos: position{line: 82, col: 1, offset: 2012},
297 expr: &actionExpr{
298 pos: position{line: 82, col: 14, offset: 2025},
299 run: (*parser).callonStallStage1,
300 expr: &seqExpr{
301 pos: position{line: 82, col: 14, offset: 2025},
302 exprs: []interface{}{
303 &litMatcher{
304 pos: position{lin e: 82, col: 14, offset: 2025},
305 val: "@",
306 ignoreCase: false,
307 },
308 &labeledExpr{
309 pos: position{line: 82 , col: 18, offset: 2029},
310 label: "amt",
311 expr: &ruleRefExpr{
312 pos: position{l ine: 82, col: 22, offset: 2033},
313 name: "Duration" ,
314 },
315 },
316 },
317 },
318 },
319 },
320 {
321 name: "ReturnStage",
322 pos: position{line: 86, col: 1, offset: 2093},
323 expr: &actionExpr{
324 pos: position{line: 86, col: 15, offset: 2107},
325 run: (*parser).callonReturnStage1,
326 expr: &seqExpr{
327 pos: position{line: 86, col: 15, offset: 2107},
328 exprs: []interface{}{
329 &litMatcher{
330 pos: position{lin e: 86, col: 15, offset: 2107},
331 val: "=",
332 ignoreCase: false,
333 },
334 &labeledExpr{
335 pos: position{line: 86 , col: 19, offset: 2111},
336 label: "val",
337 expr: &ruleRefExpr{
338 pos: position{l ine: 86, col: 23, offset: 2115},
339 name: "Num",
340 },
341 },
342 &labeledExpr{
343 pos: position{line: 86 , col: 27, offset: 2119},
344 label: "exp",
345 expr: &zeroOrOneExpr{
346 pos: position{li ne: 86, col: 31, offset: 2123},
347 expr: &seqExpr{
348 pos: pos ition{line: 86, col: 32, offset: 2124},
349 exprs: [ ]interface{}{
350 &litMatcher{
351 pos: position{line: 86, col: 32, offset: 2124},
352 val: "<",
353 ignoreCase: false,
354 },
355 &ruleRefExpr{
356 pos: position{line: 86, col: 36, offset: 2128},
357 name: "Duration",
358 },
359 },
360 },
361 },
362 },
363 },
364 },
365 },
366 },
367 {
368 name: "DepsStage",
369 pos: position{line: 94, col: 1, offset: 2287},
370 expr: &choiceExpr{
371 pos: position{line: 94, col: 13, offset: 2299},
372 alternatives: []interface{}{
373 &actionExpr{
374 pos: position{line: 94, col: 13, offset: 2299},
375 run: (*parser).callonDepsStage2,
376 expr: &seqExpr{
377 pos: position{line: 94, col: 13, offset: 2299},
378 exprs: []interface{}{
379 &labeledExpr{
380 pos: p osition{line: 94, col: 13, offset: 2299},
381 label: " first",
382 expr: &r uleRefExpr{
383 pos: position{line: 94, col: 19, offset: 2305},
384 name: "Dependency",
385 },
386 },
387 &labeledExpr{
388 pos: p osition{line: 94, col: 30, offset: 2316},
389 label: " restI",
390 expr: &z eroOrMoreExpr{
391 pos: position{line: 94, col: 36, offset: 2322},
392 expr: &seqExpr{
393 pos: position{line: 94, col: 37, offset: 2323},
394 exprs: []interface{}{
395 &litMatcher{
396 pos: position{line: 94, col: 37, offset: 2323},
397 val: "&",
398 ignoreCase: false,
399 },
400 &ruleRefExpr{
401 pos: position{line: 94, col: 41, offset: 2327},
402 name: "Dependency",
403 },
404 },
405 },
406 },
407 },
408 },
409 },
410 },
411 &actionExpr{
412 pos: position{line: 106, col: 5, offset: 2644},
413 run: (*parser).callonDepsStage11 ,
414 expr: &seqExpr{
415 pos: position{line: 106, col: 5, offset: 2644},
416 exprs: []interface{}{
417 &litMatcher{
418 pos: position{line: 106, col: 5, offset: 2644},
419 val: "&",
420 ignoreCa se: false,
421 },
422 &zeroOrMoreExpr{
423 pos: pos ition{line: 106, col: 9, offset: 2648},
424 expr: &a nyMatcher{
425 line: 106, col: 9, offset: 2648,
426 },
427 },
428 },
429 },
430 },
431 },
432 },
433 },
434 {
435 name: "Dependency",
436 pos: position{line: 110, col: 1, offset: 2726},
437 expr: &actionExpr{
438 pos: position{line: 110, col: 14, offset: 2739},
439 run: (*parser).callonDependency1,
440 expr: &seqExpr{
441 pos: position{line: 110, col: 14, offset : 2739},
442 exprs: []interface{}{
443 &labeledExpr{
444 pos: position{line: 11 0, col: 14, offset: 2739},
445 label: "shards",
446 expr: &zeroOrOneExpr{
447 pos: position{li ne: 110, col: 21, offset: 2746},
448 expr: &ruleRefEx pr{
449 pos: po sition{line: 110, col: 21, offset: 2746},
450 name: "S hards",
451 },
452 },
453 },
454 &labeledExpr{
455 pos: position{line: 11 0, col: 29, offset: 2754},
456 label: "attempts",
457 expr: &zeroOrOneExpr{
458 pos: position{li ne: 110, col: 38, offset: 2763},
459 expr: &ruleRefEx pr{
460 pos: po sition{line: 110, col: 38, offset: 2763},
461 name: "A ttempts",
462 },
463 },
464 },
465 &labeledExpr{
466 pos: position{line: 11 0, col: 48, offset: 2773},
467 label: "id",
468 expr: &ruleRefExpr{
469 pos: position{l ine: 110, col: 51, offset: 2776},
470 name: "ID",
471 },
472 },
473 &labeledExpr{
474 pos: position{line: 11 0, col: 54, offset: 2779},
475 label: "options",
476 expr: &zeroOrOneExpr{
477 pos: position{li ne: 110, col: 62, offset: 2787},
478 expr: &ruleRefEx pr{
479 pos: po sition{line: 110, col: 62, offset: 2787},
480 name: "O ption",
481 },
482 },
483 },
484 &labeledExpr{
485 pos: position{line: 11 0, col: 70, offset: 2795},
486 label: "subI",
487 expr: &zeroOrOneExpr{
488 pos: position{li ne: 110, col: 75, offset: 2800},
489 expr: &seqExpr{
490 pos: pos ition{line: 110, col: 77, offset: 2802},
491 exprs: [ ]interface{}{
492 &litMatcher{
493 pos: position{line: 110, col: 77, offset: 2802},
494 val: "(",
495 ignoreCase: false,
496 },
497 &ruleRefExpr{
498 pos: position{line: 110, col: 81, offset: 2806},
499 name: "Phrase",
500 },
501 &litMatcher{
502 pos: position{line: 110, col: 88, offset: 2813},
503 val: ")",
504 ignoreCase: false,
505 },
506 },
507 },
508 },
509 },
510 },
511 },
512 },
513 },
514 {
515 name: "Option",
516 pos: position{line: 144, col: 1, offset: 3446},
517 expr: &choiceExpr{
518 pos: position{line: 144, col: 10, offset: 3455},
519 alternatives: []interface{}{
520 &actionExpr{
521 pos: position{line: 144, col: 10 , offset: 3455},
522 run: (*parser).callonOption2,
523 expr: &seqExpr{
524 pos: position{line: 144, col: 10, offset: 3455},
525 exprs: []interface{}{
526 &litMatcher{
527 pos: position{line: 144, col: 10, offset: 3455},
528 val: "+",
529 ignoreCa se: false,
530 },
531 &labeledExpr{
532 pos: p osition{line: 144, col: 14, offset: 3459},
533 label: " num",
534 expr: &r uleRefExpr{
535 pos: position{line: 144, col: 18, offset: 3463},
536 name: "Num",
537 },
538 },
539 },
540 },
541 },
542 &actionExpr{
543 pos: position{line: 146, col: 5, offset: 3516},
544 run: (*parser).callonOption7,
545 expr: &seqExpr{
546 pos: position{line: 146, col: 5, offset: 3516},
547 exprs: []interface{}{
548 &litMatcher{
549 pos: position{line: 146, col: 5, offset: 3516},
550 val: "^",
551 ignoreCa se: false,
552 },
553 &labeledExpr{
554 pos: p osition{line: 146, col: 9, offset: 3520},
555 label: " num",
556 expr: &r uleRefExpr{
557 pos: position{line: 146, col: 13, offset: 3524},
558 name: "Num",
559 },
560 },
561 },
562 },
563 },
564 },
565 },
566 },
567 {
568 name: "Shards",
569 pos: position{line: 150, col: 1, offset: 3577},
570 expr: &actionExpr{
571 pos: position{line: 150, col: 10, offset: 3586},
572 run: (*parser).callonShards1,
573 expr: &seqExpr{
574 pos: position{line: 150, col: 10, offset : 3586},
575 exprs: []interface{}{
576 &litMatcher{
577 pos: position{lin e: 150, col: 10, offset: 3586},
578 val: "{",
579 ignoreCase: false,
580 },
581 &labeledExpr{
582 pos: position{line: 15 0, col: 14, offset: 3590},
583 label: "num",
584 expr: &ruleRefExpr{
585 pos: position{l ine: 150, col: 18, offset: 3594},
586 name: "Num",
587 },
588 },
589 &litMatcher{
590 pos: position{lin e: 150, col: 22, offset: 3598},
591 val: "}",
592 ignoreCase: false,
593 },
594 },
595 },
596 },
597 },
598 {
599 name: "Attempts",
600 pos: position{line: 154, col: 1, offset: 3625},
601 expr: &actionExpr{
602 pos: position{line: 154, col: 12, offset: 3636},
603 run: (*parser).callonAttempts1,
604 expr: &seqExpr{
605 pos: position{line: 154, col: 12, offset : 3636},
606 exprs: []interface{}{
607 &litMatcher{
608 pos: position{lin e: 154, col: 12, offset: 3636},
609 val: "[",
610 ignoreCase: false,
611 },
612 &labeledExpr{
613 pos: position{line: 15 4, col: 16, offset: 3640},
614 label: "rs",
615 expr: &ruleRefExpr{
616 pos: position{l ine: 154, col: 19, offset: 3643},
617 name: "RangeSlic e",
618 },
619 },
620 &litMatcher{
621 pos: position{lin e: 154, col: 30, offset: 3654},
622 val: "]",
623 ignoreCase: false,
624 },
625 },
626 },
627 },
628 },
629 {
630 name: "RangeSlice",
631 pos: position{line: 158, col: 1, offset: 3680},
632 expr: &actionExpr{
633 pos: position{line: 158, col: 14, offset: 3693},
634 run: (*parser).callonRangeSlice1,
635 expr: &seqExpr{
636 pos: position{line: 158, col: 14, offset : 3693},
637 exprs: []interface{}{
638 &labeledExpr{
639 pos: position{line: 15 8, col: 14, offset: 3693},
640 label: "firstI",
641 expr: &ruleRefExpr{
642 pos: position{l ine: 158, col: 21, offset: 3700},
643 name: "Range",
644 },
645 },
646 &labeledExpr{
647 pos: position{line: 15 8, col: 27, offset: 3706},
648 label: "restI",
649 expr: &zeroOrMoreExpr{
650 pos: position{li ne: 158, col: 33, offset: 3712},
651 expr: &seqExpr{
652 pos: pos ition{line: 158, col: 34, offset: 3713},
653 exprs: [ ]interface{}{
654 &litMatcher{
655 pos: position{line: 158, col: 34, offset: 3713},
656 val: ",",
657 ignoreCase: false,
658 },
659 &ruleRefExpr{
660 pos: position{line: 158, col: 38, offset: 3717},
661 name: "Range",
662 },
663 },
664 },
665 },
666 },
667 },
668 },
669 },
670 },
671 {
672 name: "Range",
673 pos: position{line: 170, col: 1, offset: 3950},
674 expr: &choiceExpr{
675 pos: position{line: 170, col: 9, offset: 3958},
676 alternatives: []interface{}{
677 &actionExpr{
678 pos: position{line: 170, col: 9, offset: 3958},
679 run: (*parser).callonRange2,
680 expr: &seqExpr{
681 pos: position{line: 170, col: 9, offset: 3958},
682 exprs: []interface{}{
683 &labeledExpr{
684 pos: p osition{line: 170, col: 9, offset: 3958},
685 label: " loI",
686 expr: &r uleRefExpr{
687 pos: position{line: 170, col: 13, offset: 3962},
688 name: "Num",
689 },
690 },
691 &litMatcher{
692 pos: position{line: 170, col: 17, offset: 3966},
693 val: "-",
694 ignoreCa se: false,
695 },
696 &labeledExpr{
697 pos: p osition{line: 170, col: 21, offset: 3970},
698 label: " hiI",
699 expr: &r uleRefExpr{
700 pos: position{line: 170, col: 25, offset: 3974},
701 name: "Num",
702 },
703 },
704 },
705 },
706 },
707 &actionExpr{
708 pos: position{line: 179, col: 5, offset: 4149},
709 run: (*parser).callonRange9,
710 expr: &labeledExpr{
711 pos: position{line: 17 9, col: 5, offset: 4149},
712 label: "num",
713 expr: &ruleRefExpr{
714 pos: position{l ine: 179, col: 9, offset: 4153},
715 name: "Num",
716 },
717 },
718 },
719 },
720 },
721 },
722 {
723 name: "Duration",
724 pos: position{line: 183, col: 1, offset: 4199},
725 expr: &actionExpr{
726 pos: position{line: 183, col: 12, offset: 4210},
727 run: (*parser).callonDuration1,
728 expr: &labeledExpr{
729 pos: position{line: 183, col: 12, offs et: 4210},
730 label: "num",
731 expr: &ruleRefExpr{
732 pos: position{line: 183, col: 1 6, offset: 4214},
733 name: "Num",
734 },
735 },
736 },
737 },
738 {
739 name: "Num",
740 pos: position{line: 187, col: 1, offset: 4279},
741 expr: &choiceExpr{
742 pos: position{line: 187, col: 7, offset: 4285},
743 alternatives: []interface{}{
744 &actionExpr{
745 pos: position{line: 187, col: 7, offset: 4285},
746 run: (*parser).callonNum2,
747 expr: &litMatcher{
748 pos: position{lin e: 187, col: 7, offset: 4285},
749 val: "0",
750 ignoreCase: false,
751 },
752 },
753 &actionExpr{
754 pos: position{line: 189, col: 5, offset: 4349},
755 run: (*parser).callonNum4,
756 expr: &seqExpr{
757 pos: position{line: 189, col: 5, offset: 4349},
758 exprs: []interface{}{
759 &charClassMatche r{
760 pos: position{line: 189, col: 5, offset: 4349},
761 val: "[1-9]",
762 ranges: []rune{'1', '9'},
763 ignoreCa se: false,
764 inverted : false,
765 },
766 &zeroOrMoreExpr{
767 pos: pos ition{line: 189, col: 10, offset: 4354},
768 expr: &c harClassMatcher{
769 pos: position{line: 189, col: 10, offset: 4354},
770 val: "[0-9]",
771 ranges: []rune{'0', '9'},
772 ignoreCase: false,
773 inverted: false,
774 },
775 },
776 },
777 },
778 },
779 &actionExpr{
780 pos: position{line: 191, col: 5, offset: 4418},
781 run: (*parser).callonNum9,
782 expr: &zeroOrMoreExpr{
783 pos: position{line: 191, col: 5, offset: 4418},
784 expr: &anyMatcher{
785 line: 191, col: 5, offset: 4418,
786 },
787 },
788 },
789 },
790 },
791 },
792 {
793 name: "ID",
794 pos: position{line: 195, col: 1, offset: 4494},
795 expr: &actionExpr{
796 pos: position{line: 195, col: 6, offset: 4499},
797 run: (*parser).callonID1,
798 expr: &oneOrMoreExpr{
799 pos: position{line: 195, col: 6, offset: 4499},
800 expr: &charClassMatcher{
801 pos: position{line: 195, col: 6, offset: 4499},
802 val: "[a-zA-Z'_]",
803 chars: []rune{'\'', '_'},
804 ranges: []rune{'a', 'z', 'A' , 'Z'},
805 ignoreCase: false,
806 inverted: false,
807 },
808 },
809 },
810 },
811 },
812 }
813
814 func (c *current) onOverall2(p interface{}) (interface{}, error) {
815 return p, nil
816 }
817
818 func (p *parser) callonOverall2() (interface{}, error) {
819 stack := p.vstack[len(p.vstack)-1]
820 _ = stack
821 return p.cur.onOverall2(stack["p"])
822 }
823
824 func (c *current) onOverall8(p, ext interface{}) (interface{}, error) {
825 return nil, fmt.Errorf("found extra: %q", ext.(string))
826 }
827
828 func (p *parser) callonOverall8() (interface{}, error) {
829 stack := p.vstack[len(p.vstack)-1]
830 _ = stack
831 return p.cur.onOverall8(stack["p"], stack["ext"])
832 }
833
834 func (c *current) onOverall14() (interface{}, error) {
835 return nil, fmt.Errorf("empty phrase")
836 }
837
838 func (p *parser) callonOverall14() (interface{}, error) {
839 stack := p.vstack[len(p.vstack)-1]
840 _ = stack
841 return p.cur.onOverall14()
842 }
843
844 func (c *current) onOverall17(ext interface{}) (interface{}, error) {
845 return nil, fmt.Errorf("expected phrase: %q", ext.(string))
846 }
847
848 func (p *parser) callonOverall17() (interface{}, error) {
849 stack := p.vstack[len(p.vstack)-1]
850 _ = stack
851 return p.cur.onOverall17(stack["ext"])
852 }
853
854 func (c *current) onExtra1() (interface{}, error) {
855 return string(c.text), nil
856 }
857
858 func (p *parser) callonExtra1() (interface{}, error) {
859 stack := p.vstack[len(p.vstack)-1]
860 _ = stack
861 return p.cur.onExtra1()
862 }
863
864 func (c *current) onPhrase2(ret interface{}) (interface{}, error) {
865 return Phrase{ret.(Stage)}, nil
866 }
867
868 func (p *parser) callonPhrase2() (interface{}, error) {
869 stack := p.vstack[len(p.vstack)-1]
870 _ = stack
871 return p.cur.onPhrase2(stack["ret"])
872 }
873
874 func (c *current) onPhrase5(first, middleI, retI interface{}) (interface{}, erro r) {
875 middle, _ := middleI.([]interface{})
876 retStage, _ := retI.([]interface{})
877
878 amt := 1
879 if middle != nil {
880 amt += len(middle)
881 }
882 if retStage != nil {
883 amt++
884 }
885
886 ret := make(Phrase, 0, amt)
887 ret = append(ret, first.(Stage))
888 for _, itm := range middle {
889 ret = append(ret, itm.([]interface{})[1].(Stage))
890 }
891 if retStage != nil {
892 ret = append(ret, retStage[1].(Stage))
893 }
894
895 return ret, nil
896 }
897
898 func (p *parser) callonPhrase5() (interface{}, error) {
899 stack := p.vstack[len(p.vstack)-1]
900 _ = stack
901 return p.cur.onPhrase5(stack["first"], stack["middleI"], stack["retI"])
902 }
903
904 func (c *current) onPhrase19() (interface{}, error) {
905 return nil, fmt.Errorf("expected stage in %q", string(c.text))
906 }
907
908 func (p *parser) callonPhrase19() (interface{}, error) {
909 stack := p.vstack[len(p.vstack)-1]
910 _ = stack
911 return p.cur.onPhrase19()
912 }
913
914 func (c *current) onStage1(s interface{}) (interface{}, error) {
915 return s, nil
916 }
917
918 func (p *parser) callonStage1() (interface{}, error) {
919 stack := p.vstack[len(p.vstack)-1]
920 _ = stack
921 return p.cur.onStage1(stack["s"])
922 }
923
924 func (c *current) onFailureStage1(num interface{}) (interface{}, error) {
925 return FailureStage(num.(uint64)), nil
926 }
927
928 func (p *parser) callonFailureStage1() (interface{}, error) {
929 stack := p.vstack[len(p.vstack)-1]
930 _ = stack
931 return p.cur.onFailureStage1(stack["num"])
932 }
933
934 func (c *current) onStallStage1(amt interface{}) (interface{}, error) {
935 return StallStage(amt.(time.Duration)), nil
936 }
937
938 func (p *parser) callonStallStage1() (interface{}, error) {
939 stack := p.vstack[len(p.vstack)-1]
940 _ = stack
941 return p.cur.onStallStage1(stack["amt"])
942 }
943
944 func (c *current) onReturnStage1(val, exp interface{}) (interface{}, error) {
945 ret := &ReturnStage{Value: val.(uint64)}
946 if exp != nil {
947 ret.Expiration = exp.([]interface{})[1].(time.Duration)
948 }
949 return ret, nil
950 }
951
952 func (p *parser) callonReturnStage1() (interface{}, error) {
953 stack := p.vstack[len(p.vstack)-1]
954 _ = stack
955 return p.cur.onReturnStage1(stack["val"], stack["exp"])
956 }
957
958 func (c *current) onDepsStage2(first, restI interface{}) (interface{}, error) {
959 rest, _ := restI.([]interface{})
960
961 if rest == nil {
962 return DepsStage{first.(*Dependency)}, nil
963 }
964 ret := make(DepsStage, 0, 1+len(rest))
965 ret = append(ret, first.(*Dependency))
966 for _, itm := range rest {
967 ret = append(ret, itm.([]interface{})[1].(*Dependency))
968 }
969 return ret, nil
970 }
971
972 func (p *parser) callonDepsStage2() (interface{}, error) {
973 stack := p.vstack[len(p.vstack)-1]
974 _ = stack
975 return p.cur.onDepsStage2(stack["first"], stack["restI"])
976 }
977
978 func (c *current) onDepsStage11() (interface{}, error) {
979 return nil, fmt.Errorf("expected dependency in %q", string(c.text))
980 }
981
982 func (p *parser) callonDepsStage11() (interface{}, error) {
983 stack := p.vstack[len(p.vstack)-1]
984 _ = stack
985 return p.cur.onDepsStage11()
986 }
987
988 func (c *current) onDependency1(shards, attempts, id, options, subI interface{}) (interface{}, error) {
989 ret := &Dependency{Name: id.(string)}
990
991 if shards != nil {
992 ret.ShardCount = shards.(uint64)
993 }
994
995 if attempts != nil {
996 ret.AttemptNums = attempts.(RangeSlice)
997 }
998
999 if options != nil {
1000 switch x := options.(type) {
1001 case retriesHolder:
1002 if attempts != nil {
1003 return nil, fmt.Errorf(
1004 "in %q: retries are incompatible with sp ecified Attempts",
1005 string(c.text))
1006 }
1007 ret.Retries = uint64(x)
1008
1009 case identityHolder:
1010 ret.Uniq = uint64(x)
1011 }
1012 }
1013
1014 sub, _ := subI.([]interface{})
1015 if sub != nil {
1016 ret.Substages = sub[1].(Phrase)
1017 }
1018
1019 return ret, nil
1020 }
1021
1022 func (p *parser) callonDependency1() (interface{}, error) {
1023 stack := p.vstack[len(p.vstack)-1]
1024 _ = stack
1025 return p.cur.onDependency1(stack["shards"], stack["attempts"], stack["id "], stack["options"], stack["subI"])
1026 }
1027
1028 func (c *current) onOption2(num interface{}) (interface{}, error) {
1029 return retriesHolder(num.(uint64)), nil
1030 }
1031
1032 func (p *parser) callonOption2() (interface{}, error) {
1033 stack := p.vstack[len(p.vstack)-1]
1034 _ = stack
1035 return p.cur.onOption2(stack["num"])
1036 }
1037
1038 func (c *current) onOption7(num interface{}) (interface{}, error) {
1039 return identityHolder(num.(uint64)), nil
1040 }
1041
1042 func (p *parser) callonOption7() (interface{}, error) {
1043 stack := p.vstack[len(p.vstack)-1]
1044 _ = stack
1045 return p.cur.onOption7(stack["num"])
1046 }
1047
1048 func (c *current) onShards1(num interface{}) (interface{}, error) {
1049 return num, nil
1050 }
1051
1052 func (p *parser) callonShards1() (interface{}, error) {
1053 stack := p.vstack[len(p.vstack)-1]
1054 _ = stack
1055 return p.cur.onShards1(stack["num"])
1056 }
1057
1058 func (c *current) onAttempts1(rs interface{}) (interface{}, error) {
1059 return rs, nil
1060 }
1061
1062 func (p *parser) callonAttempts1() (interface{}, error) {
1063 stack := p.vstack[len(p.vstack)-1]
1064 _ = stack
1065 return p.cur.onAttempts1(stack["rs"])
1066 }
1067
1068 func (c *current) onRangeSlice1(firstI, restI interface{}) (interface{}, error) {
1069 rest, _ := restI.([]interface{})
1070
1071 ret := make(RangeSlice, 0, 1+len(rest))
1072 ret = append(ret, firstI.(Range))
1073 for _, itm := range rest {
1074 ret = append(ret, itm.([]interface{})[1].(Range))
1075 }
1076
1077 return ret, nil
1078 }
1079
1080 func (p *parser) callonRangeSlice1() (interface{}, error) {
1081 stack := p.vstack[len(p.vstack)-1]
1082 _ = stack
1083 return p.cur.onRangeSlice1(stack["firstI"], stack["restI"])
1084 }
1085
1086 func (c *current) onRange2(loI, hiI interface{}) (interface{}, error) {
1087 lo := loI.(uint64)
1088 hi := hiI.(uint64)
1089
1090 if lo >= hi {
1091 return nil, fmt.Errorf("invalid range %q: lo >= hi", string(c.te xt))
1092 }
1093
1094 return Range{lo, hi}, nil
1095 }
1096
1097 func (p *parser) callonRange2() (interface{}, error) {
1098 stack := p.vstack[len(p.vstack)-1]
1099 _ = stack
1100 return p.cur.onRange2(stack["loI"], stack["hiI"])
1101 }
1102
1103 func (c *current) onRange9(num interface{}) (interface{}, error) {
1104 return Range{num.(uint64), 0}, nil
1105 }
1106
1107 func (p *parser) callonRange9() (interface{}, error) {
1108 stack := p.vstack[len(p.vstack)-1]
1109 _ = stack
1110 return p.cur.onRange9(stack["num"])
1111 }
1112
1113 func (c *current) onDuration1(num interface{}) (interface{}, error) {
1114 return time.Second * time.Duration(num.(uint64)), nil
1115 }
1116
1117 func (p *parser) callonDuration1() (interface{}, error) {
1118 stack := p.vstack[len(p.vstack)-1]
1119 _ = stack
1120 return p.cur.onDuration1(stack["num"])
1121 }
1122
1123 func (c *current) onNum2() (interface{}, error) {
1124 return nil, fmt.Errorf("zero value not acceptable")
1125 }
1126
1127 func (p *parser) callonNum2() (interface{}, error) {
1128 stack := p.vstack[len(p.vstack)-1]
1129 _ = stack
1130 return p.cur.onNum2()
1131 }
1132
1133 func (c *current) onNum4() (interface{}, error) {
1134 return strconv.ParseUint(string(c.text), 10, 64)
1135 }
1136
1137 func (p *parser) callonNum4() (interface{}, error) {
1138 stack := p.vstack[len(p.vstack)-1]
1139 _ = stack
1140 return p.cur.onNum4()
1141 }
1142
1143 func (c *current) onNum9() (interface{}, error) {
1144 return nil, fmt.Errorf("expected number, got %q", string(c.text))
1145 }
1146
1147 func (p *parser) callonNum9() (interface{}, error) {
1148 stack := p.vstack[len(p.vstack)-1]
1149 _ = stack
1150 return p.cur.onNum9()
1151 }
1152
1153 func (c *current) onID1() (interface{}, error) {
1154 return string(c.text), nil
1155 }
1156
1157 func (p *parser) callonID1() (interface{}, error) {
1158 stack := p.vstack[len(p.vstack)-1]
1159 _ = stack
1160 return p.cur.onID1()
1161 }
1162
1163 var (
1164 // errNoRule is returned when the grammar to parse has no rule.
1165 errNoRule = errors.New("grammar has no rule")
1166
1167 // errInvalidEncoding is returned when the source is not properly
1168 // utf8-encoded.
1169 errInvalidEncoding = errors.New("invalid encoding")
1170
1171 // errNoMatch is returned if no match could be found.
1172 errNoMatch = errors.New("no match found")
1173 )
1174
1175 // Option is a function that can set an option on the parser. It returns
1176 // the previous setting as an Option.
1177 type Option func(*parser) Option
1178
1179 // Debug creates an Option to set the debug flag to b. When set to true,
1180 // debugging information is printed to stdout while parsing.
1181 //
1182 // The default is false.
1183 func Debug(b bool) Option {
1184 return func(p *parser) Option {
1185 old := p.debug
1186 p.debug = b
1187 return Debug(old)
1188 }
1189 }
1190
1191 // Memoize creates an Option to set the memoize flag to b. When set to true,
1192 // the parser will cache all results so each expression is evaluated only
1193 // once. This guarantees linear parsing time even for pathological cases,
1194 // at the expense of more memory and slower times for typical cases.
1195 //
1196 // The default is false.
1197 func Memoize(b bool) Option {
1198 return func(p *parser) Option {
1199 old := p.memoize
1200 p.memoize = b
1201 return Memoize(old)
1202 }
1203 }
1204
1205 // Recover creates an Option to set the recover flag to b. When set to
1206 // true, this causes the parser to recover from panics and convert it
1207 // to an error. Setting it to false can be useful while debugging to
1208 // access the full stack trace.
1209 //
1210 // The default is true.
1211 func Recover(b bool) Option {
1212 return func(p *parser) Option {
1213 old := p.recover
1214 p.recover = b
1215 return Recover(old)
1216 }
1217 }
1218
1219 // ParseFile parses the file identified by filename.
1220 func ParseFile(filename string, opts ...Option) (interface{}, error) {
1221 f, err := os.Open(filename)
1222 if err != nil {
1223 return nil, err
1224 }
1225 defer f.Close()
1226 return ParseReader(filename, f, opts...)
1227 }
1228
1229 // ParseReader parses the data from r using filename as information in the
1230 // error messages.
1231 func ParseReader(filename string, r io.Reader, opts ...Option) (interface{}, err or) {
1232 b, err := ioutil.ReadAll(r)
1233 if err != nil {
1234 return nil, err
1235 }
1236
1237 return Parse(filename, b, opts...)
1238 }
1239
1240 // Parse parses the data from b using filename as information in the
1241 // error messages.
1242 func Parse(filename string, b []byte, opts ...Option) (interface{}, error) {
1243 return newParser(filename, b, opts...).parse(g)
1244 }
1245
1246 // position records a position in the text.
1247 type position struct {
1248 line, col, offset int
1249 }
1250
1251 func (p position) String() string {
1252 return fmt.Sprintf("%d:%d [%d]", p.line, p.col, p.offset)
1253 }
1254
1255 // savepoint stores all state required to go back to this point in the
1256 // parser.
1257 type savepoint struct {
1258 position
1259 rn rune
1260 w int
1261 }
1262
1263 type current struct {
1264 pos position // start position of the match
1265 text []byte // raw text of the match
1266 }
1267
1268 // the AST types...
1269
1270 type grammar struct {
1271 pos position
1272 rules []*rule
1273 }
1274
1275 type rule struct {
1276 pos position
1277 name string
1278 displayName string
1279 expr interface{}
1280 }
1281
1282 type choiceExpr struct {
1283 pos position
1284 alternatives []interface{}
1285 }
1286
1287 type actionExpr struct {
1288 pos position
1289 expr interface{}
1290 run func(*parser) (interface{}, error)
1291 }
1292
1293 type seqExpr struct {
1294 pos position
1295 exprs []interface{}
1296 }
1297
1298 type labeledExpr struct {
1299 pos position
1300 label string
1301 expr interface{}
1302 }
1303
1304 type expr struct {
1305 pos position
1306 expr interface{}
1307 }
1308
1309 type andExpr expr
1310 type notExpr expr
1311 type zeroOrOneExpr expr
1312 type zeroOrMoreExpr expr
1313 type oneOrMoreExpr expr
1314
1315 type ruleRefExpr struct {
1316 pos position
1317 name string
1318 }
1319
1320 type andCodeExpr struct {
1321 pos position
1322 run func(*parser) (bool, error)
1323 }
1324
1325 type notCodeExpr struct {
1326 pos position
1327 run func(*parser) (bool, error)
1328 }
1329
1330 type litMatcher struct {
1331 pos position
1332 val string
1333 ignoreCase bool
1334 }
1335
1336 type charClassMatcher struct {
1337 pos position
1338 val string
1339 chars []rune
1340 ranges []rune
1341 classes []*unicode.RangeTable
1342 ignoreCase bool
1343 inverted bool
1344 }
1345
1346 type anyMatcher position
1347
1348 // errList cumulates the errors found by the parser.
1349 type errList []error
1350
1351 func (e *errList) add(err error) {
1352 *e = append(*e, err)
1353 }
1354
1355 func (e errList) err() error {
1356 if len(e) == 0 {
1357 return nil
1358 }
1359 e.dedupe()
1360 return e
1361 }
1362
1363 func (e *errList) dedupe() {
1364 var cleaned []error
1365 set := make(map[string]bool)
1366 for _, err := range *e {
1367 if msg := err.Error(); !set[msg] {
1368 set[msg] = true
1369 cleaned = append(cleaned, err)
1370 }
1371 }
1372 *e = cleaned
1373 }
1374
1375 func (e errList) Error() string {
1376 switch len(e) {
1377 case 0:
1378 return ""
1379 case 1:
1380 return e[0].Error()
1381 default:
1382 var buf bytes.Buffer
1383
1384 for i, err := range e {
1385 if i > 0 {
1386 buf.WriteRune('\n')
1387 }
1388 buf.WriteString(err.Error())
1389 }
1390 return buf.String()
1391 }
1392 }
1393
1394 // parserError wraps an error with a prefix indicating the rule in which
1395 // the error occurred. The original error is stored in the Inner field.
1396 type parserError struct {
1397 Inner error
1398 pos position
1399 prefix string
1400 }
1401
1402 // Error returns the error message.
1403 func (p *parserError) Error() string {
1404 return p.prefix + ": " + p.Inner.Error()
1405 }
1406
1407 // newParser creates a parser with the specified input source and options.
1408 func newParser(filename string, b []byte, opts ...Option) *parser {
1409 p := &parser{
1410 filename: filename,
1411 errs: new(errList),
1412 data: b,
1413 pt: savepoint{position: position{line: 1}},
1414 recover: true,
1415 }
1416 p.setOptions(opts)
1417 return p
1418 }
1419
1420 // setOptions applies the options to the parser.
1421 func (p *parser) setOptions(opts []Option) {
1422 for _, opt := range opts {
1423 opt(p)
1424 }
1425 }
1426
1427 type resultTuple struct {
1428 v interface{}
1429 b bool
1430 end savepoint
1431 }
1432
1433 type parser struct {
1434 filename string
1435 pt savepoint
1436 cur current
1437
1438 data []byte
1439 errs *errList
1440
1441 recover bool
1442 debug bool
1443 depth int
1444
1445 memoize bool
1446 // memoization table for the packrat algorithm:
1447 // map[offset in source] map[expression or rule] {value, match}
1448 memo map[int]map[interface{}]resultTuple
1449
1450 // rules table, maps the rule identifier to the rule node
1451 rules map[string]*rule
1452 // variables stack, map of label to value
1453 vstack []map[string]interface{}
1454 // rule stack, allows identification of the current rule in errors
1455 rstack []*rule
1456
1457 // stats
1458 exprCnt int
1459 }
1460
1461 // push a variable set on the vstack.
1462 func (p *parser) pushV() {
1463 if cap(p.vstack) == len(p.vstack) {
1464 // create new empty slot in the stack
1465 p.vstack = append(p.vstack, nil)
1466 } else {
1467 // slice to 1 more
1468 p.vstack = p.vstack[:len(p.vstack)+1]
1469 }
1470
1471 // get the last args set
1472 m := p.vstack[len(p.vstack)-1]
1473 if m != nil && len(m) == 0 {
1474 // empty map, all good
1475 return
1476 }
1477
1478 m = make(map[string]interface{})
1479 p.vstack[len(p.vstack)-1] = m
1480 }
1481
1482 // pop a variable set from the vstack.
1483 func (p *parser) popV() {
1484 // if the map is not empty, clear it
1485 m := p.vstack[len(p.vstack)-1]
1486 if len(m) > 0 {
1487 // GC that map
1488 p.vstack[len(p.vstack)-1] = nil
1489 }
1490 p.vstack = p.vstack[:len(p.vstack)-1]
1491 }
1492
1493 func (p *parser) print(prefix, s string) string {
1494 if !p.debug {
1495 return s
1496 }
1497
1498 fmt.Printf("%s %d:%d:%d: %s [%#U]\n",
1499 prefix, p.pt.line, p.pt.col, p.pt.offset, s, p.pt.rn)
1500 return s
1501 }
1502
1503 func (p *parser) in(s string) string {
1504 p.depth++
1505 return p.print(strings.Repeat(" ", p.depth)+">", s)
1506 }
1507
1508 func (p *parser) out(s string) string {
1509 p.depth--
1510 return p.print(strings.Repeat(" ", p.depth)+"<", s)
1511 }
1512
1513 func (p *parser) addErr(err error) {
1514 p.addErrAt(err, p.pt.position)
1515 }
1516
1517 func (p *parser) addErrAt(err error, pos position) {
1518 var buf bytes.Buffer
1519 if p.filename != "" {
1520 buf.WriteString(p.filename)
1521 }
1522 if buf.Len() > 0 {
1523 buf.WriteString(":")
1524 }
1525 buf.WriteString(fmt.Sprintf("%d:%d (%d)", pos.line, pos.col, pos.offset) )
1526 if len(p.rstack) > 0 {
1527 if buf.Len() > 0 {
1528 buf.WriteString(": ")
1529 }
1530 rule := p.rstack[len(p.rstack)-1]
1531 if rule.displayName != "" {
1532 buf.WriteString("rule " + rule.displayName)
1533 } else {
1534 buf.WriteString("rule " + rule.name)
1535 }
1536 }
1537 pe := &parserError{Inner: err, prefix: buf.String()}
1538 p.errs.add(pe)
1539 }
1540
1541 // read advances the parser to the next rune.
1542 func (p *parser) read() {
1543 p.pt.offset += p.pt.w
1544 rn, n := utf8.DecodeRune(p.data[p.pt.offset:])
1545 p.pt.rn = rn
1546 p.pt.w = n
1547 p.pt.col++
1548 if rn == '\n' {
1549 p.pt.line++
1550 p.pt.col = 0
1551 }
1552
1553 if rn == utf8.RuneError {
1554 if n > 0 {
1555 p.addErr(errInvalidEncoding)
1556 }
1557 }
1558 }
1559
1560 // restore parser position to the savepoint pt.
1561 func (p *parser) restore(pt savepoint) {
1562 if p.debug {
1563 defer p.out(p.in("restore"))
1564 }
1565 if pt.offset == p.pt.offset {
1566 return
1567 }
1568 p.pt = pt
1569 }
1570
1571 // get the slice of bytes from the savepoint start to the current position.
1572 func (p *parser) sliceFrom(start savepoint) []byte {
1573 return p.data[start.position.offset:p.pt.position.offset]
1574 }
1575
1576 func (p *parser) getMemoized(node interface{}) (resultTuple, bool) {
1577 if len(p.memo) == 0 {
1578 return resultTuple{}, false
1579 }
1580 m := p.memo[p.pt.offset]
1581 if len(m) == 0 {
1582 return resultTuple{}, false
1583 }
1584 res, ok := m[node]
1585 return res, ok
1586 }
1587
1588 func (p *parser) setMemoized(pt savepoint, node interface{}, tuple resultTuple) {
1589 if p.memo == nil {
1590 p.memo = make(map[int]map[interface{}]resultTuple)
1591 }
1592 m := p.memo[pt.offset]
1593 if m == nil {
1594 m = make(map[interface{}]resultTuple)
1595 p.memo[pt.offset] = m
1596 }
1597 m[node] = tuple
1598 }
1599
1600 func (p *parser) buildRulesTable(g *grammar) {
1601 p.rules = make(map[string]*rule, len(g.rules))
1602 for _, r := range g.rules {
1603 p.rules[r.name] = r
1604 }
1605 }
1606
1607 func (p *parser) parse(g *grammar) (val interface{}, err error) {
1608 if len(g.rules) == 0 {
1609 p.addErr(errNoRule)
1610 return nil, p.errs.err()
1611 }
1612
1613 // TODO : not super critical but this could be generated
1614 p.buildRulesTable(g)
1615
1616 if p.recover {
1617 // panic can be used in action code to stop parsing immediately
1618 // and return the panic as an error.
1619 defer func() {
1620 if e := recover(); e != nil {
1621 if p.debug {
1622 defer p.out(p.in("panic handler"))
1623 }
1624 val = nil
1625 switch e := e.(type) {
1626 case error:
1627 p.addErr(e)
1628 default:
1629 p.addErr(fmt.Errorf("%v", e))
1630 }
1631 err = p.errs.err()
1632 }
1633 }()
1634 }
1635
1636 // start rule is rule [0]
1637 p.read() // advance to first rune
1638 val, ok := p.parseRule(g.rules[0])
1639 if !ok {
1640 if len(*p.errs) == 0 {
1641 // make sure this doesn't go out silently
1642 p.addErr(errNoMatch)
1643 }
1644 return nil, p.errs.err()
1645 }
1646 return val, p.errs.err()
1647 }
1648
1649 func (p *parser) parseRule(rule *rule) (interface{}, bool) {
1650 if p.debug {
1651 defer p.out(p.in("parseRule " + rule.name))
1652 }
1653
1654 if p.memoize {
1655 res, ok := p.getMemoized(rule)
1656 if ok {
1657 p.restore(res.end)
1658 return res.v, res.b
1659 }
1660 }
1661
1662 start := p.pt
1663 p.rstack = append(p.rstack, rule)
1664 p.pushV()
1665 val, ok := p.parseExpr(rule.expr)
1666 p.popV()
1667 p.rstack = p.rstack[:len(p.rstack)-1]
1668 if ok && p.debug {
1669 p.print(strings.Repeat(" ", p.depth)+"MATCH", string(p.sliceFrom (start)))
1670 }
1671
1672 if p.memoize {
1673 p.setMemoized(start, rule, resultTuple{val, ok, p.pt})
1674 }
1675 return val, ok
1676 }
1677
1678 func (p *parser) parseExpr(expr interface{}) (interface{}, bool) {
1679 var pt savepoint
1680 var ok bool
1681
1682 if p.memoize {
1683 res, ok := p.getMemoized(expr)
1684 if ok {
1685 p.restore(res.end)
1686 return res.v, res.b
1687 }
1688 pt = p.pt
1689 }
1690
1691 p.exprCnt++
1692 var val interface{}
1693 switch expr := expr.(type) {
1694 case *actionExpr:
1695 val, ok = p.parseActionExpr(expr)
1696 case *andCodeExpr:
1697 val, ok = p.parseAndCodeExpr(expr)
1698 case *andExpr:
1699 val, ok = p.parseAndExpr(expr)
1700 case *anyMatcher:
1701 val, ok = p.parseAnyMatcher(expr)
1702 case *charClassMatcher:
1703 val, ok = p.parseCharClassMatcher(expr)
1704 case *choiceExpr:
1705 val, ok = p.parseChoiceExpr(expr)
1706 case *labeledExpr:
1707 val, ok = p.parseLabeledExpr(expr)
1708 case *litMatcher:
1709 val, ok = p.parseLitMatcher(expr)
1710 case *notCodeExpr:
1711 val, ok = p.parseNotCodeExpr(expr)
1712 case *notExpr:
1713 val, ok = p.parseNotExpr(expr)
1714 case *oneOrMoreExpr:
1715 val, ok = p.parseOneOrMoreExpr(expr)
1716 case *ruleRefExpr:
1717 val, ok = p.parseRuleRefExpr(expr)
1718 case *seqExpr:
1719 val, ok = p.parseSeqExpr(expr)
1720 case *zeroOrMoreExpr:
1721 val, ok = p.parseZeroOrMoreExpr(expr)
1722 case *zeroOrOneExpr:
1723 val, ok = p.parseZeroOrOneExpr(expr)
1724 default:
1725 panic(fmt.Sprintf("unknown expression type %T", expr))
1726 }
1727 if p.memoize {
1728 p.setMemoized(pt, expr, resultTuple{val, ok, p.pt})
1729 }
1730 return val, ok
1731 }
1732
1733 func (p *parser) parseActionExpr(act *actionExpr) (interface{}, bool) {
1734 if p.debug {
1735 defer p.out(p.in("parseActionExpr"))
1736 }
1737
1738 start := p.pt
1739 val, ok := p.parseExpr(act.expr)
1740 if ok {
1741 p.cur.pos = start.position
1742 p.cur.text = p.sliceFrom(start)
1743 actVal, err := act.run(p)
1744 if err != nil {
1745 p.addErrAt(err, start.position)
1746 }
1747 val = actVal
1748 }
1749 if ok && p.debug {
1750 p.print(strings.Repeat(" ", p.depth)+"MATCH", string(p.sliceFrom (start)))
1751 }
1752 return val, ok
1753 }
1754
1755 func (p *parser) parseAndCodeExpr(and *andCodeExpr) (interface{}, bool) {
1756 if p.debug {
1757 defer p.out(p.in("parseAndCodeExpr"))
1758 }
1759
1760 ok, err := and.run(p)
1761 if err != nil {
1762 p.addErr(err)
1763 }
1764 return nil, ok
1765 }
1766
1767 func (p *parser) parseAndExpr(and *andExpr) (interface{}, bool) {
1768 if p.debug {
1769 defer p.out(p.in("parseAndExpr"))
1770 }
1771
1772 pt := p.pt
1773 p.pushV()
1774 _, ok := p.parseExpr(and.expr)
1775 p.popV()
1776 p.restore(pt)
1777 return nil, ok
1778 }
1779
1780 func (p *parser) parseAnyMatcher(any *anyMatcher) (interface{}, bool) {
1781 if p.debug {
1782 defer p.out(p.in("parseAnyMatcher"))
1783 }
1784
1785 if p.pt.rn != utf8.RuneError {
1786 start := p.pt
1787 p.read()
1788 return p.sliceFrom(start), true
1789 }
1790 return nil, false
1791 }
1792
1793 func (p *parser) parseCharClassMatcher(chr *charClassMatcher) (interface{}, bool ) {
1794 if p.debug {
1795 defer p.out(p.in("parseCharClassMatcher"))
1796 }
1797
1798 cur := p.pt.rn
1799 // can't match EOF
1800 if cur == utf8.RuneError {
1801 return nil, false
1802 }
1803 start := p.pt
1804 if chr.ignoreCase {
1805 cur = unicode.ToLower(cur)
1806 }
1807
1808 // try to match in the list of available chars
1809 for _, rn := range chr.chars {
1810 if rn == cur {
1811 if chr.inverted {
1812 return nil, false
1813 }
1814 p.read()
1815 return p.sliceFrom(start), true
1816 }
1817 }
1818
1819 // try to match in the list of ranges
1820 for i := 0; i < len(chr.ranges); i += 2 {
1821 if cur >= chr.ranges[i] && cur <= chr.ranges[i+1] {
1822 if chr.inverted {
1823 return nil, false
1824 }
1825 p.read()
1826 return p.sliceFrom(start), true
1827 }
1828 }
1829
1830 // try to match in the list of Unicode classes
1831 for _, cl := range chr.classes {
1832 if unicode.Is(cl, cur) {
1833 if chr.inverted {
1834 return nil, false
1835 }
1836 p.read()
1837 return p.sliceFrom(start), true
1838 }
1839 }
1840
1841 if chr.inverted {
1842 p.read()
1843 return p.sliceFrom(start), true
1844 }
1845 return nil, false
1846 }
1847
1848 func (p *parser) parseChoiceExpr(ch *choiceExpr) (interface{}, bool) {
1849 if p.debug {
1850 defer p.out(p.in("parseChoiceExpr"))
1851 }
1852
1853 for _, alt := range ch.alternatives {
1854 p.pushV()
1855 val, ok := p.parseExpr(alt)
1856 p.popV()
1857 if ok {
1858 return val, ok
1859 }
1860 }
1861 return nil, false
1862 }
1863
1864 func (p *parser) parseLabeledExpr(lab *labeledExpr) (interface{}, bool) {
1865 if p.debug {
1866 defer p.out(p.in("parseLabeledExpr"))
1867 }
1868
1869 p.pushV()
1870 val, ok := p.parseExpr(lab.expr)
1871 p.popV()
1872 if ok && lab.label != "" {
1873 m := p.vstack[len(p.vstack)-1]
1874 m[lab.label] = val
1875 }
1876 return val, ok
1877 }
1878
1879 func (p *parser) parseLitMatcher(lit *litMatcher) (interface{}, bool) {
1880 if p.debug {
1881 defer p.out(p.in("parseLitMatcher"))
1882 }
1883
1884 start := p.pt
1885 for _, want := range lit.val {
1886 cur := p.pt.rn
1887 if lit.ignoreCase {
1888 cur = unicode.ToLower(cur)
1889 }
1890 if cur != want {
1891 p.restore(start)
1892 return nil, false
1893 }
1894 p.read()
1895 }
1896 return p.sliceFrom(start), true
1897 }
1898
1899 func (p *parser) parseNotCodeExpr(not *notCodeExpr) (interface{}, bool) {
1900 if p.debug {
1901 defer p.out(p.in("parseNotCodeExpr"))
1902 }
1903
1904 ok, err := not.run(p)
1905 if err != nil {
1906 p.addErr(err)
1907 }
1908 return nil, !ok
1909 }
1910
1911 func (p *parser) parseNotExpr(not *notExpr) (interface{}, bool) {
1912 if p.debug {
1913 defer p.out(p.in("parseNotExpr"))
1914 }
1915
1916 pt := p.pt
1917 p.pushV()
1918 _, ok := p.parseExpr(not.expr)
1919 p.popV()
1920 p.restore(pt)
1921 return nil, !ok
1922 }
1923
1924 func (p *parser) parseOneOrMoreExpr(expr *oneOrMoreExpr) (interface{}, bool) {
1925 if p.debug {
1926 defer p.out(p.in("parseOneOrMoreExpr"))
1927 }
1928
1929 var vals []interface{}
1930
1931 for {
1932 p.pushV()
1933 val, ok := p.parseExpr(expr.expr)
1934 p.popV()
1935 if !ok {
1936 if len(vals) == 0 {
1937 // did not match once, no match
1938 return nil, false
1939 }
1940 return vals, true
1941 }
1942 vals = append(vals, val)
1943 }
1944 }
1945
1946 func (p *parser) parseRuleRefExpr(ref *ruleRefExpr) (interface{}, bool) {
1947 if p.debug {
1948 defer p.out(p.in("parseRuleRefExpr " + ref.name))
1949 }
1950
1951 if ref.name == "" {
1952 panic(fmt.Sprintf("%s: invalid rule: missing name", ref.pos))
1953 }
1954
1955 rule := p.rules[ref.name]
1956 if rule == nil {
1957 p.addErr(fmt.Errorf("undefined rule: %s", ref.name))
1958 return nil, false
1959 }
1960 return p.parseRule(rule)
1961 }
1962
1963 func (p *parser) parseSeqExpr(seq *seqExpr) (interface{}, bool) {
1964 if p.debug {
1965 defer p.out(p.in("parseSeqExpr"))
1966 }
1967
1968 var vals []interface{}
1969
1970 pt := p.pt
1971 for _, expr := range seq.exprs {
1972 val, ok := p.parseExpr(expr)
1973 if !ok {
1974 p.restore(pt)
1975 return nil, false
1976 }
1977 vals = append(vals, val)
1978 }
1979 return vals, true
1980 }
1981
1982 func (p *parser) parseZeroOrMoreExpr(expr *zeroOrMoreExpr) (interface{}, bool) {
1983 if p.debug {
1984 defer p.out(p.in("parseZeroOrMoreExpr"))
1985 }
1986
1987 var vals []interface{}
1988
1989 for {
1990 p.pushV()
1991 val, ok := p.parseExpr(expr.expr)
1992 p.popV()
1993 if !ok {
1994 return vals, true
1995 }
1996 vals = append(vals, val)
1997 }
1998 }
1999
2000 func (p *parser) parseZeroOrOneExpr(expr *zeroOrOneExpr) (interface{}, bool) {
2001 if p.debug {
2002 defer p.out(p.in("parseZeroOrOneExpr"))
2003 }
2004
2005 p.pushV()
2006 val, _ := p.parseExpr(expr.expr)
2007 p.popV()
2008 // whether it matched or not, consider it a match
2009 return val, true
2010 }
2011
2012 func rangeTable(class string) *unicode.RangeTable {
2013 if rt, ok := unicode.Categories[class]; ok {
2014 return rt
2015 }
2016 if rt, ok := unicode.Properties[class]; ok {
2017 return rt
2018 }
2019 if rt, ok := unicode.Scripts[class]; ok {
2020 return rt
2021 }
2022
2023 // cannot happen
2024 panic(fmt.Sprintf("invalid Unicode class: %s", class))
2025 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698