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

My parser doesn't realize that it should have taken the second branch of a rule

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

您可能在跑道尽头看到过数字,例如:

24L

24L-36R

读作:24 Left24 Left/36 Right

这些数字称为“跑道指示符”。

跑道可以用 designatordesignator 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 生成的字符串执行任何操作,因此它实际上不应该在任一输入上生成任何输出。但我想你只是把那部分从你在这里发布的代码中遗漏了。