001: /*
002: [The "BSD licence"]
003: Copyright (c) 2005 Martin Traverso
004: All rights reserved.
005:
006: Redistribution and use in source and binary forms, with or without
007: modification, are permitted provided that the following conditions
008: are met:
009: 1. Redistributions of source code must retain the above copyright
010: notice, this list of conditions and the following disclaimer.
011: 2. Redistributions in binary form must reproduce the above copyright
012: notice, this list of conditions and the following disclaimer in the
013: documentation and/or other materials provided with the distribution.
014: 3. The name of the author may not be used to endorse or promote products
015: derived from this software without specific prior written permission.
016:
017: THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
018: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
019: OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
020: IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
021: INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
022: NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
023: DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
024: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
025: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
026: THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
027: */
028:
029: /*
030:
031: Please excuse my obvious lack of Java experience. The code here is probably
032: full of WTFs - though IMHO Java is the Real WTF(TM) here...
033:
034: */
035:
036: package org.antlr.codegen;
037:
038: import java.util.*;
039:
040: public class PythonTarget extends Target {
041: /** Target must be able to override the labels used for token types */
042: public String getTokenTypeAsTargetLabel(CodeGenerator generator,
043: int ttype) {
044: // use ints for predefined types;
045: // <invalid> <EOR> <DOWN> <UP>
046: if (ttype >= 0 && ttype <= 3) {
047: return String.valueOf(ttype);
048: }
049:
050: String name = generator.grammar.getTokenDisplayName(ttype);
051:
052: // If name is a literal, return the token type instead
053: if (name.charAt(0) == '\'') {
054: return String.valueOf(ttype);
055: }
056:
057: return name;
058: }
059:
060: public String getTargetCharLiteralFromANTLRCharLiteral(
061: CodeGenerator generator, String literal) {
062: return "u" + literal;
063: }
064:
065: private List splitLines(String text) {
066: ArrayList l = new ArrayList();
067: int idx = 0;
068:
069: while (true) {
070: int eol = text.indexOf("\n", idx);
071: if (eol == -1) {
072: l.add(text.substring(idx));
073: break;
074: } else {
075: l.add(text.substring(idx, eol + 1));
076: idx = eol + 1;
077: }
078: }
079:
080: return l;
081: }
082:
083: public List postProcessAction(List chunks, antlr.Token actionToken) {
084: /* TODO
085: - check for and report TAB usage
086: */
087:
088: //System.out.println("\n*** Action at " + actionToken.getLine() + ":" + actionToken.getColumn());
089: /* First I create a new list of chunks. String chunks are splitted into
090: lines and some whitespace my be added at the beginning.
091:
092: As a result I get a list of chunks
093: - where the first line starts at column 0
094: - where every LF is at the end of a string chunk
095: */
096:
097: List nChunks = new ArrayList();
098: for (int i = 0; i < chunks.size(); i++) {
099: Object chunk = chunks.get(i);
100:
101: if (chunk instanceof String) {
102: String text = (String) chunks.get(i);
103: if (nChunks.size() == 0 && actionToken.getColumn() > 0) {
104: // first chunk and some 'virtual' WS at beginning
105: // prepend to this chunk
106:
107: String ws = "";
108: for (int j = 0; j < actionToken.getColumn(); j++) {
109: ws += " ";
110: }
111: text = ws + text;
112: }
113:
114: List parts = splitLines(text);
115: for (int j = 0; j < parts.size(); j++) {
116: chunk = parts.get(j);
117: nChunks.add(chunk);
118: }
119: } else {
120: if (nChunks.size() == 0 && actionToken.getColumn() > 0) {
121: // first chunk and some 'virtual' WS at beginning
122: // add as a chunk of its own
123:
124: String ws = "";
125: for (int j = 0; j < actionToken.getColumn(); j++) {
126: ws += " ";
127: }
128: nChunks.add(ws);
129: }
130:
131: nChunks.add(chunk);
132: }
133: }
134:
135: int lineNo = actionToken.getLine();
136: int col = 0;
137:
138: // strip trailing empty lines
139: int lastChunk = nChunks.size() - 1;
140: while (lastChunk > 0
141: && nChunks.get(lastChunk) instanceof String
142: && ((String) nChunks.get(lastChunk)).trim().length() == 0)
143: lastChunk--;
144:
145: // string leading empty lines
146: int firstChunk = 0;
147: while (firstChunk <= lastChunk
148: && nChunks.get(firstChunk) instanceof String
149: && ((String) nChunks.get(firstChunk)).trim().length() == 0
150: && ((String) nChunks.get(firstChunk)).endsWith("\n")) {
151: lineNo++;
152: firstChunk++;
153: }
154:
155: int indent = -1;
156: for (int i = firstChunk; i <= lastChunk; i++) {
157: Object chunk = nChunks.get(i);
158:
159: //System.out.println(lineNo + ":" + col + " " + quote(chunk.toString()));
160:
161: if (chunk instanceof String) {
162: String text = (String) chunk;
163:
164: if (col == 0) {
165: if (indent == -1) {
166: // first non-blank line
167: // count number of leading whitespaces
168:
169: indent = 0;
170: for (int j = 0; j < text.length(); j++) {
171: if (!Character.isWhitespace(text.charAt(j)))
172: break;
173:
174: indent++;
175: }
176: }
177:
178: if (text.length() >= indent) {
179: int j;
180: for (j = 0; j < indent; j++) {
181: if (!Character.isWhitespace(text.charAt(j))) {
182: // should do real error reporting here...
183: System.err
184: .println("Warning: badly indented line "
185: + lineNo
186: + " in action:");
187: System.err.println(text);
188: break;
189: }
190: }
191:
192: nChunks.set(i, text.substring(j));
193: } else if (text.trim().length() > 0) {
194: // should do real error reporting here...
195: System.err
196: .println("Warning: badly indented line "
197: + lineNo + " in action:");
198: System.err.println(text);
199: }
200: }
201:
202: if (text.endsWith("\n")) {
203: lineNo++;
204: col = 0;
205: } else {
206: col += text.length();
207: }
208: } else {
209: // not really correct, but all I need is col to increment...
210: col += 1;
211: }
212: }
213:
214: return nChunks;
215: }
216: }
|