2016-04-18 3 views
0

Я являюсь абсолютным новичком в yacc/lex, и я натыкаюсь на то, что кажется мне простым, но я не могу понять. У меня есть два правила: S : E; и E : STR; (и в лексере [a-z]+ отображается на STR). Я предполагаю, что когда я даю вход «hithere», например, вход потребляется, и парсер должен выйти, нет?Конец правила грамматики в YACC

Дело в том, что синтаксический анализатор все еще ждет ввода, поэтому каким-то образом 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() выполнен.

ответ

0

Bison/Yacc (и многие, хотя и не все производные) на самом деле построить «дополненной» грамматику путем добавления нового запуска производства, которое эффективно:

$start: S END 

Где S Ваш начальный символ (или первый нетерминал в грамматике, если вы не укажете), а END - это токен, представляющий конец ввода. (Это реальный токен, значение которого равно 0. (f) Сканеры lex возвращают 0, когда они получают конец файла, поэтому в парсер он выглядит так, будто ему дается токен END.)

Таким образом, парсер не вернется, пока не увидит токен END, а это значит, что сканер увидел конец файла. Если ваш вход поступает с терминала, вам необходимо отправить EOF, как правило, путем ввода символа EOF: control-D в большинстве Unix-подобных систем или control-Z в Windows/DOS.

В отличие от многих генераторов парсера, зубр будет выполнять уменьшение без считывания символа вида, если символ возврата не требуется, чтобы решить, что необходимо выполнить редукцию. В случае вашей грамматики это возможно при производстве S: E, потому что нет возможной смены; либо сокращение правильное (если следующий токен равен END), либо вход не является синтаксически действительным (если следующий токен - это что-то еще). Таким образом, семантическое значение строки печатается. Для еще более сложной грамматики этого не произойдет (пока не будет распознан EOF).

0

Ожидает большего количества ввода, чтобы уменьшить производство S : E ;. Вам нужно ввести ctrl/d или ctrl/z в зависимости от вашей системы.