treetop 0.1.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 (59) hide show
  1. data/lib/treetop.rb +6 -0
  2. data/lib/treetop/api.rb +3 -0
  3. data/lib/treetop/api/load_grammar.rb +16 -0
  4. data/lib/treetop/api/malformed_grammar_exception.rb +9 -0
  5. data/lib/treetop/grammar.rb +7 -0
  6. data/lib/treetop/grammar/grammar.rb +48 -0
  7. data/lib/treetop/grammar/grammar_builder.rb +35 -0
  8. data/lib/treetop/grammar/parsing_expression_builder.rb +5 -0
  9. data/lib/treetop/grammar/parsing_expression_builder_helper.rb +121 -0
  10. data/lib/treetop/grammar/parsing_expressions.rb +18 -0
  11. data/lib/treetop/grammar/parsing_expressions/and_predicate.rb +17 -0
  12. data/lib/treetop/grammar/parsing_expressions/anything_symbol.rb +20 -0
  13. data/lib/treetop/grammar/parsing_expressions/character_class.rb +24 -0
  14. data/lib/treetop/grammar/parsing_expressions/node_instantiating_parsing_expression.rb +14 -0
  15. data/lib/treetop/grammar/parsing_expressions/node_propagating_parsing_expression.rb +4 -0
  16. data/lib/treetop/grammar/parsing_expressions/nonterminal_symbol.rb +42 -0
  17. data/lib/treetop/grammar/parsing_expressions/not_predicate.rb +18 -0
  18. data/lib/treetop/grammar/parsing_expressions/one_or_more.rb +12 -0
  19. data/lib/treetop/grammar/parsing_expressions/optional.rb +14 -0
  20. data/lib/treetop/grammar/parsing_expressions/ordered_choice.rb +27 -0
  21. data/lib/treetop/grammar/parsing_expressions/parsing_expression.rb +36 -0
  22. data/lib/treetop/grammar/parsing_expressions/predicate.rb +25 -0
  23. data/lib/treetop/grammar/parsing_expressions/repeating_parsing_expression.rb +29 -0
  24. data/lib/treetop/grammar/parsing_expressions/sequence.rb +41 -0
  25. data/lib/treetop/grammar/parsing_expressions/terminal_parsing_expression.rb +11 -0
  26. data/lib/treetop/grammar/parsing_expressions/terminal_symbol.rb +31 -0
  27. data/lib/treetop/grammar/parsing_expressions/zero_or_more.rb +11 -0
  28. data/lib/treetop/grammar/parsing_rule.rb +10 -0
  29. data/lib/treetop/metagrammar.rb +2 -0
  30. data/lib/treetop/metagrammar/metagrammar.rb +14 -0
  31. data/lib/treetop/metagrammar/metagrammar.treetop +320 -0
  32. data/lib/treetop/parser.rb +11 -0
  33. data/lib/treetop/parser/node_cache.rb +25 -0
  34. data/lib/treetop/parser/parse_cache.rb +17 -0
  35. data/lib/treetop/parser/parse_failure.rb +22 -0
  36. data/lib/treetop/parser/parse_result.rb +26 -0
  37. data/lib/treetop/parser/parser.rb +24 -0
  38. data/lib/treetop/parser/sequence_syntax_node.rb +14 -0
  39. data/lib/treetop/parser/syntax_node.rb +31 -0
  40. data/lib/treetop/parser/terminal_parse_failure.rb +18 -0
  41. data/lib/treetop/parser/terminal_syntax_node.rb +7 -0
  42. data/lib/treetop/protometagrammar.rb +16 -0
  43. data/lib/treetop/protometagrammar/anything_symbol_expression_builder.rb +13 -0
  44. data/lib/treetop/protometagrammar/block_expression_builder.rb +17 -0
  45. data/lib/treetop/protometagrammar/character_class_expression_builder.rb +25 -0
  46. data/lib/treetop/protometagrammar/grammar_expression_builder.rb +38 -0
  47. data/lib/treetop/protometagrammar/nonterminal_symbol_expression_builder.rb +45 -0
  48. data/lib/treetop/protometagrammar/ordered_choice_expression_builder.rb +21 -0
  49. data/lib/treetop/protometagrammar/parsing_rule_expression_builder.rb +23 -0
  50. data/lib/treetop/protometagrammar/parsing_rule_sequence_expression_builder.rb +14 -0
  51. data/lib/treetop/protometagrammar/prefix_expression_builder.rb +25 -0
  52. data/lib/treetop/protometagrammar/primary_expression_builder.rb +71 -0
  53. data/lib/treetop/protometagrammar/protometagrammar.rb +25 -0
  54. data/lib/treetop/protometagrammar/sequence_expression_builder.rb +37 -0
  55. data/lib/treetop/protometagrammar/suffix_expression_builder.rb +33 -0
  56. data/lib/treetop/protometagrammar/terminal_symbol_expression_builder.rb +52 -0
  57. data/lib/treetop/protometagrammar/trailing_block_expression_builder.rb +30 -0
  58. data/lib/treetop/ruby_extension.rb +11 -0
  59. metadata +110 -0
@@ -0,0 +1,11 @@
1
+ dir = File.dirname(__FILE__)
2
+ require "#{dir}/parser/parser"
3
+ require "#{dir}/parser/parse_result"
4
+ require "#{dir}/parser/syntax_node"
5
+ require "#{dir}/parser/terminal_syntax_node"
6
+ require "#{dir}/parser/sequence_syntax_node"
7
+ require "#{dir}/parser/parse_failure"
8
+ require "#{dir}/parser/node_cache"
9
+ require "#{dir}/parser/parse_cache"
10
+ require "#{dir}/parser/parse_failure"
11
+ require "#{dir}/parser/terminal_parse_failure"
@@ -0,0 +1,25 @@
1
+ module Treetop
2
+ class NodeCache
3
+ attr_reader :parse_results
4
+
5
+ def initialize
6
+ @parse_results = {}
7
+ end
8
+
9
+ def empty?
10
+ parse_results.empty?
11
+ end
12
+
13
+ def store(parse_result)
14
+ if parse_result.failure?
15
+ parse_results[parse_result.index] = parse_result
16
+ else
17
+ parse_results[parse_result.interval.begin] = parse_result
18
+ end
19
+ end
20
+
21
+ def [](start_index)
22
+ parse_results[start_index]
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,17 @@
1
+ module Treetop
2
+ class ParseCache
3
+ attr_reader :node_caches
4
+
5
+ def initialize
6
+ @node_caches = {}
7
+ end
8
+
9
+ def [](parsing_expression)
10
+ node_caches[parsing_expression] ||= NodeCache.new
11
+ end
12
+
13
+ def empty?
14
+ node_caches.empty?
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,22 @@
1
+ module Treetop
2
+ class ParseFailure < ParseResult
3
+ attr_reader :index
4
+
5
+ def initialize(index, nested_failures = [])
6
+ super(nested_failures)
7
+ @index = index
8
+ end
9
+
10
+ def success?
11
+ false
12
+ end
13
+
14
+ def failure?
15
+ true
16
+ end
17
+
18
+ def interval
19
+ @interval ||= (index...index)
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,26 @@
1
+ module Treetop
2
+ class ParseResult
3
+ attr_reader :nested_failures
4
+
5
+ def initialize(nested_failures = [])
6
+ @nested_failures = select_failures_at_maximum_index(nested_failures)
7
+ end
8
+
9
+ protected
10
+ def select_failures_at_maximum_index(failures)
11
+ maximum_index = 0
12
+ failures_at_maximum_index = []
13
+
14
+ failures.each do |failure|
15
+ if failure.index > maximum_index
16
+ failures_at_maximum_index = [failure]
17
+ maximum_index = failure.index
18
+ elsif failure.index == maximum_index
19
+ failures_at_maximum_index << failure
20
+ end
21
+ end
22
+
23
+ return failures_at_maximum_index
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,24 @@
1
+ module Treetop
2
+ class Parser
3
+ attr_reader :grammar, :parse_cache
4
+
5
+ def initialize(grammar)
6
+ @grammar = grammar
7
+ @parse_cache = ParseCache.new
8
+ end
9
+
10
+ def parse(input)
11
+ @parse_cache = ParseCache.new
12
+ result = grammar.root.parse_at(input, 0, self)
13
+ if result.success? and result.interval.end == input.size
14
+ return result
15
+ else
16
+ return ParseFailure.new(result.interval.end, result.nested_failures)
17
+ end
18
+ end
19
+
20
+ def node_cache_for(parsing_expression)
21
+ parse_cache[parsing_expression]
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,14 @@
1
+ module Treetop
2
+ class SequenceSyntaxNode < SyntaxNode
3
+ attr_reader :elements
4
+
5
+ def initialize(input, interval, elements, nested_failures = [])
6
+ super(input, interval, nested_failures)
7
+ @elements = elements
8
+ end
9
+
10
+ def empty?
11
+ elements.empty?
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,31 @@
1
+ module Treetop
2
+ class SyntaxNode < ParseResult
3
+ attr_reader :input, :interval
4
+
5
+ def initialize(input, interval, nested_failures = [])
6
+ super(nested_failures)
7
+ @input = input
8
+ @interval = interval
9
+ end
10
+
11
+ def update_nested_failures(failures)
12
+ @nested_failures = select_failures_at_maximum_index(nested_failures + failures)
13
+ end
14
+
15
+ def text_value
16
+ input[interval]
17
+ end
18
+
19
+ def success?
20
+ true
21
+ end
22
+
23
+ def failure?
24
+ false
25
+ end
26
+
27
+ def epsilon?
28
+ false
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,18 @@
1
+ module Treetop
2
+ class TerminalParseFailure < ParseFailure
3
+ attr_reader :expression
4
+
5
+ def initialize(index, expression)
6
+ super(index)
7
+ @expression = expression
8
+ end
9
+
10
+ def nested_failures
11
+ [self]
12
+ end
13
+
14
+ def to_s
15
+ "String matching #{expression} expected at position #{index}."
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,7 @@
1
+ module Treetop
2
+ class TerminalSyntaxNode < SyntaxNode
3
+ def epsilon?
4
+ text_value.eql? ""
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,16 @@
1
+ dir = File.dirname(__FILE__)
2
+ require "#{dir}/protometagrammar/protometagrammar"
3
+ require "#{dir}/protometagrammar/grammar_expression_builder"
4
+ require "#{dir}/protometagrammar/parsing_rule_sequence_expression_builder"
5
+ require "#{dir}/protometagrammar/parsing_rule_expression_builder"
6
+ require "#{dir}/protometagrammar/primary_expression_builder"
7
+ require "#{dir}/protometagrammar/nonterminal_symbol_expression_builder"
8
+ require "#{dir}/protometagrammar/terminal_symbol_expression_builder"
9
+ require "#{dir}/protometagrammar/character_class_expression_builder"
10
+ require "#{dir}/protometagrammar/anything_symbol_expression_builder"
11
+ require "#{dir}/protometagrammar/sequence_expression_builder"
12
+ require "#{dir}/protometagrammar/suffix_expression_builder"
13
+ require "#{dir}/protometagrammar/prefix_expression_builder"
14
+ require "#{dir}/protometagrammar/ordered_choice_expression_builder"
15
+ require "#{dir}/protometagrammar/block_expression_builder"
16
+ require "#{dir}/protometagrammar/trailing_block_expression_builder"
@@ -0,0 +1,13 @@
1
+ module Treetop
2
+ class Protometagrammar
3
+ class AnythingSymbolExpressionBuilder < ParsingExpressionBuilder
4
+ def build
5
+ exp(".") do
6
+ def value(grammar = nil)
7
+ AnythingSymbol.new
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,17 @@
1
+ module Treetop
2
+ class Protometagrammar
3
+ class BlockExpressionBuilder < ParsingExpressionBuilder
4
+ def build
5
+ seq('{', zero_or_more(choice(:block, anything_but_a_brace)), '}') do
6
+ def value
7
+ elements[1].text_value
8
+ end
9
+ end
10
+ end
11
+
12
+ def anything_but_a_brace
13
+ seq(notp(choice('{', '}')), any)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,25 @@
1
+ module Treetop
2
+ class Protometagrammar
3
+ class CharacterClassExpressionBuilder < ParsingExpressionBuilder
4
+ def build
5
+ character_class
6
+ end
7
+
8
+ def character_class
9
+ seq('[', one_or_more(char_class_char), ']') do
10
+ def value(grammar = nil)
11
+ CharacterClass.new(characters)
12
+ end
13
+
14
+ def characters
15
+ elements[1].text_value
16
+ end
17
+ end
18
+ end
19
+
20
+ def char_class_char
21
+ seq(notp(']'), choice(escaped(']'), any))
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,38 @@
1
+ module Treetop
2
+ class Protometagrammar
3
+ class GrammarExpressionBuilder < ParsingExpressionBuilder
4
+ def build
5
+ seq('grammar', :space, grammar_name, :parsing_rule_sequence, optional(:space), 'end') do
6
+ def value
7
+ grammar = Grammar.new(grammar_name)
8
+ parsing_rules(grammar).each do |parsing_rule|
9
+ grammar.add_parsing_rule(parsing_rule)
10
+ end
11
+ return grammar
12
+ end
13
+
14
+ def grammar_name
15
+ name_string = elements[2].text_value.chop
16
+
17
+ if name_string.empty?
18
+ nil
19
+ else
20
+ name_string.to_sym
21
+ end
22
+ end
23
+
24
+ def parsing_rules(grammar)
25
+ elements[3].value(grammar)
26
+ end
27
+ end
28
+ end
29
+
30
+ def grammar_name
31
+ optional(
32
+ seq(char_class('A-Z'),
33
+ zero_or_more(char_class('a-z0-9_')),
34
+ :space))
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,45 @@
1
+ module Treetop
2
+ class Protometagrammar
3
+ class NonterminalSymbolExpressionBuilder < ParsingExpressionBuilder
4
+ def build
5
+ seq(notp(naked_keyword), nonterminal_symbol) do
6
+ def value(grammar)
7
+ nonterminal_symbol.value(grammar)
8
+ end
9
+
10
+ def nonterminal_symbol
11
+ elements[1]
12
+ end
13
+ end
14
+ end
15
+
16
+ def naked_keyword
17
+ seq(:keyword, notp(alphanumeric_char))
18
+ end
19
+
20
+ def nonterminal_symbol
21
+ seq(alpha_char, zero_or_more(alphanumeric_char)) do
22
+ def value(grammar)
23
+ grammar.nonterminal_symbol(name)
24
+ end
25
+
26
+ def name
27
+ text_value.to_sym
28
+ end
29
+ end
30
+ end
31
+
32
+ def alpha_char
33
+ char_class('A-Za-z_')
34
+ end
35
+
36
+ def numeric_char
37
+ char_class('0-9')
38
+ end
39
+
40
+ def alphanumeric_char
41
+ choice(alpha_char, numeric_char)
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,21 @@
1
+ module Treetop
2
+ class Protometagrammar
3
+ class OrderedChoiceExpressionBuilder < ParsingExpressionBuilder
4
+ def build
5
+ choice(ordered_choice, :sequence)
6
+ end
7
+
8
+ def ordered_choice
9
+ two_or_more_delimited(:sequence, seq(optional(:space), "/", optional(:space))) do
10
+ def value(grammar)
11
+ OrderedChoice.new(element_values(grammar))
12
+ end
13
+
14
+ def element_values(grammar)
15
+ elements.collect { |element| element.value(grammar) }
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,23 @@
1
+ module Treetop
2
+ class Protometagrammar
3
+ class ParsingRuleExpressionBuilder < ParsingExpressionBuilder
4
+ def build
5
+ seq('rule', :space, :nonterminal_symbol, :space, :ordered_choice, :space, 'end') do
6
+ def value(grammar)
7
+ ParsingRule.new(nonterminal_symbol.value(grammar),
8
+ parsing_expression.value(grammar))
9
+ end
10
+
11
+ def nonterminal_symbol
12
+ elements[2]
13
+ end
14
+
15
+ def parsing_expression
16
+ elements[4]
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+
@@ -0,0 +1,14 @@
1
+ module Treetop
2
+ class Protometagrammar
3
+ class ParsingRuleSequenceExpressionBuilder < ParsingExpressionBuilder
4
+ def build
5
+ zero_or_more_delimited(:parsing_rule, :space) do
6
+ def value(grammar)
7
+ elements.collect {|element| element.value(grammar) }
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
14
+
@@ -0,0 +1,25 @@
1
+ module Treetop
2
+ class Protometagrammar
3
+ class PrefixExpressionBuilder < ParsingExpressionBuilder
4
+ def build
5
+ choice(and_predicate, not_predicate)
6
+ end
7
+
8
+ def and_predicate
9
+ exp('&') do
10
+ def value(parsing_expression)
11
+ parsing_expression.and_predicate
12
+ end
13
+ end
14
+ end
15
+
16
+ def not_predicate
17
+ exp('!') do
18
+ def value(parsing_expression)
19
+ parsing_expression.not_predicate
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end