我的解析器没有意识到它应该采用规则的第二个分支
My parser doesn't realize that it should have taken the second branch of a rule
我正在为包含机场跑道数据的文件创建解析器。
您可能在跑道尽头看到过数字,例如:
24L
24L-36R
读作:24 Left
、24 Left/36 Right
这些数字称为“跑道指示符”。
跑道可以用 designator
或 designator hyphen designator
标记。
相应地,我的 .y
文件中有这条规则(有两个分支的选择):
rwydsg: RUNWAY { $$ = concat(3, "<RunwayDesignator>", , "</RunwayDesignator>"); }
| RUNWAY '-' RUNWAY { $$ = concat(7, "<RunwayDesignator_1>", , "</RunwayDesignator_1>", "<Hyphen>-</Hyphen>", "<RunwayDesignator_2>", , "</RunwayDesignator_2>"); }
;
concat() 函数是我创建的一个小函数。它工作正常。
有了这个输入:
24L
我得到这个输出:
<RunwayDesignator>24L</RunwayDesignator>
完美!
有了这个输入:
24L-36R
我没有输出。这是为什么?
这是我的输入文件:
24R-36L
这是我的“.l”文件:
%{
#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", ); }
rwydsg: RUNWAY { $$ = concat(3, "<RunwayDesignator>", , "</RunwayDesignator>"); }
| RUNWAY '-' RUNWAY { $$ = concat(7, "<RunwayDesignator><RunwayDesignator_1>", , "</RunwayDesignator_1>", "<Hyphen>-</Hyphen>", "<RunwayDesignator_2>", , "</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: %s\n", 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*
的类型定义(这是代码唯一有意义的方式),最终只会将 8 添加到 size
每次(或您平台上指针的大小)。由于这通常小于字符串的实际大小(您需要 strlen
才能找到),您最终会得到一个太小的缓冲区,无法容纳您尝试写入的所有字符.
此外,您永远不会对 rwydsg
生成的字符串执行任何操作,因此它实际上不应该在任一输入上生成任何输出。但我想你只是把那部分从你在这里发布的代码中遗漏了。
我正在为包含机场跑道数据的文件创建解析器。
您可能在跑道尽头看到过数字,例如:
24L
24L-36R
读作:24 Left
、24 Left/36 Right
这些数字称为“跑道指示符”。
跑道可以用 designator
或 designator hyphen designator
标记。
相应地,我的 .y
文件中有这条规则(有两个分支的选择):
rwydsg: RUNWAY { $$ = concat(3, "<RunwayDesignator>", , "</RunwayDesignator>"); }
| RUNWAY '-' RUNWAY { $$ = concat(7, "<RunwayDesignator_1>", , "</RunwayDesignator_1>", "<Hyphen>-</Hyphen>", "<RunwayDesignator_2>", , "</RunwayDesignator_2>"); }
;
concat() 函数是我创建的一个小函数。它工作正常。
有了这个输入:
24L
我得到这个输出:
<RunwayDesignator>24L</RunwayDesignator>
完美!
有了这个输入:
24L-36R
我没有输出。这是为什么?
这是我的输入文件:
24R-36L
这是我的“.l”文件:
%{
#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", ); }
rwydsg: RUNWAY { $$ = concat(3, "<RunwayDesignator>", , "</RunwayDesignator>"); }
| RUNWAY '-' RUNWAY { $$ = concat(7, "<RunwayDesignator><RunwayDesignator_1>", , "</RunwayDesignator_1>", "<Hyphen>-</Hyphen>", "<RunwayDesignator_2>", , "</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: %s\n", 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*
的类型定义(这是代码唯一有意义的方式),最终只会将 8 添加到 size
每次(或您平台上指针的大小)。由于这通常小于字符串的实际大小(您需要 strlen
才能找到),您最终会得到一个太小的缓冲区,无法容纳您尝试写入的所有字符.
此外,您永远不会对 rwydsg
生成的字符串执行任何操作,因此它实际上不应该在任一输入上生成任何输出。但我想你只是把那部分从你在这里发布的代码中遗漏了。