您遇到问题的原因是您只为输入文件的一部分定义了规则,并希望词法分析器和分析器将其余部分忽略。这不是工具的工作方式;他们尝试并匹配所有内容,因此您必须为输入数据的每个方面定义所有内容。
我还注意到您的原始词法分析器文件没有用flex构建。你有错误的顺序规则。你原来的规则集:
%option noyywrap
%{
#include "parser.tab.h"
%}
%%
"<!--<legend>" {return name1;}
(.*?) {yylval.sval=strdup(yytext); return name2;}
"<\/legend>" {return name3;}
%%
提供以下错误:
"test.l", line 8: warning, rule cannot be matched
这是因为Flex使用规则,以便和name3
永远不能返回的模式为name2
也将匹配name3
。你明显地解决了这个问题,以便能够构建你的测试程序。解决方法是反向的规则的顺序,如:弯曲(野牛)的
%option noyywrap
%{
#include "parser.tab.h"
%}
%%
"<!--<legend>" {return name1;}
"<\/legend>" {return name3;}
(.*?) {yylval.sval=strdup(yytext); return name2;}
%%
一个特点,那就是在调试有用的是调试模式,这并不奇怪!
如果我们运行与调试模式下的代码启用,像这样:
bison -d parser.y
flex -d test.l
gcc parser.tab.c lex.yy.c -lfl -o run
,然后执行该程序,我们现在得到的词法分析器有帮助输出:
--(end of buffer or a NUL)
--accepting rule at line 8 ("")
EEK, parse error! Message:syntax error, unexpected name2, expecting name1
你可以看到您的规则(.*?)
确实符合任何文字,但不仅限于<legend>
,而且也包含在其他地方。这意味着您的解析器在看到name1
之前将会看到一系列令牌name2
,name2
,name2
。现在您的只有规则在解析器中说在输入必须令牌开始name1
,因此你得到一个语法错误。
现在,有几种方法可以解决这个问题。您可以将您的野牛规则更改为在name1
之前接受许多name2
令牌,或者可以升级整个语法来描述整个XML/HTML。至少你可能想升级语法来接受几个<legend>
标签在一个文件中!目前,你的语法只匹配一个包含一个单一<legend>
结构的文件,而不是别的 - 记住它不会忽略其他输入(除非你告诉它)!
重写一般化XML结构的语法会更大,但可以做的是指示flex词法分析器忽略其他输入,以便不返回name2
模式。我们只需为输入数据文件中的其他内容编写模式。我们需要匹配其他XML标签,注释行和空白区域,并告诉flex忽略它们。
这样做可能是一个例子:
%{
#include "parser.tab.h"
%}
%%
"<!--<legend>" {return name1;}
"<\/legend>" {return name3;}
"<".[^-](.|[ \t])*">" ; /* Skip other tags */
"//".*[\r\n]+ ; /* Skip comments */
[\r\n\t ]+ ; /* Skip unused whitespace */
(.*?) {yylval.sval=strdup(yytext); return name2;}
%%
当我们运行这段代码我们设法跳过一些不必要的标签:
--(end of buffer or a NUL)
--accepting rule at line 7 ("<!DOCTYPE html>")
--accepting rule at line 9 ("
")
--accepting rule at line 7 ("<html charset="utf-8" lang="en">")
--accepting rule at line 9 ("
")
--accepting rule at line 7 ("<head>")
--accepting rule at line 9 ("
")
--accepting rule at line 7 ("<meta content="text/html; charset=UTF-8" http-equiv
="content-type">")
--accepting rule at line 9 ("
")
--accepting rule at line 7 ("<meta content="text/css" http-equiv="Content-Style-
Type">")
--accepting rule at line 9 ("
")
--accepting rule at line 7 ("<script src="/commd/jquery.nivo.slider.pack.js"></s
cript>")
--accepting rule at line 9 ("
")
--accepting rule at line 7 ("<link rel="stylesheet" type="text/css" href="/fonts
/stylesheet.css"/>")
--accepting rule at line 9 ("
")
--accepting rule at line 7 ("<link rel="stylesheet" type="text/css" href="/commd
/stylesheet.css"/>")
--accepting rule at line 9 ("
")
--accepting rule at line 10 ("<!--<legend> DATA TO BE EXTRACTED</legend>--> //re
levant data between <legend> tag")
EEK, parse error! Message:syntax error, unexpected name2, expecting name1
我们打了另一个问题。神秘的是,它为什么不匹配并返回name1
?这是由匹配算法贪婪引起的,并找到匹配最长令牌的规则。为了克服这个问题,我们必须使用flex的start condition特性,并且只能在<legend>
结构内匹配一般文本。在匹配XML中使用起始条件时,我们必须小心,因为<
符号用于表示状态更改以及引入XML标记。我们可以重新编码切换状态是这样的:
%{
#include "parser.tab.h"
%}
%x legends
%x finishd
%%
<INITIAL>"<!--<legend>" {BEGIN(legends); return name1;}
<finishd>"</legend>-->" {BEGIN(INITIAL); return name3;}
<INITIAL>"<".[^-](.|[ \t])*">" ; /* Skip other tags */
<INITIAL>"//".*[\r\n]+ ; /* Skip comments */
<INITIAL>[\r\n\t ]+ ; /* Skip unused whitespace */
<legends>[^<>]+ {BEGIN(finishd); yylval.sval=strdup(yytext); return name2;}
%%
那么神奇,我们得到如下:
--(end of buffer or a NUL)
--accepting rule at line 9 ("<!DOCTYPE html>")
--accepting rule at line 11 ("
")
--accepting rule at line 9 ("<html charset="utf-8" lang="en">")
--accepting rule at line 11 ("
")
--accepting rule at line 9 ("<head>")
--accepting rule at line 11 ("
")
--accepting rule at line 9 ("<meta content="text/html; charset=UTF-8" http-equiv
="content-type">")
--accepting rule at line 11 ("
")
--accepting rule at line 9 ("<meta content="text/css" http-equiv="Content-Style-
Type">")
--accepting rule at line 11 ("
")
--accepting rule at line 9 ("<script src="/commd/jquery.nivo.slider.pack.js"></s
cript>")
--accepting rule at line 11 ("
")
--accepting rule at line 9 ("<link rel="stylesheet" type="text/css" href="/fonts
/stylesheet.css"/>")
--accepting rule at line 11 ("
")
--accepting rule at line 9 ("<link rel="stylesheet" type="text/css" href="/commd
/stylesheet.css"/>")
--accepting rule at line 11 ("
")
--accepting rule at line 7 ("<!--<legend>")
--accepting rule at line 12 (" DATA TO BE EXTRACTED")
--accepting rule at line 8 ("</legend>-->")
DATA TO BE EXTRACTED
--accepting rule at line 11 (" ")
--(end of buffer or a NUL)
--accepting rule at line 10 ("//relevant data between <legend> tag
")
--(end of buffer or a NUL)
--EOF (start condition 0
现在,如果你关闭了柔性调试,你只会得到所需的输出:
DATA TO BE EXTRACTED
如果有超过一组数据需要提取,您仍然需要更新野牛语法;实际上你应该升级整个bison语法来更好地匹配更多的XML。至少我已经解释过,教程的时尚,发生了什么以及使它与你的样本数据集一起工作的一种方法。
非常感谢!如何调整flex的调试? –
发现它(:必须编译flex而不使用-d选项。 –