tutorial lexico analizador unicode flex-lexer

unicode - lexico - flex c



Flex(lexer) soporte para unicode (3)

Me pregunto si la versión más reciente de flex es compatible con Unicode.

Si es así, ¿cómo se pueden usar patrones para unir caracteres chinos?

Para hacer coincidir patrones con caracteres chinos y otros puntos de código Unicode con un analizador léxico similar a Flex, puede usar el analizador léxico RE / flex para C ++ que es compatible con Flex con versiones anteriores. RE / flex es compatible con Unicode y trabaja con Bison para construir lexers y analizadores.

Puede escribir patrones Unicode (y expresiones regulares UTF-8) en especificaciones RE / flex como:

%option flex unicode %% [肖晗] { printf ("xiaohan/2/n"); } %%

Utilice la %option unicode global %option unicode para habilitar Unicode. También puede usar un modificador local (?u:) para restringir Unicode a un solo patrón (por lo que todo lo demás sigue siendo ASCII / 8 bits como en Flex):

%option flex %% (?u:[肖晗]) { printf ("xiaohan/2/n"); } (?u:/p{Han}) { printf ("Han character %s/n", yytext); } . { printf ("8-bit character %d/n", yytext[0]); } %%

La opción flex habilita la compatibilidad con Flex, por lo que puede usar yytext , yyleng , ECHO , etc. Sin la opción flex , RE / flex espera las llamadas al método Lexer: text() (o str() y wstr() para std::string y std::wstring ), size() (o wsize() para longitud de caracteres amplia), y echo() . Las llamadas al método RE / flex son IMHO más limpias, e incluyen operaciones de char amplia.

Me pregunto si la versión más reciente de flex es compatible con Unicode.

Si es así, ¿cómo se pueden usar patrones para hacer coincidir los caracteres chinos?

Más: use expresiones regulares para hacer coincidir CUALQUIER carácter chino en la codificación utf-8


En este momento, flex solo genera escáneres de 8 bits que básicamente lo limitan a usar UTF-8. Así que si tienes un patrón:

肖晗 { printf ("xiaohan/n"); }

funcionará como se espera, ya que la secuencia de bytes en el patrón y en la entrada será la misma. Lo que es más difícil son las clases de personajes. Si quieres hacer coincidir el carácter 肖 o, no puedes escribir:

[肖晗] { printf ("xiaohan/2/n"); }

porque coincidirá con cada uno de los seis bytes 0xe8, 0x82, 0x96, 0xe6, 0x99 y 0x97, lo que en la práctica significa que si proporciona 肖晗 como entrada, el patrón coincidirá seis veces. Entonces, en este caso simple, tienes que reescribir el patrón a (肖|晗) .

Para rangos, Hans Aberg ha escrito una herramienta en Haskell que los transforma en patrones de 8 bits:

Unicode> urToRegU8 0 0xFFFF [/0-/x7F]|[/xC2-/xDF][/x80-/xBF]|(/xE0[/xA0-/xBF]|[/xE1-/xEF][/x80-/xBF])[/x80-/xBF] Unicode> urToRegU32 0x00010000 0x001FFFFF /0[/x01-/x1F][/0-/xFF][/0-/xFF] Unicode> urToRegU32L 0x00010000 0x001FFFFF [/x01-/x1F][/0-/xFF][/0-/xFF]/0

Esto no es bonito, pero debería funcionar.


Flex no es compatible con Unicode. Sin embargo, Flex admite la entrada binaria "8 bit clean". Por lo tanto, puede escribir patrones léxicos que coincidan con UTF-8. Puede utilizar estos patrones en áreas léxicas específicas del idioma de entrada, por ejemplo, identificadores, comentarios o literales de cadena.

Esto funcionará bien para los lenguajes de programación típicos, donde puede afirmar a los usuarios de su implementación que el lenguaje fuente está escrito en ASCII / UTF-8 (y no se admite ninguna otra codificación, punto).

Este enfoque no funcionará si su escáner debe procesar texto que puede estar en cualquier codificación. Tampoco funcionará (muy bien) si necesita expresar reglas léxicas específicamente para elementos Unicode. Es decir, necesita caracteres Unicode y expresiones regulares Unicode en el propio escáner.

La idea es que puede reconocer un patrón que incluye UTF-8 bytes usando una regla lex (y luego tal vez tomar el yytext y convertirlo de UTF-8 o al menos validarlo).

Para ver un ejemplo de trabajo, consulte el código fuente del lenguaje TXR, en particular este archivo: http://www.kylheku.com/cgit/txr/tree/parser.l

Desplácese hasta esta sección:

ASC [/x00-/x7f] ASCN [/x00-/t/v-/x7f] U [/x80-/xbf] U2 [/xc2-/xdf] U3 [/xe0-/xef] U4 [/xf0-/xf4] UANY {ASC}|{U2}{U}|{U3}{U}{U}|{U4}{U}{U}{U} UANYN {ASCN}|{U2}{U}|{U3}{U}{U}|{U4}{U}{U}{U} UONLY {U2}{U}|{U3}{U}{U}|{U4}{U}{U}{U}

Como puede ver, podemos definir patrones para que coincidan con los caracteres ASCII, así como con los bytes de inicio y de continuación UTF-8. UTF-8 es una notación léxica, y este es un generador analizador léxico, así que ... ¡no hay problema!

Algunas explicaciones: los medios UANY coinciden con cualquier carácter, ASCII de un solo byte o UTF-8 de múltiples bytes. UANYN significa como UANY pero no coincide con la nueva línea. Esto es útil para tokens que no se dividen entre líneas, como decir un comentario desde # hasta el final de la línea, que contiene texto internacional. UONLY significa que solo coinciden un carácter extendido UTF-8, no uno ASCII. Esto es útil para escribir una regla lex que necesita excluir ciertos caracteres ASCII específicos (no solo la nueva línea), pero todos los caracteres extendidos están bien.

NEGACIÓN DE RESPONSABILIDAD: utf8_dup_from en cuenta que las reglas del escáner utilizan una función llamada utf8_dup_from para convertir el texto yytext en cadenas de caracteres anchos que contienen puntos de código Unicode. Esa función es robusta; detecta problemas como secuencias demasiado largas y bytes no válidos y los maneja adecuadamente. Es decir, este programa no está confiando en estas reglas de lex para hacer la validación y la conversión, solo para hacer el reconocimiento léxico básico. Estas reglas reconocerán una forma demasiado larga (como un código ASCII codificado con varios bytes) como una sintaxis válida, pero la función de conversión las tratará correctamente. En cualquier caso, no espero problemas de seguridad relacionados con UTF-8 en el código fuente del programa, ya que tiene que confiar en que el código fuente lo ejecutará de todos modos (pero los datos manejados por el programa pueden no ser de confianza). escribiendo un escáner para datos UTF-8 no confiables, ¡cuidado!