summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKornelius Kalnbach <murphy@rubychan.de>2017-11-05 17:59:45 +0100
committerKornelius Kalnbach <murphy@rubychan.de>2017-11-05 17:59:45 +0100
commita9e04e1f52f6530cbf4b5251abcf6f1f82840ce9 (patch)
tree8bf81eba1e403be0704e6ca6fefd7d4f85c3b733
parent465e6c3ca2d9c23043c6e5b89f637c284e4ef722 (diff)
downloadcoderay-a9e04e1f52f6530cbf4b5251abcf6f1f82840ce9.tar.gz
fix specs, update SimpleScannerDSL
-rw-r--r--lib/coderay/simple_scanner.rb2
-rw-r--r--lib/coderay/simple_scanner_dsl.rb93
-rw-r--r--spec/simple_scanner_spec.rb33
-rw-r--r--spec/spec_helper.rb2
4 files changed, 77 insertions, 53 deletions
diff --git a/lib/coderay/simple_scanner.rb b/lib/coderay/simple_scanner.rb
index 96a0e51..2ad5fe3 100644
--- a/lib/coderay/simple_scanner.rb
+++ b/lib/coderay/simple_scanner.rb
@@ -15,7 +15,7 @@ module CodeRay
class_eval <<-RUBY
def scan_tokens encoder, options
-#{ scan_tokens_code.chomp.gsub(/^/, ' ' * 2) }
+#{ scan_tokens_code.chomp.gsub(/^/, ' ') }
end
RUBY
end
diff --git a/lib/coderay/simple_scanner_dsl.rb b/lib/coderay/simple_scanner_dsl.rb
index b3c8c57..e954ccf 100644
--- a/lib/coderay/simple_scanner_dsl.rb
+++ b/lib/coderay/simple_scanner_dsl.rb
@@ -3,6 +3,8 @@ require 'set'
module CodeRay
module Scanners
module SimpleScannerDSL
+ NoStatesError = Class.new StandardError
+
Pattern = Struct.new :pattern
Groups = Struct.new :token_kinds
Kind = Struct.new :token_kind
@@ -26,7 +28,7 @@ module CodeRay
def eval
@first = true
- @code = ""
+ @code = ''
instance_eval(&block)
end
@@ -111,115 +113,119 @@ when #{names.map(&:inspect).join(', ')}
end
end
- @code << "#{'els' unless @first}if #{condition_expressions.join(' && ')}\n"
+ condition_code = "#{'els' unless @first}if #{condition_expressions.join(' && ')}\n"
+ action_code = ''
for action in actions
case action
when String
raise
- @code << "p 'evaluate #{action.inspect}'\n" if $DEBUG
- @code << "#{action}\n"
+ action_code << "p 'evaluate #{action.inspect}'\n" if $DEBUG
+ action_code << "#{action}\n"
when Symbol
- @code << "p 'text_token %p %p' % [match, #{action.inspect}]\n" if $DEBUG
- @code << "encoder.text_token match, #{action.inspect}\n"
+ action_code << "p 'text_token %p %p' % [match, #{action.inspect}]\n" if $DEBUG
+ action_code << "encoder.text_token match, #{action.inspect}\n"
when Kind
case action.token_kind
when Proc
- @code << "encoder.text_token match, kind = #{dsl.add_callback(action.token_kind)}\n"
+ action_code << "encoder.text_token match, kind = #{dsl.add_callback(action.token_kind)}\n"
else
raise "I don't know how to evaluate this kind: %p" % [action.token_kind]
end
when Groups
- @code << "p 'text_tokens %p in groups %p' % [match, #{action.token_kinds.inspect}]\n" if $DEBUG
+ action_code << "p 'text_tokens %p in groups %p' % [match, #{action.token_kinds.inspect}]\n" if $DEBUG
action.token_kinds.each_with_index do |kind, i|
- @code << "encoder.text_token self[#{i + 1}], #{kind.inspect} if self[#{i + 1}]\n"
+ action_code << "encoder.text_token self[#{i + 1}], #{kind.inspect} if self[#{i + 1}]\n"
end
when Push, PushState
case action.state
when String
raise
- @code << "p 'push %p' % [#{action.state}]\n" if $DEBUG
- @code << "state = #{action.state}\n"
- @code << "states << state\n"
+ action_code << "p 'push %p' % [#{action.state}]\n" if $DEBUG
+ action_code << "state = #{action.state}\n"
+ action_code << "states << state\n"
when Symbol
- @code << "p 'push %p' % [#{action.state.inspect}]\n" if $DEBUG
- @code << "state = #{action.state.inspect}\n"
- @code << "states << state\n"
+ action_code << "p 'push %p' % [#{action.state.inspect}]\n" if $DEBUG
+ action_code << "state = #{action.state.inspect}\n"
+ action_code << "states << state\n"
when Proc
- @code << "if new_state = #{dsl.add_callback(action.state)}\n"
- @code << " state = new_state\n"
- @code << " states << new_state\n"
- @code << "end\n"
+ action_code << "if new_state = #{dsl.add_callback(action.state)}\n"
+ action_code << " state = new_state\n"
+ action_code << " states << new_state\n"
+ action_code << "end\n"
else
raise "I don't know how to evaluate this push state: %p" % [action.state]
end
if action.is_a? Push
if action.state == action.group
- @code << "encoder.begin_group state\n"
+ action_code << "encoder.begin_group state\n"
else
case action.state
when Symbol
- @code << "p 'begin group %p' % [#{action.group.inspect}]\n" if $DEBUG
- @code << "encoder.begin_group #{action.group.inspect}\n"
+ action_code << "p 'begin group %p' % [#{action.group.inspect}]\n" if $DEBUG
+ action_code << "encoder.begin_group #{action.group.inspect}\n"
when Proc
- @code << "encoder.begin_group #{dsl.add_callback(action.group)}\n"
+ action_code << "encoder.begin_group #{dsl.add_callback(action.group)}\n"
else
raise "I don't know how to evaluate this push state: %p" % [action.state]
end
end
end
when Pop, PopState
- @code << "p 'pop %p' % [states.last]\n" if $DEBUG
+ action_code << "p 'pop %p' % [states.last]\n" if $DEBUG
if action.is_a? Pop
if action.group
case action.group
when Symbol
- @code << "encoder.end_group #{action.group.inspect}\n"
+ action_code << "encoder.end_group #{action.group.inspect}\n"
else
raise "I don't know how to evaluate this pop group: %p" % [action.group]
end
- @code << "states.pop\n"
+ action_code << "states.pop\n"
else
- @code << "encoder.end_group states.pop\n"
+ action_code << "encoder.end_group states.pop\n"
end
else
- @code << "states.pop\n"
+ action_code << "states.pop\n"
end
- @code << "state = states.last\n"
+ action_code << "state = states.last\n"
when ValueSetter
case action.value
when Proc
- @code << "#{action.targets.join(' = ')} = #{dsl.add_callback(action.value)}\n"
+ action_code << "#{action.targets.join(' = ')} = #{dsl.add_callback(action.value)}\n"
when Symbol
- @code << "#{action.targets.join(' = ')} = #{action.value}\n"
+ action_code << "#{action.targets.join(' = ')} = #{action.value}\n"
else
- @code << "#{action.targets.join(' = ')} = #{action.value.inspect}\n"
+ action_code << "#{action.targets.join(' = ')} = #{action.value.inspect}\n"
end
when Increment
case action.value
when Proc
- @code << "#{action.targets.join(' = ')} #{action.operation}= #{dsl.add_callback(action.value)}\n"
+ action_code << "#{action.targets.join(' = ')} #{action.operation}= #{dsl.add_callback(action.value)}\n"
when Symbol
- @code << "#{action.targets.join(' = ')} #{action.operation}= #{action.value}\n"
+ action_code << "#{action.targets.join(' = ')} #{action.operation}= #{action.value}\n"
else
- @code << "#{action.targets.join(' = ')} #{action.operation}= #{action.value.inspect}\n"
+ action_code << "#{action.targets.join(' = ')} #{action.operation}= #{action.value.inspect}\n"
end
when Proc
- @code << "#{dsl.add_callback(action)}\n"
+ action_code << "#{dsl.add_callback(action)}\n"
when Continue
- @code << "next\n"
+ action_code << "next\n"
else
raise "I don't know how to evaluate this action: %p" % [action]
end
end
+ @code << condition_code
+ @code << action_code.gsub(/^/, ' ')
+
@first = false
end
@@ -347,8 +353,7 @@ when #{names.map(&:inspect).join(', ')}
<<-"RUBY"
state = options[:state] || @state
states = [state]
-#{ restore_local_variables_code.chomp }
-
+#{ restore_local_variables_code }
until eos?
case state
#{ states_code.chomp.gsub(/^/, ' ') }
@@ -359,7 +364,7 @@ end
@state = state if options[:keep_state]
-#{ close_groups_code.chomp }
+close_groups(encoder, states)
encoder
RUBY
@@ -370,11 +375,11 @@ encoder
end
def states_code
- @states.map(&:code)[0,1].join
- end
+ unless defined? @states
+ raise NoStatesError, 'no states defined for %p' % [self.class]
+ end
- def close_groups_code
- 'close_groups(encoder, states)'
+ @states.map(&:code).join
end
end
end
diff --git a/spec/simple_scanner_spec.rb b/spec/simple_scanner_spec.rb
index 088343c..bc2aec4 100644
--- a/spec/simple_scanner_spec.rb
+++ b/spec/simple_scanner_spec.rb
@@ -1,17 +1,37 @@
RSpec.describe CodeRay::Scanners::SimpleScanner do
- let(:scanner) { Class.new described_class }
+ let(:scanner) { described_class }
describe '#scan_tokens_code' do
subject { scanner.send :scan_tokens_code }
- it 'lets you define states' do
- is_expected.to eq <<-RUBY
+ it 'throws an error' do
+ expect { subject }.to raise_error(CodeRay::Scanners::SimpleScannerDSL::NoStatesError)
+ end
+ end
+
+ describe 'with one state' do
+ let(:scanner) do
+ Class.new described_class do
+ state :somepony do
+ on %r/rainbow/, :dash
+ end
+ end
+ end
+
+ describe '#scan_tokens_code' do
+ subject { scanner.send :scan_tokens_code }
+ it 'returns an scanner with one states' do
+ is_expected.to eq <<-RUBY
state = options[:state] || @state
states = [state]
-
until eos?
case state
-
+ when :somepony
+ if match = scan(/rainbow/)
+ encoder.text_token match, :dash
+ else
+ encoder.text_token getch, :error
+ end
else
raise_inspect 'Unknown state: %p' % [state], encoder
end
@@ -22,7 +42,8 @@ end
close_groups(encoder, states)
encoder
- RUBY
+ RUBY
+ end
end
end
end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 49b6a0e..fe4e726 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -91,6 +91,4 @@ RSpec.configure do |config|
Kernel.srand config.seed
end
-$LOAD_PATH << 'lib/coderay'
-
require 'coderay'