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.
- data/README +3 -0
- data/Rakefile +35 -0
- data/bin/tt +25 -0
- data/lib/treetop.rb +10 -6
- data/lib/treetop/compiler.rb +7 -0
- data/lib/treetop/compiler/grammar_compiler.rb +21 -0
- data/lib/treetop/compiler/lexical_address_space.rb +17 -0
- data/lib/treetop/compiler/load_grammar.rb +7 -0
- data/lib/treetop/compiler/metagrammar.rb +2441 -0
- data/lib/treetop/compiler/metagrammar.treetop +384 -0
- data/lib/treetop/compiler/node_classes.rb +18 -0
- data/lib/treetop/compiler/node_classes/anything_symbol.rb +10 -0
- data/lib/treetop/compiler/node_classes/atomic_expression.rb +9 -0
- data/lib/treetop/compiler/node_classes/character_class.rb +10 -0
- data/lib/treetop/compiler/node_classes/choice.rb +31 -0
- data/lib/treetop/compiler/node_classes/declaration_sequence.rb +24 -0
- data/lib/treetop/compiler/node_classes/grammar.rb +28 -0
- data/lib/treetop/compiler/node_classes/inline_module.rb +27 -0
- data/lib/treetop/compiler/node_classes/nonterminal.rb +11 -0
- data/lib/treetop/compiler/node_classes/optional.rb +19 -0
- data/lib/treetop/compiler/node_classes/parenthesized_expression.rb +9 -0
- data/lib/treetop/compiler/node_classes/parsing_expression.rb +132 -0
- data/lib/treetop/compiler/node_classes/parsing_rule.rb +55 -0
- data/lib/treetop/compiler/node_classes/predicate.rb +45 -0
- data/lib/treetop/compiler/node_classes/repetition.rb +56 -0
- data/lib/treetop/compiler/node_classes/sequence.rb +64 -0
- data/lib/treetop/compiler/node_classes/terminal.rb +10 -0
- data/lib/treetop/compiler/node_classes/treetop_file.rb +9 -0
- data/lib/treetop/compiler/ruby_builder.rb +109 -0
- data/lib/treetop/ruby_extensions.rb +2 -0
- data/lib/treetop/ruby_extensions/string.rb +19 -0
- data/lib/treetop/runtime.rb +9 -0
- data/lib/treetop/runtime/compiled_parser.rb +66 -0
- data/lib/treetop/runtime/node_cache.rb +27 -0
- data/lib/treetop/runtime/parse_cache.rb +19 -0
- data/lib/treetop/runtime/parse_failure.rb +32 -0
- data/lib/treetop/runtime/parse_result.rb +30 -0
- data/lib/treetop/runtime/syntax_node.rb +53 -0
- data/lib/treetop/runtime/terminal_parse_failure.rb +33 -0
- data/lib/treetop/runtime/terminal_syntax_node.rb +12 -0
- data/test/compilation_target/target.rb +143 -0
- data/test/compilation_target/target.treetop +15 -0
- data/test/compilation_target/target_test.rb +56 -0
- data/test/compiler/and_predicate_test.rb +33 -0
- data/test/compiler/anything_symbol_test.rb +24 -0
- data/test/compiler/character_class_test.rb +45 -0
- data/test/compiler/choice_test.rb +49 -0
- data/test/compiler/circular_compilation_test.rb +20 -0
- data/test/compiler/failure_propagation_functional_test.rb +20 -0
- data/test/compiler/grammar_compiler_test.rb +58 -0
- data/test/compiler/grammar_test.rb +33 -0
- data/test/compiler/nonterminal_symbol_test.rb +15 -0
- data/test/compiler/not_predicate_test.rb +35 -0
- data/test/compiler/one_or_more_test.rb +30 -0
- data/test/compiler/optional_test.rb +32 -0
- data/test/compiler/parsing_rule_test.rb +30 -0
- data/test/compiler/sequence_test.rb +68 -0
- data/test/compiler/terminal_symbol_test.rb +35 -0
- data/test/compiler/test_grammar.treetop +7 -0
- data/test/compiler/zero_or_more_test.rb +51 -0
- data/test/composition/a.treetop +11 -0
- data/test/composition/b.treetop +11 -0
- data/test/composition/c.treetop +10 -0
- data/test/composition/d.treetop +10 -0
- data/test/composition/grammar_composition_test.rb +23 -0
- data/test/parser/syntax_node_test.rb +53 -0
- data/test/parser/terminal_parse_failure_test.rb +22 -0
- data/test/ruby_extensions/string_test.rb +33 -0
- data/test/screw/Rakefile +16 -0
- data/test/screw/unit.rb +37 -0
- data/test/screw/unit/assertion_failed_error.rb +14 -0
- data/test/screw/unit/assertions.rb +615 -0
- data/test/screw/unit/auto_runner.rb +227 -0
- data/test/screw/unit/collector.rb +45 -0
- data/test/screw/unit/collector/dir.rb +107 -0
- data/test/screw/unit/collector/objectspace.rb +28 -0
- data/test/screw/unit/error.rb +48 -0
- data/test/screw/unit/failure.rb +45 -0
- data/test/screw/unit/sugar.rb +25 -0
- data/test/screw/unit/test_case.rb +176 -0
- data/test/screw/unit/test_result.rb +73 -0
- data/test/screw/unit/test_suite.rb +70 -0
- data/test/screw/unit/ui.rb +4 -0
- data/test/screw/unit/ui/console/test_runner.rb +118 -0
- data/test/screw/unit/ui/fox/test_runner.rb +268 -0
- data/test/screw/unit/ui/gtk/test_runner.rb +416 -0
- data/test/screw/unit/ui/gtk2/testrunner.rb +465 -0
- data/test/screw/unit/ui/test_runner_mediator.rb +58 -0
- data/test/screw/unit/ui/test_runner_utilities.rb +46 -0
- data/test/screw/unit/ui/tk/test_runner.rb +260 -0
- data/test/screw/unit/util.rb +4 -0
- data/test/screw/unit/util/backtrace_filter.rb +40 -0
- data/test/screw/unit/util/observable.rb +82 -0
- data/test/screw/unit/util/proc_wrapper.rb +48 -0
- data/test/test_helper.rb +89 -0
- metadata +127 -69
- data/lib/treetop/api.rb +0 -3
- data/lib/treetop/api/load_grammar.rb +0 -16
- data/lib/treetop/api/malformed_grammar_exception.rb +0 -9
- data/lib/treetop/grammar.rb +0 -7
- data/lib/treetop/grammar/grammar.rb +0 -48
- data/lib/treetop/grammar/grammar_builder.rb +0 -35
- data/lib/treetop/grammar/parsing_expression_builder.rb +0 -5
- data/lib/treetop/grammar/parsing_expression_builder_helper.rb +0 -121
- data/lib/treetop/grammar/parsing_expressions.rb +0 -18
- data/lib/treetop/grammar/parsing_expressions/and_predicate.rb +0 -17
- data/lib/treetop/grammar/parsing_expressions/anything_symbol.rb +0 -20
- data/lib/treetop/grammar/parsing_expressions/character_class.rb +0 -24
- data/lib/treetop/grammar/parsing_expressions/node_instantiating_parsing_expression.rb +0 -14
- data/lib/treetop/grammar/parsing_expressions/node_propagating_parsing_expression.rb +0 -4
- data/lib/treetop/grammar/parsing_expressions/nonterminal_symbol.rb +0 -42
- data/lib/treetop/grammar/parsing_expressions/not_predicate.rb +0 -18
- data/lib/treetop/grammar/parsing_expressions/one_or_more.rb +0 -12
- data/lib/treetop/grammar/parsing_expressions/optional.rb +0 -14
- data/lib/treetop/grammar/parsing_expressions/ordered_choice.rb +0 -27
- data/lib/treetop/grammar/parsing_expressions/parsing_expression.rb +0 -36
- data/lib/treetop/grammar/parsing_expressions/predicate.rb +0 -25
- data/lib/treetop/grammar/parsing_expressions/repeating_parsing_expression.rb +0 -29
- data/lib/treetop/grammar/parsing_expressions/sequence.rb +0 -41
- data/lib/treetop/grammar/parsing_expressions/terminal_parsing_expression.rb +0 -11
- data/lib/treetop/grammar/parsing_expressions/terminal_symbol.rb +0 -31
- data/lib/treetop/grammar/parsing_expressions/zero_or_more.rb +0 -11
- data/lib/treetop/grammar/parsing_rule.rb +0 -10
- data/lib/treetop/metagrammar.rb +0 -2
- data/lib/treetop/metagrammar/metagrammar.rb +0 -14
- data/lib/treetop/metagrammar/metagrammar.treetop +0 -320
- data/lib/treetop/parser.rb +0 -11
- data/lib/treetop/parser/node_cache.rb +0 -25
- data/lib/treetop/parser/parse_cache.rb +0 -17
- data/lib/treetop/parser/parse_failure.rb +0 -22
- data/lib/treetop/parser/parse_result.rb +0 -26
- data/lib/treetop/parser/parser.rb +0 -24
- data/lib/treetop/parser/sequence_syntax_node.rb +0 -14
- data/lib/treetop/parser/syntax_node.rb +0 -31
- data/lib/treetop/parser/terminal_parse_failure.rb +0 -18
- data/lib/treetop/parser/terminal_syntax_node.rb +0 -7
- data/lib/treetop/protometagrammar.rb +0 -16
- data/lib/treetop/protometagrammar/anything_symbol_expression_builder.rb +0 -13
- data/lib/treetop/protometagrammar/block_expression_builder.rb +0 -17
- data/lib/treetop/protometagrammar/character_class_expression_builder.rb +0 -25
- data/lib/treetop/protometagrammar/grammar_expression_builder.rb +0 -38
- data/lib/treetop/protometagrammar/nonterminal_symbol_expression_builder.rb +0 -45
- data/lib/treetop/protometagrammar/ordered_choice_expression_builder.rb +0 -21
- data/lib/treetop/protometagrammar/parsing_rule_expression_builder.rb +0 -23
- data/lib/treetop/protometagrammar/parsing_rule_sequence_expression_builder.rb +0 -14
- data/lib/treetop/protometagrammar/prefix_expression_builder.rb +0 -25
- data/lib/treetop/protometagrammar/primary_expression_builder.rb +0 -71
- data/lib/treetop/protometagrammar/protometagrammar.rb +0 -25
- data/lib/treetop/protometagrammar/sequence_expression_builder.rb +0 -37
- data/lib/treetop/protometagrammar/suffix_expression_builder.rb +0 -33
- data/lib/treetop/protometagrammar/terminal_symbol_expression_builder.rb +0 -52
- data/lib/treetop/protometagrammar/trailing_block_expression_builder.rb +0 -30
- data/lib/treetop/ruby_extension.rb +0 -11
| @@ -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,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
         |