在bison中调用c函数

标签 c bison

我正在尝试 .y 文件中的 C 文件中的函数

lex 文件如下所示

%{


#include "Expression.h"
#include "Parser.h"

#include <stdio.h>

%}

%option outfile="Lexer.c" header-file="Lexer.h"
%option warn nodefault

%option reentrant noyywrap never-interactive nounistd
%option bison-bridge

LPAREN      "("
RPAREN      ")"
PLUS        "+"
MULTIPLY    "*"


ALPHABET    [a-z]+
NUMBER      [0-9]+
WS          [ \r\n\t]*

%%
 /* Rules */
{WS}            { /* Skip blanks. */ }
{NUMBER}        { sscanf_s(yytext, "%d", &yylval->value); return TOKEN_NUMBER; }
{ALPHABET}      { sscanf_s(yytext, "%c", &yylval->value);printf("%s",yytext); return TOKEN_ALPHABET;}
{MULTIPLY}      { return TOKEN_MULTIPLY; }
{PLUS}          { return TOKEN_PLUS; }
{LPAREN}        { return TOKEN_LPAREN; }
{RPAREN}        { return TOKEN_RPAREN; }
.               {  }

%%

int yyerror(const char *msg) {
    fprintf(stderr,"Error:%s\n",msg);
    return 0;
}

yacc 文件是

%{

/*
 * Parser.y file
 * To generate the parser run: "bison Parser.y"
 */

#include "Expression.h"
#include "Parser.h"
#include "Lexer.h"

int yyerror(SExpression **expression, yyscan_t scanner, const char *msg);

%}

%code requires {

#ifndef YY_TYPEDEF_YY_SCANNER_T
#define YY_TYPEDEF_YY_SCANNER_T
typedef void* yyscan_t;
#endif

}

%output  "Parser.c"
%defines "Parser.h"

%define api.pure
%lex-param   { yyscan_t scanner }
%parse-param { SExpression **expression }
%parse-param { yyscan_t scanner }
%parse-param { char **str}
%union {

    int value;
    SExpression *expression;
}

%left '+' TOKEN_PLUS
%left '*' TOKEN_MULTIPLY

%token <value> TOKEN_ALPHABET
%token TOKEN_LPAREN
%token TOKEN_RPAREN
%token TOKEN_PLUS
%token TOKEN_MULTIPLY
%token <value> TOKEN_NUMBER

%type <expression> expr
%type <expression> l
%%
letters: l {}
    l: TOKEN_ALPHABET {printf("alphabet",$1); $$ = createAlphabet( $1);}
    ;

input
    : letters { printf("alphabet"); }
    ;

expr
    : expr TOKEN_PLUS expr { $$ = createOperation( ePLUS, $1, $3 ); }
    | expr TOKEN_MULTIPLY expr { $$ = createOperation( eMULTIPLY, $1, $3 ); }
    | TOKEN_LPAREN expr TOKEN_RPAREN { $$ = $2; }
    | TOKEN_NUMBER { $$ = createNumber($1); }
    ;


%%

我尝试调用的函数在 expression.h 中声明并包含在 yacc 文件中。 其功能是

char **createAlphabet(char str[])
{
    char b[100];
    b[0] = str[0];

    if (b == NULL)
        return NULL;

    //b->left = left;

    return &b;

}

但是当我在这个函数中放置断点时,形式参数将没有正确的值。它说读取字符串字符时出错。

谁能告诉我可能出了什么问题吗?我很确定有很多错误,我想这有点模糊,但我想知道从 .y 文件调用 c 文件中的函数的正确方法

谢谢!

最佳答案

首先,您必须使用正确的参数类型来调用它。我确信您忽略了有关此的编译器警告。

您已声明 TOKEN_ALPHABET有类型标签value其类型为 int ,并且您的扫描仪代码尝试填写 value yylval的成员与单个字符的 union 。 (尽管你用几乎可以想象到的最复杂的方式来做到这一点。 yylval->value = yytext[0] 会工作得很好,但你这样做的方式是不正确的,因为 sscanf 期望 char* 而不是 int* 。你的编译器应该有也警告过您这一点。)

但是,在您的 Bison 操作中,您随后调用 createAlphabet($1) ,其中$1TOKEN_ALPHABET token (因此是 int ),但是 createAlphabet宣布收到 char[]争论。在 C 中,用作形式参数的数组会衰减为指针,因此您实际上是在声明 createAlphabet获取指向字符串 ( char* ) 的指针并给它一个整数。将小整数视为指针是官方未定义的行为,但我可以告诉您事情将如何表现:您的程序将因段错误而终止。 (通常的 UB 免责声明适用。)

即使这没有发生,您也会立即返回局部变量的地址,这是一个悬空指针;任何使用createAlphabet的返回值的尝试也是未定义的行为,但其后果更难以预测,因此更危险。

b 是不可能的成为NULL , 顺便一提。如果您的编译器没有警告您这一点,那是因为您没有使用正确的编译器标志进行编译;您应该始终启用所有警告并注意它们。

除此之外,您尝试从 bison 生成的解析器调用 C 函数的方式没有任何问题。这些问题几乎都与 C 编程有关。

关于在bison中调用c函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28491344/

相关文章:

c - 我无法纠正此 C 代码中的错误,该代码接受用户输入以使用 scanf 填充二维数组

c++ - 如何解决while/while解析中的shift/reduce冲突

c - 为什么我的 bison/flex 没有按预期工作?

bison - Lex/Yacc : Print message before input

c++ - Flex++ Bisonc++ 解析器

c - 如何使用exec函数启动登录shell(csh)?

c++ - 多窗口 CMD

bison - 为什么 yylval 为空?

c - IRC 程序不打印最后一条消息

c - MASM:从程序集访问全局 C 变量