我正在Bison中编写一个基本编译器的解析器(然后将其扩展为包含子例程和动态内存分配)。语法在龙书的附录A中定义。我的Flex扫描仪工作 - 我通过它运行我的测试文件,它打印出它找到的所有正确的标记。对于下面的奇怪格式抱歉。我在emacs中的野牛和弹性模式有点乱,所以我只是使用C模式,直到我修复。
%{
#include <stdio.h>
#define YYERROR_VERBOSE 1066
extern FILE* yyin ;
extern int yylineno ;
extern char* yytext ;
extern int yylex() ;
extern void yyerror() ;
int YYDEBUG = 1 ;
%}
/* Tokens */
%token AND BASIC BREAK DO ELSE EQ FALSE
%token GREQ ID IF INDEX LEEQ MINUS NOEQ NUM OR REAL TEMP TRUE WHILE
/* Grammar rules from Appendix A */
%%
program: block { printf( "Matched program\n" ) ; }
;
block: '{' decls stmts '}' { printf( " Matched block\n" ) ; }
;
decls: decls decl |
;
decl: type ID ';'
;
type: type '[' NUM ']' | BASIC
;
stmts: stmts stmt |
;
stmt: loc '=' bool ';'
| IF '(' bool ')' stmt
| IF '(' bool ')' stmt ELSE stmt
| WHILE '(' bool ')' stmt
| DO stmt WHILE '(' bool ')' ';'
| BREAK ';'
| block
;
loc: loc '[' bool ']' | ID
;
bool: bool OR join | join
;
join: join AND equality | equality
;
equality: equality EQ rel | equality NOEQ rel | rel
;
rel: expr '<' expr | expr LEEQ expr | expr GREQ expr | expr '>' expr | expr
;
expr: expr '+' term | expr '-' term | term
;
term: term '*' unary | term '/' unary | unary
;
unary: '!' unary | '-' unary | factor
;
factor: '(' bool ')' | loc | NUM | REAL | TRUE | FALSE
;
%%
/*
* Additional C Code
* Main Routine
* yyerror()
*/
int main( int argc, char *argv[] ) {
int i ;
if ( argc < 2 ) {
fprintf( stderr, "No input files.\n\n" ) ;
return 1 ;
}
for ( i = 0 ; i < argc ; i++ ) {
yyin = fopen( argv[i], "r" ) ;
if ( !yyin ) {
fprintf( stderr, "Error opening file: %s.\n\n", argv[i] ) ;
return 1 ;
}
yyparse() ;
}
return 0 ;
}
void yyerror( char *s ) {
/* fprintf( stderr, "Error parsing - %d: %s at %s\n", yylineno, s, yytext ) ; */
fprintf( stderr, "Error parsing - %d: %s at %s\n", yylineno, s, yytext ) ;
}
我觉得我可能会遗漏一些重要的东西。我不认为这是规则。我将yyin设置为argv []中提供的输入文件。错误是
解析时出错 - 1:语法错误,意外为TRUE,期待'{'at
解析时出错 - 1:语法错误,意外为FALSE,期待ELF上的'{'
非常感谢任何帮助!
编辑:如果我将主函数更改为不设置yyin(因此yyparse只是从stdin读取),我得到了这个:
{int x; }
解析时出错 - 1:语法错误,意外为TRUE,在{
预期'{'我不明白这是怎么回事......
答案 0 :(得分:2)
当我使用存根yylex运行上面的示例输入时,输入程序匹配。我假设“int”标记为BASIC。 (你还需要修复“retrun”。)
您需要调试词法分析器。附加一个调试器,以便您可以看到它返回的内容,或者在yylex的末尾添加一个print语句。
这取代了底部的所有内容:
%%
FILE* yyin = NULL;
int yylineno = 0;
char* yytext = NULL;
int main()
{
yyparse() ;
return 0 ;
}
void yyerror( char *s )
{
fprintf( stderr, "Error parsing - %d: %s at %s\n", yylineno, s, yytext ) ;
}
int yylex()
{
static int i = 0;
static int tokens[] = { '{', BASIC, ID, ';', '}' };
int tok = tokens[i];
yylineno++;
i++;
return tok;
}
答案 1 :(得分:0)
如果没有在同一输入上看到标记化器的输出,则很难说解析器失败的位置。
我自己,我将所有内容都标记,将'{'和'}'转换为LC和RC等,以确保标记器中唯一出现的是严格处理的令牌。这样可以更容易地确定源文件的每个字符的处理位置。
如果将源文件的每个标记移动到单独的行,例如
{
int
x
;
}
报告了什么错误?