Flex/Bison:yytext跳过一个值 [英] Flex/Bison: yytext skips over a value
问题描述
我已经花了两天的时间试图弄清楚该程序为何采用这种方式.对于一个类项目,我试图编写一个解析地址并以某种方式输出地址的程序.在我真正进入程序的输出部分之前,我只想确保Bison-fu实际上是正确的,并正确输出一些调试信息.
I've been racking my brain for two days trying to figure out why the program is behaving this way. For a class project, I'm trying to write a program that parses an address and outputs it a certain way. Before I actually get to the output portion of the program, I just wanted to make sure my Bison-fu was actually correct and outputting some debugging information correctly.
Flex和Bison看起来好像很好地相互协作,正如预期的那样,但是由于某种原因,当我解析地址的第三行时,yytext只是跳过了邮政编码,直接转到新行.
It looks as if Flex and Bison are cooperating with each other nicely, as expected, but for some reason, when I get to the parsing of the third line of the address, yytext just skips over the zip code and goes straight to the new line.
以下是我测试过的Flex和Bison文件的精简版本,但仍输出与完整版本相同的内容:
Below is a stripped down version of my Flex and Bison files that I tested and still outputs the same thing as the full version:
[19:45]<Program4> $ cat scan.l
%option noyywrap
%option nounput
%option noinput
%{
#include <stdlib.h>
#include "y.tab.h"
#include "program4.h"
%}
%%
[\ \t]+ { /* Eat whitespace */}
[\n] { return EOLTOKEN; }
"," { return COMMATOKEN; }
[0-9]+ { return INTTOKEN; }
[A-Za-z]+ { return NAMETOKEN; }
[A-Za-z0-9]+ { return IDENTIFIERTOKEN; }
%%
/*This area just occupies space*/
[19:45]<Program4> $ cat parse.y
%{
#include <stdlib.h>
#include <stdio.h>
#include "program4.h"
%}
%union {int num; char id[20]; }
%start locationPart
%expect 0
%token <num> NAMETOKEN
%token <num> EOLTOKEN
%token <num> INTTOKEN
%token <num> COMMATOKEN
%type <id> townName zipCode stateCode
%%
/* Entire block */
locationPart: townName COMMATOKEN stateCode zipCode EOLTOKEN
{ printf("Rule 12: LP: TN COMMA SC ZC EOL: %s\n", yytext); }
| /* bad location part */
{ printf("Rule 13: LP: Bad location part: %s\n", yytext); }
;
/* Lil tokens */
townName: NAMETOKEN
{ printf("Rule 23: TN: NAMETOKEN: %s\n", yytext); }
;
stateCode: NAMETOKEN
{ printf("Rule 24: SC: NAMETOKEN: %s\n", yytext); }
;
zipCode: INTTOKEN DASHTOKEN INTTOKEN
{ printf("Rule 25: ZC: INT DASH INT: %s\n", yytext); }
| INTTOKEN
{ printf("Rule 26: ZC: INT: %s\n", yytext); }
;
%%
int yyerror (char const *s){
extern int yylineno; //Defined in lex
fprintf(stderr, "ERROR: %s at symbol \"%s\"\n at line %d.\n", s, yytext,
yylineno);
exit(1);
}
[19:45]<Program4> $ cat addresses/zip.txt
Rockford, HI 12345
[19:45]<Program4> $ parser < addresses/zip.txt
Operating in parse mode.
Rule 23: TN: NAMETOKEN: Rockford
Rule 24: SC: NAMETOKEN: HI
Rule 26: ZC: INT:
Rule 12: LP: TN COMMA SC ZC EOL:
Parse successful!
[19:46]<Program4> $
如您在底部附近看到的那样,它会打印规则26:ZC:INT:
,但无法打印5位数的邮政编码.就像程序只是跳过数字并存储换行符一样.有什么想法为什么它不存储和打印邮政编码?
As you can see near the bottom, it prints Rule 26: ZC: INT:
but fails to print the 5 digit zip code. It's like the program just skips the number and stores the newline instead. Any ideas why it won't store and print the zip code?
注意:
- yytext在我的.h文件中定义为外部元素(不在此处发布);
- 我正在使用
-vdy
标志来编译parse.c文件
- yytext is defined as an extern in my .h file (not posted here);
- I am using the
-vdy
flags to compile the parse.c file
推荐答案
由于 yytext
是全局变量,因此已被覆盖,因此您必须将其复制到 lex 中脚本.在纯解析器中,即使它不再是全局的,它仍然可以重用并作为参数传递,因此像您尝试的那样使用它的值是不正确的.
Because yytext
is a global variable, it's overwritten and you will have to copy it in your lex script. In a pure parser, even though it's not global anymore it's still reused and passed as a parameter so it's incorrect to use it's value like you are attempting.
此外,请勿在野牛中使用它,而应使用 $ n
,其中 n
是标记在规则中的位置.您可能需要将%union
指令更改为类似的
Also, don't use it in bison, instead use $n
where n
is the position of the token in the rule. You probably need the %union
directive changed to something like
%union {
int number;
char *name;
};
因此在 flex 文件中,如果要捕获文本,请执行类似的操作
So in the flex file, if you want to capture the text do something like
[A-Za-z]+ { yylval.name = strdup(yytext); return NAMETOKEN; }
请记住,不要在 bison 中使用 yytext
,这是词法分析器使用的内部工具.
and remember, do not use yytext
in bison, it's an internal thing used by the lexer.
然后,由于您已经定义了邮政编码的类型
Then and since you have defined a type for the zip code
/* Entire block */
locationPart: townName COMMATOKEN stateCode zipCode EOLTOKEN {
printf("Rule 12: LP: TN COMMA SC ZC EOL: town:%s, stateCode:%d zip-code:%s\n", $1, $3, $4);
}
这篇关于Flex/Bison:yytext跳过一个值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!