[英]calling c function in 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文件中调用ac文件中函数的正确方法
谢谢!
首先,您必须使用正确的参数类型来调用它。 我敢肯定,您会忽略有关此的编译器警告。
您已声明TOKEN_ALPHABET
具有类型标记value
int
类型,并且您的扫描器代码尝试用单个字符填充yylval
联合的value
成员。 (尽管您以几乎可以想象到的最复杂的方式执行此操作yylval->value = yytext[0]
可以正常工作,并且由于sscanf
期望使用char*
而不是int*
,所以这样做也不正确。也应该警告过您。)
但是,在野牛动作中,您随后调用createAlphabet($1)
,其中$1
是TOKEN_ALPHABET
令牌(因此是int
),但是createAlphabet
被声明为接收char[]
参数。 在C语言中,用作形式参数的数组会衰减为指针,因此您可以有效地声明createAlphabet
来获取指向字符串( char*
)的指针,并为其指定一个整数。 将小整数视为指针是官方未定义的行为,但是我可以告诉您事情的表现:您的程序将因段错误而死亡。 (通常的UB免责声明适用。)
即使这种情况没有发生,您也可以立即返回局部变量的地址,该变量是一个悬空的指针。 使用createAlphabet
的返回值的任何尝试也是未定义的行为,但是其后果可预测性要低得多,因此更加危险。
顺便说一下, b
不可能为NULL
。 如果您的编译器没有警告您,那是因为您没有使用正确的编译器标志进行编译; 您应该始终启用所有警告,并注意它们。
除此之外,尝试从bison生成的解析器调用C函数的方式没有任何问题。 问题实际上几乎全部与C编程有关。
将%c与sscanf一起使用,将期望使用char参数,而不是int。 因此,我希望它向第一个字节写入一个字符,而其他3个字节将未初始化。
为什么不将char缓冲区添加到%union并将%s与sscanf一起使用?
您将createAlphabet的参数声明为char []而不是char有点奇怪。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.