class Arborist::Matcher

Included Modules

Defined in:

matcher.cr

Constructors

Instance Method Summary

Instance methods inherited from module Arborist::DSL

alt(strings : Array(String)) : Expr
alt(alts : Array(String | Expr)) : Expr
alt(strings : Set(String)) : Expr
alt(*alternatives : String | Expr) : Expr
alt
, apply(rule_name : String) : Expr apply, choice(alternatives : Array(Expr)) : Expr
choice(*alternatives) : Expr
choice
, dot : Expr dot, label(label : String, expr : Expr) : Expr label, neg(expr : Expr) : Expr neg, opt(expr : Expr) : Expr opt, plus(expr : Expr) : Expr plus, pos(expr : Expr) : Expr pos, range(chars : Range(Char, Char)) : Expr range, seq(exprs : Array(Expr)) : Expr
seq(*exprs) : Expr
seq
, star(expr : Expr) : Expr star, term(string : String) : Expr term

Constructor Detail

def self.new(rules : Hash(String, Arborist::Rule) = {} of String => Rule) #

[View source]

Instance Method Detail

def add_rule(rule_name, expr : Expr) #

[View source]
def add_rule_while_matching_is_in_progress_if_necessary(rule_name : String, expr : Expr) #

[View source]
def add_skip_rule_if_necessary #

[View source]
def apply_calls_in_call_stack : Array(ApplyCall) #

[View source]
def apply_calls_that_resulted_in_left_recursion : Array(ApplyCall) #

[View source]
def apply_skip_rule(expr : Expr) #

The application of the skip rule is internally represented as a parameterized rule, such that the skip rule is specialized for each expression that will follow. This approach made it possible implement the skip rule as: parameterized_skip_rule[following_expr] <- !following_expr skip* Eventually I concluded that implementing the skip rule as !{following expression} skip* was not what I wanted right now, but this establishes the pattern of implementing parameterized rules, and I may decide to go back to implementing the skip rule as !{following expression} skip*.


[View source]
def consume(c : Char) : Bool #

[View source]
def consume(count : Int32) : String | Nil #

consumes a string of length count returns nil if unable to consume count characters


[View source]
def eof? #

[View source]
def expr_call_tree_controller : ExprCallTreeController #

[View source]
def expr_call_tree_controller=(expr_call_tree_controller : ExprCallTreeController) #

[View source]
def expr_failures : Hash(Int32, Set(MatchFailure)) #

[View source]
def expr_failures=(expr_failures : Hash(Int32, Set(MatchFailure))) #

[View source]
def get_rule(rule_name) : Rule #

[View source]
def get_seed(rule : Rule, pos : Int32) #

[View source]
def get_seed?(rule : Rule, pos : Int32) : ParseTree | Nil #

[View source]
def growing : Hash(Int32, Hash(Rule, ParseTree | Nil)) #

[View source]
def growing=(growing : Hash(Int32, Hash(Rule, ParseTree | Nil))) #

[View source]
def has_memoized_result?(rule : Rule) : Bool #

[View source]
def input : CharArray #

[View source]
def log_match_failure(pos : Int32, expr : Expr) : Nil #

[View source]
def lookup_most_recent_rule_application_in_call_stack(rule) : ApplyCall | Nil #

returns the deepest/most-recent application of rule in the rule application stack


[View source]
def lookup_oldest_rule_application_that_resulted_in_left_recursion(rule) : ApplyCall | Nil #

returns the leftmost/earliest/oldest/shallowest application of rule in the rule application stack that resulted in left recursion


[View source]
def lookup_rule_application_in_call_stack(rule, pos) : ApplyCall | Nil #

returns the deepest/most-recent application of rule at position #pos in the rule application stack


[View source]
def mark_most_recent_applications_unsafe_to_memoize(oldest_application) #

this method marks all ApplyCall calls on the call stack occurring more recent than oldest_application as unsafe to memoize


[View source]
def mark_parent_seed_growths_as_resulting_in_deeper_seed_growth(child_seed_growth_rule_application) #

[View source]
def match(input : String, start_rule_name = (@rules.first_key? || "start")) : ApplyTree | Nil #

returns nil if the grammar rules don't match the full input string


[View source]
def memoize_result(pos, next_pos, rule, parse_tree : ParseTree | Nil) : MemoizedParseTree #

[View source]
def mode : Symbol #

[View source]
def mode=(mode : Symbol) #

[View source]
def most_recent_rule_application : ApplyCall | Nil #

[View source]
def ohm_mode? #

if we're operating in Ohm mode, then the syntactic rule semantics apply. See https://github.com/harc/ohm/blob/master/doc/syntax-reference.md#syntactic-lexical for more information. From https://github.com/harc/ohm/blob/master/doc/syntax-reference.md#syntactic-lexical:

Syntactic vs. Lexical Rules

A syntactic rule is a rule whose name begins with an uppercase letter, and lexical rule is one whose name begins with a lowercase letter. The difference between lexical and syntactic rules is that syntactic rules implicitly skip whitespace characters.

For the purposes of a syntactic rule, a "whitespace character" is anything that matches its enclosing grammar's "space" rule. The default implementation of "space" matches ' ', '\t', '\n', '\r', and any other character that is considered whitespace in the ES5 spec.


[View source]
def pop_off_of_call_stack(the_top_of_stack_expr_call_successfully_parsed : Bool) : ExprCall #

[View source]
def pos : Int32 #

[View source]
def pos=(pos : Int32) #

[View source]
def prepare_for_matching #

per https://tratt.net/laurie/research/pubs/html/tratt__direct_left_recursive_parsing_expression_grammars/: growing is the data structure at the heart of the algorithm. A programming language-like type for it would be Map<Rule,Map<Int,Result>>. Since we statically know all the rules for a PEG, growing is statically initialised with an empty map for each rule at the beginning of the algorithm (line 1).

So, we want to initialize the growing map just prior to using it, since that will be the only point that we know for sure that all of the rules have been added to the matcher.


[View source]
def print_match_failure_error #

[View source]
def push_onto_call_stack(expr_application : ExprCall) #

[View source]
def python_mode? #

[View source]
def remove_seed(rule : Rule, pos : Int32) #

[View source]
def remove_seeds_between(start_pos, end_pos) #

remove all seeds of any rule in the range [start_pos, end_pos]


[View source]
def remove_seeds_to_the_right_of(start_pos) #

remove all seeds of any rule in the range (start_pos, ]


[View source]
def remove_seeds_used_to_grow_larger_seed(rule, larger_seed : ParseTree) #

this removes all "descendant" seeds that were used to grow a larger seed, <larger_seed>, that encompases all the descendant seeds


[View source]
def rule_in_recursion_call_stack_state : Array(Tuple(Int32, Rule)) #

returns an array of pairs of the form {pos, rule}, each summarizing an ApplyCall


[View source]
def rules : Hash(String, Rule) #

[View source]
def seed_defined?(rule : Rule, pos : Int32) #

[View source]
def set_mode(desired_mode) #

[View source]
def set_seed(rule : Rule, pos : Int32, seed_parse_tree : ParseTree | Nil) : ParseTree | Nil #

todo: decide whether this should return the previous seed value


[View source]
def simple_mode? #

[View source]
def skip_whitespace_if_in_syntactic_context(expr : Expr) #

[View source]
def use_memoized_result(rule_name) : ParseTree | Nil #

[View source]