繁体   English   中英

YACC中的语法规则结束

[英]End of grammar rule in YACC

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

问题是,解析器仍在等待输入,因此不使用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; 实际上已经被识别并执行printf()

它正在等待更多输入,因此可以减少产量S : E ; 您需要根据系统输入ctrl / d或ctrl / z。

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

$start: S END

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

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

与许多解析器生成器不同,如果不必使用先行符号来确定必须执行缩减,则野牛将执行精简操作而不读取先行符号。 在您的语法情况下, S: E产生是可能的,因为没有可能的转移。 减少是正确的(如果下一个标记是END ),或者输入在语法上无效(如果下一个标记是其他任何东西)。 因此,将打印字符串的语义值。 对于一个稍微复杂一点的语法,就不会发生(直到EOF被识别)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM