2013-05-15 4 views
1

저는 Lex와 Yacc을 처음 사용하고 있으며 간단한 산술 및 동등한 표현식을 허용하는 간단한 구문 분석기를 만들려고합니다. 일부는 작동하지만, 바이너리 연산과 관련된 표현식을 파싱 할 때 오류가 발생합니다. 여기 내 .y 파일입니다이진 연산자를 사용하는 표현식을 구문 분석 할 때 Yacc 및 Lex 오류가 발생했습니다.

%{ 
    #include <stdlib.h> 
    #include <stdio.h> 
%} 

%token NUMBER 
%token HOME 
%token PU 
%token PD 
%token FD 
%token BK 
%token RT 
%token LT 

%left '+' '-' 
%left '=' '<' '>' 
%nonassoc UMINUS 


%% 

S  :  statement S     { printf("S -> stmt S\n"); } 
     |         { printf("S -> \n"); } 
; 

statement :  HOME      { printf("stmt -> HOME\n"); } 
     |  PD       { printf("stmt -> PD\n"); } 
     |  PU       { printf("stmt -> PU\n"); } 
     |  FD expression    { printf("stmt -> FD expr\n"); } 
     |  BK expression    { printf("stmt -> BK expr\n"); } 
     |  RT expression    { printf("stmt -> RT expr\n"); } 
     |  LT expression    { printf("stmt -> LT expr\n"); } 
; 

expression : expression '+' expression { printf("expr -> expr + expr\n"); } 
     |  expression '-' expression { printf("expr -> expr - expr\n"); } 
     |  expression '>' expression { printf("expr -> expr > expr\n"); } 
     |  expression '<' expression { printf("expr -> expr < expr\n"); } 
     |  expression '=' expression { printf("expr -> expr = expr\n"); } 
     |  '(' expression ')'   { printf("expr -> (expr)\n"); } 
     |  '-' expression %prec UMINUS { printf("expr -> -expr\n"); } 
     |  NUMBER      { printf("expr -> number\n"); } 
; 

%% 

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

int main() 
{ 
    yyparse(); 
} 

그리고 여기 렉스에 대한 내 .l 파일입니다

%{ 
    #include "testYacc.h" 
%} 

number [0-9]+ 

%% 
[ ]    { /* skip blanks */ } 
{number}  { sscanf(yytext, "%d", &yylval); return NUMBER; } 
home   { return HOME; } 
pu    { return PU; } 
pd    { return PD; } 
fd    { return FD; } 
bk    { return BK; } 
rt    { return RT; } 
lt    { return LT; } 

%% 

내가 평가에 대한 명령 줄에 연산 식을 입력하려고, 다음과 같은 결과 오류 :

home 
stmt -> HOME 

pu 
stmt -> PU 

fd 10 
expr -> number 

fd 10 
stmt -> FD expr 
expr -> number 

fd (10 + 10) 
stmt -> FD expr 
(expr -> number 
+stmt -> FD expr 
S -> 
S -> stmt S 
S -> stmt S 
S -> stmt S 
S -> stmt S 
S -> stmt S 
syntax error 

답변

2

귀하의 렉서 일치 및 '+''*' 같은 토큰을 반환하는 규칙을 부족, 그렇다면이 당신의 입력에있는 어떤 것이라도, 그냥 그들을 울리고 그들을 버릴 것입니다. fd (10 + 10)을 입력하면 렉서가 FDNUMBERNUMBER을 반환하는 반면 +(은 stdout에 에코를 표시합니다. 그런 다음 파서는 구문 오류를 제공합니다.

이러한 단일 문자 토큰을 반환하는 규칙을 추가하려고합니다. 가장 쉬운 방법은 마지막에 .l 파일에 하나의 규칙을 추가하는 것입니다.

.    { return *yytext; } 

하나의 문자와 일치하는 규칙을 추가하는 것입니다.

이것은 개행 문자가 \n (개행)과 일치하지 않으므로 입력 내용의 줄 바꿈은 계속 표시되고 무시됩니다. 건너 뛰기 공란에 규칙 (탭 및 캐리지 리턴)을 추가 할 수 있습니다.

+0

고맙습니다. 어떤 이유로,'+'등이 인용 되었기 때문에, 그들은 yacc에서 어떻게 든 특별한 '프리미티브'연산자였습니다. – dtg

+0

그들은 yacc에 있습니다. 그래서 char 값을 반환하는 것이 효과적이므로 % TOKEN을 정의 할 필요가 없습니다. 그러나 그들은 lex/flex에서 특별하지 않습니다. – EJP

+0

나는 그들이 올바르게 해석 할 수 있도록, 먼저 Lex에서 토큰으로 정의 될 필요가있다. – dtg