为什么在使用 Bison 的 C 语法分析期间无法识别已定义的标记?
Why is a defined token not recognized during syntax analysis in C using Bison?
我目前正在为给定的语法开发一个简单的中缀到后缀编译器。我目前处于语法分析阶段。我已经使用 Flex 库编写了一个词法分析器,但是我遇到了一个看似简单的问题。下面的信息似乎需要处理很多,但我认为这个问题对于任何在编译器构造方面有一定经验的人来说都是相当基础的。
这是我的词法分析器:
%{
#include <stdlib.h>
#include "global.h"
int lineno = 1, tokenval = NONE;
%}
letter [A-Za-z]
digit [0-9]
id {letter}({letter}|{digit})*
%option noinput
%option nounput
%%
[ \t]+ {}
\n {lineno++;}
{digit}+ {tokenval = atoi(yytext);
printf("digit\n");
return NUM;}
{id} {int p;
p = lookup(yytext);
if(p==0){
p = insert(yytext, ID);
}
tokenval = p;
return symtable[p].token;
}
<<EOF>> {return DONE;}
. {tokenval = NONE;
return yytext[0];}
这里没什么特别的,只是定义一些标记并处理它们。
还有我的 parser.y 文件:
%{
#include "global.h"
%}
%token digit
%%
start: line {printf("success!\n");};
line: expr ';' line | expr ;
expr: digit;
%%
void yyerror(char const *s)
{
printf("error\n");
};
int main()
{
yyparse();
return 0;
}
问题在线:
expr: digit;
编译器显然对 digit
标记有一些问题,因为如果我用数字以外的任何常量代替,它一切正常,像 -;
或 [=16= 这样的表达式] 将被接受。我不知道为什么会这样,尤其是我很确定我的词法分析器工作正常。
global.h
文件只是其他文件的链接,包含必要的函数原型和任何必要变量的链接:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#define BSIZE 128
#define NONE -1
#define EOS '[=13=]'
#define NUM 256
#define DIV 257
#define MOD 258
#define ID 259
#define DONE 260
extern int tokenval;
extern int lineno;
struct entry
{
char *lexptr;
int token;
};
extern struct entry symtable[];
int insert (char s[], int tok);
void error (char *m) ;
int lookup (char s[]) ;
void init () ;
void parse () ;
int yylex (void) ;
void expr () ;
void term () ;
void factor () ;
void match (int t) ;
void emit (int t, int tval) ;
void yyerror(char const *s);
您的扫描器 returns NUM 当它找到一个数字序列时,而不是 digit。标识符 digit 仅在您的 Flex 规范内部使用。
然后你有 another digit 在你的 Bison 语法中定义为一个标记,但它没有以任何方式连接到 Flex一.
要解决此问题,请在您的 Bison 语法中使用 NUM,并作为来自词法分析器的 return 值。不要自己用 #define 声明它,而是让 Bison 根据您的 %token 定义创建这些声明。您可以使用 -d 标志让 Bison 输出头文件。 运行 Bison before Flex,以及 #include Bison 的输出头文件,其中包含 NUM,在您的 Flex 代码中。
我目前正在为给定的语法开发一个简单的中缀到后缀编译器。我目前处于语法分析阶段。我已经使用 Flex 库编写了一个词法分析器,但是我遇到了一个看似简单的问题。下面的信息似乎需要处理很多,但我认为这个问题对于任何在编译器构造方面有一定经验的人来说都是相当基础的。
这是我的词法分析器:
%{
#include <stdlib.h>
#include "global.h"
int lineno = 1, tokenval = NONE;
%}
letter [A-Za-z]
digit [0-9]
id {letter}({letter}|{digit})*
%option noinput
%option nounput
%%
[ \t]+ {}
\n {lineno++;}
{digit}+ {tokenval = atoi(yytext);
printf("digit\n");
return NUM;}
{id} {int p;
p = lookup(yytext);
if(p==0){
p = insert(yytext, ID);
}
tokenval = p;
return symtable[p].token;
}
<<EOF>> {return DONE;}
. {tokenval = NONE;
return yytext[0];}
这里没什么特别的,只是定义一些标记并处理它们。
还有我的 parser.y 文件:
%{
#include "global.h"
%}
%token digit
%%
start: line {printf("success!\n");};
line: expr ';' line | expr ;
expr: digit;
%%
void yyerror(char const *s)
{
printf("error\n");
};
int main()
{
yyparse();
return 0;
}
问题在线:
expr: digit;
编译器显然对 digit
标记有一些问题,因为如果我用数字以外的任何常量代替,它一切正常,像 -;
或 [=16= 这样的表达式] 将被接受。我不知道为什么会这样,尤其是我很确定我的词法分析器工作正常。
global.h
文件只是其他文件的链接,包含必要的函数原型和任何必要变量的链接:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#define BSIZE 128
#define NONE -1
#define EOS '[=13=]'
#define NUM 256
#define DIV 257
#define MOD 258
#define ID 259
#define DONE 260
extern int tokenval;
extern int lineno;
struct entry
{
char *lexptr;
int token;
};
extern struct entry symtable[];
int insert (char s[], int tok);
void error (char *m) ;
int lookup (char s[]) ;
void init () ;
void parse () ;
int yylex (void) ;
void expr () ;
void term () ;
void factor () ;
void match (int t) ;
void emit (int t, int tval) ;
void yyerror(char const *s);
您的扫描器 returns NUM 当它找到一个数字序列时,而不是 digit。标识符 digit 仅在您的 Flex 规范内部使用。
然后你有 another digit 在你的 Bison 语法中定义为一个标记,但它没有以任何方式连接到 Flex一.
要解决此问题,请在您的 Bison 语法中使用 NUM,并作为来自词法分析器的 return 值。不要自己用 #define 声明它,而是让 Bison 根据您的 %token 定义创建这些声明。您可以使用 -d 标志让 Bison 输出头文件。 运行 Bison before Flex,以及 #include Bison 的输出头文件,其中包含 NUM,在您的 Flex 代码中。