001: package gnu.expr;
002:
003: import gnu.text.SourceMessages;
004:
005: /** A very abstract "parser".
006: * Converts some input representation to Expression trees. */
007:
008: public class Parser {
009: /** If doing immediate evaluation. */
010: public boolean immediate;
011:
012: public Parser(SourceMessages messages) {
013: this .messages = messages;
014: }
015:
016: /** This may not make sense, except for Lisp-like languages.
017: * For those, 'input' an s-expression from the reader. */
018: public Expression parse(Object input) {
019: throw new Error("unimeplemented parse");
020: }
021:
022: public Interpreter getInterpreter() {
023: return Interpreter.getInterpreter();
024: }
025:
026: public LambdaExp currentLambda() {
027: return current_scope.currentLambda();
028: }
029:
030: public ModuleExp currentModule() {
031: return current_scope.currentModule();
032: }
033:
034: /** Note that we have seen a construct that must be compiled, not evaluated.
035: * If we are not inside a lambda (which is always compiled), but
036: * only inside the outer-most ModuleExp, note that it must be compiled.
037: */
038: public void mustCompileHere() {
039: ScopeExp exp = current_scope;
040: for (;; exp = exp.outer) {
041: if (exp == null)
042: return;
043: if (exp instanceof ModuleExp) {
044: ((ModuleExp) exp).mustCompile = true;
045: return;
046: }
047: }
048: }
049:
050: public ScopeExp currentScope() {
051: return current_scope;
052: }
053:
054: //public abstract boolean popBinding();
055:
056: //public abstract void pushBinding(String name, Object value);
057:
058: public void push(ScopeExp scope) {
059: scope.outer = current_scope;
060: if (!(scope instanceof ModuleExp))
061: mustCompileHere();
062: current_scope = scope;
063: }
064:
065: public void pop(ScopeExp scope) {
066: current_scope = scope.outer;
067: }
068:
069: public final void pop() {
070: pop(current_scope);
071: }
072:
073: public Declaration lookup(String name, int namespace) {
074: Interpreter interp = getInterpreter();
075: for (ScopeExp scope = current_scope; scope != null; scope = scope.outer) {
076: Declaration decl = scope.lookup(name, interp, namespace);
077: if (decl != null)
078: return decl;
079: }
080: return null;
081: }
082:
083: public SourceMessages getMessages() {
084: return messages;
085: }
086:
087: public void setMessages(SourceMessages messages) {
088: this .messages = messages;
089: }
090:
091: public void error(char severity, String message) {
092: messages.error(severity, current_filename, current_line,
093: current_column, message);
094: }
095:
096: public void error(char severity, Declaration decl, String msg1,
097: String msg2) {
098: String filename = current_filename;
099: int line = current_line;
100: int column = current_column;
101: int decl_line = decl.getLine();
102: if (decl_line > 0) {
103: filename = decl.getFile();
104: line = decl_line;
105: column = decl.getColumn();
106: }
107: messages.error(severity, filename, line, column, msg1
108: + decl.getName() + msg2);
109: }
110:
111: public final String getFile() {
112: return current_filename;
113: }
114:
115: public final int getLine() {
116: return current_line;
117: }
118:
119: public final int getColumn() {
120: return current_column;
121: }
122:
123: public void setFile(String filename) {
124: current_filename = filename;
125: }
126:
127: public void setLine(int line) {
128: current_line = line;
129: }
130:
131: public void setColumn(int column) {
132: current_column = column;
133: }
134:
135: public void setLine(String filename, int line, int column) {
136: current_filename = filename;
137: current_line = line;
138: current_column = column;
139: }
140:
141: protected ScopeExp current_scope;
142:
143: protected String current_filename;
144: protected int current_line;
145: protected int current_column;
146:
147: protected SourceMessages messages;
148: }
|