【问题标题】:Making lex to read UTF-8 doesn't work让 lex 读取 UTF-8 不起作用
【发布时间】:2012-04-20 20:01:10
【问题描述】:

我编写了一个解析 ASCII 文件的 xml 解析器,但我现在需要能够读取 UTF-8 编码的文件。我在 lex 中有以下正则表达式,但它们与 UTF-8 不匹配。我不确定我做错了什么:

utf_8       [\x00-\xff]*
bom         [\xEF\xBB\xBF]

然后:

bom             { fprintf( stderr, "OMG I SAW A BOM"); return BOM;}
utf_8           { fprintf( stderr, "OMG I SAW A UTF CHAR", yytext[0] ); return UTF_8;}

我还有以下语法规则:

program 
: UTF8 '<' '?'ID attribute_list '?''>' 
root ...

UTF8 在哪里:

UTF8

: BOM           {printf("i saw a bom\n");}
| UTF_8         {printf("i saw a utf\n");}
|               {printf("i didn't see anything.'\n");} 
;

它总是出现i didn't see anything,我的解析器适用于 ASCII 文件,即当我将 XML UTF-8 文件复制粘贴到一个空文档中时。

任何帮助将不胜感激。

编辑:

这是一个修剪后的 .l 文件供参考:

%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "y.tab.h"
int lines = 1;
%}

utf_8       [\x0000-\xffff]*
bom         [\xEF\xBB\xBF]
whitespace  [ \t]
ev          (.|{bom})
ev1         (.|{utf_8})
%%
{whitespace}    { fprintf( stderr, "%s", yytext );}
\n              { fprintf( stderr, "%s%d ", yytext, lines++ );}
.               { fprintf( stderr, "{TOKEN:%c}", yytext[0] ); return yytext[0];}
bom             { fprintf( stderr, "OMG I SAW A BOM"); return BOM;}
utf_8           { fprintf( stderr, "OMG I SAW A UTF CHAR", yytext[0] ); return UTF_8;}
%%

void error( char *message )
{
    fprintf( stderr, "Error: %s\n", message );
    exit(1);
}

【问题讨论】:

  • 究竟是哪个“lex”你使用的是?有些可以处理高字节集的字符,有些不能,有些严格面向字节,有些处理代码点等。
  • 另外,一个完整的.l 文件将不胜感激。
  • @Zack c `flex' 版本 2.5.35
  • 好的,你似乎想要做的事情应该flex一起工作。不过,如果没有完整的 flex 输入文件,我将无能为力。
  • @Zack 我刚刚添加了一个修剪过的 .l 文件。

标签: c xml parsing utf-8 lex


【解决方案1】:

好的,这是你的问题:

utf_8       [\x0000-\xffff]*
bom         [\xEF\xBB\xBF]

这里有两个问题。首先,Flex 实际上并不理解 Unicode。它适用于字节。因此,您需要一个匹配任何有效 UTF-8 字节序列的正则表达式宏。 http://keithdevens.com/weblog/archive/2004/Jun/29/UTF-8.regex 有一个正则表达式可以做到这一点,转换为 Flex 语法并不难(见下文)。其次,BOM 宏中的方括号使其匹配任何 单字节 值 EF、BB 或 BF,而不是 三字节序列 EB BB BF你想要什么。

(顺便说一下,UTF-8 文件应该有字节顺序标记,尽管很多都这样做。)

这是一个完整的 Flex 输入文件,它或多或少地完成了您似乎一直在尝试做的事情:

%{
#include <stdio.h>
%}

bom     \xEF\xBB\xBF
white   [ \t]

u2a     [\xC2-\xDF][\x80-\xBF]
u2b     \xE0[\xA0-\xBF][\x80-\xBF]
u3a     [\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}
u3b     \xED[\x80-\x9F][\x80-\xBF]
u4a     \xF0[\x90-\xBF][\x80-\xBF]{2}
u4b     [\xF1-\xF3][\x80-\xBF]{3}
u4c     \xF4[\x80-\x8F][\x80-\xBF]{2}

utf_8   {u2a}|{u2b}|{u3a}|{u3b}|{u4a}|{u4b}|{u4c}

%%

{white}     { putchar(' ');  }
\n          { putchar('\n'); }
{bom}       { putchar('B');  }
{utf_8}     { putchar('u');  }
[\x21-\x7e] { putchar('.');  }
.           { putchar('^');  }

【讨论】:

  • 这是否匹配任何有效的 UTF-8 字节序列,还是只是一个示例,因为我仍然收到消息 syntax error, unexpected $undefined, expecting
  • 我写的不是完整的lex输入文件。我将编辑一个真正有效的完整输入文件。
  • 您是否尝试在 UTF8 编码文件上运行它?我仍然收到您的代码未定义的消息?我猜我应该为我缺少的字符添加编码?
  • 如果上面的文件是test.l,那么flex -8 -o test.c test.l; gcc test.c -lfl 没有给出任何语法错误,而且结果在UTF-8 输入上似乎可以正常工作。 (我是随便测试的,没有彻底测试。)究竟是什么命令给你语法错误信息?
  • 它停在我正在测试的文档的第一个字符上,我确信它是一个 XML(文件 -bi testFile 说它的 XML),它没有给我任何编译错误。你从哪里得到你的测试文件。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-01-29
  • 2013-07-19
  • 1970-01-01
  • 1970-01-01
  • 2015-08-06
  • 2019-01-30
  • 1970-01-01
相关资源
最近更新 更多