treetop 0.1.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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