我是C的新手,对Flex和Bison来说更新。我正在为一个项目编写一个简单的解析器。我试图能够创建一个加载命令,以便我可以从外部文件加载代码并让解析器运行它。这是我的代码:
Bison(spire.y):
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include "helper.h"
/* prototypes */
nodeType *opr(int oper, int nops, ...);
nodeType *id(int i);
nodeType *con(int value);
void freeNode(nodeType *p);
int ex(nodeType *p);
int yylex(void);
void yyerror(char *s);
int sym[26]; /* symbol table */
%}
%union {
int iValue; /* integer value */
char sIndex; /* symbol table index */
char *var;
char *str;
nodeType *nPtr; /* node pointer */
};
%token <iValue> INTEGER
%token <sIndex> VARIABLE
%token <var> VARNAME
%token <str> STRING
%token WHILE IF TELL EXITCOMM LOAD
%nonassoc IFX
%nonassoc ELSE
%left GE LE EQ NE '>' '<' BLKND
%left '+' '-'
%left '*' '/'
%nonassoc UMINUS
%type <nPtr> stmt expr stmt_list
%%
spire:
code { exit(0); }
;
code:
code stmt { ex($2); freeNode($2); }
| /* NULL */
;
stmt:
';' { $$ = opr(';', 2, NULL, NULL); }
| expr ';' { $$ = $1; }
| EXITCOMM {exit(EXIT_SUCCESS); }
| LOAD STRING ';' { char *f = $2; f++[strlen(f)-1] = 0; $$ = getCode(f); }
...
%%
...
const char * getCode(char *fileName){
char ch;
char *code;
FILE *fp;
fp = fopen(fileName, "r");
if( fp == NULL )
{
printf("Error while opening the file %s.\n", fileName);
return ';';
}else{
while((ch = fgetc(fp))!=EOF)
code = strcat(code, ch);
fclose(fp);
return code;
}
FLEX(spire.l):
%{
#include <stdlib.h>
#include "helper.h"
#include "spire.tab.h"
void yyerror(char *);
%}
%%
[a-z] {
yylval.sIndex = *yytext - 'a';
return VARIABLE;
}
0 {
yylval.iValue = atoi(yytext);
return INTEGER;
}
[1-9][0-9]* {
yylval.iValue = atoi(yytext);
return INTEGER;
}
[-()<>^=+*/;{}~."] {
return *yytext;
}
'~' return EXITCOMM;
"^^" return BLKND;
">=" return GE;
"<=" return LE;
"==" return EQ;
"!=" return NE;
"while" return WHILE;
"if" return IF;
"else" return ELSE;
"tell" return TELL;
"load" return LOAD;
[a-z][a-zA-Z0-9_]* {
yylval.var = strdup(yytext);
return VARNAME;
}
\"[^"\n]*["\n] {
yylval.str = strdup(yytext);
return STRING;
}
[ \t\n]+ ; /* ignore whitespace */
. yyerror("Unknown character");
%%
int yywrap(void) {
return 1;
}
以下是我得到的错误加载,每当我尝试修复错误时,我就会得到更多错误。
错误:
spire.y: In function 'yyparse':
spire.y:56: warning: assignment makes pointer from integer without a cast
spire.y: At top level:
spire.y:112: error: conflicting types for 'getCode'
spire.y:56: note: previous implicit declaration of 'getCode' was here
spire.y: In function 'getCode':
spire.y:122: warning: return makes pointer from integer without a cast
spire.y:125: warning: passing argument 2 of 'strcat' makes pointer from integer without a cast
/usr/include/string.h:136: note: expected 'const char * __restrict__' but argument is of type 'char'
spire.y:208: error: expected declaration or statement at end of input
如果您想要整个Bison文件,请告诉我
答案 0 :(得分:1)
getCode
完全错了。这与野牛无关。一次读一个整个文件是愚蠢的;将每个字符连接到字符串的末尾具有二次执行时间,因为需要针对每个连接扫描整个字符串,并且在任何情况下,您永远不会为您正在尝试构造的字符串分配任何内存;你永远不会检查你是否已经将所有内存allocatef用于字符串,并且你似乎相信char是一个单字符的字符串,即使从char和char *完全是类型的字符串应该是明显的不同。 (这不是该函数问题的完整列表。)strcat
需要两个字符串,而不是字符串和字符。
从flex / bison的角度来看,由于flex了解如何读取输入文件,因此自己无需阅读文件。您需要做的就是打开FILE*
并安排flex生成的扫描程序读取它。一种方法是在Flex手册的多输入缓冲区一节中显示。另一种方法是使用可重入的扫描程序和解析器,并递归调用解析器。
如果在解析器中调用getCode
,则将其返回值(const char *)分配给$$
的语义值(stmt
),但stmt
具有类型标记nPtr,因此赋值是类型错误。