2013-03-30 2 views
0

내 수업에서 두 ​​번째 주에 간단한 컴파일러를 만들려고 노력 중이며 다음과 같은 점에 완전히 걸림돌이되고있다. 플렉스와 들소 파일은 공간) :컴파일러에 관한 의문점 (플렉스/들소)

..snip.. 
end  {return(END);} 
skip  {return(SKIP);} 
in  {return(IN);} 
integer {return(INTEGER);} 
let  {return(LET);} 
..snip.. 
[ \t\n\r]+ 

하고 simple.y : 내가 컴파일하고이를 실행하면

%start program 
%token LET IN END 
%token SKIP IF THEN ELSE WHILE DO READ WRITE FI ASSGNOP 
%token NUMBER PERIOD COMMA SEMICOLON INTEGER 
%token IDENTIFIER EWHILE LT 
%left '-' '+' 
%left '*' '/' 
%right '^' 
%% 

program : LET declarations IN commands END SEMICOLON 
declarations : 
|INTEGER id_seq IDENTIFIER PERIOD 
; 
id_seq: 
|id_seq IDENTIFIER COMMA 
; 
commands : 
| commands command SEMICOLON 
; 
command : SKIP 
; 
exp : NUMBER 
| IDENTIFIER 
| '('exp')' 
; 
..snip.. 
%% 

나의 첫 번째 문제는, 제대로 끝까지 내 입력을 허용하지만 끝에서 중지하지 않는다; 입력에

: 즉, 다시 상태로 시작되어, 그것이 종료가 발생하면 종료 안됩니다

Starting parse 
Entering state 0 
Reading a token: let 
Next token is token LET() 
Shifting token LET() 
Entering state 1 
Reading a token: integer x. 
Next token is token INTEGER() 
Shifting token INTEGER() 
Entering state 3 
Reducing stack by rule 4 (line 22): 
-> $$ = nterm id_seq() 
Stack now 0 1 3 
Entering state 6 
Reading a token: Next token is token IDENTIFIER() 
Shifting token IDENTIFIER() 
Entering state 8 
Reading a token: Next token is token PERIOD() 
Shifting token PERIOD() 
Entering state 10 
Reducing stack by rule 3 (line 20): 
    $1 = token INTEGER() 
    $2 = nterm id_seq() 
    $3 = token IDENTIFIER() 
    $4 = token PERIOD() 
-> $$ = nterm declarations() 
Stack now 0 1 
Entering state 4 
Reading a token: in 
Next token is token IN() 
Shifting token IN() 
Entering state 7 
Reducing stack by rule 6 (line 25): 
-> $$ = nterm commands() 
Stack now 0 1 4 7 
Entering state 9 
Reading a token: skip; 
Next token is token SKIP() 
Shifting token SKIP() 
Entering state 13 
Reducing stack by rule 8 (line 28): 
    $1 = token SKIP() 
-> $$ = nterm command() 
Stack now 0 1 4 7 9 
Entering state 19 
Reading a token: Next token is token SEMICOLON() 
Shifting token SEMICOLON() 
Entering state 29 
Reducing stack by rule 7 (line 26): 
    $1 = nterm commands() 
    $2 = nterm command() 
    $3 = token SEMICOLON() 
-> $$ = nterm commands() 
Stack now 0 1 4 7 
Entering state 9 
Reading a token: end; 
Next token is token END() 
Shifting token END() 
Entering state 12 
Reading a token: Next token is token SEMICOLON() 
Shifting token SEMICOLON() 
Entering state 20 
Reducing stack by rule 1 (line 18): 
    $1 = token LET() 
    $2 = nterm declarations() 
    $3 = token IN() 
    $4 = nterm commands() 
    $5 = token END() 
    $6 = token SEMICOLON() 
-> $$ = nterm program() 
Stack now 0 
Entering state 2 
Reading a token: 

가 왜 여기

let 
integer x. 
in 
skip; 
end; 

는 출력 내가 끝낼 때 토큰을 다시 읽을 준비가되었습니다. ?? 내가 뭘 놓치고 있니? 여기서 끝내면 안 될까요? 내가 지금 무엇을 입력하면 그것은 나에게 다음과 같은 오류를 제공합니다 :

Reading a token: let 
Next token is token LET() 
syntax error, unexpected LET, expecting $end 
Error: popping nterm program() 
Stack now 0 
Cleanup: discarding lookahead token LET() 
Stack now 0 

제 2의 의심이 컴파일러 구현의 다음 단계해야 무엇인가? 이 부분과 코드 생성 부분 사이에 더 많은 단계가 필요합니까? 이제 Symbol 테이블을 어떻게 구현합니까? 이 파서가 파일로부터 코드를 받아들이게하려면 어떻게해야합니까? 지금까지 터미널에서 입력을 제공 할 때까지 my_program.simple과 같은 파일에서이 코드를 허용하려면 어떻게해야합니까? 감사합니다.

+2

EOF (파일 끝 표시)를 읽으려는 대기 중 (시도 중)입니다. EOF (터미널에 ctrl-D 적중)를 주면 깨끗하게 종료해야합니다. 또는 파일에서 리디렉션하면 파일에 EOF –

+0

가 표시됩니다. Chris에게 감사드립니다. 의심의 여지가 없어졌습니다. –

답변

1
declarations : 
|INTEGER id_seq IDENTIFIER PERIOD 
; 
... 

난 당신이 잘못된 구문을 사용하고 있다고 생각 : 당신이 declarations (뿐만 아니라 idseqcommands가) epsilon, 즉 빈 생산 될 수 있다고 언급. 그게 이기 때문에 그것은 alternative 연산자입니다. 빈 몸체와 실제 패턴 사이의 대안. 말이되지 않습니다.

저는 파서가 반복되는 원인이 될 수 있다고 생각합니다.

심볼 테이블의 경우 파서 외부에서 전역으로 선언 된 맵 (C++을 생성하고 싶습니다.)을 사용할 수 있습니다. 그런 다음 본 때 기호를 삽입하십시오.

컴파일러를 얻으려면 인터프리터을 사용하는 것이 유용 할 수 있습니다. 컴파일러를 다시 작성하여 더 쉽게 사용할 수있는 여러면을 분명히합니다.

+0

중복되어 있습니다. 그것이 틀렸다면, 그것은 모호한 말입니다, yacc는 그렇게 말했을 것입니다. 파서 루핑의 원인이되지는 않습니다. – EJP