Validate checks for any errors in the rules and issues warnings, returns true if valid (no err) and false if invalid (errs)
(ps *State)
| 514 | // Validate checks for any errors in the rules and issues warnings, |
| 515 | // returns true if valid (no err) and false if invalid (errs) |
| 516 | func (pr *Rule) Validate(ps *State) bool { |
| 517 | valid := true |
| 518 | |
| 519 | // do this here so everything else is compiled |
| 520 | if len(pr.Rules) == 0 && pr.FirstTokenMap { |
| 521 | pr.CompileTokMap(ps) |
| 522 | } |
| 523 | |
| 524 | if len(pr.Rules) == 0 && !pr.HasChildren() && !tree.IsRoot(pr) { |
| 525 | ps.Error(lexer.PosZero, "Validate: rule has no rules and no children", pr) |
| 526 | valid = false |
| 527 | } |
| 528 | if !pr.tokenMatchGroup && len(pr.Rules) > 0 && pr.HasChildren() { |
| 529 | ps.Error(lexer.PosZero, "Validate: rule has both rules and children -- should be either-or", pr) |
| 530 | valid = false |
| 531 | } |
| 532 | if pr.reverse { |
| 533 | if len(pr.Rules) != 3 { |
| 534 | ps.Error(lexer.PosZero, "Validate: a Reverse (-) rule must have 3 children -- for binary operator expressions only", pr) |
| 535 | valid = false |
| 536 | } else { |
| 537 | if !pr.Rules[1].IsToken() { |
| 538 | ps.Error(lexer.PosZero, "Validate: a Reverse (-) rule must have a token to be recognized in the middle of two rules -- for binary operator expressions only", pr) |
| 539 | } |
| 540 | } |
| 541 | } |
| 542 | |
| 543 | if len(pr.Rules) > 0 { |
| 544 | if pr.Rules[0].IsRule() && (pr.Rules[0].Rule == pr || pr.ParentLevel(pr.Rules[0].Rule) >= 0) { // left recursive |
| 545 | if pr.Rules[0].Match { |
| 546 | ps.Error(lexer.PosZero, fmt.Sprintf("Validate: rule refers to itself recursively in first sub-rule: %v and that sub-rule is marked as a Match -- this is infinite recursion and is not allowed! Must use distinctive tokens in rule to match this rule, and then left-recursive elements will be filled in when the rule runs, but they cannot be used for matching rule.", pr.Rules[0].Rule.Name), pr) |
| 547 | valid = false |
| 548 | } |
| 549 | ntok := 0 |
| 550 | for _, rr := range pr.Rules { |
| 551 | if rr.IsToken() { |
| 552 | ntok++ |
| 553 | } |
| 554 | } |
| 555 | if ntok == 0 { |
| 556 | ps.Error(lexer.PosZero, fmt.Sprintf("Validate: rule refers to itself recursively in first sub-rule: %v, and does not have any tokens in the rule -- MUST promote tokens to this rule to disambiguate match, otherwise will just do infinite recursion!", pr.Rules[0].Rule.Name), pr) |
| 557 | valid = false |
| 558 | } |
| 559 | } |
| 560 | } |
| 561 | |
| 562 | // now we iterate over our kids |
| 563 | for _, kpri := range pr.Children { |
| 564 | kpr := kpri.(*Rule) |
| 565 | if !kpr.Validate(ps) { |
| 566 | valid = false |
| 567 | } |
| 568 | } |
| 569 | return valid |
| 570 | } |
| 571 | |
| 572 | // StartParse is called on the root of the parse rule tree to start the parsing process |
| 573 | func (pr *Rule) StartParse(ps *State) *Rule { |
nothing calls this directly
no test coverage detected