【问题标题】:End of grammar rule in YACCYACC 中的语法规则结束
【发布时间】:2016-04-18 22:18:17
【问题描述】:

我是 yacc/lex 的绝对初学者,我偶然发现了一些对我来说似乎很简单但我无法理解的东西。我有以下两个规则:S : E;E : STR;(在词法分析器中,[a-z]+ 映射到 STR)。我的猜测是,例如,当我输入“这里”时,输入被消耗并且解析器应该退出,不是吗?

问题是,解析器仍在等待输入,所以不知何故 S : E 没有被消耗(或者我猜是这样)。如果我继续输入,则会引发语法错误(这是预期的)。

我的问题是,在什么情况下解析器会停止请求输入?也许更准确地说,为什么我的具体示例不满足 S : E; 规则?

我在此处附上我的 .l 和 .y 文件:

test1.l

%{
#include <stdio.h>
#include <stdlib.h>
#include "y.tab.h"
%}

%option noyywrap

%%
[a-z]+                  {yylval.str = yytext; return (STR);}
.                       { ; }
%%

test1.y:

%{
#include <stdio.h>
#include <stdlib.h>
extern int yylex();
%}

%union {
    char    *str;
}

%token <str> STR
%type <str> E

%%

S : E                   {printf("%s\n", $1);}
  ;

E : STR                 {$$ = $1;}
  ;

%%

int yyerror(char *msg) {
    printf("%s\n", msg);
    return (0);
}

int main() {
    yyparse();
    return (0);
}

对我来说似乎很奇怪的是,如果我输入“hithere”,“hithere”会在我的终端上打印回来,所以这对我来说是一个强有力的指标,S : E; 实际上已被识别并且@ 987654332@被执行。

【问题讨论】:

    标签: c yacc lex


    【解决方案1】:

    Bison/yacc(以及许多(尽管不是全部)派生词)实际上通过添加一个新的开始产生式来构建“增强”语法,这实际上是:

    $start: S END
    

    S 是您的开始符号(如果您未指定,则为语法中的第一个非终结符),END 是表示输入结束的标记。 (它是一个真正的令牌,其值为 0。(f)lex 扫描器在获得文件结尾时返回 0,因此对于解析器来说,它看起来像是被赋予了一个 END 令牌。)

    所以解析器在看到END 标记之前不会返回,这意味着扫描器已经看到文件结尾。如果您的输入来自终端,则需要发送 EOF,通常通过键入 EOF 字符:在大多数类 Unix 系统上为 control-D,或在 Windows/DOS 上为 control-Z。

    与许多解析器生成器不同,如果不需要先行符号来决定必须执行缩减,bison 将执行缩减而不读取先行符号。对于您的语法,S: E 产生式是可能的,因为没有可能的转变;减少是正确的(如果下一个标记是END)或者输入在语法上无效(如果下一个标记是其他任何东西)。所以字符串的语义值被打印出来了。对于稍微复杂一点的语法,这不会发生(直到 EOF 被识别)。

    【讨论】:

      【解决方案2】:

      它正在等待更多输入,以便减少生产S : E ;。您需要根据您的系统键入 ctrl/d 或 ctrl/z。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-01-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多