2017-02-15 7 views
0

내가이 .Y 파일 들소 구문 오류 ... 쉽게 파일

%{ 
#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

렉서 기능 yylex은 입력의 끝을 나타 내기 위해 0을 리턴해야합니다. 그러나 구현은 getchar에 의해 반환 된 값을 통과하며 이는 EOF (일반적으로 -1)입니다.

또한 사용자의 입력에는 개행 문자가 포함될 가능성이 거의 있으며 파서에 전달됩니다.

파서가 \n도 아니고 EOF도 인식하지 못하기 때문에 파서가 그 중 하나를 받으면 오류가 발생합니다.

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

그러나 당신은 여전히 ​​(아마도 무시하거나 당신의 렉서에서 그들을 처리하여 줄 바꿈 charactets 처리해야합니다 :

최소한

올바르게 입력의 끝 응답 yylex을 수정해야 그들 또는 아마도 입력 imidication의 끝을 반환), 또는 귀하의 문법에서 처리하여.

bison/yacc 생성 파서는 항상 문법을 만족하는 가장 긴 시퀀스가 ​​아닌 전체 입력 스트림을 구문 분석합니다. 이는 약간의 작업으로 조정할 수 있습니다 - YYACCEPT 특수 작업에 대한 설명서를 참조하십시오. 그러나 표준 동작은 일반적으로 파싱 할 때 원하는 것입니다.

그런데 문제를 피하고 독자 혼란을 피하기 위해 bison/yacc 문법에 표준 스타일 규칙을 사용하십시오. 일반적으로 우리는 터미널 심볼에 대해 UPPER_CASE을 예약한다. 그 이유는 그것도 렉서에서 컴파일 타임 상수로 사용되기 때문이다. 비 터미널은 일반적으로 lower_case으로 작성되지만 일부는 CamelCase을 선호합니다. 터미널의 경우 표준 라이브러리 (예 : EOF) 또는 (f) lex (BEGIN) 또는 bison/yacc (END)로 예약 된 이름을 사용하지 않아야합니다. 설명서에는 예약 된 이름 목록이 있습니다.