/// <summary> /// Interpreta un nodo /// </summary> private MLNode ParseNode(string name, ParserTokenizer tokenizer, bool searchBracket) { MLNode nodeML = new MLNode(name); // Captura el siguiente nodo if (!tokenizer.IsEof()) { if (searchBracket) { // Obtiene el siguiente token GetNextToken(tokenizer); // Debería ser una llave de apertura if (_idActualType == TokenType.BraceOpen) { nodeML.Nodes.Add(ParseNodesArray(tokenizer)); } else if (_idActualType != TokenType.BracketOpen) { throw new ParserException("Se esperaba una llave de apertura"); } else { ParseNodeAttributes(tokenizer, nodeML); } } else { ParseNodeAttributes(tokenizer, nodeML); } } // Devuelve el nodo interpretado return(nodeML); }
/// <summary> /// Interpreta un nodo /// </summary> private MLNode ParseNode(string strName, ParserTokenizer objTokenizer, bool blnSearchBracket) { MLNode objMLNode = new MLNode(strName); // Captura el siguiente nodo if (!objTokenizer.IsEof()) { if (blnSearchBracket) { // Obtiene el siguiente token GetNextToken(objTokenizer); // Debería ser una llave de apertura if (intIDActualType == TokenType.BraceOpen) { objMLNode.Nodes.Add(ParseNodesArray(objTokenizer)); } else if (intIDActualType != TokenType.BracketOpen) { throw new ParserException("Se esperaba una llave de apertura"); } else { ParseNodeAttributes(objTokenizer, objMLNode); } } else { ParseNodeAttributes(objTokenizer, objMLNode); } } // Devuelve el nodo interpretado return(objMLNode); }
/// <summary> /// Interpreta los nodos de un array /// </summary> private MLNode ParseNodesArray(string nodeParent, ParserTokenizer tokenizer) { MLNode nodeML = new MLNode(nodeParent); bool end = false; int index = 0; // Obtiene el siguiente token (puede que se trate de un array vacío) while (!tokenizer.IsEof() && !end) { // Obtiene el siguiente token GetNextToken(tokenizer); // Interpreta el nodo switch (_idActualType) { case TokenType.BracketOpen: nodeML.Nodes.Add(ParseNode("Struct", tokenizer, false)); break; case TokenType.BraceOpen: nodeML.Nodes.Add(ParseNodesArray(tokenizer)); break; case TokenType.String: case TokenType.Numeric: case TokenType.True: case TokenType.False: case TokenType.Null: nodeML.Nodes.Add("Item", _actualToken.Lexema); break; case TokenType.Comma: // ... no hace nada, simplemente pasa al siguiente incrementando el índice index++; break; case TokenType.BraceClose: // ... corchete de cierre, indica que ha terminado end = true; break; default: throw new NotImplementedException($"No se ha encontrado un token válido ('{_actualToken.Lexema}')"); } } // Si no se ha encontrado un corchete, lanza una excepción if (!end) { throw new ParserException("No se ha encontrado el carácter de fin del array ']'"); } // Devuelve la colección de nodos return(nodeML); }
/// <summary> /// Interpreta los atributos de un nodo "id":"value","id":"value", ... ó "id":{object} ó "id":[array] /// </summary> private void ParseNodeAttributes(ParserTokenizer tokenizer, MLNode nodeMLParent) { bool end = false; // Obtiene los nodos while (!tokenizer.IsEof() && !end) { // Lee el siguiente Token, debería ser un identificador GetNextToken(tokenizer); // Comprueba que sea correcto if (_idActualType == TokenType.BracketClose) // ... es un objeto vacío { end = true; } else if (_idActualType != TokenType.String) // ... no se ha encontrado el identificador { throw new ParserException("Se esperaba el identificador del elemento"); } else { MLAttribute attributeML = new MLAttribute(); // Asigna el código del atributo attributeML.Name = _actualToken.Lexema; // Lee el siguiente token. Deberían ser dos puntos GetNextToken(tokenizer); // Comprueba que sea correcto if (_idActualType != TokenType.Colon) { throw new ParserException("Se esperaban dos puntos (separador de identificador / valor)"); } else { // Lee el siguiente token... GetNextToken(tokenizer); // Interpreta el valor switch (_idActualType) { case TokenType.String: case TokenType.True: case TokenType.False: case TokenType.Numeric: case TokenType.Null: // Asigna el valor al atributo switch (_idActualType) { case TokenType.Null: attributeML.Value = ""; break; case TokenType.String: attributeML.Value = ParseUnicode(_actualToken.Lexema); break; default: attributeML.Value = _actualToken.Lexema; break; } // Añade el atributo al nodo nodeMLParent.Attributes.Add(attributeML); break; case TokenType.BracketOpen: // ... definición de objeto MLNode nodeML = ParseNode(attributeML.Name, tokenizer, false); // Añade el nodo como objeto nodeMLParent.Nodes.Add(nodeML); break; case TokenType.BraceOpen: // ... definición de array nodeMLParent.Nodes.Add(ParseNodesArray(attributeML.Name, tokenizer)); break; default: throw new ParserException($"Cadena desconocida. {_actualToken.Lexema}"); } } // Lee el siguiente token GetNextToken(tokenizer); // Si es una coma, seguir con el siguiente atributo del nodo, si es una llave de cierre, terminar switch (_idActualType) { case TokenType.Comma: // ... no hace nada, simplemente pasa a la creación del siguiente nodo break; case TokenType.BracketClose: end = true; break; default: throw new ParserException("Cadena desconocida. " + _actualToken.Lexema); } } } }