antlr3 1.2.3
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/ANTLR-LICENSE.txt +26 -0
- data/History.txt +66 -0
- data/README.txt +139 -0
- data/bin/antlr4ruby +33 -0
- data/java/RubyTarget.java +524 -0
- data/java/antlr-full-3.2.1.jar +0 -0
- data/lib/antlr3.rb +176 -0
- data/lib/antlr3/constants.rb +88 -0
- data/lib/antlr3/debug.rb +701 -0
- data/lib/antlr3/debug/event-hub.rb +210 -0
- data/lib/antlr3/debug/record-event-listener.rb +25 -0
- data/lib/antlr3/debug/rule-tracer.rb +55 -0
- data/lib/antlr3/debug/socket.rb +360 -0
- data/lib/antlr3/debug/trace-event-listener.rb +92 -0
- data/lib/antlr3/dfa.rb +247 -0
- data/lib/antlr3/dot.rb +174 -0
- data/lib/antlr3/error.rb +657 -0
- data/lib/antlr3/main.rb +561 -0
- data/lib/antlr3/modes/ast-builder.rb +41 -0
- data/lib/antlr3/modes/filter.rb +56 -0
- data/lib/antlr3/profile.rb +322 -0
- data/lib/antlr3/recognizers.rb +1280 -0
- data/lib/antlr3/streams.rb +985 -0
- data/lib/antlr3/streams/interactive.rb +91 -0
- data/lib/antlr3/streams/rewrite.rb +412 -0
- data/lib/antlr3/test/call-stack.rb +57 -0
- data/lib/antlr3/test/config.rb +23 -0
- data/lib/antlr3/test/core-extensions.rb +269 -0
- data/lib/antlr3/test/diff.rb +165 -0
- data/lib/antlr3/test/functional.rb +207 -0
- data/lib/antlr3/test/grammar.rb +371 -0
- data/lib/antlr3/token.rb +592 -0
- data/lib/antlr3/tree.rb +1415 -0
- data/lib/antlr3/tree/debug.rb +163 -0
- data/lib/antlr3/tree/visitor.rb +84 -0
- data/lib/antlr3/tree/wizard.rb +481 -0
- data/lib/antlr3/util.rb +149 -0
- data/lib/antlr3/version.rb +27 -0
- data/samples/ANTLRv3Grammar.g +621 -0
- data/samples/Cpp.g +749 -0
- data/templates/AST.stg +335 -0
- data/templates/ASTDbg.stg +40 -0
- data/templates/ASTParser.stg +153 -0
- data/templates/ASTTreeParser.stg +272 -0
- data/templates/Dbg.stg +192 -0
- data/templates/Ruby.stg +1514 -0
- data/test/functional/ast-output/auto-ast.rb +797 -0
- data/test/functional/ast-output/construction.rb +555 -0
- data/test/functional/ast-output/hetero-nodes.rb +753 -0
- data/test/functional/ast-output/rewrites.rb +1327 -0
- data/test/functional/ast-output/tree-rewrite.rb +1662 -0
- data/test/functional/debugging/debug-mode.rb +689 -0
- data/test/functional/debugging/profile-mode.rb +165 -0
- data/test/functional/debugging/rule-tracing.rb +74 -0
- data/test/functional/delegation/import.rb +379 -0
- data/test/functional/lexer/basic.rb +559 -0
- data/test/functional/lexer/filter-mode.rb +245 -0
- data/test/functional/lexer/nuances.rb +47 -0
- data/test/functional/lexer/properties.rb +104 -0
- data/test/functional/lexer/syn-pred.rb +32 -0
- data/test/functional/lexer/xml.rb +206 -0
- data/test/functional/main/main-scripts.rb +245 -0
- data/test/functional/parser/actions.rb +224 -0
- data/test/functional/parser/backtracking.rb +244 -0
- data/test/functional/parser/basic.rb +282 -0
- data/test/functional/parser/calc.rb +98 -0
- data/test/functional/parser/ll-star.rb +143 -0
- data/test/functional/parser/nuances.rb +165 -0
- data/test/functional/parser/predicates.rb +103 -0
- data/test/functional/parser/properties.rb +242 -0
- data/test/functional/parser/rule-methods.rb +132 -0
- data/test/functional/parser/scopes.rb +274 -0
- data/test/functional/token-rewrite/basic.rb +318 -0
- data/test/functional/token-rewrite/via-parser.rb +100 -0
- data/test/functional/tree-parser/basic.rb +750 -0
- data/test/unit/sample-input/file-stream-1 +2 -0
- data/test/unit/sample-input/teststreams.input2 +2 -0
- data/test/unit/test-dfa.rb +52 -0
- data/test/unit/test-exceptions.rb +44 -0
- data/test/unit/test-recognizers.rb +55 -0
- data/test/unit/test-scheme.rb +62 -0
- data/test/unit/test-streams.rb +459 -0
- data/test/unit/test-tree-wizard.rb +535 -0
- data/test/unit/test-trees.rb +854 -0
- metadata +205 -0
data/lib/antlr3/util.rb
ADDED
@@ -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
|
+
|