rattler 0.2.2 → 0.3.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 (56) hide show
  1. data/README.rdoc +83 -64
  2. data/features/grammar/comments.feature +24 -0
  3. data/features/grammar/list_matching.feature +41 -0
  4. data/features/grammar/symantic_action.feature +30 -12
  5. data/lib/rattler/back_end/parser_generator/assert_generator.rb +27 -27
  6. data/lib/rattler/back_end/parser_generator/choice_generator.rb +29 -29
  7. data/lib/rattler/back_end/parser_generator/direct_action_generator.rb +17 -17
  8. data/lib/rattler/back_end/parser_generator/disallow_generator.rb +27 -27
  9. data/lib/rattler/back_end/parser_generator/dispatch_action_generator.rb +17 -17
  10. data/lib/rattler/back_end/parser_generator/expr_generator.rb +129 -40
  11. data/lib/rattler/back_end/parser_generator/label_generator.rb +15 -15
  12. data/lib/rattler/back_end/parser_generator/list1_generator.rb +61 -0
  13. data/lib/rattler/back_end/parser_generator/list_generating.rb +71 -0
  14. data/lib/rattler/back_end/parser_generator/list_generator.rb +57 -0
  15. data/lib/rattler/back_end/parser_generator/one_or_more_generator.rb +14 -15
  16. data/lib/rattler/back_end/parser_generator/optional_generator.rb +24 -24
  17. data/lib/rattler/back_end/parser_generator/predicate_propogating.rb +9 -9
  18. data/lib/rattler/back_end/parser_generator/repeat_generating.rb +16 -16
  19. data/lib/rattler/back_end/parser_generator/sequence_generator.rb +40 -40
  20. data/lib/rattler/back_end/parser_generator/skip_generator.rb +18 -18
  21. data/lib/rattler/back_end/parser_generator/skip_propogating.rb +5 -5
  22. data/lib/rattler/back_end/parser_generator/sub_generating.rb +128 -0
  23. data/lib/rattler/back_end/parser_generator/token_generator.rb +15 -15
  24. data/lib/rattler/back_end/parser_generator/token_propogating.rb +1 -1
  25. data/lib/rattler/back_end/parser_generator/zero_or_more_generator.rb +12 -13
  26. data/lib/rattler/back_end/parser_generator.rb +10 -7
  27. data/lib/rattler/grammar/grammar_parser.rb +16 -21
  28. data/lib/rattler/grammar/metagrammar.rb +1039 -1035
  29. data/lib/rattler/grammar/rattler.rtlr +28 -28
  30. data/lib/rattler/parsers/action_code.rb +20 -9
  31. data/lib/rattler/parsers/fail.rb +7 -1
  32. data/lib/rattler/parsers/list.rb +57 -0
  33. data/lib/rattler/parsers/list1.rb +58 -0
  34. data/lib/rattler/parsers/parser_dsl.rb +60 -38
  35. data/lib/rattler/parsers.rb +5 -3
  36. data/lib/rattler/runtime/extended_packrat_parser.rb +88 -20
  37. data/lib/rattler/runtime/packrat_parser.rb +21 -14
  38. data/lib/rattler/runtime/parser.rb +74 -18
  39. data/lib/rattler/runtime/recursive_descent_parser.rb +15 -46
  40. data/spec/rattler/back_end/compiler_spec.rb +173 -107
  41. data/spec/rattler/back_end/parser_generator/list1_generator_spec.rb +304 -0
  42. data/spec/rattler/back_end/parser_generator/list_generator_spec.rb +288 -0
  43. data/spec/rattler/grammar/grammar_parser_spec.rb +65 -76
  44. data/spec/rattler/parsers/action_code_spec.rb +84 -34
  45. data/spec/rattler/parsers/direct_action_spec.rb +56 -34
  46. data/spec/rattler/parsers/fail_spec.rb +20 -0
  47. data/spec/rattler/parsers/list1_spec.rb +82 -0
  48. data/spec/rattler/parsers/list_spec.rb +82 -0
  49. data/spec/rattler/parsers/parser_dsl_spec.rb +48 -19
  50. data/spec/rattler/runtime/extended_packrat_parser_spec.rb +0 -1
  51. metadata +92 -173
  52. data/bin/rtlr.bat +0 -3
  53. data/lib/rattler/back_end/parser_generator/generator_helper.rb +0 -130
  54. data/lib/rattler/back_end/parser_generator/generators.rb +0 -86
  55. data/lib/rattler/back_end/parser_generator/nested_generators.rb +0 -15
  56. data/lib/rattler/back_end/parser_generator/top_level_generators.rb +0 -15
@@ -1,94 +1,94 @@
1
1
  require 'rattler/back_end/parser_generator'
2
2
 
3
3
  module Rattler::BackEnd::ParserGenerator
4
-
4
+
5
5
  # @private
6
6
  class DisallowGenerator < ExprGenerator #:nodoc:
7
-
7
+
8
8
  def gen_basic(disallow)
9
- generate disallow.child, :gen_disallow
9
+ generate disallow.child, :disallow
10
10
  end
11
-
11
+
12
12
  def gen_assert(disallow)
13
13
  @g << 'false'
14
14
  end
15
-
15
+
16
16
  def gen_disallow(disallow)
17
17
  gen_basic disallow
18
18
  end
19
-
19
+
20
20
  def gen_skip_nested(disallow)
21
21
  gen_basic_nested disallow
22
22
  end
23
-
23
+
24
24
  def gen_skip_top_level(disallow)
25
25
  gen_basic_top_level disallow
26
26
  end
27
-
27
+
28
28
  def gen_dispatch_action_nested(disallow, target, method_name)
29
29
  atomic_block { gen_dispatch_action_top_level disallow, target, method_name }
30
30
  end
31
-
31
+
32
32
  def gen_dispatch_action_top_level(disallow, target, method_name)
33
33
  gen_action disallow,
34
34
  dispatch_action_result(target, method_name, :array_expr => '[]')
35
35
  end
36
-
36
+
37
37
  def gen_direct_action_nested(disallow, code)
38
38
  atomic_block { gen_direct_action_top_level disallow, code }
39
39
  end
40
-
40
+
41
41
  def gen_direct_action_top_level(disallow, code)
42
42
  gen_action disallow, direct_action_result(code)
43
43
  end
44
-
44
+
45
45
  def gen_token_nested(disallow)
46
46
  atomic_block { gen_token_top_level disallow }
47
47
  end
48
-
48
+
49
49
  def gen_token_top_level(disallow)
50
50
  gen_action disallow, "''"
51
51
  end
52
-
52
+
53
53
  def gen_intermediate(disallow)
54
- generate disallow.child, :gen_intermediate_disallow
54
+ generate disallow.child, :intermediate_disallow
55
55
  end
56
-
56
+
57
57
  def gen_intermediate_disallow(disallow)
58
58
  gen_intermediate disallow
59
59
  end
60
-
60
+
61
61
  def gen_intermediate_skip(disallow)
62
62
  gen_intermediate disallow
63
63
  end
64
-
64
+
65
65
  private
66
-
66
+
67
67
  def gen_action(disallow, result_code)
68
68
  gen_intermediate disallow
69
69
  (@g << ' &&').newline << result_code
70
70
  end
71
-
71
+
72
72
  end
73
-
73
+
74
74
  # @private
75
75
  class NestedDisallowGenerator < DisallowGenerator #:nodoc:
76
76
  include Nested
77
- include NestedGenerators
77
+ include NestedSubGenerating
78
78
  end
79
-
79
+
80
80
  def DisallowGenerator.nested(*args)
81
81
  NestedDisallowGenerator.new(*args)
82
82
  end
83
-
83
+
84
84
  # @private
85
85
  class TopLevelDisallowGenerator < DisallowGenerator #:nodoc:
86
86
  include TopLevel
87
- include TopLevelGenerators
87
+ include TopLevelSubGenerating
88
88
  end
89
-
89
+
90
90
  def DisallowGenerator.top_level(*args)
91
91
  TopLevelDisallowGenerator.new(*args)
92
92
  end
93
-
93
+
94
94
  end
@@ -1,61 +1,61 @@
1
1
  require 'rattler/back_end/parser_generator'
2
2
 
3
3
  module Rattler::BackEnd::ParserGenerator
4
-
4
+
5
5
  # @private
6
6
  class DispatchActionGenerator < ExprGenerator #:nodoc:
7
7
  include PredicatePropogating
8
8
  include TokenPropogating
9
9
  include SkipPropogating
10
-
10
+
11
11
  def gen_basic_nested(action)
12
- generate action.child, :gen_dispatch_action_nested,
12
+ generate action.child, :dispatch_action_nested,
13
13
  action.target, action.method_name
14
14
  end
15
-
15
+
16
16
  def gen_basic_top_level(action)
17
- generate action.child, :gen_dispatch_action_top_level,
17
+ generate action.child, :dispatch_action_top_level,
18
18
  action.target, action.method_name
19
19
  end
20
-
20
+
21
21
  def gen_dispatch_action_nested(inner, target, method_name)
22
22
  atomic_block { gen_dispatch_action_top_level inner, target, method_name }
23
23
  end
24
-
24
+
25
25
  def gen_dispatch_action_top_level(inner, target, method_name)
26
26
  @g.surround("(#{result_name} = ", ')') { gen_basic_nested inner }
27
27
  (@g << ' &&').newline << dispatch_action_result(target, method_name)
28
28
  end
29
-
29
+
30
30
  def gen_direct_action_nested(inner, code)
31
31
  atomic_block { gen_direct_action_top_level inner, code }
32
32
  end
33
-
33
+
34
34
  def gen_direct_action_top_level(inner, code)
35
35
  @g.surround("(#{result_name} = ", ')') { gen_basic_nested inner }
36
36
  (@g << ' &&').newline << direct_action_result(code)
37
37
  end
38
-
38
+
39
39
  end
40
-
40
+
41
41
  # @private
42
42
  class NestedDispatchActionGenerator < DispatchActionGenerator #:nodoc:
43
43
  include Nested
44
- include NestedGenerators
44
+ include NestedSubGenerating
45
45
  end
46
-
46
+
47
47
  def DispatchActionGenerator.nested(*args)
48
48
  NestedDispatchActionGenerator.new(*args)
49
49
  end
50
-
50
+
51
51
  # @private
52
52
  class TopLevelDispatchActionGenerator < DispatchActionGenerator #:nodoc:
53
53
  include TopLevel
54
- include TopLevelGenerators
54
+ include TopLevelSubGenerating
55
55
  end
56
-
56
+
57
57
  def DispatchActionGenerator.top_level(*args)
58
58
  TopLevelDispatchActionGenerator.new(*args)
59
59
  end
60
-
60
+
61
61
  end
@@ -1,60 +1,149 @@
1
1
  require 'rattler/back_end/parser_generator'
2
2
 
3
3
  module Rattler::BackEnd::ParserGenerator
4
-
4
+
5
5
  # @private
6
6
  class ExprGenerator #:nodoc:
7
- include GeneratorHelper
8
-
7
+ # include GeneratorHelper
8
+
9
9
  include Rattler::Parsers
10
-
10
+
11
11
  def initialize(g, choice_level=nil, sequence_level=nil, repeat_level=nil)
12
12
  @g = g
13
13
  @choice_level = choice_level
14
14
  @sequence_level = sequence_level
15
15
  @repeat_level = repeat_level
16
16
  end
17
-
18
- def generate(parser, gen_method=:gen_basic, *args)
19
- case parser
20
- when Eof then gen_eof
21
- else generator(parser).send(gen_method, parser, *args)
22
- end
17
+
18
+ def gen_basic_nested(parser)
19
+ gen_basic parser
23
20
  end
24
-
25
- def gen_eof
26
- @g << '@scanner.eos?'
27
- end
28
-
29
- private
30
-
31
- def generator(parser)
32
- case parser
33
- when Match then match_generator
34
- when Choice then choice_generator
35
- when Sequence then sequence_generator
36
- when Optional then optional_generator
37
- when ZeroOrMore then zero_or_more_generator
38
- when OneOrMore then one_or_more_generator
39
- when Apply then apply_generator
40
- when Assert then assert_generator
41
- when Disallow then disallow_generator
42
- when DispatchAction then dispatch_action_generator
43
- when DirectAction then direct_action_generator
44
- when Token then token_generator
45
- when Skip then skip_generator
46
- when Label then label_generator
47
- when Fail then fail_generator
48
- end
21
+
22
+ def gen_basic_top_level(parser)
23
+ gen_basic parser
24
+ end
25
+
26
+ def gen_assert_nested(parser)
27
+ gen_assert parser
28
+ end
29
+
30
+ def gen_assert_top_level(parser)
31
+ gen_assert parser
32
+ end
33
+
34
+ def gen_disallow_nested(parser)
35
+ gen_disallow parser
36
+ end
37
+
38
+ def gen_disallow_top_level(parser)
39
+ gen_disallow parser
40
+ end
41
+
42
+ def gen_dispatch_action_nested(parser, target, method_name)
43
+ gen_dispatch_action parser, target, method_name
44
+ end
45
+
46
+ def gen_dispatch_action_top_level(parser, target, method_name)
47
+ gen_dispatch_action parser, target, method_name
48
+ end
49
+
50
+ def gen_direct_action_nested(parser, action)
51
+ gen_direct_action parser, action
52
+ end
53
+
54
+ def gen_direct_action_top_level(parser, action)
55
+ gen_direct_action parser, action
56
+ end
57
+
58
+ def gen_token_nested(parser)
59
+ atomic_block { gen_token_top_level parser }
60
+ end
61
+
62
+ def gen_token_top_level(parser)
63
+ (@g << "tp = @scanner.pos").newline
64
+ gen_intermediate_skip parser
65
+ (@g << ' &&').newline
66
+ @g << "@scanner.string[tp...(@scanner.pos)]"
67
+ end
68
+
69
+ def gen_skip_nested(parser)
70
+ gen_skip parser
71
+ end
72
+
73
+ def gen_skip_top_level(parser)
74
+ gen_skip parser
49
75
  end
50
-
76
+
77
+ def gen_intermediate(parser)
78
+ gen_basic_nested parser
79
+ end
80
+
81
+ def gen_intermediate_assert(parser)
82
+ gen_assert_nested parser
83
+ end
84
+
85
+ def gen_intermediate_disallow(parser)
86
+ gen_disallow_nested parser
87
+ end
88
+
89
+ def gen_intermediate_skip(parser)
90
+ gen_skip_nested parser
91
+ end
92
+
93
+ protected
94
+
51
95
  attr_reader :choice_level, :sequence_level, :repeat_level
52
-
96
+
97
+ def atomic_expr
98
+ @g.surround('(', ')') { yield }
99
+ end
100
+
101
+ def atomic_block
102
+ @g.block('begin') { yield }
103
+ end
104
+
105
+ def result_name
106
+ 'r'
107
+ end
108
+
109
+ def saved_pos_name
110
+ "p#{sequence_level}"
111
+ end
112
+
113
+ def dispatch_action_result(target, method_name, options = {})
114
+ args = [options[:array_expr] || "[#{result_name}]"]
115
+ labeled = options[:labeled]
116
+ if labeled and not labeled.empty?
117
+ if labeled.respond_to?(:to_hash)
118
+ labeled = '{' + labeled.map {|k, v| ":#{k} => #{v}"}.join(', ') + '}'
119
+ end
120
+ args << ":labeled => #{labeled}"
121
+ end
122
+ t = target == 'self' ? '' : "#{target}."
123
+ "#{t}#{method_name}(#{args.join ', '})"
124
+ end
125
+
126
+ def direct_action_result(code, options = {})
127
+ args = options[:bind_args] || [result_name]
128
+ labeled = options[:labeled] || {}
129
+ "(#{code.bind args, labeled})"
130
+ end
131
+
132
+ def lookahead
133
+ (@g << "#{saved_pos_name} = @scanner.pos").newline
134
+ yield
135
+ (@g << "@scanner.pos = #{saved_pos_name}").newline
136
+ end
137
+
53
138
  end
54
-
139
+
55
140
  # @private
56
141
  class TopLevelGenerator < ExprGenerator #:nodoc:
57
- include TopLevelGenerators
142
+ include TopLevelSubGenerating
143
+
144
+ def generate(parser)
145
+ super
146
+ end
58
147
  end
59
-
148
+
60
149
  end
@@ -1,45 +1,45 @@
1
1
  require 'rattler/back_end/parser_generator'
2
2
 
3
3
  module Rattler::BackEnd::ParserGenerator
4
-
4
+
5
5
  # @private
6
6
  class LabelGenerator < ExprGenerator #:nodoc:
7
7
  include PredicatePropogating
8
8
  include TokenPropogating
9
9
  include SkipPropogating
10
-
10
+
11
11
  def gen_basic(label)
12
- generate label.child, :gen_basic
12
+ generate label.child, :basic
13
13
  end
14
-
14
+
15
15
  def gen_dispatch_action(label, target, method_name)
16
- generate label.child, :gen_dispatch_action, target, method_name
16
+ generate label.child, :dispatch_action, target, method_name
17
17
  end
18
-
18
+
19
19
  def gen_direct_action(label, code)
20
- generate label.child, :gen_direct_action, code
20
+ generate label.child, :direct_action, code
21
21
  end
22
-
22
+
23
23
  end
24
-
24
+
25
25
  # @private
26
26
  class NestedLabelGenerator < LabelGenerator #:nodoc:
27
27
  include Nested
28
- include NestedGenerators
28
+ include NestedSubGenerating
29
29
  end
30
-
30
+
31
31
  def LabelGenerator.nested(*args)
32
32
  NestedLabelGenerator.new(*args)
33
33
  end
34
-
34
+
35
35
  # @private
36
36
  class TopLevelLabelGenerator < LabelGenerator #:nodoc:
37
37
  include TopLevel
38
- include TopLevelGenerators
38
+ include TopLevelSubGenerating
39
39
  end
40
-
40
+
41
41
  def LabelGenerator.top_level(*args)
42
42
  TopLevelLabelGenerator.new(*args)
43
43
  end
44
-
44
+
45
45
  end
@@ -0,0 +1,61 @@
1
+ require 'rattler/back_end/parser_generator'
2
+
3
+ module Rattler::BackEnd::ParserGenerator
4
+
5
+ # @private
6
+ class List1Generator < ExprGenerator #:nodoc:
7
+ include ListGenerating
8
+ include NestedSubGenerating
9
+ include PredicatePropogating
10
+
11
+ def gen_skip_top_level(list)
12
+ (@g << "#{result_name} = false").newline
13
+ (@g << "#{saved_pos_name} = nil").newline
14
+ @g << 'while '
15
+ generate list.child, :intermediate_skip
16
+ @g.block '' do
17
+ (@g << "#{result_name} = true").newline
18
+ (@g << "#{saved_pos_name} = @scanner.pos").newline
19
+ @g << 'break unless '
20
+ generate list.sep_parser, :intermediate_skip
21
+ end.newline
22
+ @g << "@scanner.pos = #{saved_pos_name} unless #{saved_pos_name}.nil?"
23
+ @g.newline << result_name
24
+ end
25
+
26
+ protected
27
+
28
+ def gen_result(captures)
29
+ @g << captures << " unless #{accumulator_name}.empty?"
30
+ end
31
+
32
+ end
33
+
34
+ # @private
35
+ class NestedList1Generator < List1Generator #:nodoc:
36
+ include Nested
37
+ end
38
+
39
+ def List1Generator.nested(*args)
40
+ NestedList1Generator.new(*args)
41
+ end
42
+
43
+ # @private
44
+ class TopLevelList1Generator < List1Generator #:nodoc:
45
+ include TopLevel
46
+
47
+ def gen_assert(parser)
48
+ generate parser.child, :assert_top_level
49
+ end
50
+
51
+ def gen_disallow(parser)
52
+ generate parser.child, :disallow_top_level
53
+ end
54
+
55
+ end
56
+
57
+ def List1Generator.top_level(*args)
58
+ TopLevelList1Generator.new(*args)
59
+ end
60
+
61
+ end
@@ -0,0 +1,71 @@
1
+ require 'rattler/back_end/parser_generator'
2
+
3
+ module Rattler::BackEnd::ParserGenerator
4
+ # @private
5
+ module ListGenerating #:nodoc:
6
+
7
+ def gen_basic_nested(list)
8
+ atomic_block { gen_basic_top_level list }
9
+ end
10
+
11
+ def gen_basic_top_level(list)
12
+ list.capturing? ? gen_capturing(list) : gen_skip_top_level(list)
13
+ end
14
+
15
+ def gen_dispatch_action_nested(list, target, method_name)
16
+ atomic_block do
17
+ gen_dispatch_action_top_level list, target, method_name
18
+ end
19
+ end
20
+
21
+ def gen_dispatch_action_top_level(list, target, method_name)
22
+ gen_capturing list do |a|
23
+ dispatch_action_result target, method_name,
24
+ :array_expr => "select_captures(#{a})"
25
+ end
26
+ end
27
+
28
+ def gen_direct_action_nested(list, action)
29
+ atomic_block do
30
+ gen_direct_action_top_level list, action
31
+ end
32
+ end
33
+
34
+ def gen_direct_action_top_level(list, action)
35
+ gen_capturing list do |a|
36
+ direct_action_result action, :bind_args => ["select_captures(#{a})"]
37
+ end
38
+ end
39
+
40
+ def gen_skip_nested(list)
41
+ atomic_block { gen_skip_top_level list }
42
+ end
43
+
44
+ protected
45
+
46
+ def gen_capturing(list)
47
+ (@g << "#{accumulator_name} = []").newline
48
+ (@g << "#{saved_pos_name} = nil").newline
49
+ @g << "while #{result_name} = "
50
+ generate list.child, :basic
51
+ @g.block '' do
52
+ (@g << "#{saved_pos_name} = @scanner.pos").newline
53
+ (@g << "#{accumulator_name} << #{result_name}").newline
54
+ @g << 'break unless '
55
+ generate list.sep_parser, :intermediate_skip
56
+ end.newline
57
+ @g << "@scanner.pos = #{saved_pos_name} unless #{saved_pos_name}.nil?"
58
+ @g.newline
59
+ gen_result(block_given? ? yield(accumulator_name) : accumulator_name)
60
+ end
61
+
62
+ def accumulator_name
63
+ "a#{repeat_level}"
64
+ end
65
+
66
+ def saved_pos_name
67
+ "lp#{repeat_level}"
68
+ end
69
+
70
+ end
71
+ end
@@ -0,0 +1,57 @@
1
+ require 'rattler/back_end/parser_generator'
2
+
3
+ module Rattler::BackEnd::ParserGenerator
4
+
5
+ # @private
6
+ class ListGenerator < ExprGenerator #:nodoc:
7
+ include ListGenerating
8
+ include NestedSubGenerating
9
+
10
+ def gen_assert(optional)
11
+ @g << 'true'
12
+ end
13
+
14
+ def gen_disallow(optional)
15
+ @g << 'false'
16
+ end
17
+
18
+ def gen_skip_top_level(list)
19
+ (@g << "#{saved_pos_name} = nil").newline
20
+ @g << 'while '
21
+ generate list.child, :intermediate_skip
22
+ @g.block '' do
23
+ (@g << "#{saved_pos_name} = @scanner.pos").newline
24
+ @g << 'break unless '
25
+ generate list.sep_parser, :intermediate_skip
26
+ end.newline
27
+ @g << "@scanner.pos = #{saved_pos_name} unless #{saved_pos_name}.nil?"
28
+ @g.newline << true
29
+ end
30
+
31
+ protected
32
+
33
+ def gen_result(captures)
34
+ @g << captures
35
+ end
36
+
37
+ end
38
+
39
+ # @private
40
+ class NestedListGenerator < ListGenerator #:nodoc:
41
+ include Nested
42
+ end
43
+
44
+ def ListGenerator.nested(*args)
45
+ NestedListGenerator.new(*args)
46
+ end
47
+
48
+ # @private
49
+ class TopLevelListGenerator < ListGenerator #:nodoc:
50
+ include TopLevel
51
+ end
52
+
53
+ def ListGenerator.top_level(*args)
54
+ TopLevelListGenerator.new(*args)
55
+ end
56
+
57
+ end