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

http://github.com/nddrylliog/ooc · Java · 158 lines · 132 code · 26 blank · 0 comment · 34 complexity · aa739ff00b006f4c5fcd59515c53960f MD5 · raw file

  1. package org.ooc.frontend.parser;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. import org.ooc.frontend.model.Argument;
  5. import org.ooc.frontend.model.MemberArgument;
  6. import org.ooc.frontend.model.MemberAssignArgument;
  7. import org.ooc.frontend.model.Module;
  8. import org.ooc.frontend.model.NodeList;
  9. import org.ooc.frontend.model.RegularArgument;
  10. import org.ooc.frontend.model.Type;
  11. import org.ooc.frontend.model.VarArg;
  12. import org.ooc.frontend.model.tokens.Token;
  13. import org.ooc.frontend.model.tokens.TokenReader;
  14. import org.ooc.frontend.model.tokens.Token.TokenType;
  15. import org.ubi.CompilationFailedError;
  16. import org.ubi.SourceReader;
  17. public class ArgumentParser {
  18. public static boolean fill(Module module, SourceReader sReader, TokenReader reader, boolean acceptTypeArgs, NodeList<Argument> args) {
  19. if(reader.peek().type == TokenType.OPEN_PAREN) {
  20. reader.skip();
  21. boolean comma = false;
  22. while(true) {
  23. if(reader.peekWhiteless().type == TokenType.CLOS_PAREN) {
  24. reader.skipWhitespace();
  25. reader.skip(); // skip the ')'
  26. break;
  27. }
  28. if(comma) {
  29. if(reader.read().type != TokenType.COMMA) {
  30. throw new CompilationFailedError(sReader.getLocation(reader.prev(2)),
  31. "Did you forget to close the parenthesis here?");
  32. }
  33. } else {
  34. if(!parseInto(module, sReader, reader, acceptTypeArgs, args)) {
  35. throw new CompilationFailedError(sReader.getLocation(reader.peek()),
  36. "Expected argument specification of a function definition");
  37. }
  38. }
  39. comma = !comma;
  40. }
  41. return true;
  42. }
  43. return false;
  44. }
  45. public static boolean parseInto(Module module, SourceReader sReader, TokenReader reader,
  46. boolean acceptTypeArgs, NodeList<Argument> args) {
  47. int mark = reader.mark();
  48. Token startToken = reader.peek();
  49. if(startToken.type == TokenType.TRIPLE_DOT) {
  50. reader.skip();
  51. VarArg varArg = new VarArg(startToken);
  52. args.add(varArg);
  53. return true;
  54. }
  55. Token token = reader.readWhiteless();
  56. if(tryRegular(module, sReader, reader, args, mark, token)) return true;
  57. if(tryAssign(sReader, reader, args, token)) return true;
  58. if(tryMember(sReader, reader, args, token)) return true;
  59. reader.reset(mark);
  60. if(acceptTypeArgs) {
  61. Type type = TypeParser.parse(module, sReader, reader);
  62. if(type == null) {
  63. throw new CompilationFailedError(sReader.getLocation(reader.peek()),
  64. "Expected argument type in extern func definition ':'");
  65. }
  66. TypeArgument typeArg = new TypeArgument(type, type.startToken);
  67. args.add(typeArg);
  68. return true;
  69. }
  70. reader.reset();
  71. return false;
  72. }
  73. protected static boolean tryMember(SourceReader sReader, TokenReader reader,
  74. NodeList<Argument> args, Token token)
  75. throws CompilationFailedError {
  76. if(token.type != TokenType.DOT) return false;
  77. Token t2 = reader.read();
  78. if(t2.type != TokenType.NAME) {
  79. throw new CompilationFailedError(sReader.getLocation(t2),
  80. "Expecting member variable name in member-assign-argument");
  81. }
  82. MemberArgument arg = new MemberArgument(t2.get(sReader), token);
  83. args.add(arg);
  84. return true;
  85. }
  86. protected static boolean tryAssign(SourceReader sReader, TokenReader reader,
  87. NodeList<Argument> args, Token token)
  88. throws CompilationFailedError {
  89. if(token.type != TokenType.ASSIGN) return false;
  90. Token t2 = reader.read();
  91. if(t2.type != TokenType.NAME) {
  92. throw new CompilationFailedError(sReader.getLocation(t2),
  93. "Expecting member variable name in member-assign-argument");
  94. }
  95. MemberAssignArgument arg = new MemberAssignArgument(t2.get(sReader), token);
  96. args.add(arg);
  97. return true;
  98. }
  99. protected static boolean tryRegular(Module module, SourceReader sReader, TokenReader reader,
  100. NodeList<Argument> args, int mark, Token token) {
  101. if(!token.isNameToken()) return false;
  102. List<String> names = new ArrayList<String>();
  103. List<Token> tokens = new ArrayList<Token>();
  104. names.add(token.get(sReader));
  105. tokens.add(token);
  106. while(reader.peek().type == TokenType.COMMA) {
  107. reader.skip();
  108. if(reader.peek().type != TokenType.NAME) {
  109. reader.reset(mark);
  110. return false;
  111. }
  112. Token subToken = reader.read();
  113. names.add(subToken.get(sReader));
  114. tokens.add(subToken);
  115. }
  116. if(reader.peek().type == TokenType.COLON) {
  117. reader.skip();
  118. Type type = TypeParser.parse(module, sReader, reader, false);
  119. if(type == null) {
  120. throw new CompilationFailedError(sReader.getLocation(reader.peek()),
  121. "Expected argument type after its name and ':'");
  122. }
  123. for(int i = 0; i < names.size(); i++) {
  124. RegularArgument regArg = new RegularArgument(type, names.get(i), tokens.get(i));
  125. args.add(regArg);
  126. }
  127. return true;
  128. }
  129. reader.reset(mark);
  130. return false;
  131. }
  132. }