OLD | NEW |
(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 ¬Expr{ |
| 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: ¬Expr{ |
| 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 } |
OLD | NEW |