001: // Copyright (c) Corporation for National Research Initiatives
002: package org.python.core;
003:
004: import org.python.parser.*;
005: import org.python.parser.ast.modType;
006: import java.io.*;
007:
008: /**
009: * Facade for the classes in the org.python.parser package.
010: */
011:
012: public class parser {
013:
014: private static IParserHost literalMkrForParser = new LiteralMakerForParser();
015:
016: private parser() {
017: ;
018: }
019:
020: static String getLine(BufferedReader reader, int line) {
021: if (reader == null)
022: return "";
023: try {
024: String text = null;
025: for (int i = 0; i < line; i++) {
026: text = reader.readLine();
027: }
028: return text;
029: } catch (IOException ioe) {
030: return null;
031: }
032: }
033:
034: // if reader != null, reset it
035: public static PyException fixParseError(BufferedReader reader,
036: Throwable t, String filename) {
037: if (reader != null) {
038: // System.err.println("resetting istream");
039: try {
040: reader.reset();
041: } catch (IOException e) {
042: reader = null;
043: }
044: }
045:
046: if (t instanceof ParseException) {
047: ParseException e = (ParseException) t;
048: Token tok = e.currentToken;
049: int col = 0;
050: int line = 0;
051: if (tok != null && tok.next != null) {
052: col = tok.next.beginColumn;
053: line = tok.next.beginLine;
054: }
055: String text = getLine(reader, line);
056: return new PySyntaxError(e.getMessage(), line, col, text,
057: filename);
058: }
059: if (t instanceof TokenMgrError) {
060: TokenMgrError e = (TokenMgrError) t;
061: boolean eofSeen = e.EOFSeen;
062:
063: int col = e.errorColumn;
064: int line = e.errorLine;
065: //System.err.println("eof seen: "+eofSeen+", "+e.curChar+", "+col+
066: // ", "+line);
067: String text = getLine(reader, line);
068: if (eofSeen)
069: col -= 1;
070: return new PySyntaxError(e.getMessage(), line, col, text,
071: filename);
072: } else
073: return Py.JavaError(t);
074: }
075:
076: public static Node parse(String string, String kind) {
077: return parse(new ByteArrayInputStream(string.getBytes()), kind,
078: "<string>", null);
079: }
080:
081: public static modType parse(InputStream istream, String kind,
082: String filename, CompilerFlags cflags) {
083: BufferedReader bufreader = prepBufreader(istream, cflags);
084:
085: PythonGrammar g = new PythonGrammar(new ReaderCharStream(
086: bufreader), literalMkrForParser);
087:
088: modType node = null;
089: try {
090: node = doparse(kind, cflags, g);
091: } catch (Throwable t) {
092: throw fixParseError(bufreader, t, filename);
093: }
094: return node;
095: }
096:
097: public static modType partialParse(String string, String kind,
098: String filename, CompilerFlags cflags, boolean stdprompt) {
099: modType node = null;
100: //System.err.println(new PyString(string).__repr__().toString());
101:
102: BufferedReader bufreader = prepBufreader(
103: new ByteArrayInputStream(string.getBytes()), cflags);
104:
105: PythonGrammar g = new PythonGrammar(new ReaderCharStream(
106: bufreader), literalMkrForParser);
107:
108: g.token_source.partial = true;
109: g.token_source.stdprompt = stdprompt;
110:
111: try {
112: node = doparse(kind, cflags, g);
113: } catch (Throwable t) {
114: /*
115: CPython codeop exploits that with CPython parser adding newlines
116: to a partial valid sentence move the reported error position,
117: this is not true for our parser, so we need a different approach:
118: we check whether all sentence tokens have been consumed or
119: the remaining ones fullfill lookahead expectations. See:
120: PythonGrammar.partial_valid_sentence (def in python.jjt)
121: */
122:
123: if (g.partial_valid_sentence(t)) {
124: return null;
125: }
126: throw fixParseError(bufreader, t, filename);
127: }
128: return node;
129:
130: // try {
131: // node = parse(new StringBufferInputStream(string),
132: // kind, filename, cflags, true);
133: // }
134: // catch (PySyntaxError e) {
135: // //System.out.println("e: "+e.lineno+", "+e.column+", "+
136: // // e.forceNewline);
137: // try {
138: // node = parse(new StringBufferInputStream(string+"\n"),
139: // kind, filename, cflags, true);
140: // }
141: // catch (PySyntaxError e1) {
142: // //System.out.println("e1: "+e1.lineno+", "+e1.column+
143: // // ", "+e1.forceNewline);
144: // if (e.forceNewline || !e1.forceNewline) throw e;
145: // }
146: // return null;
147: // }
148: // return node;
149: }
150:
151: private static modType doparse(String kind, CompilerFlags cflags,
152: PythonGrammar g) throws ParseException {
153: modType node = null;
154:
155: if (cflags != null)
156: g.token_source.generator_allowed = cflags.generator_allowed;
157:
158: if (kind.equals("eval")) {
159: node = g.eval_input();
160: } else if (kind.equals("exec")) {
161: node = g.file_input();
162: } else if (kind.equals("single")) {
163: node = g.single_input();
164: } else {
165: throw Py.ValueError("parse kind must be eval, exec, "
166: + "or single");
167: }
168: return node;
169: }
170:
171: private static BufferedReader prepBufreader(InputStream istream,
172: CompilerFlags cflags) {
173: int nbytes;
174: try {
175: nbytes = istream.available();
176: } catch (IOException ioe1) {
177: nbytes = 10000;
178: }
179: if (nbytes <= 0)
180: nbytes = 10000;
181: if (nbytes > 100000)
182: nbytes = 100000;
183:
184: Reader reader = null;
185: try {
186: if (cflags != null && cflags.encoding != null) {
187: reader = new InputStreamReader(istream, cflags.encoding);
188: }
189: } catch (UnsupportedEncodingException exc) {
190: ;
191: }
192: if (reader == null) {
193: reader = new InputStreamReader(istream);
194: }
195:
196: //if (Options.fixMacReaderBug);
197: reader = new FixMacReaderBug(reader);
198:
199: BufferedReader bufreader = new BufferedReader(reader);
200:
201: try {
202: bufreader.mark(nbytes);
203: } catch (IOException exc) {
204: }
205: return bufreader;
206: }
207:
208: }
209:
210: /**
211: * A workaround for a bug in MRJ2.2's FileReader, where the value returned
212: * from read(b, o, l) sometimes are wrong.
213: */
214: class FixMacReaderBug extends FilterReader {
215: public FixMacReaderBug(Reader in) {
216: super (in);
217: }
218:
219: public int read(char b[], int off, int len) throws IOException {
220: int l = super .read(b, off, len);
221: if (l < -1)
222: l += off;
223: return l;
224: }
225: }
226:
227: class LiteralMakerForParser implements IParserHost {
228:
229: public Object newLong(String s) {
230: return Py.newLong(s);
231: }
232:
233: public Object newLong(java.math.BigInteger i) {
234: return Py.newLong(i);
235: }
236:
237: public Object newFloat(double v) {
238: return Py.newFloat(v);
239: }
240:
241: public Object newImaginary(double v) {
242: return Py.newImaginary(v);
243: }
244:
245: public Object newInteger(int i) {
246: return Py.newInteger(i);
247: }
248:
249: public String decode_UnicodeEscape(String str, int start, int end,
250: String errors, boolean unicode) {
251: return PyString.decode_UnicodeEscape(str, start, end, errors,
252: unicode);
253: }
254:
255: }
|