Dada la cantidad de material que trata de explicar qué es una gramática libre de contexto (CFG), me pareció sorprendente que muy pocos (en mi muestra, menos de 1 en 20) den una explicación de por qué esas gramáticas se llaman "contexto- gratis". Y, en mi opinión, ninguno logra hacerlo.
Mi pregunta es, ¿por qué las gramáticas sin contexto se llaman sin contexto? ¿Qué es "el contexto"? Tenía la intuición de que el contexto podría ser otras construcciones del lenguaje que rodean la construcción actualmente analizada, pero ese no parece ser el caso. ¿Alguien podría dar una explicación precisa?
Respuestas:
Significa que todas sus reglas de producción tienen un único no terminal en su lado izquierdo.
Por ejemplo, esta gramática que reconoce cadenas de paréntesis coincidentes ("()", "() ()", "(()) ()", ...) no tiene contexto:
El lado izquierdo de cada regla consiste en un único no terminal (en este caso siempre es así
S
, pero podría haber más).Ahora considere esta otra gramática que reconoce cadenas de la forma {a ^ nb ^ nc ^ n: n> = 1} (por ejemplo, "abc", "aabbcc", "aaabbbccc"):
Si el carácter no terminal
B
está precedido por el carácter terminal / literalc
, reescribe ese término,WB
pero si está precedido porb
, en subb
lugar , se expande a . Presumiblemente, esto es a lo que alude la sensibilidad al contexto de las gramáticas sensibles al contexto.Un lenguaje libre de contexto puede reconocerse como un autómata pushdown . Mientras que una máquina de estados finitos no utiliza almacenamiento auxiliar, es decir, su decisión se basa solo en su estado actual y su entrada, un autómata push-down también tiene una pila a su disposición y puede mirar en la parte superior de la pila para tomar decisiones.
Para ver eso en acción, puede analizar paréntesis anidados moviéndose de izquierda a derecha y empujando un paréntesis izquierdo en una pila cada vez que encuentre uno, y haciendo estallar cada vez que encuentre un paréntesis derecho. Si nunca termina intentando saltar de una pila vacía, y la pila está vacía al final de la cadena, la cadena es válida.
Para un lenguaje sensible al contexto, un PDA no es suficiente. Necesitará un autómata con límites lineales que es como una máquina de Turing cuya cinta no es ilimitada (aunque la cantidad de cinta disponible es proporcional a la entrada). Tenga en cuenta que eso describe las computadoras bastante bien: nos gusta pensar en ellas como máquinas de Turing, pero en el mundo real no puede tomar arbitrariamente más RAM a mitad del programa. Si no es obvio para usted cómo un LBA es más poderoso que un PDA, un LBA puede emular un PDA utilizando parte de su cinta como una pila, pero también puede elegir usar su cinta de otras maneras.
(Si se pregunta qué puede reconocer una máquina de estados finitos, la respuesta son las expresiones regulares. Pero no las expresiones regulares de los esteroides con grupos de captura y mirar hacia atrás / mirar hacia adelante que ve en los lenguajes de los programas; me refiero a los que puede construir con operadores como
[abc]
,|
,*
,+
, y?
. Se puede ver que lasabbbz
coincidencias de expresiones regularesab*z
con sólo mantener su posición actual en la cuerda y expresiones regulares, sin pila necesaria.)fuente
Las otras respuestas son bastante largas, incluso si son precisas y correctas. Esta es la version corta.
Si tiene una cadena de caracteres (terminales y no terminales) y desea reemplazar un no terminal en la cadena, una gramática libre de contexto le permite hacerlo independientemente de los caracteres que rodean al no terminal.
Considere las siguientes reglas (las minúsculas son terminales, las mayúsculas son no terminales):
En la primera regla, puede reemplazar un
A
independientemente de lo que aparezca a su alrededor (contexto). En la segunda regla, no puede reemplazar aA
menos que sea seguido porB
. Si bien ambos no terminales serán reemplazados en ese caso, el punto importante es que los no terminales que rodean elA
asunto. No se puede reemplazarBA
cona
, oB
cona
: solo unA
seguido de aB
porque el orden, el contexto de los no terminales es importante. Esto significa que el contexto de un asunto no terminal en la segunda regla, lo hace sensible al contexto, mientras que la primera regla está libre de contexto.fuente
a
partir deAB
menosA
es seguido porB
lugar de decir 'no se puede reemplazarA
' que podría no ser posible debido a que en realidad va a reemplazarAB
no es ¿verdad?A
oAB
en la segunda regla (sensible al contexto)? Creo que todavía estás tratando de reemplazarA
como se dice en tu respuesta.Para comprender mejor la distinción y la terminología, es una buena idea contrastar un lenguaje sin contexto como a n b n con un lenguaje sensible al contexto como a n b n c n . (Notación: a, byc son literales aquí y el exponente n significa repetir el literal n veces, n > 0, por ejemplo). Por ejemplo,
aabbc
oaabbbcc
no está en el último idioma, mientrasaabbcc
que sí.Un aceptador para el lenguaje sin contexto a n b n puede contraer un par
a
eb
independientemente de lo que lo rodea (es decir, independientemente del contexto en el que aparece ab) y funcionará correctamente, aceptando solo cadenas en el idioma y rechazando cualquier otra cosa, es decir, la gramática esS -> aSb | ab
. Tenga en cuenta que no hay terminales en el lado izquierdo de la producción . (Hay dos reglas de producción, pero las estamos escribiendo de manera compacta). El aceptador básicamente puede tomar una decisión local y sin contexto.Por el contrario, no puede hacer algo así para el lenguaje sensible al contexto a n b n c n , porque para esto último debe recordar de alguna manera el contexto en el que se encontraba, es decir, cuántas contracciones de ab hace para que coincidan con las contracciones. de bc. Una gramática para el último idioma es
Tenga en cuenta que tiene terminales y no terminales a la izquierda en las últimas dos reglas. Los terminales de la izquierda son el contexto en el que se pueden expandir los no terminales.
Bootnote con respecto a la terminología de "contrato" frente a "expandir", etc .: aunque las gramáticas formales son [formalmente, ja] generativas, la forma en que realmente se implementan en los analizadores es en realidad reduccionista, es decir, usted contacta todo a un no terminal, básicamente aplicar las reglas "al revés", por lo que incluso la primera gramática dada anteriormente no es práctica en un programa (le daría el famoso conflicto de reducción de turno porque no puede decidir qué regla aplicar), pero las dos anteriores las gramáticas son suficientes para ilustrar la distinción entre libre de contexto y sensible al contexto. El tema de la ambigüedad en las gramáticas libres de contexto es bastante complicado, y no es realmente el tema de esta pregunta, por lo que no voy a decir más aquí, especialmente porque resulta que Wikipedia tiene un artículo decente sobre eso.. En contraste, sus artículos sobre el contexto libre y especialmente el lenguaje sensible al contexto son! @ # $ @! # $ Especialmente si eres nuevo en el tema ... Supongo que eso está más en mi lista TODO.
fuente
Las respuestas anteriores dan una muy buena definición de lo que es. Veamos si puedo expresarlo con mis propias palabras, para que tenga 23 explicaciones en lugar de 20. El propósito completo de una gramática, cualquier gramática, es averiguar si una oración en particular es una oración en el idioma dado. Sin embargo, para lo que realmente utilizamos las gramáticas y el análisis es averiguar qué significa la oración. Es como la antigua diagramación de una oración que puedes haber hecho o no en la clase de inglés en la escuela. Una oración está hecha de una parte sujeto y una parte predicada, una parte sujeto tiene un sustantivo y quizás algunos adjetivos, una parte predicada tiene un verbo y quizás un sustantivo objeto, con algunos adjetivos más, etc.
Si hubiera una gramática para el inglés (y no creo que la haya, no en el sentido informático), tendría reglas de la siguiente forma, llamadas producciones.
etc ...
Luego, podría escribir un programa y entregarle cualquier oración, y el programa podría usar la gramática para descubrir qué parte de la oración es cada palabra y qué relación tienen entre sí.
Si en cada producción, solo hay una cosa en el lado izquierdo, eso significa que siempre que vea el lado derecho en la oración, se le permite sustituir en el lado izquierdo. Por ejemplo, cada vez que viste un sustantivo de adjetivo, podrías decir "Esa es una Parte de Sujeto" sin prestar atención a nada fuera de esa frase.
Sin embargo, el inglés (incluso la descripción simplificada del inglés que di anteriormente) es sensible al contexto. "Adjetivo sustantivo" no siempre es una SubjectPart, podría ser una NounPhrase en un PredicatePart. Depende del contexto. Expandamos un poco nuestra gramática pseudo-inglesa:
Solo puede hacer un "sustantivo adjetivo" en una ObjectNounPhrase si viene inmediatamente después de una VerbPhrase.
Básicamente, si tiene una producción y puede aplicarla en cualquier momento que desee, sin importar lo que la rodee, no tiene contexto.
Siempre se puede saber si una gramática está libre de contexto fácilmente. Simplemente verifique si hay más de un símbolo en el lado izquierdo de las flechas.
Cualquier lenguaje puede ser descrito por más de una gramática. Si alguna gramática de un idioma no tiene contexto, el idioma no tiene contexto. Se puede demostrar para algunos idiomas que no hay una gramática libre de contexto posible. Supongo que podría haber una gramática libre de contexto para el subconjunto pseudo-inglés simplificado que describo anteriormente.
En cuanto a por qué es importante, requiere un tipo de programa más simple para analizar una gramática libre de contexto. Como se señaló en las otras respuestas, no requiere toda la potencia de una máquina de Turing para analizar una gramática libre de contexto. Un analizador LR (1) de búsqueda anticipada (que es una especie de máquina pushdown) para una gramática particular sin contexto puede analizar cualquier oración en esa gramática en tiempo y espacio lineal a la longitud de la oración. Si la oración está en el idioma, el analizador producirá un árbol de estructura que identifica lo que significa cada símbolo en la oración (o al menos qué papel juega en la estructura). Si la oración no está en la gramática, el analizador notará y se detendrá en el primer símbolo que es imposible de conciliar con la gramática y los símbolos anteriores (en el primer "error").
Lo que es aún mejor es que hay programas a los que puede dar una descripción de una gramática y una lista de instrucciones sobre qué hacer con cada parte (en cierto sentido adjuntando un "significado" a cada producción) y el programa escribirá el analizador para ti. El programa analizará la oración, encontrará la estructura y ejecutará sus instrucciones en cada parte de la estructura. Este tipo de programa se llama generador de analizadores o compilador-compilador.
Este tipo de análisis del lenguaje fue inventado para el análisis automático del lenguaje natural (como el inglés), pero resulta que esto es muy útil para analizar lenguajes de computadora. Un diseñador de idiomas puede escribir una gramática que capture su nuevo idioma, luego ejecutarlo a través del generador de analizadores para obtener un programa que analice su idioma y traduzca, interprete, compile, ejecute, etc. si lo desea.
De hecho, en la mayoría de los casos realmente no puedes hacer esto. Por ejemplo, los paréntesis equilibrados son un lenguaje libre de contexto, pero un lenguaje donde se requiere declarar todas las variables antes de usarlas es sensible al contexto. El analizador es parte del compilador, pero se requiere lógica adicional para hacer cumplir estos otros requisitos. Lo que debe hacer es escribir una gramática que capture la mayor cantidad posible de su idioma, ejecutarla a través de un generador de analizadores, luego escribir código que aplique el resto de los requisitos (controlador de tabla de símbolos, etc.).
Por lo general, no usamos gramáticas sensibles al contexto porque son mucho menos compatibles. No sé si hay un equivalente a un generador de analizadores LR (k) para lenguajes sensibles al contexto. Sí, una máquina de Turing (o máquina lineal) puede analizar una, pero no sé si hay un algoritmo general para convertir una gramática sensible al contexto en un programa para una máquina de Turing, en el sentido de que un LR (1 ) generador hace tablas de análisis para una máquina pushdown. Mi conjetura es que las tablas que subyacen al analizador serían exponencialmente más grandes. En cualquier caso, a los estudiantes de CS (como yo, en el pasado) generalmente se les enseñan gramáticas libres de contexto y generadores de analizadores LR (1) como YACC.
fuente
Las gramáticas sin contexto no consideran ningún contexto para las reglas de producción. El contexto son terminales o no terminales.
Entonces: las gramáticas libres de contexto solo tienen un único no terminal en el lado izquierdo de las reglas de producción.
fuente