¿Cómo hacer un intérprete de ecuaciones matemáticas en QuickBASIC? Parte 3
¿Cómo hacer un intérprete de ecuaciones matemáticas en QuickBASIC? Parte 3

Imagen generada usando Bing Image Creator
Para ver la segunda parte de este artículo puedes usar este enlace: Parte 2
Introducción
En la parte anterior de este texto, estuvimos hablando de la importancia de definir la gramática de una expresión matemática para utilizarla como punto de partida para implementar un intérprete de ecuaciones, y terminamos definiendo dicha gramática como se expone a continuación:
<expression> ::= <term> [<add_op> <term>]*
<term> ::= <factor> [<mul_op> <factor>]*
<factor> ::= <number> | (<expression>) | <identifier> | <function> | <signed_factor>
Pero como también se comentó, esta representación más bien básica de la gramática expuesta en notación BNF, adolece de la falta de algunos detalles importantes para permitir una más precisa implementación del analizador lexicográfico.
En esta parte del tutorial terminaremos de definir la gramática de una expresión matemática.
La gramática de una expresión matemática en más detalle
En nuestra definición de gramática tenemos una descripción de una expresión (<expression>), un término (<term>), y un factor (<factor>), y la relación recursiva entre ellos. En esas definiciones la más incompleta es la de factor, si bien en la definición de expresión se usa un símbolo <add_op> y en la de término otro símbolo denominado <mul_op>.
En su momento se comentó como <add_op> consistía en los operadores matemáticos para la suma y la resta y por tanto su representación puede ser:
<add_op> ::= '+' | '-'
Del mismo modo la representación de <mul_op> es tan sencilla como:
<mul_op> ::= '*' | '/'
En este momento por lo tanto sólo nos falta definir <number>, <identifier>, <function>, y <signed_factor>.
La definición de <number>
En particular un número podría ser un entero o más bien ser real, y en adición podría estar escrito usando una notación especial como la notación exponencial o científica; todo esto debe estar expresado en la gramática para como se ha dicho un número sea reconocido correctamente por el analizador lexicográfico, si bien nosotros vamos a escribir nuestro analizador manualmente.
El caso del número entero puede denotarse como (caso más sencillo):
<number> ::= [<digit>]+
donde <digit> significa un dígito de "0" a "9" y "+" significa uno a más de estos dígitos:
<digit> ::= '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'
En este caso se estaría definiendo un número entero solamente y esto podríamos hacerlo de forma más detallada:
<integer> ::= [<digit>]+
El caso de un número real sería representado como:
<float> ::= <integer> . <integer>
Por eso un número tanto entero como real sería representado como:
<number> ::= <integer> | <float>
Los números también pueden tener un signo delante y si tenemos en cuenta eso la representación sería:
<integer_with_sign> ::= [ + | - ] <integer>
<float_with_sign> ::= [ + | - ] <integer> . <integer>
<number> ::= <integer_with_sign> | <float_with_sign>
Por fin, si deseamos reconocer números en notación exponencial, la representación sería:
<number> ::= <integer_with_sign> | <float_with_sign> | <float_with_sign> <exponent>
<exponent> ::= E <integer_with_sign> | e <integer_with_sign>
La definición de <identifier>
Por su parte, como vimos antes, un identificador puede ser una variable, o una constante, como mismo puede ser una palabra reservada del lenguaje de programación.
En nuestro caso, como no se trata de una gramática de un lenguaje de programación, y no vamos a utilizar constantes, un identificador será interpretado como una variable, si bien una función también puede ser un identificador terminado con paréntesis entre los cuales se define la lista de parámetros.
Por eso, dado un identificador pueden ser muchas cosas, en algunos lenguajes de programación se obliga a declarar previamente las variables, o a terminar una llamada a una función con paréntesis vacios a pesar de no pasarle argumentos; todo esto no se hace así por capricho, se hace así simplemente para poder distinguir unas cosas de otras, para eliminar la posible ambigüedad, o luego el analizador lexicográfico podría confundirse.
Nota: Las palabras claves son identificadas por medio de una tabla de símbolos preexistente.
La notación común para un identificador podría ser como esta (en algunos lenguajes están permitidos otros símbolos como "_"):
<identifier> ::= <letter> [<letter> | <digit>]*
Pero como seguro saben, en casi todos los lenguajes de programación comunes, un identificador como un nombre de una variable o de una función también está limitado en cuanto a su extensión.
En nuestro caso no vamos a tener en cuenta esto último de la extensión, ni vamos a definir <letter>, puesto como es fácil de suponer se trata de un carácter alfabético.
La definición de <function>
La definición de una función es bastante sencilla, como se ha dicho antes se trata de un identificador seguido de paréntesis para contener la lista de parámetros:
<function> ::= <identifier>(<parameters>)
<parameters> ::= ε | <expression> [, <expression> ]*
Nota: ε significa "vacío" (para funciones sin argumentos).
Las funciones pueden ser intrínsecas o definidas por el programador, nosotros nada más usaremos funciones intrínsecas, y en este caso lo común es reconocerlas como a las palabras reservadas del lenguaje buscando en una tabla de símbolos predefinida.
La definición de <signed_factor>
Por último nos faltaría la definición de un factor con signo, lo cual también es bastante sencillo de representar:
<signed_factor> ::= [ + | - ] <factor>
En este punto tenemos la definición bastante completa de la gramática de una expresión matemática, salvo por algún detalle no imprescindible para implementar nuestro intérprete de ecuaciones matemáticas.
En la próxima parte podremos por tanto utilizar toda la gramática definida como lo hemos hecho y por fin empezar a escribir código implementando el analizador lexicográfico en QuickBASIC.
¿Qué te ha parecido esta tercera parte?
Tú participación aportando ideas, dando sugerencias, o expresando tu crítica constructiva a través de tus comentarios, es importante y fundamental para permitirnos crecer y crear contenidos con cada vez más calidad.
También es importante tu voto si crees vale la pena concederlo.
¡Nos vemos en la siguiente parte de este artículo tutorial!
Congratulations @retrotech-cuba! You have completed the following achievement on the Hive blockchain And have been rewarded with New badge(s)
Your next target is to reach 50 upvotes.
You can view your badges on your board and compare yourself to others in the Ranking
If you no longer want to receive notifications, reply to this comment with the word
STOPCheck out our last posts: