El análisis léxico del compilador se basa en autómatas finitos (autómata finito) y expresiones regulares (expresión regular)
alfabeto: conjunto finito de símbolos alfabeto: una colección de símbolos finitos
cadena: secuencia de símbolos de un alfabeto dado cadena: una secuencia de símbolos de un alfabeto dado
lenguaje: conjunto de cadenas una colección de cadenas
Por ejemplo, x12 = 32; hay token
x12 identificador
= asignación
32 unsigned int
; fin de la declaración
Las 4 fichas aquí en realidad pueden considerarse como 4 idiomas, cada idioma tiene su propia composición de caracteres única.
Al pasar una cadena (o un token) a un autómata finito o una expresión regular, volverá a indicarle si se trata de un token legal o no, un token que pertenece a su idioma.
Los autómatas finitos y las expresiones regulares como herramienta para identificar el lenguaje solo pueden reconocer el lenguaje regular (lenguaje estándar).
DFA es relativamente más estricto y cada salida posible tiene una y solo una salida.
L = { w | w contiene 101 como subcadena}
DFA (autómatas finitos deterministas) (autómatas finitos deterministas) para L
tabla de transición para DFA:
Código
switch(state)
case q0:
if sym == 0 go to q0
if sym == 1 go to q1
case q1:
if sym == 0 go to q1
if sym == 1 go to q2
Todo AFD es también un AFN, pero no todo AFN es un AFD.
NFA (autómatas finitos no deterministas) (autómatas finitos no deterministas) para L
tabla de transición para NFA
Método NFA a DFA: método de construcción de subconjuntos
Entonces, si se implementa en código, ¿es más fácil implementar DFA o NFA?
La respuesta es DFA. Entonces, en el proceso de análisis léxico, generalmente se construye un DFA.
L = {w | w contiene la subcadena 101 o la subcadena 111}
NFA:
L = {w | w contiene la subcadena 101 o termina con la subcadena 111}
NFA:
expresión regular (expresión regular)
Construcción de Thompson : el método para convertir expresiones regulares en NFA
NFA a DFA: construcción de subconjuntos método de construcción de subconjuntos
Las expresiones regulares son la forma más fácil de entender para los humanos. Primero debemos convertir la expresión regular a NFA y luego convertirla en el DFA final mediante el método de construcción de subconjuntos. Solo después de convertirla a DFA podemos escribir código de manera intuitiva
.
Existe una herramienta llamada flex que nos puede ayudar a hacer estas conversiones, solo necesitamos ingresar una expresión regular y la herramienta nos devolverá el código en lenguaje C.
La expresión regular para L = {w | w contiene 101 como subcadena} es:
(0 U 1)* 101 (0 U 1)*
o también se puede escribir como ∑* 101 ∑* //aquí ∑* representa todas las entradas posibles
Aquí hay dos ejemplos más de expresiones regulares:
L = {w | w tiene una longitud par} // longitud par
(∑∑)*
L = {w | w tiene una longitud impar} //longitud impar
∑(∑∑)*
Expresión regular para
int sin signo: [0 - 9]* Permite 0 al principio y permite cadenas vacías
0 U [1 - 9][0 - 9]* No permite 0 al principio
0 U [1 - 9][0 - 9]* para NFA:
Reglas de nomenclatura de variables y su expresión regular (_ U [a - z]) ([az] U [0 - 9] U _)*su NFA
: