private bool IsValidDelimiter(CharWrapper item, CharWrapper nextItem) { // To be considered valid, the item must be... // white space if (char.IsWhiteSpace(item.Char)) { return(true); } // new line if (item.Char == NEW_LINE) { return(true); } // a operator if (GetOperatorToken(item.ToString()) != null || GetOperatorToken(item.ToString() + nextItem.ToString()) != null) { return(true); } // special symbol if (GetSpecialSymbolToken(item.ToString()) != null || GetSpecialSymbolToken(item.ToString() + nextItem.ToString()) != null) { return(true); } return(false); }
private Token ExtractAlphanumericProcedure(Stack <CharWrapper> items) { if (char.IsLetter(currentItem.Char)) { string strToConcate = ""; CharWrapper startItem = currentItem; // Consider underline as alphanumeric here, since is used to identifier while (char.IsLetterOrDigit(currentItem.Char) || currentItem.Char == UNDERLINE) { strToConcate = string.Concat(strToConcate, currentItem.ToString()); currentItem = GetNextItem(items); } // Validate if the extracted value is delimited by a valid delimiter if (!IsValidDelimiter(currentItem, PreviewNextItem(items))) { throw new LexicalException(GetLineColumnText(startItem) + ": Identificador " + strToConcate + currentItem + PreviewNextItem(items) + " é inválido", startItem.Line); } // Verify if extracted string contains in... // Operators Token extractedOperator = GetOperatorToken(strToConcate); if (extractedOperator != null) { extractedOperator.StartChar = startItem; return(extractedOperator); } // Reserved Words Token extractedReservedWord = GetReservedWordToken(strToConcate); if (extractedReservedWord != null) { extractedReservedWord.StartChar = startItem; return(extractedReservedWord); } // Otherwise is Identifier if (strToConcate.Count() > 30) { throw new LexicalException(GetLineColumnText(startItem) + ": O identificador " + strToConcate + " possui mais que os 30 caracteres limite", startItem.Line); } return(new Token { Type = IdentifierEnum.Identifier, Value = strToConcate, StartChar = startItem }); } return(null); }
private Token ExtractLiteralProcedure(Stack <CharWrapper> items) { // On found an apostrophe if (currentItem.Char.Equals(APOSTROPHE)) { string strToConcate = char.ToString(APOSTROPHE); CharWrapper startItem = currentItem; currentItem = GetNextItem(items); // Continues until found final apostrophe while (!currentItem.Char.Equals(APOSTROPHE)) { // If a newline was found, must throw a exception if (currentItem.Line != startItem.Line) { throw new LexicalException(GetLineColumnText(startItem) + ": Não é permitido quebra de linha em literais: " + strToConcate, startItem.Line); } strToConcate = string.Concat(strToConcate, currentItem.ToString()); currentItem = GetNextItem(items); } strToConcate = string.Concat(strToConcate, char.ToString(APOSTROPHE)); currentItem = GetNextItem(items); if (strToConcate.Count() > 257) // 257 -> 255 + apostrophe { throw new LexicalException(GetLineColumnText(startItem) + ": O literal " + strToConcate + " possui mais que os 255 caracteres limite", startItem.Line); } return(new Token { Type = LiteralEnum.Literal, Value = strToConcate, StartChar = startItem }); } return(null); }
private Token ExtractSignalOperatorsProcedure(Stack <CharWrapper> items) { // Ignore letters, digits and white space if (!char.IsLetterOrDigit(currentItem.Char) && !char.IsWhiteSpace(currentItem.Char)) { CharWrapper nextItem = PreviewNextItem(items); Token extractedOperator; // Ignore letters, digits and white space if (!char.IsLetterOrDigit(nextItem.Char) && !char.IsWhiteSpace(nextItem.Char)) { // Check for operators with two chars string composedOperator = currentItem.ToString() + nextItem.ToString(); extractedOperator = GetOperatorToken(composedOperator); if (extractedOperator != null) { extractedOperator.StartChar = currentItem; // Foward two chars since was analyze the current and the next positions currentItem = GetNextItem(items); currentItem = GetNextItem(items); return(extractedOperator); } } // Check for operators with one char extractedOperator = GetOperatorToken(currentItem.ToString()); if (extractedOperator != null) { extractedOperator.StartChar = currentItem; currentItem = GetNextItem(items); return(extractedOperator); } } return(null); }
private void ClearCommentProcedure(Stack <CharWrapper> items) { CharWrapper nextItem = PreviewNextItem(items); if (currentItem.Char.Equals(PARENTHESES_INI) && nextItem.Char.Equals(ASTERISK)) { CharWrapper startItem = currentItem; currentItem = GetNextItem(items); while (!(currentItem.Char.Equals(ASTERISK) && PreviewNextItem(items).Char.Equals(PARENTHESES_END))) { currentItem = GetNextItem(items); if (items.Count == 0) { throw new LexicalException(GetLineColumnText(startItem) + ": Comentário iniciado mas não fechado", startItem.Line); } } currentItem = GetNextItem(items); currentItem = GetNextItem(items); } }
private CharWrapper PreviewNextItem(Stack <CharWrapper> stk, int position = 0) { CharWrapper nextItem = stk.ElementAtOrDefault(position); return(nextItem ?? new CharWrapper()); }
private string GetLineColumnText(CharWrapper charWrapper) { return("(Linha: " + charWrapper.Line + ", Coluna: " + charWrapper.Position + ")"); }
public IList <Token> Start() { IList <Token> tokensList = new List <Token>(); // Create a stack of CharWrapper to analyze Stack <CharWrapper> items = CreateItemsStack(textToAnalyze); currentItem = GetNextItem(items); while (items.Count != 0) { Queue procedureQueue = new Queue(); /* * Atenção! * Quando um procedimento encontrar um token, é responsabilidade dele avançar para o próximo item a ser analizado */ // Procedure Comments ClearCommentProcedure(items); // Procedure Literals procedureQueue.Enqueue(ExtractLiteralProcedure(items)); // Procedure Digits procedureQueue.Enqueue(ExtractDigitsProcedure(items)); // Procedure Operators (Signals: +, >, >=...) procedureQueue.Enqueue(ExtractSignalOperatorsProcedure(items)); // Procedure Alphanumeric (Extract identifier, reserved words and alphanumeric operators) procedureQueue.Enqueue(ExtractAlphanumericProcedure(items)); // Procedure Special Symbols procedureQueue.Enqueue(ExtractSpecialSymbolProcedure(items)); // Iterate over each item in the queue to create the stack bool hasAnyValidToken = false; foreach (Token procedure in procedureQueue) { if (procedure != null) { hasAnyValidToken = true; tokensList.Add(procedure); } } // If all procedure do not returns a valid toke if (!hasAnyValidToken) { // If character is not recognized by a procedure and is not a white space or new line if (!char.IsWhiteSpace(currentItem.Char) && currentItem.Char != NEW_LINE) { throw new LexicalException(GetLineColumnText(currentItem) + ": " + currentItem.ToString() + " não é reconhecido como um caracter válido", currentItem.Line); } currentItem = GetNextItem(items); } } // Before return validate if has unclosed brackets or parentheses if (openBrackets.Count > 0) { throw new LexicalException(GetLineColumnText(openBrackets.Peek()) + ": Colchetes não foi fechado", openBrackets.Peek().Line); } if (openParentheses.Count > 0) { throw new LexicalException(GetLineColumnText(openParentheses.Peek()) + ": Parênteses não foi fechado", openParentheses.Peek().Line); } return(tokensList); }
private Token ExtractSpecialSymbolProcedure(Stack <CharWrapper> items) { // To avoid conflict with open comment symbol "(*" and "(" symbol, call method to clear comment before continue ClearCommentProcedure(items); // Ignore white space if (!char.IsWhiteSpace(currentItem.Char)) { CharWrapper nextItem = PreviewNextItem(items); Token extractedSymbol; // Ignore white space if (!char.IsWhiteSpace(nextItem.Char)) { // Check for symbols with two chars string composedSymbol = currentItem.ToString() + nextItem.ToString(); extractedSymbol = GetSpecialSymbolToken(composedSymbol); if (extractedSymbol != null) { extractedSymbol.StartChar = currentItem; // Foward two chars since was analyze the current and the next positions currentItem = GetNextItem(items); currentItem = GetNextItem(items); return(extractedSymbol); } } // Check for symbols with one char extractedSymbol = GetSpecialSymbolToken(currentItem.ToString()); if (extractedSymbol != null) { // If symbol is a open brackets if (extractedSymbol.Type.GetValue <int>() == SpecialSymbolEnum.LeftBracket.GetValue <int>()) { openBrackets.Push(currentItem); } // If symbol is a close brackets if (extractedSymbol.Type.GetValue <int>() == SpecialSymbolEnum.RightBracket.GetValue <int>()) { try { openBrackets.Pop(); } catch (InvalidOperationException) { throw new LexicalException(GetLineColumnText(currentItem) + ": Não é possível fechar um colchetes que não foi aberto", currentItem.Line); } } // If symbol is a open parentheses if (extractedSymbol.Type.GetValue <int>() == SpecialSymbolEnum.LeftParentheses.GetValue <int>()) { openParentheses.Push(currentItem); } // If symbol is a close parentheses if (extractedSymbol.Type.GetValue <int>() == SpecialSymbolEnum.RightParentheses.GetValue <int>()) { try { openParentheses.Pop(); } catch (InvalidOperationException) { throw new LexicalException(GetLineColumnText(currentItem) + ": Não é possível fechar um parênteses que não foi aberto", currentItem.Line); } } extractedSymbol.StartChar = currentItem; currentItem = GetNextItem(items); return(extractedSymbol); } } return(null); }
private Token ExtractDigitsProcedure(Stack <CharWrapper> items) { string strToConcate = ""; CharWrapper startItem = null; CharWrapper nextItem = PreviewNextItem(items); // Negative number signal if (currentItem.Char.Equals(MINUS) && char.IsDigit(nextItem.Char)) { strToConcate = currentItem.ToString(); startItem = currentItem; currentItem = GetNextItem(items); } if (char.IsDigit(currentItem.Char)) { while (char.IsDigit(currentItem.Char)) { strToConcate = string.Concat(strToConcate, currentItem.ToString()); startItem = startItem ?? currentItem; nextItem = PreviewNextItem(items); // Validade if number can be beginning of an identificator if (char.IsLetter(nextItem.Char)) { throw new LexicalException(GetLineColumnText(startItem) + ": Identificadores não podem iniciar com números: " + strToConcate + nextItem + "...", startItem.Line); } currentItem = GetNextItem(items); nextItem = PreviewNextItem(items); // Validade if number contains decimal separator if (char.IsDigit(nextItem.Char) && currentItem.Char.Equals('.')) { throw new LexicalException(GetLineColumnText(startItem) + ": Números não podem conter ponto flutuante: " + strToConcate + currentItem + nextItem + "...", startItem.Line); } } // Validate if extracted number is the range –32767, 32767 try { int parsedNumber = int.Parse(strToConcate); if (parsedNumber.CompareTo(-32767) == -1 || parsedNumber.CompareTo(32767) == 1) { throw new LexicalException(GetLineColumnText(startItem) + ": O número " + strToConcate + " está fora do intervalo permitido -32767 a 32767", startItem.Line); } } catch (OverflowException error) { throw new LexicalException(GetLineColumnText(startItem) + ": O número " + strToConcate + " está fora do intervalo permitido -32767 a 32767", startItem.Line); } return(new Token { Type = NumberEnum.Integer, Value = strToConcate, StartChar = startItem }); } return(null); }