2010-04-08 5 views
5

는 좀 들소 문법이 있습니다Bison/YACC가 전체 문자열을 구문 분석 할 때까지 명령을 인식하지 못하게하려면 어떻게합니까?

input: /* empty */ 
     | input command 
; 

command: 
     builtin 
     | external 
; 

builtin: 
     CD { printf("Changing to home directory...\n"); } 
     | CD WORD { printf("Changing to directory %s\n", $2); } 
; 

나는이 모든 입력을 읽을 때까지 들소는 command로 (YYACCEPT?) 뭔가를 허용하지 얼마나 궁금하네요. 따라서 아래에있는 모든 규칙을 사용하여 재귀를 사용하거나 물건을 만드는 모든 방법을 사용할 수 있습니다. 유효한 명령이나 작동하지 않는 결과가 발생합니다.

위의 코드로 수행중인 간단한 테스트 중 하나는 "cd mydir mydir"입니다. Bison은 CDWORD을 파싱하고 "이봐,이게 명령이다. 그런 다음 찾은 다음 토큰은 규칙이없는 WORD이며 그 다음에 오류를보고합니다.

전체 라인을 읽고 실현하고 싶습니다. CD WORD WORD은 규칙이 아니며 오류를보고합니다. 나는 명백한 무엇인가 놓치고 있고, 어떤 도움이라도 크게 감사 할 것이다라고 생각한다 - 고마워한다!

또한 - input command NEWLINE 또는 유사한 것을 사용하려고 시도했지만 아직까지 CD WORD을 명령으로 맨 뒤 푸시하고 여분의 WORD을 별도로 구문 분석합니다.

+0

'내장'은 줄 바꿈 ('입력'이 아니라)으로 끝내야합니다. 'CD WORD NEWLINE'에서와 같이 – leeeroy

+0

'builtin'에'{'이 없으면'| CD WORD {printf ("% s로 변환하는 \ n", $ 2); } ' –

+0

죄송합니다. 그건 내가 테스트하는 데 사용하는 코드가 아니었다 ... – chucknelson

답변

2

때로는 문법을 평평하게하여 이러한 사례를 처리합니다.

당신의 경우, 개개의 명령 줄 분리 자 (;)에 대해 렉서에 토큰을 추가하여 Bison 문법에 명시 적으로 넣을 수 있으므로 파서는 명령에 대한 완전한 입력 행을 기대할 수 있습니다 commmand로 받아들이 기 전에.

sep: NEWLINE | SEMICOLON 
    ; 

command: CD sep 
    | CD WORD sep 
    ; 

은 또는, 실제 쉘과 같은 임의의 인수 목록 :

args: 
    /* empty */ 
    | args WORD 
    ; 

command: 
     CD args sep 
    ; 
+0

이것은 작동하는 것 같다. 하지만 각 커맨드에 대한 분리 기호 표현을 구체적으로 언급해야한다는 것은 어리석은 생각입니다. 나는 언젠가는 임의의 논쟁으로 바뀔지도 모르지만 ... 아직! 이 작업을 수행하는 다른 방법이 있다면 여전히 궁금합니다. – chucknelson

+0

수정 :이 단어는 2 단어 (cd hello hello)로 작동하지만 그 시점에서 토큰이 튀어 나옵니다. 그런 다음 다시 시작됩니다. 따라서 "cd hello1 hello2 hello3"은 cd, hello1 및 hello2를 표시하지만 hello3에 대한 별도의 규칙과 일치 시키려고 시도합니다. 나는 매우 혼란 스럽다 ... – chucknelson

+0

위의 두 번째 부분에서와 같이 "args"규칙을 사용하면 임의의 숫자와 일치해야한다. – codenheim

0

일반적으로 사물은 설명대로 처리되지 않습니다.

Bison/Yakk/Lex에서는 일반적으로 구문을 신중하게 디자인하여 필요한 것을 정확하게 처리합니다. Bison/Yakk/Lex는 정규 표현식을 사용하여 자연히 greedy이므로이 방법이 도움이됩니다.

그럼 어때?

한 번에 전체 을 파싱하므로이 사실을 우리의 장점으로 사용하고 구문을 수정할 수 있다고 생각합니다.

input : /* empty */ 
     | line 


command-break : command-break semi-colon 
       | semi-colon 

line : commands new-line 

commands : commands command-break command 
     | commands command-break command command-break 
     | command 
     | command command-break 

... 

경우 new-line, '세미콜론 is defined in your 렉스 source as something like \ n , \ t`. 이렇게하면 찾고있는 명령에 대한 UNIX 스타일의 구문을 얻을 수 있습니다. 모든 종류의 일들이 가능하며, 여럿의 세미콜론을 허용하면서 약간 비대 해져서 공백을 고려하지 않지만, 아이디어를 얻어야합니다.

렉스 (Lex)와 야크크 (Yakk)는 강력한 도구이며, 적어도 당신이 마감 기한을 지키고 있지 않을 때는 꽤 즐겁습니다.

0

방금 ​​작업 목록에 추가 할 규칙 일치 작업을 변경할 수 없습니다 당신이 경우 수행 할 모든게 효과가 있니? 그런 다음 전체 입력이 처리 된 후에 구문 분석 오류를 본 경우에 기반하여 해당 작업 목록에 있던 작업을 수행할지 결정합니다.

1

직접 액션을 호출하는 대신 추상적 인 구문 트리를 먼저 작성하십시오. 그런 다음 결과와 선호도에 따라 그 부분을 실행하거나 아무 것도 실행하지 마십시오. 트리를 만드는 동안 구문 분석 오류가 발생하면 % destructor 지시어를 사용하여 bison에게 정리 작업 방법을 알릴 수 있습니다.

실제로 내용과 논리를 완벽하게 제어 할 수있는 적절한 방법입니다. 바이손이 파싱을 처리하게하십시오.

+0

답변 주셔서 감사합니다 - 현재 수업에서 저는 언어를 파싱하고 AST를 작성하며 코드를 생성하는 프로젝트를 진행하고 있습니다. 슬프게도 나는 Bison과 YACC를 사용하는 수업에서 그 경험을 되찾지 못했습니다. 다시 한 번 감사드립니다. 다음 번에 비슷한 문제를 해결해야 할 때마다 문제에 대해 생각할 것입니다. – chucknelson