Class: Token
- Inherits:
-
Object
show all
- Defined in:
- lib/raka/token.rb
Overview
A raka expression is a list of linked tokens. The Token class store current token, info of previous tokens, and context. It plays rule of both token and expr
Instance Attribute Summary collapse
Instance Method Summary
collapse
Constructor Details
#initialize(compiler, context, chain, inline_scope, input_exts: nil) ⇒ Token
Returns a new instance of Token.
31
32
33
34
35
36
37
38
39
|
# File 'lib/raka/token.rb', line 31
def initialize(compiler, context, chain, inline_scope, input_exts: nil)
@compiler = compiler
@context = context
@chain = chain
@inline_scope = inline_scope
@options = {}
@options[:input_exts] = input_exts
@compiler_options = @compiler.instance_variable_get(:@options)
end
|
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(sym, *args) ⇒ Object
rubocop:disable Style/MissingRespondToMissing # for DSL not essential
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
# File 'lib/raka/token.rb', line 87
def method_missing(sym, *args)
super if internal(sym)
if sym.to_s.end_with? '='
@compiler.compile(_attach_(sym.to_s.chomp('=')), args.first)
elsif !args.empty?
_attach_ args.first.to_s
else
_attach_ sym.to_s
end
end
|
Instance Attribute Details
#chain ⇒ Object
Returns the value of attribute chain.
29
30
31
|
# File 'lib/raka/token.rb', line 29
def chain
@chain
end
|
Instance Method Details
#[](pattern, options = {}) ⇒ Object
These two methods indicate that this is a pattern token
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
|
# File 'lib/raka/token.rb', line 156
def [](pattern, options = {})
symbol = @chain.pop.to_s
pattern = pattern.to_s.gsub(/\(\S+?\)/).with_index { |m, i| "(?<#{symbol}#{i}>#{m})" }
options = @compiler_options&.pattern_options&.merge(options)
refined_pattern = case options[:match_mode]
when 'exact'
pattern.to_s
when 'prefix'
"#{pattern}\\w*"
else
raise "Invalid match_mode: #{match_mode}. Use 'exact' or 'prefix'"
end
if symbol == Pattern::ANY @chain.push refined_pattern
else
@chain.push "(?<#{symbol}>(#{refined_pattern}))"
end
self
end
|
#[]=(pattern, *args) ⇒ Object
185
186
187
188
189
190
191
192
193
194
195
196
197
198
|
# File 'lib/raka/token.rb', line 185
def []=(pattern, *args)
case args.length
when 1
value = args[0]
@compiler.compile(self[pattern], value)
when 2
options, value = args
@compiler.compile(self[pattern, options], value)
else
raise ArgumentError, "wrong number of arguments (given #{args.length + 1}, expected 2 or 3)"
end
end
|
#_(*args) ⇒ Object
non capture matching anything
104
105
106
107
108
109
110
|
# File 'lib/raka/token.rb', line 104
def _(*args)
if !args.empty?
_attach_ args.first.to_s
else
_attach_ Pattern::ANY
end
end
|
#_=(rhs) ⇒ Object
112
113
114
|
# File 'lib/raka/token.rb', line 112
def _=(rhs)
@compiler.compile(_attach_(Pattern::ANY), rhs)
end
|
#_attach_(item) ⇒ Object
attach a new item to the chain
82
83
84
|
# File 'lib/raka/token.rb', line 82
def _attach_(item)
Token.new(@compiler, @context, @chain + [item], @inline_scope, **@options)
end
|
#_captures_(target) ⇒ Object
45
46
47
48
49
|
# File 'lib/raka/token.rb', line 45
def _captures_(target)
matched = _pattern_.match(target)
keys = matched.names.map(&:to_sym)
Hash[keys.zip(matched.captures)]
end
|
116
117
118
|
# File 'lib/raka/token.rb', line 116
def _input_?
@chain.length > 1
end
|
120
121
122
123
124
125
126
127
128
129
130
131
|
# File 'lib/raka/token.rb', line 120
def _inputs_(output, ext)
return [] if @chain.length == 1
info = _parse_output_(output)
input_stem = /^\S+?__(\S+)$/.match(info.stem)[1]
auto_input = "#{input_stem}.#{ext}"
auto_input = "#{info.target_scope}/" + auto_input if info.target_scope
auto_input = "#{info.scope}/" + auto_input if info.scope
[auto_input]
end
|
#_options_ ⇒ Object
41
42
43
|
# File 'lib/raka/token.rb', line 41
def _options_
@options
end
|
#_parse_output_(output) ⇒ Object
rubocop:disable Style/MethodLength # long but straightforward
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
|
# File 'lib/raka/token.rb', line 52
def _parse_output_(output)
out_pattern = %r{^((?<scope>\S+)/)?}.source
out_pattern += %r{(?<target_scope>#{@inline_scope})/}.source unless @inline_scope.nil?
out_pattern += /(?<stem>(\S+))(?<ext>\.[^.]+)$/.source
info = Regexp.new(out_pattern).match(output)
res = Hash[info.names.zip(info.captures)]
unless info[:scope].nil?
rule_scopes = Regexp.new(_scope_pattern_).match(info[:scope]).captures
res[:rule_scopes] = rule_scopes[2..-1].reverse
end
if !@inline_scope.nil? && !info[:target_scope].nil?
segs = Regexp.new(@inline_scope).match(info[:target_scope]).captures
res[:target_scope_captures] = segs
end
name_details = /^(\S+?)__(\S+)$/.match(info[:stem])
res = if name_details
res.merge(func: name_details[1], input_stem: name_details[2])
else
res.merge(func: nil, input_stem: nil)
end
res = res.merge(captures: OpenStruct.new(_captures_(output)))
res[:name] = output
res[:output] = output
res[:output_stem] = info[:stem]
OpenStruct.new res
end
|
#_pattern_ ⇒ Object
141
142
143
144
145
146
147
|
# File 'lib/raka/token.rb', line 141
def _pattern_
leading = !@context.scopes.empty? ? _scope_pattern_ + '/' : _scope_pattern_
leading += "(#{@inline_scope})/" unless @inline_scope.nil?
body = @chain.reverse.map { |s| "(#{s})" }.join('__')
Regexp.new('^' + leading + body + '\.' + @context.ext.to_s + '$')
end
|
#_rule_scope_pattern_ ⇒ Object
133
134
135
|
# File 'lib/raka/token.rb', line 133
def _rule_scope_pattern_
(@context.scopes.map { |layer| "(#{layer.join('|')})" }).join('/') + ')'
end
|
#_scope_pattern_ ⇒ Object
137
138
139
|
# File 'lib/raka/token.rb', line 137
def _scope_pattern_
'((?:(\S+)/)?' + _rule_scope_pattern_
end
|
#_template_(scope = nil) ⇒ Object
149
150
151
152
153
|
# File 'lib/raka/token.rb', line 149
def _template_(scope = nil)
(scope.nil? ? '' : scope + '/') + (@inline_scope.nil? ? '' : @inline_scope + '/') +
@chain.reverse.join('__') + '.' +
@context.ext.to_s
end
|