plurimath-parslet 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/HISTORY.txt +284 -0
- data/LICENSE +23 -0
- data/README.adoc +454 -0
- data/Rakefile +71 -0
- data/lib/parslet/accelerator/application.rb +62 -0
- data/lib/parslet/accelerator/engine.rb +112 -0
- data/lib/parslet/accelerator.rb +162 -0
- data/lib/parslet/atoms/alternative.rb +53 -0
- data/lib/parslet/atoms/base.rb +157 -0
- data/lib/parslet/atoms/can_flatten.rb +137 -0
- data/lib/parslet/atoms/capture.rb +38 -0
- data/lib/parslet/atoms/context.rb +103 -0
- data/lib/parslet/atoms/dsl.rb +112 -0
- data/lib/parslet/atoms/dynamic.rb +32 -0
- data/lib/parslet/atoms/entity.rb +45 -0
- data/lib/parslet/atoms/ignored.rb +26 -0
- data/lib/parslet/atoms/infix.rb +115 -0
- data/lib/parslet/atoms/lookahead.rb +52 -0
- data/lib/parslet/atoms/named.rb +32 -0
- data/lib/parslet/atoms/re.rb +41 -0
- data/lib/parslet/atoms/repetition.rb +87 -0
- data/lib/parslet/atoms/scope.rb +26 -0
- data/lib/parslet/atoms/sequence.rb +48 -0
- data/lib/parslet/atoms/str.rb +42 -0
- data/lib/parslet/atoms/visitor.rb +89 -0
- data/lib/parslet/atoms.rb +34 -0
- data/lib/parslet/cause.rb +101 -0
- data/lib/parslet/context.rb +21 -0
- data/lib/parslet/convenience.rb +33 -0
- data/lib/parslet/error_reporter/contextual.rb +120 -0
- data/lib/parslet/error_reporter/deepest.rb +100 -0
- data/lib/parslet/error_reporter/tree.rb +63 -0
- data/lib/parslet/error_reporter.rb +8 -0
- data/lib/parslet/export.rb +163 -0
- data/lib/parslet/expression/treetop.rb +92 -0
- data/lib/parslet/expression.rb +51 -0
- data/lib/parslet/graphviz.rb +97 -0
- data/lib/parslet/parser.rb +68 -0
- data/lib/parslet/pattern/binding.rb +49 -0
- data/lib/parslet/pattern.rb +113 -0
- data/lib/parslet/position.rb +21 -0
- data/lib/parslet/rig/rspec.rb +52 -0
- data/lib/parslet/scope.rb +42 -0
- data/lib/parslet/slice.rb +105 -0
- data/lib/parslet/source/line_cache.rb +99 -0
- data/lib/parslet/source.rb +96 -0
- data/lib/parslet/transform.rb +265 -0
- data/lib/parslet/version.rb +5 -0
- data/lib/parslet.rb +314 -0
- data/plurimath-parslet.gemspec +42 -0
- data/spec/acceptance/infix_parser_spec.rb +145 -0
- data/spec/acceptance/mixing_parsers_spec.rb +74 -0
- data/spec/acceptance/regression_spec.rb +329 -0
- data/spec/acceptance/repetition_and_maybe_spec.rb +44 -0
- data/spec/acceptance/unconsumed_input_spec.rb +21 -0
- data/spec/examples/boolean_algebra_spec.rb +257 -0
- data/spec/examples/calc_spec.rb +278 -0
- data/spec/examples/capture_spec.rb +137 -0
- data/spec/examples/comments_spec.rb +186 -0
- data/spec/examples/deepest_errors_spec.rb +420 -0
- data/spec/examples/documentation_spec.rb +205 -0
- data/spec/examples/email_parser_spec.rb +275 -0
- data/spec/examples/empty_spec.rb +37 -0
- data/spec/examples/erb_spec.rb +482 -0
- data/spec/examples/ip_address_spec.rb +153 -0
- data/spec/examples/json_spec.rb +413 -0
- data/spec/examples/local_spec.rb +302 -0
- data/spec/examples/mathn_spec.rb +151 -0
- data/spec/examples/minilisp_spec.rb +492 -0
- data/spec/examples/modularity_spec.rb +340 -0
- data/spec/examples/nested_errors_spec.rb +322 -0
- data/spec/examples/optimized_erb_spec.rb +299 -0
- data/spec/examples/parens_spec.rb +239 -0
- data/spec/examples/prec_calc_spec.rb +525 -0
- data/spec/examples/readme_spec.rb +228 -0
- data/spec/examples/scopes_spec.rb +187 -0
- data/spec/examples/seasons_spec.rb +196 -0
- data/spec/examples/sentence_spec.rb +119 -0
- data/spec/examples/simple_xml_spec.rb +250 -0
- data/spec/examples/string_parser_spec.rb +407 -0
- data/spec/fixtures/examples/boolean_algebra.rb +62 -0
- data/spec/fixtures/examples/calc.rb +86 -0
- data/spec/fixtures/examples/capture.rb +36 -0
- data/spec/fixtures/examples/comments.rb +22 -0
- data/spec/fixtures/examples/deepest_errors.rb +99 -0
- data/spec/fixtures/examples/documentation.rb +32 -0
- data/spec/fixtures/examples/email_parser.rb +42 -0
- data/spec/fixtures/examples/empty.rb +10 -0
- data/spec/fixtures/examples/erb.rb +39 -0
- data/spec/fixtures/examples/ip_address.rb +103 -0
- data/spec/fixtures/examples/json.rb +107 -0
- data/spec/fixtures/examples/local.rb +60 -0
- data/spec/fixtures/examples/mathn.rb +47 -0
- data/spec/fixtures/examples/minilisp.rb +75 -0
- data/spec/fixtures/examples/modularity.rb +60 -0
- data/spec/fixtures/examples/nested_errors.rb +95 -0
- data/spec/fixtures/examples/optimized_erb.rb +105 -0
- data/spec/fixtures/examples/parens.rb +25 -0
- data/spec/fixtures/examples/prec_calc.rb +71 -0
- data/spec/fixtures/examples/readme.rb +59 -0
- data/spec/fixtures/examples/scopes.rb +43 -0
- data/spec/fixtures/examples/seasons.rb +40 -0
- data/spec/fixtures/examples/sentence.rb +18 -0
- data/spec/fixtures/examples/simple_xml.rb +51 -0
- data/spec/fixtures/examples/string_parser.rb +77 -0
- data/spec/parslet/atom_results_spec.rb +39 -0
- data/spec/parslet/atoms/alternative_spec.rb +26 -0
- data/spec/parslet/atoms/base_spec.rb +127 -0
- data/spec/parslet/atoms/capture_spec.rb +21 -0
- data/spec/parslet/atoms/combinations_spec.rb +5 -0
- data/spec/parslet/atoms/dsl_spec.rb +7 -0
- data/spec/parslet/atoms/entity_spec.rb +77 -0
- data/spec/parslet/atoms/ignored_spec.rb +15 -0
- data/spec/parslet/atoms/infix_spec.rb +5 -0
- data/spec/parslet/atoms/lookahead_spec.rb +22 -0
- data/spec/parslet/atoms/named_spec.rb +4 -0
- data/spec/parslet/atoms/re_spec.rb +14 -0
- data/spec/parslet/atoms/repetition_spec.rb +24 -0
- data/spec/parslet/atoms/scope_spec.rb +26 -0
- data/spec/parslet/atoms/sequence_spec.rb +28 -0
- data/spec/parslet/atoms/str_spec.rb +15 -0
- data/spec/parslet/atoms/visitor_spec.rb +101 -0
- data/spec/parslet/atoms_spec.rb +488 -0
- data/spec/parslet/convenience_spec.rb +54 -0
- data/spec/parslet/error_reporter/contextual_spec.rb +118 -0
- data/spec/parslet/error_reporter/deepest_spec.rb +82 -0
- data/spec/parslet/error_reporter/tree_spec.rb +7 -0
- data/spec/parslet/export_spec.rb +40 -0
- data/spec/parslet/expression/treetop_spec.rb +74 -0
- data/spec/parslet/minilisp.citrus +29 -0
- data/spec/parslet/minilisp.tt +29 -0
- data/spec/parslet/parser_spec.rb +36 -0
- data/spec/parslet/parslet_spec.rb +38 -0
- data/spec/parslet/pattern_spec.rb +272 -0
- data/spec/parslet/position_spec.rb +14 -0
- data/spec/parslet/rig/rspec_spec.rb +54 -0
- data/spec/parslet/scope_spec.rb +45 -0
- data/spec/parslet/slice_spec.rb +186 -0
- data/spec/parslet/source/line_cache_spec.rb +74 -0
- data/spec/parslet/source_spec.rb +210 -0
- data/spec/parslet/transform/context_spec.rb +56 -0
- data/spec/parslet/transform_spec.rb +183 -0
- data/spec/spec_helper.rb +74 -0
- data/spec/support/opal.rb +8 -0
- data/spec/support/opal.rb.erb +14 -0
- data/spec/support/parslet_matchers.rb +96 -0
- metadata +240 -0
@@ -0,0 +1,127 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Parslet::Atoms::Base do
|
4
|
+
let(:parslet) { Parslet::Atoms::Base.new }
|
5
|
+
let(:context) { Parslet::Atoms::Context.new }
|
6
|
+
|
7
|
+
describe '<- #try(io)' do
|
8
|
+
it 'raises NotImplementedError' do
|
9
|
+
lambda {
|
10
|
+
parslet.try(double(:io), context, false)
|
11
|
+
}.should raise_error(NotImplementedError)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe '<- #flatten_sequence' do
|
16
|
+
[
|
17
|
+
# 9 possibilities for making a word of 2 letters from the alphabeth of
|
18
|
+
# A(rray), H(ash) and S(tring). Make sure that all results are valid.
|
19
|
+
#
|
20
|
+
%w[a b], 'ab', # S S
|
21
|
+
[['a'], ['b']], %w[a b], # A A
|
22
|
+
[{ a: 'a' }, { b: 'b' }], { a: 'a', b: 'b' }, # H H
|
23
|
+
|
24
|
+
[{ a: 'a' }, ['a']], [{ a: 'a' }, 'a'], # H A
|
25
|
+
[{ a: 'a' }, 's'], { a: 'a' }, # H S
|
26
|
+
|
27
|
+
[['a'], { a: 'a' }], ['a', { a: 'a' }], # A H (symmetric to H A)
|
28
|
+
[['a'], 'b'], ['a'], # A S
|
29
|
+
|
30
|
+
['a', { b: 'b' }], { b: 'b' }, # S H (symmetric to H S)
|
31
|
+
['a', ['b']], ['b'], # S A (symmetric to A S)
|
32
|
+
|
33
|
+
[nil, ['a']], ['a'], # handling of lhs nil
|
34
|
+
[nil, { a: 'a' }], { a: 'a' },
|
35
|
+
[['a'], nil], ['a'], # handling of rhs nil
|
36
|
+
[{ a: 'a' }, nil], { a: 'a' }
|
37
|
+
].each_slice(2) do |sequence, result|
|
38
|
+
context 'for ' + sequence.inspect do
|
39
|
+
it "equals #{result.inspect}" do
|
40
|
+
parslet.flatten_sequence(sequence).should == result
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe '<- #flatten_repetition' do
|
47
|
+
def unnamed(obj)
|
48
|
+
parslet.flatten_repetition(obj, false)
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'gives subtrees precedence' do
|
52
|
+
unnamed([[{ a: 'a' }, { m: 'm' }], { a: 'a' }]).should == [{ a: 'a' }]
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe '#parse(source)' do
|
57
|
+
context 'when given something that looks like a source' do
|
58
|
+
let(:source) do
|
59
|
+
double('source lookalike',
|
60
|
+
line_and_column: [1, 2],
|
61
|
+
bytepos: 1,
|
62
|
+
chars_left: 0)
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'does not rewrap in a source' do
|
66
|
+
expect(Parslet::Source).not_to receive(:new)
|
67
|
+
|
68
|
+
begin
|
69
|
+
parslet.parse(source)
|
70
|
+
rescue NotImplementedError
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
context 'when the parse fails, the exception' do
|
77
|
+
it 'contains a string' do
|
78
|
+
Parslet.str('foo').parse('bar')
|
79
|
+
rescue Parslet::ParseFailed => e
|
80
|
+
e.message.should be_kind_of(String)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
context 'when not all input is consumed' do
|
85
|
+
let(:parslet) { Parslet.str('foo') }
|
86
|
+
|
87
|
+
it 'raises with a proper error message' do
|
88
|
+
error = catch_failed_parse do
|
89
|
+
parslet.parse('foobar')
|
90
|
+
end
|
91
|
+
|
92
|
+
error.to_s.should == "Don't know what to do with \"bar\" at line 1 char 4."
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
context 'when only parsing string prefix' do
|
97
|
+
let(:parslet) { Parslet.str('foo') >> Parslet.str('bar') }
|
98
|
+
|
99
|
+
it 'returns the first half on a prefix parse' do
|
100
|
+
parslet.parse('foobarbaz', prefix: true).should == 'foobar'
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
describe ':reporter option' do
|
105
|
+
let(:parslet) { Parslet.str('test') >> Parslet.str('ing') }
|
106
|
+
let(:reporter) { double(:reporter) }
|
107
|
+
|
108
|
+
it 'replaces the default reporter' do
|
109
|
+
cause = double(:cause)
|
110
|
+
|
111
|
+
# Two levels of the parse, calling two different error reporting
|
112
|
+
# methods.
|
113
|
+
expect(reporter).to receive(:err_at).once
|
114
|
+
expect(reporter).to receive(:err).and_return(cause).once
|
115
|
+
expect(reporter).to receive(:succ).once
|
116
|
+
|
117
|
+
# The final cause will be sent the #raise method.
|
118
|
+
expect(cause).to receive(:raise).once.and_throw(:raise)
|
119
|
+
|
120
|
+
catch(:raise) do
|
121
|
+
parslet.parse('testung', reporter: reporter)
|
122
|
+
|
123
|
+
raise 'NEVER REACHED'
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Parslet::Atoms::Capture do
|
4
|
+
include Parslet
|
5
|
+
|
6
|
+
let(:context) { Parslet::Atoms::Context.new(nil) }
|
7
|
+
|
8
|
+
def inject string, parser
|
9
|
+
source = Parslet::Source.new(string)
|
10
|
+
parser.apply(source, context, true)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should capture simple results" do
|
14
|
+
inject 'a', str('a').capture(:a)
|
15
|
+
context.captures[:a].should == 'a'
|
16
|
+
end
|
17
|
+
it "should capture complex results" do
|
18
|
+
inject 'a', str('a').as(:b).capture(:a)
|
19
|
+
context.captures[:a].should == {:b => 'a'}
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Parslet::Atoms::Entity do
|
4
|
+
context "when constructed with str('bar') inside" do
|
5
|
+
let(:named) { Parslet::Atoms::Entity.new('name', &proc { Parslet.str('bar') }) }
|
6
|
+
|
7
|
+
it "should parse 'bar' without raising exceptions" do
|
8
|
+
named.parse('bar')
|
9
|
+
end
|
10
|
+
it "should raise when applied to 'foo'" do
|
11
|
+
lambda {
|
12
|
+
named.parse('foo')
|
13
|
+
}.should raise_error(Parslet::ParseFailed)
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "#inspect" do
|
17
|
+
it "should return the name of the entity" do
|
18
|
+
named.inspect.should == 'NAME'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
context "when constructed with empty block" do
|
23
|
+
let(:entity) { Parslet::Atoms::Entity.new('name', &proc { }) }
|
24
|
+
|
25
|
+
it "should raise NotImplementedError" do
|
26
|
+
lambda {
|
27
|
+
entity.parse('some_string')
|
28
|
+
}.should raise_error(NotImplementedError)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context "recursive definition parser" do
|
33
|
+
class RecDefParser
|
34
|
+
include Parslet
|
35
|
+
rule :recdef do
|
36
|
+
str('(') >> atom >> str(')')
|
37
|
+
end
|
38
|
+
rule :atom do
|
39
|
+
str('a') | str('b') | recdef
|
40
|
+
end
|
41
|
+
end
|
42
|
+
let(:parser) { RecDefParser.new }
|
43
|
+
|
44
|
+
it "should parse balanced parens" do
|
45
|
+
parser.recdef.parse("(((a)))")
|
46
|
+
end
|
47
|
+
it "should not throw 'stack level too deep' when printing errors" do
|
48
|
+
cause = catch_failed_parse { parser.recdef.parse('(((a))') }
|
49
|
+
cause.ascii_tree
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context "when constructed with a label" do
|
54
|
+
let(:named) { Parslet::Atoms::Entity.new('name', 'label', &proc { Parslet.str('bar') }) }
|
55
|
+
|
56
|
+
it "should parse 'bar' without raising exceptions" do
|
57
|
+
named.parse('bar')
|
58
|
+
end
|
59
|
+
it "should raise when applied to 'foo'" do
|
60
|
+
lambda {
|
61
|
+
named.parse('foo')
|
62
|
+
}.should raise_error(Parslet::ParseFailed)
|
63
|
+
end
|
64
|
+
|
65
|
+
describe "#inspect" do
|
66
|
+
it "should return the label of the entity" do
|
67
|
+
named.inspect.should == 'label'
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe "#parslet" do
|
72
|
+
it "should set the label on the cached parslet" do
|
73
|
+
named.parslet.label.should == 'label'
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Parslet::Atoms::Ignored do
|
4
|
+
include Parslet
|
5
|
+
|
6
|
+
describe "ignore" do
|
7
|
+
it "ignores parts of the input" do
|
8
|
+
str('a').ignore.parse('a').should == nil
|
9
|
+
(str('a') >> str('b').ignore >> str('c')).parse('abc').should == 'ac'
|
10
|
+
(str('a') >> str('b').as(:name).ignore >> str('c')).parse('abc').should == 'ac'
|
11
|
+
(str('a') >> str('b').maybe.ignore >> str('c')).parse('abc').should == 'ac'
|
12
|
+
(str('a') >> str('b').maybe.ignore >> str('c')).parse('ac').should == 'ac'
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Parslet::Atoms::Lookahead do
|
4
|
+
include Parslet
|
5
|
+
|
6
|
+
describe 'negative lookahead' do
|
7
|
+
it "influences the error tree" do
|
8
|
+
parser = str('f').absent? >> str('b')
|
9
|
+
cause = catch_failed_parse { parser.parse('f') }
|
10
|
+
|
11
|
+
cause.ascii_tree.should == "Failed to match sequence (!'f' 'b') at line 1 char 1.\n`- Input should not start with 'f' at line 1 char 1.\n"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
describe 'positive lookahead' do
|
15
|
+
it "influences the error tree" do
|
16
|
+
parser = str('f').present? >> str('b')
|
17
|
+
cause = catch_failed_parse { parser.parse('b') }
|
18
|
+
|
19
|
+
cause.ascii_tree.should == "Failed to match sequence (&'f' 'b') at line 1 char 1.\n`- Input should start with 'f' at line 1 char 1.\n"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Parslet::Atoms::Re do
|
4
|
+
describe "construction" do
|
5
|
+
include Parslet
|
6
|
+
|
7
|
+
it "should allow match(str) form" do
|
8
|
+
Parslet.match('[a]').should be_a(Parslet::Atoms::Re)
|
9
|
+
end
|
10
|
+
it "should allow match[str] form" do
|
11
|
+
Parslet.match['a'].should be_a(Parslet::Atoms::Re)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Parslet::Atoms::Repetition do
|
4
|
+
include Parslet
|
5
|
+
|
6
|
+
describe "repeat" do
|
7
|
+
let(:parslet) { str('a') }
|
8
|
+
|
9
|
+
describe "(min, max)" do
|
10
|
+
subject { parslet.repeat(1,2) }
|
11
|
+
|
12
|
+
it { should_not parse("") }
|
13
|
+
it { should parse("a") }
|
14
|
+
it { should parse("aa") }
|
15
|
+
end
|
16
|
+
describe "0 times" do
|
17
|
+
it "raises an ArgumentError" do
|
18
|
+
expect {
|
19
|
+
parslet.repeat(0,0)
|
20
|
+
}.to raise_error(ArgumentError)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Parslet::Atoms::Scope do
|
4
|
+
include Parslet
|
5
|
+
include Parslet::Atoms::DSL
|
6
|
+
|
7
|
+
|
8
|
+
let(:context) { Parslet::Atoms::Context.new(nil) }
|
9
|
+
let(:captures) { context.captures }
|
10
|
+
|
11
|
+
def inject string, parser
|
12
|
+
source = Parslet::Source.new(string)
|
13
|
+
parser.apply(source, context, true)
|
14
|
+
end
|
15
|
+
|
16
|
+
let(:aabb) {
|
17
|
+
scope {
|
18
|
+
Parslet.match['ab'].capture(:f) >> dynamic { |s,c| str(c.captures[:f]) }
|
19
|
+
}
|
20
|
+
}
|
21
|
+
it "keeps values of captures outside" do
|
22
|
+
captures[:f] = 'old_value'
|
23
|
+
inject 'aa', aabb
|
24
|
+
captures[:f].should == 'old_value'
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Parslet::Atoms::Sequence do
|
4
|
+
include Parslet
|
5
|
+
|
6
|
+
let(:sequence) { described_class.new }
|
7
|
+
|
8
|
+
describe '>> shortcut' do
|
9
|
+
let(:sequence) { str('a') >> str('b') }
|
10
|
+
|
11
|
+
context "when chained with different atoms" do
|
12
|
+
before(:each) {
|
13
|
+
# Chain something else to the sequence parslet. If it modifies the
|
14
|
+
# parslet atom in place, we'll notice:
|
15
|
+
|
16
|
+
sequence >> str('d')
|
17
|
+
}
|
18
|
+
let!(:chained) { sequence >> str('c') }
|
19
|
+
|
20
|
+
|
21
|
+
it "is side-effect free" do
|
22
|
+
chained.should parse('abc')
|
23
|
+
chained.should_not parse('abdc')
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# Encoding: UTF-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Parslet::Atoms::Str do
|
6
|
+
def str(s)
|
7
|
+
described_class.new(s)
|
8
|
+
end
|
9
|
+
|
10
|
+
describe 'regression #1: multibyte characters' do
|
11
|
+
it "parses successfully (length check works)" do
|
12
|
+
str('あああ').should parse('あああ')
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Parslet::Atoms do
|
4
|
+
include Parslet
|
5
|
+
let(:visitor) { double(:visitor) }
|
6
|
+
|
7
|
+
describe Parslet::Atoms::Str do
|
8
|
+
let(:parslet) { str('foo') }
|
9
|
+
|
10
|
+
it 'calls back visitor' do
|
11
|
+
expect(visitor).to receive(:visit_str).with('foo').once
|
12
|
+
|
13
|
+
parslet.accept(visitor)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe Parslet::Atoms::Re do
|
18
|
+
let(:parslet) { Parslet.match['abc'] }
|
19
|
+
|
20
|
+
it 'calls back visitor' do
|
21
|
+
expect(visitor).to receive(:visit_re).with('[abc]').once
|
22
|
+
|
23
|
+
parslet.accept(visitor)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe Parslet::Atoms::Sequence do
|
28
|
+
let(:parslet) { str('a') >> str('b') }
|
29
|
+
|
30
|
+
it 'calls back visitor' do
|
31
|
+
expect(visitor).to receive(:visit_sequence).with(Array).once
|
32
|
+
|
33
|
+
parslet.accept(visitor)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe Parslet::Atoms::Repetition do
|
38
|
+
let(:parslet) { str('a').repeat(1, 2) }
|
39
|
+
|
40
|
+
it 'calls back visitor' do
|
41
|
+
expect(visitor).to receive(:visit_repetition).with(:repetition, 1, 2, Parslet::Atoms::Base).once
|
42
|
+
|
43
|
+
parslet.accept(visitor)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe Parslet::Atoms::Alternative do
|
48
|
+
let(:parslet) { str('a') | str('b') }
|
49
|
+
|
50
|
+
it 'calls back visitor' do
|
51
|
+
expect(visitor).to receive(:visit_alternative).with(Array).once
|
52
|
+
|
53
|
+
parslet.accept(visitor)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe Parslet::Atoms::Named do
|
58
|
+
let(:parslet) { str('a').as(:a) }
|
59
|
+
|
60
|
+
it 'calls back visitor' do
|
61
|
+
expect(visitor).to receive(:visit_named).with(:a, Parslet::Atoms::Base).once
|
62
|
+
|
63
|
+
parslet.accept(visitor)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe Parslet::Atoms::Entity do
|
68
|
+
let(:parslet) { Parslet::Atoms::Entity.new('foo', &-> {}) }
|
69
|
+
|
70
|
+
it 'calls back visitor' do
|
71
|
+
expect(visitor).to receive(:visit_entity).with('foo', Proc).once
|
72
|
+
|
73
|
+
parslet.accept(visitor)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe Parslet::Atoms::Lookahead do
|
78
|
+
let(:parslet) { str('a').absent? }
|
79
|
+
|
80
|
+
it 'calls back visitor' do
|
81
|
+
expect(visitor).to receive(:visit_lookahead).with(false, Parslet::Atoms::Base).once
|
82
|
+
|
83
|
+
parslet.accept(visitor)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe '< Parslet::Parser' do
|
88
|
+
let(:parslet) do
|
89
|
+
Class.new(Parslet::Parser) do
|
90
|
+
rule(:test_rule) { str('test') }
|
91
|
+
root(:test_rule)
|
92
|
+
end.new
|
93
|
+
end
|
94
|
+
|
95
|
+
it 'calls back to visitor' do
|
96
|
+
expect(visitor).to receive(:visit_parser).with(Parslet::Atoms::Base).once
|
97
|
+
|
98
|
+
parslet.accept(visitor)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|