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

http://github.com/nddrylliog/ooc · Java · 124 lines · 109 code · 15 blank · 0 comment · 52 complexity · 7bfcb281d0cc20973b2a927b7253dd1a MD5 · raw file

  1. package org.ooc.frontend.parser;
  2. import org.ooc.frontend.model.Import;
  3. import org.ooc.frontend.model.Module;
  4. import org.ooc.frontend.model.NamespaceDecl;
  5. import org.ooc.frontend.model.NodeList;
  6. import org.ooc.frontend.model.tokens.Token;
  7. import org.ooc.frontend.model.tokens.TokenReader;
  8. import org.ooc.frontend.model.tokens.Token.TokenType;
  9. import org.ubi.CompilationFailedError;
  10. import org.ubi.SourceReader;
  11. public class ImportParser {
  12. public static boolean fill(Module module, SourceReader sReader, TokenReader reader) {
  13. Token startToken = reader.peek();
  14. if(startToken.type != TokenType.IMPORT_KW) {
  15. return false;
  16. }
  17. reader.skip();
  18. StringBuilder sb = new StringBuilder();
  19. NamespaceDecl namespace = null;
  20. NodeList<Import> imports = new NodeList<Import>(startToken);
  21. Token token = null;
  22. while(true) {
  23. token = reader.read();
  24. if(token.type == TokenType.LINESEP || token.type == TokenType.INTO_KW) {
  25. Import imp = new Import(sb.toString(), startToken);
  26. imports.add(imp);
  27. break;
  28. } else if(token.type == TokenType.COMMA) {
  29. Import imp = new Import(sb.toString(), startToken);
  30. imports.add(imp);
  31. sb.setLength(0);
  32. reader.skipWhitespace();
  33. startToken = reader.peek();
  34. } else if(token.type == TokenType.SLASH) {
  35. sb.append('/');
  36. if(readMulti(sReader, reader, imports, sb, token)) break;
  37. if(reader.peek().type == TokenType.COMMA) {
  38. reader.skip();
  39. }
  40. } else if(token.type == TokenType.DOT) {
  41. throw new CompilationFailedError(sReader.getLocation(token),
  42. "import my.package.MyClass style deprecated, use import my/package/MyClass instead.");
  43. } else if(token.type == TokenType.DOUBLE_DOT) {
  44. sb.append("..");
  45. } else {
  46. sb.append(token.get(sReader));
  47. }
  48. }
  49. if(token.type == TokenType.INTO_KW || reader.peek().type == TokenType.INTO_KW) {
  50. if(reader.peek().type == TokenType.INTO_KW)
  51. reader.skip();
  52. Token nameToken = reader.read();
  53. if(nameToken.type != TokenType.NAME) {
  54. throw new CompilationFailedError(sReader.getLocation(token),
  55. "Expected NAME after `into` keyword.");
  56. }
  57. if(namespace != null) {
  58. throw new CompilationFailedError(sReader.getLocation(token),
  59. "Only one `into` declaration is allowed per import statement.");
  60. }
  61. String nsName = nameToken.get(sReader);
  62. namespace = module.getNamespace(nsName);
  63. if(namespace == null) {
  64. namespace = new NamespaceDecl(nsName, nameToken, module);
  65. module.addNamespace(namespace);
  66. }
  67. }
  68. if(namespace != null) {
  69. namespace.getImports().addAll(imports);
  70. } else {
  71. module.getGlobalImports().addAll(imports);
  72. }
  73. return true;
  74. }
  75. private static boolean readMulti(SourceReader sReader, TokenReader reader,
  76. NodeList<Import> imports, StringBuilder sb,
  77. Token token) throws CompilationFailedError {
  78. if(reader.peek().type == TokenType.OPEN_SQUAR) {
  79. reader.skip();
  80. StringBuilder innerSb = new StringBuilder();
  81. Token startToken = reader.peek();
  82. while(true) {
  83. reader.skipWhitespace();
  84. Token innerToken = reader.read();
  85. if(innerToken.type == TokenType.COMMA) {
  86. Import imp = new Import(sb.toString() + innerSb.toString(), startToken);
  87. imports.add(imp);
  88. innerSb.setLength(0);
  89. startToken = reader.peek();
  90. } else if(innerToken.type == TokenType.CLOS_SQUAR) {
  91. Import imp = new Import(sb.toString() + innerSb.toString(), startToken);
  92. imports.add(imp);
  93. break;
  94. } else {
  95. innerSb.append(innerToken.get(sReader));
  96. }
  97. }
  98. sb.setLength(0);
  99. Token next = reader.peek();
  100. if(next.type == TokenType.LINESEP || next.type == TokenType.INTO_KW) {
  101. return true;
  102. } else if(next.type != TokenType.COMMA) {
  103. throw new CompilationFailedError(sReader.getLocation(next),
  104. "Unexpected token "+next+" while reading an import");
  105. }
  106. }
  107. return false;
  108. }
  109. }