/// <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 un texto /// </summary> public MLFile ParseText(string text) { ParserTokenizer tokenizer = InitTokenizer(); MLFile fileML = new MLFile(); // Inicializa el contenido tokenizer.Init(text); // Interpreta el archivo fileML.Nodes.Add(ParseNode("Root", tokenizer, true)); // Devuelve el archivo return(fileML); }
/// <summary> /// Interpreta un texto /// </summary> public MLFile ParseText(string strText) { ParserTokenizer objTokenizer = InitTokenizer(); MLFile objMLFile = new MLFile(); // Inicializa el contenido objTokenizer.Init(strText); // Interpreta el archivo objMLFile.Nodes.Add(ParseNode("Root", objTokenizer, true)); // Devuelve el archivo return(objMLFile); }
/// <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> /// Inicializa el objeto de creación de tokens /// </summary> private ParserTokenizer InitTokenizer() { ParserTokenizer tokenizer = new ParserTokenizer(); // Asigna los tokens tokenizer.TokensDefinitions.Add(GetTokenDefinition(TokenType.BracketOpen, "{")); tokenizer.TokensDefinitions.Add(GetTokenDefinition(TokenType.BracketClose, "}")); tokenizer.TokensDefinitions.Add(GetTokenDefinition(TokenType.String, "\"", "\"")); tokenizer.TokensDefinitions.Add(GetTokenDefinition(TokenType.Colon, ":")); tokenizer.TokensDefinitions.Add(GetTokenDefinition(TokenType.Comma, ",")); tokenizer.TokensDefinitions.Add(GetTokenDefinition(TokenType.BraceOpen, "[")); tokenizer.TokensDefinitions.Add(GetTokenDefinition(TokenType.BraceClose, "]")); tokenizer.TokensDefinitions.Add(GetTokenDefinition(TokenType.True, "true")); tokenizer.TokensDefinitions.Add(GetTokenDefinition(TokenType.False, "false")); tokenizer.TokensDefinitions.Add(GetTokenDefinition(TokenType.Null, "null")); tokenizer.TokensDefinitions.Add((int)TokenType.Numeric, "Numeric"); // Devuelve el objeto de creación de tokens return(tokenizer); }
/// <summary> /// Obtiene los datos del siguiente token /// </summary> private void GetNextToken(ParserTokenizer tokenizer) { _actualToken = tokenizer.GetToken(); _idActualType = GetIDType(_actualToken); }
/// <summary> /// Interpreta los nodos de un array /// </summary> private MLNode ParseNodesArray(ParserTokenizer tokenizer) { return(ParseNodesArray("Array", tokenizer)); }
/// <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); } } } }
/// <summary> /// Obtiene los datos del siguiente token /// </summary> private void GetNextToken(ParserTokenizer objTokenizer) { objActualToken = objTokenizer.GetToken(); intIDActualType = GetIDType(objActualToken); }