我试图创建一个简单的解析器/编译器,主要用于家庭作业,但最终用于学习目的和乐趣。我已经写了词法分析器和解析器文件(对于命令的初始子集),我想输出一个AST。但是,我遇到了#34;语法错误"消息,即使我试图解析一个简单的&1; 1 + 1'。这是词法分析器文件:
%{
#include "parser.tab.h"
%}
DIGIT [0-9]
LETTER [a-zA-Z]
%%
[ \t\n] ;
{DIGIT}+ {yylval = atoi(yytext); return NUMBER;}
{LETTER}* { if (strlen(yytext) <= 8){
printf( "<ID, %s> ", yytext );
} else {
yytext[8] = '\0';
printf("WARNING! Long identifier. Truncating to 8 chars\n");
printf( "<ID, %s> ", yytext );
}
}
"+" {printf("Found '+' symbol\n");return(PLUS);}
"-" return(MINUS);
"*" return(TIMES);
"/" return(DIVIDE);
"(" return(LEFT_PARENTHESIS);
")" return(RIGHT_PARENTHESIS);
<<EOF>> return(END_OF_FILE);
%%
int yywrap (void) {return 1;}
这是解析器文件:
%{
#include <stdio.h>
/*#include "tree.h"
#include "treedefs.h"*/
int yylex();
#define YYSTYPE int
%}
%start program
%token NUMBER
%token ID
%token PLUS MINUS TIMES EQUAL
%token LEFT_PARENTHESIS RIGHT_PARENTHESIS
%token LET IN AND
%token END_OF_FILE
%left PLUS MINUS
%left TIMES DIVIDE
%%
program: /* empty */
| exp { printf("Result: %d\n", $1); }
| END_OF_FILE {printf("Encountered EOF\n");}
;
exp: NUMBER { $$ = $1;}
| exp PLUS exp { $$ = $1 + $3; }
| exp TIMES exp { $$ = $1 * $3; }
| '(' exp ')' { $$ = $2;}
;
%%
int yyerror (char *s) {fprintf (stderr, "%s\n", s);
}
另外,我已经创建了一个main.c,以分别保持main()函数。您可以省略树* .h文件,因为它们只包含相对于AST的函数。
#include <stdio.h>
#include <stdlib.h>
#include "tree.h"
#include "treedefs.h"
int main(int argc, char **argv){
yyparse();
TREE *RootNode = malloc(sizeof(TREE));
return 0;
}
我已经阅读了大量的例子,但我找不到与我写的东西(非常)不同的东西。我究竟做错了什么?任何帮助,将不胜感激。
答案 0 :(得分:0)
代码存在一些问题。
首先,你的词法分析者应该包括:
%{
#include "parser.tab.h"
extern int yylval; // this line was missing
%}
其次,假设您希望在语句结束时评估代码,则必须在语句结尾处包含规则。也就是说,假设它是面向行的,您可以用以下内容替换当前的空白规则:
[ \t] {}
[\n] { return 0; }
第三,你的一条线是被吹的。而不是:
printf("WARNING! Long identifier. Truncating to 8 chars\n"$
应该是这样的:
printf("WARNING! Long identifier. Truncating to 8 chars\n");
答案 1 :(得分:0)
您的语法接受表达式或文件结尾。因此,如果您给它一个表达式后跟一个文件结尾,则会出现错误。
另一个问题是你在输入的末尾返回了令牌END_OF_FILE
,而不是0
- 野牛期待EOF令牌的0
并且会给出一个语法错误,如果它没有在输入的末尾看到一个。
对这两者最简单的解决方法是删除END_OF_FILE
令牌并让<<EOF>>
规则返回0.然后你的语法变为:
program: /* empty */ { printf("Empty input\n"); }
| exp { printf("Result: %d\n", $1); }
;
...rest of the grammar
现在你有(潜在的)问题,你的语法只接受一个表达式。您可能希望支持由换行符或其他分隔符分隔的多个表达式(可能是;
?),这可以通过多种方式完成。