我正在为包含有关机场跑道数据的文件创建解析器。
你可能见过t台尽头的数字,比如:
24L
24L-36R
读作:24 Left
,24 Left/36 Right
这些数字被称为"跑道指示符"。
跑道可以用designator
或designator 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
产生的字符串做过任何事情,所以它真的不应该在两个输入上产生任何输出。但我猜你只是把这部分遗漏在你贴在这里的代码中。