2010-04-23 5 views
3

나는 lex와 yacc을 시험해보고 이상한 문제에 부딪 혔지 만, 문제를 자세히 설명하기 전에 내 코드를 보여주는 것이 가장 좋을 것이라고 생각합니다.Bison/Yacc 문법의 의도하지 않은 연결

%{ 
#include <stdio.h> 

int yydebug=1; 
void prompt(); 
void yyerror(char *); 
int yylex(void); 
%} 

%union { 
    int intV; 
    char *strV; 
} 

%token INTEGER ID 

%% 

program: program statement EOF { prompt(); } 
     | program EOF { prompt(); } 
     | { prompt(); } 
     ; 

args: /* empty */ 
    | args ID { printf(":%s ", $<strV>2); } 
    ; 

statement: ID args { printf("%s", $<strV>1); } 
     | INTEGER { printf("%d", $<intV>1); } 
; 

EOF: '\n' 

%% 

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

void prompt() { 
    printf("> "); 
} 

int main(void) { 
    yyparse(); 
    return 0; 
} 

아주 간단한 언어, 문자열과 정수 및 기본 REPL보다 더 구성 :

%{ 
#include <stdlib.h> 
#include <string.h> 
#include "y.tab.h" 
void yyerror(char *); 
%} 

%% 

[a-zA-Z]+ { 
    yylval.strV = yytext; 
    return ID; 
} 

[0-9]+  { 
    yylval.intV = atoi(yytext); 
    return INTEGER; 
} 

[\n] { return *yytext; } 

[ \t]  ; 

. yyerror("invalid character"); 

%% 

int yywrap(void) { 
    return 1; 
} 

이 내 파서 :이 내 렉서입니다. 이제 구문 분석기에서 args이 선도 콜론으로 출력된다는 것을 알 수 있습니다. 규칙의 첫 번째 패턴과 결합하면 REPL과의 상호 작용이 다음과 같이 나타납니다.

> aaa aa a 
:aa :a aaa> 

그러나, 상호 작용은 이것이다 :

> aaa aa a 
:aa :a aaa aa aa 
> 

않는 이유는 다음과 같은 규칙의 토큰 ID

statement: ID args { printf("%s", $<strV>1); } 
     | INTEGER { printf("%d", $<intV>1); } 
; 

에는 총 입력 문자열의 의미 값이 있습니다. 개행은 포함되어 있습니까? 내가 의도 한 상호 작용을하기 위해 어떻게 내 문법을 다시 만들 수 있습니까?

답변

2

토큰 문자열을 유효한 상태로 유지하려면 토큰 문자열을 그대로 유지해야합니다.

statement: ID { printf("<%s> ", $<strV>1); } args { printf("%s", $<strV>1); } 
     | INTEGER { printf("%d", $<intV>1); } 
; 

그런 다음 입력을, 내가 출력을 얻을 : 나는 읽을 statement 규칙을 수정 당시의 초기 ID를 읽을 것을

> aaa aa a 
<aaa> :aa :a aaa aa a 
> 

주, 토큰은 정확히 무엇을 당신 예상했다. 그러나 토큰을 보존하지 않았으므로 문자열은 args이 구문 분석 된 후 다시 인쇄 할 때까지 수정되었습니다.

+0

고맙습니다. – troutwine

0

args와 명령문 제작간에 연관성 충돌이 있다고 생각합니다. 이것은 bison -v parser.output 파일에서 (부분) 출력에 의해 부담 :

Nonterminals, with rules where they appear 

$accept (6) 
    on left: 0 
program (7) 
    on left: 1 2 3, on right: 0 1 2 
statement (8) 
    on left: 4 5, on right: 1 
args (9) 
    on left: 6 7, on right: 4 7 
EOF (10) 
    on left: 8, on right: 1 2 

는 사실, 당신의 문법을 수락하려고 알아 내려고 힘든 시간을 보내고 있습니다. 부수적으로, 나는 아마 당신의 EOF 프로덕션을 EOL 토큰으로 렉서로 옮길 것이다; 이렇게하면 구문 분석 오류를 쉽게 재 동기화 할 수 있습니다.

귀하의 의도에 대한 더 나은 설명이 도움이 될 것입니다.

+0

상호 작용 섹션보다 내 의도를 더 잘 설명하는 방법을 잘 모르겠습니다. 첫 번째 ID를 논 - 인수로 식별하고 나머지는 모두 인수로 식별하는 행 지향형 REPL을 작성하려고합니다. 목표는 두 번째 상호 작용보다는 첫 번째 상호 작용의 결과입니다. – troutwine