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

http://github.com/nddrylliog/ooc · Java · 142 lines · 121 code · 20 blank · 1 comment · 39 complexity · 13c7bf94f3f372defbd72db03853c92f 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.FunctionDecl;
  5. import org.ooc.frontend.model.Module;
  6. import org.ooc.frontend.model.OocDocComment;
  7. import org.ooc.frontend.model.Type;
  8. import org.ooc.frontend.model.TypeParam;
  9. import org.ooc.frontend.model.tokens.Token;
  10. import org.ooc.frontend.model.tokens.TokenReader;
  11. import org.ooc.frontend.model.tokens.Token.TokenType;
  12. import org.ubi.CompilationFailedError;
  13. import org.ubi.SourceReader;
  14. public class FunctionDeclParser {
  15. public static FunctionDecl parse(Module module, SourceReader sReader, TokenReader reader, boolean skipFunc) {
  16. int mark = reader.mark();
  17. OocDocComment comment = null;
  18. if(reader.peek().type == TokenType.OOCDOC) {
  19. Token token = reader.read();
  20. comment = new OocDocComment(token.get(sReader), token);
  21. // allow an arbitrary number of newlines after the oocdoc comment.
  22. while(reader.peek().type == TokenType.LINESEP)
  23. reader.skip();
  24. }
  25. Token startToken= reader.peek();
  26. String name = "";
  27. Token tName = reader.peek();
  28. if(tName.isNameToken()) {
  29. name = tName.get(sReader);
  30. reader.skip();
  31. if(reader.read().type != TokenType.COLON) {
  32. reader.reset(mark);
  33. return null;
  34. }
  35. }
  36. boolean isProto = false;
  37. boolean isAbstract = false;
  38. boolean isStatic = false;
  39. boolean isFinal = false;
  40. boolean isInline = false;
  41. String externName = null;
  42. String unmangledName = null;
  43. Token kw = reader.peek();
  44. keywordRead: while(true) {
  45. switch(kw.type) {
  46. case TokenType.ABSTRACT_KW: reader.skip(); isAbstract = true; break;
  47. case TokenType.STATIC_KW: reader.skip(); isStatic = true; break;
  48. case TokenType.FINAL_KW: reader.skip(); isFinal = true; break;
  49. case TokenType.PROTO_KW: reader.skip(); isProto = true; break;
  50. case TokenType.INLINE_KW: reader.skip(); isInline = true; break;
  51. case TokenType.EXTERN_KW: externName = ExternParser.parse(sReader, reader); break;
  52. case TokenType.UNMANGLED_KW: unmangledName = UnmangledParser.parse(sReader, reader); break;
  53. default: break keywordRead;
  54. }
  55. kw = reader.peek();
  56. }
  57. if(reader.peek().type == TokenType.FUNC_KW) {
  58. reader.skip();
  59. } else if(!skipFunc) {
  60. reader.reset(mark);
  61. return null;
  62. }
  63. String suffix = "";
  64. List<TypeParam> genTypes = null;
  65. while(true) {
  66. Token tok = reader.peek();
  67. if(tok.type == TokenType.TILDE) {
  68. reader.skip();
  69. Token tSuffix = reader.peek();
  70. if(tSuffix.isNameToken()) {
  71. reader.skip();
  72. suffix = tSuffix.get(sReader);
  73. }
  74. } else if(tok.type == TokenType.LESSTHAN) {
  75. reader.skip();
  76. genTypes = new ArrayList<TypeParam>();
  77. TypeParamParser.parse(sReader, reader, genTypes);
  78. } else break;
  79. }
  80. FunctionDecl functionDecl = new FunctionDecl(
  81. name, suffix, isFinal, isStatic, isAbstract, externName, startToken, module);
  82. functionDecl.setInline(isInline);
  83. functionDecl.setUnmangledName(unmangledName);
  84. functionDecl.setProto(isProto);
  85. if(genTypes != null) {
  86. for(TypeParam genType: genTypes) {
  87. functionDecl.getTypeParams().put(genType.getName(), genType);
  88. }
  89. }
  90. if(comment != null) functionDecl.setComment(comment);
  91. ArgumentParser.fill(module, sReader, reader, functionDecl.isExtern(), functionDecl.getArguments());
  92. Token token = reader.peek();
  93. if(token.type == TokenType.ARROW) {
  94. reader.skip();
  95. reader.skipWhitespace();
  96. Type returnType = TypeParser.parse(module, sReader, reader, false);
  97. if(returnType == null) {
  98. throw new CompilationFailedError(sReader.getLocation(reader.peek()),
  99. "Expected return type after '->'");
  100. }
  101. functionDecl.setReturnType(returnType);
  102. }
  103. if(externName != null || isAbstract) {
  104. return functionDecl;
  105. }
  106. token = reader.readWhiteless();
  107. if(token == null || token.type != TokenType.OPEN_BRACK) {
  108. throw new CompilationFailedError(sReader.getLocation(reader.prev(2)),
  109. "Expected body, e.g. {} after a function name (even for empty functions)");
  110. }
  111. while(reader.hasNext() && reader.peek().type != TokenType.CLOS_BRACK) {
  112. reader.skipWhitespace();
  113. if(!LineParser.fill(module, sReader, reader, functionDecl.getBody()) && reader.hasNext()
  114. && reader.peek().type != TokenType.CLOS_BRACK) {
  115. throw new CompilationFailedError(sReader.getLocation(reader.peek()),
  116. "Expected statement in function body. Found "+reader.peek()+" instead.");
  117. }
  118. }
  119. reader.skip();
  120. return functionDecl;
  121. }
  122. }