Compilador-LL (1): primer conjunto y siguiente conjunto

Primero (A) es el símbolo inicial o el primer conjunto de símbolos de A

Seguir (A) se refiere al conjunto de símbolos terminales que siguen inmediatamente a la derecha de A en ciertos patrones de oraciones.

Encuentre el primer conjunto y el conjunto siguiente de la siguiente gramática recursiva correcta

Primera línea: Expr → Término Expr '

Segunda línea: Expr' → + Term Expr' | - Term Expr' | ∈

La tercera línea: Término → Factor Término '

Cuarta línea: Término ' → * Término de factor ' | / Término de factor ' | ∈

Línea 5: Factor → ident | num | ( Expr )

First(Factor) = { ident num ( } //Factor → ident | num | ( Expr ) Es obvio con qué empezar
First(Term ') = { * / ∈ } //Mira la línea gramatical donde está Term ' ubicado arriba de la misma manera
Primero(Término) = { ident num ( } //El término comienza con Factor, luego Factor comienza con ident num (
Primero(Expr ') = { + - ∈ } Primero(Expr) = { ident num ( }
//Expr comienza con Term Term está encabezado por Factor y Factor está encabezado por ident num (

//Expr siempre contiene eof como posición inicial y la última línea de la sintaxis que Expr puede seguir)
Follow(Expr) = { eof ) }
//La primera línea de Expr 'puede usarse como final de Expr, luego Expr ' contiene todos los siguientes conjuntos de Expr
//Segundo Expr ' en el lado derecho de la línea como Expr ' terminando Expr ' contiene Expr ' en sí mismo por lo que es inútil
Seguir(Expr ') = { eof ) }
//El término de primera línea aparece antes de Expr ' entonces Follow(Term) contiene First(Expr ') 
//Al mismo tiempo, debido a que Expr 'puede ser ∈, significa que Term puede aparecer como el último de Expr, entonces Follow(Expr) Follow
(Term) = { + - eof )
//La tercera línea puede encontrar que Term ' puede ser el último de Term, por lo que incluir Follow(Term)
//El Term' en el lado derecho de la cuarta línea se usa como Term ' al final de Term ', que contiene el propio Term ', por lo que es inútil
Follow(Term ') = { + - eof ) }
//La tercera línea Factor va seguida de Term ' Así que incluye First(Term ')
//Al mismo tiempo, la tercera línea Término 'puede ser ∈, entonces significa que Factor puede aparecer como el último del Término, por lo que se debe incluir seguir (Término)
Seguir(Factor) = { * / + - eof ) }

⚠️: Todas estas colecciones están equipadas con terminales, es decir, eof, que ya no necesita ser reemplazado en la gramática, representa el símbolo final de la expresión. La primera colección
es muy simple, pero cabe señalar que la siguiente colección

Mire principalmente el contenido en el lado derecho de la flecha gramatical para encontrar la ubicación del símbolo que necesita ser juzgado. Si Al final de la cadena de símbolos, contiene todos los siguientes conjuntos
S → A | B // Necesito encontrar follow(A), luego follow(A) contiene follow(B)

En segundo lugar, si no está al final de la cadena de símbolos, incluye el primer conjunto del siguiente símbolo, pero cabe señalar que si el símbolo inmediatamente siguiente puede ser ∈ en el primer conjunto, significa que el símbolo inmediatamente siguiente puede desaparecer y debe incluirse hacia atrás El primer conjunto del siguiente símbolo hasta que se encuentre un primer conjunto de símbolos que no contenga ∈ Si el primer conjunto de todos los símbolos posteriores está vacío después de recorrerlo, entonces el siguiente conjunto S →ACbS | ∈ a la izquierda de la flecha debe incluirse. //Necesitamos encontrar follow(A
) A es seguido por C, entonces primero(C) está incluido, pero si el conjunto de C primero tiene ∈ 
                              //entonces significa que C puede desaparecerá y será reemplazado por el siguiente b. b es un ternimal, definitivamente no es ∈, por lo que contiene
                              b, por lo que el proceso es Continúe retrocediendo y encuentre que si no hay un primer conjunto vacío, deténgase
                              //Si no ¿No lo encuentras después de atravesarlo? Eso significa que todas las cosas detrás de A pueden desaparecer. El seguimiento de A puede
                              //Es el seguimiento de S en el lado izquierdo de la flecha.

Una gramática es LL(1) si 
        para cada producción 
        \\X \rightarrow \beta _1|\beta _2|....|\beta _n \\First^+(X\rightarrow \beta _i) \cap (X\rightarrow \beta _j) =\oslash \\for 1\leqslant i< j\leqslant n

Definir:
        Primero^+(X\rightarrow \beta _i) = \begin{cases} Primero(\beta _i) & \text{ if } \epsilon \notin Primero(\beta_i)\\ Primero(\beta _i) \cup Seguir( X) & \text{ si } en caso contrario \end{cases}

Ejemplo 2:

S → A | B

A → b

B → BACb | a //Esta línea es recursiva a la izquierda y necesita girar a la derecha recursiva

C → ANUNCIO |
D → antes de Cristo | antes de Cristo 

Después de la conversión: 

Primera fila: S → A | B

Segunda fila: A → b

Tercera fila: B → aB'

Cuarta fila: B' → ACbB' | ∈

Quinta fila: C → AD | ∈
Sexta fila: D → BC | bC 

Primero(A) = {b}
Primero(B) = {a}
Primero(B ') = {b ∈}
Primero(C) = {b ∈}
Primero(D) = {ab}
Primero(S) = {ba }

//Buscar Seguir desde la posición inicial. eof es una posición inicial fija. Si no hay S a la derecha, entonces se acabó.
Seguir(S) = {eof}
//Encontramos que A en la primera línea es la final del símbolo, por lo que debemos incluir Follow( S)
//Al mismo tiempo, la cuarta línea A es seguida por C, por lo que se debe incluir First(C), por supuesto, se debe eliminar ∈ porque hay ∈ en el primero de C, debemos continuar //recorrido hacia atrás y ver que bb obviamente no es ∈, así que deténgase
//La quinta línea A es seguida por D, por lo que primero (D) debe incluirse y no hay ∈ en primero (D), por lo que el final
sigue (A) = {eof ba}
// El símbolo B en la primera línea está al final de la cadena de símbolos, por lo que sigue (S)
// En la sexta línea, sigue B por C, por lo que contiene primero (C) pero primero (C) tiene ∈, por lo que continúa pero no hay nada después de la cadena de símbolos. En este momento, // significa que todas las cosas después de B en la sexta línea pueden
ser Desaparece, por lo que el seguimiento de D es el seguimiento de B, por lo que contiene follow(D)
Follow(B) = {eof b}
//Hay una terminal b después de C en la cuarta línea 
//La C en la sexta línea es el final de la cadena de símbolos, por lo que el seguimiento de D es el seguimiento de C, por lo que contiene follow(D)
Follow(C) = {b }
//La quinta línea muestra que D contiene follow de C
Follow(D) = { b}
//La tercera línea muestra que B 'contiene el seguimiento de B
Seguir(B') = {eof b}

Aquí encontramos una interesante dependencia circular B' es algo que depende de B B es algo que depende de D D es algo que depende de C C depende de D 

 Una gramática es LL(1) si 
        para cada producción 
        \\X \rightarrow \beta _1|\beta _2|....|\beta _n \\First^+(X\rightarrow \beta _i) \cap (X\rightarrow \beta _j) =\oslash \\for 1\leqslant i< j\leqslant n

Definir:
        Primero^+(X\rightarrow \beta _i) = \begin{cases} Primero(\beta _i) & \text{ if } \epsilon \notin Primero(\beta_i)\\ Primero(\beta _i) \cup Seguir( X) & \text{ si } en caso contrario \end{cases}

Comprobemos si esto encaja en
la primera fila de LL1: S → A | B comienza:
Primero^+(S → A) = Primero(A) = {b}
Primero^+(S → B) = Primero(B) = {a}
Primero^+(S → A)  \gorra Primero^+(S → B) =  \ o        pasar

No es necesario marcar la segunda y tercera línea porque solo tienen una opción.

La cuarta fila B' → ACbB' | ∈
Primero^+(B' → ACbB') = {b}
Primero^+(B' → ∈) = Seguir(B') = {eof b}
Primero^+(B' → ACbB')  \gorraPrimero^+(B' → ∈ ) = {b}  \neq \O
por lo que un error demuestra que LL1 no se aplica

Antes, cambiamos de recursividad izquierda a recursión derecha para hacer una gramática aplicable a LL1. Podemos verificar si una gramática específica es LL1. Es el mismo proceso que hicimos anteriormente, lo que significa que una gramática que no es aplicable a LL1 se puede aplicar después de algunas transformaciones ¿LL1
significa que cualquier gramática se puede adaptar a LL1 mediante algunas transformaciones? Obviamente no. Algunas gramáticas no son adecuadas para las habilidades de análisis de LL1 sin importar cómo las conviertas 
, y no existe ningún algoritmo que pueda determinar directamente si una gramática específica se puede convertir exitosamente a LL1. Solo puedes seguir intentándolo. Tal vez una vez lo haga. tenga éxito o no. No tendrá éxito. Solo puede verificarlo después de la conversión. Suena como un gran problema, pero en la práctica, la mayoría de los lenguajes libres de contexto se pueden convertir a LL1 a través de la experiencia. Por lo tanto, la lógica no necesita ser perfecto. En la práctica, el máximo se puede obtener a través de la experiencia 
. problemas causados ​​por la reducción de


Una gramática que es más general que LL(1) es LR(1),    
la más central de las cuales es el lenguaje regular, y el lenguaje regular ni siquiera necesita una gramática para restringirlo, y sólo se pueden usar autómatas finitos para expresar eso
. La gramática del idioma se volverá cada vez más complicada y será cada vez más difícil restringir la expresión. Se puede imaginar que lo más difícil de restringir la expresión debe ser el lenguaje natural cotidiano de los seres humanos, como como el chino y el inglés, porque muchas veces el lenguaje natural hablado por las personas no sigue la gramática o ni siquiera la añade. Es casi imposible restringir las emociones y asociaciones con un conjunto de gramáticas o códigos rígidos. Esta es también una brecha esencialmente insalvable para Inteligencia artificial contemporánea.

Por ejemplo, las dos oraciones siguientes:

Te veo entre la multitud por
origen Te veo entre la multitud por destino

Creo que la CPU arde y humea y no puedo entender la concepción artística.

Supongo que te gusta

Origin blog.csdn.net/weixin_43754049/article/details/126284719
Recomendado
Clasificación