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
data/spec/parser_spec.rb
ADDED
|
@@ -0,0 +1,1418 @@
|
|
|
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/parser_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
|
+
|
|
13
|
+
describe 'parsing raw text, escape markers and comments' do
|
|
14
|
+
|
|
15
|
+
context_setup do
|
|
16
|
+
@parser = Parser.new()
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it 'should be able to instantiate the parser' do
|
|
20
|
+
@parser.should_not be_nil
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it 'should be able to parse a plaintext string' do
|
|
24
|
+
|
|
25
|
+
# a single word
|
|
26
|
+
result = @parser.parse('foo')
|
|
27
|
+
result.should be_kind_of(WalrusGrammar::RawText)
|
|
28
|
+
result.lexeme.should == 'foo'
|
|
29
|
+
|
|
30
|
+
# multiple words
|
|
31
|
+
result = @parser.parse('foo bar')
|
|
32
|
+
result.should be_kind_of(WalrusGrammar::RawText)
|
|
33
|
+
result.lexeme.should == 'foo bar'
|
|
34
|
+
|
|
35
|
+
# multiple lines
|
|
36
|
+
result = @parser.parse("hello\nworld")
|
|
37
|
+
result.should be_kind_of(WalrusGrammar::RawText)
|
|
38
|
+
result.lexeme.should == "hello\nworld"
|
|
39
|
+
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it 'should be able to parse a comment' do
|
|
43
|
+
|
|
44
|
+
# comment with content
|
|
45
|
+
result = @parser.parse('## hello world')
|
|
46
|
+
result.should be_kind_of(WalrusGrammar::Comment)
|
|
47
|
+
result.lexeme.should == ' hello world'
|
|
48
|
+
|
|
49
|
+
# comment with no content
|
|
50
|
+
result = @parser.parse('##')
|
|
51
|
+
result.should be_kind_of(WalrusGrammar::Comment)
|
|
52
|
+
result.lexeme.should == ''
|
|
53
|
+
|
|
54
|
+
# multi-line comment (empty)
|
|
55
|
+
result = @parser.parse('#**#')
|
|
56
|
+
result.should be_kind_of(WalrusGrammar::Comment)
|
|
57
|
+
result.should be_kind_of(WalrusGrammar::MultilineComment)
|
|
58
|
+
result.content.should == ''
|
|
59
|
+
|
|
60
|
+
# multi-line comment (with content)
|
|
61
|
+
result = @parser.parse('#* hello world *#')
|
|
62
|
+
result.should be_kind_of(WalrusGrammar::MultilineComment)
|
|
63
|
+
result.content.should == ' hello world '
|
|
64
|
+
|
|
65
|
+
# multi-line comment (spanning multiple lines)
|
|
66
|
+
result = @parser.parse("#* hello\nworld *#")
|
|
67
|
+
result.should be_kind_of(WalrusGrammar::MultilineComment)
|
|
68
|
+
result.content.should == " hello\nworld "
|
|
69
|
+
|
|
70
|
+
# multi-line comment (with nested comment)
|
|
71
|
+
result = @parser.parse('#* hello #*world*# *#')
|
|
72
|
+
result.should be_kind_of(WalrusGrammar::MultilineComment)
|
|
73
|
+
result.content[0].should == ' hello '
|
|
74
|
+
result.content[1].should be_kind_of(WalrusGrammar::MultilineComment)
|
|
75
|
+
result.content[1].content.should == 'world'
|
|
76
|
+
result.content[2].should == ' '
|
|
77
|
+
|
|
78
|
+
# multi-line comment (with nested comment, spanning multiple lines)
|
|
79
|
+
result = @parser.parse("#* hello\n#* world\n... *# *#")
|
|
80
|
+
result.should be_kind_of(WalrusGrammar::MultilineComment)
|
|
81
|
+
result.content[0].should == " hello\n"
|
|
82
|
+
result.content[1].should be_kind_of(WalrusGrammar::MultilineComment)
|
|
83
|
+
result.content[1].content.should == " world\n... "
|
|
84
|
+
result.content[2].should == ' '
|
|
85
|
+
|
|
86
|
+
# multi-line comment (with nested single-line comment)
|
|
87
|
+
result = @parser.parse("#* ##hello\n*#")
|
|
88
|
+
result.should be_kind_of(WalrusGrammar::MultilineComment)
|
|
89
|
+
result.content[0].should == ' '
|
|
90
|
+
result.content[1].should be_kind_of(WalrusGrammar::Comment)
|
|
91
|
+
result.content[1].lexeme.should == 'hello' # here the newline gets eaten
|
|
92
|
+
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
it 'should be able to parse an escape marker' do
|
|
96
|
+
|
|
97
|
+
# directive marker
|
|
98
|
+
result = @parser.parse('\\#')
|
|
99
|
+
result.should be_kind_of(WalrusGrammar::EscapeSequence)
|
|
100
|
+
result.lexeme.should == '#'
|
|
101
|
+
|
|
102
|
+
# placeholder marker
|
|
103
|
+
result = @parser.parse('\\$')
|
|
104
|
+
result.should be_kind_of(WalrusGrammar::EscapeSequence)
|
|
105
|
+
result.lexeme.should == '$'
|
|
106
|
+
|
|
107
|
+
# escape marker
|
|
108
|
+
result = @parser.parse('\\\\')
|
|
109
|
+
result.should be_kind_of(WalrusGrammar::EscapeSequence)
|
|
110
|
+
result.lexeme.should == '\\'
|
|
111
|
+
|
|
112
|
+
# multiple escape markers
|
|
113
|
+
result = @parser.parse('\\#\\$\\\\')
|
|
114
|
+
result[0].should be_kind_of(WalrusGrammar::EscapeSequence)
|
|
115
|
+
result[0].lexeme.should == '#'
|
|
116
|
+
result[1].should be_kind_of(WalrusGrammar::EscapeSequence)
|
|
117
|
+
result[1].lexeme.should == '$'
|
|
118
|
+
result[2].should be_kind_of(WalrusGrammar::EscapeSequence)
|
|
119
|
+
result[2].lexeme.should == '\\'
|
|
120
|
+
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
it 'should complain on finding an illegal escape marker' do
|
|
124
|
+
|
|
125
|
+
# invalid character
|
|
126
|
+
lambda { @parser.parse('\\x') }.should raise_error(Grammar::ParseError)
|
|
127
|
+
|
|
128
|
+
# no character
|
|
129
|
+
lambda { @parser.parse('\\') }.should raise_error(Grammar::ParseError)
|
|
130
|
+
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
it 'should be able to mix comments and plain text' do
|
|
134
|
+
|
|
135
|
+
# plain text followed by comment
|
|
136
|
+
result = @parser.parse('foobar ## hello world')
|
|
137
|
+
result[0].should be_kind_of(WalrusGrammar::RawText)
|
|
138
|
+
result[0].lexeme.should == 'foobar '
|
|
139
|
+
result[1].should be_kind_of(WalrusGrammar::Comment)
|
|
140
|
+
result[1].lexeme.should == ' hello world'
|
|
141
|
+
|
|
142
|
+
# comment should only extend up until the next newline
|
|
143
|
+
result = @parser.parse("## hello world\nfoobar")
|
|
144
|
+
result[0].should be_kind_of(WalrusGrammar::Comment)
|
|
145
|
+
result[0].lexeme.should == ' hello world'
|
|
146
|
+
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
it 'should be able to mix escape markers and plain text' do
|
|
150
|
+
|
|
151
|
+
# plain text followed by an escape marker
|
|
152
|
+
result = @parser.parse('hello \\#')
|
|
153
|
+
result[0].should be_kind_of(WalrusGrammar::RawText)
|
|
154
|
+
result[0].lexeme.should == 'hello '
|
|
155
|
+
result[1].should be_kind_of(WalrusGrammar::EscapeSequence)
|
|
156
|
+
result[1].lexeme.should == '#'
|
|
157
|
+
|
|
158
|
+
# an escape marker followed by plain text
|
|
159
|
+
result = @parser.parse('\\$hello')
|
|
160
|
+
result[0].should be_kind_of(WalrusGrammar::EscapeSequence)
|
|
161
|
+
result[0].lexeme.should == '$'
|
|
162
|
+
result[1].should be_kind_of(WalrusGrammar::RawText)
|
|
163
|
+
result[1].lexeme.should == 'hello'
|
|
164
|
+
|
|
165
|
+
# alternation
|
|
166
|
+
result = @parser.parse('hello \\\\ world')
|
|
167
|
+
result[0].should be_kind_of(WalrusGrammar::RawText)
|
|
168
|
+
result[0].lexeme.should == 'hello '
|
|
169
|
+
result[1].should be_kind_of(WalrusGrammar::EscapeSequence)
|
|
170
|
+
result[1].lexeme.should == '\\'
|
|
171
|
+
result[2].should be_kind_of(WalrusGrammar::RawText)
|
|
172
|
+
result[2].lexeme.should == ' world'
|
|
173
|
+
|
|
174
|
+
# with newlines thrown into the mix
|
|
175
|
+
result = @parser.parse("hello\n\\#")
|
|
176
|
+
result[0].should be_kind_of(WalrusGrammar::RawText)
|
|
177
|
+
result[0].lexeme.should == "hello\n"
|
|
178
|
+
result[1].should be_kind_of(WalrusGrammar::EscapeSequence)
|
|
179
|
+
result[1].lexeme.should == '#'
|
|
180
|
+
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
describe 'parsing directives' do
|
|
185
|
+
|
|
186
|
+
context_setup do
|
|
187
|
+
@parser = Parser.new()
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
it 'should complain on encountering an unknown or invalid directive name' do
|
|
191
|
+
lambda { @parser.parse('#glindenburgen') }.should raise_error(Grammar::ParseError)
|
|
192
|
+
lambda { @parser.parse('#') }.should raise_error(Grammar::ParseError)
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
it 'should complain if there is whitespace between the directive marker (#) and the directive name' do
|
|
196
|
+
lambda { @parser.parse('# extends "other_template"') }.should raise_error(Grammar::ParseError)
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
it 'should be able to parse a directive that takes a single parameter' do
|
|
200
|
+
result = @parser.parse('#extends "other_template"')
|
|
201
|
+
result.should be_kind_of(WalrusGrammar::Directive)
|
|
202
|
+
result.should be_kind_of(WalrusGrammar::ExtendsDirective)
|
|
203
|
+
result.class_name.lexeme.should == 'other_template'
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
it 'should be able to follow a directive by a comment on the same line, only if the directive has an explicit termination marker' do
|
|
207
|
+
|
|
208
|
+
# no intervening whitespace ("extends" directive, takes one parameter)
|
|
209
|
+
result = @parser.parse('#extends "other_template"### comment')
|
|
210
|
+
result[0].should be_kind_of(WalrusGrammar::ExtendsDirective)
|
|
211
|
+
result[0].class_name.lexeme.should == 'other_template'
|
|
212
|
+
result[1].should be_kind_of(WalrusGrammar::Comment)
|
|
213
|
+
result[1].lexeme.should == ' comment'
|
|
214
|
+
|
|
215
|
+
# counter-example
|
|
216
|
+
lambda { @parser.parse('#extends "other_template"## comment') }.should raise_error(Grammar::ParseError)
|
|
217
|
+
|
|
218
|
+
# intervening whitespace (between parameter and trailing comment)
|
|
219
|
+
result = @parser.parse('#extends "other_template" ### comment')
|
|
220
|
+
result[0].should be_kind_of(WalrusGrammar::ExtendsDirective)
|
|
221
|
+
result[0].class_name.lexeme.should == 'other_template'
|
|
222
|
+
result[1].should be_kind_of(WalrusGrammar::Comment)
|
|
223
|
+
result[1].lexeme.should == ' comment'
|
|
224
|
+
|
|
225
|
+
# counter-example
|
|
226
|
+
lambda { @parser.parse('#extends "other_template" ## comment') }.should raise_error(Grammar::ParseError)
|
|
227
|
+
|
|
228
|
+
# intervening whitespace (between directive and parameter)
|
|
229
|
+
result = @parser.parse('#extends "other_template" ### comment')
|
|
230
|
+
result[0].should be_kind_of(WalrusGrammar::ExtendsDirective)
|
|
231
|
+
result[0].class_name.lexeme.should == 'other_template'
|
|
232
|
+
result[1].should be_kind_of(WalrusGrammar::Comment)
|
|
233
|
+
result[1].lexeme.should == ' comment'
|
|
234
|
+
|
|
235
|
+
# counter-example
|
|
236
|
+
lambda { @parser.parse('#extends "other_template" ## comment') }.should raise_error(Grammar::ParseError)
|
|
237
|
+
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
it 'should be able to span directives across lines by using a line continuation backslash' do
|
|
241
|
+
|
|
242
|
+
# basic case
|
|
243
|
+
result = @parser.parse("#extends \\\n'other_template'")
|
|
244
|
+
result.should be_kind_of(WalrusGrammar::ExtendsDirective)
|
|
245
|
+
result.class_name.lexeme.should == 'other_template'
|
|
246
|
+
|
|
247
|
+
# should fail if backslash is not the last character on the line
|
|
248
|
+
lambda { @parser.parse("#extends \\ \n'other_template'") }.should raise_error(Grammar::ParseError)
|
|
249
|
+
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
it 'should be able to parse an "import" directive' do
|
|
253
|
+
|
|
254
|
+
# followed by a newline
|
|
255
|
+
result = @parser.parse("#import 'other_template'\nhello")
|
|
256
|
+
result[0].should be_kind_of(WalrusGrammar::ImportDirective)
|
|
257
|
+
result[0].class_name.lexeme.should == 'other_template'
|
|
258
|
+
result[1].should be_kind_of(WalrusGrammar::RawText)
|
|
259
|
+
result[1].lexeme.should == 'hello' # newline gets eaten
|
|
260
|
+
|
|
261
|
+
# followed by whitespace
|
|
262
|
+
result = @parser.parse('#import "other_template" ')
|
|
263
|
+
result.should be_kind_of(WalrusGrammar::ImportDirective)
|
|
264
|
+
result.class_name.lexeme.should == 'other_template'
|
|
265
|
+
|
|
266
|
+
# followed by the end of the input
|
|
267
|
+
result = @parser.parse('#import "other_template"')
|
|
268
|
+
result.should be_kind_of(WalrusGrammar::ImportDirective)
|
|
269
|
+
result.class_name.lexeme.should == 'other_template'
|
|
270
|
+
|
|
271
|
+
# comment with no intervening whitespace
|
|
272
|
+
result = @parser.parse('#import "other_template"### comment')
|
|
273
|
+
result[0].should be_kind_of(WalrusGrammar::ImportDirective)
|
|
274
|
+
result[0].class_name.lexeme.should == 'other_template'
|
|
275
|
+
result[1].should be_kind_of(WalrusGrammar::Comment)
|
|
276
|
+
result[1].lexeme.should == ' comment'
|
|
277
|
+
|
|
278
|
+
# counter-example
|
|
279
|
+
lambda { @parser.parse('#import "other_template"## comment') }.should raise_error(Grammar::ParseError)
|
|
280
|
+
|
|
281
|
+
# intervening whitespace (between parameter and trailing comment)
|
|
282
|
+
result = @parser.parse('#import "other_template" ### comment')
|
|
283
|
+
result[0].should be_kind_of(WalrusGrammar::ImportDirective)
|
|
284
|
+
result[0].class_name.lexeme.should == 'other_template'
|
|
285
|
+
result[1].should be_kind_of(WalrusGrammar::Comment)
|
|
286
|
+
result[1].lexeme.should == ' comment'
|
|
287
|
+
|
|
288
|
+
# counter-example
|
|
289
|
+
lambda { @parser.parse('#import "other_template" ## comment') }.should raise_error(Grammar::ParseError)
|
|
290
|
+
|
|
291
|
+
# intervening whitespace (between directive and parameter)
|
|
292
|
+
result = @parser.parse('#import "other_template" ### comment')
|
|
293
|
+
result[0].should be_kind_of(WalrusGrammar::ImportDirective)
|
|
294
|
+
result[0].class_name.lexeme.should == 'other_template'
|
|
295
|
+
result[1].should be_kind_of(WalrusGrammar::Comment)
|
|
296
|
+
result[1].lexeme.should == ' comment'
|
|
297
|
+
|
|
298
|
+
# counter-example
|
|
299
|
+
lambda { @parser.parse('#import "other_template" ## comment') }.should raise_error(Grammar::ParseError)
|
|
300
|
+
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
it 'should be able to parse single quoted string literals' do
|
|
304
|
+
|
|
305
|
+
# string literals have no special meaning when part of raw text
|
|
306
|
+
result = @parser.parse("'hello'")
|
|
307
|
+
result.should be_kind_of(WalrusGrammar::RawText)
|
|
308
|
+
result.lexeme.should == "'hello'"
|
|
309
|
+
|
|
310
|
+
# empty string
|
|
311
|
+
result = @parser.parse("#import ''")
|
|
312
|
+
result.class_name.should be_kind_of(WalrusGrammar::StringLiteral)
|
|
313
|
+
result.class_name.should be_kind_of(WalrusGrammar::SingleQuotedStringLiteral)
|
|
314
|
+
result.class_name.lexeme.to_s.should == '' # actually just returns []; I might need to add a "flatten" or "to_string" method to my Grammar specification system
|
|
315
|
+
|
|
316
|
+
# with escaped single quotes inside
|
|
317
|
+
result = @parser.parse("#import 'hello \\'world\\''")
|
|
318
|
+
result.class_name.should be_kind_of(WalrusGrammar::StringLiteral)
|
|
319
|
+
result.class_name.should be_kind_of(WalrusGrammar::SingleQuotedStringLiteral)
|
|
320
|
+
result.class_name.lexeme.should == "hello \\'world\\'"
|
|
321
|
+
|
|
322
|
+
# with other escapes inside
|
|
323
|
+
result = @parser.parse("#import 'hello\\nworld'")
|
|
324
|
+
result.class_name.should be_kind_of(WalrusGrammar::StringLiteral)
|
|
325
|
+
result.class_name.should be_kind_of(WalrusGrammar::SingleQuotedStringLiteral)
|
|
326
|
+
result.class_name.lexeme.should == 'hello\nworld'
|
|
327
|
+
|
|
328
|
+
# with double quotes inside
|
|
329
|
+
result = @parser.parse("#import 'hello \"world\"'")
|
|
330
|
+
result.class_name.should be_kind_of(WalrusGrammar::StringLiteral)
|
|
331
|
+
result.class_name.should be_kind_of(WalrusGrammar::SingleQuotedStringLiteral)
|
|
332
|
+
result.class_name.lexeme.should == 'hello "world"'
|
|
333
|
+
|
|
334
|
+
# with Walrus comments inside (ignored)
|
|
335
|
+
result = @parser.parse("#import 'hello ##world'")
|
|
336
|
+
result.class_name.should be_kind_of(WalrusGrammar::StringLiteral)
|
|
337
|
+
result.class_name.should be_kind_of(WalrusGrammar::SingleQuotedStringLiteral)
|
|
338
|
+
result.class_name.lexeme.should == 'hello ##world'
|
|
339
|
+
|
|
340
|
+
# with Walrus placeholders inside (no interpolation)
|
|
341
|
+
result = @parser.parse("#import 'hello $world'")
|
|
342
|
+
result.class_name.should be_kind_of(WalrusGrammar::StringLiteral)
|
|
343
|
+
result.class_name.should be_kind_of(WalrusGrammar::SingleQuotedStringLiteral)
|
|
344
|
+
result.class_name.lexeme.should == 'hello $world'
|
|
345
|
+
|
|
346
|
+
# with Walrus directives inside (no interpolation)
|
|
347
|
+
result = @parser.parse("#import 'hello #end'")
|
|
348
|
+
result.class_name.should be_kind_of(WalrusGrammar::StringLiteral)
|
|
349
|
+
result.class_name.should be_kind_of(WalrusGrammar::SingleQuotedStringLiteral)
|
|
350
|
+
result.class_name.lexeme.should == 'hello #end'
|
|
351
|
+
|
|
352
|
+
end
|
|
353
|
+
|
|
354
|
+
it 'should be able to parse double quoted string literals' do
|
|
355
|
+
|
|
356
|
+
# string literals have no special meaning when part of raw text
|
|
357
|
+
result = @parser.parse('"hello"')
|
|
358
|
+
result.should be_kind_of(WalrusGrammar::RawText)
|
|
359
|
+
result.lexeme.should == '"hello"'
|
|
360
|
+
|
|
361
|
+
# empty string
|
|
362
|
+
result = @parser.parse('#import ""')
|
|
363
|
+
result.class_name.should be_kind_of(WalrusGrammar::StringLiteral)
|
|
364
|
+
result.class_name.should be_kind_of(WalrusGrammar::DoubleQuotedStringLiteral)
|
|
365
|
+
result.class_name.lexeme.to_s.should == '' # actually just returns []; I might need to add a "flatten" or "to_string" method to my Grammar specification system
|
|
366
|
+
|
|
367
|
+
# with escaped double quotes inside
|
|
368
|
+
result = @parser.parse('#import "hello \\"world\\""')
|
|
369
|
+
result.class_name.should be_kind_of(WalrusGrammar::StringLiteral)
|
|
370
|
+
result.class_name.should be_kind_of(WalrusGrammar::DoubleQuotedStringLiteral)
|
|
371
|
+
result.class_name.lexeme.should == 'hello \\"world\\"'
|
|
372
|
+
|
|
373
|
+
# with other escapes inside
|
|
374
|
+
result = @parser.parse('#import "hello\\nworld"')
|
|
375
|
+
result.class_name.should be_kind_of(WalrusGrammar::StringLiteral)
|
|
376
|
+
result.class_name.should be_kind_of(WalrusGrammar::DoubleQuotedStringLiteral)
|
|
377
|
+
result.class_name.lexeme.should == 'hello\\nworld'
|
|
378
|
+
|
|
379
|
+
# with single quotes inside
|
|
380
|
+
result = @parser.parse('#import "hello \'world\'"')
|
|
381
|
+
result.class_name.should be_kind_of(WalrusGrammar::StringLiteral)
|
|
382
|
+
result.class_name.should be_kind_of(WalrusGrammar::DoubleQuotedStringLiteral)
|
|
383
|
+
result.class_name.lexeme.should == "hello 'world'"
|
|
384
|
+
|
|
385
|
+
# with Walrus comments inside (ignored)
|
|
386
|
+
result = @parser.parse('#import "hello ##world"')
|
|
387
|
+
result.class_name.should be_kind_of(WalrusGrammar::StringLiteral)
|
|
388
|
+
result.class_name.should be_kind_of(WalrusGrammar::DoubleQuotedStringLiteral)
|
|
389
|
+
result.class_name.lexeme.should == 'hello ##world'
|
|
390
|
+
|
|
391
|
+
# with Walrus placeholders inside (no interpolation)
|
|
392
|
+
result = @parser.parse('#import "hello $world"')
|
|
393
|
+
result.class_name.should be_kind_of(WalrusGrammar::StringLiteral)
|
|
394
|
+
result.class_name.should be_kind_of(WalrusGrammar::DoubleQuotedStringLiteral)
|
|
395
|
+
result.class_name.lexeme.should == 'hello $world'
|
|
396
|
+
|
|
397
|
+
# with Walrus directives inside (no interpolation)
|
|
398
|
+
result = @parser.parse('#import "hello #end"')
|
|
399
|
+
result.class_name.should be_kind_of(WalrusGrammar::StringLiteral)
|
|
400
|
+
result.class_name.should be_kind_of(WalrusGrammar::DoubleQuotedStringLiteral)
|
|
401
|
+
result.class_name.lexeme.should == 'hello #end'
|
|
402
|
+
|
|
403
|
+
end
|
|
404
|
+
|
|
405
|
+
# will use the #silent directive here because it's an easy way to make the parser look for a ruby expression
|
|
406
|
+
it 'should be able to parse basic Ruby expressions' do
|
|
407
|
+
|
|
408
|
+
# a numeric literal
|
|
409
|
+
result = @parser.parse('#silent 1')
|
|
410
|
+
result.should be_kind_of(WalrusGrammar::Directive)
|
|
411
|
+
result.should be_kind_of(WalrusGrammar::SilentDirective)
|
|
412
|
+
result.expression.should be_kind_of(WalrusGrammar::NumericLiteral)
|
|
413
|
+
result.expression.lexeme.should == '1'
|
|
414
|
+
|
|
415
|
+
# a single-quoted string literal
|
|
416
|
+
result = @parser.parse("#silent 'foo'")
|
|
417
|
+
result.should be_kind_of(WalrusGrammar::Directive)
|
|
418
|
+
result.should be_kind_of(WalrusGrammar::SilentDirective)
|
|
419
|
+
result.expression.should be_kind_of(WalrusGrammar::SingleQuotedStringLiteral)
|
|
420
|
+
result.expression.lexeme.should == 'foo'
|
|
421
|
+
|
|
422
|
+
# a double-quoted string literal
|
|
423
|
+
result = @parser.parse('#silent "foo"')
|
|
424
|
+
result.should be_kind_of(WalrusGrammar::Directive)
|
|
425
|
+
result.should be_kind_of(WalrusGrammar::SilentDirective)
|
|
426
|
+
result.expression.should be_kind_of(WalrusGrammar::DoubleQuotedStringLiteral)
|
|
427
|
+
result.expression.lexeme.should == 'foo'
|
|
428
|
+
|
|
429
|
+
# an identifier
|
|
430
|
+
result = @parser.parse('#silent foo')
|
|
431
|
+
result.should be_kind_of(WalrusGrammar::Directive)
|
|
432
|
+
result.should be_kind_of(WalrusGrammar::SilentDirective)
|
|
433
|
+
result.expression.should be_kind_of(WalrusGrammar::Identifier)
|
|
434
|
+
result.expression.lexeme.should == 'foo'
|
|
435
|
+
|
|
436
|
+
result = @parser.parse('#silent foo_bar')
|
|
437
|
+
result.should be_kind_of(WalrusGrammar::Directive)
|
|
438
|
+
result.should be_kind_of(WalrusGrammar::SilentDirective)
|
|
439
|
+
result.expression.should be_kind_of(WalrusGrammar::Identifier)
|
|
440
|
+
result.expression.lexeme.should == 'foo_bar'
|
|
441
|
+
|
|
442
|
+
# a constant
|
|
443
|
+
result = @parser.parse('#silent Foo')
|
|
444
|
+
result.should be_kind_of(WalrusGrammar::Directive)
|
|
445
|
+
result.should be_kind_of(WalrusGrammar::SilentDirective)
|
|
446
|
+
result.expression.should be_kind_of(WalrusGrammar::Constant)
|
|
447
|
+
result.expression.lexeme.should == 'Foo'
|
|
448
|
+
|
|
449
|
+
result = @parser.parse('#silent FooBar')
|
|
450
|
+
result.should be_kind_of(WalrusGrammar::Directive)
|
|
451
|
+
result.should be_kind_of(WalrusGrammar::SilentDirective)
|
|
452
|
+
result.expression.should be_kind_of(WalrusGrammar::Constant)
|
|
453
|
+
result.expression.lexeme.should == 'FooBar'
|
|
454
|
+
|
|
455
|
+
# a symbol
|
|
456
|
+
result = @parser.parse('#silent :foo')
|
|
457
|
+
result.should be_kind_of(WalrusGrammar::Directive)
|
|
458
|
+
result.should be_kind_of(WalrusGrammar::SilentDirective)
|
|
459
|
+
result.expression.should be_kind_of(WalrusGrammar::SymbolLiteral)
|
|
460
|
+
result.expression.lexeme.should == ':foo'
|
|
461
|
+
|
|
462
|
+
result = @parser.parse('#silent :Foo')
|
|
463
|
+
result.should be_kind_of(WalrusGrammar::Directive)
|
|
464
|
+
result.should be_kind_of(WalrusGrammar::SilentDirective)
|
|
465
|
+
result.expression.should be_kind_of(WalrusGrammar::SymbolLiteral)
|
|
466
|
+
result.expression.lexeme.should == ':Foo'
|
|
467
|
+
|
|
468
|
+
# an array literal
|
|
469
|
+
result = @parser.parse('#silent [1]')
|
|
470
|
+
result.should be_kind_of(WalrusGrammar::Directive)
|
|
471
|
+
result.should be_kind_of(WalrusGrammar::SilentDirective)
|
|
472
|
+
result.expression.should be_kind_of(WalrusGrammar::RubyExpression)
|
|
473
|
+
result.expression.should be_kind_of(WalrusGrammar::ArrayLiteral)
|
|
474
|
+
result.expression.elements.should be_kind_of(WalrusGrammar::NumericLiteral)
|
|
475
|
+
result.expression.elements.lexeme.should == '1'
|
|
476
|
+
|
|
477
|
+
result = @parser.parse('#silent [1, 2, 3]')
|
|
478
|
+
result.should be_kind_of(WalrusGrammar::Directive)
|
|
479
|
+
result.should be_kind_of(WalrusGrammar::SilentDirective)
|
|
480
|
+
result.expression.should be_kind_of(WalrusGrammar::RubyExpression)
|
|
481
|
+
result.expression.should be_kind_of(WalrusGrammar::ArrayLiteral)
|
|
482
|
+
result.expression.elements.should be_kind_of(Array)
|
|
483
|
+
result.expression.elements[0].should be_kind_of(WalrusGrammar::NumericLiteral)
|
|
484
|
+
result.expression.elements[0].lexeme.should == '1'
|
|
485
|
+
result.expression.elements[1].should be_kind_of(WalrusGrammar::NumericLiteral)
|
|
486
|
+
result.expression.elements[1].lexeme.should == '2'
|
|
487
|
+
result.expression.elements[2].should be_kind_of(WalrusGrammar::NumericLiteral)
|
|
488
|
+
result.expression.elements[2].lexeme.should == '3'
|
|
489
|
+
|
|
490
|
+
# a hash literal
|
|
491
|
+
result = @parser.parse('#silent { :foo => "bar" }')
|
|
492
|
+
result.should be_kind_of(WalrusGrammar::Directive)
|
|
493
|
+
result.should be_kind_of(WalrusGrammar::SilentDirective)
|
|
494
|
+
result.expression.should be_kind_of(WalrusGrammar::RubyExpression)
|
|
495
|
+
result.expression.should be_kind_of(WalrusGrammar::HashLiteral)
|
|
496
|
+
result.expression.pairs.should be_kind_of(WalrusGrammar::RubyExpression)
|
|
497
|
+
result.expression.pairs.should be_kind_of(WalrusGrammar::HashAssignment)
|
|
498
|
+
result.expression.pairs.lvalue.should be_kind_of(WalrusGrammar::SymbolLiteral)
|
|
499
|
+
result.expression.pairs.lvalue.lexeme.should == ':foo'
|
|
500
|
+
result.expression.pairs.expression.should be_kind_of(WalrusGrammar::DoubleQuotedStringLiteral)
|
|
501
|
+
result.expression.pairs.expression.lexeme.should == 'bar'
|
|
502
|
+
|
|
503
|
+
result = @parser.parse('#silent { :foo => "bar", :baz => "xyz" }')
|
|
504
|
+
result.expression.should be_kind_of(WalrusGrammar::HashLiteral)
|
|
505
|
+
result.expression.pairs.should be_kind_of(Array)
|
|
506
|
+
result.expression.pairs[0].should be_kind_of(WalrusGrammar::HashAssignment)
|
|
507
|
+
result.expression.pairs[0].lvalue.should be_kind_of(WalrusGrammar::SymbolLiteral)
|
|
508
|
+
result.expression.pairs[0].lvalue.lexeme.should == ':foo'
|
|
509
|
+
result.expression.pairs[0].expression.should be_kind_of(WalrusGrammar::DoubleQuotedStringLiteral)
|
|
510
|
+
result.expression.pairs[0].expression.lexeme.should == 'bar'
|
|
511
|
+
result.expression.pairs[1].should be_kind_of(WalrusGrammar::HashAssignment)
|
|
512
|
+
result.expression.pairs[1].lvalue.should be_kind_of(WalrusGrammar::SymbolLiteral)
|
|
513
|
+
result.expression.pairs[1].lvalue.lexeme.should == ':baz'
|
|
514
|
+
result.expression.pairs[1].expression.should be_kind_of(WalrusGrammar::DoubleQuotedStringLiteral)
|
|
515
|
+
result.expression.pairs[1].expression.lexeme.should == 'xyz'
|
|
516
|
+
|
|
517
|
+
# an addition expression
|
|
518
|
+
result = @parser.parse('#silent 1 + 2')
|
|
519
|
+
result.should be_kind_of(WalrusGrammar::Directive)
|
|
520
|
+
result.should be_kind_of(WalrusGrammar::SilentDirective)
|
|
521
|
+
result.expression.should be_kind_of(WalrusGrammar::RubyExpression)
|
|
522
|
+
result.expression.should be_kind_of(WalrusGrammar::AdditionExpression)
|
|
523
|
+
result.expression.left.should be_kind_of(WalrusGrammar::NumericLiteral)
|
|
524
|
+
result.expression.left.lexeme.should == '1'
|
|
525
|
+
result.expression.right.should be_kind_of(WalrusGrammar::NumericLiteral)
|
|
526
|
+
result.expression.right.lexeme.should == '2'
|
|
527
|
+
|
|
528
|
+
# an assignment expression
|
|
529
|
+
result = @parser.parse('#silent foo = 1')
|
|
530
|
+
result.should be_kind_of(WalrusGrammar::Directive)
|
|
531
|
+
result.should be_kind_of(WalrusGrammar::SilentDirective)
|
|
532
|
+
result.expression.should be_kind_of(WalrusGrammar::RubyExpression)
|
|
533
|
+
result.expression.should be_kind_of(WalrusGrammar::AssignmentExpression)
|
|
534
|
+
result.expression.lvalue.should be_kind_of(WalrusGrammar::Identifier)
|
|
535
|
+
result.expression.lvalue.lexeme.should == 'foo'
|
|
536
|
+
result.expression.expression.should be_kind_of(WalrusGrammar::NumericLiteral)
|
|
537
|
+
result.expression.expression.lexeme.should == '1'
|
|
538
|
+
|
|
539
|
+
# a method invocation
|
|
540
|
+
result = @parser.parse('#silent foo.delete')
|
|
541
|
+
result.should be_kind_of(WalrusGrammar::Directive)
|
|
542
|
+
result.should be_kind_of(WalrusGrammar::SilentDirective)
|
|
543
|
+
result.expression.should be_kind_of(WalrusGrammar::RubyExpression)
|
|
544
|
+
result.expression.should be_kind_of(WalrusGrammar::MessageExpression)
|
|
545
|
+
|
|
546
|
+
result = @parser.parse('#silent foo.delete()')
|
|
547
|
+
result.should be_kind_of(WalrusGrammar::Directive)
|
|
548
|
+
result.should be_kind_of(WalrusGrammar::SilentDirective)
|
|
549
|
+
result.expression.should be_kind_of(WalrusGrammar::MessageExpression)
|
|
550
|
+
result.expression.target.should be_kind_of(WalrusGrammar::Identifier)
|
|
551
|
+
result.expression.target.lexeme.should == 'foo'
|
|
552
|
+
result.expression.message.should be_kind_of(WalrusGrammar::RubyExpression)
|
|
553
|
+
result.expression.message.should be_kind_of(WalrusGrammar::MethodExpression)
|
|
554
|
+
result.expression.message.name.should be_kind_of(WalrusGrammar::Identifier)
|
|
555
|
+
result.expression.message.name.lexeme.should == 'delete'
|
|
556
|
+
result.expression.message.params.should be_kind_of(Array)
|
|
557
|
+
result.expression.message.params.should == []
|
|
558
|
+
|
|
559
|
+
result = @parser.parse('#silent foo.delete(1)')
|
|
560
|
+
result.should be_kind_of(WalrusGrammar::Directive)
|
|
561
|
+
result.should be_kind_of(WalrusGrammar::SilentDirective)
|
|
562
|
+
result.expression.should be_kind_of(WalrusGrammar::MessageExpression)
|
|
563
|
+
result.expression.target.should be_kind_of(WalrusGrammar::Identifier)
|
|
564
|
+
result.expression.target.lexeme.should == 'foo'
|
|
565
|
+
result.expression.message.should be_kind_of(WalrusGrammar::MethodExpression)
|
|
566
|
+
result.expression.message.name.should be_kind_of(WalrusGrammar::Identifier)
|
|
567
|
+
result.expression.message.name.lexeme.should == 'delete'
|
|
568
|
+
result.expression.message.params.should be_kind_of(WalrusGrammar::NumericLiteral)
|
|
569
|
+
result.expression.message.params.lexeme.should == '1'
|
|
570
|
+
|
|
571
|
+
result = @parser.parse('#silent foo.delete(bar, baz)')
|
|
572
|
+
result.should be_kind_of(WalrusGrammar::Directive)
|
|
573
|
+
result.should be_kind_of(WalrusGrammar::SilentDirective)
|
|
574
|
+
result.expression.should be_kind_of(WalrusGrammar::MessageExpression)
|
|
575
|
+
result.expression.target.should be_kind_of(WalrusGrammar::Identifier)
|
|
576
|
+
result.expression.target.lexeme.should == 'foo'
|
|
577
|
+
result.expression.message.should be_kind_of(WalrusGrammar::MethodExpression)
|
|
578
|
+
result.expression.message.name.should be_kind_of(WalrusGrammar::Identifier)
|
|
579
|
+
result.expression.message.name.lexeme.should == 'delete'
|
|
580
|
+
result.expression.message.params.should be_kind_of(Array)
|
|
581
|
+
result.expression.message.params[0].should be_kind_of(WalrusGrammar::Identifier)
|
|
582
|
+
result.expression.message.params[0].lexeme.should == 'bar'
|
|
583
|
+
result.expression.message.params[1].should be_kind_of(WalrusGrammar::Identifier)
|
|
584
|
+
result.expression.message.params[1].lexeme.should == 'baz'
|
|
585
|
+
|
|
586
|
+
# chained method invocation
|
|
587
|
+
result = @parser.parse('#silent foo.bar.baz')
|
|
588
|
+
result.should be_kind_of(WalrusGrammar::Directive)
|
|
589
|
+
result.should be_kind_of(WalrusGrammar::SilentDirective)
|
|
590
|
+
result.expression.should be_kind_of(WalrusGrammar::MessageExpression)
|
|
591
|
+
result.expression.target.should be_kind_of(WalrusGrammar::MessageExpression)
|
|
592
|
+
result.expression.target.target.should be_kind_of(WalrusGrammar::Identifier)
|
|
593
|
+
result.expression.target.target.lexeme.to_s.should == 'foo'
|
|
594
|
+
result.expression.target.message.should be_kind_of(WalrusGrammar::MethodExpression)
|
|
595
|
+
result.expression.target.message.name.should be_kind_of(WalrusGrammar::Identifier)
|
|
596
|
+
result.expression.target.message.name.lexeme.to_s.should == 'bar'
|
|
597
|
+
result.expression.target.message.params.should == []
|
|
598
|
+
result.expression.message.should be_kind_of(WalrusGrammar::MethodExpression)
|
|
599
|
+
result.expression.message.name.should be_kind_of(WalrusGrammar::Identifier)
|
|
600
|
+
result.expression.message.name.lexeme.to_s.should == 'baz'
|
|
601
|
+
result.expression.message.params.should == []
|
|
602
|
+
|
|
603
|
+
# chained method invocation with arguments
|
|
604
|
+
result = @parser.parse('#silent foo.bar(1).baz')
|
|
605
|
+
result.should be_kind_of(WalrusGrammar::Directive)
|
|
606
|
+
result.should be_kind_of(WalrusGrammar::SilentDirective)
|
|
607
|
+
result.expression.should be_kind_of(WalrusGrammar::MessageExpression)
|
|
608
|
+
|
|
609
|
+
result = @parser.parse('#silent foo.bar.baz(2)')
|
|
610
|
+
result.should be_kind_of(WalrusGrammar::Directive)
|
|
611
|
+
result.should be_kind_of(WalrusGrammar::SilentDirective)
|
|
612
|
+
result.expression.should be_kind_of(WalrusGrammar::MessageExpression)
|
|
613
|
+
|
|
614
|
+
result = @parser.parse('#silent foo.bar(1).baz(2)')
|
|
615
|
+
result.should be_kind_of(WalrusGrammar::Directive)
|
|
616
|
+
result.should be_kind_of(WalrusGrammar::SilentDirective)
|
|
617
|
+
result.expression.should be_kind_of(WalrusGrammar::MessageExpression)
|
|
618
|
+
|
|
619
|
+
# nested arrays
|
|
620
|
+
result = @parser.parse('#silent [1, 2, [foo, bar]]')
|
|
621
|
+
result.should be_kind_of(WalrusGrammar::Directive)
|
|
622
|
+
result.should be_kind_of(WalrusGrammar::SilentDirective)
|
|
623
|
+
result.expression.should be_kind_of(WalrusGrammar::ArrayLiteral)
|
|
624
|
+
result.expression.elements.should be_kind_of(Array)
|
|
625
|
+
result.expression.elements[0].should be_kind_of(WalrusGrammar::NumericLiteral)
|
|
626
|
+
result.expression.elements[0].lexeme.to_s.should == '1'
|
|
627
|
+
result.expression.elements[1].should be_kind_of(WalrusGrammar::NumericLiteral)
|
|
628
|
+
result.expression.elements[1].lexeme.to_s.should == '2'
|
|
629
|
+
result.expression.elements[2].should be_kind_of(WalrusGrammar::ArrayLiteral)
|
|
630
|
+
result.expression.elements[2].elements.should be_kind_of(Array)
|
|
631
|
+
result.expression.elements[2].elements[0].should be_kind_of(WalrusGrammar::Identifier)
|
|
632
|
+
result.expression.elements[2].elements[0].lexeme.to_s.should == 'foo'
|
|
633
|
+
result.expression.elements[2].elements[1].should be_kind_of(WalrusGrammar::Identifier)
|
|
634
|
+
result.expression.elements[2].elements[1].lexeme.to_s.should == 'bar'
|
|
635
|
+
|
|
636
|
+
# nesting in a hash
|
|
637
|
+
result = @parser.parse('#silent { :foo => [1, 2] }')
|
|
638
|
+
result.should be_kind_of(WalrusGrammar::Directive)
|
|
639
|
+
result.should be_kind_of(WalrusGrammar::SilentDirective)
|
|
640
|
+
result.expression.should be_kind_of(WalrusGrammar::HashLiteral)
|
|
641
|
+
|
|
642
|
+
# multiple addition expressions
|
|
643
|
+
result = @parser.parse('#silent 1 + 2 + 3')
|
|
644
|
+
result.should be_kind_of(WalrusGrammar::Directive)
|
|
645
|
+
result.should be_kind_of(WalrusGrammar::SilentDirective)
|
|
646
|
+
result.expression.should be_kind_of(WalrusGrammar::AdditionExpression)
|
|
647
|
+
result.expression.left.should be_kind_of(WalrusGrammar::AdditionExpression)
|
|
648
|
+
result.expression.left.left.should be_kind_of(WalrusGrammar::NumericLiteral)
|
|
649
|
+
result.expression.left.left.lexeme.to_s.should == '1'
|
|
650
|
+
result.expression.left.right.should be_kind_of(WalrusGrammar::NumericLiteral)
|
|
651
|
+
result.expression.left.right.lexeme.to_s.should == '2'
|
|
652
|
+
result.expression.right.should be_kind_of(WalrusGrammar::NumericLiteral)
|
|
653
|
+
result.expression.right.lexeme.to_s.should == '3'
|
|
654
|
+
|
|
655
|
+
# addition and assignment
|
|
656
|
+
result = @parser.parse('#silent foo = bar + 1')
|
|
657
|
+
result.should be_kind_of(WalrusGrammar::Directive)
|
|
658
|
+
result.should be_kind_of(WalrusGrammar::SilentDirective)
|
|
659
|
+
result.expression.should be_kind_of(WalrusGrammar::AssignmentExpression)
|
|
660
|
+
|
|
661
|
+
end
|
|
662
|
+
|
|
663
|
+
it 'should be able go from AST representation of a Ruby expression to an evaluable string form' do
|
|
664
|
+
|
|
665
|
+
result = @parser.parse('#silent 1 + 2 + 3')
|
|
666
|
+
|
|
667
|
+
# given that ruby expressions might be able to contain placeholders, i am not sure if a simple "reverse to original string" method will be enough...
|
|
668
|
+
|
|
669
|
+
end
|
|
670
|
+
|
|
671
|
+
it 'should be able to parse the "block" directive' do
|
|
672
|
+
|
|
673
|
+
# simple case: no parameters, no content
|
|
674
|
+
result = @parser.parse("#block foo\n#end")
|
|
675
|
+
result.should be_kind_of(WalrusGrammar::Directive)
|
|
676
|
+
result.should be_kind_of(WalrusGrammar::BlockDirective)
|
|
677
|
+
result.identifier.to_s.should == 'foo'
|
|
678
|
+
result.params.should == []
|
|
679
|
+
result.content.should == []
|
|
680
|
+
|
|
681
|
+
# pathologically short case
|
|
682
|
+
result = @parser.parse('#block foo##end')
|
|
683
|
+
result.should be_kind_of(WalrusGrammar::BlockDirective)
|
|
684
|
+
result.identifier.to_s.should == 'foo'
|
|
685
|
+
result.params.should == []
|
|
686
|
+
result.content.should == []
|
|
687
|
+
|
|
688
|
+
# some content
|
|
689
|
+
result = @parser.parse('#block foo#hello#end')
|
|
690
|
+
result.should be_kind_of(WalrusGrammar::BlockDirective)
|
|
691
|
+
result.identifier.to_s.should == 'foo'
|
|
692
|
+
result.params.should == []
|
|
693
|
+
result.content.should be_kind_of(WalrusGrammar::RawText)
|
|
694
|
+
result.content.lexeme.should == 'hello'
|
|
695
|
+
|
|
696
|
+
result = @parser.parse("#block foo\nhello\n#end")
|
|
697
|
+
result.should be_kind_of(WalrusGrammar::BlockDirective)
|
|
698
|
+
result.identifier.to_s.should == 'foo'
|
|
699
|
+
result.params.should == []
|
|
700
|
+
result.content.should be_kind_of(WalrusGrammar::RawText)
|
|
701
|
+
result.content.lexeme.should == "hello\n"
|
|
702
|
+
|
|
703
|
+
# empty params list
|
|
704
|
+
result = @parser.parse("#block foo()\n#end")
|
|
705
|
+
result.should be_kind_of(WalrusGrammar::BlockDirective)
|
|
706
|
+
result.identifier.to_s.should == 'foo'
|
|
707
|
+
result.params.should == []
|
|
708
|
+
result.content.should == []
|
|
709
|
+
|
|
710
|
+
# one param
|
|
711
|
+
result = @parser.parse("#block foo(bar)\n#end")
|
|
712
|
+
result.should be_kind_of(WalrusGrammar::BlockDirective)
|
|
713
|
+
result.identifier.to_s.should == 'foo'
|
|
714
|
+
result.params.should be_kind_of(WalrusGrammar::Identifier)
|
|
715
|
+
result.params.lexeme.should == 'bar'
|
|
716
|
+
result.content.should == []
|
|
717
|
+
|
|
718
|
+
# one param with blockault value
|
|
719
|
+
result = @parser.parse("#block foo(bar = 1)\n#end")
|
|
720
|
+
result.should be_kind_of(WalrusGrammar::BlockDirective)
|
|
721
|
+
result.identifier.to_s.should == 'foo'
|
|
722
|
+
result.params.should be_kind_of(WalrusGrammar::AssignmentExpression)
|
|
723
|
+
result.params.lvalue.should be_kind_of(WalrusGrammar::Identifier)
|
|
724
|
+
result.params.lvalue.lexeme.should == 'bar'
|
|
725
|
+
result.params.expression.should be_kind_of(WalrusGrammar::NumericLiteral)
|
|
726
|
+
result.params.expression.lexeme.should == '1'
|
|
727
|
+
result.content.should == []
|
|
728
|
+
|
|
729
|
+
result = @parser.parse("#block foo(bar = nil)\n#end")
|
|
730
|
+
result.should be_kind_of(WalrusGrammar::BlockDirective)
|
|
731
|
+
result.identifier.to_s.should == 'foo'
|
|
732
|
+
result.params.should be_kind_of(WalrusGrammar::AssignmentExpression)
|
|
733
|
+
result.params.lvalue.should be_kind_of(WalrusGrammar::Identifier)
|
|
734
|
+
result.params.lvalue.lexeme.should == 'bar'
|
|
735
|
+
result.params.expression.should be_kind_of(WalrusGrammar::Identifier)
|
|
736
|
+
result.params.expression.lexeme.should == 'nil'
|
|
737
|
+
result.content.should == []
|
|
738
|
+
|
|
739
|
+
# two params
|
|
740
|
+
result = @parser.parse("#block foo(bar, baz)\n#end")
|
|
741
|
+
result.should be_kind_of(WalrusGrammar::BlockDirective)
|
|
742
|
+
result.identifier.to_s.should == 'foo'
|
|
743
|
+
result.params[0].should be_kind_of(WalrusGrammar::Identifier)
|
|
744
|
+
result.params[0].lexeme.should == 'bar'
|
|
745
|
+
result.params[1].should be_kind_of(WalrusGrammar::Identifier)
|
|
746
|
+
result.params[1].lexeme.should == 'baz'
|
|
747
|
+
result.content.should == []
|
|
748
|
+
|
|
749
|
+
# nested block block
|
|
750
|
+
result = @parser.parse(%Q{#block outer
|
|
751
|
+
hello
|
|
752
|
+
#block inner
|
|
753
|
+
world
|
|
754
|
+
#end
|
|
755
|
+
...
|
|
756
|
+
#end})
|
|
757
|
+
result.should be_kind_of(WalrusGrammar::BlockDirective)
|
|
758
|
+
result.identifier.to_s.should == 'outer'
|
|
759
|
+
result.params.should == []
|
|
760
|
+
result.content[0].should be_kind_of(WalrusGrammar::RawText)
|
|
761
|
+
result.content[0].lexeme.should == "hello\n"
|
|
762
|
+
result.content[1].should be_kind_of(WalrusGrammar::BlockDirective)
|
|
763
|
+
result.content[1].identifier.to_s.should == 'inner'
|
|
764
|
+
result.content[1].params.should == []
|
|
765
|
+
result.content[1].content.should be_kind_of(WalrusGrammar::RawText)
|
|
766
|
+
result.content[1].content.lexeme.should == "world\n"
|
|
767
|
+
result.content[2].should be_kind_of(WalrusGrammar::RawText)
|
|
768
|
+
result.content[2].lexeme.should == "...\n"
|
|
769
|
+
|
|
770
|
+
# missing identifier
|
|
771
|
+
lambda { @parser.parse("#block\n#end") }.should raise_error(Grammar::ParseError)
|
|
772
|
+
lambda { @parser.parse("#block ()\n#end") }.should raise_error(Grammar::ParseError)
|
|
773
|
+
|
|
774
|
+
# non-terminated parameter list
|
|
775
|
+
lambda { @parser.parse("#block foo(bar\n#end") }.should raise_error(Grammar::ParseError)
|
|
776
|
+
lambda { @parser.parse("#block foo(bar,)\n#end") }.should raise_error(Grammar::ParseError)
|
|
777
|
+
|
|
778
|
+
# illegal parameter type
|
|
779
|
+
lambda { @parser.parse("#block foo(1)\n#end") }.should raise_error(Grammar::ParseError)
|
|
780
|
+
lambda { @parser.parse("#block foo($bar)\n#end") }.should raise_error(Grammar::ParseError)
|
|
781
|
+
|
|
782
|
+
end
|
|
783
|
+
|
|
784
|
+
it 'should be able to parse the "def" directive' do
|
|
785
|
+
|
|
786
|
+
# simple case: no parameters, no content
|
|
787
|
+
result = @parser.parse("#def foo\n#end")
|
|
788
|
+
result.should be_kind_of(WalrusGrammar::Directive)
|
|
789
|
+
result.should be_kind_of(WalrusGrammar::DefDirective)
|
|
790
|
+
result.identifier.to_s.should == 'foo'
|
|
791
|
+
result.params.should == []
|
|
792
|
+
result.content.should == []
|
|
793
|
+
|
|
794
|
+
# pathologically short case
|
|
795
|
+
result = @parser.parse('#def foo##end')
|
|
796
|
+
result.should be_kind_of(WalrusGrammar::DefDirective)
|
|
797
|
+
result.identifier.to_s.should == 'foo'
|
|
798
|
+
result.params.should == []
|
|
799
|
+
result.content.should == []
|
|
800
|
+
|
|
801
|
+
# some content
|
|
802
|
+
result = @parser.parse('#def foo#hello#end')
|
|
803
|
+
result.should be_kind_of(WalrusGrammar::DefDirective)
|
|
804
|
+
result.identifier.to_s.should == 'foo'
|
|
805
|
+
result.params.should == []
|
|
806
|
+
result.content.should be_kind_of(WalrusGrammar::RawText)
|
|
807
|
+
result.content.lexeme.should == 'hello'
|
|
808
|
+
|
|
809
|
+
result = @parser.parse("#def foo\nhello\n#end")
|
|
810
|
+
result.should be_kind_of(WalrusGrammar::DefDirective)
|
|
811
|
+
result.identifier.to_s.should == 'foo'
|
|
812
|
+
result.params.should == []
|
|
813
|
+
result.content.should be_kind_of(WalrusGrammar::RawText)
|
|
814
|
+
result.content.lexeme.should == "hello\n"
|
|
815
|
+
|
|
816
|
+
# empty params list
|
|
817
|
+
result = @parser.parse("#def foo()\n#end")
|
|
818
|
+
result.should be_kind_of(WalrusGrammar::DefDirective)
|
|
819
|
+
result.identifier.to_s.should == 'foo'
|
|
820
|
+
result.params.should == []
|
|
821
|
+
result.content.should == []
|
|
822
|
+
|
|
823
|
+
# one param
|
|
824
|
+
result = @parser.parse("#def foo(bar)\n#end")
|
|
825
|
+
result.should be_kind_of(WalrusGrammar::DefDirective)
|
|
826
|
+
result.identifier.to_s.should == 'foo'
|
|
827
|
+
result.params.should be_kind_of(WalrusGrammar::Identifier)
|
|
828
|
+
result.params.lexeme.should == 'bar'
|
|
829
|
+
result.content.should == []
|
|
830
|
+
|
|
831
|
+
# one param with default value
|
|
832
|
+
result = @parser.parse("#def foo(bar = 1)\n#end")
|
|
833
|
+
result.should be_kind_of(WalrusGrammar::DefDirective)
|
|
834
|
+
result.identifier.to_s.should == 'foo'
|
|
835
|
+
result.params.should be_kind_of(WalrusGrammar::AssignmentExpression)
|
|
836
|
+
result.params.lvalue.should be_kind_of(WalrusGrammar::Identifier)
|
|
837
|
+
result.params.lvalue.lexeme.should == 'bar'
|
|
838
|
+
result.params.expression.should be_kind_of(WalrusGrammar::NumericLiteral)
|
|
839
|
+
result.params.expression.lexeme.should == '1'
|
|
840
|
+
result.content.should == []
|
|
841
|
+
|
|
842
|
+
result = @parser.parse("#def foo(bar = nil)\n#end")
|
|
843
|
+
result.should be_kind_of(WalrusGrammar::DefDirective)
|
|
844
|
+
result.identifier.to_s.should == 'foo'
|
|
845
|
+
result.params.should be_kind_of(WalrusGrammar::AssignmentExpression)
|
|
846
|
+
result.params.lvalue.should be_kind_of(WalrusGrammar::Identifier)
|
|
847
|
+
result.params.lvalue.lexeme.should == 'bar'
|
|
848
|
+
result.params.expression.should be_kind_of(WalrusGrammar::Identifier)
|
|
849
|
+
result.params.expression.lexeme.should == 'nil'
|
|
850
|
+
result.content.should == []
|
|
851
|
+
|
|
852
|
+
# two params
|
|
853
|
+
result = @parser.parse("#def foo(bar, baz)\n#end")
|
|
854
|
+
result.should be_kind_of(WalrusGrammar::DefDirective)
|
|
855
|
+
result.identifier.to_s.should == 'foo'
|
|
856
|
+
result.params[0].should be_kind_of(WalrusGrammar::Identifier)
|
|
857
|
+
result.params[0].lexeme.should == 'bar'
|
|
858
|
+
result.params[1].should be_kind_of(WalrusGrammar::Identifier)
|
|
859
|
+
result.params[1].lexeme.should == 'baz'
|
|
860
|
+
result.content.should == []
|
|
861
|
+
|
|
862
|
+
# nested def block
|
|
863
|
+
result = @parser.parse(%Q{#def outer
|
|
864
|
+
hello
|
|
865
|
+
#def inner
|
|
866
|
+
world
|
|
867
|
+
#end
|
|
868
|
+
...
|
|
869
|
+
#end})
|
|
870
|
+
result.should be_kind_of(WalrusGrammar::DefDirective)
|
|
871
|
+
result.identifier.to_s.should == 'outer'
|
|
872
|
+
result.params.should == []
|
|
873
|
+
result.content[0].should be_kind_of(WalrusGrammar::RawText)
|
|
874
|
+
result.content[0].lexeme.should == "hello\n"
|
|
875
|
+
result.content[1].should be_kind_of(WalrusGrammar::DefDirective)
|
|
876
|
+
result.content[1].identifier.to_s.should == 'inner'
|
|
877
|
+
result.content[1].params.should == []
|
|
878
|
+
result.content[1].content.should be_kind_of(WalrusGrammar::RawText)
|
|
879
|
+
result.content[1].content.lexeme.should == "world\n"
|
|
880
|
+
result.content[2].should be_kind_of(WalrusGrammar::RawText)
|
|
881
|
+
result.content[2].lexeme.should == "...\n"
|
|
882
|
+
|
|
883
|
+
# missing identifier
|
|
884
|
+
lambda { @parser.parse("#def\n#end") }.should raise_error(Grammar::ParseError)
|
|
885
|
+
lambda { @parser.parse("#def ()\n#end") }.should raise_error(Grammar::ParseError)
|
|
886
|
+
|
|
887
|
+
# non-terminated parameter list
|
|
888
|
+
lambda { @parser.parse("#def foo(bar\n#end") }.should raise_error(Grammar::ParseError)
|
|
889
|
+
lambda { @parser.parse("#def foo(bar,)\n#end") }.should raise_error(Grammar::ParseError)
|
|
890
|
+
|
|
891
|
+
# illegal parameter type
|
|
892
|
+
lambda { @parser.parse("#def foo(1)\n#end") }.should raise_error(Grammar::ParseError)
|
|
893
|
+
lambda { @parser.parse("#def foo($bar)\n#end") }.should raise_error(Grammar::ParseError)
|
|
894
|
+
|
|
895
|
+
end
|
|
896
|
+
|
|
897
|
+
it 'should be able to parse the "echo" directive' do
|
|
898
|
+
|
|
899
|
+
# success case
|
|
900
|
+
result = @parser.parse('#echo foo')
|
|
901
|
+
result.should be_kind_of(WalrusGrammar::Directive)
|
|
902
|
+
result.should be_kind_of(WalrusGrammar::EchoDirective)
|
|
903
|
+
result.expression.should be_kind_of(WalrusGrammar::Identifier)
|
|
904
|
+
result.expression.lexeme.should == 'foo'
|
|
905
|
+
|
|
906
|
+
# failing case
|
|
907
|
+
lambda { @parser.parse('#echo') }.should raise_error(Grammar::ParseError)
|
|
908
|
+
|
|
909
|
+
# allow multiple expressions separated by semicolons
|
|
910
|
+
result = @parser.parse('#echo foo; bar')
|
|
911
|
+
result.should be_kind_of(WalrusGrammar::EchoDirective)
|
|
912
|
+
result.expression.should be_kind_of(Array)
|
|
913
|
+
result.expression[0].should be_kind_of(WalrusGrammar::Identifier)
|
|
914
|
+
result.expression[0].lexeme.should == 'foo'
|
|
915
|
+
result.expression[1].should be_kind_of(WalrusGrammar::Identifier)
|
|
916
|
+
result.expression[1].lexeme.should == 'bar'
|
|
917
|
+
|
|
918
|
+
end
|
|
919
|
+
|
|
920
|
+
it 'should be able to parse "echo" directive, short notation' do
|
|
921
|
+
|
|
922
|
+
# single expression
|
|
923
|
+
result = @parser.parse('#= 1 #')
|
|
924
|
+
result.should be_kind_of(WalrusGrammar::Directive)
|
|
925
|
+
result.should be_kind_of(WalrusGrammar::EchoDirective)
|
|
926
|
+
result.expression.should be_kind_of(WalrusGrammar::NumericLiteral)
|
|
927
|
+
result.expression.lexeme.should == '1'
|
|
928
|
+
|
|
929
|
+
# expression list
|
|
930
|
+
result = @parser.parse('#= foo; bar #')
|
|
931
|
+
result.should be_kind_of(WalrusGrammar::EchoDirective)
|
|
932
|
+
result.expression.should be_kind_of(Array)
|
|
933
|
+
result.expression[0].should be_kind_of(WalrusGrammar::Identifier)
|
|
934
|
+
result.expression[0].lexeme.should == 'foo'
|
|
935
|
+
result.expression[1].should be_kind_of(WalrusGrammar::Identifier)
|
|
936
|
+
result.expression[1].lexeme.should == 'bar'
|
|
937
|
+
|
|
938
|
+
# explicit end marker is required
|
|
939
|
+
lambda { @parser.parse('#= 1') }.should raise_error(Grammar::ParseError)
|
|
940
|
+
lambda { @parser.parse('#= foo; bar') }.should raise_error(Grammar::ParseError)
|
|
941
|
+
|
|
942
|
+
end
|
|
943
|
+
|
|
944
|
+
it 'should be able to parse the "raw" directive' do
|
|
945
|
+
|
|
946
|
+
# shortest example possible
|
|
947
|
+
result = @parser.parse('#raw##end')
|
|
948
|
+
result.should be_kind_of(WalrusGrammar::Directive)
|
|
949
|
+
result.should be_kind_of(WalrusGrammar::RawDirective)
|
|
950
|
+
result.content.should == ''
|
|
951
|
+
|
|
952
|
+
# one character longer
|
|
953
|
+
result = @parser.parse('#raw##end#')
|
|
954
|
+
result.should be_kind_of(WalrusGrammar::Directive)
|
|
955
|
+
result.should be_kind_of(WalrusGrammar::RawDirective)
|
|
956
|
+
result.content.should == ''
|
|
957
|
+
|
|
958
|
+
# same but with trailing newline instead
|
|
959
|
+
result = @parser.parse("#raw##end\n")
|
|
960
|
+
result.should be_kind_of(WalrusGrammar::Directive)
|
|
961
|
+
result.should be_kind_of(WalrusGrammar::RawDirective)
|
|
962
|
+
result.content.should == ''
|
|
963
|
+
|
|
964
|
+
# only slightly longer (still on one line)
|
|
965
|
+
result = @parser.parse('#raw#hello world#end')
|
|
966
|
+
result.should be_kind_of(WalrusGrammar::Directive)
|
|
967
|
+
result.should be_kind_of(WalrusGrammar::RawDirective)
|
|
968
|
+
result.content.should == 'hello world'
|
|
969
|
+
|
|
970
|
+
result = @parser.parse('#raw#hello world#end#')
|
|
971
|
+
result.should be_kind_of(WalrusGrammar::Directive)
|
|
972
|
+
result.should be_kind_of(WalrusGrammar::RawDirective)
|
|
973
|
+
result.content.should == 'hello world'
|
|
974
|
+
|
|
975
|
+
result = @parser.parse("#raw#hello world#end\n")
|
|
976
|
+
result.should be_kind_of(WalrusGrammar::Directive)
|
|
977
|
+
result.should be_kind_of(WalrusGrammar::RawDirective)
|
|
978
|
+
result.content.should == 'hello world'
|
|
979
|
+
|
|
980
|
+
result = @parser.parse("#raw\nhello world\n#end")
|
|
981
|
+
result.should be_kind_of(WalrusGrammar::Directive)
|
|
982
|
+
result.should be_kind_of(WalrusGrammar::RawDirective)
|
|
983
|
+
result.content.should == "hello world\n"
|
|
984
|
+
|
|
985
|
+
result = @parser.parse("#raw\nhello world\n#end#")
|
|
986
|
+
result.should be_kind_of(WalrusGrammar::Directive)
|
|
987
|
+
result.should be_kind_of(WalrusGrammar::RawDirective)
|
|
988
|
+
result.content.should == "hello world\n"
|
|
989
|
+
|
|
990
|
+
# with embedded directives (should be ignored)
|
|
991
|
+
result = @parser.parse('#raw##def example#end')
|
|
992
|
+
result.should be_kind_of(WalrusGrammar::Directive)
|
|
993
|
+
result.should be_kind_of(WalrusGrammar::RawDirective)
|
|
994
|
+
result.content.should == '#def example'
|
|
995
|
+
|
|
996
|
+
# with embedded placeholders (should be ignored)
|
|
997
|
+
result = @parser.parse('#raw#$foobar#end')
|
|
998
|
+
result.should be_kind_of(WalrusGrammar::Directive)
|
|
999
|
+
result.should be_kind_of(WalrusGrammar::RawDirective)
|
|
1000
|
+
result.content.should == '$foobar'
|
|
1001
|
+
|
|
1002
|
+
# with embedded escapes (should be ignored)
|
|
1003
|
+
result = @parser.parse('#raw#\\$placeholder#end')
|
|
1004
|
+
result.should be_kind_of(WalrusGrammar::Directive)
|
|
1005
|
+
result.should be_kind_of(WalrusGrammar::RawDirective)
|
|
1006
|
+
result.content.should == '\\$placeholder'
|
|
1007
|
+
|
|
1008
|
+
# note that you can't include a literal "#end" in the raw block
|
|
1009
|
+
lambda { @parser.parse('#raw# here is my #end! #end') }.should raise_error(Grammar::ParseError)
|
|
1010
|
+
|
|
1011
|
+
# must use a "here doc" in order to do that
|
|
1012
|
+
result = @parser.parse('#raw <<HERE_DOCUMENT
|
|
1013
|
+
#end
|
|
1014
|
+
HERE_DOCUMENT')
|
|
1015
|
+
result.should be_kind_of(WalrusGrammar::RawDirective)
|
|
1016
|
+
result.content.should == "#end\n"
|
|
1017
|
+
|
|
1018
|
+
# optionally indented end marker
|
|
1019
|
+
result = @parser.parse('#raw <<-HERE_DOCUMENT
|
|
1020
|
+
#end
|
|
1021
|
+
HERE_DOCUMENT')
|
|
1022
|
+
result.should be_kind_of(WalrusGrammar::RawDirective)
|
|
1023
|
+
result.content.should == "#end\n"
|
|
1024
|
+
|
|
1025
|
+
# actually indented end marker
|
|
1026
|
+
result = @parser.parse('#raw <<-HERE_DOCUMENT
|
|
1027
|
+
#end
|
|
1028
|
+
HERE_DOCUMENT')
|
|
1029
|
+
result.should be_kind_of(WalrusGrammar::RawDirective)
|
|
1030
|
+
result.content.should == "#end\n"
|
|
1031
|
+
|
|
1032
|
+
# empty here document
|
|
1033
|
+
result = @parser.parse('#raw <<HERE_DOCUMENT
|
|
1034
|
+
HERE_DOCUMENT')
|
|
1035
|
+
result.should be_kind_of(WalrusGrammar::RawDirective)
|
|
1036
|
+
result.content.should == ''
|
|
1037
|
+
|
|
1038
|
+
result = @parser.parse('#raw <<-HERE_DOCUMENT
|
|
1039
|
+
HERE_DOCUMENT')
|
|
1040
|
+
result.should be_kind_of(WalrusGrammar::RawDirective)
|
|
1041
|
+
result.content.should == ''
|
|
1042
|
+
|
|
1043
|
+
# whitespace after end marker
|
|
1044
|
+
result = @parser.parse('#raw <<HERE_DOCUMENT
|
|
1045
|
+
#end
|
|
1046
|
+
HERE_DOCUMENT ')
|
|
1047
|
+
result.should be_kind_of(WalrusGrammar::RawDirective)
|
|
1048
|
+
result.content.should == "#end\n"
|
|
1049
|
+
|
|
1050
|
+
# invalid here document (whitespace before end marker)
|
|
1051
|
+
lambda { @parser.parse('#raw <<HERE_DOCUMENT
|
|
1052
|
+
#end
|
|
1053
|
+
HERE_DOCUMENT') }.should raise_error(Grammar::ParseError)
|
|
1054
|
+
|
|
1055
|
+
# invalid here document (non-matching end marker)
|
|
1056
|
+
lambda { @parser.parse('#raw <<HERE_DOCUMENT
|
|
1057
|
+
#end
|
|
1058
|
+
THERE_DOCUMENT') }.should raise_error(Grammar::ParseError)
|
|
1059
|
+
|
|
1060
|
+
end
|
|
1061
|
+
|
|
1062
|
+
it 'should be able to parse the "ruby" directive' do
|
|
1063
|
+
|
|
1064
|
+
# the end marker is required
|
|
1065
|
+
lambda { @parser.parse('#ruby') }.should raise_error(Grammar::ParseError)
|
|
1066
|
+
lambda { @parser.parse('#ruby#foo') }.should raise_error(Grammar::ParseError)
|
|
1067
|
+
|
|
1068
|
+
# shortest possible version
|
|
1069
|
+
result = @parser.parse('#ruby##end')
|
|
1070
|
+
result.should be_kind_of(WalrusGrammar::Directive)
|
|
1071
|
+
result.should be_kind_of(WalrusGrammar::RubyDirective)
|
|
1072
|
+
result.content.should == ''
|
|
1073
|
+
|
|
1074
|
+
# two line version, also short
|
|
1075
|
+
result = @parser.parse("#ruby\n#end")
|
|
1076
|
+
result.should be_kind_of(WalrusGrammar::RubyDirective)
|
|
1077
|
+
result.content.should == ''
|
|
1078
|
+
|
|
1079
|
+
# simple examples with content
|
|
1080
|
+
result = @parser.parse('#ruby#hello world#end')
|
|
1081
|
+
result.should be_kind_of(WalrusGrammar::RubyDirective)
|
|
1082
|
+
result.content.should == 'hello world'
|
|
1083
|
+
|
|
1084
|
+
result = @parser.parse("#ruby\nfoobar#end")
|
|
1085
|
+
result.should be_kind_of(WalrusGrammar::RubyDirective)
|
|
1086
|
+
result.content.should == 'foobar'
|
|
1087
|
+
|
|
1088
|
+
# can include anything at all in the block, escape sequences, placeholders, directives etc and all will be ignored
|
|
1089
|
+
result = @parser.parse("#ruby\n#ignored,$ignored,\\#ignored,\\$ignored#end")
|
|
1090
|
+
result.should be_kind_of(WalrusGrammar::RubyDirective)
|
|
1091
|
+
result.content.should == '#ignored,$ignored,\\#ignored,\\$ignored'
|
|
1092
|
+
|
|
1093
|
+
# to include a literal "#end" you must use a here document
|
|
1094
|
+
result = @parser.parse('#ruby <<HERE_DOCUMENT
|
|
1095
|
+
#end
|
|
1096
|
+
HERE_DOCUMENT')
|
|
1097
|
+
result.should be_kind_of(WalrusGrammar::RubyDirective)
|
|
1098
|
+
result.content.should == "#end\n"
|
|
1099
|
+
|
|
1100
|
+
# optionally indented end marker
|
|
1101
|
+
result = @parser.parse('#ruby <<-HERE_DOCUMENT
|
|
1102
|
+
#end
|
|
1103
|
+
HERE_DOCUMENT')
|
|
1104
|
+
result.should be_kind_of(WalrusGrammar::RubyDirective)
|
|
1105
|
+
result.content.should == "#end\n"
|
|
1106
|
+
|
|
1107
|
+
# actually indented end marker
|
|
1108
|
+
result = @parser.parse('#ruby <<-HERE_DOCUMENT
|
|
1109
|
+
#end
|
|
1110
|
+
HERE_DOCUMENT')
|
|
1111
|
+
result.should be_kind_of(WalrusGrammar::RubyDirective)
|
|
1112
|
+
result.content.should == "#end\n"
|
|
1113
|
+
|
|
1114
|
+
# empty here document
|
|
1115
|
+
result = @parser.parse('#ruby <<HERE_DOCUMENT
|
|
1116
|
+
HERE_DOCUMENT')
|
|
1117
|
+
result.should be_kind_of(WalrusGrammar::RubyDirective)
|
|
1118
|
+
result.content.should == ''
|
|
1119
|
+
|
|
1120
|
+
result = @parser.parse('#ruby <<-HERE_DOCUMENT
|
|
1121
|
+
HERE_DOCUMENT')
|
|
1122
|
+
result.should be_kind_of(WalrusGrammar::RubyDirective)
|
|
1123
|
+
result.content.should == ''
|
|
1124
|
+
|
|
1125
|
+
# whitespace after end marker
|
|
1126
|
+
result = @parser.parse('#ruby <<HERE_DOCUMENT
|
|
1127
|
+
#end
|
|
1128
|
+
HERE_DOCUMENT ')
|
|
1129
|
+
result.should be_kind_of(WalrusGrammar::RubyDirective)
|
|
1130
|
+
result.content.should == "#end\n"
|
|
1131
|
+
|
|
1132
|
+
# invalid here document (whitespace before end marker)
|
|
1133
|
+
lambda { @parser.parse('#ruby <<HERE_DOCUMENT
|
|
1134
|
+
#end
|
|
1135
|
+
HERE_DOCUMENT') }.should raise_error(Grammar::ParseError)
|
|
1136
|
+
|
|
1137
|
+
# invalid here document (non-matching end marker)
|
|
1138
|
+
lambda { @parser.parse('#ruby <<HERE_DOCUMENT
|
|
1139
|
+
#end
|
|
1140
|
+
THERE_DOCUMENT') }.should raise_error(Grammar::ParseError)
|
|
1141
|
+
|
|
1142
|
+
end
|
|
1143
|
+
|
|
1144
|
+
it 'should be able to parse the "set" directive' do
|
|
1145
|
+
|
|
1146
|
+
# assign a string literal
|
|
1147
|
+
result = @parser.parse('#set $foo = "bar"')
|
|
1148
|
+
result.should be_kind_of(WalrusGrammar::Directive)
|
|
1149
|
+
result.should be_kind_of(WalrusGrammar::SetDirective)
|
|
1150
|
+
result.placeholder.to_s.should == 'foo'
|
|
1151
|
+
result.expression.should be_kind_of(WalrusGrammar::DoubleQuotedStringLiteral)
|
|
1152
|
+
result.expression.lexeme.should == 'bar'
|
|
1153
|
+
|
|
1154
|
+
# assign a local variable
|
|
1155
|
+
result = @parser.parse('#set $foo = bar')
|
|
1156
|
+
result.should be_kind_of(WalrusGrammar::SetDirective)
|
|
1157
|
+
result.placeholder.to_s.should == 'foo'
|
|
1158
|
+
result.expression.should be_kind_of(WalrusGrammar::Identifier)
|
|
1159
|
+
result.expression.lexeme.should == 'bar'
|
|
1160
|
+
|
|
1161
|
+
# no whitespace allowed between "$" and placeholder name
|
|
1162
|
+
lambda { @parser.parse('#set $ foo = bar') }.should raise_error(Grammar::ParseError)
|
|
1163
|
+
|
|
1164
|
+
# "long form" not allowed in #set directives
|
|
1165
|
+
lambda { @parser.parse('#set ${foo} = bar') }.should raise_error(Grammar::ParseError)
|
|
1166
|
+
|
|
1167
|
+
# explicitly close directive
|
|
1168
|
+
result = @parser.parse('#set $foo = "bar"#')
|
|
1169
|
+
result.should be_kind_of(WalrusGrammar::SetDirective)
|
|
1170
|
+
result.placeholder.to_s.should == 'foo'
|
|
1171
|
+
result.expression.should be_kind_of(WalrusGrammar::DoubleQuotedStringLiteral)
|
|
1172
|
+
result.expression.lexeme.should == 'bar'
|
|
1173
|
+
|
|
1174
|
+
end
|
|
1175
|
+
|
|
1176
|
+
it 'should be able to parse the "silent" directive' do
|
|
1177
|
+
|
|
1178
|
+
# for more detailed tests see "should be able to parse basic Ruby expressions above"
|
|
1179
|
+
lambda { @parser.parse('#silent') }.should raise_error(Grammar::ParseError)
|
|
1180
|
+
|
|
1181
|
+
# allow multiple expressions separated by semicolons
|
|
1182
|
+
result = @parser.parse('#silent foo; bar')
|
|
1183
|
+
result.should be_kind_of(WalrusGrammar::Directive)
|
|
1184
|
+
result.should be_kind_of(WalrusGrammar::SilentDirective)
|
|
1185
|
+
result.expression.should be_kind_of(Array)
|
|
1186
|
+
result.expression[0].should be_kind_of(WalrusGrammar::Identifier)
|
|
1187
|
+
result.expression[0].lexeme.should == 'foo'
|
|
1188
|
+
result.expression[1].should be_kind_of(WalrusGrammar::Identifier)
|
|
1189
|
+
result.expression[1].lexeme.should == 'bar'
|
|
1190
|
+
|
|
1191
|
+
end
|
|
1192
|
+
|
|
1193
|
+
it 'should be able to parse "silent" directive, short notation' do
|
|
1194
|
+
|
|
1195
|
+
# single expression
|
|
1196
|
+
result = @parser.parse('# 1 #')
|
|
1197
|
+
result.should be_kind_of(WalrusGrammar::Directive)
|
|
1198
|
+
result.should be_kind_of(WalrusGrammar::SilentDirective)
|
|
1199
|
+
result.expression.should be_kind_of(WalrusGrammar::NumericLiteral)
|
|
1200
|
+
result.expression.lexeme.should == '1'
|
|
1201
|
+
|
|
1202
|
+
# expression list
|
|
1203
|
+
result = @parser.parse('# foo; bar #')
|
|
1204
|
+
result.should be_kind_of(WalrusGrammar::SilentDirective)
|
|
1205
|
+
result.expression.should be_kind_of(Array)
|
|
1206
|
+
result.expression[0].should be_kind_of(WalrusGrammar::Identifier)
|
|
1207
|
+
result.expression[0].lexeme.should == 'foo'
|
|
1208
|
+
result.expression[1].should be_kind_of(WalrusGrammar::Identifier)
|
|
1209
|
+
result.expression[1].lexeme.should == 'bar'
|
|
1210
|
+
|
|
1211
|
+
# more complex expression
|
|
1212
|
+
result = @parser.parse("# @secret_ivar = 'foo' #")
|
|
1213
|
+
result = @parser.parse("# foo + bar #")
|
|
1214
|
+
result = @parser.parse("# foo.bar #")
|
|
1215
|
+
result = @parser.parse("# [foo, bar]#")
|
|
1216
|
+
result = @parser.parse("# { :foo => bar }#")
|
|
1217
|
+
|
|
1218
|
+
# leading whitespace is obligatory
|
|
1219
|
+
lambda { @parser.parse('#1 #') }.should raise_error(Grammar::ParseError)
|
|
1220
|
+
lambda { @parser.parse('#foo; bar #') }.should raise_error(Grammar::ParseError)
|
|
1221
|
+
|
|
1222
|
+
# explicit end marker is required
|
|
1223
|
+
lambda { @parser.parse('# 1') }.should raise_error(Grammar::ParseError)
|
|
1224
|
+
lambda { @parser.parse('# foo; bar') }.should raise_error(Grammar::ParseError)
|
|
1225
|
+
|
|
1226
|
+
end
|
|
1227
|
+
|
|
1228
|
+
it 'should be able to parse the "slurp" directive' do
|
|
1229
|
+
|
|
1230
|
+
# basic case
|
|
1231
|
+
result = @parser.parse("hello #slurp\nworld")
|
|
1232
|
+
result[0].should be_kind_of(WalrusGrammar::RawText)
|
|
1233
|
+
result[0].lexeme.should == 'hello '
|
|
1234
|
+
result[1].should be_kind_of(WalrusGrammar::SlurpDirective)
|
|
1235
|
+
result[2].should be_kind_of(WalrusGrammar::RawText)
|
|
1236
|
+
result[2].lexeme.should == 'world'
|
|
1237
|
+
|
|
1238
|
+
# must be the last thing on the line (no comments)
|
|
1239
|
+
lambda { @parser.parse("hello #slurp ## my comment...\nworld") }.should raise_error(Grammar::ParseError)
|
|
1240
|
+
|
|
1241
|
+
# but intervening whitespace is ok
|
|
1242
|
+
result = @parser.parse("hello #slurp \nworld")
|
|
1243
|
+
result[0].should be_kind_of(WalrusGrammar::RawText)
|
|
1244
|
+
result[0].lexeme.should == 'hello '
|
|
1245
|
+
result[1].should be_kind_of(WalrusGrammar::SlurpDirective)
|
|
1246
|
+
result[2].should be_kind_of(WalrusGrammar::RawText)
|
|
1247
|
+
result[2].lexeme.should == 'world'
|
|
1248
|
+
|
|
1249
|
+
# should only slurp one newline, not multiple newlines
|
|
1250
|
+
result = @parser.parse("hello #slurp\n\n\nworld") # three newlines
|
|
1251
|
+
result[0].should be_kind_of(WalrusGrammar::RawText)
|
|
1252
|
+
result[0].lexeme.should == 'hello '
|
|
1253
|
+
result[1].should be_kind_of(WalrusGrammar::SlurpDirective)
|
|
1254
|
+
result[2].should be_kind_of(WalrusGrammar::RawText)
|
|
1255
|
+
result[2].lexeme.should == "\n\nworld" # one newline slurped, two left
|
|
1256
|
+
|
|
1257
|
+
end
|
|
1258
|
+
|
|
1259
|
+
it 'should be able to parse the "super" directive with parentheses' do
|
|
1260
|
+
|
|
1261
|
+
# super with empty params
|
|
1262
|
+
result = @parser.parse('#super()')
|
|
1263
|
+
result.should be_kind_of(WalrusGrammar::SuperDirective)
|
|
1264
|
+
result.params.should == []
|
|
1265
|
+
|
|
1266
|
+
# same with intervening whitespace
|
|
1267
|
+
result = @parser.parse('#super ()')
|
|
1268
|
+
result.should be_kind_of(WalrusGrammar::SuperDirective)
|
|
1269
|
+
result.params.should == []
|
|
1270
|
+
|
|
1271
|
+
# super with one param
|
|
1272
|
+
result = @parser.parse('#super("foo")')
|
|
1273
|
+
result.should be_kind_of(WalrusGrammar::SuperDirective)
|
|
1274
|
+
result.params.should be_kind_of(WalrusGrammar::DoubleQuotedStringLiteral)
|
|
1275
|
+
result.params.lexeme.should == 'foo'
|
|
1276
|
+
result.params.to_s.should == 'foo'
|
|
1277
|
+
|
|
1278
|
+
# same with intervening whitespace
|
|
1279
|
+
result = @parser.parse('#super ("foo")')
|
|
1280
|
+
result.should be_kind_of(WalrusGrammar::SuperDirective)
|
|
1281
|
+
result.params.should be_kind_of(WalrusGrammar::DoubleQuotedStringLiteral)
|
|
1282
|
+
result.params.lexeme.should == 'foo'
|
|
1283
|
+
result.params.to_s.should == 'foo'
|
|
1284
|
+
|
|
1285
|
+
# super with two params
|
|
1286
|
+
result = @parser.parse('#super("foo", "bar")')
|
|
1287
|
+
result.should be_kind_of(WalrusGrammar::SuperDirective)
|
|
1288
|
+
result.params.should be_kind_of(Array)
|
|
1289
|
+
result.params[0].should be_kind_of(WalrusGrammar::DoubleQuotedStringLiteral)
|
|
1290
|
+
result.params[0].lexeme.should == 'foo'
|
|
1291
|
+
result.params[0].to_s.should == 'foo'
|
|
1292
|
+
result.params[1].should be_kind_of(WalrusGrammar::DoubleQuotedStringLiteral)
|
|
1293
|
+
result.params[1].lexeme.should == 'bar'
|
|
1294
|
+
result.params[1].to_s.should == 'bar'
|
|
1295
|
+
|
|
1296
|
+
# same with intervening whitespace
|
|
1297
|
+
result = @parser.parse('#super ("foo", "bar")')
|
|
1298
|
+
result.should be_kind_of(WalrusGrammar::SuperDirective)
|
|
1299
|
+
result.params.should be_kind_of(Array)
|
|
1300
|
+
result.params[0].should be_kind_of(WalrusGrammar::DoubleQuotedStringLiteral)
|
|
1301
|
+
result.params[0].lexeme.should == 'foo'
|
|
1302
|
+
result.params[0].to_s.should == 'foo'
|
|
1303
|
+
result.params[1].should be_kind_of(WalrusGrammar::DoubleQuotedStringLiteral)
|
|
1304
|
+
result.params[1].lexeme.should == 'bar'
|
|
1305
|
+
result.params[1].to_s.should == 'bar'
|
|
1306
|
+
|
|
1307
|
+
end
|
|
1308
|
+
|
|
1309
|
+
it 'should be able to parse the "super" directive without parentheses' do
|
|
1310
|
+
|
|
1311
|
+
# super with no params
|
|
1312
|
+
result = @parser.parse('#super')
|
|
1313
|
+
result.should be_kind_of(WalrusGrammar::SuperDirective)
|
|
1314
|
+
result.params.should == []
|
|
1315
|
+
|
|
1316
|
+
# super with one param
|
|
1317
|
+
result = @parser.parse('#super "foo"')
|
|
1318
|
+
result.should be_kind_of(WalrusGrammar::SuperDirective)
|
|
1319
|
+
result.params.should be_kind_of(WalrusGrammar::DoubleQuotedStringLiteral)
|
|
1320
|
+
result.params.lexeme.should == 'foo'
|
|
1321
|
+
result.params.to_s.should == 'foo'
|
|
1322
|
+
|
|
1323
|
+
# super with two params
|
|
1324
|
+
result = @parser.parse('#super "foo", "bar"')
|
|
1325
|
+
result.should be_kind_of(WalrusGrammar::SuperDirective)
|
|
1326
|
+
result.params.should be_kind_of(Array)
|
|
1327
|
+
result.params[0].should be_kind_of(WalrusGrammar::DoubleQuotedStringLiteral)
|
|
1328
|
+
result.params[0].lexeme.should == 'foo'
|
|
1329
|
+
result.params[0].to_s.should == 'foo'
|
|
1330
|
+
result.params[1].should be_kind_of(WalrusGrammar::DoubleQuotedStringLiteral)
|
|
1331
|
+
result.params[1].lexeme.should == 'bar'
|
|
1332
|
+
result.params[1].to_s.should == 'bar'
|
|
1333
|
+
|
|
1334
|
+
end
|
|
1335
|
+
|
|
1336
|
+
it 'parse results should contain information about their location in the original source (line and column start/end)' do
|
|
1337
|
+
|
|
1338
|
+
# simple raw text
|
|
1339
|
+
result = @parser.parse('hello world')
|
|
1340
|
+
result.line_start.should == 0 # where the node starts
|
|
1341
|
+
result.column_start.should == 0 # where the node starts
|
|
1342
|
+
result.line_end.should == 0 # how far the parser got
|
|
1343
|
+
result.column_end.should == 11 # how far the parser got
|
|
1344
|
+
|
|
1345
|
+
# super with two params
|
|
1346
|
+
result = @parser.parse('#super "foo", "bar"')
|
|
1347
|
+
result.line_start.should == 0
|
|
1348
|
+
result.column_start.should == 0
|
|
1349
|
+
result.line_end.should == 0
|
|
1350
|
+
result.column_end.should == 19
|
|
1351
|
+
result.params.line_start.should == 0
|
|
1352
|
+
# result.params.column_start.should == 7 # get 0
|
|
1353
|
+
result.params.line_end.should == 0
|
|
1354
|
+
result.params.column_end.should == 19
|
|
1355
|
+
result.params[0].line_start.should == 0
|
|
1356
|
+
result.params[0].column_start.should == 7
|
|
1357
|
+
result.params[0].line_end.should == 0
|
|
1358
|
+
result.params[0].column_end.should == 12
|
|
1359
|
+
result.params[1].line_start.should == 0
|
|
1360
|
+
# result.params[1].column_start.should == 14 # get 12
|
|
1361
|
+
result.params[1].line_end.should == 0
|
|
1362
|
+
result.params[1].column_end.should == 19
|
|
1363
|
+
|
|
1364
|
+
end
|
|
1365
|
+
|
|
1366
|
+
it 'ParseErrors should contain information about the location of the problem' do
|
|
1367
|
+
|
|
1368
|
+
# error at beginning of string (unknown directive)
|
|
1369
|
+
begin
|
|
1370
|
+
@parser.parse('#sooper')
|
|
1371
|
+
rescue Grammar::ParseError => e
|
|
1372
|
+
exception = e
|
|
1373
|
+
end
|
|
1374
|
+
exception.line_start.should == 0
|
|
1375
|
+
exception.column_start.should == 0
|
|
1376
|
+
exception.line_end.should == 0
|
|
1377
|
+
exception.column_end.should == 0
|
|
1378
|
+
|
|
1379
|
+
# error on second line (unknown directive)
|
|
1380
|
+
begin
|
|
1381
|
+
@parser.parse("## a comment\n#sooper")
|
|
1382
|
+
rescue Grammar::ParseError => e
|
|
1383
|
+
exception = e
|
|
1384
|
+
end
|
|
1385
|
+
exception.line_start.should == 0
|
|
1386
|
+
exception.column_start.should == 0
|
|
1387
|
+
exception.line_end.should == 1
|
|
1388
|
+
exception.column_end.should == 0
|
|
1389
|
+
|
|
1390
|
+
# error at end of second line (missing closing bracket)
|
|
1391
|
+
begin
|
|
1392
|
+
@parser.parse("## a comment\n#super (1, 2")
|
|
1393
|
+
rescue Grammar::ParseError => e
|
|
1394
|
+
exception = e
|
|
1395
|
+
end
|
|
1396
|
+
exception.line_start.should == 0
|
|
1397
|
+
exception.column_start.should == 0
|
|
1398
|
+
exception.line_end.should == 1
|
|
1399
|
+
# exception.column_end.should == 12 # returns 0, which is almost right... but we want the rightmost coordinate, not the beginning of the busted directive
|
|
1400
|
+
|
|
1401
|
+
# here the error was returned at line 1, column 0 (the very beginning of the #super directive)
|
|
1402
|
+
# but we really would have preferred it to be reported at column 12 (the missing closing bracket)
|
|
1403
|
+
# to get to the rightmost point the parser will have had to follow this path:
|
|
1404
|
+
# - try to scan a directive
|
|
1405
|
+
# - try to scan a super directive
|
|
1406
|
+
# - try to scan a parameter list
|
|
1407
|
+
# - try to scan a paremeter etc
|
|
1408
|
+
|
|
1409
|
+
end
|
|
1410
|
+
|
|
1411
|
+
it 'produced AST nodes should contain information about their location in the source file' do
|
|
1412
|
+
|
|
1413
|
+
end
|
|
1414
|
+
|
|
1415
|
+
end
|
|
1416
|
+
|
|
1417
|
+
end # module Walrus
|
|
1418
|
+
|