private Expresion AnalizarExpresionAritmeticaPrimaria(Token tipoDeDato)
        {
            if (TokenActual.Tipo == TipoSintaxis.TokenParentesisApertura)
            {
                var izquierda = CoincideCon(TipoSintaxis.TokenParentesisApertura);
                var expresion = AnalizarExpresionAritmetica(tipoDeDato);
                var derecha   = CoincideCon(TipoSintaxis.TokenParentesisCierre);
                return(new ExpresionEnParentesis(izquierda, expresion, derecha));
            }

            var tokenNumero = SiguienteToken();

            if (tokenNumero.Tipo is TipoSintaxis.TokenInteger && tipoDeDato.Tipo == TipoSintaxis.IntegerKeyword)
            {
                return(new ExpresionEntera(tokenNumero));
            }
            else if (tokenNumero.Tipo is TipoSintaxis.TokenDecimal && tipoDeDato.Tipo == TipoSintaxis.IntegerKeyword)
            {
                var token = new Token(tokenNumero.Tipo, tokenNumero.Position, tokenNumero.Text, (int)float.Parse(tokenNumero.Value.ToString()));
                return(new ExpresionEntera(token));
            }
            else if (tokenNumero.Tipo is TipoSintaxis.TokenDecimal && tipoDeDato.Tipo == TipoSintaxis.FloatKeyword)
            {
                return(new ExpresionDecimal(tokenNumero));
            }
            else if (tokenNumero.Tipo is TipoSintaxis.TokenInteger && tipoDeDato.Tipo == TipoSintaxis.FloatKeyword)
            {
                var token = new Token(tokenNumero.Tipo, tokenNumero.Position, tokenNumero.Text, (float)int.Parse(tokenNumero.Value.ToString()));
                return(new ExpresionDecimal(token));
            }
            else if (tokenNumero.Tipo is TipoSintaxis.Identificador)
            {
                var identificador = tokenNumero;
                if (TablaSimbolos.ContainsKey(identificador.Value.ToString()))
                {
                    var variable = (Token)TablaSimbolos[identificador.Value.ToString()];
                    if (variable.Tipo is TipoSintaxis.TokenInteger ||
                        variable.Tipo is TipoSintaxis.TokenDecimal)
                    {
                        return(new ExpresionIdentificador(tokenNumero));
                    }
                    else
                    {
                        _diagnostics.Add($"ERROR: Se variable de tipo invalido, se esperaba tipo <{variable.Tipo}>");
                        return(new ExpresionIdentificador(new Token(TipoSintaxis.Identificador, _position, null, null)));
                    }
                }
                else
                {
                    _diagnostics.Add($"ERROR: Identificador <{identificador}> no existe en el ambito actual.");
                    return(new ExpresionNumericaInvalida(new Token(TipoSintaxis.TokenNumericoInvalido, _position, null, null)));
                }
            }

            _diagnostics.Add($"ERROR: Variable de tipo invalido, se esperaba valor numerico.");
            return(new ExpresionNumericaInvalida(new Token(TipoSintaxis.TokenNumericoInvalido, _position, null, null)));
        }
        private Expresion AnalizarExpresionDeDeclaracion()
        {
            var tokenTipoDato      = SiguienteToken();
            var tokenIdentificador = CoincideCon(TipoSintaxis.Identificador);

            if (TablaSimbolos.ContainsKey(tokenIdentificador.Value.ToString()))
            {
                _diagnostics.Add($"ERROR: Multiple declarations of variable <{tokenIdentificador.Value.ToString()}>");
            }
            var equalsToken = CoincideCon(TipoSintaxis.TokenIgual);

            Expresion expresion = null;

            if (tokenTipoDato.Tipo.Equals(TipoSintaxis.IntegerKeyword) ||
                tokenTipoDato.Tipo.Equals(TipoSintaxis.FloatKeyword) ||
                tokenTipoDato.Tipo.Equals(TipoSintaxis.LongKeyword) ||
                tokenTipoDato.Tipo.Equals(TipoSintaxis.DoubleKeyword))
            {
                expresion = AnalizarExpresionAritmetica(tokenTipoDato);

                // If expresion is not an arithmetic expresion, then is invalid.
            }

            else if (tokenTipoDato.Tipo.Equals(TipoSintaxis.BoolKeyword))
            {
                expresion = AnalizarExpresionLogica();
            }
            else if (tokenTipoDato.Tipo.Equals(TipoSintaxis.CharKeyword))
            {
                expresion = AnalizarExpresionChar();
            }
            else if (tokenTipoDato.Tipo.Equals(TipoSintaxis.StringKeyword))
            {
                expresion = AnalizarExpresionString();
            }

            if (tokenTipoDato.Tipo == TipoSintaxis.IntegerKeyword)
            {
                TablaSimbolos[tokenIdentificador.Value.ToString()] =
                    new Token(TipoSintaxis.TokenInteger, tokenIdentificador.Position, tokenIdentificador.Value.ToString(), expresion);
            }
            else if (tokenTipoDato.Tipo == TipoSintaxis.FloatKeyword)
            {
                TablaSimbolos[tokenIdentificador.Value.ToString()] =
                    new Token(TipoSintaxis.TokenDecimal, tokenIdentificador.Position, tokenIdentificador.Value.ToString(), expresion);
            }
            else if (tokenTipoDato.Tipo == TipoSintaxis.StringKeyword)
            {
                TablaSimbolos[tokenIdentificador.Value.ToString()] =
                    new Token(TipoSintaxis.TokenString, tokenIdentificador.Position, tokenIdentificador.Value.ToString(), expresion);
            }

            var semicolonToken = CoincideCon(TipoSintaxis.TokenPuntoyComa);

            return(new ExplresionDeclaracion(tokenTipoDato, tokenIdentificador, equalsToken, expresion, semicolonToken));
        }
        public Token EvaluarExpresionString(Expresion nodo)
        {
            if (nodo is ExpresionString n)
            {
                string valor       = n.Valor.Value.ToString();
                var    tokenString = new Token(TipoSintaxis.TokenInteger, 0, valor, valor);
                return(tokenString);
            }

            if (nodo is ExpresionIdentificador id)
            {
                var identificador = id.Identificador;
                var tokenString   = (TablaSimbolos[identificador.Value.ToString()] as Token).Value;

                if (!TablaSimbolos.ContainsKey(identificador.Value.ToString()))
                {
                    Diagnostico.Add($"ERROR: Variable no declarada <{identificador}>");
                }
                else if (!(tokenString is null))
                {
                    return(new Token(TipoSintaxis.TokenString, 0, tokenString.ToString(), tokenString.ToString()));
                }

                // Invalid string
                return(null);
            }


            if (nodo is ExpresionBinaria b)
            {
                var izquierda = EvaluarExpresionString(b.Izquierda);
                var derecha   = EvaluarExpresionString(b.Derecha);

                if (b.Operador.Tipo == TipoSintaxis.TokenMas)
                {
                    string result = izquierda.Value.ToString() + derecha.Value.ToString();
                    return(new Token(TipoSintaxis.TokenString, 0, result, result));
                }

                else
                {
                    throw new Exception($"Operador binario inesperado: {b.Operador.Tipo}");
                }
            }

            if (nodo is ExpresionEnParentesis p)
            {
                return(EvaluarExpresionString(p.Expresion));
            }

            throw new Exception($"Nodo inesperado {nodo.Tipo}");
        }
        private Expresion AnalizarExpresionStringPrimaria()
        {
            if (TokenActual.Tipo == TipoSintaxis.TokenParentesisApertura)
            {
                var izquierda = CoincideCon(TipoSintaxis.TokenParentesisApertura);
                var expresion = AnalizarExpresionString();
                var derecha   = CoincideCon(TipoSintaxis.TokenParentesisCierre);
                return(new ExpresionEnParentesis(izquierda, expresion, derecha));
            }

            var tokenString = SiguienteToken();

            if (tokenString.Tipo is TipoSintaxis.TokenString)
            {
                return(new ExpresionString(tokenString));
            }
            else if (tokenString.Tipo is TipoSintaxis.Identificador)
            {
                var identificador = tokenString;
                if (TablaSimbolos.ContainsKey(identificador.Value.ToString()))
                {
                    var variable = (Token)TablaSimbolos[identificador.Value.ToString()];
                    if (variable.Tipo is TipoSintaxis.TokenString)
                    {
                        return(new ExpresionIdentificador(tokenString));
                    }
                    else
                    {
                        _diagnostics.Add($"ERROR: Se variable de tipo invalido, se esperaba tipo <{variable.Tipo}>");
                        return(new ExpresionIdentificador(new Token(TipoSintaxis.Identificador, _position, null, null)));
                    }
                }
            }

            _diagnostics.Add($"ERROR: Variable de tipo invalido, se esperaba string.");
            return(new ExpresionStringInvalida(new Token(TipoSintaxis.TokenNumericoInvalido, _position, null, null)));
        }
        public Token EvaluarExpresionAritmetica(Expresion nodo, TipoSintaxis tipo)
        {
            if (nodo is ExpresionNumericaInvalida invalidExpression)
            {
                return(new Token(TipoSintaxis.TokenInvalido, 0, null, null));
            }

            if (nodo is ExpresionEntera n)
            {
                int valor       = Convert.ToInt32((Convert.ToDouble(n.Numero.Value)));
                var tokenEntero = new Token(TipoSintaxis.TokenInteger, 0, valor.ToString(), valor);
                return(tokenEntero);
            }

            //if (nodo is ExpresionEntera n)
            //{
            //    int valor = Convert.ToInt32((Convert.ToDouble(n.Numero.Value)));
            //    var tokenEntero = new Token(TipoSintaxis.TokenInteger, 0, valor.ToString(), valor);
            //    return tokenEntero;
            //}


            if (nodo is ExpresionDecimal nd)
            {
                float valor        = (float)nd.Numero.Value;
                var   tokenDecimal = new Token(TipoSintaxis.TokenDecimal, 0, valor.ToString(), valor);
                return(tokenDecimal);
            }

            if (nodo is ExpresionIdentificador id)
            {
                var identificador = id.Identificador;
                var tokenNumero   = (TablaSimbolos[identificador.Value.ToString()] as Token).Value;

                if (!TablaSimbolos.ContainsKey(identificador.Value.ToString()))
                {
                    Console.WriteLine($"ERROR: Variable no declarada <{identificador}>");
                    Diagnostico.Add($"ERROR: Variable no declarada <{identificador}>");
                }
                else if (!(tokenNumero is null))
                {
                    var stringData = tokenNumero.ToString();
                    // if contains a dot, then is decimal.
                    if (stringData.Contains("."))
                    {
                        float.TryParse(stringData, out var val);
                        return(new Token(TipoSintaxis.TokenDecimal, 0, val.ToString(), val));
                    }

                    int.TryParse(stringData, out var value);
                    return(new Token(TipoSintaxis.TokenInteger, 0, value.ToString(), value));
                }

                // Invalid number
                return(null);
            }


            if (nodo is ExpresionBinaria b)
            {
                var izquierda = EvaluarExpresionAritmetica(b.Izquierda, tipo);
                var derecha   = EvaluarExpresionAritmetica(b.Derecha, tipo);

                if (b.Operador.Tipo == TipoSintaxis.TokenMas)
                {
                    if (izquierda.Tipo is TipoSintaxis.TokenInteger &&
                        derecha.Tipo is TipoSintaxis.TokenInteger)
                    {
                        int result = int.Parse(izquierda.Value.ToString()) + int.Parse(derecha.Value.ToString());
                        return(new Token(TipoSintaxis.TokenInteger, 0, result.ToString(), result));
                    }
                    if (izquierda.Tipo is TipoSintaxis.TokenDecimal ||
                        derecha.Tipo is TipoSintaxis.TokenDecimal)
                    {
                        float result = float.Parse(izquierda.Value.ToString()) + float.Parse(derecha.Value.ToString());
                        return(new Token(TipoSintaxis.TokenInteger, 0, result.ToString(), result));
                    }
                }

                else if (b.Operador.Tipo == TipoSintaxis.TokenMenos)
                {
                    if (izquierda.Tipo is TipoSintaxis.TokenInteger &&
                        derecha.Tipo is TipoSintaxis.TokenInteger)
                    {
                        int result = int.Parse(izquierda.Value.ToString()) - int.Parse(derecha.Value.ToString());
                        return(new Token(TipoSintaxis.TokenInteger, 0, result.ToString(), result));
                    }
                    if (izquierda.Tipo is TipoSintaxis.TokenDecimal ||
                        derecha.Tipo is TipoSintaxis.TokenDecimal)
                    {
                        float result = float.Parse(izquierda.Value.ToString()) - float.Parse(derecha.Value.ToString());
                        return(new Token(TipoSintaxis.TokenInteger, 0, result.ToString(), result));
                    }
                }

                else if (b.Operador.Tipo == TipoSintaxis.TokenMultiplicacion)
                {
                    if (izquierda.Tipo is TipoSintaxis.TokenInteger &&
                        derecha.Tipo is TipoSintaxis.TokenInteger)
                    {
                        int result = int.Parse(izquierda.Value.ToString()) * int.Parse(derecha.Value.ToString());
                        return(new Token(TipoSintaxis.TokenInteger, 0, result.ToString(), result));
                    }
                    if (izquierda.Tipo is TipoSintaxis.TokenDecimal ||
                        derecha.Tipo is TipoSintaxis.TokenDecimal)
                    {
                        float result = float.Parse(izquierda.Value.ToString()) * float.Parse(derecha.Value.ToString());
                        return(new Token(TipoSintaxis.TokenInteger, 0, result.ToString(), result));
                    }
                }
                else if (b.Operador.Tipo == TipoSintaxis.TokenDivision)
                {
                    if (izquierda.Tipo is TipoSintaxis.TokenDecimal ||
                        derecha.Tipo is TipoSintaxis.TokenDecimal)
                    {
                        float result = float.Parse(izquierda.Value.ToString()) / float.Parse(derecha.Value.ToString());
                        return(new Token(TipoSintaxis.TokenInteger, 0, result.ToString(), result));
                    }
                }
                else if (b.Operador.Tipo == TipoSintaxis.TokenPotencia)
                {
                    if (izquierda.Tipo is TipoSintaxis.TokenDecimal ||
                        derecha.Tipo is TipoSintaxis.TokenDecimal)
                    {
                        float result = float.Parse(izquierda.Value.ToString()) + float.Parse(derecha.Value.ToString());
                        return(new Token(TipoSintaxis.TokenInteger, 0, result.ToString(), result));
                    }
                }
                else if (b.Operador.Tipo == TipoSintaxis.TokenModulo)
                {
                    if (izquierda.Tipo is TipoSintaxis.TokenInteger &&
                        derecha.Tipo is TipoSintaxis.TokenInteger)
                    {
                        int result = int.Parse(izquierda.Value.ToString()) % int.Parse(derecha.Value.ToString());
                        return(new Token(TipoSintaxis.TokenInteger, 0, result.ToString(), result));
                    }
                    if (izquierda.Tipo is TipoSintaxis.TokenDecimal ||
                        derecha.Tipo is TipoSintaxis.TokenDecimal)
                    {
                        float result = float.Parse(izquierda.Value.ToString()) % float.Parse(derecha.Value.ToString());
                        return(new Token(TipoSintaxis.TokenInteger, 0, result.ToString(), result));
                    }
                }
                else
                {
                    throw new Exception($"Operador binario inesperado: {b.Operador.Tipo}");
                }
            }

            if (nodo is ExpresionEnParentesis p)
            {
                return(EvaluarExpresionAritmetica(p.Expresion, tipo));
            }

            throw new Exception($"Nodo inesperado {nodo.Tipo}");
        }