Saltar al contenido

Compatibilidad con flex (lexer) para unicode

Agradecemos tu apoyo para difundir nuestras secciones acerca de las ciencias informáticas.

Solución:

Por el momento, flex solo genera escáneres de 8 bits, lo que básicamente te limita a usar UTF-8. Entonces, si tienes un patrón:

肖晗    printf ("xiaohann"); 

Funcionará como se esperaba, 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 desea hacer coincidir el carácter 肖 o 晗, no puede escribir:

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

porque esto 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 simple caso, debes reescribir el patrón para (肖|晗).

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

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

Esto no es bonito, pero debería funcionar.

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

Esto funcionará bien para lenguajes de programación típicos, donde es posible que pueda 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 escáner.

La idea es que puedas reconocer un patrón que incluya bytes UTF-8 usando una regla lex, (y luego quizás tomar la yytexty convertirlo en UTF-8 o al menos validarlo).

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

Desplácese hacia abajo hasta esta sección:

ASC     [x00-x7f]
ASCN    [x00-tv-x7f]
U       [x80-xbf]
U2      [xc2-xdf]
U3      [xe0-xef]
U4      [xf0-xf4]

UANY    ASC|U2U|U3UU|U4UUU
UANYN   ASCN|U2U|U3UU|U4UUU 
UONLY   U2U|U3UU|U4UUU

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

Algunas explicaciones: El UANY significa coincidir con cualquier carácter, ASCII de un solo byte o UTF-8 de varios 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 de # al final de la línea, que contiene texto internacional. UONLY significa coincidir solo con un carácter extendido UTF-8, no con uno ASCII. Esto es útil para escribir una regla lex que necesita excluir ciertos caracteres ASCII específicos (no solo una nueva línea) pero todos los caracteres extendidos están bien.

DESCARGO DE RESPONSABILIDAD: Tenga en cuenta que las reglas del escáner utilizan una función llamada utf8_dup_from para convertir el yytext a cadenas de caracteres anchas 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 correctamente. Es decir, este programa no se basa en estas reglas lex para realizar la validación y conversión, solo para realizar el reconocimiento léxico básico. Estas reglas reconocerán una forma demasiado larga (como un código ASCII codificado con varios bytes) como 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 debe confiar en el código fuente para ejecutarlo de todos modos (¡pero es posible que los datos manejados por el programa no sean confiables!). escribir un escáner para datos UTF-8 que no son de confianza, ¡cuidado!

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?

Para hacer coincidir patrones con caracteres chinos y otros puntos de código Unicode con un analizador léxico compatible con Flex, puede usar el analizador léxico RE / flex para C ++.

Reflejo admite de forma segura el estándar Unicode 12 completo y acepta archivos de entrada UTF-8, UTF-16 y UTF-32 sin requerir hacks UTF-8 que ni siquiera pueden admitir la entrada UTF-16/32.

Además, los trucos UTF-8 con Flex no le permiten escribir expresiones regulares Unicode como [肖晗] que son totalmente compatibles con RE / flex.

Funciona a la perfección con Bison para crear lexers y analizadores.

De hecho, con RE / flex podemos escribir cualquier patrón Unicode como expresiones regulares basadas en UTF-8 en lexer .l especificaciones, tales como:

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

Esto genera un lexer que escanea archivos UTF-8, UTF-16 y UTF-32 automáticamente. Según la estandarización UTF, para la entrada UTF-16/32 se espera una lista de materiales UTF en la entrada, mientras que una lista de materiales UTF-8 es opcional.

Podemos usar global %option unicode para habilitar Unicode y %option flex para especificar especificaciones Flex. Un modificador local (?u:) se puede usar 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/2n"); 
(?u:pHan)   printf ("Han character %sn", yytext); 
.              printf ("8-bit character %dn", yytext[0]); 
%%

Opción flex habilita la compatibilidad con Flex, para que pueda usar yytext, yyleng, ECHO, y así. Sin el flex La opción RE / flex espera llamadas al método Lexer: text() (o str() y wstr() por std::string y std::wstring), size() (o wsize() para una gran longitud de char), y echo(). Las llamadas al método RE / flex son más limpias en mi humilde opinión e incluyen operaciones de caracteres amplios.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *