** (Advanced) ** Models a PEG Rule.** ** Rules are commonly created by using methods from the `Rules` mixin, but may be parsed from string patterns.** ** `Rule` *may* sub-classed to create your own custom rules. @Jsabstractclass Rule {** Creates a rule by parsing the given pattern:** ** syntax: fantom ** Rule.fromPattern("[abc] / [xyz]")** ** See `Peg.parseRule`staticnew parseRule(Str pattern){ PegGrammar().parseRule(pattern)}** The name of this rule definition.** ** name <- foobar foobar** ** Only rules with names (or labels) appear in debug output and the output tree, unless explicitly disabled.** ** Should be a legal Fantom identifier (think variable names!).virtual Str? name {// internal set because only "Grammar definitions" should have names// rules have labels, definitions have names.// ideally we'd have a separate class for thisinternal set {// allow names to be programmatically re-setif(it != null)if(!it.chars.first.isAlpha || it.chars.any { !it.isAlphaNum && it != '_' && it != '-'})throw ArgErr("Name must be a valid Fantom identifier: $it") &name = it}}** A label for this rule.** ** someRule <- label:foobar foobar** ** Note the same rule definition may have multiple / different labels when used in different parts of PEG grammar. ** ** Only rules with labels (or names) appear in debug output and the output tree, unless explicitly disabled.** ** Should be a legal Fantom identifier (think variable names!).virtual Str? label { set {// allow labels to be programmatically re-setif(it != null)if(!it.chars.first.isAlpha || it.chars.any { !it.isAlphaNum && it != '_' && it != '-'})throw ArgErr("Label must be a valid Fantom identifier: $it") &label = it}}** Disable debugging of this rule if it gets too noisy.virtual Bool debug := true** Not all rules are useful in the parsed AST. virtual Bool useInResult := true** Override to implement Rule logic. @NoDocabstract Bool doProcess(RuleCtx ctx)** Returns the PEG expression for this rule (with any label definition). Example:** ** label:[a-zA-Z0-9] Str expression(){ _labelDis + _expression}** Returns the PEG definition for this rule. Example:** ** alphaNum <- [a-zA-Z0-9] Str definition(){if(name == null)return expression ex := nameif(!useInResult) ex = "-" + exif(!debug) ex = ex + "-"return"${ex} <- ${expression}"}** A helpful builder method for setting the label.** ** someRule <- label:foobar foobar** ** Note the same rule definition may have multiple / different labels when used in different parts of PEG grammar. ** ** Only rules with labels (or names) appear in debug output and the output tree.** ** Should be a legal Fantom identifier (think variable names!). This withLabel(Str? label){this.label = labelreturnthis}** A helpful builder method for turning debug off.** ** In PEG grammar, rules are excluded from debug by add a hyphen suffix to the declaration.** ** noDebugRule- = foobar foobar This debugOff(){this.debug = falsereturnthis}** A helpful builder method for removing this rule from tree results.** ** In PEG grammar, rules are excluded from results by add a hyphen prefix to the declaration.** ** -excludedRule = foobar foobar This excludeFromResults(){this.useInResult = falsereturnthis}** Matches this rule against the given string.** ** See `Peg.match` Match? match(Str str){ Peg(str, this).match} @NoDocvirtual Str typeName(){// if converting doProcess() to processFn then THIS method will need to be converted to another field name := typeof.name.decapitalizereturn name.endsWith("Rule") ? name[0..<-4] : name} @Operator @NoDocvirtual This add(Rule rule){throw Err("${typeof.qname} does not support add()")}** Returns the PEG expression for this rule. Example:** ** [a-zA-Z0-9] @NoDocabstract Str _expression() @NoDocinternal Str _dis(){ dis := name == null && (thisis SequenceRule || thisis FirstOfRule) ? "(" + _expression + ")" : (name ?: _expression)return _labelDis + dis} @NoDocinternal Str _labelDis(){ label == null ? "" : label + ":"} @NoDocoverride Str toStr(){ definition }}