我必须编写一个包含以下规则的lex程序:
标识符:字母数字字符串(和
_
),以字母字符开头文字:整数和字符串
评论:从
!
字符开始,一直到行尾
这是我提出的
[a-zA-Z][a-zA-Z0-9]+ return(ID);
[+-]?[0-9]+ return(INTEGER);
[a-zA-Z]+ return ( STRING);
!.*\n return ( COMMENT );
但是,当我编译这个lex文件时,我仍然会遇到很多错误。
您认为错误是什么?
答案 0 :(得分:0)
如果您更清楚地了解代码的问题,那会有所帮助。例如,您是否收到错误消息或未按预期运行?
您的代码存在一些问题,但主要是正确的。我看到的第一个问题是你没有将你的lex程序划分为%%
分隔符所需的部分。 lex程序的第一部分是声明部分,其中指定了正则表达式模式。第二部分是指定匹配模式的操作的位置。 (可选)第三部分是放置任何代码(用于编译器)的地方。编译器的代码也可以放在声明部分,在行的开头由%{
和%}
描述。
如果我们将代码放入lex,我们会收到此错误:
" SoNov16.l",第1行:坏人:[
" SoNov16.l",第1行:未知错误处理部分1
" SoNov16.l",第1行:未知错误处理部分1
" SoNov16.l",第1行:坏人:] " SoNov16.l",第1行:坏字符:+
" SoNov16.l",第1行:未知错误处理部分1
" SoNov16.l",第1行:坏人:(
" SoNov16.l",第1行:未知错误处理部分1
" SoNov16.l",第1行:坏人物:) " SoNov16.l",第1行:坏人物:;
你有没有这样的东西?在您的示例代码中,您指定了操作(return(ID);
是操作的示例),因此您的代码用于第二部分。因此,您需要在其前面加上%%
行。那将是一个有效的lex计划。
您的代码依赖于(可能)解析器,它使用(并声明)令牌。出于测试目的,首先打印令牌通常更容易。我通过制作一个 C 宏来解决这个问题,该宏将执行打印并可以在以后阶段重新定义以执行return
。像这样:
%{
#define TOKEN(t) printf("String: %s Matched: " #t "\n",yytext)
%}
%%
[a-zA-Z][a-zA-Z0-9]+ TOKEN(ID);
[+-]?[0-9]+ TOKEN(INTEGER);
[a-zA-Z]+ TOKEN (STRING);
!.*\n TOKEN (COMMENT);
如果我们构建并测试它,我们会得到以下结果:
ABC
字符串:abc符合次数:IDABC123
字符串:abc123符合次数:ID!评论文本
字符串:!评论文本
匹配:评论
不太正确。我们可以看到ID规则匹配应该是字符串。这是由于规则的排序。我们必须首先放置String规则以确保它首先匹配 - 除非你当然应该匹配某些引号内的字符串?您还错过了ID模式的下划线。匹配和丢弃任何空格字符也是一个好主意:
%{
#define TOKEN(t) printf("String: %s Matched: " #t "\n",yytext)
%}
%%
[a-zA-Z]+ TOKEN (STRING);
[a-zA-Z][a-zA-Z0-9_]+ TOKEN(ID);
[+-]?[0-9]+ TOKEN(INTEGER);
!.*\n TOKEN (COMMENT);
[ \t\r\n]+ ;
测试时显示:
ABC
字符串:abc符合条件:字符串
abc123_
字符串:abc123_符合次数:ID
-1234
字符串:-1234符合条件:INTEGER
abc abc123!评论文本
字符串:abc符合条件:字符串
字符串:abc123符合次数:ID
字符串:!评论文本
匹配:评论
万一你想要引号中的字符串,这也很容易:
%{
#define TOKEN(t) printf("String: %s Matched: " #t "\n",yytext)
%}
%%
\"[^"]+\" TOKEN (STRING);
[a-zA-Z][a-zA-Z0-9_]+ TOKEN(ID);
[+-]?[0-9]+ TOKEN(INTEGER);
!.*\n TOKEN (COMMENT );
[ \t\r\n] ;
" ABC"
字符串:" abc"匹配:STRING