2012-03-08 11 views

Respuesta

14

Por el momento, la flexión sólo genera analizadores de 8 bits, que se limite básicamente a utilizar UTF-8. Así que si usted tiene un patrón:

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

que va a funcionar como se espera, como la secuencia de bytes en el modelo y en la entrada será el mismo. Lo que es más difícil es las clases de personajes. Si desea hacer coincidir ya sea el carácter o 肖 晗, no se puede escribir:

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

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

Para rangos, Hans Aberg ha escrito un tool in Haskell que transforma estos en los 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 bastante, pero debería funcionar.

+0

¿Más sugerencias sobre la solución? – xiaohan2012

+0

Copié mi respuesta de la lista de correo a la respuesta. –

+0

Gracias. ¡Parece inspirarme mucho! – xiaohan2012

15

Flex no es compatible con Unicode. Sin embargo, Flex admite 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 cadenas.

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

Este enfoque no funcionará si el 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 se puede reconocer un patrón que incluye bytes UTF-8 utilizando una regla lex, (y tal vez tomar la yytext, y convertirlo de UTF-8 o al menos validarlo.)

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

de desplazamiento hacia abajo para 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 se puede ver, podemos definir patrones para que coincida con ASCII Characte rs así como los bytes de inicio y continuación 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 que coincide con cualquier carácter, ASCII de un 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 en líneas, como por ejemplo un comentario de # hasta el final de la línea, que contiene texto internacional.UONLY significa que solo coincide con un carácter extendido UTF-8, no uno ASCII. Esto es útil para escribir una regla de lex que necesita excluir ciertos caracteres ASCII específicos (no solo la línea nueva), pero todos los caracteres extendidos están bien.

Exención de responsabilidad: Tenga en cuenta que las reglas del analizador utilizan una función llamada utf8_dup_from para convertir el yytext a cadenas de caracteres anchos que contienen puntos de código Unicode. Esa función es robusta; detecta problemas como secuencias excesivas y bytes no válidos y los maneja adecuadamente. Es decir. este programa no se basa en estas reglas 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 utilizando varios bytes) como sintaxis válida, pero la función de conversión las tratará adecuadamente. 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 se ejecutará de todos modos (¡pero los datos manejados por el programa pueden no ser confiables!) escribiendo un escáner para datos UTF-8 que no son de confianza, ¡ten cuidado!

+0

Sólo me preguntaba, no debe la definición de U4 ser como: 'U4 [\ xf0- \ XF7]' para acomodar realidad todas las posibilidades de 11110000 a 11110111? – exa

+0

@exa ¡Buena atención al detalle! El rango completo del byte nos daría puntos de código hasta 'U + 3FFFFF'. El 'F4' se restringe a' U + 10FFFF'. – Kaz

+0

Me pregunto si el enfoque propuesto es seguro. Estos patrones TRX incluyen el rango U + D800-U + DFFF no válido (las mitades sustitutas UTF016 no son válidas Unicode) y '{U4} {U} {U} {U}' supera el límite superior Unicode U + 10FFFF, a diferencia de lo que el último punto de código debe ser '\ xf4 [\ x80- \ x8f] [\ x80- \ xbf] [\ x80- \ xbf]' not '\ xf4 [\ x80- \ xbf] [\ x80- \ xbf] [\ x80- \ xbf] '. –

1

Me pregunto si la última versión de flex admite unicode?

Si es así, ¿cómo se puede utilizar patrones para que coincida con los caracteres chinos?

para que coincida con los patrones con caracteres chinos y otros puntos de código Unicode con un analizador léxico Flex-como, usted podría utilizar el RE/flex lexical analyzer para C++ que es compatible con Flex. RE/flex es compatible con Unicode y funciona con Bison para construir lexers y analizadores sintácticos.

Usted puede escribir patrones Unicode (UTF-8 y expresiones regulares) en las especificaciones de flexión RE/como:

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

uso mundial %option unicode que permitan Unicode. También puede utilizar un modificador locales (?u:) para restringir Unicode a un único patrón (por lo que todo lo demás es todavía 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]); } 
%% 

Opción flex permite la compatibilidad Flex, para que pueda utilizar yytext, yyleng, ECHO, y así sucesivamente. Sin la flex opción RE/flex espera método Lexer llamadas: text() (o str() y wstr() para std::string y std::wstring), size() (o wsize() para longitud de carbonización de ancho), y echo(). Las llamadas a los métodos RE/flex son en mi humilde opinión más limpias e incluyen operaciones de charlas amplias.

Cuestiones relacionadas