2017-02-15 10 views
0

я пытаюсь запустить этот файл .YBison Ошибки синтаксиса простого файл

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

%} 

%start BEGIN 

%% 

BEGIN: 'a' | BEGIN 'a' 


%% 

int yylex(){ 
    return getchar(); 
} 

int yyerror(char* s){ 
    fprintf(stderr, "*** ERROR: %s\n", s); 
    return 0; 
} 

int main(int argn, char **argv){ 
    yyparse(); 
    return 0; 
} 

Это простая программа в бизоне, синтаксис, мне кажется правильным, но всегда получаю проблему ошибки синтаксиса ... Спасибо за вашу помощь.

ответ

1

Функция lexer yylex должна вернуть 0, чтобы указать конец ввода. Однако ваша реализация просто проходит через значение, возвращаемое getchar, которое будет EOF (обычно -1).

Кроме того, ваш ввод почти наверняка будет содержать символ новой строки, который также будет передан парсеру.

Поскольку анализатор не распознает ни \n, ни EOF, он выдает сообщение об ошибке, когда получает один из них.

Как минимум, вы должны изменить yylex правильно реагировать на конец ввода:

int yylex(void) { 
    int ch = getchar(); 
    return (ch == EOF) ? 0 : ch; 
} 

Но вам все равно придется иметь дело с новой строки charactets, либо путем обработки их в лексический (возможно, не обращая внимания их или, возможно, возвращение конца ввода imdication), или путем обработки их в вашей грамматике.

Обратите внимание, что парсеры, основанные на бизонах/yacc, всегда анализируют весь входной поток, а не только самую длинную последовательность, удовлетворяющую грамматике. Это можно скорректировать с некоторой работой - см. Документацию для специального действия YYACCEPT, но стандартное поведение обычно является желательным при разборе.

Кстати, пожалуйста, используйте стандартные условные условные обозначения в ваших грамматиках bison/yacc, чтобы избежать проблем и во избежание запутывания читателей. Обычно мы резервируем UPPER_CASE для символов терминала, так как они также используются в качестве констант времени компиляции в лексере. Нетерминалы обычно записываются в lower_case, хотя некоторые предпочитают использовать CamelCase. Для терминалов вам необходимо избегать использования имен, зарезервированных стандартной библиотекой (например, EOF) или (f) lex (BEGIN) или bison/yacc (END). В руководствах есть списки зарезервированных имен.