treetop 0.1.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (153) hide show
  1. data/README +3 -0
  2. data/Rakefile +35 -0
  3. data/bin/tt +25 -0
  4. data/lib/treetop.rb +10 -6
  5. data/lib/treetop/compiler.rb +7 -0
  6. data/lib/treetop/compiler/grammar_compiler.rb +21 -0
  7. data/lib/treetop/compiler/lexical_address_space.rb +17 -0
  8. data/lib/treetop/compiler/load_grammar.rb +7 -0
  9. data/lib/treetop/compiler/metagrammar.rb +2441 -0
  10. data/lib/treetop/compiler/metagrammar.treetop +384 -0
  11. data/lib/treetop/compiler/node_classes.rb +18 -0
  12. data/lib/treetop/compiler/node_classes/anything_symbol.rb +10 -0
  13. data/lib/treetop/compiler/node_classes/atomic_expression.rb +9 -0
  14. data/lib/treetop/compiler/node_classes/character_class.rb +10 -0
  15. data/lib/treetop/compiler/node_classes/choice.rb +31 -0
  16. data/lib/treetop/compiler/node_classes/declaration_sequence.rb +24 -0
  17. data/lib/treetop/compiler/node_classes/grammar.rb +28 -0
  18. data/lib/treetop/compiler/node_classes/inline_module.rb +27 -0
  19. data/lib/treetop/compiler/node_classes/nonterminal.rb +11 -0
  20. data/lib/treetop/compiler/node_classes/optional.rb +19 -0
  21. data/lib/treetop/compiler/node_classes/parenthesized_expression.rb +9 -0
  22. data/lib/treetop/compiler/node_classes/parsing_expression.rb +132 -0
  23. data/lib/treetop/compiler/node_classes/parsing_rule.rb +55 -0
  24. data/lib/treetop/compiler/node_classes/predicate.rb +45 -0
  25. data/lib/treetop/compiler/node_classes/repetition.rb +56 -0
  26. data/lib/treetop/compiler/node_classes/sequence.rb +64 -0
  27. data/lib/treetop/compiler/node_classes/terminal.rb +10 -0
  28. data/lib/treetop/compiler/node_classes/treetop_file.rb +9 -0
  29. data/lib/treetop/compiler/ruby_builder.rb +109 -0
  30. data/lib/treetop/ruby_extensions.rb +2 -0
  31. data/lib/treetop/ruby_extensions/string.rb +19 -0
  32. data/lib/treetop/runtime.rb +9 -0
  33. data/lib/treetop/runtime/compiled_parser.rb +66 -0
  34. data/lib/treetop/runtime/node_cache.rb +27 -0
  35. data/lib/treetop/runtime/parse_cache.rb +19 -0
  36. data/lib/treetop/runtime/parse_failure.rb +32 -0
  37. data/lib/treetop/runtime/parse_result.rb +30 -0
  38. data/lib/treetop/runtime/syntax_node.rb +53 -0
  39. data/lib/treetop/runtime/terminal_parse_failure.rb +33 -0
  40. data/lib/treetop/runtime/terminal_syntax_node.rb +12 -0
  41. data/test/compilation_target/target.rb +143 -0
  42. data/test/compilation_target/target.treetop +15 -0
  43. data/test/compilation_target/target_test.rb +56 -0
  44. data/test/compiler/and_predicate_test.rb +33 -0
  45. data/test/compiler/anything_symbol_test.rb +24 -0
  46. data/test/compiler/character_class_test.rb +45 -0
  47. data/test/compiler/choice_test.rb +49 -0
  48. data/test/compiler/circular_compilation_test.rb +20 -0
  49. data/test/compiler/failure_propagation_functional_test.rb +20 -0
  50. data/test/compiler/grammar_compiler_test.rb +58 -0
  51. data/test/compiler/grammar_test.rb +33 -0
  52. data/test/compiler/nonterminal_symbol_test.rb +15 -0
  53. data/test/compiler/not_predicate_test.rb +35 -0
  54. data/test/compiler/one_or_more_test.rb +30 -0
  55. data/test/compiler/optional_test.rb +32 -0
  56. data/test/compiler/parsing_rule_test.rb +30 -0
  57. data/test/compiler/sequence_test.rb +68 -0
  58. data/test/compiler/terminal_symbol_test.rb +35 -0
  59. data/test/compiler/test_grammar.treetop +7 -0
  60. data/test/compiler/zero_or_more_test.rb +51 -0
  61. data/test/composition/a.treetop +11 -0
  62. data/test/composition/b.treetop +11 -0
  63. data/test/composition/c.treetop +10 -0
  64. data/test/composition/d.treetop +10 -0
  65. data/test/composition/grammar_composition_test.rb +23 -0
  66. data/test/parser/syntax_node_test.rb +53 -0
  67. data/test/parser/terminal_parse_failure_test.rb +22 -0
  68. data/test/ruby_extensions/string_test.rb +33 -0
  69. data/test/screw/Rakefile +16 -0
  70. data/test/screw/unit.rb +37 -0
  71. data/test/screw/unit/assertion_failed_error.rb +14 -0
  72. data/test/screw/unit/assertions.rb +615 -0
  73. data/test/screw/unit/auto_runner.rb +227 -0
  74. data/test/screw/unit/collector.rb +45 -0
  75. data/test/screw/unit/collector/dir.rb +107 -0
  76. data/test/screw/unit/collector/objectspace.rb +28 -0
  77. data/test/screw/unit/error.rb +48 -0
  78. data/test/screw/unit/failure.rb +45 -0
  79. data/test/screw/unit/sugar.rb +25 -0
  80. data/test/screw/unit/test_case.rb +176 -0
  81. data/test/screw/unit/test_result.rb +73 -0
  82. data/test/screw/unit/test_suite.rb +70 -0
  83. data/test/screw/unit/ui.rb +4 -0
  84. data/test/screw/unit/ui/console/test_runner.rb +118 -0
  85. data/test/screw/unit/ui/fox/test_runner.rb +268 -0
  86. data/test/screw/unit/ui/gtk/test_runner.rb +416 -0
  87. data/test/screw/unit/ui/gtk2/testrunner.rb +465 -0
  88. data/test/screw/unit/ui/test_runner_mediator.rb +58 -0
  89. data/test/screw/unit/ui/test_runner_utilities.rb +46 -0
  90. data/test/screw/unit/ui/tk/test_runner.rb +260 -0
  91. data/test/screw/unit/util.rb +4 -0
  92. data/test/screw/unit/util/backtrace_filter.rb +40 -0
  93. data/test/screw/unit/util/observable.rb +82 -0
  94. data/test/screw/unit/util/proc_wrapper.rb +48 -0
  95. data/test/test_helper.rb +89 -0
  96. metadata +127 -69
  97. data/lib/treetop/api.rb +0 -3
  98. data/lib/treetop/api/load_grammar.rb +0 -16
  99. data/lib/treetop/api/malformed_grammar_exception.rb +0 -9
  100. data/lib/treetop/grammar.rb +0 -7
  101. data/lib/treetop/grammar/grammar.rb +0 -48
  102. data/lib/treetop/grammar/grammar_builder.rb +0 -35
  103. data/lib/treetop/grammar/parsing_expression_builder.rb +0 -5
  104. data/lib/treetop/grammar/parsing_expression_builder_helper.rb +0 -121
  105. data/lib/treetop/grammar/parsing_expressions.rb +0 -18
  106. data/lib/treetop/grammar/parsing_expressions/and_predicate.rb +0 -17
  107. data/lib/treetop/grammar/parsing_expressions/anything_symbol.rb +0 -20
  108. data/lib/treetop/grammar/parsing_expressions/character_class.rb +0 -24
  109. data/lib/treetop/grammar/parsing_expressions/node_instantiating_parsing_expression.rb +0 -14
  110. data/lib/treetop/grammar/parsing_expressions/node_propagating_parsing_expression.rb +0 -4
  111. data/lib/treetop/grammar/parsing_expressions/nonterminal_symbol.rb +0 -42
  112. data/lib/treetop/grammar/parsing_expressions/not_predicate.rb +0 -18
  113. data/lib/treetop/grammar/parsing_expressions/one_or_more.rb +0 -12
  114. data/lib/treetop/grammar/parsing_expressions/optional.rb +0 -14
  115. data/lib/treetop/grammar/parsing_expressions/ordered_choice.rb +0 -27
  116. data/lib/treetop/grammar/parsing_expressions/parsing_expression.rb +0 -36
  117. data/lib/treetop/grammar/parsing_expressions/predicate.rb +0 -25
  118. data/lib/treetop/grammar/parsing_expressions/repeating_parsing_expression.rb +0 -29
  119. data/lib/treetop/grammar/parsing_expressions/sequence.rb +0 -41
  120. data/lib/treetop/grammar/parsing_expressions/terminal_parsing_expression.rb +0 -11
  121. data/lib/treetop/grammar/parsing_expressions/terminal_symbol.rb +0 -31
  122. data/lib/treetop/grammar/parsing_expressions/zero_or_more.rb +0 -11
  123. data/lib/treetop/grammar/parsing_rule.rb +0 -10
  124. data/lib/treetop/metagrammar.rb +0 -2
  125. data/lib/treetop/metagrammar/metagrammar.rb +0 -14
  126. data/lib/treetop/metagrammar/metagrammar.treetop +0 -320
  127. data/lib/treetop/parser.rb +0 -11
  128. data/lib/treetop/parser/node_cache.rb +0 -25
  129. data/lib/treetop/parser/parse_cache.rb +0 -17
  130. data/lib/treetop/parser/parse_failure.rb +0 -22
  131. data/lib/treetop/parser/parse_result.rb +0 -26
  132. data/lib/treetop/parser/parser.rb +0 -24
  133. data/lib/treetop/parser/sequence_syntax_node.rb +0 -14
  134. data/lib/treetop/parser/syntax_node.rb +0 -31
  135. data/lib/treetop/parser/terminal_parse_failure.rb +0 -18
  136. data/lib/treetop/parser/terminal_syntax_node.rb +0 -7
  137. data/lib/treetop/protometagrammar.rb +0 -16
  138. data/lib/treetop/protometagrammar/anything_symbol_expression_builder.rb +0 -13
  139. data/lib/treetop/protometagrammar/block_expression_builder.rb +0 -17
  140. data/lib/treetop/protometagrammar/character_class_expression_builder.rb +0 -25
  141. data/lib/treetop/protometagrammar/grammar_expression_builder.rb +0 -38
  142. data/lib/treetop/protometagrammar/nonterminal_symbol_expression_builder.rb +0 -45
  143. data/lib/treetop/protometagrammar/ordered_choice_expression_builder.rb +0 -21
  144. data/lib/treetop/protometagrammar/parsing_rule_expression_builder.rb +0 -23
  145. data/lib/treetop/protometagrammar/parsing_rule_sequence_expression_builder.rb +0 -14
  146. data/lib/treetop/protometagrammar/prefix_expression_builder.rb +0 -25
  147. data/lib/treetop/protometagrammar/primary_expression_builder.rb +0 -71
  148. data/lib/treetop/protometagrammar/protometagrammar.rb +0 -25
  149. data/lib/treetop/protometagrammar/sequence_expression_builder.rb +0 -37
  150. data/lib/treetop/protometagrammar/suffix_expression_builder.rb +0 -33
  151. data/lib/treetop/protometagrammar/terminal_symbol_expression_builder.rb +0 -52
  152. data/lib/treetop/protometagrammar/trailing_block_expression_builder.rb +0 -30
  153. data/lib/treetop/ruby_extension.rb +0 -11
@@ -0,0 +1,10 @@
1
+ module Treetop
2
+ module Compiler
3
+ class Terminal < AtomicExpression
4
+ def compile(address, builder, parent_expression = nil)
5
+ super
6
+ assign_result "parse_terminal(#{text_value}, #{node_class}#{optional_arg(inline_module_name)})"
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,9 @@
1
+ module Treetop
2
+ module Compiler
3
+ class TreetopFile < Runtime::SyntaxNode
4
+ def compile
5
+ (elements.map {|elt| elt.compile}).join
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,109 @@
1
+ module Treetop
2
+ module Compiler
3
+ class RubyBuilder
4
+
5
+ attr_reader :level, :address_space, :ruby
6
+
7
+ def initialize
8
+ @level = 0
9
+ @address_space = LexicalAddressSpace.new
10
+ @ruby = ""
11
+ end
12
+
13
+ def <<(ruby_line)
14
+ return if ruby_line.blank?
15
+ ruby << ruby_line.tabto(level) << "\n"
16
+ end
17
+
18
+ def newline
19
+ ruby << indent << "\n"
20
+ end
21
+
22
+ def indented(depth = 2)
23
+ self.in(depth)
24
+ yield
25
+ self.out(depth)
26
+ end
27
+
28
+ def class_declaration(name, &block)
29
+ self << "class #{name}"
30
+ indented(&block)
31
+ self << "end"
32
+ end
33
+
34
+ def module_declaration(name, &block)
35
+ self << "module #{name}"
36
+ indented(&block)
37
+ self << "end"
38
+ end
39
+
40
+ def method_declaration(name, &block)
41
+ self << "def #{name}"
42
+ indented(&block)
43
+ self << "end"
44
+ end
45
+
46
+ def assign(left, right)
47
+ if left.instance_of? Array
48
+ self << "#{left.join(', ')} = #{right.join(', ')}"
49
+ else
50
+ self << "#{left} = #{right}"
51
+ end
52
+ end
53
+
54
+ def accumulate(left, right)
55
+ self << "#{left} << #{right}"
56
+ end
57
+
58
+ def if__(condition, &block)
59
+ self << "if #{condition}"
60
+ indented(&block)
61
+ end
62
+
63
+ def if_(condition, &block)
64
+ if__(condition, &block)
65
+ self << 'end'
66
+ end
67
+
68
+ def else_(&block)
69
+ self << 'else'
70
+ indented(&block)
71
+ self << 'end'
72
+ end
73
+
74
+ def loop(&block)
75
+ self << 'loop do'
76
+ indented(&block)
77
+ self << 'end'
78
+ end
79
+
80
+ def break
81
+ self << 'break'
82
+ end
83
+
84
+ def in(depth = 2)
85
+ @level += depth
86
+ self
87
+ end
88
+
89
+ def out(depth = 2)
90
+ @level -= depth
91
+ self
92
+ end
93
+
94
+ def next_address
95
+ address_space.next_address
96
+ end
97
+
98
+ def reset_addresses
99
+ address_space.reset_addresses
100
+ end
101
+
102
+ protected
103
+
104
+ def indent
105
+ " " * level
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,2 @@
1
+ dir = File.dirname(__FILE__)
2
+ require "#{dir}/ruby_extensions/string"
@@ -0,0 +1,19 @@
1
+ class String
2
+ def column_of(index)
3
+ return 1 if index == 0
4
+ newline_index = rindex("\n", index - 1)
5
+ if newline_index
6
+ index - newline_index
7
+ else
8
+ index + 1
9
+ end
10
+ end
11
+
12
+ def line_of(index)
13
+ self[0...index].count("\n") + 1
14
+ end
15
+
16
+ def blank?
17
+ self == ""
18
+ end
19
+ end
@@ -0,0 +1,9 @@
1
+ dir = File.dirname(__FILE__)
2
+ require "#{dir}/runtime/compiled_parser"
3
+ require "#{dir}/runtime/parse_result"
4
+ require "#{dir}/runtime/syntax_node"
5
+ require "#{dir}/runtime/parse_failure"
6
+ require "#{dir}/runtime/node_cache"
7
+ require "#{dir}/runtime/parse_cache"
8
+ require "#{dir}/runtime/parse_failure"
9
+ require "#{dir}/runtime/terminal_parse_failure"
@@ -0,0 +1,66 @@
1
+ module Treetop
2
+ module Runtime
3
+ class CompiledParser
4
+ include Treetop::Runtime
5
+
6
+ attr_reader :input, :index
7
+
8
+ def parse(input)
9
+ prepare_to_parse(input)
10
+ return root
11
+ end
12
+
13
+ protected
14
+
15
+ attr_reader :node_cache
16
+ attr_writer :index
17
+
18
+ def prepare_to_parse(input)
19
+ @input = input
20
+ reset_index
21
+ @node_cache = Hash.new {|hash, key| hash[key] = Hash.new}
22
+ end
23
+
24
+ def reset_index
25
+ @index = 0
26
+ end
27
+
28
+ def parse_char_class(char_class_re, char_class_string, node_class = SyntaxNode, inline_module = nil)
29
+ if input.index(char_class_re, index) == index
30
+ result = node_class.new(input, index...(index + 1))
31
+ result.extend(inline_module) if inline_module
32
+ @index += 1
33
+ result
34
+ else
35
+ terminal_parse_failure("[#{char_class_string}]")
36
+ end
37
+ end
38
+
39
+ def parse_terminal(terminal_string, node_class = SyntaxNode, inline_module = nil)
40
+ if input.index(terminal_string, index) == index
41
+ result = node_class.new(input, index...(index + terminal_string.length))
42
+ result.extend(inline_module) if inline_module
43
+ @index += terminal_string.length
44
+ result
45
+ else
46
+ terminal_parse_failure(terminal_string)
47
+ end
48
+ end
49
+
50
+ def parse_anything(node_class = SyntaxNode, inline_module = nil)
51
+ if index < input.length
52
+ result = node_class.new(input, index...(index + 1))
53
+ result.extend(inline_module) if inline_module
54
+ @index += 1
55
+ result
56
+ else
57
+ terminal_parse_failure("any character")
58
+ end
59
+ end
60
+
61
+ def terminal_parse_failure(expected_string)
62
+ TerminalParseFailure.new(input, index, expected_string)
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,27 @@
1
+ module Treetop
2
+ module Runtime
3
+ class NodeCache
4
+ attr_reader :parse_results
5
+
6
+ def initialize
7
+ @parse_results = {}
8
+ end
9
+
10
+ def empty?
11
+ parse_results.empty?
12
+ end
13
+
14
+ def store(parse_result)
15
+ if parse_result.failure?
16
+ parse_results[parse_result.index] = parse_result
17
+ else
18
+ parse_results[parse_result.interval.begin] = parse_result
19
+ end
20
+ end
21
+
22
+ def [](start_index)
23
+ parse_results[start_index]
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,19 @@
1
+ module Treetop
2
+ module Runtime
3
+ class ParseCache
4
+ attr_reader :node_caches
5
+
6
+ def initialize
7
+ @node_caches = {}
8
+ end
9
+
10
+ def [](parsing_expression)
11
+ node_caches[parsing_expression] ||= NodeCache.new
12
+ end
13
+
14
+ def empty?
15
+ node_caches.empty?
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,32 @@
1
+ module Treetop
2
+ module Runtime
3
+ class ParseFailure < ParseResult
4
+ attr_reader :index
5
+
6
+ def initialize(input, index, nested_results = [])
7
+ super(input, nested_results)
8
+ @index = index
9
+ end
10
+
11
+ def line
12
+ input.line_of(index)
13
+ end
14
+
15
+ def column
16
+ input.column_of(index)
17
+ end
18
+
19
+ def success?
20
+ false
21
+ end
22
+
23
+ def failure?
24
+ true
25
+ end
26
+
27
+ def interval
28
+ @interval ||= (index...index)
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,30 @@
1
+ module Treetop
2
+ module Runtime
3
+ class ParseResult
4
+ attr_reader :input, :nested_failures
5
+
6
+ def initialize(input, nested_results = [])
7
+ @input = input
8
+ @nested_failures = collect_nested_failures_at_maximum_index(nested_results)
9
+ end
10
+
11
+ def collect_nested_failures_at_maximum_index(results)
12
+ maximum_index = 0
13
+ nested_failures = []
14
+
15
+ results.each do |result|
16
+ next if result.nested_failures.empty?
17
+ index_of_nested_failures = result.nested_failures.first.index
18
+ if index_of_nested_failures > maximum_index
19
+ maximum_index = index_of_nested_failures
20
+ nested_failures = result.nested_failures
21
+ elsif index_of_nested_failures == maximum_index
22
+ nested_failures += result.nested_failures
23
+ end
24
+ end
25
+
26
+ return nested_failures.uniq
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,53 @@
1
+ module Treetop
2
+ module Runtime
3
+ class SyntaxNode < ParseResult
4
+ attr_reader :input, :interval
5
+
6
+ def initialize(input, interval, elements = nil, nested_results = elements)
7
+ super(input, nested_results || [])
8
+ @interval = interval
9
+ @elements = elements
10
+ end
11
+
12
+ def success?
13
+ true
14
+ end
15
+
16
+ def failure?
17
+ false
18
+ end
19
+
20
+ def terminal?
21
+ @elements.nil?
22
+ end
23
+
24
+ def nonterminal?
25
+ !terminal?
26
+ end
27
+
28
+ def elements
29
+ @elements || [self]
30
+ end
31
+
32
+ def text_value
33
+ input[interval]
34
+ end
35
+
36
+ def update_nested_results(nested_results)
37
+ new_nested_failures = collect_nested_failures_at_maximum_index(nested_results)
38
+
39
+ return if new_nested_failures.empty?
40
+ @nested_failures = new_nested_failures and return if nested_failures.empty?
41
+
42
+ current_nested_failure_index = nested_failures.first.index
43
+ new_nested_failure_index = new_nested_failures.first.index
44
+
45
+ if new_nested_failure_index > current_nested_failure_index
46
+ @nested_failures = new_nested_failures
47
+ elsif new_nested_failure_index == current_nested_failure_index
48
+ @nested_failures += new_nested_failures
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,33 @@
1
+ module Treetop
2
+ module Runtime
3
+ class TerminalParseFailure < ParseFailure
4
+ attr_reader :expected_string
5
+
6
+ def initialize(input, index, expected_string)
7
+ super(input, index)
8
+ @expected_string = expected_string
9
+ end
10
+
11
+ def nested_failures
12
+ [self]
13
+ end
14
+
15
+ def to_s
16
+ "String matching #{expected_string} expected at line #{line}, column #{column} (index #{index})."
17
+ end
18
+
19
+ def ==(other_failure)
20
+ eql?(other_failure)
21
+ end
22
+
23
+ def eql?(other_failure)
24
+ return false unless other_failure.instance_of?(TerminalParseFailure)
25
+ expected_string.eql?(other_failure.expected_string) && index.eql?(other_failure.index)
26
+ end
27
+
28
+ def hash
29
+ [index, expected_string].hash
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,12 @@
1
+ module Treetop
2
+ module Runtime
3
+ class TerminalSyntaxNode < SyntaxNode
4
+
5
+ def initialize(input, interval)
6
+ super(input, interval, [])
7
+ end
8
+
9
+
10
+ end
11
+ end
12
+ end