/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
- package org.ooc.frontend.parser;
- import java.util.ArrayList;
- import java.util.List;
- import org.ooc.frontend.model.FunctionDecl;
- import org.ooc.frontend.model.Module;
- import org.ooc.frontend.model.OocDocComment;
- import org.ooc.frontend.model.Type;
- import org.ooc.frontend.model.TypeParam;
- import org.ooc.frontend.model.tokens.Token;
- import org.ooc.frontend.model.tokens.TokenReader;
- import org.ooc.frontend.model.tokens.Token.TokenType;
- import org.ubi.CompilationFailedError;
- import org.ubi.SourceReader;
- public class FunctionDeclParser {
- public static FunctionDecl parse(Module module, SourceReader sReader, TokenReader reader, boolean skipFunc) {
- int mark = reader.mark();
-
- OocDocComment comment = null;
- if(reader.peek().type == TokenType.OOCDOC) {
- Token token = reader.read();
- comment = new OocDocComment(token.get(sReader), token);
- // allow an arbitrary number of newlines after the oocdoc comment.
- while(reader.peek().type == TokenType.LINESEP)
- reader.skip();
- }
-
- Token startToken= reader.peek();
-
- String name = "";
- Token tName = reader.peek();
- if(tName.isNameToken()) {
- name = tName.get(sReader);
- reader.skip();
- if(reader.read().type != TokenType.COLON) {
- reader.reset(mark);
- return null;
- }
- }
-
- boolean isProto = false;
- boolean isAbstract = false;
- boolean isStatic = false;
- boolean isFinal = false;
- boolean isInline = false;
- String externName = null;
- String unmangledName = null;
-
- Token kw = reader.peek();
- keywordRead: while(true) {
- switch(kw.type) {
- case TokenType.ABSTRACT_KW: reader.skip(); isAbstract = true; break;
- case TokenType.STATIC_KW: reader.skip(); isStatic = true; break;
- case TokenType.FINAL_KW: reader.skip(); isFinal = true; break;
- case TokenType.PROTO_KW: reader.skip(); isProto = true; break;
- case TokenType.INLINE_KW: reader.skip(); isInline = true; break;
- case TokenType.EXTERN_KW: externName = ExternParser.parse(sReader, reader); break;
- case TokenType.UNMANGLED_KW: unmangledName = UnmangledParser.parse(sReader, reader); break;
- default: break keywordRead;
- }
- kw = reader.peek();
- }
-
- if(reader.peek().type == TokenType.FUNC_KW) {
- reader.skip();
- } else if(!skipFunc) {
- reader.reset(mark);
- return null;
- }
-
- String suffix = "";
- List<TypeParam> genTypes = null;
- while(true) {
- Token tok = reader.peek();
- if(tok.type == TokenType.TILDE) {
- reader.skip();
- Token tSuffix = reader.peek();
- if(tSuffix.isNameToken()) {
- reader.skip();
- suffix = tSuffix.get(sReader);
- }
- } else if(tok.type == TokenType.LESSTHAN) {
- reader.skip();
- genTypes = new ArrayList<TypeParam>();
- TypeParamParser.parse(sReader, reader, genTypes);
- } else break;
- }
-
- FunctionDecl functionDecl = new FunctionDecl(
- name, suffix, isFinal, isStatic, isAbstract, externName, startToken, module);
- functionDecl.setInline(isInline);
- functionDecl.setUnmangledName(unmangledName);
- functionDecl.setProto(isProto);
- if(genTypes != null) {
- for(TypeParam genType: genTypes) {
- functionDecl.getTypeParams().put(genType.getName(), genType);
- }
- }
- if(comment != null) functionDecl.setComment(comment);
-
- ArgumentParser.fill(module, sReader, reader, functionDecl.isExtern(), functionDecl.getArguments());
-
- Token token = reader.peek();
- if(token.type == TokenType.ARROW) {
- reader.skip();
- reader.skipWhitespace();
- Type returnType = TypeParser.parse(module, sReader, reader, false);
- if(returnType == null) {
- throw new CompilationFailedError(sReader.getLocation(reader.peek()),
- "Expected return type after '->'");
- }
- functionDecl.setReturnType(returnType);
- }
-
- if(externName != null || isAbstract) {
- return functionDecl;
- }
- token = reader.readWhiteless();
- if(token == null || token.type != TokenType.OPEN_BRACK) {
- throw new CompilationFailedError(sReader.getLocation(reader.prev(2)),
- "Expected body, e.g. {} after a function name (even for empty functions)");
- }
-
- while(reader.hasNext() && reader.peek().type != TokenType.CLOS_BRACK) {
- reader.skipWhitespace();
-
- if(!LineParser.fill(module, sReader, reader, functionDecl.getBody()) && reader.hasNext()
- && reader.peek().type != TokenType.CLOS_BRACK) {
- throw new CompilationFailedError(sReader.getLocation(reader.peek()),
- "Expected statement in function body. Found "+reader.peek()+" instead.");
- }
- }
- reader.skip();
-
- return functionDecl;
- }
-
- }