00001
00005 package edu.mit.csail.sdg.squander.spec;
00006
00007 import org.antlr.runtime.ANTLRStringStream;
00008 import org.antlr.runtime.CommonTokenStream;
00009 import org.antlr.runtime.RecognitionException;
00010 import org.antlr.runtime.tree.Tree;
00011 import org.antlr.runtime.tree.TreeAdaptor;
00012
00013 import edu.mit.csail.sdg.squander.log.Log;
00014 import edu.mit.csail.sdg.squander.parser.JFSLLexer;
00015 import edu.mit.csail.sdg.squander.parser.JFSLParser;
00016 import edu.mit.csail.sdg.squander.parser.JFSLParserException;
00017 import edu.mit.csail.sdg.squander.parser.JFSLParser.Node;
00018 import edu.mit.csail.sdg.squander.parser.JFSLParser.NodeAdaptor;
00019 import forge.program.ForgeExpression;
00020
00028 public class Source {
00029 static enum Rule {
00030 CLAUSE, DECLARATION, FRAME
00031 };
00032
00033
00034 public final String source;
00035 public final NameSpace ns;
00036 public final Rule rule;
00037 public final boolean isFuncFlag;
00038
00039
00040 private Node node;
00041 private boolean typechecked = false;
00042
00044 Source(String source, NameSpace ns, Rule kind) {
00045 this(source, ns, kind, false);
00046 }
00047
00048 Source(String source, NameSpace ns, Rule kind, boolean isFuncFlag) {
00049 this.source = source;
00050 this.rule = kind;
00051 this.ns = ns;
00052 this.node = null;
00053 this.isFuncFlag = isFuncFlag;
00054 if (isFuncFlag)
00055 assert kind == Rule.DECLARATION;
00056 }
00057
00058 public boolean isClause() { return rule == Rule.CLAUSE; }
00059 public boolean isFrame() { return rule == Rule.FRAME; }
00060 public boolean isDecl() { return rule == Rule.DECLARATION; }
00061 public boolean isFuncField() { return isFuncFlag; }
00062
00063 public Node node() {
00064 try {
00065 if (node == null)
00066 parse();
00067 } catch (JFSLParserException e) {
00068 if (source != null)
00069 throw new JFSLParserException(e.getMessage(), source);
00070 else
00071 throw e;
00072 }
00073 return node;
00074 }
00075
00076 public void parse() {
00077
00078 Log.trace("parsing: " + source);
00079 final Node node;
00080
00081
00082 final ANTLRStringStream cs = new ANTLRStringStream(source);
00083 final JFSLLexer lexer = new JFSLLexer(cs);
00084 final CommonTokenStream tokens = new CommonTokenStream();
00085 tokens.setTokenSource(lexer);
00086 final JFSLParser parser = new JFSLParser(tokens);
00087 final TreeAdaptor adaptor = new NodeAdaptor();
00088 parser.setTreeAdaptor(adaptor);
00089
00090
00091 try {
00092 final Object result;
00093 switch(rule) {
00094 case CLAUSE: result = parser.clause().getTree(); break;
00095 case DECLARATION: result = parser.specField().getTree(); break;
00096 case FRAME: result = parser.modifies().getTree(); break;
00097 default: result = null;
00098 }
00099
00100 if (!(result instanceof Node)) {
00101 if (result instanceof Tree)
00102 throw new JFSLParserException("cannot produce AST", (Tree) result);
00103 else
00104 throw new JFSLParserException("cannot produce AST");
00105 } else {
00106 node = (Node) result;
00107 }
00108 } catch (JFSLParserException e) {
00109 throw e;
00110 } catch (RuntimeException e) {
00111 throw new JFSLParserException(e);
00112 } catch (RecognitionException e) {
00113 throw new JFSLParserException(e);
00114 }
00115
00116 this.node = node;
00117 }
00118
00119 public void typecheck(TypeChecker checker) {
00120 if (typechecked)
00121 return;
00122 if (node == null)
00123 parse();
00124 Log.trace("typechecking: " + source);
00125 try {
00126 checker.visit(ns, this.node);
00127 } catch (TypeCheckException e) {
00128 e.setSource(source);
00129 throw e;
00130 }
00131 typechecked = true;
00132 }
00133
00137 public ForgeExpression translate(Tr tr, ForgeEnv env) {
00138 assert typechecked : "must typecheck before translating to ForgeExpression";
00139 try {
00140 Log.trace("translating with " + tr.getClass().getSimpleName() + ": " + source);
00141 ForgeExpression expr = tr.visit(env, node());
00142 return expr;
00143 } catch (Exception e) {
00144 throw new JFSLParserException("Error translating: " + source, e);
00145 }
00146 }
00147
00148 @Override
00149 public String toString() {
00150 return rule + ": \"" + source + "\"";
00151 }
00152
00153 }