Parsing 我的莱克斯模式没有';无法匹配输入文件,如何更正?
我有一个简单的模式来匹配:head+content+tail,我有一个lex文件,如下所示:Parsing 我的莱克斯模式没有';无法匹配输入文件,如何更正?,parsing,printing,match,lex,Parsing,Printing,Match,Lex,我有一个简单的模式来匹配:head+content+tail,我有一个lex文件,如下所示: $ cat b.l %{ #include<stdio.h> %} %% "12" {printf("head\n");} "34" {printf("tail\n");} .* {printf("content\n");} %% 我的期望是,它会打印出来 head content tail 但实际上它只打印“内容”行。我做错了什么,怎么纠正 谢谢 (F)lex始终匹配最长的令牌。由于*
$ cat b.l
%{
#include<stdio.h>
%}
%%
"12" {printf("head\n");}
"34" {printf("tail\n");}
.* {printf("content\n");}
%%
我的期望是,它会打印出来
head
content
tail
但实际上它只打印“内容”行。我做错了什么,怎么纠正
谢谢 (F)lex始终匹配最长的令牌。由于*
将匹配任何不包含换行符的序列,因此它将很高兴地匹配12sdaesre34
。(在(f)lex中,
匹配除换行符以外的任何字符。)因此,34
不再可用于匹配
要解决这个问题,您必须清楚您希望内容
匹配什么。例如,以下内容将匹配任何不包含数字的内容:
[^[:digit:]]+ { printf("content\n"); }
您可能希望将换行符添加到不匹配的字符列表中:
[^\n[:digit:]]+ { printf("content\n"); }
或者,您可能希望匹配不包含34
的最长序列。这很棘手,但可以做到:
([^3]|3+[^34])+ { printf("content\n"); }
但是,这仍然会匹配初始12
,因此它不足以解决问题
如果您的输入总是由形式为12…34
的字符串组成,并且可能夹杂着其他内容,那么您可以匹配整个12…34
序列,并将其拆分为三个标记。这无疑是最简单的解决方案,因为开始和结束标记的长度是已知的。以下模式中的第一个匹配的字符串不以12
开头,在12
的第一个实例之前结束,第二个匹配的字符串以12
开头,在34
的第一个实例结束(匹配)。这两种模式都不会匹配包含不匹配的12
的输入;因此,添加了第三条规则以匹配该情况;它看起来很像第二条规则,但不包括结尾处的34
匹配。因为(f)lex总是匹配尽可能长的令牌,所以第三条规则只有在第二条规则失败时才会成功
([^1]|1+[^12])* { puts("content"); }
12([^3]|3+[^34])*34 { puts("head content tail"); }
12([^3]|3+[^34])* { puts("error"); }
通常,您希望实际捕获内容的值
以传递给调用程序。在第一条规则中,这只是yytext
,但在第二条规则中,内容由yyleng-4
字符组成,从yytext+2
开始(以删除前导和尾随分隔符)
在大多数情况下,如果需要保留匹配的标记,则有必要复制它,因为yytext
指向词法扫描程序使用的内部数据结构,指针将在下一个模式匹配时失效。对于第一条规则,您可以使用strcpy创建字符串的副本,但是对于第二条规则,您希望自己创建副本:
([^1]|1+[^12])* { yylval = strcpy(yytext); ... }
12([^3]|3+[^34])*34 { yylval = malloc(yyleng-3);
memcpy(yylval, yytext, yyleng-4);
yylval[yyleng-4] = '\0';
...
}
这些假设是yylval
是一个类型为char*
的全局变量,并且在代码中的某个地方您可以free()
规则保存的字符串。它们还假设您使用省略的代码(…
)中的yylval
执行某些操作,或者您返回给调用方,并指示是否遇到了头部和尾部。(F)lex始终匹配最长的令牌。由于*
将匹配任何不包含换行符的序列,因此它将很高兴地匹配12sdaesre34
。(在(f)lex中,
匹配除换行符以外的任何字符。)因此,34
不再可用于匹配
要解决这个问题,您必须清楚您希望内容
匹配什么。例如,以下内容将匹配任何不包含数字的内容:
[^[:digit:]]+ { printf("content\n"); }
您可能希望将换行符添加到不匹配的字符列表中:
[^\n[:digit:]]+ { printf("content\n"); }
或者,您可能希望匹配不包含34
的最长序列。这很棘手,但可以做到:
([^3]|3+[^34])+ { printf("content\n"); }
但是,这仍然会匹配初始12
,因此它不足以解决问题
如果您的输入总是由形式为12…34
的字符串组成,并且可能夹杂着其他内容,那么您可以匹配整个12…34
序列,并将其拆分为三个标记。这无疑是最简单的解决方案,因为开始和结束标记的长度是已知的。以下模式中的第一个匹配的字符串不以12
开头,在12
的第一个实例之前结束,第二个匹配的字符串以12
开头,在34
的第一个实例结束(匹配)。这两种模式都不会匹配包含不匹配的12
的输入;因此,添加了第三条规则以匹配该情况;它看起来很像第二条规则,但不包括结尾处的34
匹配。因为(f)lex总是匹配尽可能长的令牌,所以第三条规则只有在第二条规则失败时才会成功
([^1]|1+[^12])* { puts("content"); }
12([^3]|3+[^34])*34 { puts("head content tail"); }
12([^3]|3+[^34])* { puts("error"); }
通常,您希望实际捕获内容的值
以传递给调用程序。在第一条规则中,这只是yytext
,但在第二条规则中,内容由yyleng-4
字符组成,从yytext+2
开始(以删除前导和尾随分隔符)
在大多数情况下,如果需要保留匹配的标记,则有必要复制它,因为yytext
指向词法扫描程序使用的内部数据结构,指针将在下一个模式匹配时失效。对于第一条规则,您可以使用strcpy创建字符串的副本,但是对于第二条规则,您希望自己创建副本:
([^1]|1+[^12])* { yylval = strcpy(yytext); ... }
12([^3]|3+[^34])*34 { yylval = malloc(yyleng-3);
memcpy(yylval, yytext, yyleng-4);
yylval[yyleng-4] = '\0';
...
}
这些假设是yylval
是一个类型为char*
的全局变量,并且在代码中的某个地方您可以free()
规则保存的字符串。它们还假设您使用省略的代码(…
)中的yylval
执行某些操作,或者您重新