gpt4 book ai didi

使用 Flex 和 Bison 创建解析器的输入函数

转载 作者:行者123 更新时间:2023-11-30 15:08:21 25 4
gpt4 key购买 nike

我对 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 文件,请告诉我

最佳答案

getCode 完全错误。这和比森无关。一次一个字符地读取整个文件是愚蠢的;将每个字符连接到字符串的末尾具有二次执行时间,因为每个连接都需要扫描整个字符串,并且在任何情况下,您都不会为您尝试构造的字符串分配任何内存;您从不检查是否已使用了字符串的所有内存分配,并且您似乎相信 char 是单字符字符串,即使从类型中可以明显看出 char 和 char* 完全是不同的。 (这不是该函数问题的完整列表。)strcat 需要两个字符串,而不是一个字符串和一个字符。

从flex/bison的角度来看,由于flex了解如何读取输入文件,因此您自己读取文件实际上没有意义。您所需要做的就是打开一个FILE*并安排flex生成的扫描仪来读取它。 Flex 手册中有关多个输入缓冲区的部分显示了实现此目的的一种方法。另一种方法是使用可重入扫描器和解析器,并递归调用解析器。

在解析器中调用 getCode 时,您将其返回值(const char *)分配给 stmt 的语义值 ($$) ,但stmt具有类型标记nPtr,因此赋值是类型错误。

关于使用 Flex 和 Bison 创建解析器的输入函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37381170/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com