///|
priv struct RuleRegistry {
mut rules : Array[RuleEntry]
mut disabled : Array[RuleName]
mut overrides : Array[RuleEntry]
mut next_order : Int
}
///|
priv struct PreparedRulePlan {
registry : RuleRegistry
block_rules : Array[RuleEntry]
block_continue_rules : Array[RuleEntry]
inline_parse_rules : Array[RuleEntry]
inline_fallback_rules : Array[RuleEntry]
inline_ascii_rule_buckets : Array[Array[RuleEntry]]
inline_rule_buckets : Array[InlineRuleBucket]
inline_mode : InlineParseMode
inline_trigger_chars : String
inline_has_triggers_outside_commonmark : Bool
core_rules : Array[RuleEntry]
}
///|
priv struct InlineRuleBucket {
trigger : Int
rules : Array[RuleEntry]
}
///|
fn RuleRegistry::RuleRegistry() -> RuleRegistry {
{ rules: [], disabled: [], overrides: [], next_order: 0 }
}
///|
fn PreparedRulePlan::PreparedRulePlan(
registry : RuleRegistry,
) -> PreparedRulePlan {
let block_rules = registry.block_rules()
let block_continue_rules = registry.block_continue_rules()
let inline_parse_rules = registry.inline_parse_rules()
let core_rules = registry.core_rules()
let inline_trigger_chars = inline_trigger_chars(inline_parse_rules)
let inline_fallback_rules = inline_fallback_rules(inline_parse_rules)
{
registry,
block_rules,
block_continue_rules,
inline_parse_rules,
inline_fallback_rules,
inline_ascii_rule_buckets: inline_ascii_rule_buckets(
inline_parse_rules, inline_trigger_chars, inline_fallback_rules,
),
inline_rule_buckets: inline_non_ascii_rule_buckets(
inline_parse_rules, inline_trigger_chars,
),
inline_mode: inline_parse_mode(inline_parse_rules),
inline_trigger_chars,
inline_has_triggers_outside_commonmark: inline_has_triggers_other_than(
inline_trigger_chars,
commonmark_inline_trigger_chars(),
),
core_rules,
}
}
///|
fn RuleRegistry::register(
self : RuleRegistry,
rule : RuleEntry,
) -> RuleRegistry {
match self.override_for(rule.name) {
Some(replace) => self.override_registered(replace)
None => self.register_raw(rule)
}
}
///|
fn RuleRegistry::register_raw(
self : RuleRegistry,
rule : RuleEntry,
) -> RuleRegistry {
let r = {
name: rule.name,
chain: rule.chain,
before: copy_rule_names(rule.before),
after: copy_rule_names(rule.after),
priority: rule.priority,
order: self.next_order,
triggers: rule.triggers,
block: rule.block,
inline: rule.inline,
core: rule.core,
}
self.next_order = self.next_order + 1
self.rules.push(r)
sort_rules(self.rules)
self
}
///|
fn RuleRegistry::use_rule(self : RuleRegistry, rule : Rule) -> RuleRegistry {
for op in rule.ops {
ignore(self.apply_rule_op(op))
}
self
}
///|
fn RuleRegistry::apply_rule_op(
self : RuleRegistry,
op : RuleOp,
) -> RuleRegistry {
match op {
RegisterRule(rule) => self.register(rule)
DisableRule(name) => self.disable(name)
EnableRule(name) => self.enable(name)
ReplaceRule(rule) => self.replace(rule)
}
}
///|
fn RuleRegistry::enable(self : RuleRegistry, name : RuleName) -> RuleRegistry {
let next : Array[RuleName] = []
for disabled in self.disabled {
if disabled != name {
next.push(disabled)
}
}
self.disabled = next
self
}
///|
fn RuleRegistry::disable(self : RuleRegistry, name : RuleName) -> RuleRegistry {
if !array_contains_string(self.disabled, name) {
self.disabled.push(name)
}
self
}
///|
fn RuleRegistry::replace(self : RuleRegistry, rule : RuleEntry) -> RuleRegistry {
self.remember_override(rule)
self.override_registered(rule)
}
///|
fn RuleRegistry::remember_override(
self : RuleRegistry,
rule : RuleEntry,
) -> Unit {
let next : Array[RuleEntry] = []
for old in self.overrides {
if old.name != rule.name {
next.push(old)
}
}
next.push(rule)
self.overrides = next
}
///|
fn RuleRegistry::override_for(
self : RuleRegistry,
name : RuleName,
) -> RuleEntry? {
for rule in self.overrides {
if rule.name == name {
return Some(rule)
}
}
None
}
///|
fn RuleRegistry::override_registered(
self : RuleRegistry,
rule : RuleEntry,
) -> RuleRegistry {
let next : Array[RuleEntry] = []
for old in self.rules {
if old.name != rule.name {
next.push(old)
}
}
self.rules = next
self.register_raw(rule)
}
///|
fn RuleRegistry::block_rules(self : RuleRegistry) -> Array[RuleEntry] {
self.rules_for(BlockStart)
}
///|
fn RuleRegistry::block_continue_rules(self : RuleRegistry) -> Array[RuleEntry] {
self.rules_for(BlockContinue)
}
///|
fn RuleRegistry::inline_rules(self : RuleRegistry) -> Array[RuleEntry] {
self.rules_for(Inline)
}
///|
fn RuleRegistry::delimiter_rules(self : RuleRegistry) -> Array[RuleEntry] {
self.rules_for(Delimiter)
}
///|
fn RuleRegistry::core_rules(self : RuleRegistry) -> Array[RuleEntry] {
self.rules_for(Core)
}
///|
fn RuleRegistry::inline_parse_rules(self : RuleRegistry) -> Array[RuleEntry] {
let rules = self.delimiter_rules()
for rule in self.inline_rules() {
rules.push(rule)
}
rules
}
///|
fn inline_trigger_chars(rules : Array[RuleEntry]) -> String {
let out = StringBuilder::new()
let seen : Array[Int] = []
for rule in rules {
for i in 0.. Array[RuleEntry] {
let selected : Array[RuleEntry] = []
for rule in rules {
if rule.triggers == "" {
selected.push(rule)
}
}
selected
}
///|
fn inline_ascii_rule_buckets(
rules : Array[RuleEntry],
triggers : String,
fallback : Array[RuleEntry],
) -> Array[Array[RuleEntry]] {
let buckets : Array[Array[RuleEntry]] = []
for _ in 0..<128 {
buckets.push(fallback)
}
for i in 0..= 0 && trigger < buckets.length() {
buckets[trigger] = inline_rules_for_trigger(rules, trigger)
}
}
buckets
}
///|
fn inline_non_ascii_rule_buckets(
rules : Array[RuleEntry],
triggers : String,
) -> Array[InlineRuleBucket] {
let buckets : Array[InlineRuleBucket] = []
for i in 0..= 128 {
buckets.push({ trigger, rules: inline_rules_for_trigger(rules, trigger) })
}
}
buckets
}
///|
fn inline_rules_for_trigger(
rules : Array[RuleEntry],
trigger : Int,
) -> Array[RuleEntry] {
let selected : Array[RuleEntry] = []
for rule in rules {
if rule.triggers == "" || contains_char(rule.triggers, trigger) {
selected.push(rule)
}
}
selected
}
///|
fn PreparedRulePlan::inline_rules_for(
self : PreparedRulePlan,
trigger : Int,
) -> Array[RuleEntry] {
if trigger >= 0 && trigger < self.inline_ascii_rule_buckets.length() {
return self.inline_ascii_rule_buckets[trigger]
}
for bucket in self.inline_rule_buckets {
if bucket.trigger == trigger {
return bucket.rules
}
}
self.inline_fallback_rules
}
///|
fn inline_parse_mode(_rules : Array[RuleEntry]) -> InlineParseMode {
CustomInlinePipeline
}
///|
fn inline_has_triggers_other_than(triggers : String, ignored : String) -> Bool {
for i in 0.. String {
" ![<&`*_\\\n"
}
///|
fn RuleRegistry::rules_for(
self : RuleRegistry,
chain : RuleChain,
) -> Array[RuleEntry] {
let selected : Array[RuleEntry] = []
for rule in self.rules {
if rule.chain == chain && !array_contains_string(self.disabled, rule.name) {
selected.push(rule)
}
}
selected
}
///|
fn sort_rules(rules : Array[RuleEntry]) -> Unit {
let n = rules.length()
for i in 1.. 0 && rule_less(current, rules[j - 1]) {
rules[j] = rules[j - 1]
j = j - 1
}
rules[j] = current
}
apply_rule_edges(rules)
}
///|
fn apply_rule_edges(rules : Array[RuleEntry]) -> Unit {
let n = rules.length()
for _ in 0..= 0 && i > j {
move_rule(rules, i, j)
}
}
for name in rule.after {
let j = find_rule_index(rules, name, rule.chain)
if j >= 0 && i < j {
move_rule(rules, i, j)
}
}
}
}
}
///|
fn rule_less(left : RuleEntry, right : RuleEntry) -> Bool {
if left.priority != right.priority {
left.priority > right.priority
} else {
left.order < right.order
}
}
///|
fn find_rule_index(
rules : Array[RuleEntry],
name : RuleName,
chain : RuleChain,
) -> Int {
for i in 0.. Unit {
let rule = rules[from]
if from < to {
for i in from..=..(to + 1) {
rules[i] = rules[i - 1]
}
}
rules[to] = rule
}
///|
fn array_contains_string(items : Array[RuleName], needle : RuleName) -> Bool {
for item in items {
if item == needle {
return true
}
}
false
}
///|
fn array_contains_int(items : Array[Int], needle : Int) -> Bool {
for item in items {
if item == needle {
return true
}
}
false
}
///|
fn copy_rule_names(names : Array[RuleName]) -> Array[RuleName] {
let copied : Array[RuleName] = []
for name in names {
copied.push(name)
}
copied
}
///|
fn copy_rule_entry(rule : RuleEntry) -> RuleEntry {
{
name: rule.name,
chain: rule.chain,
before: copy_rule_names(rule.before),
after: copy_rule_names(rule.after),
priority: rule.priority,
order: rule.order,
triggers: rule.triggers,
block: rule.block,
inline: rule.inline,
core: rule.core,
}
}
///|
fn copy_rule_op(op : RuleOp) -> RuleOp {
match op {
RegisterRule(rule) => RegisterRule(copy_rule_entry(rule))
DisableRule(name) => DisableRule(name)
EnableRule(name) => EnableRule(name)
ReplaceRule(rule) => ReplaceRule(copy_rule_entry(rule))
}
}
///|
fn copy_rule_ops(ops : Array[RuleOp]) -> Array[RuleOp] {
let copied : Array[RuleOp] = []
for op in ops {
copied.push(copy_rule_op(op))
}
copied
}