public override MyToken[] Eval(ObjectStream <Char> input, MyDiscardDelegate <char> discarder) { Ensure(input, discarder); // Ignora código descartável inicialmente input.Discard(discarder); if (input.EndOfStream()) { return(null); } var initialPos = input.GetPosition(); char character = input.Next(); if (character != _character) { input.SetPosition(initialPos); return(null); } var token = new MyToken( GetTokenClass(), initialPos, input.GetPosition(), null ); return(new MyToken[] { token }); }
public override SyntaxTreeNode Make(ObjectStream <MyToken> input, MyDiscardDelegate <MyToken> discarder) { Ensure(input, discarder); // Ignora código descartável inicialmente input.Discard(discarder); if (input.EndOfStream()) { return(null); } var initialPos = input.GetPosition(); var token = input.Next(); if (token == null || (CalcTwoNumbersTokenClass)token.Class != (CalcTwoNumbersTokenClass)GetTokenClass()) { input.SetPosition(initialPos); return(null); } if (string.IsNullOrEmpty((string)token.Content)) { throw new SyntaxAnalysisException("Invalid content for NUMBER element"); } uint number = 0; if (!uint.TryParse((string)token.Content, out number)) { throw new SyntaxAnalysisException("Invalid number value for NUMBER element"); } return(new UIntegerTreeNode(number)); }
public override MyToken[] Eval(ObjectStream <Char> input, MyDiscardDelegate <char> discarder) { Ensure(input, discarder); // Ignora código descartável inicialmente input.Discard(discarder); if (input.EndOfStream()) { return(null); } var initialPos = input.GetPosition(); var foundTokens = new List <MyToken>(); foreach (var element in _elements) { var elementTokens = element.Eval(input, discarder); // Qualquer elemento do grupo falhando, todo o grupo falha if (elementTokens == null) { return(null); } foundTokens.AddRange(elementTokens); } if (!foundTokens.Any()) { input.SetPosition(initialPos); return(null); } // O próprio elemento de grupo torna-se um token. // Isso é util para ser usado como um demarcador var token = new MyToken( GetTokenClass(), initialPos, input.GetPosition(), null ); var firstToken = new MyToken[] { token }; // Os demais tokens seguem o demarcador return(firstToken.Concat(foundTokens).ToArray()); }
/// <summary> /// Executa a análise léxica. /// </summary> /// <param name="input">Sequência de caracteres de entrada</param> /// <returns>Sequência de tokens</returns> /// <exception cref="LexicalAnalysisException">Se houver algum erro durante a análise</exception> /// <exception cref="TokenNotFoundException">Se nenhum token for encontrado</exception> /// <exception cref="InputNotConsumedCompletelyException">Se a entrada não for completamente consumida</exception> public ObjectStream <MyToken> Run(ObjectStream <Char> input) { if (input == null) { throw new ArgumentNullException(nameof(input)); } MyDiscardDelegate <Char> discarder = (c) => false; if (_grammar.OnLexerDiscard != null) { discarder = _grammar.OnLexerDiscard; } try { MyToken[] acquiredTokens = _grammar.RootElement.Eval(input, discarder); if (acquiredTokens == null || acquiredTokens.Count() < 1) { // TODO: Informar [currentPos] ??? throw new TokenNotFoundException(); } // Ignorando qualquer código descartável que tenha restado input.Discard(discarder); if (!input.EndOfStream()) { // TODO: Informar [currentPos] ??? throw new InputNotConsumedCompletelyException(); } var output = new TokenStream(); Array.ForEach(acquiredTokens, (token) => output.Push(token)); return(output); } catch (LexicalAnalysisException) { throw; } catch (Exception ex) { throw new LexicalAnalysisException(ex); } }
public override SyntaxTreeNode Make(ObjectStream <MyToken> input, MyDiscardDelegate <MyToken> discarder) { Ensure(input, discarder); // Ignora código descartável inicialmente input.Discard(discarder); if (input.EndOfStream()) { return(null); } var initialPos = input.GetPosition(); // O primeiro token é só um marcador (etiqueta) pra indicar // um elemento válido var tag = input.Next(); if (tag == null || (CalcTwoNumbersTokenClass)tag.Class != (CalcTwoNumbersTokenClass)GetTokenClass()) { input.SetPosition(initialPos); return(null); } var numberLeftNode = ExpressionElements[0].Make(input, discarder); var plusNode = ExpressionElements[1].Make(input, discarder); var numberRightNode = ExpressionElements[2].Make(input, discarder); if (numberLeftNode == null || plusNode == null || numberRightNode == null) { input.SetPosition(initialPos); return(null); } var exprTreeNode = new SyntaxTreeNode(); plusNode.AddChildNode(numberLeftNode); plusNode.AddChildNode(numberRightNode); exprTreeNode.AddChildNode(plusNode); return(exprTreeNode); }
/// <summary> /// Executa a análise sintática. /// </summary> /// <param name="input">Sequência de tokens de entrada</param> /// <returns>Árvore sintática abstrata</returns> /// <exception cref="SyntaxAnalysisException">Se houver algum erro durante a análise</exception> /// <exception cref="TheNodeWasNotCreatedException">Se algum nó não puder ser construído</exception> /// <exception cref="InputNotConsumedCompletelyException">Se a entrada não for completamente consumida</exception> public MyAbstractSyntaxTree Run(ObjectStream <MyToken> input) { if (input == null) { throw new ArgumentNullException(nameof(input)); } MyDiscardDelegate <MyToken> discarder = (c) => false; if (_grammar.OnParserDiscard != null) { discarder = _grammar.OnParserDiscard; } try { SyntaxTreeNode rootNode = _grammar.RootElement.Make(input, discarder); if (rootNode == null) { throw new TheNodeWasNotCreatedException(); } // Ignorando qualquer código descartável que tenha restado input.Discard(discarder); if (!input.EndOfStream()) { throw new InputNotConsumedCompletelyException(); } return(new MyAbstractSyntaxTree(rootNode)); } catch (SyntaxAnalysisException) { throw; } catch (Exception ex) { throw new SyntaxAnalysisException(ex); } }
public override MyToken[] Eval(ObjectStream <Char> input, MyDiscardDelegate <char> discarder) { Ensure(input, discarder); // Ignora código descartável inicialmente input.Discard(discarder); var initialPos = input.GetPosition(); var foundChars = new List <Char>(); while (!input.EndOfStream()) { var pos = input.GetPosition(); char c = input.Next(); if (!_validChars.Contains(c)) { input.SetPosition(pos); break; } foundChars.Add(c); } if (!foundChars.Any()) { input.SetPosition(initialPos); return(null); } var token = new MyToken( GetTokenClass(), initialPos, input.GetPosition(), new string(foundChars.ToArray()) ); return(new MyToken[] { token }); }
public override SyntaxTreeNode Make(ObjectStream <MyToken> input, MyDiscardDelegate <MyToken> discarder) { Ensure(input, discarder); // Ignora código descartável inicialmente input.Discard(discarder); if (input.EndOfStream()) { return(null); } var initialPos = input.GetPosition(); var token = input.Next(); if (token == null || (CalcTwoNumbersTokenClass)token.Class != (CalcTwoNumbersTokenClass)GetTokenClass()) { input.SetPosition(initialPos); return(null); } return(new SumOperatorTreeNode()); }
public override MyToken[] Eval(ObjectStream <Char> input, MyDiscardDelegate <char> discarder) { Ensure(input, discarder); // Ignora código descartável inicialmente input.Discard(discarder); if (input.EndOfStream()) { return(null); } var initialPos = input.GetPosition(); var foundTokens = new List <MyToken>(); foreach (var element in _elements) { var elementTokens = element.Eval(input, discarder); // O primeiro elemento que obter sucesso, esse é o aceito if (elementTokens != null) { foundTokens.AddRange(elementTokens); break; } } if (!foundTokens.Any()) { input.SetPosition(initialPos); return(null); } return(foundTokens.ToArray()); }