구문분석기 생성기 yacc

47
구구구구구 구구구 YACC

Upload: oakley

Post on 21-Mar-2016

280 views

Category:

Documents


8 download

DESCRIPTION

구문분석기 생성기 YACC. 문법표현 + C 코드. Yacc. 원시 프로그램. 어휘분석기. y.tab.c. C 코드의 실행결과. Yacc. Yacc Yet Another Compiler Compiler 1975 년 , Johnson LALR(1) 파서 생성기. Lex 와의 결합. 어휘분석기와 구문분석기의 관계 구문분석기 : 토큰을 요구 Yacc: yylex() 를 호출 어휘분석기 : 입력 프로그램을 잘라서 토큰으로 전달 Lex: 토큰 값을 return UNIX 명령어 - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: 구문분석기 생성기  YACC

구문분석기 생성기 YACC

Page 2: 구문분석기 생성기  YACC

Yacc• Yacc

– Yet Another Compiler Compiler– 1975 년 , Johnson– LALR(1) 파서 생성기

문법표현 + C 코드Yacc

y.tab.c

원시 프로그램C 코드의 실행결과어휘분석기

Page 3: 구문분석기 생성기  YACC

Lex 와의 결합• 어휘분석기와 구문분석기의 관계

– 구문분석기 : 토큰을 요구• Yacc: yylex() 를 호출

– 어휘분석기 : 입력 프로그램을 잘라서 토큰으로 전달

• Lex: 토큰 값을 return

• UNIX 명령어% vi simple.l simple.y% lex simple.l% yacc -d simple.y% cc -o sim lex.yy.c y.tab.c -ly -ll

Page 4: 구문분석기 생성기  YACC

Lex Source• 수식문법을 위한 lex source

%{#include "y.tab.h"%}%%[0-9]+ return(NUMBER);[ \t] ;\n return(0);\+ return('+');\* return('*');. { printf("'%c': illegal character\n", yytext[0]); exit(-1); }

Page 5: 구문분석기 생성기  YACC

Yacc 의 입력• 입력의 구성

– 선언 부분• y.tab.c 에서 사용할 자료구조 , 변수 , 상수를 정의• 생성규칙 부분에서 사용되는 토큰의 이름을 정의

– 생성규칙 부분• 문법의 생성규칙을 기술• 생성규칙이 reduce 될 때 처리할 행위 (C 코드 ) 를 기술

선언 부분%%생성규칙 부분%%사용자 부프로그램 부분

Page 6: 구문분석기 생성기  YACC

선언 부분• 형태

• 정의 예%token NUMBER

%{ /* y.tab.c 에 복사될 내용 */%}%token 토큰이름 1 토큰이름 2 ...%start 시작문법기호%left 모호한 문법에서 사용%right ' '%nonassoc ' '

Page 7: 구문분석기 생성기  YACC

생성규칙 부분• 형태

– ::= 기호 대신에 : 기호를 사용– 문자토큰은 ' 와 ' 사이에 둠 ( 대소문자 구별은 없음 )– 생성규칙의 끝에는 ; 기호를 첨가

• 정의 예%%Exp : Exp '+' Term { printf("rule 1\n"); } | Term { printf("rule 2\n"); } ;

%%생성규칙 1 C 코드 1생성규칙 2 C 코드 2...생성규칙 n C 코드 n

Page 8: 구문분석기 생성기  YACC

Yacc 입력의 예• 수식문법의 예

%token NUMBER%%Exp : Exp '+' Term { printf("rule 1\n"); } | Term { printf("rule 2\n"); } ;

Term : Term '*' Num { printf("rule 3\n"); } | Num { printf("rule 4\n"); } ;

Num : NUMBER { printf("rule 5\n"); } ;

Page 9: 구문분석기 생성기  YACC

ToyPL 문법 검사기• 문제 : ToyPL 로 작성된 어떤 프로그램이

문법에 적합한지 검사하자 .– 입력 : ToyPL 로 작성되었다고 여겨지는

어떤 프로그램– 출력 : 문법에 맞지 않으면 “ syntax error” 를

출력– 방법 : ToyPL 문법을 yacc 으로 작성

Page 10: 구문분석기 생성기  YACC

Yacc 실습• 괄호문법

S ::= ( S ) S |

• 괄호문법을 위한 lex source– 괄호 이외의 문자는 모두 무시함

• 괄호문법을 위한 입력 예( a + b ) + ( 4 * ( ( 33 - sum ) / ( sum + 21 ) ) )

Page 11: 구문분석기 생성기  YACC

Yacc 의 상세 설명• yyerror()

– 문법에 맞지 않는 문장에 대한 오류 메세지– 사용자 부 프로그램 부분에 정의

%%yyerror() { printf("틀린 수식입니다 \n");}

• yyparse()– lex 의 yylex() 에 해당– 응용 예 : 파싱이 시작됨과 끝났음을 출력

• yacc -v– 파싱테이블을 y.output 에 출력

Page 12: 구문분석기 생성기  YACC

Yacc 실행체계

main()

yyerror()

yyparse() yylex()

main() { . . . yyparse(); . . .}

yyparse() { . . . while (1) { . . . t = yylex(); . . . yyerror(); . . . } . . .}

yylex() { . . . return(T); . . .}

Page 13: 구문분석기 생성기  YACC

구문지향 번역

Page 14: 구문분석기 생성기  YACC

구문지향 번역• 구문지향 번역 (syntax directed translation)

– 문법의 각 생성규칙에 대응하여 코드를 생성– 트리를 만들지 않음

• 비교– 트리를 사용한 번역에 비하여 간단하다– 1-pass 번역에만 적용 가능

Page 15: 구문분석기 생성기  YACC

수식 값의 계산• 수식 값의 계산

– 1+2*3 의 값 ?– 일반적인 방법

• 파스트리를 만든 후에 값을 계산– 다른 방법

• Yacc 에서 문법 기호의 값을 이용

• 문법 기호의 값– 생성규칙

A : B C D– 좌측 기호의 값 = $$– 우측 첫 기호의 값 = $1, 두번째의 값 = $2

Page 16: 구문분석기 생성기  YACC

문법 기호의 값• 1+2*3 의 유도 과정

Exp=> Exp + Term ( 규칙 1)=> Exp + Term * Num ( 규칙 3)=> Exp + Term * 3 ( 규칙 5)

• 문법규칙1. Exp ::= Exp + Term3. Term ::= Term * Num5. Num ::= 3

3

Term

Term

Num*

$$

$1 $2 $3

3

Exp

Term

Exp Term

Num

+

*

3

Num$$$1

Page 17: 구문분석기 생성기  YACC

예제• Yacc 의 예 1

A : B C D { printf("%d %d %d => %d", $1, $2, $3, $$); }

• Yacc 의 예 2E : E '+' T { printf("%d + %d = %d\n", $1, $3, $$); }

• Yacc 의 예 3%token NUMBER%%N : NUMBER { printf("%d\n", $1); $$ = $1; }

• 예 3 의 Lex[0-9]+ { yylval = atoi(yytext); return NUMBER; }

Page 18: 구문분석기 생성기  YACC

토큰의 값• 토큰의 값

– yylval 을 통하여 파서에게 전달• 토큰 값의 타입

– yylval 의 타입– YYSTYPE

• 여러 타입의 값을 허용하려면– C: union 을 사용– Yacc: %union 을 사용

Page 19: 구문분석기 생성기  YACC

%union• 토큰 값의 종류

– 정수 , 실수 , 스트링 , …– 여러 타입의 토큰을 파서에게 전달

• Yacc 에서 토큰의 타입을 정의%union { double dval; int vblno;}

• 각 토큰의 타입을 지정%token <vblno> NAME%token <dval> NUMBER

Page 20: 구문분석기 생성기  YACC

문법 기호의 타입• 문법 기호의 타입

– %union 에서 정의– %type 을 이용하여 지정

• 예%union { double dval; struct symtab *symp;}%token <symp> NAME%token <dval> NUMBER%type <dval> expression

Page 21: 구문분석기 생성기  YACC

평가용 실습• 문제

" 입력되는 수식의 값을 계산하는 lex 와 yacc의 source 을 작성하시오 "

– 허용하는 연산자 : + * - / ( )– 우선순위 : ( ) > * / > + -– 결합순위 : 모두 좌측 결합

• 입력 예(1+2+3)*(2*(51-47)/(1+2*3))

Page 22: 구문분석기 생성기  YACC

실습용 문법• 덧셈과 곱셈 식을 생성하는 문법

Exp : Exp ‘+’ Term | Exp ‘-’ Term | TermTerm : Term ‘*’ Fact | Term ‘/’ Fact | FactFact : ‘(’ Exp ‘)’ | NUMBER

Page 23: 구문분석기 생성기  YACC

Pretty Printer• Pretty printer 란 ?

– 입력된 프로그램을 보기 좋게 출력하는 프로그램

– 입력 : 문법에 따라 쓰여진 프로그램– 출력 : 들여쓰기 (indentation) 된 프로그램

• 예– UNIX 의 cb(C beautifier)

Page 24: 구문분석기 생성기  YACC

포함된 행동• 포함된 행동 (embedded action)

– 생성규칙의 중간에 있는 행동– 예

• 기존 : A : B C D { printf(); }• 포함 : A : B { printf(); } C D

– 실제의 의미는 ?A : B { printf(); } C D==>A : B xx C Dxx : { printf(); }

Page 25: 구문분석기 생성기  YACC

PP 용 입력 문법• 입력문법

S : If| While| ‘stmt’

If : ‘if’ Cond ‘then’ SWhile : ‘while’ Cond ‘do’ S ‘end’Cond : ‘c0’

Page 26: 구문분석기 생성기  YACC

입력과 출력의 예• 입력 예

while c0 do while c0 do if c0 then stmt end end

• 출력 예while c0 dowhile c0 doif c0 thenstmtend

end

Page 27: 구문분석기 생성기  YACC

Yacc 입력의 일부• Yacc 입력의 일부

%{int i, k;

%}%token ii tt ...%%...

If : ii {printf("\n"); for(k=0;k<i;k++) printf(" "); printf("if");} Cond tt {printf("then"); i=i+4;} S {i=i-4;} ;...

%%main() {i = 0;yyparse();

}

Page 28: 구문분석기 생성기  YACC

ToyPL 의 PP• 문제

– ToyPL 을 위한 Pretty Printer 를 lex 와 yacc를 이용하여 작성하시오

• 입력 예program Sample; proc Fact(n:long)var m:int; begin ... endvar a,b: int; begin ... end .

Page 29: 구문분석기 생성기  YACC

ToyPL 의 PP 출력• 출력 예

program Sample; proc Fact(n: long) var m: int; begin ... end var a,b: int;begin ...end.

Page 30: 구문분석기 생성기  YACC

문법의 모호성

Page 31: 구문분석기 생성기  YACC

파서를 만들 수 없는 문법• 모호한 문법

%% Exp : Exp '-' Exp | Exp '*' Exp | 'a' ;

• yacc 에서는…– 항상 shift/reduce conflict 가 발생– yacc 에서는 억지로 파서를 만듬

Page 32: 구문분석기 생성기  YACC

Lookahead 가 많이 필요한 문법

• 2 개의 미리보기가 필요 %% Exp : ZeroOne '+' '2' | OneTwo '+' '3' ; ZeroOne: '0' | '1' ; OneTwo : '1' | '2' ;

• 비교 : 미리보기가 1 개만 있어도 됨 %% Exp : ZeroOne '2' | OneTwo '3' ; ZeroOne: '0' | '1' ; OneTwo : '1' | '2' ;

Yacc 은LALR(1)

파서를 생성

Page 33: 구문분석기 생성기  YACC

수식문법• 뺄셈과 곱셈 식을 생성하는 문법

1. Exp ::= Exp - Exp2. | Exp * Exp3. | Num4. Num ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9

Page 34: 구문분석기 생성기  YACC

1-2*3 의 유도• 좌측유도

E 1 E - E 3 N - E 4 1 - E 2 1 - E * E 3 1 - N * E 4 1 - 2 * E 3 1 - 2 * N 4 1 - 2 * 3

E 2 E * E 1 E - E * E 3 N - E * E 4 1 - E * E 3 1 - N * E 4 1 - 2 * E 3 1 - 2 * N 4 1 - 2 * 3

• 우측유도E 1 E - E 2 E - E * E 3 E - E * N 4 E - E * 3

3 E - N * 3 4 E - 2 * 3 3 N - 2 * 3 4 1 - 2 * 3E 2 E * E 3 E * N 4 E * 3 1 E - E * 3

3 E - N * 3 4 E - 2 * 3 3 N - 2 * 3 4 1 - 2 * 3

12343434

Page 35: 구문분석기 생성기  YACC

1-2*3 의 유도트리

32

Exp

Exp Exp

Exp Exp

Num Num

Num

1

-

*

21

Exp

Exp Exp

Exp Exp

Num Num

Num

3

*

-

Page 36: 구문분석기 생성기  YACC

1-2-3 의 유도• 좌측유도

E 1 E - E 3 N - E 4 1 - E 1 1 - E - E 3 1 - N - E 4 1 - 2 - E 3 1 - 2 - N 4 1 - 2 - 3

E 1 E - E 1 E - E - E 3 N - E - E 4 1 - E - E 3 1 - N - E 4 1 - 2 - E 3 1 - 2 - N 4 1 - 2 - 3

• 우측유도E 1 E - E 1 E - E - E 3 E - E - N 4 E - E - 3

3 E - N - 3 4 E - 2 - 3 3 N - 2 - 3 4 1 - 2 - 3E 2 E - E 3 E - N 4 E - 3 1 E - E - 3

3 E - N - 3 4 E - 2 - 3 3 N - 2 - 3 4 1 - 2 - 3

11343434

Page 37: 구문분석기 생성기  YACC

1-2-3 의 유도트리

32

Exp

Exp Exp

Exp Exp

Num Num

Num

1

-

-

21

Exp

Exp Exp

Exp Exp

Num Num

Num

3

-

-

Page 38: 구문분석기 생성기  YACC

Yacc 실습• 다음의 yacc 입력으로 파서를 만드시오 .

%token Num%%E : E ‘-’ E { printf(“rule 1\n”); } | E ‘*’ E { printf(“rule 2\n”); } | N { printf(“rule 3\n”); } ;N : Num { printf(“rule 4\n”); } ;

• 다음 입력에 대하여 적용된 생성규칙을 확인하고 파스 트리를 그리시오 .1 - 2 * 31 * 2 - 31 - 2 - 3

Page 39: 구문분석기 생성기  YACC

모호한 문법• 모호한 문법 (ambiguous grammar)

– 어떤 문장에 대하여 유도트리가 두개이상 존재할 때

– 수식문법은 모호• 예 : If- 문

<Stmt> ::= <AsgnStmt> | <IfStmt> | <WhileStmt> | <ForStmt> | <CallStmt> | <CompStmt> | s<IfStmt> ::= if ( <Cond> ) then <Stmt> | if ( <Cond> ) then <Stmt> else <Stmt><Cond> ::= c

Page 40: 구문분석기 생성기  YACC

유도트리 그리기• 다음 문장에 대한 유도트리를 모두

그리시오 .if ( c ) then if ( c ) then s else s

• 2 개의 유도트리가 존재

Page 41: 구문분석기 생성기  YACC

모호한 문법의 문제점• 문장에 대한 여러 해석이 가능• 수식문법

– 1 - 2 * 3 의 값은 ?• If- 문

– 다음의 문장에서 j++ 가 실행되는 조건은 ?– if (i < 0) then if (j < 0) then i++ else j++

Page 42: 구문분석기 생성기  YACC

해결책• 해결책

– 모호하지 않은 문법으로 변환– yacc 의 모호성 해결 규칙의 사용

• 모호하지 않은 문법으로 변환Exp ::= Exp + Term | TermTerm ::= Term * Num | NumNum ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9

3

2

Exp

Term

Exp Term

Num

NumTerm

+

*

1

Num

Page 43: 구문분석기 생성기  YACC

Yacc 의 모호성 해결• yacc 에서 conflict 해결

– 사용자가 명시하지 않을 경우=> 기본 (default) 규칙

– 사용자가 명시=> 사용자가 우선순위 / 결합순위를 명시

• 기본 규칙– shift/reduce conflict: shift 우선– reduce/reduce conflict: 문법 상에서 먼저

나타나는 규칙을 reduce

Page 44: 구문분석기 생성기  YACC

우선순위• 사용자가 순서를 명시

– 지정 위치 : 정의 부분– 순위 지정의 대상 : 토큰

• 우선순위– 높은 우선순위의 연산자를 먼저 적어 준다 .– 1 - 2 * 3– 지정 예 :

%left ‘*’ %left ‘-’ %%

Page 45: 구문분석기 생성기  YACC

결합순위• 결합순위

– 같은 우선 순위의 연산자 사이의 순서– 1 - 2 - 3

• 좌측결합– (1 - 2) - 3– %left ‘-’

• 우측결합– 1 - (2 - 3)– %right ‘-’

Page 46: 구문분석기 생성기  YACC

결합 / 우선순위로 해결한 예• 결합 / 우선순위로 해결한 예

%left ‘*’%left ‘-’%token Num%%E : E ‘-’ E { printf(“rule 1\n”); } | E ‘*’ E { printf(“rule 2\n”); } | N { printf(“rule 3\n”); } ;N : Num { printf(“rule 4\n”); } ;

Page 47: 구문분석기 생성기  YACC

Yacc 실습• 결합 / 우선순위를 다음과 같이 지정하여

각각의 파서를 만들자 .%left ‘*’ %right ‘*’ %left ‘-’ %right ‘-’%left ‘-’ %right ‘-’ %left ‘*’ %right ‘*’%% %% %% %%

• 각 파서에 대하여 다음의 입력으로 실행하여 적용된 생성규칙을 확인하고 파스 트리를 그리자 .1 - 2 * 3 1 * 2 - 3 1 - 2 - 3