/src/org/ooc/frontend/parser/LineParser.java

http://github.com/nddrylliog/ooc · Java · 113 lines · 98 code · 15 blank · 0 comment · 30 complexity · 158fc49cc467d748842f96d8ac672a5c MD5 · raw file

  1. package org.ooc.frontend.parser;
  2. import org.ooc.frontend.model.BinaryOperation;
  3. import org.ooc.frontend.model.ControlStatement;
  4. import org.ooc.frontend.model.Expression;
  5. import org.ooc.frontend.model.FunctionCall;
  6. import org.ooc.frontend.model.Line;
  7. import org.ooc.frontend.model.MemberCall;
  8. import org.ooc.frontend.model.Module;
  9. import org.ooc.frontend.model.Node;
  10. import org.ooc.frontend.model.NodeList;
  11. import org.ooc.frontend.model.Statement;
  12. import org.ooc.frontend.model.VariableAccess;
  13. import org.ooc.frontend.model.VariableDecl;
  14. import org.ooc.frontend.model.tokens.Token;
  15. import org.ooc.frontend.model.tokens.TokenReader;
  16. import org.ooc.frontend.model.tokens.Token.TokenType;
  17. import org.ubi.CompilationFailedError;
  18. import org.ubi.SourceReader;
  19. public class LineParser {
  20. static int seedNumber = 1;
  21. @SuppressWarnings({ "unchecked", "null" })
  22. public static boolean fill(Module module, SourceReader sReader, TokenReader reader, NodeList<Line> body) {
  23. int mark = reader.mark();
  24. reader.skipWhitespace();
  25. if(!reader.hasNext()) {
  26. reader.reset(mark);
  27. return false;
  28. }
  29. int mark2 = reader.mark();
  30. Node node = VariableDeclParser.parseMulti(module, sReader, reader);
  31. Statement statement = null;
  32. Line line = null;
  33. if(node != null) {
  34. if(node instanceof NodeList<?>) {
  35. for(VariableDecl vDecl : (NodeList<VariableDecl>) node) {
  36. statement = vDecl;
  37. line = new Line(vDecl);
  38. body.add(line);
  39. }
  40. } else {
  41. statement = (Statement) node;
  42. VariableDecl vDecl = (VariableDecl) node;
  43. line = new Line(vDecl);
  44. body.add(line);
  45. }
  46. } else {
  47. reader.reset(mark2);
  48. statement = StatementParser.parse(module, sReader, reader);
  49. if(statement == null) {
  50. reader.reset(mark);
  51. return false;
  52. }
  53. line = new Line(statement);
  54. body.add(line);
  55. }
  56. while(reader.hasNext() && reader.peek().type == TokenType.DOT) {
  57. Expression expr = null;
  58. if(statement instanceof MemberCall) {
  59. MemberCall memberCall = (MemberCall) statement;
  60. expr = memberCall.getExpression();
  61. if(expr instanceof FunctionCall || expr instanceof BinaryOperation) {
  62. VariableDecl vdfe = new VariableDecl(null, "callroot" + (seedNumber++), expr, statement.startToken, null);
  63. body.addBefore(line, new Line(vdfe));
  64. expr = new VariableAccess(vdfe, expr.startToken);
  65. memberCall.setExpression(expr);
  66. }
  67. } else if(statement instanceof VariableDecl) {
  68. VariableDecl varDecl = (VariableDecl) statement;
  69. expr = new VariableAccess(varDecl, statement.startToken);
  70. } else if(statement instanceof Expression) {
  71. expr = (Expression) statement;
  72. } else {
  73. throw new CompilationFailedError(sReader.getLocation(reader.peek()),
  74. "Dots '.' for chain-calls should be used after expressions, not "
  75. +statement.getClass().getSimpleName()+"s.");
  76. }
  77. reader.skip();
  78. reader.skipWhitespace();
  79. Token startToken = reader.peek();
  80. FunctionCall otherCall = FunctionCallParser.parse(module, sReader, reader);
  81. if(otherCall == null) {
  82. throw new CompilationFailedError(sReader.getLocation(reader.peek()),
  83. "Expected function call after a dot '.'");
  84. }
  85. statement = new MemberCall(expr, otherCall, startToken);
  86. body.add(new Line(statement));
  87. }
  88. if(!(statement instanceof ControlStatement)) {
  89. Token next = reader.peek();
  90. if(next.type != TokenType.LINESEP && next.type != TokenType.CLOS_BRACK && next.type != TokenType.CLOS_PAREN) {
  91. throw new CompilationFailedError(sReader.getLocation(next),
  92. "Missing semi-colon at the end of a line (got a "+next+" instead)");
  93. }
  94. if(next.type == TokenType.LINESEP) reader.skip();
  95. }
  96. return true;
  97. }
  98. }