rattler 0.2.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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
data/README.rdoc CHANGED
@@ -14,13 +14,13 @@ A language syntax is specified in a grammar using the Rattler syntax. Parser
14
14
  classes and modules can be generated statically using the "rtlr" command or
15
15
  dynamically from strings.
16
16
 
17
- {RDoc}[http://rubydoc.info/gems/rattler/0.2.1/frames]
17
+ {RDoc}[http://rubydoc.info/gems/rattler/0.2.2/frames]
18
18
 
19
19
  == FEATURES:
20
20
 
21
21
  * Uses readable PEG-like grammars
22
22
  * A packrat parser to cache results for backtracking
23
- * A parser that supports directly left-recursive grammars
23
+ * An extended packrat parser that supports left-recursive grammars
24
24
  * Whitespace can be specified in one place and skipped automatically
25
25
  * Automatic and custom parse error reporting
26
26
  * Optimizing parser generator
@@ -30,91 +30,109 @@ dynamically from strings.
30
30
 
31
31
  == PROBLEMS/LIMITATIONS:
32
32
 
33
- * Indirect left-recursion is not yet supported
34
33
  * Optimizations are very limited at this point
35
34
  * Only strings can be parsed, so files have to be read completely before parsing
36
- * There are undoubtedly many bugs
35
+ * There are many holes in the tests so there are undoubtedly many bugs
37
36
 
38
37
  == EXAMPLES:
39
38
 
40
39
  === Example 1: Statically generated parser class
41
40
 
42
- ==== In file calculator.rtlr:
41
+ ==== json.rtlr:
43
42
 
44
- parser Calculator < Rattler::Runtime::WDMParser
45
-
46
- %whitespace SPACE*
47
-
48
- start <- expr EOF
49
-
50
- expr <- expr ~'+' term {|a, b| a + b }
51
- | expr ~'-' term {|a, b| a - b }
52
- | term
53
-
54
- term <- term ~'*' primary {|a, b| a * b }
55
- | term ~'/' primary {|a, b| a / b }
56
- | primary
57
-
58
- primary <- ~'(' expr ~')'
59
- | @(DIGIT+ ('.' DIGIT+)?) {|_| _.to_f }
60
-
61
- ==== In a shell:
43
+ # JSON parser based on the grammar at http://www.json.org
44
+
45
+ parser JsonParser < Rattler::Runtime::PackratParser
46
+
47
+ %whitespace (SPACE+ | '/*' (! '*/' .)* '*/' | '//' [^\n]*)*
48
+
49
+ object <- ~'{' members ~'}' { object _ }
50
+
51
+ members <- pair *^ ','
52
+
53
+ pair <- string ~':' value
54
+
55
+ array <- ~'[' elements ~']'
56
+
57
+ elements <- value *^ ','
58
+
59
+ value <- string { string _ }
60
+ | number !DIGIT { _.to_f }
61
+ | object
62
+ | array
63
+ | `true` { :true }
64
+ | `false` { :false }
65
+ | `null` { :null }
66
+ | fail "value expected"
67
+
68
+ string <- @('"' ('\\' . | [^"])* '"')
69
+
70
+ number <- @('-'? ('0' | [1-9] DIGIT*) ('.' DIGIT+)? ([eE] [+-]? DIGIT+)?)
71
+
72
+ ==== json_helper.rb:
73
+
74
+ module JsonHelper
75
+
76
+ def object(members)
77
+ Hash[*members.flatten(1)]
78
+ end
79
+
80
+ def string(expr)
81
+ eval expr, TOPLEVEL_BINDING
82
+ end
83
+
84
+ end
85
+
86
+ ==== $ rtlr json.rtlr
62
87
 
63
- $ rtlr calculator.rtlr
64
- calculator.rtlr -> calculator.rb
88
+ json.rtlr -> json_parser.rb
65
89
 
66
- ==== In file calculator.rb:
90
+ ==== parse_json.rb:
67
91
 
68
92
  require 'rubygems'
69
93
  require 'rattler'
70
- require 'calculator'
94
+ require 'json_parser'
71
95
 
72
96
  begin
73
- puts Calculator.parse!(expr)
97
+ p JsonParser.parse!(open(ARGV[0]) {|io| io.read })
74
98
  rescue Rattler::Runtime::SyntaxError => e
75
99
  puts e
76
100
  end
77
101
 
78
102
  === Example 2: Statically generated grammar module
79
103
 
80
- ==== calculator.rtlr:
81
-
82
- grammar CalculatorGrammar
83
-
84
- %whitespace SPACE*
85
-
86
- start <- expr EOF
104
+ ==== json.rtlr:
87
105
 
88
- expr <- expr ~'+' term {|a, b| a + b }
89
- | expr ~'-' term {|a, b| a - b }
90
- | term
91
-
92
- term <- term ~'*' primary {|a, b| a * b }
93
- | term ~'/' primary {|a, b| a / b }
94
- | primary
95
-
96
- primary <- ~'(' expr ~')'
97
- | @(DIGIT+ ('.' DIGIT+)?) {|_| _.to_f }
106
+ # JSON parser based on the grammar at http://www.json.org
107
+
108
+ grammar JsonGrammar
109
+
110
+ %whitespace (SPACE+ | '/*' (! '*/' .)* '*/' | '//' [^\n]*)*
111
+
112
+ ...
98
113
 
99
- ==== In a shell:
114
+ ==== $ rtlr json.rtlr
100
115
 
101
- $ rtlr calculator.rtlr
102
- calculator.rtlr -> calculator_grammar.rb
116
+ json.rtlr -> json_grammar.rb
103
117
 
104
- ==== calculator.rb:
118
+ ==== json_parser.rb:
105
119
 
106
120
  require 'rubygems'
107
121
  require 'rattler'
108
- require 'calculator_grammar'
122
+ require 'json_grammar'
109
123
 
110
- class Calculator < Rattler::Runtime::WDMParser
111
- include CalculatorGrammar
112
- end
113
-
114
- begin
115
- puts Calculator.parse!(expr)
116
- rescue Rattler::Runtime::SyntaxError => e
117
- puts e
124
+ class JsonParser < Rattler::Runtime::PackratParser
125
+
126
+ include JsonGrammar
127
+
128
+ def object(members)
129
+ Hash[*members.flatten(1)]
130
+ end
131
+
132
+ def string(expr)
133
+ eval expr, TOPLEVEL_BINDING
134
+ end
135
+
118
136
  end
119
137
 
120
138
  === Example 3: Dynamically generated parser class
@@ -127,17 +145,18 @@ dynamically from strings.
127
145
 
128
146
  start <- expr EOF
129
147
 
130
- expr <- expr ~'+' term {|a, b| a + b }
131
- | expr ~'-' term {|a, b| a - b }
148
+ expr <- expr ~'+' term {|a, b| a + b }
149
+ | expr ~'-' term {|a, b| a - b }
132
150
  | term
133
151
 
134
- term <- term ~'*' primary {|a, b| a * b }
135
- | term ~'/' primary {|a, b| a / b }
152
+ term <- term ~'*' primary {|a, b| a * b }
153
+ | term ~'/' primary {|a, b| a / b }
136
154
  | primary
137
155
 
138
156
  primary <- ~'(' expr ~')'
139
- | @(DIGIT+ ('.' DIGIT+)?) {|_| _.to_f }
140
- }, :type => :wdm
157
+ | @('-'? DIGIT+ '.' DIGIT+) { _.to_f }
158
+ | @('-'? DIGIT+) { _.to_i }
159
+ }, :type => :extended_packrat
141
160
 
142
161
  begin
143
162
  puts Calculator.parse!(expr)
@@ -0,0 +1,24 @@
1
+ Feature: Whitespace
2
+
3
+ Comments start with "#" and continue to the end of the line.
4
+
5
+ In order to clarify my grammars
6
+ As a language designer
7
+ I want to use comments
8
+
9
+ Scenario: Entire line as a comment
10
+ Given a grammar with:
11
+ """
12
+ # match one or more alphanumeric or underscore characters
13
+ word <- @WORD+
14
+ """
15
+ When I parse "foo"
16
+ Then the parse result should be "foo"
17
+
18
+ Scenario: Comment at the end of a line
19
+ Given a grammar with:
20
+ """
21
+ word <- @WORD+ # WORD matches any alphanumeric or underscore character
22
+ """
23
+ When I parse "foo"
24
+ Then the parse result should be "foo"
@@ -0,0 +1,41 @@
1
+ Feature: List Matching
2
+
3
+ An term expression followed by "*^" or "+^" and a separator expression means
4
+ to match a list of terms with separators between them. "*^" matches a list of
5
+ zero or more terms, "+^" matches a list of one or more term.
6
+
7
+ In order to clearly and easily match list expressions
8
+ As a language designer
9
+ I want to use a list-matching expression
10
+
11
+ Scenario Outline: Zero or more terms
12
+ Given a grammar with:
13
+ """
14
+ words <- @WORD+ *^ ','
15
+ """
16
+ When I parse <input>
17
+ Then the parse result should be <result>
18
+ And the parse position should be <pos>
19
+
20
+ Examples:
21
+ | input | result | pos |
22
+ | "foo" | ["foo"] | 3 |
23
+ | "foo,bar,baz" | ["foo", "bar", "baz"] | 11 |
24
+ | "foo,bar," | ["foo", "bar"] | 7 |
25
+ | " " | [] | 0 |
26
+
27
+ Scenario Outline: One or more terms
28
+ Given a grammar with:
29
+ """
30
+ words <- @WORD+ +^ ','
31
+ """
32
+ When I parse <input>
33
+ Then the parse result should be <result>
34
+ And the parse position should be <pos>
35
+
36
+ Examples:
37
+ | input | result | pos |
38
+ | "foo" | ["foo"] | 3 |
39
+ | "foo,bar,baz" | ["foo", "bar", "baz"] | 11 |
40
+ | "foo,bar," | ["foo", "bar"] | 7 |
41
+ | " " | FAIL | 0 |
@@ -6,7 +6,7 @@ Feature: Symantic Actions
6
6
  specified like Ruby block parameters and are bound to the parse results from
7
7
  the match. If there are fewer parameters than parse results the extra results
8
8
  are simply ignored. Labeled parse results can be refered to as identifiers in
9
- the action.
9
+ the action. The special identifier "_" refers to the entire parse results.
10
10
 
11
11
  In order to add simple symantics to parse results
12
12
  As a language designer
@@ -15,19 +15,11 @@ Feature: Symantic Actions
15
15
  Scenario: Single token
16
16
  Given a grammar with:
17
17
  """
18
- integer <- /\d+/ {|_| _.to_i }
18
+ integer <- /\d+/ {|s| s.to_i }
19
19
  """
20
20
  When I parse "42"
21
21
  Then the parse result should be 42
22
22
 
23
- Scenario: Shortcut form
24
- Given a grammar with:
25
- """
26
- integer <- /\d+/ <.to_i>
27
- """
28
- When I parse "23"
29
- Then the parse result should be 23
30
-
31
23
  Scenario: Sequence
32
24
  Given a grammar with:
33
25
  """
@@ -36,7 +28,7 @@ Feature: Symantic Actions
36
28
  """
37
29
  When I parse "3 16"
38
30
  Then the parse result should be 48
39
-
31
+
40
32
  Scenario: Sequence with non-capturing expressions
41
33
  Given a grammar with:
42
34
  """
@@ -51,4 +43,30 @@ Feature: Symantic Actions
51
43
  sum <- "(" left:/\d+/ "+" right:/\d+/ ")" { left.to_i + right.to_i }
52
44
  """
53
45
  When I parse "(17+29)"
54
- Then the parse result should be 46
46
+ Then the parse result should be 46
47
+
48
+ Scenario: Single token using "_"
49
+ Given a grammar with:
50
+ """
51
+ integer <- /\d+/ { _.to_i }
52
+ """
53
+ When I parse "23"
54
+ Then the parse result should be 23
55
+
56
+ Scenario: Sequence using "_"
57
+ Given a grammar with:
58
+ """
59
+ %whitespace SPACE*
60
+ ints <- /\d+/ /\d+/ { _.reverse }
61
+ """
62
+ When I parse "3 16"
63
+ Then the parse result should be ["16", "3"]
64
+
65
+ Scenario: Sequence using "_" as a parameter name
66
+ Given a grammar with:
67
+ """
68
+ %whitespace SPACE*
69
+ ints <- /\d+/ /\d+/ {|_| _.to_i }
70
+ """
71
+ When I parse "3 16"
72
+ Then the parse result should be 3
@@ -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 AssertGenerator < ExprGenerator #:nodoc:
7
-
7
+
8
8
  def gen_basic(assert)
9
- generate assert.child, :gen_assert
9
+ generate assert.child, :assert
10
10
  end
11
-
11
+
12
12
  def gen_assert(assert)
13
13
  gen_basic assert
14
14
  end
15
-
15
+
16
16
  def gen_disallow(assert)
17
17
  @g << 'false'
18
18
  end
19
-
19
+
20
20
  def gen_skip_nested(assert)
21
21
  gen_basic_nested assert
22
22
  end
23
-
23
+
24
24
  def gen_skip_top_level(assert)
25
25
  gen_basic_top_level assert
26
26
  end
27
-
27
+
28
28
  def gen_dispatch_action_nested(assert, target, method_name)
29
29
  atomic_block { gen_dispatch_action_top_level assert, target, method_name }
30
30
  end
31
-
31
+
32
32
  def gen_dispatch_action_top_level(assert, target, method_name)
33
33
  gen_action assert,
34
34
  dispatch_action_result(target, method_name, :array_expr => '[]')
35
35
  end
36
-
36
+
37
37
  def gen_direct_action_nested(assert, code)
38
38
  atomic_block { gen_direct_action_top_level assert, code }
39
39
  end
40
-
40
+
41
41
  def gen_direct_action_top_level(assert, code)
42
42
  gen_action assert, direct_action_result(code)
43
43
  end
44
-
44
+
45
45
  def gen_token_nested(assert)
46
46
  atomic_block { gen_token_top_level assert }
47
47
  end
48
-
48
+
49
49
  def gen_token_top_level(assert)
50
50
  gen_action assert, "''"
51
51
  end
52
-
52
+
53
53
  def gen_intermediate(assert)
54
- generate assert.child, :gen_intermediate_assert
54
+ generate assert.child, :intermediate_assert
55
55
  end
56
-
56
+
57
57
  def gen_intermediate_assert(assert)
58
58
  gen_intermediate assert
59
59
  end
60
-
60
+
61
61
  def gen_intermediate_skip(assert)
62
62
  gen_intermediate assert
63
63
  end
64
-
64
+
65
65
  private
66
-
66
+
67
67
  def gen_action(assert, result_code)
68
68
  gen_intermediate assert
69
69
  (@g << ' &&').newline << result_code
70
70
  end
71
-
71
+
72
72
  end
73
-
73
+
74
74
  # @private
75
75
  class NestedAssertGenerator < AssertGenerator #:nodoc:
76
76
  include Nested
77
- include NestedGenerators
77
+ include NestedSubGenerating
78
78
  end
79
-
79
+
80
80
  def AssertGenerator.nested(*args)
81
81
  NestedAssertGenerator.new(*args)
82
82
  end
83
-
83
+
84
84
  # @private
85
85
  class TopLevelAssertGenerator < AssertGenerator #:nodoc:
86
86
  include TopLevel
87
- include TopLevelGenerators
87
+ include TopLevelSubGenerating
88
88
  end
89
-
89
+
90
90
  def AssertGenerator.top_level(*args)
91
91
  TopLevelAssertGenerator.new(*args)
92
92
  end
93
-
93
+
94
94
  end
@@ -1,88 +1,88 @@
1
1
  require 'rattler/back_end/parser_generator'
2
2
 
3
3
  module Rattler::BackEnd::ParserGenerator
4
-
4
+
5
5
  # @private
6
6
  class ChoiceGenerator < ExprGenerator #:nodoc:
7
- include NestedGenerators
8
-
7
+ include NestedSubGenerating
8
+
9
9
  def gen_basic_nested(choice)
10
10
  atomic_block { gen_basic_top_level choice }
11
11
  end
12
-
12
+
13
13
  def gen_basic_top_level(choice)
14
14
  @g.intersperse_nl(choice, ' ||') {|_| generate _ }
15
15
  end
16
-
16
+
17
17
  def gen_assert_nested(choice)
18
18
  atomic_expr { gen_assert_top_level choice }
19
19
  end
20
-
20
+
21
21
  def gen_assert_top_level(choice)
22
22
  gen_intermediate_assert choice
23
23
  @g << ' && true'
24
24
  end
25
-
25
+
26
26
  def gen_disallow(choice)
27
27
  @g << '!'
28
28
  gen_intermediate_assert choice
29
29
  end
30
-
30
+
31
31
  def gen_dispatch_action_nested(choice, target, method_name)
32
32
  atomic_block { gen_dispatch_action_top_level choice, target, method_name }
33
33
  end
34
-
34
+
35
35
  def gen_dispatch_action_top_level(choice, target, method_name)
36
36
  gen_action_code choice do |labeled|
37
37
  dispatch_action_result(target, method_name, :labeled => labeled)
38
38
  end
39
39
  end
40
-
40
+
41
41
  def gen_direct_action_nested(choice, action)
42
42
  atomic_block { gen_direct_action_top_level choice, action }
43
43
  end
44
-
44
+
45
45
  def gen_direct_action_top_level(choice, action)
46
46
  gen_action_code choice do |labeled|
47
47
  direct_action_result(action, :labeled => labeled)
48
48
  end
49
49
  end
50
-
50
+
51
51
  def gen_token_nested(choice)
52
52
  atomic_block { gen_token_top_level choice }
53
53
  end
54
-
54
+
55
55
  def gen_token_top_level(choice)
56
- @g.intersperse_nl(choice, ' ||') {|_| generate _, :gen_token }
56
+ @g.intersperse_nl(choice, ' ||') {|_| generate _, :token }
57
57
  end
58
-
58
+
59
59
  def gen_skip_nested(choice)
60
60
  @g.surround('(', ')') { gen_skip_top_level choice }
61
61
  end
62
-
62
+
63
63
  def gen_skip_top_level(choice)
64
64
  gen_intermediate_skip choice
65
65
  @g << ' && true'
66
66
  end
67
-
67
+
68
68
  def gen_intermediate_assert(choice)
69
69
  atomic_block do
70
70
  @g.intersperse_nl(choice, ' ||') do |_|
71
- generate _, :gen_intermediate_assert
71
+ generate _, :intermediate_assert
72
72
  end
73
73
  end
74
74
  end
75
-
75
+
76
76
  def gen_intermediate_skip(choice)
77
77
  atomic_block do
78
78
  @g.intersperse_nl(choice, ' ||') do |_|
79
- generate _, :gen_intermediate_skip
79
+ generate _, :intermediate_skip
80
80
  end
81
81
  end
82
82
  end
83
-
83
+
84
84
  private
85
-
85
+
86
86
  def gen_action_code(choice)
87
87
  labeled = choice.any? {|_| _.labeled? } ? labeled_name : nil
88
88
  @g.block("(#{result_name} = begin", 'end)') do
@@ -101,29 +101,29 @@ module Rattler::BackEnd::ParserGenerator
101
101
  end << ' && '
102
102
  @g << yield(labeled)
103
103
  end
104
-
104
+
105
105
  def labeled_name
106
106
  "l#{choice_level}"
107
107
  end
108
-
108
+
109
109
  end
110
-
110
+
111
111
  # @private
112
112
  class NestedChoiceGenerator < ChoiceGenerator #:nodoc:
113
113
  include Nested
114
114
  end
115
-
115
+
116
116
  def ChoiceGenerator.nested(*args)
117
117
  NestedChoiceGenerator.new(*args)
118
118
  end
119
-
119
+
120
120
  # @private
121
121
  class TopLevelChoiceGenerator < ChoiceGenerator #:nodoc:
122
122
  include TopLevel
123
123
  end
124
-
124
+
125
125
  def ChoiceGenerator.top_level(*args)
126
126
  TopLevelChoiceGenerator.new(*args)
127
127
  end
128
-
128
+
129
129
  end
@@ -1,59 +1,59 @@
1
1
  require 'rattler/back_end/parser_generator'
2
2
 
3
3
  module Rattler::BackEnd::ParserGenerator
4
-
4
+
5
5
  # @private
6
6
  class DirectActionGenerator < 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_direct_action_nested, action.bindable_code
12
+ generate action.child, :direct_action_nested, action.bindable_code
13
13
  end
14
-
14
+
15
15
  def gen_basic_top_level(action)
16
- generate action.child, :gen_direct_action_top_level, action.bindable_code
16
+ generate action.child, :direct_action_top_level, action.bindable_code
17
17
  end
18
-
18
+
19
19
  def gen_dispatch_action_nested(inner, target, method_name)
20
20
  atomic_block { gen_dispatch_action_top_level inner, target, method_name }
21
21
  end
22
-
22
+
23
23
  def gen_dispatch_action_top_level(inner, target, method_name)
24
24
  @g.surround("(#{result_name} = ", ')') { gen_basic_nested inner }
25
25
  (@g << ' &&').newline << dispatch_action_result(target, method_name)
26
26
  end
27
-
27
+
28
28
  def gen_direct_action_nested(inner, code)
29
29
  atomic_block { gen_direct_action_top_level inner, code }
30
30
  end
31
-
31
+
32
32
  def gen_direct_action_top_level(inner, code)
33
33
  @g.surround("(#{result_name} = ", ')') { gen_basic_nested inner }
34
34
  (@g << ' &&').newline << direct_action_result(code)
35
35
  end
36
-
36
+
37
37
  end
38
-
38
+
39
39
  # @private
40
40
  class NestedDirectActionGenerator < DirectActionGenerator #:nodoc:
41
41
  include Nested
42
- include NestedGenerators
42
+ include NestedSubGenerating
43
43
  end
44
-
44
+
45
45
  def DirectActionGenerator.nested(*args)
46
46
  NestedDirectActionGenerator.new(*args)
47
47
  end
48
-
48
+
49
49
  # @private
50
50
  class TopLevelDirectActionGenerator < DirectActionGenerator #:nodoc:
51
51
  include TopLevel
52
- include TopLevelGenerators
52
+ include TopLevelSubGenerating
53
53
  end
54
-
54
+
55
55
  def DirectActionGenerator.top_level(*args)
56
56
  TopLevelDirectActionGenerator.new(*args)
57
57
  end
58
-
58
+
59
59
  end