Durante una conferencia de la UNESCO sobre el lenguaje de programación ALGOL 58 el matemático John Backus presento un informe en el que describía bajo una notación formal dicho lenguaje.
Cuando Peter Naur leyó el informe realizo una serie de cambios respecto de la formalización propuesta por Backus que fue presentada en su informe para el ALGOL60. Esta última notación formal es la que hoy en día se emplea y se conoce como BNF.
1959: Se describe un método de parsing de FORTRAN que introducía paréntesis adicionales alrededor de los operandos para ser capaz de analizar las expresiones.
1960: Se desarrollan los diversos métodos de parsers ascendentes y descendentes
1961: Se realiza el uso por primera vez de un parsing descendente recursivo.
1965: Se define las gramáticas LR y describe la construcción de una tabla canónica de parser LR.
1968: Se estudian y definen las gramáticas LL así como los parsers predictivos
1970: Se describen los métodos SLR y LALR de parser LR. Debido a su sencillez y a su capacidad de análisis para una gran variedad de lenguajes, la técnica de parsing LR va a ser la elegida para los generadores automáticos de parsers.
1975: Se crea el generador de analizadores sintácticos YACC para funcionar bajo un entorno UNIX . Junto al análisis sintáctico, también se fuedesarrollando el análisis semántico.
un metalenguaje es un lenguaje que se usa
para hablar acerca de otro lenguaje.
1*
[*] También de Wikipedia ;)
es una estructura matemática con un conjunto de reglas de formación que definen las cadenas de caracteres admisibles en un determinado lenguaje formal en la que cada regla de producción tiene la forma:
Donde V es un símbolo no terminal y w es una cadena de terminales y/o no terminales
2*
::=
|
'if', '5'
<oración> ::= <sujeto> <predicado>
<sujeto> ::= Juan | Julia
<predicado> ::= <verbo> <adverbio>
<verbo> ::= maneja | corre
<adverbio> ::= descuidadamente | rápido | frecuentemente
<número-decimal> ::= <entero-sin-signo> | <fracción-decimal>
<fracción-decimal> ::= <entero-sin-signo> . <fracción-decimal> |
<fracción-decimal>
<entero-sin-signo> ::= <dígito> | <dígito> <entero-sin-signo>
<dígito> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9
La figura muestra un árbol de deducción, en esta gramática, del número decimal 23.14. Observe que el enunciado BNF es recursivo en la segunda parte de su lado derecho y también es normal.
En general, se sabe que muchas gramáticas diferentes pueden producir el mismo lenguaje.
Para una cadena terminal hay más de un árbol sintáctico
<expr> ::= x | y | z | (<expr>) | <expr> + <expr> | <expr> * <expr>
(recursión a izquierda y derecha para un mismo símbolo no-term.)
Dos árboles sintácticos para la cadena x + y * z :
Ejemplo de uso de la notación BNF para la descripción de un lenguaje de programación
<Programa> ::= <ListaDeFunciones>
<ListaDeFunciones> ::= <Función> | <ListaDeFunciones> <Función>
<Función> ::= FUNC <Variable> ( <ListaDeParámetros> ) <Sentencia>
<ListaDeParámetros> ::= <ListaDeVariables> | ε
<ListaDeVariables> ::= <Variable> | <ListaDeVariables> , <Variable>
<Variable> ::= <Letra> | <Variable> <Alfanumérico>
<Alfanumércio> ::= <Letra> | <Dígito>
<Letra> ::= a | b | ... | y | z
<Dígito> ::= 0 | 1 | ... | 8 | 9
<Sentencia> ::= <SentenciaDeAsignación> | <SentenciaDeRetorno> |
<SentenciaDeImpresión> | <SentenciaNula> |
<SentenciaCondicional> | <SentenciaWhile> | <Bloque>
<SentenciaDeAsignación> ::= <Variable> := <Expresión>
<Expresión> ::= <Expresión> <OperadorBinario> <Expresión> |
<OperadorUnario> <Expresión> | ( <Expresión> ) | <Entero> |
<Variable> | <Variable> (<ListaDeArgumentos> )
<OperadorBinario> ::= + | - | * | /
<OperadorUnario> ::= -
<Entero> ::= <Dígito> | <Entero> <Dígito>
<ListaDeArgumentos> ::= <ListaDeExpresiones> | ε
<ListaDeExpresiones> ::= <Expresión> | <Expresión> , <ListaDeExpresiones>
<SentenciaDeImpresión> ::= PRINT <ListaDeImpresión>
<ListaDeImpresión> ::= <ElementoDeImpresión> |
<ListaDeImpresión> , <ElementoDeImpresión>
<ElementoDeImpresión> ::= <Expresión> | “<Texto> ”
<Texto> ::= <Carácter> | <Carácter> <Texto>
<Carácter> ::= <CarácterImprimible> | <CarácterEscapado>
<CarácterImprimible> ::= Cualquier carácter ASCII imprimible
<CarácterEscapado> ::= \n
<SentenciaDeRetorno> ::= RETURN <Expresión>
<SentenciaNula> ::= CONTINUE
<SentenciaCondicional> ::= IF <Expresión> THEN <Sentencia> FI |
IF <Expresión> THEN <Sentencia> ELSE <Sentencia> FI
<SentenciaWhile> ::= WHILE <Expresión> DO <Sentencia> DONE
<Bloque> ::= { <ListaDeDeclaraciones> <ListaDeSentencias> }
<ListaDeDeclaraciones> ::= <Declaración> <ListaDeDeclaraciones> | ε
<Declaración> ::= VAR <ListaDeVariables>
<ListaDeSEntencias> ::= <Sentencia> | <ListaDeSentencias> <Sentencia>
G = (N, T, P, S)
N = {identificador, resto, dígito, letra}
T = {a, b, c, . . . , z, 0, 1, 2, 3, . . . , 9}
P = N U T
S = identificador
<identificador> ::= <letra> | <letra> <resto>
<resto> ::= <letra> | <dígito> |
<letra> <resto> | <dígito> <resto>
<resto> ::= a | b | c . . . | z
<dígito> ::= 0 | 1 | 2 | 3 | 4 | 5 | 6| 7 | 8 | 9
De nuevo, se observa que las producciones que aparecen en el enunciado de resto, son recursivos y normales.
Ejemplo: expresión matemática en notación BNF:
---> 4*(3+1)
<expresión> ::= <numero> | (<expresión>) |
<expresión><operador><expresión>
<operador> ::= + | - | * | /
<numero> ::= <digito> | <numero><digito>
<digito> ::= 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0
Representación en diagrama sintáctico:
Nuevos símbolos: