expresiones regulares en competencia (condición de carrera)
Estoy intentando usar PLY (lex/yacc) en Python para analizar un lenguaje llamado ‘GRBL’.
GRBL se ve algo así:
Los códigos ‘G’ indican a una máquina que se ‘mueva’ y las coordenadas indican hacia dónde.
LEX nos exige especificar una expresión regular única para cada posible ‘token’.
Así que en este caso necesito una expresión regular que defina claramente ‘G00’ y otra que defina claramente ‘G01’, etc.
Obviamente, el primer pensamiento sería ‘r’G00’ etc.
Sin embargo, el código G es impreciso. Puede estar en mayúscula o minúscula, puede haber ceros anteriores, etc.
(g0, G00, g001, etc.)
Entonces algo para G00 podría ser tan simple como:
‘r'[Gg]{1}0*’
Y para G01 podríamos tener
‘r'[Gg]{1}0*1’
Pero esto no funciona. G00 se analiza correctamente, pero G01 muestra lo siguiente:
LexToken(G00, ‘G0’, 3,21)
Carácter no válido ‘1’
Es decir, lex piensa que G01 es un token G0 y no sabe qué hacer con el ‘1’.
Claramente, este es algún tipo de problema de coincidencia ambiciosa.
Desafortunadamente, no puedo usar el terminador “$” para especificar que la cadena debe ‘terminar’ con un “1”.
Me doy cuenta de que esto puede parecer sencillo para algunos, ¡pero llevo 3 horas intentando hacerlo funcionar! ¿Alguien sabe cómo solucionar este problema?
davy.ai
Solución utilizando lookahead
Para resolver este problema, podemos utilizar lookahead
(?=)
para asegurarnos de que el token termine con 0 o 1, dependiendo del código G que se esté analizando.Para G00, la expresión regular se vería así:
Esto coincidirá con cualquier cadena que comience con G o g, seguido de un 0, y termine con un carácter de espacio en blanco o las coordenadas X, Y, Z, o el final de la cadena.
Para G01, la expresión regular se vería así:
Esto coincidirá con cualquier cadena que comience con G o g, seguido de uno o más 0s, luego un 1, y termine con un carácter de espacio en blanco o las coordenadas X, Y, Z, o el final de la cadena.
Utilizando estas expresiones regulares, deberías poder analizar con precisión los códigos G en GRBL.