/usr/lib/ruby/vendor_ruby/temple/mixins/grammar_dsl.rb is in ruby-temple 0.6.7-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 | module Temple
module Mixins
# @api private
module GrammarDSL
class Rule
def initialize(grammar)
@grammar = grammar
end
def |(rule)
Or.new(@grammar, self, rule)
end
def copy_to(grammar)
copy = dup.instance_eval { @grammar = grammar; self }
copy.after_copy(self) if copy.respond_to?(:after_copy)
copy
end
end
class Or < Rule
def initialize(grammar, *children)
super(grammar)
@children = children.map {|rule| @grammar.Rule(rule) }
end
def <<(rule)
@children << @grammar.Rule(rule)
self
end
alias | <<
def match(exp, unmatched)
tmp = []
@children.any? {|rule| rule.match(exp, tmp) } || (unmatched.concat(tmp) && false)
end
def after_copy(source)
@children = @children.map {|child| child.copy_to(@grammar) }
end
end
class Root < Or
def initialize(grammar, name)
super(grammar)
@name = name.to_sym
end
def match(exp, unmatched)
success = super
unmatched << [@name, exp] unless success
success
end
def match?(exp)
match(exp, [])
end
def validate!(exp)
unmatched = []
unless match(exp, unmatched)
require 'pp'
entry = unmatched.first
unmatched.reverse_each do |u|
entry = u if u.flatten.size < entry.flatten.size
end
raise(InvalidExpression, PP.pp(entry.last, "#{@grammar}::#{entry.first} did not match\n"))
end
end
def copy_to(grammar)
grammar.const_defined?(@name) ? grammar.const_get(@name) : super
end
def after_copy(source)
@grammar.const_set(@name, self)
super
end
end
class Element < Or
def initialize(grammar, rule)
super(grammar)
@rule = grammar.Rule(rule)
end
def match(exp, unmatched)
return false unless Array === exp && !exp.empty?
head, *tail = exp
@rule.match(head, unmatched) && super(tail, unmatched)
end
def after_copy(source)
@children = @children.map do |child|
child == source ? self : child.copy_to(@grammar)
end
@rule = @rule.copy_to(@grammar)
end
end
class Value < Rule
def initialize(grammar, value)
super(grammar)
@value = value
end
def match(exp, unmatched)
@value === exp
end
end
def extended(mod)
mod.extend GrammarDSL
constants.each do |name|
const_get(name).copy_to(mod) if Rule === const_get(name)
end
end
def match?(exp)
const_get(:Expression).match?(exp)
end
def validate!(exp)
const_get(:Expression).validate!(exp)
end
alias === match?
alias =~ match?
def Value(value)
Value.new(self, value)
end
def Rule(rule)
case rule
when Rule
rule
when Symbol, Class, true, false, nil
Value(rule)
when Array
start = Or.new(self)
curr = [start]
rule.each do |elem|
if elem =~ /^(.*)(\*|\?|\+)$/
elem = Element.new(self, const_get($1))
curr.each {|c| c << elem }
elem << elem if $2 != '?'
curr = $2 == '+' ? [elem] : (curr << elem)
else
elem = Element.new(self, elem)
curr.each {|c| c << elem }
curr = [elem]
end
end
elem = Value([])
curr.each {|c| c << elem }
start
else
raise ArgumentError, "Invalid grammar rule '#{rule.inspect}'"
end
end
def const_missing(name)
const_set(name, Root.new(self, name))
end
end
end
end
|