纠正 lex 和 yacc 中的一些简单逻辑错误
请帮助我解决我在示例中遇到的两个简单的逻辑错误。
以下是详细信息:
输入文件:(input.txt)
名字:James
姓氏:史密斯
普通文本
输出文件:(output.txt) - [有两个逻辑错误]
名称是:James
姓名是:姓氏:Smith
名称是:普通文本
我期望的输出(而不是上面的行)-[没有逻辑错误]
名称是:James
名字是:史密斯
普通文本
换句话说,我不希望将姓氏发送到输出,并且如果普通文本写在“名字:”或“姓氏:”之后,我也希望匹配普通文本。
这是我的 lex 文件 (example.l):
%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "y.tab.h"
/* prototypes */
void yyerror(const char*);
/* Variables: */
char *tempString;
%}
%START sBody
%%
"FirstName:" { BEGIN sBody; }
"LastName:" { BEGIN sBody; }
.? { return sNormalText; }
\n /* Ignore end of line */;
[ \t]+ /* Ignore whitespace */;
<sBody>.+ {
tempString = (char *)calloc(strlen(yytext)+1, sizeof(char));
strcpy(tempString, yytext);
yylval.sValue = tempString;
return sText;
}
%%
int main(int argc, char *argv[])
{
if ( argc < 3 )
{
printf("Please you need two args: inputFileName and outputFileName");
}
else
{
yyin = fopen(argv[1], "r");
yyout = fopen(argv[2], "w");
yyparse();
fclose(yyin);
fclose(yyout);
}
return 0;
}
这是我的 yacc 文件: (example.y):
%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "y.tab.h"
void yyerror(const char*);
int yywrap();
extern FILE *yyout;
%}
%union
{
int iValue;
char* sValue;
};
%token <sValue> sText
%token <sValue> sNormalText
%%
StartName: /* for empty */
| sName StartName
;
sName:
sText
{
fprintf(yyout, "The Name is: %s\n", $1);
}
|
sNormalText
{
fprintf(yyout, "%s\n", $1);
}
;
%%
void yyerror(const char *str)
{
fprintf(stderr,"error: %s\n",str);
}
int yywrap()
{
return 1;
}
如果您能帮助我纠正这些简单的逻辑错误,我将不胜感激。
预先感谢您的帮助和阅读我的帖子。
Please i need help in solving those two simple logic errors that i am facing in my example.
Here are the details:
The Input File: (input.txt)
FirstName:James
LastName:Smith
normal text
The output File: (output.txt) - [with two logic errors]
The Name is: James
The Name is: LastName:Smith
The Name is: normal text
What I am expecting as output (instead of the above lines) - [without logical errors]
The Name is: James
The Name is: Smith
normal text
In other words, i don't want the lastName to be sent to output, and i want to match normal text as well if it is written after the "FirstName:" or "LastName:".
Here is my lex File (example.l):
%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "y.tab.h"
/* prototypes */
void yyerror(const char*);
/* Variables: */
char *tempString;
%}
%START sBody
%%
"FirstName:" { BEGIN sBody; }
"LastName:" { BEGIN sBody; }
.? { return sNormalText; }
\n /* Ignore end of line */;
[ \t]+ /* Ignore whitespace */;
<sBody>.+ {
tempString = (char *)calloc(strlen(yytext)+1, sizeof(char));
strcpy(tempString, yytext);
yylval.sValue = tempString;
return sText;
}
%%
int main(int argc, char *argv[])
{
if ( argc < 3 )
{
printf("Please you need two args: inputFileName and outputFileName");
}
else
{
yyin = fopen(argv[1], "r");
yyout = fopen(argv[2], "w");
yyparse();
fclose(yyin);
fclose(yyout);
}
return 0;
}
Here is my yacc file: (example.y):
%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "y.tab.h"
void yyerror(const char*);
int yywrap();
extern FILE *yyout;
%}
%union
{
int iValue;
char* sValue;
};
%token <sValue> sText
%token <sValue> sNormalText
%%
StartName: /* for empty */
| sName StartName
;
sName:
sText
{
fprintf(yyout, "The Name is: %s\n", $1);
}
|
sNormalText
{
fprintf(yyout, "%s\n", $1);
}
;
%%
void yyerror(const char *str)
{
fprintf(stderr,"error: %s\n",str);
}
int yywrap()
{
return 1;
}
Please if you can help me out correcting those simple logical errors, i will be grateful.
Thanks in advance for your help and for reading my post.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
部分问题是你进入状态“sBody”,但你永远不会回到初始状态 0。
另一个问题 - 还不是一个主要问题 - 是你使用右递归语法规则而不是(对于 Yacc 来说是自然的) ) 左递归规则:
vs
将
BEGIN 0;
添加到
Lex 规则改进了很多;剩下的麻烦是,对于普通文本中的每个字母,输出文件中都会多一行“Smith”。您需要检查如何将值返回到语法中。通过在返回
sNormalText
的规则中的 return 之前添加yylval.sValue = yytext;
,我得到了“预期”输出。example.l
example.y
output.txt
将 yywrap() 与词法分析器一起放入而不是与语法一起放入可能更有意义。我在代码中留下了简洁的调试打印 - 它们帮助我了解出了什么问题。
您需要使用“
.?
”规则才能完整返回正常文本。您可能还需要在文件中移动它 - 启动状态是稍微特殊的生物。当我将规则更改为“.+
”时,Flex 向我发出警告:这些行引用了空白/制表符和 sBody 规则。在 sBody 规则之后移动不合格的“
.+
”删除了警告,但似乎没有达到预期的效果。玩得开心...Part of the trouble is that you move into state 'sBody' but you never move back to the initial state 0.
Another problem - not yet a major one - is that you use a right-recursive grammar rule instead of the (natural for Yacc) left-recursive rule:
vs
Adding
BEGIN 0;
to the<sBody>
Lex rule improves things a lot; the remaining trouble is that you get one more line 'Smith' in the output file for each single letter in the normal text. You need to review how the value is returned to your grammar.By adding
yylval.sValue = yytext;
before the return in the rule that returnssNormalText
, I got the 'expected' output.example.l
example.y
output.txt
It might make more sense to put
yywrap()
in with the lexical analyzer rather than with the grammar. I've left the terse debugging prints in the code - they helped me see what was going wrong.You'll need to play with the '
.?
' rule to get normal text returned in its entirety. You may also have to move it around the file - start states are slightly peculiar critters. When I changed the rule to '.+
', Flex gave me the warning:These lines referred to the blank/tab and sBody rules. Moving the unqualified '
.+
' after the sBody rule removed the warnings, but didn't seem to do what was wanted. Have fun...