0

好的,这就是交易。

用我的语言,我有一些命令,比如说

XYZ 3 5
GGB 8 9
HDH 8783 33

在我的 Lex 文件中

XYZ { return XYZ; }
GGB { return GGB; }
HDH { return HDH; }
[0-9]+ { yylval.ival = atoi(yytext); return NUMBER; }
\n  { return EOL; }

在我的 yacc 文件中

start : commands
    ;

commands : command
         | command EOL commands
    ;

    command : xyz
            | ggb
            | hdh
    ;

    xyz : XYZ NUMBER NUMBER { /* Do something with the numbers */ }
       ;

    etc. etc. etc. etc.

我的问题是,我怎样才能得到整个文本

XYZ 3 5
GGB 8 9
HDH 8783 33

在返回数字的同时进入命令?

另外,当我的 Lex 返回 STRING [0-9a-zA-Z]+,并且我想验证它的长度时,我应该这样做吗

rule: STRING STRING { if (strlen($1) < 5 ) /* Do some shit else error */ }

或者实际上在我的 Lex 中有一个令牌,它根据长度返回不同的令牌?

4

3 回答 3

1

如果我正确理解了您的第一个问题,您可以进行语义操作,例如

{ $$ = makeXYZ($2, $3); }

这将允许您根据需要构建命令的值。

对于第二个问题,词法分析和语法分析之间以及语法分析和语义分析之间的界限并不难确定。移动它们是在易于描述、错误消息的清晰度和出现错误时的稳健性等因素之间进行权衡。考虑到字符串长度的验证,出错的可能性是相当高的,如果通过返回不同长度的不同终端来处理,错误信息可能会不清楚。所以如果有可能——这取决于语法——我会在语义分析阶段处理它,在那里可以轻松地定制消息。

于 2009-08-06T06:24:39.167 回答
1

如果您安排您的词法分析器 ( yylex()) 将整个字符串存储在某个变量中,那么您的代码就可以访问它。与解析器的通信将通过正常机制进行,但没有什么说你不能还有另一个变量潜伏在周围(可能是一个文件静态变量 - 但要注意多线程),它在被解剖之前存储整个输入行。

于 2009-08-06T11:24:19.920 回答
0

当您使用时,您的 YACC 源代码中yylval.ival已经有了unionwith字段,如下所示:ival

%union {
    int ival;
}

现在您指定令牌类型,如下所示:

%token <ival> NUMBER

因此,现在您可以像在规则中一样ival简单地访问 NUMBER 令牌的字段,例如$1

xyz : XYZ NUMBER NUMBER { printf("XYZ %d %d", $2, $3); }

对于你的第二个问题,我会这样定义联合:

%union {
    char*   strval;
    int     ival;
}

并在您的 LEX 源中指定令牌类型

%token <strval> STRING;
%token <ival> NUMBER;

所以现在你可以做类似的事情

foo : STRING NUMBER { printf("%s (len %d) %d", $1, strlen($1), $2); }
于 2009-08-06T06:27:51.250 回答