nirvdrum-less 1.1.4

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.
Files changed (164) hide show
  1. data/.gitignore +4 -0
  2. data/LICENSE +179 -0
  3. data/README.md +39 -0
  4. data/Rakefile +90 -0
  5. data/VERSION +1 -0
  6. data/bin/lessc +86 -0
  7. data/less.gemspec +205 -0
  8. data/lib/ext.rb +62 -0
  9. data/lib/less.rb +33 -0
  10. data/lib/less/command.rb +106 -0
  11. data/lib/less/engine.rb +54 -0
  12. data/lib/less/engine/builder.rb +8 -0
  13. data/lib/less/engine/grammar/common.tt +29 -0
  14. data/lib/less/engine/grammar/entity.tt +139 -0
  15. data/lib/less/engine/grammar/less.tt +271 -0
  16. data/lib/less/engine/nodes.rb +9 -0
  17. data/lib/less/engine/nodes/element.rb +186 -0
  18. data/lib/less/engine/nodes/entity.rb +79 -0
  19. data/lib/less/engine/nodes/function.rb +79 -0
  20. data/lib/less/engine/nodes/literal.rb +167 -0
  21. data/lib/less/engine/nodes/property.rb +156 -0
  22. data/lib/less/engine/nodes/ruleset.rb +12 -0
  23. data/lib/less/engine/nodes/selector.rb +39 -0
  24. data/lib/vendor/treetop/.gitignore +7 -0
  25. data/lib/vendor/treetop/LICENSE +19 -0
  26. data/lib/vendor/treetop/README +164 -0
  27. data/lib/vendor/treetop/Rakefile +19 -0
  28. data/lib/vendor/treetop/benchmark/seqpar.gnuplot +15 -0
  29. data/lib/vendor/treetop/benchmark/seqpar.treetop +16 -0
  30. data/lib/vendor/treetop/benchmark/seqpar_benchmark.rb +107 -0
  31. data/lib/vendor/treetop/bin/tt +28 -0
  32. data/lib/vendor/treetop/lib/treetop.rb +8 -0
  33. data/lib/vendor/treetop/lib/treetop/bootstrap_gen_1_metagrammar.rb +45 -0
  34. data/lib/vendor/treetop/lib/treetop/compiler.rb +6 -0
  35. data/lib/vendor/treetop/lib/treetop/compiler/grammar_compiler.rb +42 -0
  36. data/lib/vendor/treetop/lib/treetop/compiler/lexical_address_space.rb +17 -0
  37. data/lib/vendor/treetop/lib/treetop/compiler/metagrammar.rb +3097 -0
  38. data/lib/vendor/treetop/lib/treetop/compiler/metagrammar.treetop +408 -0
  39. data/lib/vendor/treetop/lib/treetop/compiler/node_classes.rb +19 -0
  40. data/lib/vendor/treetop/lib/treetop/compiler/node_classes/anything_symbol.rb +18 -0
  41. data/lib/vendor/treetop/lib/treetop/compiler/node_classes/atomic_expression.rb +14 -0
  42. data/lib/vendor/treetop/lib/treetop/compiler/node_classes/character_class.rb +24 -0
  43. data/lib/vendor/treetop/lib/treetop/compiler/node_classes/choice.rb +31 -0
  44. data/lib/vendor/treetop/lib/treetop/compiler/node_classes/declaration_sequence.rb +24 -0
  45. data/lib/vendor/treetop/lib/treetop/compiler/node_classes/grammar.rb +28 -0
  46. data/lib/vendor/treetop/lib/treetop/compiler/node_classes/inline_module.rb +27 -0
  47. data/lib/vendor/treetop/lib/treetop/compiler/node_classes/nonterminal.rb +13 -0
  48. data/lib/vendor/treetop/lib/treetop/compiler/node_classes/optional.rb +19 -0
  49. data/lib/vendor/treetop/lib/treetop/compiler/node_classes/parenthesized_expression.rb +9 -0
  50. data/lib/vendor/treetop/lib/treetop/compiler/node_classes/parsing_expression.rb +138 -0
  51. data/lib/vendor/treetop/lib/treetop/compiler/node_classes/parsing_rule.rb +55 -0
  52. data/lib/vendor/treetop/lib/treetop/compiler/node_classes/predicate.rb +45 -0
  53. data/lib/vendor/treetop/lib/treetop/compiler/node_classes/repetition.rb +55 -0
  54. data/lib/vendor/treetop/lib/treetop/compiler/node_classes/sequence.rb +68 -0
  55. data/lib/vendor/treetop/lib/treetop/compiler/node_classes/terminal.rb +20 -0
  56. data/lib/vendor/treetop/lib/treetop/compiler/node_classes/transient_prefix.rb +9 -0
  57. data/lib/vendor/treetop/lib/treetop/compiler/node_classes/treetop_file.rb +9 -0
  58. data/lib/vendor/treetop/lib/treetop/compiler/ruby_builder.rb +113 -0
  59. data/lib/vendor/treetop/lib/treetop/ruby_extensions.rb +2 -0
  60. data/lib/vendor/treetop/lib/treetop/ruby_extensions/string.rb +42 -0
  61. data/lib/vendor/treetop/lib/treetop/runtime.rb +5 -0
  62. data/lib/vendor/treetop/lib/treetop/runtime/compiled_parser.rb +105 -0
  63. data/lib/vendor/treetop/lib/treetop/runtime/interval_skip_list.rb +4 -0
  64. data/lib/vendor/treetop/lib/treetop/runtime/interval_skip_list/head_node.rb +15 -0
  65. data/lib/vendor/treetop/lib/treetop/runtime/interval_skip_list/interval_skip_list.rb +200 -0
  66. data/lib/vendor/treetop/lib/treetop/runtime/interval_skip_list/node.rb +164 -0
  67. data/lib/vendor/treetop/lib/treetop/runtime/syntax_node.rb +72 -0
  68. data/lib/vendor/treetop/lib/treetop/runtime/terminal_parse_failure.rb +16 -0
  69. data/lib/vendor/treetop/lib/treetop/runtime/terminal_syntax_node.rb +17 -0
  70. data/lib/vendor/treetop/lib/treetop/version.rb +9 -0
  71. data/lib/vendor/treetop/spec/compiler/and_predicate_spec.rb +36 -0
  72. data/lib/vendor/treetop/spec/compiler/anything_symbol_spec.rb +44 -0
  73. data/lib/vendor/treetop/spec/compiler/character_class_spec.rb +182 -0
  74. data/lib/vendor/treetop/spec/compiler/choice_spec.rb +80 -0
  75. data/lib/vendor/treetop/spec/compiler/circular_compilation_spec.rb +28 -0
  76. data/lib/vendor/treetop/spec/compiler/failure_propagation_functional_spec.rb +21 -0
  77. data/lib/vendor/treetop/spec/compiler/grammar_compiler_spec.rb +84 -0
  78. data/lib/vendor/treetop/spec/compiler/grammar_spec.rb +41 -0
  79. data/lib/vendor/treetop/spec/compiler/nonterminal_symbol_spec.rb +40 -0
  80. data/lib/vendor/treetop/spec/compiler/not_predicate_spec.rb +38 -0
  81. data/lib/vendor/treetop/spec/compiler/one_or_more_spec.rb +35 -0
  82. data/lib/vendor/treetop/spec/compiler/optional_spec.rb +37 -0
  83. data/lib/vendor/treetop/spec/compiler/parenthesized_expression_spec.rb +19 -0
  84. data/lib/vendor/treetop/spec/compiler/parsing_rule_spec.rb +32 -0
  85. data/lib/vendor/treetop/spec/compiler/sequence_spec.rb +115 -0
  86. data/lib/vendor/treetop/spec/compiler/terminal_spec.rb +81 -0
  87. data/lib/vendor/treetop/spec/compiler/terminal_symbol_spec.rb +37 -0
  88. data/lib/vendor/treetop/spec/compiler/test_grammar.treetop +7 -0
  89. data/lib/vendor/treetop/spec/compiler/test_grammar.tt +7 -0
  90. data/lib/vendor/treetop/spec/compiler/test_grammar_do.treetop +7 -0
  91. data/lib/vendor/treetop/spec/compiler/zero_or_more_spec.rb +56 -0
  92. data/lib/vendor/treetop/spec/composition/a.treetop +11 -0
  93. data/lib/vendor/treetop/spec/composition/b.treetop +11 -0
  94. data/lib/vendor/treetop/spec/composition/c.treetop +10 -0
  95. data/lib/vendor/treetop/spec/composition/d.treetop +10 -0
  96. data/lib/vendor/treetop/spec/composition/f.treetop +17 -0
  97. data/lib/vendor/treetop/spec/composition/grammar_composition_spec.rb +40 -0
  98. data/lib/vendor/treetop/spec/composition/subfolder/e_includes_c.treetop +15 -0
  99. data/lib/vendor/treetop/spec/ruby_extensions/string_spec.rb +32 -0
  100. data/lib/vendor/treetop/spec/runtime/compiled_parser_spec.rb +101 -0
  101. data/lib/vendor/treetop/spec/runtime/interval_skip_list/delete_spec.rb +147 -0
  102. data/lib/vendor/treetop/spec/runtime/interval_skip_list/expire_range_spec.rb +349 -0
  103. data/lib/vendor/treetop/spec/runtime/interval_skip_list/insert_and_delete_node.rb +385 -0
  104. data/lib/vendor/treetop/spec/runtime/interval_skip_list/insert_spec.rb +660 -0
  105. data/lib/vendor/treetop/spec/runtime/interval_skip_list/interval_skip_list_spec.graffle +6175 -0
  106. data/lib/vendor/treetop/spec/runtime/interval_skip_list/interval_skip_list_spec.rb +58 -0
  107. data/lib/vendor/treetop/spec/runtime/interval_skip_list/palindromic_fixture.rb +23 -0
  108. data/lib/vendor/treetop/spec/runtime/interval_skip_list/palindromic_fixture_spec.rb +164 -0
  109. data/lib/vendor/treetop/spec/runtime/interval_skip_list/spec_helper.rb +84 -0
  110. data/lib/vendor/treetop/spec/runtime/syntax_node_spec.rb +53 -0
  111. data/lib/vendor/treetop/spec/spec_helper.rb +106 -0
  112. data/lib/vendor/treetop/spec/spec_suite.rb +4 -0
  113. data/lib/vendor/treetop/treetop.gemspec +17 -0
  114. data/spec/command_spec.rb +102 -0
  115. data/spec/css/accessors.css +18 -0
  116. data/spec/css/big.css +3768 -0
  117. data/spec/css/colors.css +11 -0
  118. data/spec/css/comments.css +9 -0
  119. data/spec/css/css-3.css +2 -0
  120. data/spec/css/css.css +45 -0
  121. data/spec/css/functions.css +6 -0
  122. data/spec/css/import.css +12 -0
  123. data/spec/css/lazy-eval.css +1 -0
  124. data/spec/css/mixins-args.css +0 -0
  125. data/spec/css/mixins.css +28 -0
  126. data/spec/css/operations.css +28 -0
  127. data/spec/css/parens.css +16 -0
  128. data/spec/css/rulesets.css +17 -0
  129. data/spec/css/scope.css +11 -0
  130. data/spec/css/selectors.css +8 -0
  131. data/spec/css/strings.css +12 -0
  132. data/spec/css/variables.css +6 -0
  133. data/spec/css/whitespace.css +11 -0
  134. data/spec/engine_spec.rb +111 -0
  135. data/spec/less/accessors.less +20 -0
  136. data/spec/less/big.less +4810 -0
  137. data/spec/less/colors.less +34 -0
  138. data/spec/less/comments.less +46 -0
  139. data/spec/less/css-3.less +11 -0
  140. data/spec/less/css.less +98 -0
  141. data/spec/less/exceptions/mixed-units-error.less +3 -0
  142. data/spec/less/exceptions/name-error-1.0.less +3 -0
  143. data/spec/less/exceptions/syntax-error-1.0.less +3 -0
  144. data/spec/less/functions.less +6 -0
  145. data/spec/less/import.less +7 -0
  146. data/spec/less/import/import-test-a.less +2 -0
  147. data/spec/less/import/import-test-b.less +8 -0
  148. data/spec/less/import/import-test-c.less +6 -0
  149. data/spec/less/import/import-test-d.css +1 -0
  150. data/spec/less/lazy-eval.less +6 -0
  151. data/spec/less/mixins-args.less +0 -0
  152. data/spec/less/mixins.less +43 -0
  153. data/spec/less/operations.less +39 -0
  154. data/spec/less/parens.less +21 -0
  155. data/spec/less/rulesets.less +30 -0
  156. data/spec/less/scope.less +32 -0
  157. data/spec/less/selectors.less +15 -0
  158. data/spec/less/strings.less +14 -0
  159. data/spec/less/variables.less +18 -0
  160. data/spec/less/whitespace.less +30 -0
  161. data/spec/spec.css +82 -0
  162. data/spec/spec.less +148 -0
  163. data/spec/spec_helper.rb +8 -0
  164. metadata +219 -0
@@ -0,0 +1,80 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../spec_helper")
2
+
3
+ module ChoiceSpec
4
+ describe "A choice between terminal symbols" do
5
+ testing_expression '"foo" { def foo_method; end } / "bar" { def bar_method; end } / "baz" { def baz_method; end }'
6
+
7
+ it "successfully parses input matching any of the alternatives, returning a node that responds to methods defined in its respective inline module" do
8
+ result = parse('foo')
9
+ result.should_not be_nil
10
+ result.should respond_to(:foo_method)
11
+
12
+ result = parse('bar')
13
+ result.should_not be_nil
14
+ result.should respond_to(:bar_method)
15
+
16
+ result = parse('baz')
17
+ result.should_not be_nil
18
+ result.should respond_to(:baz_method)
19
+ end
20
+
21
+ it "upon parsing a string matching the second alternative, records the failure of the first terminal" do
22
+ result = parse('bar')
23
+ terminal_failures = parser.terminal_failures
24
+ terminal_failures.size.should == 1
25
+ failure = terminal_failures[0]
26
+ failure.expected_string.should == 'foo'
27
+ failure.index.should == 0
28
+ end
29
+
30
+ it "upon parsing a string matching the third alternative, records the failure of the first two terminals" do
31
+ result = parse('baz')
32
+
33
+ terminal_failures = parser.terminal_failures
34
+
35
+ terminal_failures.size.should == 2
36
+
37
+ failure_1 = terminal_failures[0]
38
+ failure_1.expected_string == 'foo'
39
+ failure_1.index.should == 0
40
+
41
+ failure_2 = terminal_failures[1]
42
+ failure_2.expected_string == 'bar'
43
+ failure_2.index.should == 0
44
+ end
45
+ end
46
+
47
+ describe "A choice between sequences" do
48
+ testing_expression "'foo' 'bar' 'baz'\n/\n'bing' 'bang' 'boom'"
49
+
50
+ it "successfully parses input matching any of the alternatives" do
51
+ parse('foobarbaz').should_not be_nil
52
+ parse('bingbangboom').should_not be_nil
53
+ end
54
+ end
55
+
56
+ describe "A choice between terminals followed by a block" do
57
+ testing_expression "('a'/ 'b' / 'c') { def a_method; end }"
58
+
59
+ it "extends a match of any of its subexpressions with a module created from the block" do
60
+ ['a', 'b', 'c'].each do |letter|
61
+ parse(letter).should respond_to(:a_method)
62
+ end
63
+ end
64
+ end
65
+
66
+ module TestModule
67
+ def a_method
68
+ end
69
+ end
70
+
71
+ describe "a choice followed by a declared module" do
72
+ testing_expression "('a'/ 'b' / 'c') <ChoiceSpec::TestModule>"
73
+
74
+ it "extends a match of any of its subexpressions with a module created from the block" do
75
+ ['a', 'b', 'c'].each do |letter|
76
+ parse(letter).should respond_to(:a_method)
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,28 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../spec_helper")
2
+ BENCHMARK = false
3
+
4
+ module CircularCompilationSpec
5
+ describe "a parser for the metagrammar" do
6
+ attr_reader :parser
7
+
8
+ before do
9
+ @parser = Treetop::Compiler::MetagrammarParser.new
10
+ end
11
+
12
+ it "can parse the metagrammar.treetop whence it was generated" do
13
+ File.open(METAGRAMMAR_PATH, 'r') do |f|
14
+ metagrammar_source = f.read
15
+ result = parser.parse(metagrammar_source)
16
+ result.should_not be_nil
17
+
18
+ # generated_parser = result.compile
19
+ # Object.class_eval(generated_parser)
20
+ # parser_2 = Treetop::Compiler::MetagrammarParser.new
21
+ # optionally_benchmark do
22
+ # result = parser_2.parse(metagrammar_source)
23
+ # result.should_not be_nil
24
+ # end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,21 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../spec_helper")
2
+
3
+ describe "An expression for braces surrounding zero or more letters followed by semicolons" do
4
+ testing_expression "'{' ([a-z] ';')* '}'"
5
+
6
+ it "parses matching input successfully" do
7
+ parse('{a;b;c;}').should_not be_nil
8
+ end
9
+
10
+ it "fails to parse input with an expression that is missing a semicolon, reporting the terminal failure occurring at the maximum index" do
11
+ parse('{a;b;c}') do |result|
12
+ result.should be_nil
13
+
14
+ terminal_failures = parser.terminal_failures
15
+ terminal_failures.size.should == 1
16
+ failure = terminal_failures[0]
17
+ failure.index.should == 6
18
+ failure.expected_string.should == ';'
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,84 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../spec_helper")
2
+
3
+ describe Compiler::GrammarCompiler do
4
+ attr_reader :compiler, :source_path_with_treetop_extension, :source_path_with_tt_extension, :target_path, :alternate_target_path
5
+ before do
6
+ @compiler = Compiler::GrammarCompiler.new
7
+
8
+ dir = File.dirname(__FILE__)
9
+ @source_path_with_treetop_extension = "#{dir}/test_grammar.treetop"
10
+ @source_path_with_do = "#{dir}/test_grammar_do.treetop"
11
+ @source_path_with_tt_extension = "#{dir}/test_grammar.tt"
12
+ @target_path = "#{dir}/test_grammar.rb"
13
+ @target_path_with_do = "#{dir}/test_grammar_do.rb"
14
+ @alternate_target_path = "#{dir}/test_grammar_alt.rb"
15
+ delete_target_files
16
+ end
17
+
18
+ after do
19
+ delete_target_files
20
+ Object.class_eval do
21
+ remove_const(:Test) if const_defined?(:Test)
22
+ end
23
+ end
24
+
25
+ specify "compilation of a single file to a default file name" do
26
+ File.exists?(target_path).should be_false
27
+ compiler.compile(source_path_with_treetop_extension)
28
+ File.exists?(target_path).should be_true
29
+ require target_path
30
+ Test::GrammarParser.new.parse('foo').should_not be_nil
31
+ end
32
+
33
+ specify "compilation of a single file to an explicit file name" do
34
+ File.exists?(alternate_target_path).should be_false
35
+ compiler.compile(source_path_with_treetop_extension, alternate_target_path)
36
+ File.exists?(alternate_target_path).should be_true
37
+ require alternate_target_path
38
+ Test::GrammarParser.new.parse('foo').should_not be_nil
39
+ end
40
+
41
+ specify "compilation of a single file without writing it to an output file" do
42
+ compiler.ruby_source(source_path_with_treetop_extension).should_not be_nil
43
+ end
44
+
45
+ specify "ruby_source_from_string compiles a grammar stored in string" do
46
+ compiler.ruby_source_from_string(File.read(source_path_with_treetop_extension)).should_not be_nil
47
+ end
48
+
49
+ specify "Treetop.load_from_string compiles and evaluates a source grammar stored in string" do
50
+ Treetop.load_from_string File.read(source_path_with_treetop_extension)
51
+ Test::GrammarParser.new.parse('foo').should_not be_nil
52
+ end
53
+
54
+ specify "Treetop.load compiles and evaluates a source grammar with a .treetop extension" do
55
+ Treetop.load source_path_with_treetop_extension
56
+ Test::GrammarParser.new.parse('foo').should_not be_nil
57
+ end
58
+
59
+ specify "Treetop.load compiles and evaluates a source grammar with a .tt extension" do
60
+ path_without_extension = source_path_with_tt_extension
61
+ Treetop.load path_without_extension
62
+ Test::GrammarParser.new.parse('foo').should_not be_nil
63
+ end
64
+
65
+
66
+ specify "Treetop.load compiles and evaluates source grammar with no extension" do
67
+ path_without_extension = source_path_with_treetop_extension.gsub(/\.treetop\Z/, '')
68
+ Treetop.load path_without_extension
69
+ Test::GrammarParser.new.parse('foo').should_not be_nil
70
+ end
71
+
72
+ specify "grammars with 'do' compile" do
73
+ compiler.compile(@source_path_with_do)
74
+ require @target_path_with_do
75
+ Test::GrammarParser.new.parse('foo').should_not be_nil
76
+ end
77
+
78
+ def delete_target_files
79
+ File.delete(target_path) if File.exists?(target_path)
80
+ File.delete(@target_path_with_do) if File.exists?(@target_path_with_do)
81
+ File.delete(alternate_target_path) if File.exists?(alternate_target_path)
82
+ end
83
+ end
84
+
@@ -0,0 +1,41 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../spec_helper")
2
+
3
+ module GrammarSpec
4
+ module Bar
5
+ end
6
+
7
+ describe "a grammar" do
8
+ testing_grammar %{
9
+ grammar Foo
10
+ # This comment should not cause a syntax error, nor should the following empty one
11
+ #
12
+ include GrammarSpec::Bar
13
+
14
+ rule foo
15
+ bar / baz
16
+ end
17
+
18
+ rule bar
19
+ 'bar' 'bar'
20
+ end
21
+
22
+ rule baz
23
+ 'baz' 'baz'
24
+ end
25
+ end
26
+ }
27
+
28
+ it "parses matching input" do
29
+ parse('barbar').should_not be_nil
30
+ parse('bazbaz').should_not be_nil
31
+ end
32
+
33
+ it "fails if it does not parse all input" do
34
+ parse('barbarbazbaz').should be_nil
35
+ end
36
+
37
+ it "mixes in included modules" do
38
+ self.class.const_get(:Foo).ancestors.should include(GrammarSpec::Bar)
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,40 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../spec_helper")
2
+
3
+ module NonterminalSymbolSpec
4
+ describe "A nonterminal symbol followed by a block" do
5
+ testing_expression 'foo { def a_method; end }'
6
+
7
+ parser_class_under_test.class_eval do
8
+ def _nt_foo
9
+ '_nt_foo called'
10
+ end
11
+ end
12
+
13
+ it "compiles to a method call, extending its results with the anonymous module for the block" do
14
+ result = parse('')
15
+ result.should == '_nt_foo called'
16
+ result.should respond_to(:a_method)
17
+ end
18
+ end
19
+
20
+ module TestModule
21
+ def a_method
22
+ end
23
+ end
24
+
25
+ describe "a non-terminal followed by a module declaration" do
26
+ testing_expression 'foo <NonterminalSymbolSpec::TestModule>'
27
+
28
+ parser_class_under_test.class_eval do
29
+ def _nt_foo
30
+ '_nt_foo called'
31
+ end
32
+ end
33
+
34
+ it "compiles to a method call, extending its results with the anonymous module for the block" do
35
+ result = parse('')
36
+ result.should == '_nt_foo called'
37
+ result.should respond_to(:a_method)
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,38 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../spec_helper")
2
+
3
+ module NotPredicateSpec
4
+ describe "A !-predicated terminal symbol" do
5
+ testing_expression '!"foo"'
6
+
7
+ it "fails to parse input matching the terminal symbol" do
8
+ parse('foo').should be_nil
9
+ end
10
+ end
11
+
12
+ describe "A sequence of a terminal and an and another !-predicated terminal" do
13
+ testing_expression '"foo" !"bar"'
14
+
15
+ it "fails to match input matching both terminals" do
16
+ parse('foobar').should be_nil
17
+ end
18
+
19
+ it "successfully parses input matching the first terminal and not the second, reporting the parse failure of the second terminal" do
20
+ parse('foo') do |result|
21
+ result.should_not be_nil
22
+ terminal_failures = parser.terminal_failures
23
+ terminal_failures.size.should == 1
24
+ failure = terminal_failures.first
25
+ failure.index.should == 3
26
+ failure.expected_string.should == 'bar'
27
+ end
28
+ end
29
+ end
30
+
31
+ describe "A !-predicated sequence" do
32
+ testing_expression '!("a" "b" "c")'
33
+
34
+ it "fails to parse matching input" do
35
+ parse('abc').should be_nil
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,35 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../spec_helper")
2
+
3
+ module OneOrMoreSpec
4
+ class Foo < Treetop::Runtime::SyntaxNode
5
+ end
6
+
7
+ describe "one or more of a terminal symbol followed by a node class declaration and a block" do
8
+ testing_expression '"foo"+ <OneOrMoreSpec::Foo> { def a_method; end }'
9
+
10
+ it "fails to parse epsilon, reporting a failure" do
11
+ parse('') do |result|
12
+ result.should be_nil
13
+ terminal_failures = parser.terminal_failures
14
+ terminal_failures.size.should == 1
15
+ failure = terminal_failures.first
16
+ failure.index.should == 0
17
+ failure.expected_string.should == 'foo'
18
+ end
19
+ end
20
+
21
+ it "successfully parses two of that terminal in a row, returning an instance of the declared node class and reporting the failure the third parsing attempt" do
22
+ parse("foofoo") do |result|
23
+ result.should_not be_nil
24
+ result.should be_an_instance_of(Foo)
25
+ result.should respond_to(:a_method)
26
+
27
+ terminal_failures = parser.terminal_failures
28
+ terminal_failures.size.should == 1
29
+ failure = terminal_failures.first
30
+ failure.index.should == 6
31
+ failure.expected_string.should == 'foo'
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,37 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../spec_helper")
2
+
3
+ module OptionalSpec
4
+ describe "An optional terminal symbol" do
5
+ testing_expression '"foo"?'
6
+
7
+ it "parses input matching the terminal" do
8
+ parse('foo').should_not be_nil
9
+ end
10
+
11
+ it "parses epsilon, recording a failure" do
12
+ parse('') do |result|
13
+ result.should_not be_nil
14
+ result.interval.should == (0...0)
15
+
16
+ terminal_failures = parser.terminal_failures
17
+ terminal_failures.size.should == 1
18
+ failure = terminal_failures.first
19
+ failure.index.should == 0
20
+ failure.expected_string.should == 'foo'
21
+ end
22
+ end
23
+
24
+ it "parses input not matching the terminal, returning an epsilon result and recording a failure" do
25
+ parse('bar', :consume_all_input => false) do |result|
26
+ result.should_not be_nil
27
+ result.interval.should == (0...0)
28
+
29
+ terminal_failures = parser.terminal_failures
30
+ terminal_failures.size.should == 1
31
+ failure = terminal_failures.first
32
+ failure.index.should == 0
33
+ failure.expected_string.should == 'foo'
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,19 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../spec_helper")
2
+
3
+ module ParenthesizedExpressionSpec
4
+ describe "An unadorned expression inside of parentheses" do
5
+ testing_expression '("foo")'
6
+
7
+ it "should behave as normal" do
8
+ parse('foo').should_not be_nil
9
+ end
10
+ end
11
+
12
+ describe "A prefixed-expression inside of parentheses" do
13
+ testing_expression '(!"foo")'
14
+
15
+ it "should behave as normal" do
16
+ parse('foo').should be_nil
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,32 @@
1
+ require File.expand_path("#{File.dirname(__FILE__)}/../spec_helper")
2
+
3
+ module ParsingRuleSpec
4
+ describe "a grammar with one parsing rule" do
5
+
6
+ testing_grammar %{
7
+ grammar Foo
8
+ rule bar
9
+ "baz"
10
+ end
11
+ end
12
+ }
13
+
14
+ it "stores and retrieves nodes in its node cache" do
15
+ parser = self.class.const_get(:FooParser).new
16
+ parser.send(:prepare_to_parse, 'baz')
17
+ node_cache = parser.send(:node_cache)
18
+
19
+ node_cache[:bar][0].should be_nil
20
+
21
+ parser._nt_bar
22
+
23
+ cached_node = node_cache[:bar][0]
24
+ cached_node.should be_an_instance_of(Runtime::SyntaxNode)
25
+ cached_node.text_value.should == 'baz'
26
+
27
+ parser.instance_eval { @index = 0 }
28
+ parser._nt_bar.should equal(cached_node)
29
+ parser.index.should == cached_node.interval.end
30
+ end
31
+ end
32
+ end