github.com/angdraug/packer@v1.3.2/common/bootcommand/boot_command.go (about) 1 // Code generated by pigeon; DO NOT EDIT. 2 3 package bootcommand 4 5 import ( 6 "bytes" 7 "errors" 8 "fmt" 9 "io" 10 "io/ioutil" 11 "math" 12 "os" 13 "sort" 14 "strconv" 15 "strings" 16 "time" 17 "unicode" 18 "unicode/utf8" 19 ) 20 21 var g = &grammar{ 22 rules: []*rule{ 23 { 24 name: "Input", 25 pos: position{line: 6, col: 1, offset: 26}, 26 expr: &actionExpr{ 27 pos: position{line: 6, col: 10, offset: 35}, 28 run: (*parser).callonInput1, 29 expr: &seqExpr{ 30 pos: position{line: 6, col: 10, offset: 35}, 31 exprs: []interface{}{ 32 &labeledExpr{ 33 pos: position{line: 6, col: 10, offset: 35}, 34 label: "expr", 35 expr: &ruleRefExpr{ 36 pos: position{line: 6, col: 15, offset: 40}, 37 name: "Expr", 38 }, 39 }, 40 &ruleRefExpr{ 41 pos: position{line: 6, col: 20, offset: 45}, 42 name: "EOF", 43 }, 44 }, 45 }, 46 }, 47 }, 48 { 49 name: "Expr", 50 pos: position{line: 10, col: 1, offset: 75}, 51 expr: &actionExpr{ 52 pos: position{line: 10, col: 9, offset: 83}, 53 run: (*parser).callonExpr1, 54 expr: &labeledExpr{ 55 pos: position{line: 10, col: 9, offset: 83}, 56 label: "l", 57 expr: &oneOrMoreExpr{ 58 pos: position{line: 10, col: 11, offset: 85}, 59 expr: &choiceExpr{ 60 pos: position{line: 10, col: 13, offset: 87}, 61 alternatives: []interface{}{ 62 &ruleRefExpr{ 63 pos: position{line: 10, col: 13, offset: 87}, 64 name: "Wait", 65 }, 66 &ruleRefExpr{ 67 pos: position{line: 10, col: 20, offset: 94}, 68 name: "CharToggle", 69 }, 70 &ruleRefExpr{ 71 pos: position{line: 10, col: 33, offset: 107}, 72 name: "Special", 73 }, 74 &ruleRefExpr{ 75 pos: position{line: 10, col: 43, offset: 117}, 76 name: "Literal", 77 }, 78 }, 79 }, 80 }, 81 }, 82 }, 83 }, 84 { 85 name: "Wait", 86 pos: position{line: 14, col: 1, offset: 150}, 87 expr: &actionExpr{ 88 pos: position{line: 14, col: 8, offset: 157}, 89 run: (*parser).callonWait1, 90 expr: &seqExpr{ 91 pos: position{line: 14, col: 8, offset: 157}, 92 exprs: []interface{}{ 93 &ruleRefExpr{ 94 pos: position{line: 14, col: 8, offset: 157}, 95 name: "ExprStart", 96 }, 97 &litMatcher{ 98 pos: position{line: 14, col: 18, offset: 167}, 99 val: "wait", 100 ignoreCase: false, 101 }, 102 &labeledExpr{ 103 pos: position{line: 14, col: 25, offset: 174}, 104 label: "duration", 105 expr: &zeroOrOneExpr{ 106 pos: position{line: 14, col: 34, offset: 183}, 107 expr: &choiceExpr{ 108 pos: position{line: 14, col: 36, offset: 185}, 109 alternatives: []interface{}{ 110 &ruleRefExpr{ 111 pos: position{line: 14, col: 36, offset: 185}, 112 name: "Duration", 113 }, 114 &ruleRefExpr{ 115 pos: position{line: 14, col: 47, offset: 196}, 116 name: "Integer", 117 }, 118 }, 119 }, 120 }, 121 }, 122 &ruleRefExpr{ 123 pos: position{line: 14, col: 58, offset: 207}, 124 name: "ExprEnd", 125 }, 126 }, 127 }, 128 }, 129 }, 130 { 131 name: "CharToggle", 132 pos: position{line: 27, col: 1, offset: 453}, 133 expr: &actionExpr{ 134 pos: position{line: 27, col: 14, offset: 466}, 135 run: (*parser).callonCharToggle1, 136 expr: &seqExpr{ 137 pos: position{line: 27, col: 14, offset: 466}, 138 exprs: []interface{}{ 139 &ruleRefExpr{ 140 pos: position{line: 27, col: 14, offset: 466}, 141 name: "ExprStart", 142 }, 143 &labeledExpr{ 144 pos: position{line: 27, col: 24, offset: 476}, 145 label: "lit", 146 expr: &ruleRefExpr{ 147 pos: position{line: 27, col: 29, offset: 481}, 148 name: "Literal", 149 }, 150 }, 151 &labeledExpr{ 152 pos: position{line: 27, col: 38, offset: 490}, 153 label: "t", 154 expr: &choiceExpr{ 155 pos: position{line: 27, col: 41, offset: 493}, 156 alternatives: []interface{}{ 157 &ruleRefExpr{ 158 pos: position{line: 27, col: 41, offset: 493}, 159 name: "On", 160 }, 161 &ruleRefExpr{ 162 pos: position{line: 27, col: 46, offset: 498}, 163 name: "Off", 164 }, 165 }, 166 }, 167 }, 168 &ruleRefExpr{ 169 pos: position{line: 27, col: 51, offset: 503}, 170 name: "ExprEnd", 171 }, 172 }, 173 }, 174 }, 175 }, 176 { 177 name: "Special", 178 pos: position{line: 31, col: 1, offset: 574}, 179 expr: &actionExpr{ 180 pos: position{line: 31, col: 11, offset: 584}, 181 run: (*parser).callonSpecial1, 182 expr: &seqExpr{ 183 pos: position{line: 31, col: 11, offset: 584}, 184 exprs: []interface{}{ 185 &ruleRefExpr{ 186 pos: position{line: 31, col: 11, offset: 584}, 187 name: "ExprStart", 188 }, 189 &labeledExpr{ 190 pos: position{line: 31, col: 21, offset: 594}, 191 label: "s", 192 expr: &ruleRefExpr{ 193 pos: position{line: 31, col: 24, offset: 597}, 194 name: "SpecialKey", 195 }, 196 }, 197 &labeledExpr{ 198 pos: position{line: 31, col: 36, offset: 609}, 199 label: "t", 200 expr: &zeroOrOneExpr{ 201 pos: position{line: 31, col: 38, offset: 611}, 202 expr: &choiceExpr{ 203 pos: position{line: 31, col: 39, offset: 612}, 204 alternatives: []interface{}{ 205 &ruleRefExpr{ 206 pos: position{line: 31, col: 39, offset: 612}, 207 name: "On", 208 }, 209 &ruleRefExpr{ 210 pos: position{line: 31, col: 44, offset: 617}, 211 name: "Off", 212 }, 213 }, 214 }, 215 }, 216 }, 217 &ruleRefExpr{ 218 pos: position{line: 31, col: 50, offset: 623}, 219 name: "ExprEnd", 220 }, 221 }, 222 }, 223 }, 224 }, 225 { 226 name: "Number", 227 pos: position{line: 39, col: 1, offset: 810}, 228 expr: &actionExpr{ 229 pos: position{line: 39, col: 10, offset: 819}, 230 run: (*parser).callonNumber1, 231 expr: &seqExpr{ 232 pos: position{line: 39, col: 10, offset: 819}, 233 exprs: []interface{}{ 234 &zeroOrOneExpr{ 235 pos: position{line: 39, col: 10, offset: 819}, 236 expr: &litMatcher{ 237 pos: position{line: 39, col: 10, offset: 819}, 238 val: "-", 239 ignoreCase: false, 240 }, 241 }, 242 &ruleRefExpr{ 243 pos: position{line: 39, col: 15, offset: 824}, 244 name: "Integer", 245 }, 246 &zeroOrOneExpr{ 247 pos: position{line: 39, col: 23, offset: 832}, 248 expr: &seqExpr{ 249 pos: position{line: 39, col: 25, offset: 834}, 250 exprs: []interface{}{ 251 &litMatcher{ 252 pos: position{line: 39, col: 25, offset: 834}, 253 val: ".", 254 ignoreCase: false, 255 }, 256 &oneOrMoreExpr{ 257 pos: position{line: 39, col: 29, offset: 838}, 258 expr: &ruleRefExpr{ 259 pos: position{line: 39, col: 29, offset: 838}, 260 name: "Digit", 261 }, 262 }, 263 }, 264 }, 265 }, 266 }, 267 }, 268 }, 269 }, 270 { 271 name: "Integer", 272 pos: position{line: 43, col: 1, offset: 884}, 273 expr: &choiceExpr{ 274 pos: position{line: 43, col: 11, offset: 894}, 275 alternatives: []interface{}{ 276 &litMatcher{ 277 pos: position{line: 43, col: 11, offset: 894}, 278 val: "0", 279 ignoreCase: false, 280 }, 281 &actionExpr{ 282 pos: position{line: 43, col: 17, offset: 900}, 283 run: (*parser).callonInteger3, 284 expr: &seqExpr{ 285 pos: position{line: 43, col: 17, offset: 900}, 286 exprs: []interface{}{ 287 &ruleRefExpr{ 288 pos: position{line: 43, col: 17, offset: 900}, 289 name: "NonZeroDigit", 290 }, 291 &zeroOrMoreExpr{ 292 pos: position{line: 43, col: 30, offset: 913}, 293 expr: &ruleRefExpr{ 294 pos: position{line: 43, col: 30, offset: 913}, 295 name: "Digit", 296 }, 297 }, 298 }, 299 }, 300 }, 301 }, 302 }, 303 }, 304 { 305 name: "Duration", 306 pos: position{line: 47, col: 1, offset: 977}, 307 expr: &actionExpr{ 308 pos: position{line: 47, col: 12, offset: 988}, 309 run: (*parser).callonDuration1, 310 expr: &oneOrMoreExpr{ 311 pos: position{line: 47, col: 12, offset: 988}, 312 expr: &seqExpr{ 313 pos: position{line: 47, col: 14, offset: 990}, 314 exprs: []interface{}{ 315 &ruleRefExpr{ 316 pos: position{line: 47, col: 14, offset: 990}, 317 name: "Number", 318 }, 319 &ruleRefExpr{ 320 pos: position{line: 47, col: 21, offset: 997}, 321 name: "TimeUnit", 322 }, 323 }, 324 }, 325 }, 326 }, 327 }, 328 { 329 name: "On", 330 pos: position{line: 51, col: 1, offset: 1060}, 331 expr: &actionExpr{ 332 pos: position{line: 51, col: 6, offset: 1065}, 333 run: (*parser).callonOn1, 334 expr: &litMatcher{ 335 pos: position{line: 51, col: 6, offset: 1065}, 336 val: "on", 337 ignoreCase: true, 338 }, 339 }, 340 }, 341 { 342 name: "Off", 343 pos: position{line: 55, col: 1, offset: 1098}, 344 expr: &actionExpr{ 345 pos: position{line: 55, col: 7, offset: 1104}, 346 run: (*parser).callonOff1, 347 expr: &litMatcher{ 348 pos: position{line: 55, col: 7, offset: 1104}, 349 val: "off", 350 ignoreCase: true, 351 }, 352 }, 353 }, 354 { 355 name: "Literal", 356 pos: position{line: 59, col: 1, offset: 1139}, 357 expr: &actionExpr{ 358 pos: position{line: 59, col: 11, offset: 1149}, 359 run: (*parser).callonLiteral1, 360 expr: &anyMatcher{ 361 line: 59, col: 11, offset: 1149, 362 }, 363 }, 364 }, 365 { 366 name: "ExprEnd", 367 pos: position{line: 64, col: 1, offset: 1230}, 368 expr: &litMatcher{ 369 pos: position{line: 64, col: 11, offset: 1240}, 370 val: ">", 371 ignoreCase: false, 372 }, 373 }, 374 { 375 name: "ExprStart", 376 pos: position{line: 65, col: 1, offset: 1244}, 377 expr: &litMatcher{ 378 pos: position{line: 65, col: 13, offset: 1256}, 379 val: "<", 380 ignoreCase: false, 381 }, 382 }, 383 { 384 name: "SpecialKey", 385 pos: position{line: 66, col: 1, offset: 1260}, 386 expr: &choiceExpr{ 387 pos: position{line: 66, col: 14, offset: 1273}, 388 alternatives: []interface{}{ 389 &litMatcher{ 390 pos: position{line: 66, col: 14, offset: 1273}, 391 val: "bs", 392 ignoreCase: true, 393 }, 394 &litMatcher{ 395 pos: position{line: 66, col: 22, offset: 1281}, 396 val: "del", 397 ignoreCase: true, 398 }, 399 &litMatcher{ 400 pos: position{line: 66, col: 31, offset: 1290}, 401 val: "enter", 402 ignoreCase: true, 403 }, 404 &litMatcher{ 405 pos: position{line: 66, col: 42, offset: 1301}, 406 val: "esc", 407 ignoreCase: true, 408 }, 409 &litMatcher{ 410 pos: position{line: 66, col: 51, offset: 1310}, 411 val: "f10", 412 ignoreCase: true, 413 }, 414 &litMatcher{ 415 pos: position{line: 66, col: 60, offset: 1319}, 416 val: "f11", 417 ignoreCase: true, 418 }, 419 &litMatcher{ 420 pos: position{line: 66, col: 69, offset: 1328}, 421 val: "f12", 422 ignoreCase: true, 423 }, 424 &litMatcher{ 425 pos: position{line: 67, col: 11, offset: 1345}, 426 val: "f1", 427 ignoreCase: true, 428 }, 429 &litMatcher{ 430 pos: position{line: 67, col: 19, offset: 1353}, 431 val: "f2", 432 ignoreCase: true, 433 }, 434 &litMatcher{ 435 pos: position{line: 67, col: 27, offset: 1361}, 436 val: "f3", 437 ignoreCase: true, 438 }, 439 &litMatcher{ 440 pos: position{line: 67, col: 35, offset: 1369}, 441 val: "f4", 442 ignoreCase: true, 443 }, 444 &litMatcher{ 445 pos: position{line: 67, col: 43, offset: 1377}, 446 val: "f5", 447 ignoreCase: true, 448 }, 449 &litMatcher{ 450 pos: position{line: 67, col: 51, offset: 1385}, 451 val: "f6", 452 ignoreCase: true, 453 }, 454 &litMatcher{ 455 pos: position{line: 67, col: 59, offset: 1393}, 456 val: "f7", 457 ignoreCase: true, 458 }, 459 &litMatcher{ 460 pos: position{line: 67, col: 67, offset: 1401}, 461 val: "f8", 462 ignoreCase: true, 463 }, 464 &litMatcher{ 465 pos: position{line: 67, col: 75, offset: 1409}, 466 val: "f9", 467 ignoreCase: true, 468 }, 469 &litMatcher{ 470 pos: position{line: 68, col: 12, offset: 1426}, 471 val: "return", 472 ignoreCase: true, 473 }, 474 &litMatcher{ 475 pos: position{line: 68, col: 24, offset: 1438}, 476 val: "tab", 477 ignoreCase: true, 478 }, 479 &litMatcher{ 480 pos: position{line: 68, col: 33, offset: 1447}, 481 val: "up", 482 ignoreCase: true, 483 }, 484 &litMatcher{ 485 pos: position{line: 68, col: 41, offset: 1455}, 486 val: "down", 487 ignoreCase: true, 488 }, 489 &litMatcher{ 490 pos: position{line: 68, col: 51, offset: 1465}, 491 val: "spacebar", 492 ignoreCase: true, 493 }, 494 &litMatcher{ 495 pos: position{line: 68, col: 65, offset: 1479}, 496 val: "insert", 497 ignoreCase: true, 498 }, 499 &litMatcher{ 500 pos: position{line: 68, col: 77, offset: 1491}, 501 val: "home", 502 ignoreCase: true, 503 }, 504 &litMatcher{ 505 pos: position{line: 69, col: 11, offset: 1509}, 506 val: "end", 507 ignoreCase: true, 508 }, 509 &litMatcher{ 510 pos: position{line: 69, col: 20, offset: 1518}, 511 val: "pageup", 512 ignoreCase: true, 513 }, 514 &litMatcher{ 515 pos: position{line: 69, col: 32, offset: 1530}, 516 val: "pagedown", 517 ignoreCase: true, 518 }, 519 &litMatcher{ 520 pos: position{line: 69, col: 46, offset: 1544}, 521 val: "leftalt", 522 ignoreCase: true, 523 }, 524 &litMatcher{ 525 pos: position{line: 69, col: 59, offset: 1557}, 526 val: "leftctrl", 527 ignoreCase: true, 528 }, 529 &litMatcher{ 530 pos: position{line: 69, col: 73, offset: 1571}, 531 val: "leftshift", 532 ignoreCase: true, 533 }, 534 &litMatcher{ 535 pos: position{line: 70, col: 11, offset: 1594}, 536 val: "rightalt", 537 ignoreCase: true, 538 }, 539 &litMatcher{ 540 pos: position{line: 70, col: 25, offset: 1608}, 541 val: "rightctrl", 542 ignoreCase: true, 543 }, 544 &litMatcher{ 545 pos: position{line: 70, col: 40, offset: 1623}, 546 val: "rightshift", 547 ignoreCase: true, 548 }, 549 &litMatcher{ 550 pos: position{line: 70, col: 56, offset: 1639}, 551 val: "leftsuper", 552 ignoreCase: true, 553 }, 554 &litMatcher{ 555 pos: position{line: 70, col: 71, offset: 1654}, 556 val: "rightsuper", 557 ignoreCase: true, 558 }, 559 &litMatcher{ 560 pos: position{line: 71, col: 11, offset: 1678}, 561 val: "left", 562 ignoreCase: true, 563 }, 564 &litMatcher{ 565 pos: position{line: 71, col: 21, offset: 1688}, 566 val: "right", 567 ignoreCase: true, 568 }, 569 }, 570 }, 571 }, 572 { 573 name: "NonZeroDigit", 574 pos: position{line: 73, col: 1, offset: 1698}, 575 expr: &charClassMatcher{ 576 pos: position{line: 73, col: 16, offset: 1713}, 577 val: "[1-9]", 578 ranges: []rune{'1', '9'}, 579 ignoreCase: false, 580 inverted: false, 581 }, 582 }, 583 { 584 name: "Digit", 585 pos: position{line: 74, col: 1, offset: 1719}, 586 expr: &charClassMatcher{ 587 pos: position{line: 74, col: 9, offset: 1727}, 588 val: "[0-9]", 589 ranges: []rune{'0', '9'}, 590 ignoreCase: false, 591 inverted: false, 592 }, 593 }, 594 { 595 name: "TimeUnit", 596 pos: position{line: 75, col: 1, offset: 1733}, 597 expr: &choiceExpr{ 598 pos: position{line: 75, col: 13, offset: 1745}, 599 alternatives: []interface{}{ 600 &litMatcher{ 601 pos: position{line: 75, col: 13, offset: 1745}, 602 val: "ns", 603 ignoreCase: false, 604 }, 605 &litMatcher{ 606 pos: position{line: 75, col: 20, offset: 1752}, 607 val: "us", 608 ignoreCase: false, 609 }, 610 &litMatcher{ 611 pos: position{line: 75, col: 27, offset: 1759}, 612 val: "µs", 613 ignoreCase: false, 614 }, 615 &litMatcher{ 616 pos: position{line: 75, col: 34, offset: 1767}, 617 val: "ms", 618 ignoreCase: false, 619 }, 620 &litMatcher{ 621 pos: position{line: 75, col: 41, offset: 1774}, 622 val: "s", 623 ignoreCase: false, 624 }, 625 &litMatcher{ 626 pos: position{line: 75, col: 47, offset: 1780}, 627 val: "m", 628 ignoreCase: false, 629 }, 630 &litMatcher{ 631 pos: position{line: 75, col: 53, offset: 1786}, 632 val: "h", 633 ignoreCase: false, 634 }, 635 }, 636 }, 637 }, 638 { 639 name: "_", 640 displayName: "\"whitespace\"", 641 pos: position{line: 77, col: 1, offset: 1792}, 642 expr: &zeroOrMoreExpr{ 643 pos: position{line: 77, col: 19, offset: 1810}, 644 expr: &charClassMatcher{ 645 pos: position{line: 77, col: 19, offset: 1810}, 646 val: "[ \\n\\t\\r]", 647 chars: []rune{' ', '\n', '\t', '\r'}, 648 ignoreCase: false, 649 inverted: false, 650 }, 651 }, 652 }, 653 { 654 name: "EOF", 655 pos: position{line: 79, col: 1, offset: 1822}, 656 expr: ¬Expr{ 657 pos: position{line: 79, col: 8, offset: 1829}, 658 expr: &anyMatcher{ 659 line: 79, col: 9, offset: 1830, 660 }, 661 }, 662 }, 663 }, 664 } 665 666 func (c *current) onInput1(expr interface{}) (interface{}, error) { 667 return expr, nil 668 } 669 670 func (p *parser) callonInput1() (interface{}, error) { 671 stack := p.vstack[len(p.vstack)-1] 672 _ = stack 673 return p.cur.onInput1(stack["expr"]) 674 } 675 676 func (c *current) onExpr1(l interface{}) (interface{}, error) { 677 return l, nil 678 } 679 680 func (p *parser) callonExpr1() (interface{}, error) { 681 stack := p.vstack[len(p.vstack)-1] 682 _ = stack 683 return p.cur.onExpr1(stack["l"]) 684 } 685 686 func (c *current) onWait1(duration interface{}) (interface{}, error) { 687 var d time.Duration 688 switch t := duration.(type) { 689 case time.Duration: 690 d = t 691 case int64: 692 d = time.Duration(t) * time.Second 693 default: 694 d = time.Second 695 } 696 return &waitExpression{d}, nil 697 } 698 699 func (p *parser) callonWait1() (interface{}, error) { 700 stack := p.vstack[len(p.vstack)-1] 701 _ = stack 702 return p.cur.onWait1(stack["duration"]) 703 } 704 705 func (c *current) onCharToggle1(lit, t interface{}) (interface{}, error) { 706 return &literal{lit.(*literal).s, t.(KeyAction)}, nil 707 } 708 709 func (p *parser) callonCharToggle1() (interface{}, error) { 710 stack := p.vstack[len(p.vstack)-1] 711 _ = stack 712 return p.cur.onCharToggle1(stack["lit"], stack["t"]) 713 } 714 715 func (c *current) onSpecial1(s, t interface{}) (interface{}, error) { 716 l := strings.ToLower(string(s.([]byte))) 717 if t == nil { 718 return &specialExpression{l, KeyPress}, nil 719 } 720 return &specialExpression{l, t.(KeyAction)}, nil 721 } 722 723 func (p *parser) callonSpecial1() (interface{}, error) { 724 stack := p.vstack[len(p.vstack)-1] 725 _ = stack 726 return p.cur.onSpecial1(stack["s"], stack["t"]) 727 } 728 729 func (c *current) onNumber1() (interface{}, error) { 730 return string(c.text), nil 731 } 732 733 func (p *parser) callonNumber1() (interface{}, error) { 734 stack := p.vstack[len(p.vstack)-1] 735 _ = stack 736 return p.cur.onNumber1() 737 } 738 739 func (c *current) onInteger3() (interface{}, error) { 740 return strconv.ParseInt(string(c.text), 10, 64) 741 } 742 743 func (p *parser) callonInteger3() (interface{}, error) { 744 stack := p.vstack[len(p.vstack)-1] 745 _ = stack 746 return p.cur.onInteger3() 747 } 748 749 func (c *current) onDuration1() (interface{}, error) { 750 return time.ParseDuration(string(c.text)) 751 } 752 753 func (p *parser) callonDuration1() (interface{}, error) { 754 stack := p.vstack[len(p.vstack)-1] 755 _ = stack 756 return p.cur.onDuration1() 757 } 758 759 func (c *current) onOn1() (interface{}, error) { 760 return KeyOn, nil 761 } 762 763 func (p *parser) callonOn1() (interface{}, error) { 764 stack := p.vstack[len(p.vstack)-1] 765 _ = stack 766 return p.cur.onOn1() 767 } 768 769 func (c *current) onOff1() (interface{}, error) { 770 return KeyOff, nil 771 } 772 773 func (p *parser) callonOff1() (interface{}, error) { 774 stack := p.vstack[len(p.vstack)-1] 775 _ = stack 776 return p.cur.onOff1() 777 } 778 779 func (c *current) onLiteral1() (interface{}, error) { 780 r, _ := utf8.DecodeRune(c.text) 781 return &literal{r, KeyPress}, nil 782 } 783 784 func (p *parser) callonLiteral1() (interface{}, error) { 785 stack := p.vstack[len(p.vstack)-1] 786 _ = stack 787 return p.cur.onLiteral1() 788 } 789 790 var ( 791 // errNoRule is returned when the grammar to parse has no rule. 792 errNoRule = errors.New("grammar has no rule") 793 794 // errInvalidEntrypoint is returned when the specified entrypoint rule 795 // does not exit. 796 errInvalidEntrypoint = errors.New("invalid entrypoint") 797 798 // errInvalidEncoding is returned when the source is not properly 799 // utf8-encoded. 800 errInvalidEncoding = errors.New("invalid encoding") 801 802 // errMaxExprCnt is used to signal that the maximum number of 803 // expressions have been parsed. 804 errMaxExprCnt = errors.New("max number of expresssions parsed") 805 ) 806 807 // Option is a function that can set an option on the parser. It returns 808 // the previous setting as an Option. 809 type Option func(*parser) Option 810 811 // MaxExpressions creates an Option to stop parsing after the provided 812 // number of expressions have been parsed, if the value is 0 then the parser will 813 // parse for as many steps as needed (possibly an infinite number). 814 // 815 // The default for maxExprCnt is 0. 816 func MaxExpressions(maxExprCnt uint64) Option { 817 return func(p *parser) Option { 818 oldMaxExprCnt := p.maxExprCnt 819 p.maxExprCnt = maxExprCnt 820 return MaxExpressions(oldMaxExprCnt) 821 } 822 } 823 824 // Entrypoint creates an Option to set the rule name to use as entrypoint. 825 // The rule name must have been specified in the -alternate-entrypoints 826 // if generating the parser with the -optimize-grammar flag, otherwise 827 // it may have been optimized out. Passing an empty string sets the 828 // entrypoint to the first rule in the grammar. 829 // 830 // The default is to start parsing at the first rule in the grammar. 831 func Entrypoint(ruleName string) Option { 832 return func(p *parser) Option { 833 oldEntrypoint := p.entrypoint 834 p.entrypoint = ruleName 835 if ruleName == "" { 836 p.entrypoint = g.rules[0].name 837 } 838 return Entrypoint(oldEntrypoint) 839 } 840 } 841 842 // Statistics adds a user provided Stats struct to the parser to allow 843 // the user to process the results after the parsing has finished. 844 // Also the key for the "no match" counter is set. 845 // 846 // Example usage: 847 // 848 // input := "input" 849 // stats := Stats{} 850 // _, err := Parse("input-file", []byte(input), Statistics(&stats, "no match")) 851 // if err != nil { 852 // log.Panicln(err) 853 // } 854 // b, err := json.MarshalIndent(stats.ChoiceAltCnt, "", " ") 855 // if err != nil { 856 // log.Panicln(err) 857 // } 858 // fmt.Println(string(b)) 859 // 860 func Statistics(stats *Stats, choiceNoMatch string) Option { 861 return func(p *parser) Option { 862 oldStats := p.Stats 863 p.Stats = stats 864 oldChoiceNoMatch := p.choiceNoMatch 865 p.choiceNoMatch = choiceNoMatch 866 if p.Stats.ChoiceAltCnt == nil { 867 p.Stats.ChoiceAltCnt = make(map[string]map[string]int) 868 } 869 return Statistics(oldStats, oldChoiceNoMatch) 870 } 871 } 872 873 // Debug creates an Option to set the debug flag to b. When set to true, 874 // debugging information is printed to stdout while parsing. 875 // 876 // The default is false. 877 func Debug(b bool) Option { 878 return func(p *parser) Option { 879 old := p.debug 880 p.debug = b 881 return Debug(old) 882 } 883 } 884 885 // Memoize creates an Option to set the memoize flag to b. When set to true, 886 // the parser will cache all results so each expression is evaluated only 887 // once. This guarantees linear parsing time even for pathological cases, 888 // at the expense of more memory and slower times for typical cases. 889 // 890 // The default is false. 891 func Memoize(b bool) Option { 892 return func(p *parser) Option { 893 old := p.memoize 894 p.memoize = b 895 return Memoize(old) 896 } 897 } 898 899 // AllowInvalidUTF8 creates an Option to allow invalid UTF-8 bytes. 900 // Every invalid UTF-8 byte is treated as a utf8.RuneError (U+FFFD) 901 // by character class matchers and is matched by the any matcher. 902 // The returned matched value, c.text and c.offset are NOT affected. 903 // 904 // The default is false. 905 func AllowInvalidUTF8(b bool) Option { 906 return func(p *parser) Option { 907 old := p.allowInvalidUTF8 908 p.allowInvalidUTF8 = b 909 return AllowInvalidUTF8(old) 910 } 911 } 912 913 // Recover creates an Option to set the recover flag to b. When set to 914 // true, this causes the parser to recover from panics and convert it 915 // to an error. Setting it to false can be useful while debugging to 916 // access the full stack trace. 917 // 918 // The default is true. 919 func Recover(b bool) Option { 920 return func(p *parser) Option { 921 old := p.recover 922 p.recover = b 923 return Recover(old) 924 } 925 } 926 927 // GlobalStore creates an Option to set a key to a certain value in 928 // the globalStore. 929 func GlobalStore(key string, value interface{}) Option { 930 return func(p *parser) Option { 931 old := p.cur.globalStore[key] 932 p.cur.globalStore[key] = value 933 return GlobalStore(key, old) 934 } 935 } 936 937 // InitState creates an Option to set a key to a certain value in 938 // the global "state" store. 939 func InitState(key string, value interface{}) Option { 940 return func(p *parser) Option { 941 old := p.cur.state[key] 942 p.cur.state[key] = value 943 return InitState(key, old) 944 } 945 } 946 947 // ParseFile parses the file identified by filename. 948 func ParseFile(filename string, opts ...Option) (i interface{}, err error) { 949 f, err := os.Open(filename) 950 if err != nil { 951 return nil, err 952 } 953 defer func() { 954 if closeErr := f.Close(); closeErr != nil { 955 err = closeErr 956 } 957 }() 958 return ParseReader(filename, f, opts...) 959 } 960 961 // ParseReader parses the data from r using filename as information in the 962 // error messages. 963 func ParseReader(filename string, r io.Reader, opts ...Option) (interface{}, error) { 964 b, err := ioutil.ReadAll(r) 965 if err != nil { 966 return nil, err 967 } 968 969 return Parse(filename, b, opts...) 970 } 971 972 // Parse parses the data from b using filename as information in the 973 // error messages. 974 func Parse(filename string, b []byte, opts ...Option) (interface{}, error) { 975 return newParser(filename, b, opts...).parse(g) 976 } 977 978 // position records a position in the text. 979 type position struct { 980 line, col, offset int 981 } 982 983 func (p position) String() string { 984 return fmt.Sprintf("%d:%d [%d]", p.line, p.col, p.offset) 985 } 986 987 // savepoint stores all state required to go back to this point in the 988 // parser. 989 type savepoint struct { 990 position 991 rn rune 992 w int 993 } 994 995 type current struct { 996 pos position // start position of the match 997 text []byte // raw text of the match 998 999 // state is a store for arbitrary key,value pairs that the user wants to be 1000 // tied to the backtracking of the parser. 1001 // This is always rolled back if a parsing rule fails. 1002 state storeDict 1003 1004 // globalStore is a general store for the user to store arbitrary key-value 1005 // pairs that they need to manage and that they do not want tied to the 1006 // backtracking of the parser. This is only modified by the user and never 1007 // rolled back by the parser. It is always up to the user to keep this in a 1008 // consistent state. 1009 globalStore storeDict 1010 } 1011 1012 type storeDict map[string]interface{} 1013 1014 // the AST types... 1015 1016 type grammar struct { 1017 pos position 1018 rules []*rule 1019 } 1020 1021 type rule struct { 1022 pos position 1023 name string 1024 displayName string 1025 expr interface{} 1026 } 1027 1028 type choiceExpr struct { 1029 pos position 1030 alternatives []interface{} 1031 } 1032 1033 type actionExpr struct { 1034 pos position 1035 expr interface{} 1036 run func(*parser) (interface{}, error) 1037 } 1038 1039 type recoveryExpr struct { 1040 pos position 1041 expr interface{} 1042 recoverExpr interface{} 1043 failureLabel []string 1044 } 1045 1046 type seqExpr struct { 1047 pos position 1048 exprs []interface{} 1049 } 1050 1051 type throwExpr struct { 1052 pos position 1053 label string 1054 } 1055 1056 type labeledExpr struct { 1057 pos position 1058 label string 1059 expr interface{} 1060 } 1061 1062 type expr struct { 1063 pos position 1064 expr interface{} 1065 } 1066 1067 type andExpr expr 1068 type notExpr expr 1069 type zeroOrOneExpr expr 1070 type zeroOrMoreExpr expr 1071 type oneOrMoreExpr expr 1072 1073 type ruleRefExpr struct { 1074 pos position 1075 name string 1076 } 1077 1078 type stateCodeExpr struct { 1079 pos position 1080 run func(*parser) error 1081 } 1082 1083 type andCodeExpr struct { 1084 pos position 1085 run func(*parser) (bool, error) 1086 } 1087 1088 type notCodeExpr struct { 1089 pos position 1090 run func(*parser) (bool, error) 1091 } 1092 1093 type litMatcher struct { 1094 pos position 1095 val string 1096 ignoreCase bool 1097 } 1098 1099 type charClassMatcher struct { 1100 pos position 1101 val string 1102 basicLatinChars [128]bool 1103 chars []rune 1104 ranges []rune 1105 classes []*unicode.RangeTable 1106 ignoreCase bool 1107 inverted bool 1108 } 1109 1110 type anyMatcher position 1111 1112 // errList cumulates the errors found by the parser. 1113 type errList []error 1114 1115 func (e *errList) add(err error) { 1116 *e = append(*e, err) 1117 } 1118 1119 func (e errList) err() error { 1120 if len(e) == 0 { 1121 return nil 1122 } 1123 e.dedupe() 1124 return e 1125 } 1126 1127 func (e *errList) dedupe() { 1128 var cleaned []error 1129 set := make(map[string]bool) 1130 for _, err := range *e { 1131 if msg := err.Error(); !set[msg] { 1132 set[msg] = true 1133 cleaned = append(cleaned, err) 1134 } 1135 } 1136 *e = cleaned 1137 } 1138 1139 func (e errList) Error() string { 1140 switch len(e) { 1141 case 0: 1142 return "" 1143 case 1: 1144 return e[0].Error() 1145 default: 1146 var buf bytes.Buffer 1147 1148 for i, err := range e { 1149 if i > 0 { 1150 buf.WriteRune('\n') 1151 } 1152 buf.WriteString(err.Error()) 1153 } 1154 return buf.String() 1155 } 1156 } 1157 1158 // parserError wraps an error with a prefix indicating the rule in which 1159 // the error occurred. The original error is stored in the Inner field. 1160 type parserError struct { 1161 Inner error 1162 pos position 1163 prefix string 1164 expected []string 1165 } 1166 1167 // Error returns the error message. 1168 func (p *parserError) Error() string { 1169 return p.prefix + ": " + p.Inner.Error() 1170 } 1171 1172 // newParser creates a parser with the specified input source and options. 1173 func newParser(filename string, b []byte, opts ...Option) *parser { 1174 stats := Stats{ 1175 ChoiceAltCnt: make(map[string]map[string]int), 1176 } 1177 1178 p := &parser{ 1179 filename: filename, 1180 errs: new(errList), 1181 data: b, 1182 pt: savepoint{position: position{line: 1}}, 1183 recover: true, 1184 cur: current{ 1185 state: make(storeDict), 1186 globalStore: make(storeDict), 1187 }, 1188 maxFailPos: position{col: 1, line: 1}, 1189 maxFailExpected: make([]string, 0, 20), 1190 Stats: &stats, 1191 // start rule is rule [0] unless an alternate entrypoint is specified 1192 entrypoint: g.rules[0].name, 1193 emptyState: make(storeDict), 1194 } 1195 p.setOptions(opts) 1196 1197 if p.maxExprCnt == 0 { 1198 p.maxExprCnt = math.MaxUint64 1199 } 1200 1201 return p 1202 } 1203 1204 // setOptions applies the options to the parser. 1205 func (p *parser) setOptions(opts []Option) { 1206 for _, opt := range opts { 1207 opt(p) 1208 } 1209 } 1210 1211 type resultTuple struct { 1212 v interface{} 1213 b bool 1214 end savepoint 1215 } 1216 1217 const choiceNoMatch = -1 1218 1219 // Stats stores some statistics, gathered during parsing 1220 type Stats struct { 1221 // ExprCnt counts the number of expressions processed during parsing 1222 // This value is compared to the maximum number of expressions allowed 1223 // (set by the MaxExpressions option). 1224 ExprCnt uint64 1225 1226 // ChoiceAltCnt is used to count for each ordered choice expression, 1227 // which alternative is used how may times. 1228 // These numbers allow to optimize the order of the ordered choice expression 1229 // to increase the performance of the parser 1230 // 1231 // The outer key of ChoiceAltCnt is composed of the name of the rule as well 1232 // as the line and the column of the ordered choice. 1233 // The inner key of ChoiceAltCnt is the number (one-based) of the matching alternative. 1234 // For each alternative the number of matches are counted. If an ordered choice does not 1235 // match, a special counter is incremented. The name of this counter is set with 1236 // the parser option Statistics. 1237 // For an alternative to be included in ChoiceAltCnt, it has to match at least once. 1238 ChoiceAltCnt map[string]map[string]int 1239 } 1240 1241 type parser struct { 1242 filename string 1243 pt savepoint 1244 cur current 1245 1246 data []byte 1247 errs *errList 1248 1249 depth int 1250 recover bool 1251 debug bool 1252 1253 memoize bool 1254 // memoization table for the packrat algorithm: 1255 // map[offset in source] map[expression or rule] {value, match} 1256 memo map[int]map[interface{}]resultTuple 1257 1258 // rules table, maps the rule identifier to the rule node 1259 rules map[string]*rule 1260 // variables stack, map of label to value 1261 vstack []map[string]interface{} 1262 // rule stack, allows identification of the current rule in errors 1263 rstack []*rule 1264 1265 // parse fail 1266 maxFailPos position 1267 maxFailExpected []string 1268 maxFailInvertExpected bool 1269 1270 // max number of expressions to be parsed 1271 maxExprCnt uint64 1272 // entrypoint for the parser 1273 entrypoint string 1274 1275 allowInvalidUTF8 bool 1276 1277 *Stats 1278 1279 choiceNoMatch string 1280 // recovery expression stack, keeps track of the currently available recovery expression, these are traversed in reverse 1281 recoveryStack []map[string]interface{} 1282 1283 // emptyState contains an empty storeDict, which is used to optimize cloneState if global "state" store is not used. 1284 emptyState storeDict 1285 } 1286 1287 // push a variable set on the vstack. 1288 func (p *parser) pushV() { 1289 if cap(p.vstack) == len(p.vstack) { 1290 // create new empty slot in the stack 1291 p.vstack = append(p.vstack, nil) 1292 } else { 1293 // slice to 1 more 1294 p.vstack = p.vstack[:len(p.vstack)+1] 1295 } 1296 1297 // get the last args set 1298 m := p.vstack[len(p.vstack)-1] 1299 if m != nil && len(m) == 0 { 1300 // empty map, all good 1301 return 1302 } 1303 1304 m = make(map[string]interface{}) 1305 p.vstack[len(p.vstack)-1] = m 1306 } 1307 1308 // pop a variable set from the vstack. 1309 func (p *parser) popV() { 1310 // if the map is not empty, clear it 1311 m := p.vstack[len(p.vstack)-1] 1312 if len(m) > 0 { 1313 // GC that map 1314 p.vstack[len(p.vstack)-1] = nil 1315 } 1316 p.vstack = p.vstack[:len(p.vstack)-1] 1317 } 1318 1319 // push a recovery expression with its labels to the recoveryStack 1320 func (p *parser) pushRecovery(labels []string, expr interface{}) { 1321 if cap(p.recoveryStack) == len(p.recoveryStack) { 1322 // create new empty slot in the stack 1323 p.recoveryStack = append(p.recoveryStack, nil) 1324 } else { 1325 // slice to 1 more 1326 p.recoveryStack = p.recoveryStack[:len(p.recoveryStack)+1] 1327 } 1328 1329 m := make(map[string]interface{}, len(labels)) 1330 for _, fl := range labels { 1331 m[fl] = expr 1332 } 1333 p.recoveryStack[len(p.recoveryStack)-1] = m 1334 } 1335 1336 // pop a recovery expression from the recoveryStack 1337 func (p *parser) popRecovery() { 1338 // GC that map 1339 p.recoveryStack[len(p.recoveryStack)-1] = nil 1340 1341 p.recoveryStack = p.recoveryStack[:len(p.recoveryStack)-1] 1342 } 1343 1344 func (p *parser) print(prefix, s string) string { 1345 if !p.debug { 1346 return s 1347 } 1348 1349 fmt.Printf("%s %d:%d:%d: %s [%#U]\n", 1350 prefix, p.pt.line, p.pt.col, p.pt.offset, s, p.pt.rn) 1351 return s 1352 } 1353 1354 func (p *parser) in(s string) string { 1355 p.depth++ 1356 return p.print(strings.Repeat(" ", p.depth)+">", s) 1357 } 1358 1359 func (p *parser) out(s string) string { 1360 p.depth-- 1361 return p.print(strings.Repeat(" ", p.depth)+"<", s) 1362 } 1363 1364 func (p *parser) addErr(err error) { 1365 p.addErrAt(err, p.pt.position, []string{}) 1366 } 1367 1368 func (p *parser) addErrAt(err error, pos position, expected []string) { 1369 var buf bytes.Buffer 1370 if p.filename != "" { 1371 buf.WriteString(p.filename) 1372 } 1373 if buf.Len() > 0 { 1374 buf.WriteString(":") 1375 } 1376 buf.WriteString(fmt.Sprintf("%d:%d (%d)", pos.line, pos.col, pos.offset)) 1377 if len(p.rstack) > 0 { 1378 if buf.Len() > 0 { 1379 buf.WriteString(": ") 1380 } 1381 rule := p.rstack[len(p.rstack)-1] 1382 if rule.displayName != "" { 1383 buf.WriteString("rule " + rule.displayName) 1384 } else { 1385 buf.WriteString("rule " + rule.name) 1386 } 1387 } 1388 pe := &parserError{Inner: err, pos: pos, prefix: buf.String(), expected: expected} 1389 p.errs.add(pe) 1390 } 1391 1392 func (p *parser) failAt(fail bool, pos position, want string) { 1393 // process fail if parsing fails and not inverted or parsing succeeds and invert is set 1394 if fail == p.maxFailInvertExpected { 1395 if pos.offset < p.maxFailPos.offset { 1396 return 1397 } 1398 1399 if pos.offset > p.maxFailPos.offset { 1400 p.maxFailPos = pos 1401 p.maxFailExpected = p.maxFailExpected[:0] 1402 } 1403 1404 if p.maxFailInvertExpected { 1405 want = "!" + want 1406 } 1407 p.maxFailExpected = append(p.maxFailExpected, want) 1408 } 1409 } 1410 1411 // read advances the parser to the next rune. 1412 func (p *parser) read() { 1413 p.pt.offset += p.pt.w 1414 rn, n := utf8.DecodeRune(p.data[p.pt.offset:]) 1415 p.pt.rn = rn 1416 p.pt.w = n 1417 p.pt.col++ 1418 if rn == '\n' { 1419 p.pt.line++ 1420 p.pt.col = 0 1421 } 1422 1423 if rn == utf8.RuneError && n == 1 { // see utf8.DecodeRune 1424 if !p.allowInvalidUTF8 { 1425 p.addErr(errInvalidEncoding) 1426 } 1427 } 1428 } 1429 1430 // restore parser position to the savepoint pt. 1431 func (p *parser) restore(pt savepoint) { 1432 if p.debug { 1433 defer p.out(p.in("restore")) 1434 } 1435 if pt.offset == p.pt.offset { 1436 return 1437 } 1438 p.pt = pt 1439 } 1440 1441 // Cloner is implemented by any value that has a Clone method, which returns a 1442 // copy of the value. This is mainly used for types which are not passed by 1443 // value (e.g map, slice, chan) or structs that contain such types. 1444 // 1445 // This is used in conjunction with the global state feature to create proper 1446 // copies of the state to allow the parser to properly restore the state in 1447 // the case of backtracking. 1448 type Cloner interface { 1449 Clone() interface{} 1450 } 1451 1452 // clone and return parser current state. 1453 func (p *parser) cloneState() storeDict { 1454 if p.debug { 1455 defer p.out(p.in("cloneState")) 1456 } 1457 1458 if len(p.cur.state) == 0 { 1459 if len(p.emptyState) > 0 { 1460 p.emptyState = make(storeDict) 1461 } 1462 return p.emptyState 1463 } 1464 1465 state := make(storeDict, len(p.cur.state)) 1466 for k, v := range p.cur.state { 1467 if c, ok := v.(Cloner); ok { 1468 state[k] = c.Clone() 1469 } else { 1470 state[k] = v 1471 } 1472 } 1473 return state 1474 } 1475 1476 // restore parser current state to the state storeDict. 1477 // every restoreState should applied only one time for every cloned state 1478 func (p *parser) restoreState(state storeDict) { 1479 if p.debug { 1480 defer p.out(p.in("restoreState")) 1481 } 1482 p.cur.state = state 1483 } 1484 1485 // get the slice of bytes from the savepoint start to the current position. 1486 func (p *parser) sliceFrom(start savepoint) []byte { 1487 return p.data[start.position.offset:p.pt.position.offset] 1488 } 1489 1490 func (p *parser) getMemoized(node interface{}) (resultTuple, bool) { 1491 if len(p.memo) == 0 { 1492 return resultTuple{}, false 1493 } 1494 m := p.memo[p.pt.offset] 1495 if len(m) == 0 { 1496 return resultTuple{}, false 1497 } 1498 res, ok := m[node] 1499 return res, ok 1500 } 1501 1502 func (p *parser) setMemoized(pt savepoint, node interface{}, tuple resultTuple) { 1503 if p.memo == nil { 1504 p.memo = make(map[int]map[interface{}]resultTuple) 1505 } 1506 m := p.memo[pt.offset] 1507 if m == nil { 1508 m = make(map[interface{}]resultTuple) 1509 p.memo[pt.offset] = m 1510 } 1511 m[node] = tuple 1512 } 1513 1514 func (p *parser) buildRulesTable(g *grammar) { 1515 p.rules = make(map[string]*rule, len(g.rules)) 1516 for _, r := range g.rules { 1517 p.rules[r.name] = r 1518 } 1519 } 1520 1521 func (p *parser) parse(g *grammar) (val interface{}, err error) { 1522 if len(g.rules) == 0 { 1523 p.addErr(errNoRule) 1524 return nil, p.errs.err() 1525 } 1526 1527 // TODO : not super critical but this could be generated 1528 p.buildRulesTable(g) 1529 1530 if p.recover { 1531 // panic can be used in action code to stop parsing immediately 1532 // and return the panic as an error. 1533 defer func() { 1534 if e := recover(); e != nil { 1535 if p.debug { 1536 defer p.out(p.in("panic handler")) 1537 } 1538 val = nil 1539 switch e := e.(type) { 1540 case error: 1541 p.addErr(e) 1542 default: 1543 p.addErr(fmt.Errorf("%v", e)) 1544 } 1545 err = p.errs.err() 1546 } 1547 }() 1548 } 1549 1550 startRule, ok := p.rules[p.entrypoint] 1551 if !ok { 1552 p.addErr(errInvalidEntrypoint) 1553 return nil, p.errs.err() 1554 } 1555 1556 p.read() // advance to first rune 1557 val, ok = p.parseRule(startRule) 1558 if !ok { 1559 if len(*p.errs) == 0 { 1560 // If parsing fails, but no errors have been recorded, the expected values 1561 // for the farthest parser position are returned as error. 1562 maxFailExpectedMap := make(map[string]struct{}, len(p.maxFailExpected)) 1563 for _, v := range p.maxFailExpected { 1564 maxFailExpectedMap[v] = struct{}{} 1565 } 1566 expected := make([]string, 0, len(maxFailExpectedMap)) 1567 eof := false 1568 if _, ok := maxFailExpectedMap["!."]; ok { 1569 delete(maxFailExpectedMap, "!.") 1570 eof = true 1571 } 1572 for k := range maxFailExpectedMap { 1573 expected = append(expected, k) 1574 } 1575 sort.Strings(expected) 1576 if eof { 1577 expected = append(expected, "EOF") 1578 } 1579 p.addErrAt(errors.New("no match found, expected: "+listJoin(expected, ", ", "or")), p.maxFailPos, expected) 1580 } 1581 1582 return nil, p.errs.err() 1583 } 1584 return val, p.errs.err() 1585 } 1586 1587 func listJoin(list []string, sep string, lastSep string) string { 1588 switch len(list) { 1589 case 0: 1590 return "" 1591 case 1: 1592 return list[0] 1593 default: 1594 return fmt.Sprintf("%s %s %s", strings.Join(list[:len(list)-1], sep), lastSep, list[len(list)-1]) 1595 } 1596 } 1597 1598 func (p *parser) parseRule(rule *rule) (interface{}, bool) { 1599 if p.debug { 1600 defer p.out(p.in("parseRule " + rule.name)) 1601 } 1602 1603 if p.memoize { 1604 res, ok := p.getMemoized(rule) 1605 if ok { 1606 p.restore(res.end) 1607 return res.v, res.b 1608 } 1609 } 1610 1611 start := p.pt 1612 p.rstack = append(p.rstack, rule) 1613 p.pushV() 1614 val, ok := p.parseExpr(rule.expr) 1615 p.popV() 1616 p.rstack = p.rstack[:len(p.rstack)-1] 1617 if ok && p.debug { 1618 p.print(strings.Repeat(" ", p.depth)+"MATCH", string(p.sliceFrom(start))) 1619 } 1620 1621 if p.memoize { 1622 p.setMemoized(start, rule, resultTuple{val, ok, p.pt}) 1623 } 1624 return val, ok 1625 } 1626 1627 func (p *parser) parseExpr(expr interface{}) (interface{}, bool) { 1628 var pt savepoint 1629 1630 if p.memoize { 1631 res, ok := p.getMemoized(expr) 1632 if ok { 1633 p.restore(res.end) 1634 return res.v, res.b 1635 } 1636 pt = p.pt 1637 } 1638 1639 p.ExprCnt++ 1640 if p.ExprCnt > p.maxExprCnt { 1641 panic(errMaxExprCnt) 1642 } 1643 1644 var val interface{} 1645 var ok bool 1646 switch expr := expr.(type) { 1647 case *actionExpr: 1648 val, ok = p.parseActionExpr(expr) 1649 case *andCodeExpr: 1650 val, ok = p.parseAndCodeExpr(expr) 1651 case *andExpr: 1652 val, ok = p.parseAndExpr(expr) 1653 case *anyMatcher: 1654 val, ok = p.parseAnyMatcher(expr) 1655 case *charClassMatcher: 1656 val, ok = p.parseCharClassMatcher(expr) 1657 case *choiceExpr: 1658 val, ok = p.parseChoiceExpr(expr) 1659 case *labeledExpr: 1660 val, ok = p.parseLabeledExpr(expr) 1661 case *litMatcher: 1662 val, ok = p.parseLitMatcher(expr) 1663 case *notCodeExpr: 1664 val, ok = p.parseNotCodeExpr(expr) 1665 case *notExpr: 1666 val, ok = p.parseNotExpr(expr) 1667 case *oneOrMoreExpr: 1668 val, ok = p.parseOneOrMoreExpr(expr) 1669 case *recoveryExpr: 1670 val, ok = p.parseRecoveryExpr(expr) 1671 case *ruleRefExpr: 1672 val, ok = p.parseRuleRefExpr(expr) 1673 case *seqExpr: 1674 val, ok = p.parseSeqExpr(expr) 1675 case *stateCodeExpr: 1676 val, ok = p.parseStateCodeExpr(expr) 1677 case *throwExpr: 1678 val, ok = p.parseThrowExpr(expr) 1679 case *zeroOrMoreExpr: 1680 val, ok = p.parseZeroOrMoreExpr(expr) 1681 case *zeroOrOneExpr: 1682 val, ok = p.parseZeroOrOneExpr(expr) 1683 default: 1684 panic(fmt.Sprintf("unknown expression type %T", expr)) 1685 } 1686 if p.memoize { 1687 p.setMemoized(pt, expr, resultTuple{val, ok, p.pt}) 1688 } 1689 return val, ok 1690 } 1691 1692 func (p *parser) parseActionExpr(act *actionExpr) (interface{}, bool) { 1693 if p.debug { 1694 defer p.out(p.in("parseActionExpr")) 1695 } 1696 1697 start := p.pt 1698 val, ok := p.parseExpr(act.expr) 1699 if ok { 1700 p.cur.pos = start.position 1701 p.cur.text = p.sliceFrom(start) 1702 state := p.cloneState() 1703 actVal, err := act.run(p) 1704 if err != nil { 1705 p.addErrAt(err, start.position, []string{}) 1706 } 1707 p.restoreState(state) 1708 1709 val = actVal 1710 } 1711 if ok && p.debug { 1712 p.print(strings.Repeat(" ", p.depth)+"MATCH", string(p.sliceFrom(start))) 1713 } 1714 return val, ok 1715 } 1716 1717 func (p *parser) parseAndCodeExpr(and *andCodeExpr) (interface{}, bool) { 1718 if p.debug { 1719 defer p.out(p.in("parseAndCodeExpr")) 1720 } 1721 1722 state := p.cloneState() 1723 1724 ok, err := and.run(p) 1725 if err != nil { 1726 p.addErr(err) 1727 } 1728 p.restoreState(state) 1729 1730 return nil, ok 1731 } 1732 1733 func (p *parser) parseAndExpr(and *andExpr) (interface{}, bool) { 1734 if p.debug { 1735 defer p.out(p.in("parseAndExpr")) 1736 } 1737 1738 pt := p.pt 1739 state := p.cloneState() 1740 p.pushV() 1741 _, ok := p.parseExpr(and.expr) 1742 p.popV() 1743 p.restoreState(state) 1744 p.restore(pt) 1745 1746 return nil, ok 1747 } 1748 1749 func (p *parser) parseAnyMatcher(any *anyMatcher) (interface{}, bool) { 1750 if p.debug { 1751 defer p.out(p.in("parseAnyMatcher")) 1752 } 1753 1754 if p.pt.rn == utf8.RuneError && p.pt.w == 0 { 1755 // EOF - see utf8.DecodeRune 1756 p.failAt(false, p.pt.position, ".") 1757 return nil, false 1758 } 1759 start := p.pt 1760 p.read() 1761 p.failAt(true, start.position, ".") 1762 return p.sliceFrom(start), true 1763 } 1764 1765 func (p *parser) parseCharClassMatcher(chr *charClassMatcher) (interface{}, bool) { 1766 if p.debug { 1767 defer p.out(p.in("parseCharClassMatcher")) 1768 } 1769 1770 cur := p.pt.rn 1771 start := p.pt 1772 1773 // can't match EOF 1774 if cur == utf8.RuneError && p.pt.w == 0 { // see utf8.DecodeRune 1775 p.failAt(false, start.position, chr.val) 1776 return nil, false 1777 } 1778 1779 if chr.ignoreCase { 1780 cur = unicode.ToLower(cur) 1781 } 1782 1783 // try to match in the list of available chars 1784 for _, rn := range chr.chars { 1785 if rn == cur { 1786 if chr.inverted { 1787 p.failAt(false, start.position, chr.val) 1788 return nil, false 1789 } 1790 p.read() 1791 p.failAt(true, start.position, chr.val) 1792 return p.sliceFrom(start), true 1793 } 1794 } 1795 1796 // try to match in the list of ranges 1797 for i := 0; i < len(chr.ranges); i += 2 { 1798 if cur >= chr.ranges[i] && cur <= chr.ranges[i+1] { 1799 if chr.inverted { 1800 p.failAt(false, start.position, chr.val) 1801 return nil, false 1802 } 1803 p.read() 1804 p.failAt(true, start.position, chr.val) 1805 return p.sliceFrom(start), true 1806 } 1807 } 1808 1809 // try to match in the list of Unicode classes 1810 for _, cl := range chr.classes { 1811 if unicode.Is(cl, cur) { 1812 if chr.inverted { 1813 p.failAt(false, start.position, chr.val) 1814 return nil, false 1815 } 1816 p.read() 1817 p.failAt(true, start.position, chr.val) 1818 return p.sliceFrom(start), true 1819 } 1820 } 1821 1822 if chr.inverted { 1823 p.read() 1824 p.failAt(true, start.position, chr.val) 1825 return p.sliceFrom(start), true 1826 } 1827 p.failAt(false, start.position, chr.val) 1828 return nil, false 1829 } 1830 1831 func (p *parser) incChoiceAltCnt(ch *choiceExpr, altI int) { 1832 choiceIdent := fmt.Sprintf("%s %d:%d", p.rstack[len(p.rstack)-1].name, ch.pos.line, ch.pos.col) 1833 m := p.ChoiceAltCnt[choiceIdent] 1834 if m == nil { 1835 m = make(map[string]int) 1836 p.ChoiceAltCnt[choiceIdent] = m 1837 } 1838 // We increment altI by 1, so the keys do not start at 0 1839 alt := strconv.Itoa(altI + 1) 1840 if altI == choiceNoMatch { 1841 alt = p.choiceNoMatch 1842 } 1843 m[alt]++ 1844 } 1845 1846 func (p *parser) parseChoiceExpr(ch *choiceExpr) (interface{}, bool) { 1847 if p.debug { 1848 defer p.out(p.in("parseChoiceExpr")) 1849 } 1850 1851 for altI, alt := range ch.alternatives { 1852 // dummy assignment to prevent compile error if optimized 1853 _ = altI 1854 1855 state := p.cloneState() 1856 1857 p.pushV() 1858 val, ok := p.parseExpr(alt) 1859 p.popV() 1860 if ok { 1861 p.incChoiceAltCnt(ch, altI) 1862 return val, ok 1863 } 1864 p.restoreState(state) 1865 } 1866 p.incChoiceAltCnt(ch, choiceNoMatch) 1867 return nil, false 1868 } 1869 1870 func (p *parser) parseLabeledExpr(lab *labeledExpr) (interface{}, bool) { 1871 if p.debug { 1872 defer p.out(p.in("parseLabeledExpr")) 1873 } 1874 1875 p.pushV() 1876 val, ok := p.parseExpr(lab.expr) 1877 p.popV() 1878 if ok && lab.label != "" { 1879 m := p.vstack[len(p.vstack)-1] 1880 m[lab.label] = val 1881 } 1882 return val, ok 1883 } 1884 1885 func (p *parser) parseLitMatcher(lit *litMatcher) (interface{}, bool) { 1886 if p.debug { 1887 defer p.out(p.in("parseLitMatcher")) 1888 } 1889 1890 ignoreCase := "" 1891 if lit.ignoreCase { 1892 ignoreCase = "i" 1893 } 1894 val := fmt.Sprintf("%q%s", lit.val, ignoreCase) 1895 start := p.pt 1896 for _, want := range lit.val { 1897 cur := p.pt.rn 1898 if lit.ignoreCase { 1899 cur = unicode.ToLower(cur) 1900 } 1901 if cur != want { 1902 p.failAt(false, start.position, val) 1903 p.restore(start) 1904 return nil, false 1905 } 1906 p.read() 1907 } 1908 p.failAt(true, start.position, val) 1909 return p.sliceFrom(start), true 1910 } 1911 1912 func (p *parser) parseNotCodeExpr(not *notCodeExpr) (interface{}, bool) { 1913 if p.debug { 1914 defer p.out(p.in("parseNotCodeExpr")) 1915 } 1916 1917 state := p.cloneState() 1918 1919 ok, err := not.run(p) 1920 if err != nil { 1921 p.addErr(err) 1922 } 1923 p.restoreState(state) 1924 1925 return nil, !ok 1926 } 1927 1928 func (p *parser) parseNotExpr(not *notExpr) (interface{}, bool) { 1929 if p.debug { 1930 defer p.out(p.in("parseNotExpr")) 1931 } 1932 1933 pt := p.pt 1934 state := p.cloneState() 1935 p.pushV() 1936 p.maxFailInvertExpected = !p.maxFailInvertExpected 1937 _, ok := p.parseExpr(not.expr) 1938 p.maxFailInvertExpected = !p.maxFailInvertExpected 1939 p.popV() 1940 p.restoreState(state) 1941 p.restore(pt) 1942 1943 return nil, !ok 1944 } 1945 1946 func (p *parser) parseOneOrMoreExpr(expr *oneOrMoreExpr) (interface{}, bool) { 1947 if p.debug { 1948 defer p.out(p.in("parseOneOrMoreExpr")) 1949 } 1950 1951 var vals []interface{} 1952 1953 for { 1954 p.pushV() 1955 val, ok := p.parseExpr(expr.expr) 1956 p.popV() 1957 if !ok { 1958 if len(vals) == 0 { 1959 // did not match once, no match 1960 return nil, false 1961 } 1962 return vals, true 1963 } 1964 vals = append(vals, val) 1965 } 1966 } 1967 1968 func (p *parser) parseRecoveryExpr(recover *recoveryExpr) (interface{}, bool) { 1969 if p.debug { 1970 defer p.out(p.in("parseRecoveryExpr (" + strings.Join(recover.failureLabel, ",") + ")")) 1971 } 1972 1973 p.pushRecovery(recover.failureLabel, recover.recoverExpr) 1974 val, ok := p.parseExpr(recover.expr) 1975 p.popRecovery() 1976 1977 return val, ok 1978 } 1979 1980 func (p *parser) parseRuleRefExpr(ref *ruleRefExpr) (interface{}, bool) { 1981 if p.debug { 1982 defer p.out(p.in("parseRuleRefExpr " + ref.name)) 1983 } 1984 1985 if ref.name == "" { 1986 panic(fmt.Sprintf("%s: invalid rule: missing name", ref.pos)) 1987 } 1988 1989 rule := p.rules[ref.name] 1990 if rule == nil { 1991 p.addErr(fmt.Errorf("undefined rule: %s", ref.name)) 1992 return nil, false 1993 } 1994 return p.parseRule(rule) 1995 } 1996 1997 func (p *parser) parseSeqExpr(seq *seqExpr) (interface{}, bool) { 1998 if p.debug { 1999 defer p.out(p.in("parseSeqExpr")) 2000 } 2001 2002 vals := make([]interface{}, 0, len(seq.exprs)) 2003 2004 pt := p.pt 2005 state := p.cloneState() 2006 for _, expr := range seq.exprs { 2007 val, ok := p.parseExpr(expr) 2008 if !ok { 2009 p.restoreState(state) 2010 p.restore(pt) 2011 return nil, false 2012 } 2013 vals = append(vals, val) 2014 } 2015 return vals, true 2016 } 2017 2018 func (p *parser) parseStateCodeExpr(state *stateCodeExpr) (interface{}, bool) { 2019 if p.debug { 2020 defer p.out(p.in("parseStateCodeExpr")) 2021 } 2022 2023 err := state.run(p) 2024 if err != nil { 2025 p.addErr(err) 2026 } 2027 return nil, true 2028 } 2029 2030 func (p *parser) parseThrowExpr(expr *throwExpr) (interface{}, bool) { 2031 if p.debug { 2032 defer p.out(p.in("parseThrowExpr")) 2033 } 2034 2035 for i := len(p.recoveryStack) - 1; i >= 0; i-- { 2036 if recoverExpr, ok := p.recoveryStack[i][expr.label]; ok { 2037 if val, ok := p.parseExpr(recoverExpr); ok { 2038 return val, ok 2039 } 2040 } 2041 } 2042 2043 return nil, false 2044 } 2045 2046 func (p *parser) parseZeroOrMoreExpr(expr *zeroOrMoreExpr) (interface{}, bool) { 2047 if p.debug { 2048 defer p.out(p.in("parseZeroOrMoreExpr")) 2049 } 2050 2051 var vals []interface{} 2052 2053 for { 2054 p.pushV() 2055 val, ok := p.parseExpr(expr.expr) 2056 p.popV() 2057 if !ok { 2058 return vals, true 2059 } 2060 vals = append(vals, val) 2061 } 2062 } 2063 2064 func (p *parser) parseZeroOrOneExpr(expr *zeroOrOneExpr) (interface{}, bool) { 2065 if p.debug { 2066 defer p.out(p.in("parseZeroOrOneExpr")) 2067 } 2068 2069 p.pushV() 2070 val, _ := p.parseExpr(expr.expr) 2071 p.popV() 2072 // whether it matched or not, consider it a match 2073 return val, true 2074 }