Www.msharpmath.comSeoul National University 1 / 24 컴퓨터 개론 및 실습 강의 11 (parser)

Slides:



Advertisements
Similar presentations
YES C 제 1 장 C 언어의 개요 1/34 제 1 장 C 언어의 개요 문봉근. YES C 제 1 장 C 언어의 개요 2/34 제 1 장 C 언어의 개요 1.1 프로그램과 C 언어의 특징 1.2 C 언어의 프로그램 구성 1.3 비주얼 C++ 통합 환경 들어가기.
Advertisements

1.
제6장 조건문.
프로그래밍1 및 실습 (C언어) - 3장 기본자료형 (3.6부터 끝까지) -
YACC 응용 예 Desktop Calculator.
제3장 C 프로그래밍 환경.
제 1장 C 언어의 소개.
C 프로그래밍 소개 숙명여대 창병모 2011 가을.
제 8 장  파서 생성기 YACC 사용하기.
Chapter 7. 조건문.
Report #2 - Solution 문제 #1: 다음과 같이 프로그램을 작성하라.
제3장 시맨틱스(Semantics) Reading Chap 13 © 숙대 창병모.
쉽게 풀어쓴 C언어 Express 제17장 동적 메모리와 연결 리스트 C Express.
제9장 C 프로그래밍 환경 창병모
제5장 제어명령
처음으로 배우는 C 프로그래밍 제2부 기초 제5장 반복문.
3장. 변수와 연산자. 3장. 변수와 연산자 3-1 연산자, 덧셈 연산자 연산자란 무엇인가? 연산을 요구할 때 사용되는 기호 ex : +, -, *, / 3-1 연산자, 덧셈 연산자 연산자란 무엇인가? 연산을 요구할 때 사용되는 기호 ex : +, -, *, /
4장 어휘 / 구문 분석 (Term project 포함)
7. while 문의 흐름 제어.
자료구조 김현성.
쉽게 풀어쓴 C언어 Express 제17장 동적 메모리와 연결 리스트 C Express.
쉽게 풀어쓴 C언어 Express 제17장 동적메모리와 연결리스트 C Express.
동적메모리와 연결리스트 컴퓨터시뮬레이션학과 2016년 봄학기 담당교수 : 이형원 E304호,
AVR - Chapter 15 황 지 연.
fork로 생성한 자식 프로세스에서 exec 함수군을 호출
제3장 스택과 큐.
제15장 전처리 및 비트연산.
8장 함수 함수의 필요성 라이브러리 함수와 사용자 정의 함수 함수의 정의, 원형, 호출 배열을 함수 인자로 전달 재귀호출.
Chapter 06. 선택문.
C언어 프로그래밍의 이해 Ch05. 명령문 Phylogenetic: 계통, 발생(학)의.
Tail-recursive Function, High-order Function
제 3 장 상수와 변수
C++프로그래 밍 컴퓨터정보과 / 이기희교수.
10장 C 표준 파일 입출력 子曰 學而時習(실습?)之 不亦悅乎.
-제어문, 함수, 클래스- IS lab. 김건영 Python -제어문, 함수, 클래스- IS lab. 김건영
4장 제어문 선택문: if 문, if – else 문, switch 문
adopted from KNK C Programming : A Modern Approach
어서와 C언어는 처음이지 제14장.
3장 상수 변수 기본 자료형 키워드와 식별자 상수와 변수 기본 자료형 형변환 자료형의 재정의.
컴퓨터의 기초 제 2강 - 변수와 자료형 , 연산자 2006년 3월 27일.
제2장 제어구조와 배열 if-else 문에 대하여 학습한다. 중첩 if-else 문에 대하여 학습한다.
쉽게 풀어쓴 C언어 Express 제15장 전처리 및 비트연산 C Express Slide 1 (of 29)
함수와 변수 컴퓨터시뮬레이션학과 2016년 봄학기 담당교수 : 이형원 E304호,
제어문 & 반복문 C스터디 2주차.
컴퓨터 프로그래밍 기초 - 10th : 포인터 및 구조체 -
3장. 변수와 연산자. 3장. 변수와 연산자 3-1 연산자, 덧셈 연산자 연산자란 무엇인가? 연산을 요구할 때 사용되는 기호 ex : +, -, *, / 3-1 연산자, 덧셈 연산자 연산자란 무엇인가? 연산을 요구할 때 사용되는 기호 ex : +, -, *, /
Java의 정석 제 4 장 조건문과 반복문 Java 정석 남궁성 강의
Chapter 05. 입출력 함수.
자바 5.0 프로그래밍.
김선균 컴퓨터 프로그래밍 기초 - 7th : 함수 - 김선균
5장 선택제어문 if 선택문 switch-case 선택문 다양한 프로그램 작성 조건 연산자.
Fflush 사용이유 및 방법 [이유] 키보드에서 입력된 내용은 입력버퍼에 저장되었다가 Enter 키가 들어오면 프로그램으로 전달됨 이 때 입력버퍼에 있는 Enter 키도 프로그램으로 전달됨 그러므로 아래와 같은 프로그램에서 문자 하나를 입력해도 Enter키도 입력된 것으로.
U N I X 창원대학교 전자계산학과 김병찬.
C언어 프로그래밍의 이해 Ch05. 명령문.
-Part1- 제8장 조건문이란 무엇인가 (교재 199페이지 ~ 224페이지)
쉽게 풀어쓴 C언어 Express 제6장 조건문 C Express Slide 1 (of 28)
GDB - GNU Debugger 김진용.
윤성우의 열혈 C 프로그래밍 윤성우 저 열혈강의 C 프로그래밍 개정판 Chapter 08. 조건에 따른 흐름의 분기.
쉽게 풀어쓴 C언어 Express 제6장 조건문 C Express.
반복문의 기능 반복문 반복문 특정 영역을 특정 조건이 만족하는 동안에 반복 실행하기 위한 문장 while문
제5장 디버깅과 추적 문봉근.
실습과제 1번 생성된 파일 basic.txt를 프로젝트 폴더에서 메모장으로 열고 내용을 확인
3장 (2) 구문과 의미론 순천향대학교 컴퓨터공학과 하상호.
어서와 C언어는 처음이지 제16장.
제 29 강 스트링(string) 다루기 s a i s . s T i h t g r i n.
Lecture 03 제어문과 메소드 Kwang-Man Ko
C 13장. 입출력 라이브러리 #include <stdio.h> int main(void) { int num;
C.
printf("Global Korea\n");
PHP 기초문법 PHP를 공부하는데 있어 가장 기초가 되는 PHP기초문법에 대해서 배워 봅니다.
Presentation transcript:

National University 1 / 24 컴퓨터 개론 및 실습 강의 11 (parser)

National University 2 / 24 parser ■ 컴파일러의 기초 start  list eof list  expr ; list | e expr  term moreterms moreterms  + term { print("+") } moreterms * 5 = 3 + ( 4 * 5 ) | - term { print("-") } moreterms | e term  factor morefactors morefactors  * factor { print("*") } morefactors | / factor { print("/") } morefactors | div factor { print("DIV") } morefactors | mod factor { print("MOD") } morefactors | e factor  (expr) | id { print(id.lexeme) } X = 3 ; 5 + X ; | num { print(num.value) }

National University 3 / 24 ■ + - * / DIV MOD ( ) ID - 식별자 NUM - 숫자 DONE - 파일의 끝 token

National University 4 / 24 ■ * 5 ; 12div 5 mod 2 ; -3 ; // homework sample run

National University 5 / 24 #include #define STRMAX 999 #define SYMMAX 100 #define BSIZE 128 #define NONE -1 #define EOS '\0' #define NUM 256 #define DIV 257 #define MOD 258 #define ID 259 #define DONE 260 int lookahead = 0; int tokenval = NONE; int lineno = 1; int lastchar = -1; int lastentry = 0; parser program list

National University 6 / 24 char lexbuf[BSIZE]; char lexemes[STRMAX]; struct entry { char *lexptr; int token; }; struct entry symtable[SYMMAX]; struct entry keywords[] = { "div", DIV, "mod", MOD, 0, 0 }; parser program list

National University 7 / 24 int lookup(char s[]); int insert(char s[], int tok); void init(); void parse(); void expr(); void term(); void factor(); void match(int t); void emit(int t, int tval); int lexan(); void error(char *); void main() { init(); parse(); //exit(0); } void init() { struct entry *p; for (p = keywords; p->token; p++) insert(p->lexptr, p->token); } parser program list

National University 8 / 24 int lookup(char s[]) { int p; for (p = lastentry; p > 0; p = p - 1) if (strcmp(symtable[p].lexptr, s) == 0) return p; return 0; } int insert(char s[], int tok) { int len; len = strlen(s); if (lastentry + 1 >= SYMMAX) error("symbol table full"); if (lastchar + len +1 >= STRMAX) error("lexemes array full"); lastentry = lastentry + 1; symtable[lastentry].token = tok; symtable[lastentry].lexptr = &lexemes[lastchar + 1]; lastchar = lastchar + len + 1; strcpy(symtable[lastentry].lexptr, s); return lastentry; } parser program list

National University 9 / 24 start  list eof list  expr ; list | e void parse() { lookahead = lexan(); while (lookahead != DONE) { expr(); match(';'); } void match(int t) { if (lookahead == t) lookahead = lexan(); else error("syntax error"); } parser program list

National University 10 / 24 expr  term moreterms moreterms  + term { print("+") } moreterms * 5 = 3 + ( 4 * 5 ) | - term { print("-") } moreterms | e void expr() { int t; term(); while (1) switch (lookahead){ case '+': case'-': t = lookahead; match(lookahead); term(); emit(t, NONE); continue; default: return; } parser program list

National University 11 / 24 term  factor morefactors morefactors  * factor { print("*") } morefactors | / factor { print("/") } morefactors | div factor { print("DIV") } morefactors | mod factor { print("MOD") } morefactors | e void term() { int t; factor(); while (1) switch (lookahead){ case '*': case '/': case DIV: case MOD: t = lookahead; match(lookahead); factor(); emit(t, NONE); continue; default: return; } parser program list

National University 12 / 24 factor  (expr) | id { print(id.lexeme) } X = 3 ; 5 + X ; | num { print(num.value) } void factor() { switch (lookahead){ case '(': match('('); expr(); match(')'); break; case NUM: emit(NUM, tokenval); match(NUM); break; case ID: emit(ID, tokenval); match(ID); break; default: error("syntax error"); } parser program list

National University 13 / 24 void emit(int t, int tval) { switch (t) { case '+': case '-': case '*': case '/': printf("%c\n", t); break; case DIV: printf("DIV\n"); break; case MOD: printf("MOD\n"); break; case NUM: printf("%d\n", tval); break; case ID: printf("%s\n", symtable[tval].lexptr); break; default: printf("token %d, tokenval %d\n", t, tval); } void error(char *m) { //fprintf(stderr, "line %d: %s\n", lineno, m); printf("line %d: %s\n", lineno, m); //exit(1); } parser program list

National University 14 / 24 int lexan() { int t; while (1){ t = getchar(); if (t == ' ' || t == '\t') ; else if (t == '\n') lineno = lineno + 1; else if (isdigit(t)) { ungetc(t, stdin); scanf("%d", &tokenval); return NUM; } else if (isalpha(t)){ int p, b = 0; while (isalnum(t)) { lexbuf[b] = t; t = getchar(); b = b + 1; if (b >= BSIZE) error("compiler error"); } parser program list lexbuf[b] = EOS; if (t != EOF) ungetc(t, stdin); p = lookup(lexbuf); if (p == 0) p = insert(lexbuf, ID); tokenval = p; return symtable[p].token; } else if (t == EOF) return DONE; else { tokenval = NONE; return t; }

National University 15 / 24 parser program list (uminus installed version) start  list eof list  expr ; list | e expr  term moreterms moreterms  + term { print("+") } moreterms * 5 = 3 + ( 4 * 5 ) | - term { print("-") } moreterms | e term  factor morefactors morefactors  * factor { print("*") } morefactors | / factor { print("/") } morefactors | div factor { print("DIV") } morefactors | mod factor { print("MOD") } morefactors | e factor  (expr) | id { print(id.lexeme) } X = 3 ; 5 + X ; | num { print(num.value) } | - factor { print('UMINUS') }

National University 16 / 24 #define DONE 260 #define UMINUS 261 void factor() { switch (lookahead){ case '(': match('('); expr(); match(')'); break; case NUM: emit(NUM, tokenval); match(NUM); break; case ID: emit(ID, tokenval); match(ID); break; case '-': match('-'); factor(); emit(UMINUS, NONE); break; default: error("syntax error"); } void emit(int t, int tval) { switch (t) { case '+': case '-': case '*': case '/': printf("%c\n", t); break; case DIV: printf("DIV\n"); break; case MOD: printf("MOD\n"); break; case NUM: printf("%d\n", tval); break; case ID: printf("%s\n", symtable[tval].lexptr); break; case UMINUS: printf("UMINUS\n"); break; default: printf("token %d, tokenval %d\n", t, tval); } parser program list (uminus installed version)

National University 17 / 24 parser program list (power installed version) ■ power 거듭제곱 (power) 는 곱하기, 나누기 보다 우선순위가 높으므로 5 * 2 ^ 3 ; 은 5 * 2 ^ 3 = 5 * (2 ^ 3) = 5 * 8 = 40 으로 계산된다. 더하기, 빼기, 곱하기, 나누기, 거듭제곱의 우선 순위를 생각하면 * 2 ^ 3 = 4 + ( 5 * ( 2 ^ 3 ) ) 으로 처리되야 하므로 거듭제곱에 관한 파서를 만들어 보기로 한다. 하지만 다음에 제시하는 파서는 중대한 오류가 있다. 이것을 찾아서 고쳐야 하는데 일단 틀린 버전에 대해 생각해보자.

National University 18 / 24 parser program list (power installed version) but wrong !!! start  list eof list  expr ; list | e expr  term moreterms moreterms  + term { print("+") } moreterms | - term { print("-") } moreterms | e term  power morepowers morepowers  * power { print("*") } more powers | / power { print("/") } more powers | div power { print("DIV") } more powers | mod power { print("MOD") } more powers | e power  factor morefactors morefactors  ^ power { print("^") } morefactors | e factor  (expr) | id { print(id.lexeme) } | num { print(num.value) } | - factor { print('UMINUS') } start  list eof list  expr ; list | e expr  term moreterms moreterms  + term { print("+") } moreterms | - term { print("-") } moreterms | e term  factor morefactors morefactors  * factor { print("*") } morefactors | / factor { print("/") } morefactors | div factor { print("DIV") } morefactors | mod factor { print("MOD") } morefactors | e factor  (expr) | id { print(id.lexeme) }; | num { print(num.value) }

National University 19 / 24 #define UMINUS 261 #define POWER 262 void power(); void term() { int t; power(); while (1) switch (lookahead){ case '*': case '/': case DIV: case MOD: t = lookahead; match(lookahead); power(); emit(t, NONE); continue; default: return; } void power() { int t; factor(); while (1) switch (lookahead){ case '^': t = lookahead; match(lookahead); factor(); emit(t, NONE); continue; default: return; } parser program list (power installed version) but wrong !!!

National University 20 / 24 void factor() { switch (lookahead){ case '(': match('('); expr(); match(')'); break; case NUM: emit(NUM, tokenval); match(NUM); break; case ID: emit(ID, tokenval); match(ID); break; case '-': match('-'); factor(); emit(UMINUS, NONE); break; default: error("syntax error"); } void emit(int t, int tval) { switch (t) { case '+': case '-': case '*': case '/': case '^': printf("%c\n", t); break; case DIV: printf("DIV\n"); break; case MOD: printf("MOD\n"); break; case NUM: printf("%d\n", tval); break; case ID: printf("%s\n", symtable[tval].lexptr); break; case UMINUS: printf("UMINUS\n"); break default: printf("token %d, tokenval %d\n", t, tval); } parser program list (power installed version) but wrong !!!

National University 21 / 24 parser program list (power installed version) but wrong !!! ■ 프로그램 실행결과 앞에서 작성한 파서를 이용하여 * 2 ^ 3 ; 을 파싱하면 ^ * + 가 되어 2^3 을 계산하여 * + 이므로 와 같이 44 를 얻는다. 이것은 맞은 결과이다. 그러면 무엇이 잘못되었는가 ?

National University 22 / 24 parser program list (power installed version) but wrong !!! ■ 프로그램 실행결과 - 3 ^ 2; 을 파싱하면 3 UMINUS 2 ^ 그러면 3 UMINUS 가 실행되어 (-3) 2 ^ 이므로 (-3)^2 = (-3)*(-3) = 9 를 얻는다. 하지만 원래의 수식은 3 의 제곱에 음수를 붙인 것이므 로 -9 가 정답이다. 따라서 파서의 설계가 잘못 되었다. 이것을 어떻게 수정하면 될 것인지를 생각해보자.

National University 23 / 24 parser program list (power installed version) but wrong !!! ■ 문제해결을 위한 방안 앞의 문제에서 처음부터 단항연산자 UMINUS (부호를 바꾸는 연산)의 설계에 문제가 있는지 부터 생각해보자. 단항연산자 UMINUS 를 빼기와 구별하기 위하여 [-]로 나타내기로 한다. - 3 * 2; 를 파싱하는 방법에는 두 가지가 있다. (-3)*2 ; 또는 -(3*2); 는 모두 같은 결과를 얻고, 파싱 하게 되면 - ( 3 * 2 ) ; --> 3 2 * [-] ; (-3) * 2; --> 3 [-] 2 * ; 위의 결과에서 곱하기 * 를 ^ 으로 바꾸어 쓰면 -3^2 의 경우 - ( 3 ^ 2 ) ; 3 2 ^ [-] ; (-3)^2 ; --> 3 [-] 2 ^ ; 으로 되고 두 번째의 경우가 앞에서 잘못된 결과에 해당한다. 따라서 첫 번째 처럼 파싱하면 문제가 해결될 것이다. 그렇다면 UMINUS 의 처음 설계부터 고쳐야 하는지 고민하게 된다.

National University 24 / 24 parser program list (power installed version) but wrong !!! ■ Home Work (HomeWork) 홈페이지에서 C program list 실습 docx 파일을 내려받는다. 마지막에 포함된 프로그램을 수정하여 -3 ^ 2 ; 인 명령이 3 2 ^ UMINUS 와 같이 파싱되도록 수정하라. 과제의 제출은 (1) 6월 8일 기말시험 튜토링 시간(2시-3시)에 제출한다. (3시-4시는 시험 시간) (2) 내려받은 프로그램에서 수정된 부분을 포함하는 함수만 프린트한다.