antlr3 1.2.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. data/ANTLR-LICENSE.txt +26 -0
  2. data/History.txt +66 -0
  3. data/README.txt +139 -0
  4. data/bin/antlr4ruby +33 -0
  5. data/java/RubyTarget.java +524 -0
  6. data/java/antlr-full-3.2.1.jar +0 -0
  7. data/lib/antlr3.rb +176 -0
  8. data/lib/antlr3/constants.rb +88 -0
  9. data/lib/antlr3/debug.rb +701 -0
  10. data/lib/antlr3/debug/event-hub.rb +210 -0
  11. data/lib/antlr3/debug/record-event-listener.rb +25 -0
  12. data/lib/antlr3/debug/rule-tracer.rb +55 -0
  13. data/lib/antlr3/debug/socket.rb +360 -0
  14. data/lib/antlr3/debug/trace-event-listener.rb +92 -0
  15. data/lib/antlr3/dfa.rb +247 -0
  16. data/lib/antlr3/dot.rb +174 -0
  17. data/lib/antlr3/error.rb +657 -0
  18. data/lib/antlr3/main.rb +561 -0
  19. data/lib/antlr3/modes/ast-builder.rb +41 -0
  20. data/lib/antlr3/modes/filter.rb +56 -0
  21. data/lib/antlr3/profile.rb +322 -0
  22. data/lib/antlr3/recognizers.rb +1280 -0
  23. data/lib/antlr3/streams.rb +985 -0
  24. data/lib/antlr3/streams/interactive.rb +91 -0
  25. data/lib/antlr3/streams/rewrite.rb +412 -0
  26. data/lib/antlr3/test/call-stack.rb +57 -0
  27. data/lib/antlr3/test/config.rb +23 -0
  28. data/lib/antlr3/test/core-extensions.rb +269 -0
  29. data/lib/antlr3/test/diff.rb +165 -0
  30. data/lib/antlr3/test/functional.rb +207 -0
  31. data/lib/antlr3/test/grammar.rb +371 -0
  32. data/lib/antlr3/token.rb +592 -0
  33. data/lib/antlr3/tree.rb +1415 -0
  34. data/lib/antlr3/tree/debug.rb +163 -0
  35. data/lib/antlr3/tree/visitor.rb +84 -0
  36. data/lib/antlr3/tree/wizard.rb +481 -0
  37. data/lib/antlr3/util.rb +149 -0
  38. data/lib/antlr3/version.rb +27 -0
  39. data/samples/ANTLRv3Grammar.g +621 -0
  40. data/samples/Cpp.g +749 -0
  41. data/templates/AST.stg +335 -0
  42. data/templates/ASTDbg.stg +40 -0
  43. data/templates/ASTParser.stg +153 -0
  44. data/templates/ASTTreeParser.stg +272 -0
  45. data/templates/Dbg.stg +192 -0
  46. data/templates/Ruby.stg +1514 -0
  47. data/test/functional/ast-output/auto-ast.rb +797 -0
  48. data/test/functional/ast-output/construction.rb +555 -0
  49. data/test/functional/ast-output/hetero-nodes.rb +753 -0
  50. data/test/functional/ast-output/rewrites.rb +1327 -0
  51. data/test/functional/ast-output/tree-rewrite.rb +1662 -0
  52. data/test/functional/debugging/debug-mode.rb +689 -0
  53. data/test/functional/debugging/profile-mode.rb +165 -0
  54. data/test/functional/debugging/rule-tracing.rb +74 -0
  55. data/test/functional/delegation/import.rb +379 -0
  56. data/test/functional/lexer/basic.rb +559 -0
  57. data/test/functional/lexer/filter-mode.rb +245 -0
  58. data/test/functional/lexer/nuances.rb +47 -0
  59. data/test/functional/lexer/properties.rb +104 -0
  60. data/test/functional/lexer/syn-pred.rb +32 -0
  61. data/test/functional/lexer/xml.rb +206 -0
  62. data/test/functional/main/main-scripts.rb +245 -0
  63. data/test/functional/parser/actions.rb +224 -0
  64. data/test/functional/parser/backtracking.rb +244 -0
  65. data/test/functional/parser/basic.rb +282 -0
  66. data/test/functional/parser/calc.rb +98 -0
  67. data/test/functional/parser/ll-star.rb +143 -0
  68. data/test/functional/parser/nuances.rb +165 -0
  69. data/test/functional/parser/predicates.rb +103 -0
  70. data/test/functional/parser/properties.rb +242 -0
  71. data/test/functional/parser/rule-methods.rb +132 -0
  72. data/test/functional/parser/scopes.rb +274 -0
  73. data/test/functional/token-rewrite/basic.rb +318 -0
  74. data/test/functional/token-rewrite/via-parser.rb +100 -0
  75. data/test/functional/tree-parser/basic.rb +750 -0
  76. data/test/unit/sample-input/file-stream-1 +2 -0
  77. data/test/unit/sample-input/teststreams.input2 +2 -0
  78. data/test/unit/test-dfa.rb +52 -0
  79. data/test/unit/test-exceptions.rb +44 -0
  80. data/test/unit/test-recognizers.rb +55 -0
  81. data/test/unit/test-scheme.rb +62 -0
  82. data/test/unit/test-streams.rb +459 -0
  83. data/test/unit/test-tree-wizard.rb +535 -0
  84. data/test/unit/test-trees.rb +854 -0
  85. metadata +205 -0
@@ -0,0 +1,149 @@
1
+ #!/usr/bin/ruby
2
+ # encoding: utf-8
3
+
4
+ module ANTLR3
5
+ module Util
6
+
7
+ module_function
8
+
9
+ def snake_case(str)
10
+ str = str.to_s.gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
11
+ str.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
12
+ str.tr!("-", "_")
13
+ str.downcase!
14
+ str
15
+ end
16
+
17
+ def tidy(here_doc, flow = false)
18
+ here_doc.gsub!(/^ *\| ?/, '')
19
+ if flow
20
+ here_doc.strip!
21
+ here_doc.gsub!(/\s+/, ' ')
22
+ end
23
+ return here_doc
24
+ end
25
+
26
+ def silence_warnings
27
+ verbosity, $VERBOSE = $VERBOSE, nil
28
+ return yield
29
+ ensure
30
+ $VERBOSE = verbosity
31
+ end
32
+
33
+ end
34
+
35
+ module ClassMacros
36
+
37
+ private
38
+
39
+ def shared_attribute( name, *additional_members )
40
+ attr_reader name
41
+
42
+ additional_writers = additional_members.inject('') do |src, attr|
43
+ src << "@#{attr} = value if @#{attr}\n"
44
+ end
45
+
46
+ file, line, = caller[1].split(':', 3)
47
+ class_eval(<<-END, file, line.to_i)
48
+ def #{name}= value
49
+ @#{name} = value
50
+
51
+ each_delegate do |del|
52
+ del.#{name} = value
53
+ end
54
+
55
+ #{additional_writers}
56
+ end
57
+ END
58
+ end
59
+
60
+ def abstract( name, message = nil )
61
+ message ||= "abstract method -- #{self.class}::#{name} has not been implemented"
62
+ file, line, = caller[1].split(':', 3)
63
+ class_eval(<<-END, file, line.to_i)
64
+ def #{name}( * )
65
+ raise TypeError, #{message.to_s.inspect}
66
+ end
67
+ END
68
+ end
69
+
70
+ def alias_accessor( alias_name, attr_name )
71
+ alias_method( alias_name, attr_name )
72
+ alias_method( :"#{alias_name}=", :"#{attr_name}=" )
73
+ end
74
+
75
+ end
76
+
77
+ end
78
+
79
+ class Integer
80
+
81
+ # Returns the lower of self or x.
82
+ #
83
+ # 4.at_least(5) #=> 5
84
+ # 6.at_least(5) #=> 6
85
+ #
86
+ # CREDIT Florian Gross
87
+
88
+ def at_least(x)
89
+ (self >= x) ? self : x
90
+ end
91
+
92
+ # Returns the greater of self or x.
93
+ #
94
+ # 4.at_most(5) #=> 4
95
+ # 6.at_most(5) #=> 5
96
+ #
97
+ # CREDIT Florian Gross
98
+
99
+ def at_most(x)
100
+ (self <= x) ? self : x
101
+ end
102
+
103
+ # Returns self if above the given lower bound, or
104
+ # within the given lower and upper bounds,
105
+ # otherwise returns the the bound of which the
106
+ # value falls outside.
107
+ #
108
+ # 4.bound(3) #=> 4
109
+ # 4.bound(5) #=> 5
110
+ # 4.bound(2,7) #=> 4
111
+ # 9.bound(2,7) #=> 7
112
+ # 1.bound(2,7) #=> 2
113
+ #
114
+ # CREDIT Trans
115
+
116
+ def bound(lower, upper=nil)
117
+ return lower if self < lower
118
+ return self unless upper
119
+ return upper if self > upper
120
+ return self
121
+ end
122
+
123
+ end
124
+
125
+
126
+ class Range
127
+ def covers?(range)
128
+ range.first >= first or return false
129
+ if exclude_end?
130
+ range.exclude_end? ? last >= range.last : last > range.last
131
+ else
132
+ range.exclude_end? ? last.succ >= range.last : last >= range.last
133
+ end
134
+ end
135
+
136
+ def covered_by?(range)
137
+ range.covers?(self)
138
+ end
139
+
140
+ def overlaps?(range)
141
+ range.include?(first) or include?(range.first)
142
+ end
143
+
144
+ def disjoint?(range)
145
+ not overlaps?(range)
146
+ end
147
+
148
+ end
149
+
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/ruby
2
+ # encoding: utf-8
3
+
4
+ module ANTLR3
5
+
6
+ #
7
+ # The version of the ANTLR tool used while designing and
8
+ # testing the current version of this library
9
+ #
10
+ ANTLR_MAJOR_VERSION = 3
11
+ ANTLR_MINOR_VERSION = 2
12
+ ANTLR_PATCH_VERSION = 1
13
+ ANTLR_VERSION = [ANTLR_MAJOR_VERSION, ANTLR_MINOR_VERSION, ANTLR_PATCH_VERSION].freeze
14
+ ANTLR_VERSION_STRING = ANTLR_VERSION.join('.')
15
+ ANTLR_VERSION_STRING.chomp!( '.0' ) # versioning drops minor version at 0
16
+ ANTLR_VERSION_STRING.freeze
17
+
18
+ #
19
+ # The version data for the current state the library itself
20
+ #
21
+ MAJOR_VERSION = 1
22
+ MINOR_VERSION = 2
23
+ PATCH_VERSION = 3
24
+ VERSION = [MAJOR_VERSION, MINOR_VERSION, PATCH_VERSION]
25
+ VERSION_STRING = VERSION.join('.').freeze
26
+
27
+ end
@@ -0,0 +1,621 @@
1
+ /*
2
+ [The "BSD licence"]
3
+ Copyright (c) 2005-2007 Terence Parr
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions
8
+ are met:
9
+ 1. Redistributions of source code must retain the above copyright
10
+ notice, this list of conditions and the following disclaimer.
11
+ 2. Redistributions in binary form must reproduce the above copyright
12
+ notice, this list of conditions and the following disclaimer in the
13
+ documentation and/or other materials provided with the distribution.
14
+ 3. The name of the author may not be used to endorse or promote products
15
+ derived from this software without specific prior written permission.
16
+
17
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20
+ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+ */
28
+
29
+ /** ANTLR v3 grammar written in ANTLR v3 with AST construction */
30
+ grammar ANTLRv3Grammar;
31
+
32
+ options {
33
+ ASTLabelType = CommonTree;
34
+ language = Ruby;
35
+ output = AST;
36
+ }
37
+
38
+ tokens {
39
+ DOC_COMMENT;
40
+ PARSER;
41
+ LEXER;
42
+ RULE;
43
+ BLOCK;
44
+ OPTIONAL;
45
+ CLOSURE;
46
+ POSITIVE_CLOSURE;
47
+ SYNPRED;
48
+ RANGE;
49
+ CHAR_RANGE;
50
+ EPSILON;
51
+ ALT;
52
+ EOR;
53
+ EOB;
54
+ EOA; // end of alt
55
+ ID;
56
+ ARG;
57
+ ARGLIST;
58
+ RET='returns';
59
+ LEXER_GRAMMAR;
60
+ PARSER_GRAMMAR;
61
+ TREE_GRAMMAR;
62
+ COMBINED_GRAMMAR;
63
+ LABEL; // $x used in rewrite rules
64
+ TEMPLATE;
65
+ SCOPE='scope';
66
+ SEMPRED;
67
+ GATED_SEMPRED; // {p}? =>
68
+ SYN_SEMPRED; // (...) => it's a manually-specified synpred converted to sempred
69
+ BACKTRACK_SEMPRED; // auto backtracking mode syn pred converted to sempred
70
+ FRAGMENT='fragment';
71
+ TREE_BEGIN='^(';
72
+ ROOT='^';
73
+ BANG='!';
74
+ RANGE='..';
75
+ REWRITE='->';
76
+ AT='@';
77
+ LABEL_ASSIGN='=';
78
+ LIST_LABEL_ASSIGN='+=';
79
+ }
80
+
81
+ /* action -> @parser::header
82
+ {
83
+ package org.antlr.grammar.v3;
84
+ } */
85
+ /* action -> @lexer::header
86
+ {
87
+ package org.antlr.grammar.v3;
88
+ } */
89
+
90
+ @members {
91
+ attr_reader :grammar_type
92
+ }
93
+
94
+ grammar_def
95
+ : DOC_COMMENT?
96
+ ( 'lexer' { @grammar_type = LEXER_GRAMMAR } // pure lexer
97
+ | 'parser' { @grammar_type = PARSER_GRAMMAR } // pure parser
98
+ | 'tree' { @grammar_type = TREE_GRAMMAR } // a tree parser
99
+ | { @grammar_type = COMBINED_GRAMMAR } // merged parser/lexer
100
+ )
101
+ g='grammar' id ';' options_spec? tokens_spec? attr_scope* action*
102
+ rule+
103
+ EOF
104
+ -> ^( {@adaptor.create!(@grammar_type, $g) }
105
+ id DOC_COMMENT? options_spec? tokens_spec? attr_scope* action* rule+
106
+ )
107
+ ;
108
+
109
+ tokens_spec
110
+ : TOKENS token_spec+ '}' -> ^(TOKENS token_spec+)
111
+ ;
112
+
113
+ token_spec
114
+ : TOKEN_REF
115
+ ( '=' (lit=STRING_LITERAL|lit=CHAR_LITERAL) -> ^('=' TOKEN_REF $lit)
116
+ | -> TOKEN_REF
117
+ )
118
+ ';'
119
+ ;
120
+
121
+ attr_scope
122
+ : 'scope' id ACTION -> ^('scope' id ACTION)
123
+ ;
124
+
125
+ /** Match stuff like @parser::members {int i;} */
126
+ action
127
+ : '@' (action_scope_name '::')? id ACTION -> ^('@' action_scope_name? id ACTION)
128
+ ;
129
+
130
+ /** Sometimes the scope names will collide with keywords; allow them as
131
+ * ids for action scopes.
132
+ */
133
+ action_scope_name
134
+ : id
135
+ | l='lexer' -> ID[$l]
136
+ | p='parser' -> ID[$p]
137
+ ;
138
+
139
+ options_spec
140
+ : OPTIONS (option ';')+ '}' -> ^(OPTIONS option+)
141
+ ;
142
+
143
+ option
144
+ : id '=' option_value -> ^('=' id option_value)
145
+ ;
146
+
147
+ option_value
148
+ : qid
149
+ | STRING_LITERAL
150
+ | CHAR_LITERAL
151
+ | INT
152
+ | s='*' -> STRING_LITERAL[$s] // used for k=*
153
+ ;
154
+
155
+ rule
156
+ scope {
157
+ name;
158
+ }
159
+ : DOC_COMMENT?
160
+ ( modifier=('protected'|'public'|'private'|'fragment') )?
161
+ id { $rule::name = $id.text }
162
+ '!'?
163
+ ( arg=ARG_ACTION )?
164
+ ( 'returns' rt=ARG_ACTION )?
165
+ throws_spec? options_spec? rule_scope_spec? rule_action*
166
+ ':' alt_list ';'
167
+ exception_group?
168
+ -> ^( RULE id {$modifier ? @adaptor.create!($modifier) : nil} ^(ARG[$arg] $arg)? ^('returns' $rt)?
169
+ throws_spec? options_spec? rule_scope_spec? rule_action*
170
+ alt_list
171
+ exception_group?
172
+ EOR["EOR"]
173
+ )
174
+ ;
175
+
176
+ /** Match stuff like @init {int i;} */
177
+ rule_action
178
+ : '@' id ACTION -> ^('@' id ACTION)
179
+ ;
180
+
181
+ throws_spec
182
+ : 'throws' id ( ',' id )* -> ^('throws' id+)
183
+ ;
184
+
185
+ rule_scope_spec
186
+ : 'scope' ACTION -> ^('scope' ACTION)
187
+ | 'scope' id (',' id)* ';' -> ^('scope' id+)
188
+ | 'scope' ACTION
189
+ 'scope' id (',' id)* ';'
190
+ -> ^('scope' ACTION id+ )
191
+ ;
192
+
193
+ block
194
+ : lp='('
195
+ ( (opts=options_spec)? ':' )?
196
+ altpair ( '|' altpair )*
197
+ rp=')'
198
+ -> ^( BLOCK[$lp,"BLOCK"] options_spec? altpair+ EOB[$rp,"EOB"] )
199
+ ;
200
+
201
+ altpair : alternative rewrite ;
202
+
203
+ alt_list
204
+ @init {
205
+ block_root = @adaptor.create!(BLOCK, @input.look(-1), "BLOCK");
206
+ }
207
+ : altpair ( '|' altpair )* -> ^( {block_root} altpair+ EOB["eob"] )
208
+ ;
209
+
210
+ alternative
211
+ @init {
212
+ first_token = @input.look(1)
213
+ prev_token = @input.look(-1)
214
+ }
215
+ : element+ -> ^(ALT[first_token,"ALT"] element+ EOA["EOA"])
216
+ | -> ^(ALT[prev_token,"ALT"] EPSILON[prev_token,"EPSILON"] EOA["EOA"])
217
+ ;
218
+
219
+ exception_group
220
+ : ( exception_handler )+ ( finally_clause )?
221
+ | finally_clause
222
+ ;
223
+
224
+ exception_handler
225
+ : 'catch' ARG_ACTION ACTION -> ^('catch' ARG_ACTION ACTION)
226
+ ;
227
+
228
+ finally_clause
229
+ : 'finally' ACTION -> ^('finally' ACTION)
230
+ ;
231
+
232
+ element
233
+ : id (labelOp='='|labelOp='+=') atom
234
+ ( ebnf_suffix -> ^( ebnf_suffix ^(BLOCK["BLOCK"] ^(ALT["ALT"] ^($labelOp id atom) EOA["EOA"]) EOB["EOB"]))
235
+ | -> ^($labelOp id atom)
236
+ )
237
+ | id (labelOp='='|labelOp='+=') block
238
+ ( ebnf_suffix -> ^( ebnf_suffix ^(BLOCK["BLOCK"] ^(ALT["ALT"] ^($labelOp id block) EOA["EOA"]) EOB["EOB"]))
239
+ | -> ^($labelOp id block)
240
+ )
241
+ | atom
242
+ ( ebnf_suffix -> ^( ebnf_suffix ^(BLOCK["BLOCK"] ^(ALT["ALT"] atom EOA["EOA"]) EOB["EOB"]) )
243
+ | -> atom
244
+ )
245
+ | ebnf
246
+ | ACTION
247
+ | SEMPRED ( g='=>' -> GATED_SEMPRED[$g] | -> SEMPRED )
248
+ | tree_spec
249
+ ( ebnf_suffix -> ^( ebnf_suffix ^(BLOCK["BLOCK"] ^(ALT["ALT"] tree_spec EOA["EOA"]) EOB["EOB"]) )
250
+ | -> tree_spec
251
+ )
252
+ ;
253
+
254
+ atom: terminal
255
+ | range
256
+ ( (op='^'|op='!') -> ^($op range)
257
+ | -> range
258
+ )
259
+ | not_set
260
+ ( (op='^'|op='!') -> ^($op not_set)
261
+ | -> not_set
262
+ )
263
+ | RULE_REF ARG_ACTION?
264
+ ( (op='^'|op='!') -> ^($op RULE_REF ARG_ACTION?)
265
+ | -> ^(RULE_REF ARG_ACTION?)
266
+ )
267
+ ;
268
+
269
+ not_set
270
+ : '~'
271
+ ( not_terminal element_options? -> ^('~' not_terminal element_options?)
272
+ | block element_options? -> ^('~' block element_options?)
273
+ )
274
+ ;
275
+
276
+ not_terminal
277
+ : CHAR_LITERAL
278
+ | TOKEN_REF
279
+ | STRING_LITERAL
280
+ ;
281
+
282
+ element_options
283
+ : '<' qid '>' -> ^(OPTIONS qid)
284
+ | '<' option (';' option)* '>' -> ^(OPTIONS option+)
285
+ ;
286
+
287
+ element_option
288
+ : id '=' option_value -> ^('=' id option_value)
289
+ ;
290
+
291
+ tree_spec
292
+ : '^(' element ( element )+ ')' -> ^(TREE_BEGIN element+)
293
+ ;
294
+
295
+ range!
296
+ : c1=CHAR_LITERAL RANGE c2=CHAR_LITERAL element_options?
297
+ -> ^(CHAR_RANGE[$c1,".."] $c1 $c2 element_options?)
298
+ ;
299
+
300
+ terminal
301
+ : ( CHAR_LITERAL element_options? -> ^(CHAR_LITERAL element_options?)
302
+ // Args are only valid for lexer rules
303
+ | TOKEN_REF ARG_ACTION? element_options? -> ^(TOKEN_REF ARG_ACTION? element_options?)
304
+ | STRING_LITERAL element_options? -> ^(STRING_LITERAL element_options?)
305
+ | '.' element_options? -> ^('.' element_options?)
306
+ )
307
+ ( '^' -> ^('^' $terminal)
308
+ | '!' -> ^('!' $terminal)
309
+ )?
310
+ ;
311
+
312
+ /** Matches ENBF blocks (and token sets via block rule) */
313
+ ebnf
314
+ @init { first_token = @input.look(1) }
315
+ @after {
316
+ $ebnf.tree.token.line = first_token.line
317
+ $ebnf.tree.token.column = first_token.column
318
+ }
319
+ : block
320
+ ( op='?' -> ^(OPTIONAL[$op] block)
321
+ | op='*' -> ^(CLOSURE[$op] block)
322
+ | op='+' -> ^(POSITIVE_CLOSURE[$op] block)
323
+ | '=>' // syntactic predicate
324
+ -> {
325
+ @grammar_type == COMBINED_GRAMMAR && $rule::name[0].between?(?A, ?Z)
326
+ }?
327
+ // if lexer rule in combined, leave as pred for lexer
328
+ ^(SYNPRED["=>"] block)
329
+ // in real antlr tool, text for SYN_SEMPRED is predname
330
+ -> SYN_SEMPRED
331
+ | -> block
332
+ )
333
+ ;
334
+
335
+ ebnf_suffix
336
+ @init {
337
+ op = @input.look(1)
338
+ }
339
+ : '?' -> OPTIONAL[op]
340
+ | '*' -> CLOSURE[op]
341
+ | '+' -> POSITIVE_CLOSURE[op]
342
+ ;
343
+
344
+
345
+
346
+ // R E W R I T E S Y N T A X
347
+
348
+ rewrite
349
+ @init {
350
+ first_token = @input.look(1)
351
+ }
352
+ : (rew+='->' preds+=SEMPRED predicated+=rewrite_alternative)*
353
+ rew2='->' last=rewrite_alternative
354
+ -> ^($rew $preds $predicated)* ^($rew2 $last)
355
+ |
356
+ ;
357
+
358
+ rewrite_alternative
359
+ options {backtrack=true;}
360
+ : rewrite_template
361
+ | rewrite_tree_alternative
362
+ | /* empty rewrite */ -> ^(ALT["ALT"] EPSILON["EPSILON"] EOA["EOA"])
363
+ ;
364
+
365
+ rewrite_tree_block
366
+ : lp='(' rewrite_tree_alternative ')'
367
+ -> ^(BLOCK[$lp,"BLOCK"] rewrite_tree_alternative EOB[$lp,"EOB"])
368
+ ;
369
+
370
+ rewrite_tree_alternative
371
+ : rewrite_tree_element+ -> ^(ALT["ALT"] rewrite_tree_element+ EOA["EOA"])
372
+ ;
373
+
374
+ rewrite_tree_element
375
+ : rewrite_tree_atom
376
+ | rewrite_tree_atom ebnf_suffix
377
+ -> ^( ebnf_suffix ^(BLOCK["BLOCK"] ^(ALT["ALT"] rewrite_tree_atom EOA["EOA"]) EOB["EOB"]))
378
+ | rewrite_tree
379
+ ( ebnf_suffix
380
+ -> ^(ebnf_suffix ^(BLOCK["BLOCK"] ^(ALT["ALT"] rewrite_tree EOA["EOA"]) EOB["EOB"]))
381
+ | -> rewrite_tree
382
+ )
383
+ | rewrite_tree_ebnf
384
+ ;
385
+
386
+ rewrite_tree_atom
387
+ : CHAR_LITERAL
388
+ | TOKEN_REF ARG_ACTION? -> ^(TOKEN_REF ARG_ACTION?) // for imaginary nodes
389
+ | RULE_REF
390
+ | STRING_LITERAL
391
+ | d='$' id -> LABEL[$d,$id.text] // reference to a label in a rewrite rule
392
+ | ACTION
393
+ ;
394
+
395
+ rewrite_tree_ebnf
396
+ @init {
397
+ first_token = @input.look(1)
398
+ }
399
+ @after {
400
+ $rewrite_tree_ebnf.tree.token.line = first_token.line
401
+ $rewrite_tree_ebnf.tree.token.column = first_token.column
402
+ }
403
+ : rewrite_tree_block ebnf_suffix -> ^(ebnf_suffix rewrite_tree_block)
404
+ ;
405
+
406
+ rewrite_tree
407
+ : '^(' rewrite_tree_atom rewrite_tree_element* ')'
408
+ -> ^(TREE_BEGIN rewrite_tree_atom rewrite_tree_element* )
409
+ ;
410
+
411
+ /** Build a tree for a template rewrite:
412
+ ^(TEMPLATE (ID|ACTION) ^(ARGLIST ^(ARG ID ACTION) ...) )
413
+ where ARGLIST is always there even if no args exist.
414
+ ID can be "template" keyword. If first child is ACTION then it's
415
+ an indirect template ref
416
+
417
+ -> foo(a={...}, b={...})
418
+ -> ({string-e})(a={...}, b={...}) // e evaluates to template name
419
+ -> {%{$ID.text}} // create literal template from string (done in ActionTranslator)
420
+ -> {st-expr} // st-expr evaluates to ST
421
+ */
422
+ rewrite_template
423
+ : // -> template(a={...},...) "..." inline template
424
+ id lp='(' rewrite_template_args ')'
425
+ ( str=DOUBLE_QUOTE_STRING_LITERAL | str=DOUBLE_ANGLE_STRING_LITERAL )
426
+ -> ^(TEMPLATE[$lp,"TEMPLATE"] id rewrite_template_args $str)
427
+
428
+ | // -> foo(a={...}, ...)
429
+ rewrite_template_ref
430
+
431
+ | // -> ({expr})(a={...}, ...)
432
+ rewrite_indirect_template_head
433
+
434
+ | // -> {...}
435
+ ACTION
436
+ ;
437
+
438
+ /** -> foo(a={...}, ...) */
439
+ rewrite_template_ref
440
+ : id lp='(' rewrite_template_args ')'
441
+ -> ^(TEMPLATE[$lp,"TEMPLATE"] id rewrite_template_args)
442
+ ;
443
+
444
+ /** -> ({expr})(a={...}, ...) */
445
+ rewrite_indirect_template_head
446
+ : lp='(' ACTION ')' '(' rewrite_template_args ')'
447
+ -> ^(TEMPLATE[$lp,"TEMPLATE"] ACTION rewrite_template_args)
448
+ ;
449
+
450
+ rewrite_template_args
451
+ : rewrite_template_arg (',' rewrite_template_arg)*
452
+ -> ^(ARGLIST rewrite_template_arg+)
453
+ | -> ARGLIST
454
+ ;
455
+
456
+ rewrite_template_arg
457
+ : id '=' ACTION -> ^(ARG[$id.start] id ACTION)
458
+ ;
459
+
460
+ qid : id ('.' id)* ;
461
+
462
+ id :
463
+ TOKEN_REF -> ID[$TOKEN_REF]
464
+ | RULE_REF -> ID[$RULE_REF]
465
+ ;
466
+
467
+ // L E X I C A L R U L E S
468
+
469
+ SL_COMMENT
470
+ : '//'
471
+ ( ' $ANTLR ' SRC // src directive
472
+ | ~('\r'|'\n')*
473
+ )
474
+ '\r'? '\n' {$channel=HIDDEN;}
475
+ ;
476
+
477
+ ML_COMMENT
478
+ : '/*' {if @input.peek(1) == ?* then $type = DOC_COMMENT else $channel = HIDDEN end } .* '*/'
479
+ ;
480
+
481
+ CHAR_LITERAL
482
+ : '\'' LITERAL_CHAR '\''
483
+ ;
484
+
485
+ STRING_LITERAL
486
+ : '\'' LITERAL_CHAR LITERAL_CHAR* '\''
487
+ ;
488
+
489
+ fragment
490
+ LITERAL_CHAR
491
+ : ESC
492
+ | ~('\''|'\\')
493
+ ;
494
+
495
+ DOUBLE_QUOTE_STRING_LITERAL
496
+ : '"' (ESC | ~('\\'|'"'))* '"'
497
+ ;
498
+
499
+ DOUBLE_ANGLE_STRING_LITERAL
500
+ : '<<' .* '>>'
501
+ ;
502
+
503
+ fragment
504
+ ESC : '\\'
505
+ ( 'n'
506
+ | 'r'
507
+ | 't'
508
+ | 'b'
509
+ | 'f'
510
+ | '"'
511
+ | '\''
512
+ | '\\'
513
+ | '>'
514
+ | 'u' XDIGIT XDIGIT XDIGIT XDIGIT
515
+ | . // unknown, leave as it is
516
+ )
517
+ ;
518
+
519
+ fragment
520
+ XDIGIT :
521
+ '0' .. '9'
522
+ | 'a' .. 'f'
523
+ | 'A' .. 'F'
524
+ ;
525
+
526
+ INT : '0'..'9'+
527
+ ;
528
+
529
+ ARG_ACTION
530
+ : NESTED_ARG_ACTION
531
+ ;
532
+
533
+ fragment
534
+ NESTED_ARG_ACTION :
535
+ '['
536
+ ( options {greedy=false; k=1;}
537
+ : NESTED_ARG_ACTION
538
+ | ACTION_STRING_LITERAL
539
+ | ACTION_CHAR_LITERAL
540
+ | .
541
+ )*
542
+ ']'
543
+ //{setText(getText().substring(1, getText().length()-1));}
544
+ ;
545
+
546
+ ACTION
547
+ : NESTED_ACTION ( '?' { $type = SEMPRED } )?
548
+ ;
549
+
550
+ fragment
551
+ NESTED_ACTION :
552
+ '{'
553
+ ( options {greedy=false; k=2;}
554
+ : NESTED_ACTION
555
+ | SL_COMMENT
556
+ | ML_COMMENT
557
+ | ACTION_STRING_LITERAL
558
+ | ACTION_CHAR_LITERAL
559
+ | ~ '\\'
560
+ | '\\' .
561
+ )*
562
+ '}'
563
+ ;
564
+
565
+ fragment
566
+ ACTION_CHAR_LITERAL
567
+ : '\'' ( ~('\\'|'\'') | '\\' . )* '\''
568
+ ;
569
+
570
+ fragment
571
+ ACTION_STRING_LITERAL
572
+ : '"' ( ~('\\'|'"') | '\\' . )* '"'
573
+ ;
574
+
575
+ fragment
576
+ ACTION_ESC
577
+ : '\\' .
578
+ ;
579
+
580
+ TOKEN_REF
581
+ : 'A'..'Z' ('a'..'z'|'A'..'Z'|'_'|'0'..'9')*
582
+ ;
583
+
584
+ RULE_REF
585
+ : 'a'..'z' ('a'..'z'|'A'..'Z'|'_'|'0'..'9')*
586
+ ;
587
+
588
+ /** Match the start of an options section. Don't allow normal
589
+ * action processing on the {...} as it's not a action.
590
+ */
591
+ OPTIONS
592
+ : 'options' WS_LOOP '{'
593
+ ;
594
+
595
+ TOKENS
596
+ : 'tokens' WS_LOOP '{'
597
+ ;
598
+
599
+ /** Reset the file and line information; useful when the grammar
600
+ * has been generated so that errors are shown relative to the
601
+ * original file like the old C preprocessor used to do.
602
+ */
603
+ fragment
604
+ SRC : 'src' ' ' file=ACTION_STRING_LITERAL ' ' line=INT
605
+ ;
606
+
607
+ WS : ( ' '
608
+ | '\t'
609
+ | '\r'? '\n'
610
+ )+
611
+ {$channel=HIDDEN}
612
+ ;
613
+
614
+ fragment
615
+ WS_LOOP
616
+ : ( WS
617
+ | SL_COMMENT
618
+ | ML_COMMENT
619
+ )*
620
+ ;
621
+