walrus 0.1
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.
- data/bin/walrus +44 -0
- data/ext/jindex/extconf.rb +11 -0
- data/ext/jindex/jindex.c +79 -0
- data/ext/mkdtemp/extconf.rb +11 -0
- data/ext/mkdtemp/mkdtemp.c +41 -0
- data/lib/walrus/additions/module.rb +36 -0
- data/lib/walrus/additions/string.rb +37 -0
- data/lib/walrus/additions/test/unit/error_collector.rb +62 -0
- data/lib/walrus/compile_error.rb +28 -0
- data/lib/walrus/compiler.rb +124 -0
- data/lib/walrus/contrib/spec/walruscloth_spec.rb +32 -0
- data/lib/walrus/contrib/walruscloth.rb +82 -0
- data/lib/walrus/diff.rb +89 -0
- data/lib/walrus/document.rb +98 -0
- data/lib/walrus/grammar/additions/proc.rb +20 -0
- data/lib/walrus/grammar/additions/regexp.rb +21 -0
- data/lib/walrus/grammar/additions/string.rb +52 -0
- data/lib/walrus/grammar/additions/symbol.rb +42 -0
- data/lib/walrus/grammar/and_predicate.rb +40 -0
- data/lib/walrus/grammar/array_result.rb +19 -0
- data/lib/walrus/grammar/continuation_wrapper_exception.rb +28 -0
- data/lib/walrus/grammar/left_recursion_exception.rb +27 -0
- data/lib/walrus/grammar/location_tracking.rb +105 -0
- data/lib/walrus/grammar/match_data_wrapper.rb +65 -0
- data/lib/walrus/grammar/memoizing.rb +41 -0
- data/lib/walrus/grammar/memoizing_cache.rb +94 -0
- data/lib/walrus/grammar/node.rb +60 -0
- data/lib/walrus/grammar/not_predicate.rb +40 -0
- data/lib/walrus/grammar/parse_error.rb +39 -0
- data/lib/walrus/grammar/parser_state.rb +181 -0
- data/lib/walrus/grammar/parslet.rb +28 -0
- data/lib/walrus/grammar/parslet_choice.rb +120 -0
- data/lib/walrus/grammar/parslet_combination.rb +26 -0
- data/lib/walrus/grammar/parslet_combining.rb +154 -0
- data/lib/walrus/grammar/parslet_merge.rb +88 -0
- data/lib/walrus/grammar/parslet_omission.rb +57 -0
- data/lib/walrus/grammar/parslet_repetition.rb +97 -0
- data/lib/walrus/grammar/parslet_repetition_default.rb +58 -0
- data/lib/walrus/grammar/parslet_sequence.rb +202 -0
- data/lib/walrus/grammar/predicate.rb +57 -0
- data/lib/walrus/grammar/proc_parslet.rb +52 -0
- data/lib/walrus/grammar/regexp_parslet.rb +73 -0
- data/lib/walrus/grammar/skipped_substring_exception.rb +36 -0
- data/lib/walrus/grammar/string_enumerator.rb +45 -0
- data/lib/walrus/grammar/string_parslet.rb +75 -0
- data/lib/walrus/grammar/string_result.rb +24 -0
- data/lib/walrus/grammar/symbol_parslet.rb +63 -0
- data/lib/walrus/grammar.rb +170 -0
- data/lib/walrus/no_parameter_marker.rb +19 -0
- data/lib/walrus/parser.rb +420 -0
- data/lib/walrus/runner.rb +356 -0
- data/lib/walrus/template.rb +75 -0
- data/lib/walrus/walrus_grammar/assignment_expression.rb +24 -0
- data/lib/walrus/walrus_grammar/block_directive.rb +28 -0
- data/lib/walrus/walrus_grammar/comment.rb +24 -0
- data/lib/walrus/walrus_grammar/def_directive.rb +64 -0
- data/lib/walrus/walrus_grammar/echo_directive.rb +44 -0
- data/lib/walrus/walrus_grammar/escape_sequence.rb +24 -0
- data/lib/walrus/walrus_grammar/import_directive.rb +44 -0
- data/lib/walrus/walrus_grammar/include_directive.rb +27 -0
- data/lib/walrus/walrus_grammar/instance_variable.rb +24 -0
- data/lib/walrus/walrus_grammar/literal.rb +24 -0
- data/lib/walrus/walrus_grammar/message_expression.rb +25 -0
- data/lib/walrus/walrus_grammar/multiline_comment.rb +54 -0
- data/lib/walrus/walrus_grammar/placeholder.rb +40 -0
- data/lib/walrus/walrus_grammar/raw_directive.rb +42 -0
- data/lib/walrus/walrus_grammar/raw_text.rb +45 -0
- data/lib/walrus/walrus_grammar/ruby_directive.rb +29 -0
- data/lib/walrus/walrus_grammar/ruby_expression.rb +31 -0
- data/lib/walrus/walrus_grammar/set_directive.rb +24 -0
- data/lib/walrus/walrus_grammar/silent_directive.rb +44 -0
- data/lib/walrus/walrus_grammar/slurp_directive.rb +25 -0
- data/lib/walrus/walrus_grammar/super_directive.rb +27 -0
- data/lib/walrus.rb +64 -0
- data/spec/acceptance/acceptance_spec.rb +97 -0
- data/spec/acceptance/block/basic_block.expected +1 -0
- data/spec/acceptance/block/basic_block.tmpl +3 -0
- data/spec/acceptance/block/nested_blocks.expected +5 -0
- data/spec/acceptance/block/nested_blocks.tmpl +11 -0
- data/spec/acceptance/comments/comments_and_text.expected +3 -0
- data/spec/acceptance/comments/comments_and_text.tmpl +6 -0
- data/spec/acceptance/comments/single_comment.expected +0 -0
- data/spec/acceptance/comments/single_comment.tmpl +1 -0
- data/spec/acceptance/def/alternative_def_calling_conventions.expected +3 -0
- data/spec/acceptance/def/alternative_def_calling_conventions.tmpl +18 -0
- data/spec/acceptance/def/basic_def_block_no_output.expected +0 -0
- data/spec/acceptance/def/basic_def_block_no_output.tmpl +17 -0
- data/spec/acceptance/def/defs_can_be_called_multiple_times.expected +3 -0
- data/spec/acceptance/def/defs_can_be_called_multiple_times.tmpl +6 -0
- data/spec/acceptance/def/defs_can_be_dynamic.expected +4 -0
- data/spec/acceptance/def/defs_can_be_dynamic.tmpl +12 -0
- data/spec/acceptance/echo/echo_directive_with_numeric_literal.expected +1 -0
- data/spec/acceptance/echo/echo_directive_with_numeric_literal.tmpl +1 -0
- data/spec/acceptance/echo/echo_expression_list.expected +1 -0
- data/spec/acceptance/echo/echo_expression_list.tmpl +1 -0
- data/spec/acceptance/echo/echo_short_notation.expected +1 -0
- data/spec/acceptance/echo/echo_short_notation.tmpl +1 -0
- data/spec/acceptance/echo/echo_simple_expression.expected +1 -0
- data/spec/acceptance/echo/echo_simple_expression.tmpl +1 -0
- data/spec/acceptance/echo/echo_single_quoted_string_literal.expected +1 -0
- data/spec/acceptance/echo/echo_single_quoted_string_literal.tmpl +1 -0
- data/spec/acceptance/echo/multiple_echo_statements.expected +1 -0
- data/spec/acceptance/echo/multiple_echo_statements.tmpl +2 -0
- data/spec/acceptance/includes/basic_included_file.txt +1 -0
- data/spec/acceptance/includes/basic_includer.complex +3 -0
- data/spec/acceptance/includes/basic_includer.expected +3 -0
- data/spec/acceptance/includes/basic_includer.rb +38 -0
- data/spec/acceptance/includes/complicated_included_file.txt +3 -0
- data/spec/acceptance/includes/complicated_includer.complex +3 -0
- data/spec/acceptance/includes/complicated_includer.expected +3 -0
- data/spec/acceptance/includes/complicated_includer.rb +41 -0
- data/spec/acceptance/includes/nested_include_1.txt +3 -0
- data/spec/acceptance/includes/nested_include_2.txt +1 -0
- data/spec/acceptance/includes/nested_includer.complex +3 -0
- data/spec/acceptance/includes/nested_includer.expected +4 -0
- data/spec/acceptance/includes/nested_includer.rb +41 -0
- data/spec/acceptance/inheritance/basic_child.complex +10 -0
- data/spec/acceptance/inheritance/basic_child.expected +9 -0
- data/spec/acceptance/inheritance/basic_child.rb +54 -0
- data/spec/acceptance/inheritance/basic_parent.complex +5 -0
- data/spec/acceptance/inheritance/basic_parent.expected +3 -0
- data/spec/acceptance/inheritance/basic_parent.rb +41 -0
- data/spec/acceptance/inheritance/importing_child.complex +8 -0
- data/spec/acceptance/inheritance/importing_child.expected +7 -0
- data/spec/acceptance/inheritance/importing_child.rb +46 -0
- data/spec/acceptance/inheritance/subdirectory/importing_child_in_subdirectory.complex +8 -0
- data/spec/acceptance/inheritance/subdirectory/importing_child_in_subdirectory.expected +7 -0
- data/spec/acceptance/inheritance/subdirectory/importing_child_in_subdirectory.rb +44 -0
- data/spec/acceptance/multiline_comments/multiline_comment_with_directives_inside.expected +0 -0
- data/spec/acceptance/multiline_comments/multiline_comment_with_directives_inside.tmpl +15 -0
- data/spec/acceptance/multiline_comments/simple_multiline_comment.expected +2 -0
- data/spec/acceptance/multiline_comments/simple_multiline_comment.tmpl +4 -0
- data/spec/acceptance/raw/complicated_raw_example.expected +57 -0
- data/spec/acceptance/raw/complicated_raw_example.tmpl +79 -0
- data/spec/acceptance/raw-text/UTF_8.expected +12 -0
- data/spec/acceptance/raw-text/UTF_8.tmpl +12 -0
- data/spec/acceptance/raw-text/empty_file.expected +0 -0
- data/spec/acceptance/raw-text/empty_file.tmpl +0 -0
- data/spec/acceptance/raw-text/multi_line.expected +4 -0
- data/spec/acceptance/raw-text/multi_line.tmpl +4 -0
- data/spec/acceptance/raw-text/single_line.expected +1 -0
- data/spec/acceptance/raw-text/single_line.tmpl +1 -0
- data/spec/acceptance/raw-text/single_line_whitespace.expected +1 -0
- data/spec/acceptance/raw-text/single_line_whitespace.tmpl +1 -0
- data/spec/acceptance/ruby/ruby_directive_is_just_like_silent.expected +1 -0
- data/spec/acceptance/ruby/ruby_directive_is_just_like_silent.tmpl +4 -0
- data/spec/acceptance/ruby/ruby_directive_using_here_doc.expected +1 -0
- data/spec/acceptance/ruby/ruby_directive_using_here_doc.tmpl +4 -0
- data/spec/acceptance/ruby/ruby_directive_using_here_doc_alt_syntax.expected +1 -0
- data/spec/acceptance/ruby/ruby_directive_using_here_doc_alt_syntax.tmpl +4 -0
- data/spec/acceptance/ruby/ruby_directive_with_accumulate.expected +1 -0
- data/spec/acceptance/ruby/ruby_directive_with_accumulate.tmpl +4 -0
- data/spec/acceptance/ruby/ruby_directive_with_accumulate_and_block.expected +1 -0
- data/spec/acceptance/ruby/ruby_directive_with_accumulate_and_block.tmpl +6 -0
- data/spec/acceptance/set/unused_set.expected +0 -0
- data/spec/acceptance/set/unused_set.tmpl +1 -0
- data/spec/acceptance/set/used_set.expected +1 -0
- data/spec/acceptance/set/used_set.tmpl +2 -0
- data/spec/acceptance/silent/silent_and_echo_combined.expected +1 -0
- data/spec/acceptance/silent/silent_and_echo_combined.tmpl +2 -0
- data/spec/acceptance/silent/silent_short_notation.expected +1 -0
- data/spec/acceptance/silent/silent_short_notation.tmpl +1 -0
- data/spec/acceptance/silent/simple_silent_directive.expected +0 -0
- data/spec/acceptance/silent/simple_silent_directive.tmpl +1 -0
- data/spec/acceptance/slurp/basic_slurp_demo.expected +1 -0
- data/spec/acceptance/slurp/basic_slurp_demo.tmpl +4 -0
- data/spec/acceptance/super/super_with_no_effect.expected +4 -0
- data/spec/acceptance/super/super_with_no_effect.tmpl +5 -0
- data/spec/additions/module_spec.rb +126 -0
- data/spec/additions/string_spec.rb +99 -0
- data/spec/compiler_spec.rb +55 -0
- data/spec/grammar/additions/proc_spec.rb +25 -0
- data/spec/grammar/additions/regexp_spec.rb +37 -0
- data/spec/grammar/additions/string_spec.rb +106 -0
- data/spec/grammar/and_predicate_spec.rb +29 -0
- data/spec/grammar/continuation_wrapper_exception_spec.rb +23 -0
- data/spec/grammar/match_data_wrapper_spec.rb +41 -0
- data/spec/grammar/memoizing_cache_spec.rb +112 -0
- data/spec/grammar/node_spec.rb +126 -0
- data/spec/grammar/not_predicate_spec.rb +29 -0
- data/spec/grammar/parser_state_spec.rb +172 -0
- data/spec/grammar/parslet_choice_spec.rb +49 -0
- data/spec/grammar/parslet_combining_spec.rb +287 -0
- data/spec/grammar/parslet_merge_spec.rb +33 -0
- data/spec/grammar/parslet_omission_spec.rb +58 -0
- data/spec/grammar/parslet_repetition_spec.rb +77 -0
- data/spec/grammar/parslet_sequence_spec.rb +49 -0
- data/spec/grammar/parslet_spec.rb +23 -0
- data/spec/grammar/predicate_spec.rb +53 -0
- data/spec/grammar/proc_parslet_spec.rb +52 -0
- data/spec/grammar/regexp_parslet_spec.rb +347 -0
- data/spec/grammar/string_enumerator_spec.rb +94 -0
- data/spec/grammar/string_parslet_spec.rb +143 -0
- data/spec/grammar/symbol_parslet_spec.rb +30 -0
- data/spec/grammar_spec.rb +545 -0
- data/spec/parser_spec.rb +1418 -0
- data/spec/spec_helper.rb +34 -0
- data/spec/walrus_grammar/comment_spec.rb +39 -0
- data/spec/walrus_grammar/echo_directive_spec.rb +63 -0
- data/spec/walrus_grammar/escape_sequence_spec.rb +85 -0
- data/spec/walrus_grammar/literal_spec.rb +41 -0
- data/spec/walrus_grammar/message_expression_spec.rb +37 -0
- data/spec/walrus_grammar/multiline_comment_spec.rb +58 -0
- data/spec/walrus_grammar/placeholder_spec.rb +48 -0
- data/spec/walrus_grammar/raw_directive_spec.rb +81 -0
- data/spec/walrus_grammar/raw_text_spec.rb +65 -0
- data/spec/walrus_grammar/silent_directive_spec.rb +34 -0
- metadata +291 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# Copyright 2007 Wincent Colaiuta
|
|
2
|
+
# This program is distributed in the hope that it will be useful, but WITHOUT
|
|
3
|
+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
4
|
+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
5
|
+
# in the accompanying file, "LICENSE.txt", for more details.
|
|
6
|
+
#
|
|
7
|
+
# $Id: /mirrors/Walrus/trunk/walrus/spec/grammar/additions/string_spec.rb 6702 2007-04-09T15:04:40.448669Z wincent $
|
|
8
|
+
|
|
9
|
+
require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper.rb')
|
|
10
|
+
|
|
11
|
+
module Walrus
|
|
12
|
+
class Grammar
|
|
13
|
+
|
|
14
|
+
describe 'iterating over a string' do
|
|
15
|
+
|
|
16
|
+
# formerly a bug: the StringScanner used under the covers was returnin nil (stopping) on hitting a newline
|
|
17
|
+
it 'should be able to iterate over strings containing newlines' do
|
|
18
|
+
chars = []
|
|
19
|
+
"hello\nworld".each_char { |c| chars << c }
|
|
20
|
+
chars.length.should == 11
|
|
21
|
+
chars[0].should == 'h'
|
|
22
|
+
chars[1].should == 'e'
|
|
23
|
+
chars[2].should == 'l'
|
|
24
|
+
chars[3].should == 'l'
|
|
25
|
+
chars[4].should == 'o'
|
|
26
|
+
chars[5].should == "\n"
|
|
27
|
+
chars[6].should == 'w'
|
|
28
|
+
chars[7].should == 'o'
|
|
29
|
+
chars[8].should == 'r'
|
|
30
|
+
chars[9].should == 'l'
|
|
31
|
+
chars[10].should == 'd'
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
describe 'working with Unicode strings' do
|
|
37
|
+
|
|
38
|
+
setup do
|
|
39
|
+
@string = 'Unicode €!' # € (Euro) is a three-byte UTF-8 glyph: "\342\202\254"
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it 'the "each_char" method should work with multibyte characters' do
|
|
43
|
+
chars = []
|
|
44
|
+
@string.each_char { |c| chars << c }
|
|
45
|
+
chars.length.should == 10
|
|
46
|
+
chars[0].should == 'U'
|
|
47
|
+
chars[1].should == 'n'
|
|
48
|
+
chars[2].should == 'i'
|
|
49
|
+
chars[3].should == 'c'
|
|
50
|
+
chars[4].should == 'o'
|
|
51
|
+
chars[5].should == 'd'
|
|
52
|
+
chars[6].should == 'e'
|
|
53
|
+
chars[7].should == ' '
|
|
54
|
+
chars[8].should == '€'
|
|
55
|
+
chars[9].should == '!'
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it 'the "chars" method should work with multibyte characters' do
|
|
59
|
+
@string.chars.should == ['U', 'n', 'i', 'c', 'o', 'd', 'e', ' ', '€', '!']
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it 'should be able to use "enumerator" convenience method to get a string enumerator' do
|
|
63
|
+
enumerator = 'hello€'.enumerator
|
|
64
|
+
enumerator.next.should == 'h'
|
|
65
|
+
enumerator.next.should == 'e'
|
|
66
|
+
enumerator.next.should == 'l'
|
|
67
|
+
enumerator.next.should == 'l'
|
|
68
|
+
enumerator.next.should == 'o'
|
|
69
|
+
enumerator.next.should == '€'
|
|
70
|
+
enumerator.next.should be_nil
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it 'the "jlength" method should correctly report the number of characters in a string' do
|
|
74
|
+
@string.jlength.should == 10
|
|
75
|
+
"€".jlength.should == 1 # three bytes long, but one character
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# For more detailed specification of the StringParslet behaviour see string_parslet_spec.rb.
|
|
81
|
+
describe 'using shorthand to get StringParslets from String instances' do
|
|
82
|
+
|
|
83
|
+
it 'chaining two Strings with the "&" operator should yield a two-element sequence' do
|
|
84
|
+
sequence = 'foo' & 'bar'
|
|
85
|
+
sequence.parse('foobar').should == ['foo', 'bar']
|
|
86
|
+
lambda { sequence.parse('no match') }.should raise_error(ParseError)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
it 'chaining three Strings with the "&" operator should yield a three-element sequence' do
|
|
90
|
+
sequence = 'foo' & 'bar' & '...'
|
|
91
|
+
sequence.parse('foobar...').should == ['foo', 'bar', '...']
|
|
92
|
+
lambda { sequence.parse('no match') }.should raise_error(ParseError)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
it 'alternating two Strings with the "|" operator should yield a single string' do
|
|
96
|
+
sequence = 'foo' | 'bar'
|
|
97
|
+
sequence.parse('foo').should == 'foo'
|
|
98
|
+
sequence.parse('foobar').should == 'foo'
|
|
99
|
+
sequence.parse('bar').should == 'bar'
|
|
100
|
+
lambda { sequence.parse('no match') }.should raise_error(ParseError)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
end # class Grammar
|
|
106
|
+
end # module Walrus
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Copyright 2007 Wincent Colaiuta
|
|
2
|
+
# This program is distributed in the hope that it will be useful, but WITHOUT
|
|
3
|
+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
4
|
+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
5
|
+
# in the accompanying file, "LICENSE.txt", for more details.
|
|
6
|
+
#
|
|
7
|
+
# $Id: /mirrors/Walrus/trunk/walrus/spec/grammar/and_predicate_spec.rb 6702 2007-04-09T15:04:40.448669Z wincent $
|
|
8
|
+
|
|
9
|
+
require File.join(File.dirname(__FILE__), '..', 'spec_helper.rb')
|
|
10
|
+
|
|
11
|
+
module Walrus
|
|
12
|
+
class Grammar
|
|
13
|
+
|
|
14
|
+
describe 'using an "and predicate"' do
|
|
15
|
+
|
|
16
|
+
it 'should complain on trying to parse a nil string' do
|
|
17
|
+
lambda { AndPredicate.new('irrelevant').parse(nil) }.should raise_error(ArgumentError)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it 'should be able to compare for equality' do
|
|
21
|
+
AndPredicate.new('foo').should eql(AndPredicate.new('foo')) # same
|
|
22
|
+
AndPredicate.new('foo').should_not eql(AndPredicate.new('bar')) # different
|
|
23
|
+
AndPredicate.new('foo').should_not eql(Predicate.new('foo')) # same, but different classes
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
end # class Grammar
|
|
29
|
+
end # module Walrus
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Copyright 2007 Wincent Colaiuta
|
|
2
|
+
# This program is distributed in the hope that it will be useful, but WITHOUT
|
|
3
|
+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
4
|
+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
5
|
+
# in the accompanying file, "LICENSE.txt", for more details.
|
|
6
|
+
#
|
|
7
|
+
# $Id: /mirrors/Walrus/trunk/walrus/spec/grammar/continuation_wrapper_exception_spec.rb 6702 2007-04-09T15:04:40.448669Z wincent $
|
|
8
|
+
|
|
9
|
+
require File.join(File.dirname(__FILE__), '..', 'spec_helper.rb')
|
|
10
|
+
|
|
11
|
+
module Walrus
|
|
12
|
+
class Grammar
|
|
13
|
+
|
|
14
|
+
describe 'creating a continuation wrapper exception' do
|
|
15
|
+
|
|
16
|
+
it 'should complain if initialized with nil' do
|
|
17
|
+
lambda { ContinuationWrapperException.new(nil) }.should raise_error(ArgumentError)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
end # class Grammar
|
|
23
|
+
end # module Walrus
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Copyright 2007 Wincent Colaiuta
|
|
2
|
+
# This program is distributed in the hope that it will be useful, but WITHOUT
|
|
3
|
+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
4
|
+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
5
|
+
# in the accompanying file, "LICENSE.txt", for more details.
|
|
6
|
+
#
|
|
7
|
+
# $Id: /mirrors/Walrus/trunk/walrus/spec/grammar/match_data_wrapper_spec.rb 6702 2007-04-09T15:04:40.448669Z wincent $
|
|
8
|
+
|
|
9
|
+
require File.join(File.dirname(__FILE__), '..', 'spec_helper.rb')
|
|
10
|
+
|
|
11
|
+
module Walrus
|
|
12
|
+
class Grammar
|
|
13
|
+
|
|
14
|
+
describe 'using a match data object' do
|
|
15
|
+
|
|
16
|
+
setup do
|
|
17
|
+
'hello agent' =~ /(\w+)(\s+)(\w+)/
|
|
18
|
+
@match = MatchDataWrapper.new($~)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it 'should raise if initialized with nil' do
|
|
22
|
+
lambda { MatchDataWrapper.new(nil) }.should raise_error(ArgumentError)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it 'stored match data should persist after multiple matches are executed' do
|
|
26
|
+
original = @match.match_data # store original value
|
|
27
|
+
'foo' =~ /foo/ # clobber $~
|
|
28
|
+
@match.match_data.should == original # confirm that stored value is still intact
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it 'comparisons with Strings should work automatically without having to call the "to_s" method' do
|
|
32
|
+
@match.should == 'hello agent' # normal order
|
|
33
|
+
'hello agent'.should == @match # reverse order
|
|
34
|
+
@match.should_not == 'foobar' # inverse test sense (not equal)
|
|
35
|
+
'foobar'.should_not == @match
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
end # class Grammar
|
|
41
|
+
end # module Walrus
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# Copyright 2007 Wincent Colaiuta
|
|
2
|
+
# This program is distributed in the hope that it will be useful, but WITHOUT
|
|
3
|
+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
4
|
+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
5
|
+
# in the accompanying file, "LICENSE.txt", for more details.
|
|
6
|
+
#
|
|
7
|
+
# $Id: /mirrors/Walrus/trunk/walrus/spec/grammar/memoizing_cache_spec.rb 6702 2007-04-09T15:04:40.448669Z wincent $
|
|
8
|
+
|
|
9
|
+
require File.join(File.dirname(__FILE__), '..', 'spec_helper.rb')
|
|
10
|
+
|
|
11
|
+
module Walrus
|
|
12
|
+
class Grammar
|
|
13
|
+
|
|
14
|
+
class MemoizingCache
|
|
15
|
+
|
|
16
|
+
describe 'using the NoValueForKey class' do
|
|
17
|
+
|
|
18
|
+
it 'NoValueForKey should be a singleton' do
|
|
19
|
+
lambda { NoValueForKey.new }.should raise_error
|
|
20
|
+
NoValueForKey.instance.object_id.should == NoValueForKey.instance.object_id
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it 'should be able to use NoValueForKey as the default value for a hash' do
|
|
24
|
+
hash = Hash.new(NoValueForKey.instance)
|
|
25
|
+
hash.default.should == NoValueForKey.instance
|
|
26
|
+
hash[:foo].should == NoValueForKey.instance
|
|
27
|
+
hash[:foo] = 'bar'
|
|
28
|
+
hash[:foo].should == 'bar'
|
|
29
|
+
hash[:bar].should == NoValueForKey.instance
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
describe 'using a memoizing cache' do
|
|
37
|
+
|
|
38
|
+
it 'should be able to parse with memoizing turned on' do
|
|
39
|
+
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it 'should be able to parse with memoizing turned on' do
|
|
43
|
+
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it 'parsing with memoization turned on should be faster' do
|
|
47
|
+
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# left-recursion is enabled by code in the memoizer and elsewhere; keep the specs here for want of a better place
|
|
53
|
+
describe 'working with left-recursive rules' do
|
|
54
|
+
|
|
55
|
+
it 'circular rules should cause a short-circuit' do
|
|
56
|
+
grammar = Grammar.subclass('InfiniteLoop') do
|
|
57
|
+
starting_symbol :a
|
|
58
|
+
rule :a, :a # a bone-headed rule
|
|
59
|
+
end
|
|
60
|
+
lambda { grammar.parse('anything') }.should raise_error(LeftRecursionException)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it 'shortcuiting should not be fatal if a valid alternative is present' do
|
|
64
|
+
grammar = Grammar.subclass('AlmostInfinite') do
|
|
65
|
+
starting_symbol :a
|
|
66
|
+
rule :a, :a | :b # slightly less bone-headed
|
|
67
|
+
rule :b, 'foo'
|
|
68
|
+
end
|
|
69
|
+
grammar.parse('foo').should == 'foo'
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it 'should retry after short-circuiting if valid continuation point' do
|
|
73
|
+
|
|
74
|
+
grammar = Grammar.subclass('MuchMoreRealisticExample') do
|
|
75
|
+
starting_symbol :a
|
|
76
|
+
rule :a, :a & :b | :b
|
|
77
|
+
rule :b, 'foo'
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
# note the right associativity
|
|
81
|
+
grammar.parse('foo').should == 'foo'
|
|
82
|
+
grammar.parse('foofoo').should == ['foo', 'foo']
|
|
83
|
+
grammar.parse('foofoofoo').should == [['foo', 'foo'], 'foo']
|
|
84
|
+
grammar.parse('foofoofoofoo').should == [[['foo', 'foo'], 'foo'], 'foo']
|
|
85
|
+
grammar.parse('foofoofoofoofoo').should == [[[['foo', 'foo'], 'foo'], 'foo'], 'foo']
|
|
86
|
+
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
it 'right associativity should work when building AST nodes' do
|
|
90
|
+
|
|
91
|
+
grammar = Grammar.subclass('RightAssociativeAdditionExample') do
|
|
92
|
+
starting_symbol :addition_expression
|
|
93
|
+
rule :term, /\d+/
|
|
94
|
+
rule :addition_expression, :addition_expression & '+'.skip & :term | :term
|
|
95
|
+
production :addition_expression.build(:node, :left, :right)
|
|
96
|
+
|
|
97
|
+
# TODO: syntax for expressing alternate production?
|
|
98
|
+
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
end # class Grammar
|
|
112
|
+
end # module Walrus
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# Copyright 2007 Wincent Colaiuta
|
|
2
|
+
# This program is distributed in the hope that it will be useful, but WITHOUT
|
|
3
|
+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
4
|
+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
5
|
+
# in the accompanying file, "LICENSE.txt", for more details.
|
|
6
|
+
#
|
|
7
|
+
# $Id: /mirrors/Walrus/trunk/walrus/spec/grammar/node_spec.rb 6702 2007-04-09T15:04:40.448669Z wincent $
|
|
8
|
+
|
|
9
|
+
require File.join(File.dirname(__FILE__), '..', 'spec_helper.rb')
|
|
10
|
+
|
|
11
|
+
module Walrus
|
|
12
|
+
class Grammar
|
|
13
|
+
|
|
14
|
+
describe 'working in the default namespace' do
|
|
15
|
+
|
|
16
|
+
it 'should complain if passed nil as subclass name' do
|
|
17
|
+
lambda { Node.subclass(nil) }.should raise_error(ArgumentError)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it 'should be able to create a Node subclass (default namespace)' do
|
|
21
|
+
|
|
22
|
+
# passing a string
|
|
23
|
+
Node.subclass('FooNode').should_not be_nil
|
|
24
|
+
FooNode.class.should == Class # meta class
|
|
25
|
+
FooNode.new('blah').class.should == FooNode
|
|
26
|
+
|
|
27
|
+
# passing a symbol
|
|
28
|
+
Node.subclass(:BarNode).should_not be_nil
|
|
29
|
+
BarNode.class.should == Class # meta class
|
|
30
|
+
BarNode.new('blah').class.should == BarNode
|
|
31
|
+
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it 'should be able to create a Node subclass (explicit namespace, Walrus::Grammar)' do
|
|
35
|
+
|
|
36
|
+
# default accessor, lexeme
|
|
37
|
+
Node.subclass('ExplicitNamespaceNode', Walrus::Grammar).should_not be_nil
|
|
38
|
+
ExplicitNamespaceNode.new('hi').lexeme.should == 'hi'
|
|
39
|
+
|
|
40
|
+
# override default accessor
|
|
41
|
+
Node.subclass('ExplicitNamespaceNode2', Walrus::Grammar, :foo).should_not be_nil
|
|
42
|
+
ExplicitNamespaceNode2.new('hi').foo.should == 'hi'
|
|
43
|
+
|
|
44
|
+
# multiple accessors
|
|
45
|
+
Node.subclass('ExplicitNamespaceNode3', Walrus::Grammar, :foo, :bar).should_not be_nil
|
|
46
|
+
n = ExplicitNamespaceNode3.new('hi', 'world')
|
|
47
|
+
n.foo.should == 'hi'
|
|
48
|
+
n.bar.should == 'world'
|
|
49
|
+
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it 'should be able to create a Node subclass (totally custom namespace)' do
|
|
53
|
+
|
|
54
|
+
# default accessor, lexeme
|
|
55
|
+
Node.subclass('CustomNamespaceNode', Walrus).should_not be_nil
|
|
56
|
+
CustomNamespaceNode.new('hi').lexeme.should == 'hi'
|
|
57
|
+
|
|
58
|
+
# override default accessor
|
|
59
|
+
Node.subclass('CustomNamespaceNode2', Walrus, :foo).should_not be_nil
|
|
60
|
+
CustomNamespaceNode2.new('hi').foo.should == 'hi'
|
|
61
|
+
|
|
62
|
+
# multiple accessors
|
|
63
|
+
Node.subclass('CustomNamespaceNode3', Walrus, :foo, :bar).should_not be_nil
|
|
64
|
+
n = CustomNamespaceNode3.new('hi', 'world')
|
|
65
|
+
n.foo.should == 'hi'
|
|
66
|
+
n.bar.should == 'world'
|
|
67
|
+
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
it 'read accessors should work on a Node subclasses' do
|
|
71
|
+
|
|
72
|
+
# default accessor, lexeme
|
|
73
|
+
Node.subclass('AmazingNode')
|
|
74
|
+
AmazingNode.new('xyz').lexeme.should == 'xyz'
|
|
75
|
+
|
|
76
|
+
# single custom accessor
|
|
77
|
+
Node.subclass('AmazingerNode', Walrus::Grammar, :foo)
|
|
78
|
+
AmazingerNode.new('bar').foo.should == 'bar'
|
|
79
|
+
|
|
80
|
+
# two custom accessors
|
|
81
|
+
Node.subclass('AmazingestNode', Walrus::Grammar, :bar, :baz)
|
|
82
|
+
node = AmazingestNode.new('hello', 'world')
|
|
83
|
+
node.bar.should == 'hello'
|
|
84
|
+
node.baz.should == 'world'
|
|
85
|
+
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
it 'should complain if initialize called with missing arguments' do
|
|
89
|
+
|
|
90
|
+
# default accessor, lexeme
|
|
91
|
+
Node.subclass('AmazingNode2')
|
|
92
|
+
lambda { AmazingNode2.new }.should raise_error(ArgumentError)
|
|
93
|
+
|
|
94
|
+
# single custom accessor
|
|
95
|
+
Node.subclass('AmazingerNode2', Walrus::Grammar, :foo)
|
|
96
|
+
lambda { AmazingerNode2.new }.should raise_error(ArgumentError)
|
|
97
|
+
|
|
98
|
+
# two custom accessors
|
|
99
|
+
Node.subclass('AmazingestNode2', Walrus::Grammar, :bar, :baz)
|
|
100
|
+
lambda { AmazingestNode2.new }.should raise_error(ArgumentError) # missing both arguments
|
|
101
|
+
lambda { AmazingestNode2.new('hello') }.should raise_error(ArgumentError) # missing one argument
|
|
102
|
+
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
it 'should be able to subclass a Node subclass' do
|
|
106
|
+
|
|
107
|
+
Node.subclass('FirstSubclass')
|
|
108
|
+
FirstSubclass.subclass('Grandchild').should_not be_nil
|
|
109
|
+
Grandchild.new('foo').class.should == Grandchild
|
|
110
|
+
Grandchild.new('hello').lexeme.should == 'hello'
|
|
111
|
+
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
it 'read accessors should work on a subclass of a Node subclass' do
|
|
115
|
+
Node.subclass('MySubclass')
|
|
116
|
+
MySubclass.subclass('OtherSubclass', Walrus::Grammar, :from, :to).should_not be_nil
|
|
117
|
+
s = OtherSubclass.new('Bob', 'Alice')
|
|
118
|
+
s.from.should == 'Bob'
|
|
119
|
+
s.to.should == 'Alice'
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
end # class Grammar
|
|
125
|
+
end # module Walrus
|
|
126
|
+
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Copyright 2007 Wincent Colaiuta
|
|
2
|
+
# This program is distributed in the hope that it will be useful, but WITHOUT
|
|
3
|
+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
4
|
+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
5
|
+
# in the accompanying file, "LICENSE.txt", for more details.
|
|
6
|
+
#
|
|
7
|
+
# $Id: /mirrors/Walrus/trunk/walrus/spec/grammar/not_predicate_spec.rb 6702 2007-04-09T15:04:40.448669Z wincent $
|
|
8
|
+
|
|
9
|
+
require File.join(File.dirname(__FILE__), '..', 'spec_helper.rb')
|
|
10
|
+
|
|
11
|
+
module Walrus
|
|
12
|
+
class Grammar
|
|
13
|
+
|
|
14
|
+
describe 'using a "not predicate"' do
|
|
15
|
+
|
|
16
|
+
it 'should complain on trying to parse a nil string' do
|
|
17
|
+
lambda { NotPredicate.new('irrelevant').parse(nil) }.should raise_error(ArgumentError)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it 'should be able to compare for equality' do
|
|
21
|
+
NotPredicate.new('foo').should eql(NotPredicate.new('foo')) # same
|
|
22
|
+
NotPredicate.new('foo').should_not eql(NotPredicate.new('bar')) # different
|
|
23
|
+
NotPredicate.new('foo').should_not eql(Predicate.new('foo')) # same, but different classes
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
end # class Grammar
|
|
29
|
+
end # module Walrus
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# Copyright 2007 Wincent Colaiuta
|
|
2
|
+
# This program is distributed in the hope that it will be useful, but WITHOUT
|
|
3
|
+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
4
|
+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
5
|
+
# in the accompanying file, "LICENSE.txt", for more details.
|
|
6
|
+
#
|
|
7
|
+
# $Id: /mirrors/Walrus/trunk/walrus/spec/grammar/parser_state_spec.rb 6702 2007-04-09T15:04:40.448669Z wincent $
|
|
8
|
+
|
|
9
|
+
require File.join(File.dirname(__FILE__), '..', 'spec_helper.rb')
|
|
10
|
+
|
|
11
|
+
module Walrus
|
|
12
|
+
class Grammar
|
|
13
|
+
|
|
14
|
+
describe 'using a parser state object' do
|
|
15
|
+
|
|
16
|
+
setup do
|
|
17
|
+
@base_string = 'this is the string to be parsed'
|
|
18
|
+
@state = ParserState.new(@base_string)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it 'should raise an ArgumentError if initialized with nil' do
|
|
22
|
+
lambda { ParserState.new(nil) }.should raise_error(ArgumentError)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it 'before parsing has started "remainder" should equal the entire string' do
|
|
26
|
+
@state.remainder.should == @base_string
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it 'before parsing has started "remainder" should equal the entire string (when string is an empty string)' do
|
|
30
|
+
ParserState.new('').remainder.should == ''
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it 'before parsing has started "results" should be empty' do
|
|
34
|
+
@state.results.should be_empty
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it '"parsed" should complain if passed nil' do
|
|
38
|
+
lambda { @state.parsed(nil) }.should raise_error(ArgumentError)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it '"skipped" should complain if passed nil' do
|
|
42
|
+
lambda { @state.skipped(nil) }.should raise_error(ArgumentError)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it '"parsed" should return the remainder of the string' do
|
|
46
|
+
@state.parsed('this is the ').should == 'string to be parsed'
|
|
47
|
+
@state.parsed('string ').should == 'to be parsed'
|
|
48
|
+
@state.parsed('to be parsed').should == ''
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it '"skipped" should return the remainder of the string' do
|
|
52
|
+
@state.skipped('this is the ').should == 'string to be parsed'
|
|
53
|
+
@state.skipped('string ').should == 'to be parsed'
|
|
54
|
+
@state.skipped('to be parsed').should == ''
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it '"results" should return an unwrapped parsed result (for single results)' do
|
|
58
|
+
@state.parsed('this')
|
|
59
|
+
@state.results.should == 'this'
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it 'skipped substrings should not appear in "results"' do
|
|
63
|
+
@state.skipped('this')
|
|
64
|
+
@state.results.should be_empty
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
it 'should return an array of the parsed results (for multiple results)' do
|
|
68
|
+
@state.parsed('this ')
|
|
69
|
+
@state.parsed('is ')
|
|
70
|
+
@state.results.should == ['this ', 'is ']
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it 'should work when the entire string is consumed in a single operation (using "parsed")' do
|
|
74
|
+
@state.parsed(@base_string).should == ''
|
|
75
|
+
@state.results.should == @base_string
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
it 'should work when the entire string is consumed in a single operation (using "skipped")' do
|
|
79
|
+
@state.skipped(@base_string).should == ''
|
|
80
|
+
@state.results.should be_empty
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
it '"parsed" should complain if passed something that doesn\'t respond to the "line_end" and "column_end" messages' do
|
|
84
|
+
|
|
85
|
+
# line_end
|
|
86
|
+
my_mock = mock('mock_which_does_not_implement_line_end', :null_object => true)
|
|
87
|
+
my_mock.should_receive(:line_end).and_raise(NoMethodError)
|
|
88
|
+
lambda { @state.parsed(my_mock) }.should raise_error(NoMethodError)
|
|
89
|
+
|
|
90
|
+
# column_end
|
|
91
|
+
my_mock = mock('mock_which_does_not_implement_column_end', :null_object => true)
|
|
92
|
+
my_mock.should_receive(:column_end).and_raise(NoMethodError)
|
|
93
|
+
lambda { @state.parsed(my_mock) }.should raise_error(NoMethodError)
|
|
94
|
+
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
it '"skipped" should complain if passed something that doesn\'t respond to the "line_end" and "column_end" messages' do
|
|
98
|
+
|
|
99
|
+
# line_end
|
|
100
|
+
my_mock = mock('mock_which_does_not_implement_line_end', :null_object => true)
|
|
101
|
+
my_mock.should_receive(:line_end).and_raise(NoMethodError)
|
|
102
|
+
lambda { @state.skipped(my_mock) }.should raise_error(NoMethodError)
|
|
103
|
+
|
|
104
|
+
# column_end
|
|
105
|
+
my_mock = mock('mock_which_does_not_implement_column_end', :null_object => true)
|
|
106
|
+
my_mock.should_receive(:column_end).and_raise(NoMethodError)
|
|
107
|
+
lambda { @state.skipped(my_mock) }.should raise_error(NoMethodError)
|
|
108
|
+
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
it 'should be able to mix use of "parsed" and "skipped" methods' do
|
|
112
|
+
|
|
113
|
+
# first example
|
|
114
|
+
@state.skipped('this is the ').should == 'string to be parsed'
|
|
115
|
+
@state.results.should be_empty
|
|
116
|
+
@state.parsed('string ').should == 'to be parsed'
|
|
117
|
+
@state.results.should == 'string '
|
|
118
|
+
@state.skipped('to be parsed').should == ''
|
|
119
|
+
@state.results.should == 'string '
|
|
120
|
+
|
|
121
|
+
# second example (add this test to isolate a bug in another specification)
|
|
122
|
+
state = ParserState.new('foo1...')
|
|
123
|
+
state.skipped('foo').should == '1...'
|
|
124
|
+
state.remainder.should == '1...'
|
|
125
|
+
state.results.should be_empty
|
|
126
|
+
state.parsed('1').should == '...'
|
|
127
|
+
state.remainder.should == '...'
|
|
128
|
+
state.results.should == '1'
|
|
129
|
+
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
it '"parsed" and "results" methods should work with multi-byte Unicode strings' do
|
|
133
|
+
|
|
134
|
+
# basic test
|
|
135
|
+
state = ParserState.new('400€, foo')
|
|
136
|
+
state.remainder.should == '400€, foo'
|
|
137
|
+
state.parsed('40').should == '0€, foo'
|
|
138
|
+
state.results.should == '40'
|
|
139
|
+
state.parsed('0€, ').should == 'foo'
|
|
140
|
+
state.results.should == ['40', '0€, ']
|
|
141
|
+
state.parsed('foo').should == ''
|
|
142
|
+
state.results.should == ['40', '0€, ', 'foo']
|
|
143
|
+
|
|
144
|
+
# test with newlines before and after multi-byte chars
|
|
145
|
+
state = ParserState.new("400\n or more €...\nfoo")
|
|
146
|
+
state.remainder.should == "400\n or more €...\nfoo"
|
|
147
|
+
state.parsed("400\n or more").should == " €...\nfoo"
|
|
148
|
+
state.results.should == "400\n or more"
|
|
149
|
+
state.parsed(' €..').should == ".\nfoo"
|
|
150
|
+
state.results.should == ["400\n or more", ' €..']
|
|
151
|
+
state.parsed(".\nfoo").should == ''
|
|
152
|
+
state.results.should == ["400\n or more", ' €..', ".\nfoo"]
|
|
153
|
+
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
it '"skipped" and "results" methods should work with multi-byte Unicode strings' do
|
|
157
|
+
state = ParserState.new('400€, foo')
|
|
158
|
+
state.remainder.should == '400€, foo'
|
|
159
|
+
state.skipped('4').should == '00€, foo'
|
|
160
|
+
state.results.should be_empty
|
|
161
|
+
state.parsed('0').should == '0€, foo'
|
|
162
|
+
state.results.should == '0'
|
|
163
|
+
state.skipped('0€, ').should == 'foo'
|
|
164
|
+
state.results.should == '0'
|
|
165
|
+
state.parsed('foo').should == ''
|
|
166
|
+
state.results.should == ['0', 'foo']
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
end # class Grammar
|
|
172
|
+
end # module Walrus
|