/src/java/ideah/tree/FakeNode.java

http://ideah.googlecode.com/ · Java · 454 lines · 413 code · 27 blank · 14 comment · 125 complexity · a57159da0dd71932b5087bb55a46e519 MD5 · raw file

  1. package ideah.tree;
  2. import ideah.tree.decl.*;
  3. import ideah.tree.expr.*;
  4. import ideah.tree.pat.*;
  5. import ideah.tree.stmt.BindStmt;
  6. import ideah.tree.stmt.ExprStmt;
  7. import ideah.tree.stmt.LetStmt;
  8. import ideah.tree.stmt.Statement;
  9. import ideah.tree.type.*;
  10. import java.util.ArrayList;
  11. import java.util.List;
  12. public final class FakeNode extends Located {
  13. public final String name;
  14. public final List<FakeNode> children;
  15. public FakeNode(IRange location, String name, List<FakeNode> children) {
  16. super(location);
  17. this.name = name;
  18. this.children = children;
  19. }
  20. private void append(StringBuilder buf, String indent) {
  21. buf.append(indent + name + " " + location + " {\n");
  22. String newIndent = " " + indent;
  23. for (FakeNode child : children) {
  24. child.append(buf, newIndent);
  25. }
  26. buf.append(indent + "}\n");
  27. }
  28. public String toString() {
  29. StringBuilder buf = new StringBuilder();
  30. append(buf, "");
  31. return buf.toString();
  32. }
  33. // todo: range for module!
  34. ModuleTree toModule(IRange location) throws NoMatchException {
  35. if ("Module".equals(name)) {
  36. int i = 0;
  37. Ident name = null;
  38. if (i < children.size()) {
  39. try {
  40. name = children.get(i).toModuleName();
  41. i++;
  42. } catch (NoMatchException ex) {
  43. // ignore
  44. }
  45. }
  46. List<Export> exports = new ArrayList<Export>();
  47. while (i < children.size()) {
  48. FakeNode child = children.get(i);
  49. try {
  50. Export export = child.toExport();
  51. exports.add(export);
  52. } catch (NoMatchException ex) {
  53. break;
  54. }
  55. i++;
  56. }
  57. List<Import> imports = new ArrayList<Import>();
  58. while (i < children.size()) {
  59. FakeNode child = children.get(i);
  60. try {
  61. Import imp = child.toImport();
  62. imports.add(imp);
  63. } catch (NoMatchException ex) {
  64. break;
  65. }
  66. i++;
  67. }
  68. List<Declaration> declarations = new ArrayList<Declaration>();
  69. while (i < children.size()) {
  70. FakeNode child = children.get(i);
  71. Declaration declaration = child.toDeclaration();
  72. declarations.add(declaration);
  73. i++;
  74. }
  75. return new ModuleTree(location, name, exports, imports, declarations);
  76. } else {
  77. throw new NoMatchException();
  78. }
  79. }
  80. private Ident toModuleName() throws NoMatchException {
  81. if ("ModuleName".equals(name)) {
  82. return new Ident(location);
  83. } else {
  84. throw new NoMatchException();
  85. }
  86. }
  87. private Export toExport() throws NoMatchException {
  88. if ("Export".equals(name)) {
  89. return new Export(location);
  90. } else {
  91. throw new NoMatchException();
  92. }
  93. }
  94. private Import toImport() throws NoMatchException {
  95. if ("Import".equals(name)) {
  96. return new Import(location);
  97. } else {
  98. throw new NoMatchException();
  99. }
  100. }
  101. private Declaration toDeclaration() throws NoMatchException {
  102. if ("ValD".equals(name)) {
  103. return children.get(0).toBind();
  104. } else if ("TyClD".equals(name)) {
  105. return children.get(0).toTyClDeclaration();
  106. } else if ("SigD".equals(name)) {
  107. return children.get(0).toSigDeclaration();
  108. } else {
  109. // todo: other cases
  110. throw new NoMatchException();
  111. }
  112. }
  113. private Match toMatch() throws NoMatchException {
  114. if ("Match".equals(name)) {
  115. List<Pat> pats = new ArrayList<Pat>();
  116. int i = 0;
  117. try {
  118. children.get(i).toIdent();
  119. i++;
  120. } catch (NoMatchException ex) {
  121. // ignore
  122. }
  123. while (i < children.size()) {
  124. FakeNode child = children.get(i);
  125. try {
  126. Pat pattern = child.toPattern();
  127. pats.add(pattern);
  128. } catch (NoMatchException ex) {
  129. break;
  130. }
  131. i++;
  132. }
  133. GRHSs grhss = toGRHSs(children.subList(i, children.size()));
  134. return new Match(location, pats, grhss);
  135. } else {
  136. throw new NoMatchException();
  137. }
  138. }
  139. private static GRHSs toGRHSs(List<FakeNode> nodes) throws NoMatchException {
  140. int i = 0;
  141. List<GRHS> grhss = new ArrayList<GRHS>();
  142. while (i < nodes.size()) {
  143. FakeNode child = nodes.get(i);
  144. try {
  145. GRHS grhs = child.toGRHS();
  146. grhss.add(grhs);
  147. } catch (NoMatchException ex) {
  148. break;
  149. }
  150. i++;
  151. }
  152. LocalBinds where = toLocalBinds(nodes.subList(i, nodes.size()));
  153. return new GRHSs(grhss, where);
  154. }
  155. private static LocalBinds toLocalBinds(List<FakeNode> nodes) throws NoMatchException {
  156. int i = 0;
  157. List<Bind> binds = new ArrayList<Bind>();
  158. while (i < nodes.size()) {
  159. FakeNode child = nodes.get(i);
  160. try {
  161. Bind bind = child.toBind();
  162. binds.add(bind);
  163. } catch (NoMatchException ex) {
  164. break;
  165. }
  166. i++;
  167. }
  168. List<SigDecl> sigs = new ArrayList<SigDecl>();
  169. while (i < nodes.size()) {
  170. FakeNode child = nodes.get(i);
  171. SigDecl sig = child.toSigDeclaration();
  172. sigs.add(sig);
  173. i++;
  174. }
  175. return new LocalBinds(binds, sigs);
  176. }
  177. private Bind toBind() throws NoMatchException {
  178. if ("FunBind".equals(name)) {
  179. List<Match> matches = toMatches(children.subList(1, children.size()));
  180. return new FunctionDecl(location, matches);
  181. } else if ("PatBind".equals(name)) {
  182. Pat pattern = children.get(0).toPattern();
  183. GRHSs grhss = toGRHSs(children.subList(1, children.size()));
  184. return new PatternDecl(location, pattern, grhss);
  185. } else {
  186. throw new NoMatchException();
  187. }
  188. }
  189. private GRHS toGRHS() throws NoMatchException {
  190. if ("GRHS".equals(name)) {
  191. for (int i = 0; i < children.size() - 1; i++) {
  192. Statement statement = children.get(i).toStatement();
  193. // todo: extract guard
  194. }
  195. Expression expression = children.get(children.size() - 1).toExpression();
  196. // todo: statements
  197. return new GRHS(location, expression);
  198. } else {
  199. throw new NoMatchException();
  200. }
  201. }
  202. private static List<Match> toMatches(List<FakeNode> nodes) throws NoMatchException {
  203. List<Match> matches = new ArrayList<Match>();
  204. for (FakeNode node : nodes) {
  205. matches.add(node.toMatch());
  206. }
  207. return matches;
  208. }
  209. private Expression toExpression() throws NoMatchException {
  210. if ("HsOverLit".equals(name)) {
  211. return new OverLiteral(location);
  212. } else if ("HsVar".equals(name)) {
  213. return new VarExpr(location);
  214. } else if ("HsLit".equals(name)) {
  215. return new Literal(location);
  216. } else if ("HsApp".equals(name)) {
  217. Expression function = children.get(0).toExpression();
  218. Expression arg = children.get(1).toExpression();
  219. return new Application(location, function, arg);
  220. } else if ("SectionL".equals(name)) {
  221. Expression arg = children.get(0).toExpression();
  222. Expression op = children.get(1).toExpression();
  223. return new LeftSection(location, arg, op);
  224. } else if ("SectionR".equals(name)) {
  225. Expression op = children.get(0).toExpression();
  226. Expression arg = children.get(1).toExpression();
  227. return new RightSection(location, op, arg);
  228. } else if ("OpApp".equals(name)) {
  229. Expression left = children.get(0).toExpression();
  230. Expression op = children.get(1).toExpression();
  231. Expression right = children.get(2).toExpression();
  232. return new OpApplication(location, left, op, right);
  233. } else if ("NegApp".equals(name)) {
  234. Expression right = children.get(0).toExpression();
  235. return new Negation(location, right);
  236. } else if ("HsPar".equals(name)) {
  237. Expression expression = children.get(0).toExpression();
  238. return new Parentheses(location, expression);
  239. } else if ("HsCase".equals(name)) {
  240. Expression expression = children.get(0).toExpression();
  241. List<Match> matches = toMatches(children.subList(1, children.size()));
  242. return new CaseExpr(location, expression, matches);
  243. } else if ("HsIf".equals(name)) {
  244. Expression expression = children.get(0).toExpression();
  245. Expression thenExpr = children.get(1).toExpression();
  246. Expression elseExpr = children.get(2).toExpression();
  247. return new IfExpr(location, expression, thenExpr, elseExpr);
  248. } else if ("HsLam".equals(name)) {
  249. List<Match> matches = toMatches(children);
  250. return new Lambda(location, matches);
  251. } else if ("ExplicitList".equals(name)) {
  252. List<Expression> expressions = new ArrayList<Expression>();
  253. for (FakeNode child : children) {
  254. expressions.add(child.toExpression());
  255. }
  256. return new ListExpr(location, expressions);
  257. } else if ("ExplicitTuple".equals(name)) {
  258. List<Expression> expressions = new ArrayList<Expression>();
  259. for (FakeNode child : children) {
  260. expressions.add(child.toExpression());
  261. }
  262. return new TupleExpr(location, expressions);
  263. } else if ("HsLet".equals(name)) {
  264. LocalBinds binds = toLocalBinds(children.subList(0, children.size() - 1));
  265. Expression expression = children.get(children.size() - 1).toExpression();
  266. return new LetExpr(location, binds, expression);
  267. } else if ("HsDo".equals(name)) {
  268. List<Statement> statements = new ArrayList<Statement>();
  269. for (int i = 0; i < children.size() - 1; i++) {
  270. Statement statement = children.get(i).toStatement();
  271. statements.add(statement);
  272. }
  273. Expression expression = children.get(children.size() - 1).toExpression();
  274. return new DoExpr(location, statements, expression);
  275. } else {
  276. // todo: RecordCon, RecordUpd, ExprWithTySig, ArithSeq
  277. // todo: other cases
  278. throw new NoMatchException();
  279. }
  280. }
  281. private Pat toPattern() throws NoMatchException {
  282. if ("WildPat".equals(name)) {
  283. return new WildPat(location);
  284. } else if ("VarPat".equals(name)) {
  285. return new VarPat(location);
  286. } else if ("LitPat".equals(name) || "NPat".equals(name)) {
  287. return new LitPat(location);
  288. } else if ("ParPat".equals(name)) {
  289. Pat pattern = children.get(0).toPattern();
  290. return new ParenPat(location, pattern);
  291. } else if ("BangPat".equals(name)) {
  292. Pat pattern = children.get(0).toPattern();
  293. return new BangPat(location, pattern);
  294. } else if ("LazyPat".equals(name)) {
  295. Pat pattern = children.get(0).toPattern();
  296. return new LazyPat(location, pattern);
  297. } else if ("ListPat".equals(name)) {
  298. List<Pat> patterns = new ArrayList<Pat>();
  299. for (FakeNode child : children) {
  300. patterns.add(child.toPattern());
  301. }
  302. return new ListPat(location, patterns);
  303. } else if ("TuplePat".equals(name)) {
  304. List<Pat> patterns = new ArrayList<Pat>();
  305. for (FakeNode child : children) {
  306. patterns.add(child.toPattern());
  307. }
  308. return new TuplePat(location, patterns);
  309. } else if ("AsPat".equals(name)) {
  310. Ident name = children.get(0).toIdent();
  311. Pat pattern = children.get(1).toPattern();
  312. return new AsPat(location, name, pattern);
  313. } else if ("ConPatIn".equals(name)) {
  314. Ident name = children.get(0).toIdent();
  315. List<Pat> patterns = new ArrayList<Pat>();
  316. for (int i = 1; i < children.size(); i++) {
  317. FakeNode child = children.get(i);
  318. Pat pattern = child.toPattern();
  319. patterns.add(pattern);
  320. }
  321. return new ConPat(location, name, new ConPatDetails(patterns)); // todo: records?
  322. } else {
  323. // todo: other cases
  324. throw new NoMatchException();
  325. }
  326. }
  327. private Statement toStatement() throws NoMatchException {
  328. if ("BindStmt".equals(name)) {
  329. Pat pattern = children.get(0).toPattern();
  330. Expression expression = children.get(1).toExpression();
  331. return new BindStmt(location, pattern, expression);
  332. } else if ("ExprStmt".equals(name)) {
  333. Expression expression = children.get(0).toExpression();
  334. return new ExprStmt(location, expression);
  335. } else if ("LetStmt".equals(name)) {
  336. LocalBinds binds = toLocalBinds(children);
  337. return new LetStmt(location, binds);
  338. } else {
  339. // todo: other cases
  340. throw new NoMatchException();
  341. }
  342. }
  343. private Type toType() throws NoMatchException {
  344. if ("HsForAllTy".equals(name)) {
  345. Type type = children.get(0).toType();
  346. return new ForAllType(location, type);
  347. } else if ("HsTyVar".equals(name)) {
  348. return new TyVarType(location);
  349. } else if ("HsAppTy".equals(name)) {
  350. Type type = children.get(0).toType();
  351. Type arg = children.get(1).toType();
  352. return new AppTyType(location, type, arg);
  353. } else if ("HsFunTy".equals(name)) {
  354. Type arg = children.get(0).toType();
  355. Type result = children.get(1).toType();
  356. return new FuncType(location, arg, result);
  357. } else if ("HsListTy".equals(name)) {
  358. Type type = children.get(0).toType();
  359. return new ListType(location, type);
  360. } else if ("HsTupleTy".equals(name)) {
  361. List<Type> types = new ArrayList<Type>();
  362. for (FakeNode child : children) {
  363. types.add(child.toType());
  364. }
  365. return new TupleType(location, types);
  366. } else if ("HsBangTy".equals(name)) {
  367. Type type = children.get(0).toType();
  368. return new BangType(location, type);
  369. } else {
  370. // todo: HsOpTy, HsRecTy
  371. // todo: other cases
  372. throw new NoMatchException();
  373. }
  374. }
  375. private SigDecl toSigDeclaration() throws NoMatchException {
  376. if ("TypeSig".equals(name)) {
  377. Ident name = children.get(0).toIdent();
  378. Type type = children.get(1).toType();
  379. return new TypeSigDecl(location, name, type);
  380. } else {
  381. // todo: other cases
  382. throw new NoMatchException();
  383. }
  384. }
  385. private TyClDecl toTyClDeclaration() throws NoMatchException {
  386. if ("TySynonym".equals(name)) {
  387. Ident name = children.get(0).toIdent();
  388. Type type = children.get(1).toType();
  389. return new TypeSynDecl(location, name, type);
  390. } else if ("TyData".equals(name)) {
  391. Ident name = children.get(0).toIdent();
  392. List<ConDecl> constructors = new ArrayList<ConDecl>();
  393. for (int i = 1; i < children.size(); i++) {
  394. ConDecl cons = children.get(i).toConDeclaration();
  395. constructors.add(cons);
  396. }
  397. return new DataTypeDecl(location, name, constructors);
  398. } else {
  399. // todo: other cases
  400. throw new NoMatchException();
  401. }
  402. }
  403. private ConDecl toConDeclaration() throws NoMatchException {
  404. if ("ConDecl".equals(name)) {
  405. Ident name = children.get(0).toIdent();
  406. List<Type> types = new ArrayList<Type>();
  407. for (int i = 1; i < children.size(); i++) {
  408. FakeNode child = children.get(i);
  409. Type type = child.toType();
  410. types.add(type);
  411. }
  412. return new ConDecl(location, name, types);
  413. } else {
  414. throw new NoMatchException();
  415. }
  416. }
  417. private Ident toIdent() throws NoMatchException {
  418. if ("Id".equals(name)) {
  419. return new Ident(location);
  420. } else {
  421. throw new NoMatchException();
  422. }
  423. }
  424. protected Iterable<FakeNode> getChildren() {
  425. return children;
  426. }
  427. }