//public static Dictionary<string, object> variableDictionary; #region Methods /// <summary> /// Scans a string into a token stream /// </summary> /// <param name="input"></param> /// <returns></returns> public static IEnumerator <object> Scan(IOuroborosLanguage enviroment, string input, Callback callback) { List <ProcessedToken?> tokens = new List <ProcessedToken?>(); List <object> TERMINALS = enviroment.GetTERMINALS(); SymbolStringTuple[] tuples = enviroment.GetRegexPairs(); string remainder = input; string text = ""; string testingText = ""; Regex regex; while (remainder.Length > 0) { //Debug.Log("Top of While"); ProcessedToken?token = null; int i = 0; for (; i < TERMINALS.Count; i++) { //Debug.Log("For1: " + tuples[i].str); text = ""; testingText = ""; // Track the current testing string. regex = new Regex(tuples[i].str); //Debug.Log(regex); for (int k = 0; k < remainder.Length; k++) { //Debug.Log("For2: " + remainder.Length + " | " + k); testingText += remainder[k]; if (regex.IsMatch(testingText)) { text = testingText; // Store our string since we know that this is the valid string. //Debug.Log("Is Match: " + regex + " => " + testingText); //Create the processedtoken token = new ProcessedToken(i, null, text); //Execute the code for reading this token. yield return(enviroment.StartLangCoroutine(tuples[i].coroutineName, new CoroutineWrapper(enviroment, (ProcessedToken)token, (object d) => { }))); } } if (token != null) { //Debug.Log("Breaking."); break; } } if (token != null) { if (tuples[i].ignorable) { //We have ignored this section } else { //Debug.Log(text + " | " + token); tokens.Add(token); } //Debug.Log("Pre<"+remainder+">"); remainder = remainder.Substring(text.Length); //Debug.Log("Post<" + remainder + ">"); text = ""; } else { //Log ERROR Debug.LogError("Syntax Read Error: '" + testingText + "'"); } //pause before continuing yield return(null); } tokens.Add(null); callback(tokens); }
/// <summary> /// Operates on a Token stream using the ParsingTable /// </summary> /// <param name="tokens"></param> /// <param name="generateScript"></param> /// <returns></returns> public static IEnumerator <object> Execute <T>(string inputString) where T : IOuroborosLanguage { Debug.Log("Execute"); //Create an instance of the language we are going to work with. IOuroborosLanguage language = (IOuroborosLanguage)System.Activator.CreateInstance(typeof(T)); //Create a place to store out input tokens (nullable so null = EOF when processing) List <ProcessedToken?> inputTokens = null; //Call scan, to get our list of beginning tokens. yield return(Scan(language, inputString, (object d) => { inputTokens = (List <ProcessedToken?>)d; })); Debug.Log("Scanning Finished"); PrintList <ProcessedToken?>(inputTokens); List <object> TERMINALS = language.GetTERMINALS(); List <object> nonTerminals = language.GetNonTerminals(); ParserInstruction[][] ParseTable = language.GetParseTable(); //The parsing stack List <ParseStackElement> parsingStack = new List <ParseStackElement>(); //Place state 0 onto the stack parsingStack.Add(new ParseStackElement(ParseStackElement.Type.State, 0)); //The current location in the parse int currencyIndicator = 0; //Begin the Looop! while (true) { yield return(null); Debug.Log(PrintList(parsingStack, false) + "|\\|/| -> " + inputTokens[currencyIndicator]); ParseStackElement top = parsingStack[parsingStack.Count - 1]; //Look at top of stack, if it is a Token, then we need to do a GoTo, if (top.type == ParseStackElement.Type.Token) { //Debug.Log("GoTo"); //DO A GOTO ParseStackElement previousState = parsingStack[parsingStack.Count - 2]; //Debug.Log(previousState); if (previousState.type != ParseStackElement.Type.State) { Debug.LogError("Stack parsing has broken due to invalid GoTo"); yield break; } //Calculate the column for the Token that is on top of the stack. int tokenColumn = TERMINALS.Count + top.scannedToken.tokenSymbolLocation; //Push onto the stack the state we are supposed to GoTo. parsingStack.Add(new ParseStackElement(ParseStackElement.Type.State, (int)ParseTable[previousState.parserStateIndex][tokenColumn].value)); } else { //Otherwise we look at the current state and the currency indiciator //Get the input token we are looking at ProcessedToken currentInputToken = (ProcessedToken)inputTokens[currencyIndicator]; //It can (should) only be a non terminal, so calculate its column on the parse table. int tokenColumn = currentInputToken.tokenSymbolLocation; Debug.Log(currentInputToken.data); Debug.Log(tokenColumn + "/" + (nonTerminals.Count + TERMINALS.Count)); ParserInstruction targetInstruction = ParseTable[top.parserStateIndex][tokenColumn]; if (targetInstruction.instruction == ParserInstruction.Instruction.ACCEPT) { ProcessedToken finalToken = (ProcessedToken)parsingStack[parsingStack.Count - 2].scannedToken; //Execute the final rule. language.StartLangCoroutine(finalToken.rule, new CoroutineWrapper(language, finalToken, (object data) => { })); break; } else if (targetInstruction.instruction == ParserInstruction.Instruction.SHIFT) { Debug.Log("Shift"); //If it is a shift, we put this token on the stack, parsingStack.Add(new ParseStackElement(ParseStackElement.Type.Token, 0, currentInputToken)); //advance the currency token, currencyIndicator++; //then the new state on the stack. parsingStack.Add(new ParseStackElement(ParseStackElement.Type.State, (int)targetInstruction.value)); } else if (targetInstruction.instruction == ParserInstruction.Instruction.REDUCE) { //If it is reduce, we... reduce ProductionRule productionRule = language.GetProductionRules()[targetInstruction.value]; int removalCount = productionRule.rhsSize * 2; //We pop off twice as many tokens as the rhs of the reduce instruction. List <ParseStackElement> poppedList = parsingStack.GetRange(parsingStack.Count - removalCount, removalCount); parsingStack.RemoveRange(parsingStack.Count - removalCount, removalCount); //Create a list of all of the ScannedTokens List <ProcessedToken> scannedTokensList = new List <ProcessedToken>(); for (int i = 0; i < poppedList.Count; i++) { if (poppedList[i].type == ParseStackElement.Type.Token) { scannedTokensList.Add(poppedList[i].scannedToken); } } //Call the appropriate operation (Performi the Reduction) ProcessedToken resultingToken = new ProcessedToken(productionRule.result, productionRule.coroutineName, scannedTokensList); //Put the resulting LHS token onto the stack. parsingStack.Add(new ParseStackElement(ParseStackElement.Type.Token, 0, resultingToken)); } else { PrintList(parsingStack); Debug.Log(currentInputToken); inputTokens.RemoveRange(0, currencyIndicator); //PrintList(inputTokens); Debug.LogError("Stack parsing has broken due to invalid Instruction: " + System.Enum.GetName(typeof(ParserInstruction.Instruction), targetInstruction.instruction)); yield break; } } } Debug.Log("EndExecute"); } //-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------END EXECUTE