/** * 토큰열을 분석하여 함수 호출 구문 요소를 추출한다. * * @param tokens * @param lineNumber * @return */ public static FunctionCallSyntax analyze(List <Token> tokens, int lineNumber) { // 함수가 완전히 닫혔는지 확인 if (TokenTools.indexOfShellClose(tokens, 2) != tokens.Count - 1) { Debug.reportError("Syntax error", "함수가 종결되지 않았습니다.", lineNumber); return(null); } // 함수 매개 변수를 가져온다. List <List <Token> > arguments = TokenTools.split(tokens.GetRange(2, tokens.Count - 1 - 2), Type.Comma, true); List <List <Token> > trimmedArguments = new List <List <Token> >(); foreach (int i in Enumerable.Range(0, arguments.Count)) { if (arguments[i].Count > 0) { trimmedArguments.Add(arguments[i]); } } return(new FunctionCallSyntax(tokens[0], trimmedArguments)); }
/** * 토큰열을 분석하여 함수 선언 구문 요소를 추출한다. * * @param tokens * @param lineNumber * @return */ public static FunctionDeclarationSyntax analyze(List <Token> tokens, int lineNumber) { Token functionName = null; List <List <Token> > parameters = null; Token returnType = null; // 타겟형과 일반형을 구분한다. if (tokens[2].type == Type.Dot) { functionName = tokens[3]; List <Token> functionTarget = new List <Token>(); functionTarget.Add(new Token(Type.ID, "this")); functionTarget.Add(Token.findByType(Type.Colon)); functionTarget.Add(tokens[1]); // 길이 조건을 새로 체크한다. if (tokens.Count < 5) { Debug.reportError("Syntax error", "Unexpected Token.", lineNumber); return(null); } if (tokens[3].type != Type.ID) { Debug.reportError("Syntax error", "함수에 이름이 없습니다.", lineNumber); return(null); } if (tokens[4].type != Type.ShellOpen) { Debug.reportError("Syntax error", "(가 필요합니다.", lineNumber); return(null); } int indexOfShellClose = TokenTools.indexOfShellClose(tokens, 5); if (indexOfShellClose < 0) { Debug.reportError("Syntax error", "괄호가 닫히지 않았습니다.", lineNumber); return(null); } // 리턴 타입 있음 if (indexOfShellClose != tokens.Count - 1) { // 길이 조건을 새로 체크한다. if (tokens.Count <= indexOfShellClose + 2 || indexOfShellClose + 2 != tokens.Count - 1) { Debug.reportError("Syntax error", "Unexpected Token.", lineNumber); return(null); } if (tokens[tokens.Count - 2].type != Type.Right || tokens[tokens.Count - 1].type != Type.ID) { Debug.reportError("Syntax error", "Unexpected Token.", lineNumber); return(null); } returnType = tokens[tokens.Count - 1]; } // 리턴 타입 없음 else { returnType = new Token(Type.ID, "void"); } // 파라미터를 취득한다. parameters = TokenTools.split(tokens.GetRange(5, indexOfShellClose - 5), Type.Comma, true); // 타겟을 파라미터의 첫 번째에 추가한다. parameters.Insert(0, functionTarget); } // 일반형 define name(parameters)->type else { functionName = tokens[1]; // 길이 조건을 다시 체크한다. if (tokens.Count < 4) { Debug.reportError("Syntax error", "Unexpected Token.", lineNumber); return(null); } if (tokens[2].type != Type.ShellOpen) { Debug.reportError("Syntax error", "(가 필요합니다.", lineNumber); return(null); } int indexOfShellClose = TokenTools.indexOfShellClose(tokens, 3); if (indexOfShellClose < 0) { Debug.reportError("Syntax error", "괄호가 닫히지 않았습니다.", lineNumber); return(null); } // 리턴 타입 있음 if (indexOfShellClose != tokens.Count - 1) { // 길이 조건을 새로 체크한다. if (tokens.Count <= indexOfShellClose + 2 || indexOfShellClose + 2 != tokens.Count - 1) { Debug.reportError("Syntax error", "Unexpected Token.", lineNumber); return(null); } if (tokens[tokens.Count - 2].type != Type.Right || tokens[tokens.Count - 1].type != Type.ID) { Debug.reportError("Syntax error", "Unexpected Token.", lineNumber); return(null); } returnType = tokens[tokens.Count - 1]; } // 리턴 타입 없음 else { returnType = new Token(Type.ID, "void"); } // 파라미터를 취득한다. parameters = TokenTools.split(tokens.GetRange(3, indexOfShellClose - 3), Type.Comma, true); } List <List <Token> > trimmedParameters = new List <List <Token> >(); foreach (int i in Enumerable.Range(0, parameters.Count)) { if (parameters[i].Count > 0) { trimmedParameters.Add(parameters[i]); } } return(new FunctionDeclarationSyntax(functionName, returnType, trimmedParameters)); }