Skip to content

Commit a9e04e1

Browse files
committed
fix specs, update SimpleScannerDSL
1 parent 465e6c3 commit a9e04e1

File tree

4 files changed

+77
-53
lines changed

4 files changed

+77
-53
lines changed

lib/coderay/simple_scanner.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ def define_scan_tokens!
1515

1616
class_eval <<-RUBY
1717
def scan_tokens encoder, options
18-
#{ scan_tokens_code.chomp.gsub(/^/, ' ' * 2) }
18+
#{ scan_tokens_code.chomp.gsub(/^/, ' ') }
1919
end
2020
RUBY
2121
end

lib/coderay/simple_scanner_dsl.rb

Lines changed: 49 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
module CodeRay
44
module Scanners
55
module SimpleScannerDSL
6+
NoStatesError = Class.new StandardError
7+
68
Pattern = Struct.new :pattern
79
Groups = Struct.new :token_kinds
810
Kind = Struct.new :token_kind
@@ -26,7 +28,7 @@ def initialize(*)
2628
def eval
2729
@first = true
2830

29-
@code = ""
31+
@code = ''
3032
instance_eval(&block)
3133
end
3234

@@ -111,115 +113,119 @@ def on *pattern_and_actions
111113
end
112114
end
113115

114-
@code << "#{'els' unless @first}if #{condition_expressions.join(' && ')}\n"
116+
condition_code = "#{'els' unless @first}if #{condition_expressions.join(' && ')}\n"
117+
action_code = ''
115118

116119
for action in actions
117120
case action
118121
when String
119122
raise
120-
@code << "p 'evaluate #{action.inspect}'\n" if $DEBUG
121-
@code << "#{action}\n"
123+
action_code << "p 'evaluate #{action.inspect}'\n" if $DEBUG
124+
action_code << "#{action}\n"
122125

123126
when Symbol
124-
@code << "p 'text_token %p %p' % [match, #{action.inspect}]\n" if $DEBUG
125-
@code << "encoder.text_token match, #{action.inspect}\n"
127+
action_code << "p 'text_token %p %p' % [match, #{action.inspect}]\n" if $DEBUG
128+
action_code << "encoder.text_token match, #{action.inspect}\n"
126129
when Kind
127130
case action.token_kind
128131
when Proc
129-
@code << "encoder.text_token match, kind = #{dsl.add_callback(action.token_kind)}\n"
132+
action_code << "encoder.text_token match, kind = #{dsl.add_callback(action.token_kind)}\n"
130133
else
131134
raise "I don't know how to evaluate this kind: %p" % [action.token_kind]
132135
end
133136
when Groups
134-
@code << "p 'text_tokens %p in groups %p' % [match, #{action.token_kinds.inspect}]\n" if $DEBUG
137+
action_code << "p 'text_tokens %p in groups %p' % [match, #{action.token_kinds.inspect}]\n" if $DEBUG
135138
action.token_kinds.each_with_index do |kind, i|
136-
@code << "encoder.text_token self[#{i + 1}], #{kind.inspect} if self[#{i + 1}]\n"
139+
action_code << "encoder.text_token self[#{i + 1}], #{kind.inspect} if self[#{i + 1}]\n"
137140
end
138141

139142
when Push, PushState
140143
case action.state
141144
when String
142145
raise
143-
@code << "p 'push %p' % [#{action.state}]\n" if $DEBUG
144-
@code << "state = #{action.state}\n"
145-
@code << "states << state\n"
146+
action_code << "p 'push %p' % [#{action.state}]\n" if $DEBUG
147+
action_code << "state = #{action.state}\n"
148+
action_code << "states << state\n"
146149
when Symbol
147-
@code << "p 'push %p' % [#{action.state.inspect}]\n" if $DEBUG
148-
@code << "state = #{action.state.inspect}\n"
149-
@code << "states << state\n"
150+
action_code << "p 'push %p' % [#{action.state.inspect}]\n" if $DEBUG
151+
action_code << "state = #{action.state.inspect}\n"
152+
action_code << "states << state\n"
150153
when Proc
151-
@code << "if new_state = #{dsl.add_callback(action.state)}\n"
152-
@code << " state = new_state\n"
153-
@code << " states << new_state\n"
154-
@code << "end\n"
154+
action_code << "if new_state = #{dsl.add_callback(action.state)}\n"
155+
action_code << " state = new_state\n"
156+
action_code << " states << new_state\n"
157+
action_code << "end\n"
155158
else
156159
raise "I don't know how to evaluate this push state: %p" % [action.state]
157160
end
158161
if action.is_a? Push
159162
if action.state == action.group
160-
@code << "encoder.begin_group state\n"
163+
action_code << "encoder.begin_group state\n"
161164
else
162165
case action.state
163166
when Symbol
164-
@code << "p 'begin group %p' % [#{action.group.inspect}]\n" if $DEBUG
165-
@code << "encoder.begin_group #{action.group.inspect}\n"
167+
action_code << "p 'begin group %p' % [#{action.group.inspect}]\n" if $DEBUG
168+
action_code << "encoder.begin_group #{action.group.inspect}\n"
166169
when Proc
167-
@code << "encoder.begin_group #{dsl.add_callback(action.group)}\n"
170+
action_code << "encoder.begin_group #{dsl.add_callback(action.group)}\n"
168171
else
169172
raise "I don't know how to evaluate this push state: %p" % [action.state]
170173
end
171174
end
172175
end
173176
when Pop, PopState
174-
@code << "p 'pop %p' % [states.last]\n" if $DEBUG
177+
action_code << "p 'pop %p' % [states.last]\n" if $DEBUG
175178
if action.is_a? Pop
176179
if action.group
177180
case action.group
178181
when Symbol
179-
@code << "encoder.end_group #{action.group.inspect}\n"
182+
action_code << "encoder.end_group #{action.group.inspect}\n"
180183
else
181184
raise "I don't know how to evaluate this pop group: %p" % [action.group]
182185
end
183-
@code << "states.pop\n"
186+
action_code << "states.pop\n"
184187
else
185-
@code << "encoder.end_group states.pop\n"
188+
action_code << "encoder.end_group states.pop\n"
186189
end
187190
else
188-
@code << "states.pop\n"
191+
action_code << "states.pop\n"
189192
end
190-
@code << "state = states.last\n"
193+
action_code << "state = states.last\n"
191194

192195
when ValueSetter
193196
case action.value
194197
when Proc
195-
@code << "#{action.targets.join(' = ')} = #{dsl.add_callback(action.value)}\n"
198+
action_code << "#{action.targets.join(' = ')} = #{dsl.add_callback(action.value)}\n"
196199
when Symbol
197-
@code << "#{action.targets.join(' = ')} = #{action.value}\n"
200+
action_code << "#{action.targets.join(' = ')} = #{action.value}\n"
198201
else
199-
@code << "#{action.targets.join(' = ')} = #{action.value.inspect}\n"
202+
action_code << "#{action.targets.join(' = ')} = #{action.value.inspect}\n"
200203
end
201204

202205
when Increment
203206
case action.value
204207
when Proc
205-
@code << "#{action.targets.join(' = ')} #{action.operation}= #{dsl.add_callback(action.value)}\n"
208+
action_code << "#{action.targets.join(' = ')} #{action.operation}= #{dsl.add_callback(action.value)}\n"
206209
when Symbol
207-
@code << "#{action.targets.join(' = ')} #{action.operation}= #{action.value}\n"
210+
action_code << "#{action.targets.join(' = ')} #{action.operation}= #{action.value}\n"
208211
else
209-
@code << "#{action.targets.join(' = ')} #{action.operation}= #{action.value.inspect}\n"
212+
action_code << "#{action.targets.join(' = ')} #{action.operation}= #{action.value.inspect}\n"
210213
end
211214

212215
when Proc
213-
@code << "#{dsl.add_callback(action)}\n"
216+
action_code << "#{dsl.add_callback(action)}\n"
214217

215218
when Continue
216-
@code << "next\n"
219+
action_code << "next\n"
217220

218221
else
219222
raise "I don't know how to evaluate this action: %p" % [action]
220223
end
221224
end
222225

226+
@code << condition_code
227+
@code << action_code.gsub(/^/, ' ')
228+
223229
@first = false
224230
end
225231

@@ -347,8 +353,7 @@ def scan_tokens_code
347353
<<-"RUBY"
348354
state = options[:state] || @state
349355
states = [state]
350-
#{ restore_local_variables_code.chomp }
351-
356+
#{ restore_local_variables_code }
352357
until eos?
353358
case state
354359
#{ states_code.chomp.gsub(/^/, ' ') }
@@ -359,7 +364,7 @@ def scan_tokens_code
359364
360365
@state = state if options[:keep_state]
361366
362-
#{ close_groups_code.chomp }
367+
close_groups(encoder, states)
363368
364369
encoder
365370
RUBY
@@ -370,11 +375,11 @@ def restore_local_variables_code
370375
end
371376

372377
def states_code
373-
@states.map(&:code)[0,1].join
374-
end
378+
unless defined? @states
379+
raise NoStatesError, 'no states defined for %p' % [self.class]
380+
end
375381

376-
def close_groups_code
377-
'close_groups(encoder, states)'
382+
@states.map(&:code).join
378383
end
379384
end
380385
end

spec/simple_scanner_spec.rb

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,37 @@
11
RSpec.describe CodeRay::Scanners::SimpleScanner do
2-
let(:scanner) { Class.new described_class }
2+
let(:scanner) { described_class }
33

44
describe '#scan_tokens_code' do
55
subject { scanner.send :scan_tokens_code }
6-
it 'lets you define states' do
7-
is_expected.to eq <<-RUBY
6+
it 'throws an error' do
7+
expect { subject }.to raise_error(CodeRay::Scanners::SimpleScannerDSL::NoStatesError)
8+
end
9+
end
10+
11+
describe 'with one state' do
12+
let(:scanner) do
13+
Class.new described_class do
14+
state :somepony do
15+
on %r/rainbow/, :dash
16+
end
17+
end
18+
end
19+
20+
describe '#scan_tokens_code' do
21+
subject { scanner.send :scan_tokens_code }
22+
it 'returns an scanner with one states' do
23+
is_expected.to eq <<-RUBY
824
state = options[:state] || @state
925
states = [state]
1026
11-
1227
until eos?
1328
case state
14-
29+
when :somepony
30+
if match = scan(/rainbow/)
31+
encoder.text_token match, :dash
32+
else
33+
encoder.text_token getch, :error
34+
end
1535
else
1636
raise_inspect 'Unknown state: %p' % [state], encoder
1737
end
@@ -22,7 +42,8 @@
2242
close_groups(encoder, states)
2343
2444
encoder
25-
RUBY
45+
RUBY
46+
end
2647
end
2748
end
2849
end

spec/spec_helper.rb

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,4 @@
9191
Kernel.srand config.seed
9292
end
9393

94-
$LOAD_PATH << 'lib/coderay'
95-
9694
require 'coderay'

0 commit comments

Comments
 (0)