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.
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,26 @@
1
+ [The "BSD licence"]
2
+ Copyright (c) 2003-2008 Terence Parr
3
+ All rights reserved.
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions
7
+ are met:
8
+
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.
@@ -0,0 +1,66 @@
1
+ h1(update). V1.1.1 2009-10-24 Kyle Yetter <kcy5b@yahoo.com>
2
+
3
+ h2(minor). minor alteration to TokenScheme
4
+
5
+ * TokenScheme#register_name would raise an error if the token type was anonymous (i.e. T__19 or such) and the new name didn't have the format "'a string'". That works well for ANTLR tokens, but it's generally pointless, so I got rid of those restrictions.
6
+
7
+ |\2. MODIFIED |
8
+ | lib/antlr3/token.rb | made minor changes to ANTLR3::TokenScheme#register_name |
9
+
10
+ h1(update). V1.1.0 2009-10-19 Kyle Yetter <kcy5b@yahoo.com>
11
+
12
+ h2(major). moved FilterMode
13
+
14
+ * since <tt>ANTLR3::Lexer::FilterMode</tt> is only necessary in lexers that specify filter=true, I moved it out of antlr3/recognizers.rb to its own file, antlr3/modes/filter.rb.
15
+
16
+ * the FilterMode module is no longer in the Lexer namespace, but in the broader ANTLR3 namespace ... i.e. module ANTLR3::Lexer::FilterMode ==> module ANTLR3::FilterMode
17
+
18
+ * I added an autoload entry to the ANTLR3 module in antlr3.rb for FilterMode, thus the module is autoloaded as needed whenever the constant ANTLR3::FilterMode is referenced
19
+
20
+ |\2. MODIFIED |
21
+ | lib/antlr3/recognizers.rb | removed Lexer::FilterMode definition |
22
+ | lib/antlr3.rb | added autoload :FilterMode entry |
23
+ |\2. CREATED |
24
+ | lib/antlr3/modes/filter.rb | contains FilterMode module extracted from recognizers.rb |
25
+
26
+ h2(major). new module ASTBuilder
27
+
28
+ * created a new module, ANTLR3::ASTBuilder
29
+ * all tree-building recognizers (parsers and tree parsers with the output=AST option) include this module
30
+ * provides a way to test a recognizer to see if it is an AST-building recognizer (rec.is_a?(ANTLR3::ASTBuilder)) and it also added a number of methods to help clean up generated AST-parser code
31
+
32
+ |\2. MODIFIED |
33
+ | lib/antlr3.rb | added the usual autoload entry for ASTBuilder |
34
+ | templates/AST.stg | added ``include ANTLR3::ASTBuilder'' to automatically include the module on all AST-output recognizers |
35
+ |\2. CREATED |
36
+ | lib/antlr3/modes/ast-builder.rb | defined new module ANTLR3::ASTBuilder |
37
+
38
+ h2(major). refactored debug and profile modes
39
+
40
+ * began process of organizing/cleaning-up the ANTLR3::Debug module (in file lib/antlr3/debug.rb), which contains all runtime support code and features for --debug and --profile option code output.
41
+ * extracted profiling-oriented classes and modules from the Debug module and moved them to a new file, lib/antlr3/profile.rb.
42
+ * since usually you're only using one particular type of Debug::EventListener at a time, I moved the six or so different EventListener classes out of Debug and into their own respective files in the antlr3/debug directory
43
+ * since tree-oriented debugging hooks (Debug::TreeAdaptor and such) are only necessary for tree-oriented code, and thus are not part of the essential core, I moved the tree-related event modules out of Debug and into a separate file, lib/antlr3/tree/debug.rb
44
+ * debug.rb now only defines the core EventListener interface module and the event-hook modules ParserEvents, TokenStream, and the expanded RecognizerSharedState class
45
+ * as with most classes that aren't loaded by default in the runtime library, I strategically placed autoload statements in appropriate modules to autoload any of the Debug modules and classes I yanked out of the debug.rb, so there shouldn't be any need for extra 'require' statements to use the classes
46
+
47
+ |\2. MODIFIED |
48
+ | lib/antlr3/debug.rb | removed definitions: EventSocketProxy, RemoteEventSocketListener, TraceEventListener, RuleTracer, EventHub, TreeNodeStream, TreeAdaptor, ParserProfilingEvents, Profiler, Profiler::Profile, Profiler::DataSet |
49
+ |\2. CREATED |
50
+ | lib/antlr3/debug/event-hub.rb | new home for Debug::EventHub |
51
+ | lib/antlr3/debug/record-event-listener.rb | new home for Debug::RecordEventListener |
52
+ | lib/antlr3/debug/rule-tracer.rb | new home for Debug::RuleTracer |
53
+ | lib/antlr3/debug/socket.rb | new home for Debug::EventSocketProxy and Debug::RemoteEventSocketListener |
54
+ | lib/antlr3/debug/trace-event-listener.rb | new home for Debug::TraceEventListener |
55
+ | lib/antlr3/profile.rb | new profile-oriented module, Profile, contains former debug classes Profile, ProfileEvents, and Profiler |
56
+ | lib/antlr3/tree/debug.rb | new home for Debug::TreeAdaptor and Debug::TreeNodeStream |
57
+
58
+ h2(minor). moved most of the core-extension code to new Util module
59
+
60
+ * as handy as it is to add new functions to core classes, I moved most of the code in the core-extension directory to the new slightly-nebulous, catch-all dumping ground modules, ANTLR3::Util and ANTLR3::ClassMacros. String and Module methods defined in the extensions were only used in a small handful of places and thus it seemed intrusive to polute the core classes with these utility methods for little payoff.
61
+ * ANTLR classes now extend ANTLR3::ClassMacros when necessary. It defines 'abstract' to easily create abstract methods. It also provides a new method, #shared_attribute, which defines an attribute accessor with a writer
62
+
63
+ h1(update). V1.0.0 2009-10-14 Kyle Yetter <kcy5b@yahoo.com>
64
+
65
+ h2(major). Initial Release: Birthday!
66
+
@@ -0,0 +1,139 @@
1
+ ANTLR 3 for Ruby
2
+ by Kyle Yetter (kcy5b@yahoo.com)
3
+ http://antlr3.rubyforge.org
4
+
5
+ == DESCRIPTION:
6
+
7
+ Fully-featured ANTLR 3 parser generation for Ruby.
8
+
9
+ ANTLR (ANother Tool for Language Recognition) is a tool that is used to generate
10
+ code for performing a variety of language recognition tasks: lexing, parsing,
11
+ abstract syntax tree construction and manipulation, tree structure recognition,
12
+ and input translation. The tool operates simillarly to other parser generators,
13
+ taking in a grammar specification written in the special ANTLR metalanguage and
14
+ producing source code that implements the recognition functionality.
15
+
16
+ While the tool itself is implemented in Java, it has an extensible design that
17
+ allows for code generation in other programming languages. To implement an
18
+ ANTLR language target, a developer may supply a set of templates written in the
19
+ StringTemplate (http://www.stringtemplate.org) language.
20
+
21
+ ANTLR is currently distributed with a fairly limited Ruby target implementation.
22
+ While it does provide implementation for basic lexer and parser classes, the
23
+ target does not provide any implementation for abstract syntax tree
24
+ construction, tree parser class generation, input translation, or a number of
25
+ the other ANTLR features that give the program an edge over traditional code
26
+ generators.
27
+
28
+ This gem packages together a complete implementation of the majority of features
29
+ ANTLR provides for other language targets, such as Java and Python. It contains:
30
+
31
+ * A customized version of the latest ANTLR program, bundling all necessary
32
+ java code and templates for producing fully featured language recognition
33
+ in ruby code
34
+
35
+ * a ruby runtime library that collects classes used throughout the code that
36
+ ANTLR generates
37
+
38
+ * a wrapper script, `antlr4ruby', which executes the ANTLR command line tool
39
+ after ensuring the ANTLR jar is java's class path
40
+
41
+ == FEATURES
42
+
43
+ 1. generates ruby code capable of:
44
+ * lexing text input
45
+ * parsing lexical output and responding with arbitrary actions
46
+ * constructing Abstract Syntax Trees (ASTs)
47
+ * parsing AST structure and responding with arbitrary actions
48
+ * translating input source to some desired output format
49
+
50
+ 2. This package can serve as a powerful assistant when performing tasks
51
+ such as:
52
+ * code compilation
53
+ * source code highlighting and formatting
54
+ * domain-specific language implementation
55
+ * source code extraction and analysis
56
+
57
+ == USAGE
58
+
59
+ 1. Write an ANTLR grammar specification for a language
60
+
61
+ grammar SomeLanguage;
62
+
63
+ options {
64
+ language = Ruby; // <- this option must be set to Ruby
65
+ output = AST;
66
+ }
67
+
68
+ top: expr ( ',' expr )*
69
+ ;
70
+
71
+ and so on...
72
+
73
+
74
+ 2. Run the ANTLR tool with the antlr4ruby command to generate output:
75
+
76
+ antlr4ruby SomeLanguage.g
77
+ # creates:
78
+ # SomeLanguageParser.rb
79
+ # SomeLanguageLexer.rb
80
+ # SomeLanguage.g
81
+
82
+ 3. Try out the results directly, if you like:
83
+
84
+ # see how the lexer tokenizes some input
85
+ ruby SomeLanguageLexer.rb < path/to/source-code.xyz
86
+
87
+ # check whether the parser successfully matches some input
88
+ ruby SomeLanguageParser.rb --rule=top < path/to/source-code.xyz
89
+
90
+ -> Read up on the package documentation for more specific details
91
+ about loading the recognizers and using their class definitions
92
+
93
+ == ISSUES
94
+
95
+ * Currently, there are a few nuanced ways in which using the ruby output differs
96
+ from the conventions and examples covered in the ANTLR standard documentation.
97
+ I am still working on documenting these details.
98
+
99
+ * While the target is intended to be complete, I do not provide any
100
+ implementation of the template-construction mode available for Java and Python
101
+ targets. While I'm interested in having this capability, I have not implemented
102
+ it yet because ANTLR forces you to use its StringTemplate templating language.
103
+ Thus, I would have to port the StringTemplate library to Ruby and write a target
104
+ for ST parser generation. I would prefer to permit template generation that uses
105
+ ruby's standard ERB templating library.
106
+
107
+ * So far, this has only been tested on Linux with ruby 1.8.7 and ruby 1.9.1.
108
+ I'm currently working on verifying behavior on other systems and with
109
+ slightly older versions of ruby.
110
+
111
+ == LICENSE
112
+
113
+ [The "BSD licence"]
114
+ Copyright (c) 2009 Kyle Yetter
115
+ All rights reserved.
116
+
117
+ Redistribution and use in source and binary forms, with or without
118
+ modification, are permitted provided that the following conditions
119
+ are met:
120
+
121
+ 1. Redistributions of source code must retain the above copyright
122
+ notice, this list of conditions and the following disclaimer.
123
+ 2. Redistributions in binary form must reproduce the above copyright
124
+ notice, this list of conditions and the following disclaimer in the
125
+ documentation and/or other materials provided with the distribution.
126
+ 3. The name of the author may not be used to endorse or promote products
127
+ derived from this software without specific prior written permission.
128
+
129
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
130
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
131
+ OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
132
+ IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
133
+ INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
134
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
135
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
136
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
137
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
138
+ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
139
+
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/ruby
2
+ # encoding: utf-8
3
+
4
+ __DIR__ = File.expand_path( File.dirname __FILE__ )
5
+ project_top = File.dirname __DIR__
6
+ load( File.join( project_top, 'lib', 'antlr3', 'version.rb' ) )
7
+
8
+ jar_name = "antlr-full-#{ ANTLR_VERSION_STRING }.jar"
9
+ jar_path = File.join( project_top, 'java', jar_name )
10
+
11
+ unless File.exist?( jar_path )
12
+ $stderr.puts(<<-END.strip!.gsub!(/\s+/, ' '))
13
+ the ANTLR #{ ANTLR_VERSION_STRING } jar is expected
14
+ to be located at #{ jar_path }, but it does not
15
+ appear to exist.
16
+ END
17
+ exit( 1 )
18
+ end
19
+
20
+ escape = proc do | a |
21
+ if a.empty? then "''"
22
+ else
23
+ a.gsub( /([^A-Za-z0-9_\-.,:\/@\n])/n, '\\\1' ).
24
+ gsub( /\n/, "'\n'" )
25
+ end
26
+ end
27
+
28
+ command = %w(java -jar) << escape[ antlr_jar ]
29
+ for arg in ARGV
30
+ command << escape[ arg ]
31
+ end
32
+
33
+ exec command.join(' ')
@@ -0,0 +1,524 @@
1
+ /*
2
+ [The "BSD licence"]
3
+ Copyright (c) 2005 Martin Traverso
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
+ package org.antlr.codegen;
30
+
31
+ import java.io.IOException;
32
+ import java.util.*;
33
+
34
+ import org.antlr.Tool;
35
+ import org.antlr.stringtemplate.*;
36
+ import org.antlr.tool.Grammar;
37
+
38
+ public class RubyTarget
39
+ extends Target
40
+ {
41
+ public static final Set rubyKeywords =
42
+ new HashSet() {
43
+ {
44
+ add("alias"); add("end"); add("retry");
45
+ add("and"); add("ensure"); add("return");
46
+ add("BEGIN"); add("false"); add("self");
47
+ add("begin"); add("for"); add("super");
48
+ add("break"); add("if"); add("then");
49
+ add("case"); add("in"); add("true");
50
+ add("class"); add("module"); add("undef");
51
+ add("def"); add("next"); add("unless");
52
+ add("defined"); add("nil"); add("until");
53
+ add("do"); add("not"); add("when");
54
+ add("else"); add("or"); add("while");
55
+ add("elsif"); add("redo"); add("yield");
56
+ add("END"); add("rescue");
57
+ }
58
+ };
59
+
60
+ public class RubyRenderer
61
+ implements AttributeRenderer
62
+ {
63
+ public String toString(Object o) {
64
+ return o.toString();
65
+ }
66
+ public String toString(Object o, String formatName) {
67
+ String idString = o.toString();
68
+
69
+ if (idString.isEmpty()) return idString;
70
+
71
+ if (formatName.equals("snakecase")) {
72
+ return snakecase(idString);
73
+ } else if (formatName.equals("camelcase")) {
74
+ return camelcase(idString);
75
+ } else if (formatName.equals("subcamelcase")) {
76
+ return subcamelcase(idString);
77
+ } else if (formatName.equals("constant")) {
78
+ return constantcase(idString);
79
+ } else if (formatName.equals("platform")) {
80
+ return platform(idString);
81
+ } else if (formatName.equals("lexerRule")) {
82
+ return lexerRule(idString);
83
+ } else if (formatName.equals("constantPath")) {
84
+ return constantPath(idString);
85
+ } else if (formatName.equals("label")) {
86
+ return label(idString);
87
+ } else if (formatName.equals("symbol")) {
88
+ return symbol(idString);
89
+ } else {
90
+ throw new IllegalArgumentException("Unsupported format name");
91
+ }
92
+ }
93
+ /** given an input string, which is presumed
94
+ * to contain a word, which may potentially be camelcased,
95
+ * and convert it to snake_case underscore style.
96
+ *
97
+ * algorithm --
98
+ * iterate through the string with a sliding window 3 chars wide
99
+ *
100
+ * example -- aGUIWhatNot
101
+ * c c+1 c+2 action
102
+ * a G << 'a' << '_' // a lower-upper word edge
103
+ * G U I << 'g'
104
+ * U I W << 'w'
105
+ * I W h << 'i' << '_' // the last character in an acronym run of uppers
106
+ * W h << 'w'
107
+ * ... and so on
108
+ */
109
+ private String snakecase(String value) {
110
+ StringBuilder output_buffer = new StringBuilder();
111
+ int l = value.length();
112
+ int cliff = l - 1;
113
+ char cur;
114
+ char next;
115
+ char peek;
116
+
117
+ if (value.isEmpty()) return value;
118
+ if (l == 1) return value.toLowerCase();
119
+
120
+ for (int i = 0; i < cliff; i++) {
121
+ cur = value.charAt(i);
122
+ next = value.charAt(i + 1);
123
+
124
+ if ( Character.isLetter( cur ) ) {
125
+ output_buffer.append( Character.toLowerCase( cur ) );
126
+
127
+ if ( Character.isDigit( next ) || Character.isWhitespace( next ) ) {
128
+ output_buffer.append( '_' );
129
+ } else if ( Character.isLowerCase( cur ) && Character.isUpperCase( next ) ) {
130
+ // at camelcase word edge
131
+ output_buffer.append( '_' );
132
+ } else if ( (i < cliff - 1) && Character.isUpperCase( cur ) && Character.isUpperCase( next ) ) {
133
+ // cur is part of an acronym
134
+
135
+ peek = value.charAt(i + 2);
136
+ if ( Character.isLowerCase( peek ) ) {
137
+ /* if next is the start of word (indicated when peek is lowercase)
138
+ then the acronym must be completed by appending an underscore */
139
+ output_buffer.append('_');
140
+ }
141
+ }
142
+ } else if( Character.isDigit( cur ) ) {
143
+ output_buffer.append( cur );
144
+ if ( Character.isLetter( next ) ) {
145
+ output_buffer.append('_');
146
+ }
147
+ } else if (Character.isWhitespace( cur )) {
148
+ // do nothing
149
+ } else {
150
+ output_buffer.append( cur );
151
+ }
152
+
153
+ }
154
+
155
+ cur = value.charAt(cliff);
156
+ if (! Character.isWhitespace(cur) ) {
157
+ output_buffer.append( Character.toLowerCase( cur ) );
158
+ }
159
+
160
+ return output_buffer.toString();
161
+ }
162
+ private String constantcase(String value) {
163
+ return snakecase(value).toUpperCase();
164
+ }
165
+ private String platform(String value) {
166
+ return ("__" + value + "__");
167
+ }
168
+ private String symbol(String value) {
169
+ if (value.matches("[a-zA-Z_]\\w*[\\?\\!\\=]?")) {
170
+ return (":" + value);
171
+ } else {
172
+ return ("%s(" + value + ")");
173
+ }
174
+ }
175
+ private String lexerRule(String value) {
176
+ if (value.equals("Tokens")) {
177
+ return "token!";
178
+ } else {
179
+ return (snakecase(value) + "!");
180
+ }
181
+ }
182
+ private String constantPath(String value) {
183
+ return value.replaceAll("\\.", "::");
184
+ }
185
+ private String camelcase(String value) {
186
+ StringBuilder output_buffer = new StringBuilder();
187
+ int cliff = value.length();
188
+ char cur;
189
+ char next;
190
+ boolean at_edge = true;
191
+
192
+ if (value.isEmpty()) return value;
193
+ if (cliff == 1) return value.toUpperCase();
194
+
195
+ for (int i = 0; i < cliff; i++) {
196
+ cur = value.charAt(i);
197
+
198
+ if ( Character.isWhitespace( cur ) ) {
199
+ at_edge = true;
200
+ continue;
201
+ } else if ( cur == '_' ) {
202
+ at_edge = true;
203
+ continue;
204
+ } else if ( Character.isDigit( cur ) ) {
205
+ output_buffer.append( cur );
206
+ at_edge = true;
207
+ continue;
208
+ }
209
+
210
+ if (at_edge) {
211
+ output_buffer.append( Character.toUpperCase( cur ) );
212
+ if ( Character.isLetter( cur ) ) at_edge = false;
213
+ } else {
214
+ output_buffer.append( cur );
215
+ }
216
+ }
217
+
218
+ return output_buffer.toString();
219
+ }
220
+ private String label(String value) {
221
+ if (rubyKeywords.contains(value)) {
222
+ return platform(value);
223
+ } else if (Character.isUpperCase(value.charAt(0)) &&
224
+ (!value.equals("FILE")) &&
225
+ (!value.equals("LINE"))) {
226
+ return platform(value);
227
+ } else if (value.equals("FILE")) {
228
+ return "_FILE_";
229
+ } else if (value.equals("LINE")) {
230
+ return "_LINE_";
231
+ } else {
232
+ return value;
233
+ }
234
+ }
235
+ private String subcamelcase(String value) {
236
+ value = camelcase(value);
237
+ if (value.isEmpty())
238
+ return value;
239
+ Character head = Character.toLowerCase( value.charAt(0) );
240
+ String tail = value.substring(1);
241
+ return head.toString().concat(tail);
242
+ }
243
+ }
244
+
245
+ protected void genRecognizerFile(Tool tool,
246
+ CodeGenerator generator,
247
+ Grammar grammar,
248
+ StringTemplate outputFileST)
249
+ throws IOException
250
+ {
251
+ StringTemplateGroup group = generator.getTemplates();
252
+ RubyRenderer renderer = new RubyRenderer();
253
+ try {
254
+ group.registerRenderer(Class.forName("java.lang.String"), renderer);
255
+ } catch (ClassNotFoundException e) {
256
+ // this shouldn't happen
257
+ System.err.println("ClassNotFoundException: " + e.getMessage());
258
+ e.printStackTrace(System.err);
259
+ }
260
+ String fileName =
261
+ generator.getRecognizerFileName(grammar.name, grammar.type);
262
+ generator.write(outputFileST, fileName);
263
+ }
264
+ public String getTargetCharLiteralFromANTLRCharLiteral(
265
+ CodeGenerator generator,
266
+ String literal)
267
+ {
268
+ literal = literal.substring(1, literal.length() - 1);
269
+
270
+ String result = "?";
271
+
272
+ if (literal.equals("\\")) {
273
+ result += "\\\\";
274
+ }
275
+ else if (literal.equals(" ")) {
276
+ result += "\\s";
277
+ }
278
+ else if (literal.startsWith("\\u")) {
279
+ result = "0x" + literal.substring(2);
280
+ }
281
+ else {
282
+ result += literal;
283
+ }
284
+
285
+ return result;
286
+ }
287
+ public int getMaxCharValue(CodeGenerator generator)
288
+ {
289
+ // we don't support unicode, yet.
290
+ return 0xFF;
291
+ }
292
+ public String getTokenTypeAsTargetLabel(CodeGenerator generator, int ttype)
293
+ {
294
+ String name = generator.grammar.getTokenDisplayName(ttype);
295
+ // If name is a literal, return the token type instead
296
+ if ( name.charAt(0)=='\'' ) {
297
+ return generator.grammar.computeTokenNameFromLiteral(ttype, name);
298
+ }
299
+ return name;
300
+ }
301
+ /** Is scope in @scope::name {action} valid for this kind of grammar?
302
+ * Targets like C++ may want to allow new scopes like headerfile or
303
+ * some such. The action names themselves are not policed at the
304
+ * moment so targets can add template actions w/o having to recompile
305
+ * ANTLR.
306
+ */
307
+ public boolean isValidActionScope(int grammarType, String scope) {
308
+ switch (grammarType) {
309
+ case Grammar.LEXER:
310
+ if (scope.equals("lexer")) {
311
+ return true;
312
+ }
313
+ if (scope.equals("token")) {
314
+ return true;
315
+ }
316
+ if (scope.equals("module")) {
317
+ return true;
318
+ }
319
+ if (scope.equals("overrides")) {
320
+ return true;
321
+ }
322
+ break;
323
+ case Grammar.PARSER:
324
+ if (scope.equals("parser")) {
325
+ return true;
326
+ }
327
+ if (scope.equals("token")) {
328
+ return true;
329
+ }
330
+ if (scope.equals("module")) {
331
+ return true;
332
+ }
333
+ if (scope.equals("overrides")) {
334
+ return true;
335
+ }
336
+ break;
337
+ case Grammar.COMBINED:
338
+ if (scope.equals("parser")) {
339
+ return true;
340
+ }
341
+ if (scope.equals("lexer")) {
342
+ return true;
343
+ }
344
+ if (scope.equals("token")) {
345
+ return true;
346
+ }
347
+ if (scope.equals("module")) {
348
+ return true;
349
+ }
350
+ if (scope.equals("overrides")) {
351
+ return true;
352
+ }
353
+ break;
354
+ case Grammar.TREE_PARSER:
355
+ if (scope.equals("treeparser")) {
356
+ return true;
357
+ }
358
+ if (scope.equals("token")) {
359
+ return true;
360
+ }
361
+ if (scope.equals("module")) {
362
+ return true;
363
+ }
364
+ if (scope.equals("overrides")) {
365
+ return true;
366
+ }
367
+ break;
368
+ }
369
+ return false;
370
+ }
371
+ /*
372
+ public String getTargetStringLiteralFromString(String s)
373
+ {
374
+ System.out.print(s + "\n");
375
+ return super.getTargetStringLiteralFromString(s);
376
+ }
377
+
378
+ public String getTargetStringLiteralFromString(String s, boolean quoted)
379
+ {
380
+ // System.out.print(s + "\n");
381
+ String ret_value = super.getTargetStringLiteralFromString(s, quoted);
382
+ System.out.print(ret_value + "\n");
383
+ return(ret_value);
384
+ }
385
+
386
+ public String getTarget64BitStringFromValue(long word)
387
+ {
388
+ System.out.print(((Long)word).toString() + "\n");
389
+ String result = super.getTarget64BitStringFromValue(word);
390
+ System.out.print(result + "\n");
391
+ return result;
392
+ }
393
+ */
394
+ public String encodeIntAsCharEscape(final int v) {
395
+ final int intValue;
396
+
397
+ if (v == 65535) {
398
+ intValue = -1;
399
+ } else {
400
+ intValue = v;
401
+ }
402
+
403
+ return String.valueOf(intValue);
404
+ }
405
+ // public List postProcessAction(List chunks, antlr.Token actionToken) {
406
+ // List nChunks = new ArrayList();
407
+ //
408
+ // for (int i = 0; i < chunks.size(); i++) {
409
+ // Object chunk = chunks.get(i);
410
+ //
411
+ // if ( chunk instanceof String ) {
412
+ // String text = (String)chunks.get(i);
413
+ // if ( nChunks.size() == 0 && actionToken.getColumn() > 0 ) {
414
+ // // first chunk and some 'virtual' WS at beginning
415
+ // // prepend to this chunk
416
+ //
417
+ // String ws = "";
418
+ // for ( int j = 0 ; j < actionToken.getColumn() ; j++ ) {
419
+ // ws += " ";
420
+ // }
421
+ // text = ws + text;
422
+ // }
423
+ //
424
+ // String[] parts = text.split("\r?\n");
425
+ // for ( String line : parts ) {
426
+ // nChunks.add(line);
427
+ // }
428
+ // }
429
+ // else {
430
+ // if ( nChunks.size() == 0 && actionToken.getColumn() > 0 ) {
431
+ // // first chunk and some 'virtual' WS at beginning
432
+ // // add as a chunk of its own
433
+ //
434
+ // String ws = "";
435
+ // for ( int j = 0 ; j < actionToken.getColumn() ; j++ ) {
436
+ // ws += " ";
437
+ // }
438
+ // nChunks.add(ws);
439
+ // }
440
+ //
441
+ // nChunks.add(chunk);
442
+ // }
443
+ // }
444
+ //
445
+ // int lineNo = actionToken.getLine();
446
+ // int col = 0;
447
+ //
448
+ // // strip trailing empty lines
449
+ // int lastChunk = nChunks.size() - 1;
450
+ // while ( lastChunk > 0
451
+ // && nChunks.get(lastChunk) instanceof String
452
+ // && ((String)nChunks.get(lastChunk)).trim().length() == 0 )
453
+ // lastChunk--;
454
+ //
455
+ // // string leading empty lines
456
+ // int firstChunk = 0;
457
+ // while ( firstChunk <= lastChunk
458
+ // && nChunks.get(firstChunk) instanceof String
459
+ // && ((String)nChunks.get(firstChunk)).trim().length() == 0
460
+ // && ((String)nChunks.get(firstChunk)).endsWith("\n") ) {
461
+ // lineNo++;
462
+ // firstChunk++;
463
+ // }
464
+ //
465
+ // int indent = -1;
466
+ // for ( int i = firstChunk ; i <= lastChunk ; i++ ) {
467
+ // Object chunk = nChunks.get(i);
468
+ //
469
+ // //System.out.println(lineNo + ":" + col + " " + quote(chunk.toString()));
470
+ //
471
+ // if ( chunk instanceof String ) {
472
+ // String text = (String)chunk;
473
+ //
474
+ // if ( col == 0 ) {
475
+ // if ( indent == -1 ) {
476
+ // // first non-blank line
477
+ // // count number of leading whitespaces
478
+ //
479
+ // indent = 0;
480
+ // for ( int j = 0; j < text.length(); j++ ) {
481
+ // if ( !Character.isWhitespace(text.charAt(j)) )
482
+ // break;
483
+ //
484
+ // indent++;
485
+ // }
486
+ // }
487
+ //
488
+ // if ( text.length() >= indent ) {
489
+ // int j;
490
+ // for ( j = 0; j < indent ; j++ ) {
491
+ // if ( !Character.isWhitespace(text.charAt(j)) ) {
492
+ // // should do real error reporting here...
493
+ // System.err.println("Warning: badly indented line " + lineNo + " in action:");
494
+ // System.err.println(text);
495
+ // break;
496
+ // }
497
+ // }
498
+ //
499
+ // nChunks.set(i, text.substring(j));
500
+ // }
501
+ // else if ( text.trim().length() > 0 ) {
502
+ // // should do real error reporting here...
503
+ // System.err.println("Warning: badly indented line " + lineNo + " in action:");
504
+ // System.err.println(text);
505
+ // }
506
+ // }
507
+ //
508
+ // if ( text.endsWith("\n") ) {
509
+ // lineNo++;
510
+ // col = 0;
511
+ // }
512
+ // else {
513
+ // col += text.length();
514
+ // }
515
+ // }
516
+ // else {
517
+ // // not really correct, but all I need is col to increment...
518
+ // col += 1;
519
+ // }
520
+ // }
521
+ //
522
+ // return nChunks;
523
+ // }
524
+ }