¿Qué significa "sin contexto" en el término "gramática sin contexto"?

55

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?

almiar
fuente
44
busque el "análisis más desconcertante" para C ++ que le enseñará por qué la libertad de contexto es útil
freak
66
Pensé que sabía lo que era una gramática sin contexto hasta que acabo de leer algunas definiciones en Google. Ahora desearía tener un grabado al aguafuerte y un blanco suave ... tal vez salga afuera ... +1 por una buena pregunta. Esperamos algunas respuestas inteligibles!
BrianH
Su intuición es lo que entiendo, incluso si la definición formal de "otras construcciones de lenguaje que rodean la construcción actualmente analizada" es adecuadamente arcana. Pero no estoy lo suficientemente seguro como para publicar eso como respuesta.
Telastyn
1
Vea wikipages sobre gramática libre de contexto y jerarquía de Chomsky . En la práctica, el análisis del lenguaje de programación tiene algún contexto, a menudo manejado "fuera" del análisis "sin contexto" (LR o LL), por ejemplo, mediante alguna tabla de símbolos, atributos o entorno
Basile Starynkevitch
1
Aquí, tenga una referencia de xkcd: xkcd.com/1090
CaptainCodeman

Respuestas:

60

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:

S → SS
S → (S)
S → ()

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"):

S  → abc
S  → aSBc
cB → WB
WB → WX
WX → BX
BX → Bc
bB → bb

Si el carácter no terminal Bestá precedido por el carácter terminal / literal c, reescribe ese término, WBpero si está precedido por b, en su bblugar , 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 las abbbzcoincidencias de expresiones regulares ab*zcon sólo mantener su posición actual en la cuerda y expresiones regulares, sin pila necesaria.)

Doval
fuente
14
Muy buena explicación. Sin embargo, la cinta de una máquina de Turing no necesita ser infinita, solo ilimitada. Puede haber una fábrica de cintas en cada extremo que, cuando la máquina se topa con ella, simplemente hace más cinta. De esa manera, en cualquier momento, es finito.
Mike Dunlavey
2
@ MikeDunlavey Gracias por la aclaración, lo arregló.
Doval
10
Pero la fábrica de cintas necesitaría materiales de fabricación de cintas infinitas, o materiales de fabricación de cintas infinitas, o ... [desbordamiento de pila]
flamingpenguin
8
@Mehrdad: puede simular cualquier cantidad de pilas usando dos pilas: mantenga todas las pilas apiladas una encima de la otra en una pila y cuando necesite acceder a alguna pila más abajo, retire las pilas superiores y empújelas hacia la segunda pila. Esto demuestra que n> 2 acumulaciones no son más poderosas que 2 acumulaciones. Ahora, si 2 pilas son más poderosas que 1 pila, eso no lo sé. Mi intuición dice que no, pero eso podría depender exactamente de cuáles son las primitivas de la pila.
Jörg W Mittag
10
@ JörgWMittag: dos pilas son tan buenas como una cinta. Mano a mano: use una pila como el lado izquierdo de la cinta y la otra pila como el lado derecho, en relación con su posición actual. Entonces, un 2-PDA es una máquina de Turing. Para las primitivas solo necesita poder extraer un valor de una pila y empujarlo a la otra, que es cómo se mueve a lo largo de su cinta.
Steve Jessop
20

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):

A -> a
AB -> a

En la primera regla, puede reemplazar un A independientemente de lo que aparezca a su alrededor (contexto). En la segunda regla, no puede reemplazar a Amenos que sea seguido por B. Si bien ambos no terminales serán reemplazados en ese caso, el punto importante es que los no terminales que rodean el Aasunto. No se puede reemplazar BAcon a, o Bcon a: solo un Aseguido de a Bporque 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
Esta es una muy buena explicación, aunque no estoy calificado para dar fe de su precisión o integridad. ¿Es todo lo que hay que hacer?
Rick
1
Las gramáticas informáticas son parte de la jerarquía de Chomsky . Ese artículo es un buen lugar para comenzar. Además, este tema debería formar parte de cualquier programa de bachillerato en informática. Por lo menos, las universidades deberían enseñar gramáticas regulares y libres de contexto, ya que estas comprenden la abrumadora mayoría de los idiomas que los programadores probablemente encontrarán.
@Snowman: Muy crisp.It sería mejor si usted dice que" no se puede derivar a apartir de ABmenos Aes seguido por Blugar de decir 'no se puede reemplazar A' que podría no ser posible debido a que en realidad va a reemplazar ABno es ¿verdad?
Justin
@justin correcto. Actualicé mi respuesta para ser más claro al respecto.
@Snowman: ¿Te refieres a reemplazar Ao ABen la segunda regla (sensible al contexto)? Creo que todavía estás tratando de reemplazar Acomo se dice en tu respuesta.
justin
7

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, aabbco aabbbccno está en el último idioma, mientras aabbccque sí.

Un aceptador para el lenguaje sin contexto a n b n puede contraer un par ae bindependientemente 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 es S -> 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

S -> abc | aBSc
Ba -> aB
Bb -> bb

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.

Efervescencia
fuente
5

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.

Sentence -> SubjectPart PredicatePart
SubjectPart -> Adjective Noun

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:

Sentence -> SubjectPart PredicatePart
SubjectPart -> Adjective Noun
PredicatePart -> VerbPhrase ObjectNounPhrase
VerbPhrase ObjectNounPhrase -> VerbPhrase Adjective Noun

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.

kwan3217
fuente
-1

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.

Martin Thoma
fuente
3
¿Qué agrega esto a las respuestas existentes? Además, una regla de producción con dos o más no terminales en el lado izquierdo tampoco está libre de contexto.
Creo que las respuestas dadas son demasiado largas. Si uno agregaría un TL; DR, eliminaría este.
Martin Thoma
¡Agradable! ¿Diría que el "contexto" son los caracteres adicionales que califican cuando se puede aplicar cada regla de producción?
Rick