我的解析器没有意识到它应该采用规则的第二个分支



我正在为包含有关机场跑道数据的文件创建解析器。

你可能见过t台尽头的数字,比如:

24L
24L-36R

读作:24 Left,24 Left/36 Right

这些数字被称为"跑道指示符"。

跑道可以用designatordesignator hyphen designator标记。

相应地,我在.y文件中有这个规则(有两个分支的选择):

rwydsg: RUNWAY  { $$ = concat(3, "<RunwayDesignator>", $1, "</RunwayDesignator>"); }
| RUNWAY '-' RUNWAY { $$ = concat(7, "<RunwayDesignator_1>", $1, "</RunwayDesignator_1>", "<Hyphen>-</Hyphen>", "<RunwayDesignator_2>", $3, "</RunwayDesignator_2>"); }
;

concat()函数是我创建的一个小函数。

输入:

24L

我得到这样的输出:

<RunwayDesignator>24L</RunwayDesignator>

完美!

输入:

24L-36R

没有输出。为什么呢?

我的输入文件:

24R-36L

这是我的"文件:

%{
#include "helloworld.tab.h"
%}
RWY [0-9]{2,2}(C|L|R)
%%
"-"             { return yytext[0]; }
{RWY}           { yylval.sval = malloc(yyleng + 1); strcpy(yylval.sval, yytext); return(RUNWAY); }
n              { return(EOL); }
%%
int yywrap(){ return 1;}

这是我的" y"文件:

%{
#include <stdio.h>
#include "utilities.h"
int yylex(void);
extern FILE *yyin;
void yyerror(const char* msg);
%}
%union
{
char *sval;
}
%token <sval> RUNWAY
%token EOL
%type <sval> rwydsg
%%
start: rwydsg               { printf("%s", $1); }
rwydsg: RUNWAY              { $$ = concat(3, "<RunwayDesignator>", $1, "</RunwayDesignator>"); }
| RUNWAY '-' RUNWAY        { $$ = concat(7, "<RunwayDesignator><RunwayDesignator_1>", $1, "</RunwayDesignator_1>", "<Hyphen>-</Hyphen>", "<RunwayDesignator_2>", $3, "</RunwayDesignator_2></RunwayDesignator>"); }
;
%%
int main(int argc, char *argv[])
{
yyin = fopen(argv[1], "r");
yyparse();
return 0;
}
void yyerror(const char *msg)
{
fprintf(stderr, "error: %sn", msg);
}
下面是我的concat()函数:
char *concat(int numargs, ...)
{
va_list ap;
// The va_start macro enables access to the variable arguments following the 
// last fixed argument (in this case, the last fixed argument is named numargs).
va_start(ap, numargs);
// T va_arg(va_list ap, T)
// The va_arg macro expands to an expression of type T that corresponds to the 
// next value in ap 
size_t size = 0;
for (int i=0; i<numargs; i++) {
size += sizeof va_arg(ap, T);
}
size++;
char *buffer = calloc(1, size);
for (int i=0; i<numargs; i++) {
strcat(buffer, va_arg(ap, T));
}
// End traversal of the variable arguments
va_end(ap);
return (char *)buffer;
}

您的concat函数被破坏了。

首先,它没有初始化size,导致未定义的行为。你需要将它初始化为0。

其次,它使用sizeof va_arg(ap, T)(与sizeof(T)相同)来计算buffer的大小。您没有包括T的定义,但假设它是char*的类型定义(这是代码有意义的唯一方式),那么每次只会向size添加8(或者无论您的平台上指针的大小)。由于这通常小于字符串的实际大小(您需要strlen来查找),因此您最终会得到一个太小的缓冲区,无法容纳您试图写入的所有字符。

你也从来没有对rwydsg产生的字符串做过任何事情,所以它真的不应该在两个输入上产生任何输出。但我猜你只是把这部分遗漏在你贴在这里的代码中。

相关内容

最新更新