1 / 47

구문분석기 생성기 YACC

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

oakley
Download Presentation

구문분석기 생성기 YACC

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 구문분석기 생성기 YACC

  2. 문법표현 + C 코드 Yacc 원시 프로그램 어휘분석기 y.tab.c C 코드의 실행결과 Yacc • Yacc • Yet Another Compiler Compiler • 1975년, Johnson • LALR(1) 파서 생성기

  3. 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

  4. 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); }

  5. Yacc의 입력 • 입력의 구성 • 선언 부분 • y.tab.c에서 사용할 자료구조, 변수, 상수를 정의 • 생성규칙 부분에서 사용되는 토큰의 이름을 정의 • 생성규칙 부분 • 문법의 생성규칙을 기술 • 생성규칙이 reduce될 때 처리할 행위(C 코드)를 기술 선언 부분 %% 생성규칙 부분 %% 사용자 부프로그램 부분

  6. 선언 부분 • 형태 • 정의 예 %token NUMBER %{ /* y.tab.c에 복사될 내용 */ %} %token 토큰이름1 토큰이름2 ... %start 시작문법기호 %left 모호한 문법에서 사용 %right ' ' %nonassoc ' '

  7. 생성규칙 부분 • 형태 • ::= 기호 대신에 : 기호를 사용 • 문자토큰은 '와 '사이에 둠 (대소문자 구별은 없음) • 생성규칙의 끝에는 ; 기호를 첨가 • 정의 예 %% Exp : Exp '+' Term { printf("rule 1\n"); } | Term { printf("rule 2\n"); } ; %% 생성규칙1 C 코드1 생성규칙2 C 코드 2 ... 생성규칙n C 코드 n

  8. 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"); } ;

  9. ToyPL 문법 검사기 • 문제: ToyPL로 작성된 어떤 프로그램이 문법에 적합한지 검사하자. • 입력: ToyPL로 작성되었다고 여겨지는 어떤 프로그램 • 출력: 문법에 맞지 않으면 “syntax error”를 출력 • 방법: ToyPL 문법을 yacc으로 작성

  10. Yacc 실습 • 괄호문법 S ::= ( S ) S | • 괄호문법을 위한 lex source • 괄호 이외의 문자는 모두 무시함 • 괄호문법을 위한 입력 예 ( a + b ) + ( 4 * ( ( 33 - sum ) / ( sum + 21 ) ) )

  11. Yacc의 상세 설명 • yyerror() • 문법에 맞지 않는 문장에 대한 오류 메세지 • 사용자 부 프로그램 부분에 정의 %% yyerror() { printf("틀린수식입니다\n"); } • yyparse() • lex의 yylex()에 해당 • 응용 예: 파싱이 시작됨과 끝났음을 출력 • yacc -v • 파싱테이블을 y.output에 출력

  12. main() yyparse() yylex() yyerror() Yacc 실행체계 main() { . . . yyparse(); . . . } yyparse() { . . . while (1) { . . . t = yylex(); . . . yyerror(); . . . } . . . } yylex() { . . . return(T); . . . }

  13. 구문지향 번역

  14. 구문지향 번역 • 구문지향 번역 (syntax directed translation) • 문법의 각 생성규칙에 대응하여 코드를 생성 • 트리를 만들지 않음 • 비교 • 트리를 사용한 번역에 비하여 간단하다 • 1-pass 번역에만 적용 가능

  15. 수식 값의 계산 • 수식 값의 계산 • 1+2*3의 값? • 일반적인 방법 • 파스트리를 만든 후에 값을 계산 • 다른 방법 • Yacc에서 문법 기호의 값을 이용 • 문법 기호의 값 • 생성규칙 A : B C D • 좌측 기호의 값 = $$ • 우측 첫 기호의 값 = $1, 두번째의 값 = $2

  16. Exp Exp Term + Term Num * 3 $$ Term Term Num * 3 $1 $2 $3 Num $$ $1 3 문법 기호의 값 • 1+2*3의 유도 과정 Exp=> Exp + Term (규칙 1) => Exp + Term * Num (규칙 3) => Exp + Term * 3 (규칙 5) • 문법규칙 1. Exp ::= Exp + Term 3. Term ::= Term * Num 5. Num ::= 3

  17. 예제 • Yacc의 예1 A : B C D { printf("%d %d %d => %d", $1, $2, $3, $$); } • Yacc의 예2 E : 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; }

  18. 토큰의 값 • 토큰의 값 • yylval을 통하여 파서에게 전달 • 토큰 값의 타입 • yylval의 타입 • YYSTYPE • 여러 타입의 값을 허용하려면 • C: union을 사용 • Yacc: %union을 사용

  19. %union • 토큰 값의 종류 • 정수, 실수, 스트링, … • 여러 타입의 토큰을 파서에게 전달 • Yacc에서 토큰의 타입을 정의 %union { double dval; int vblno; } • 각 토큰의 타입을 지정 %token <vblno> NAME %token <dval> NUMBER

  20. 문법 기호의 타입 • 문법 기호의 타입 • %union에서 정의 • %type을 이용하여 지정 • 예 %union { double dval; struct symtab *symp; } %token <symp> NAME %token <dval> NUMBER %type <dval> expression

  21. 평가용 실습 • 문제 "입력되는 수식의 값을 계산하는 lex와 yacc의 source을 작성하시오" • 허용하는 연산자: + * - / ( ) • 우선순위: ( ) > * / > + - • 결합순위: 모두 좌측 결합 • 입력 예 (1+2+3)*(2*(51-47)/(1+2*3))

  22. 실습용 문법 • 덧셈과 곱셈 식을 생성하는 문법 Exp : Exp ‘+’ Term | Exp ‘-’ Term | Term Term : Term ‘*’ Fact | Term ‘/’ Fact | Fact Fact : ‘(’ Exp ‘)’ | NUMBER

  23. Pretty Printer • Pretty printer란? • 입력된 프로그램을 보기 좋게 출력하는 프로그램 • 입력: 문법에 따라 쓰여진 프로그램 • 출력: 들여쓰기(indentation)된 프로그램 • 예 • UNIX의 cb(C beautifier)

  24. 포함된 행동 • 포함된 행동 (embedded action) • 생성규칙의 중간에 있는 행동 • 예 • 기존: A : B C D { printf(); } • 포함: A : B { printf(); } C D • 실제의 의미는? A : B { printf(); } C D ==> A : B xx C D xx : { printf(); }

  25. PP용 입력 문법 • 입력문법 S : If | While | ‘stmt’ If : ‘if’ Cond ‘then’ S While : ‘while’ Cond ‘do’ S ‘end’ Cond : ‘c0’

  26. 입력과 출력의 예 • 입력 예 while c0 do while c0 do if c0 then stmt end end • 출력 예 while c0 do while c0 do if c0 then stmt end end

  27. 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(); }

  28. ToyPL의 PP • 문제 • ToyPL을 위한 Pretty Printer를 lex와 yacc를 이용하여 작성하시오 • 입력 예 program Sample; proc Fact(n:long) var m:int; begin ... end var a,b: int; begin ... end .

  29. ToyPL의 PP 출력 • 출력 예 program Sample; proc Fact(n: long) var m: int; begin ... end var a,b: int; begin ... end.

  30. 문법의 모호성

  31. 파서를 만들 수 없는 문법 • 모호한 문법 %% Exp : Exp '-' Exp | Exp '*' Exp | 'a' ; • yacc에서는… • 항상 shift/reduce conflict가 발생 • yacc에서는 억지로 파서를 만듬

  32. 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)파서를 생성

  33. 수식문법 • 뺄셈과 곱셈 식을 생성하는 문법 1. Exp ::= Exp - Exp 2. | Exp * Exp 3. | Num 4. Num ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9

  34. 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 * 3 E 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

  35. Exp Exp Exp - Exp Exp * Exp Num Exp * Exp Exp - Exp Num 1 Num Num Num Num 3 2 3 1 2 1-2*3의 유도트리

  36. 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 - 3 E 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

  37. Exp Exp Exp - Exp Exp - Exp Num Exp - Exp Exp - Exp Num 1 Num Num Num Num 3 2 3 1 2 1-2-3의 유도트리

  38. 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 * 3 1 * 2 - 3 1 - 2 - 3

  39. 모호한 문법 • 모호한 문법 (ambiguous grammar) • 어떤 문장에 대하여 유도트리가 두개이상 존재할 때 • 수식문법은 모호 • 예: If-문 <Stmt> ::= <AsgnStmt> | <IfStmt> | <WhileStmt> | <ForStmt> | <CallStmt> | <CompStmt> | s <IfStmt> ::= if ( <Cond> ) then <Stmt> | if ( <Cond> ) then <Stmt> else <Stmt> <Cond> ::= c

  40. 유도트리 그리기 • 다음 문장에 대한 유도트리를 모두 그리시오. if ( c ) then if ( c ) then s else s • 2개의 유도트리가 존재

  41. 모호한 문법의 문제점 • 문장에 대한 여러 해석이 가능 • 수식문법 • 1 - 2 * 3의 값은? • If-문 • 다음의 문장에서 j++가 실행되는 조건은? • if (i < 0) then if (j < 0) then i++ else j++

  42. Exp Exp + Term Term Term * Num Num Num 3 1 2 해결책 • 해결책 • 모호하지 않은 문법으로 변환 • yacc의 모호성 해결 규칙의 사용 • 모호하지 않은 문법으로 변환 Exp ::= Exp + Term | Term Term ::= Term * Num | Num Num ::= 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9

  43. Yacc의 모호성 해결 • yacc에서 conflict 해결 • 사용자가 명시하지 않을 경우=> 기본(default) 규칙 • 사용자가 명시=> 사용자가 우선순위/결합순위를 명시 • 기본 규칙 • shift/reduce conflict: shift 우선 • reduce/reduce conflict: 문법 상에서 먼저 나타나는 규칙을 reduce

  44. 우선순위 • 사용자가 순서를 명시 • 지정 위치: 정의 부분 • 순위 지정의 대상: 토큰 • 우선순위 • 높은 우선순위의 연산자를 먼저 적어 준다. • 1 - 2 * 3 • 지정 예:%left ‘*’ %left ‘-’ %%

  45. 결합순위 • 결합순위 • 같은 우선 순위의 연산자 사이의 순서 • 1 - 2 - 3 • 좌측결합 • (1 - 2) - 3 • %left ‘-’ • 우측결합 • 1 - (2 - 3) • %right ‘-’

  46. 결합/우선순위로 해결한 예 • 결합/우선순위로 해결한 예 %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”); } ;

  47. Yacc 실습 • 결합/우선순위를 다음과 같이 지정하여 각각의 파서를 만들자. %left ‘*’ %right ‘*’ %left ‘-’ %right ‘-’ %left ‘-’ %right ‘-’ %left ‘*’ %right ‘*’ %% %% %% %% • 각 파서에 대하여 다음의 입력으로 실행하여 적용된 생성규칙을 확인하고 파스 트리를 그리자. 1 - 2 * 3 1 * 2 - 3 1 - 2 - 3

More Related