Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 |
Tags
- 파이썬 #python #os #os.path #glob
- 사용자정의예외
- docker
- 파이썬 #python #Comprehension
- 파이썬 #python #filter #map #reduce
- 파이썬 #python #지역함수
- 배포
- 파이썬기본문법 #파이썬 #python
- 파이썬 #python #가변매개변수 #키워드가변매개변수 #args #kwargs
- jsonb
- 파이썬 #python #file #i/o #input #output
- Git
- aw3
- 파이썬 #python #docstring
- 파이썬 #python #전역변수 #지역변수 #eval
- aws
- 파이썬 #python #class #클래스 #상속
- 파이썬 #python #함수 #function
- 파이썬 #python #lambda #람다
- EC2
- 프로그래머스
- redis
- 연산자메서드
- 약수 수하기
- 민감 정보 관리
- 파이썬 #python #모듈 #module #import #random #time #calendar #sys
- spring boot
- 파이썬 #python #예외처리 #exception
- 파이썬 #python #enumerate
- PostgreSQL
Archives
- Today
- Total
Yeonnnnny
신택스 분석기 - (4) 함수 선언문 분석 본문
function_definition
: declaration_specifiers declarator {$$=setFunctionDeclaratorSpecifier($2,$1);} compound_statement {$$=setFunctionDeclaratorBody($3,$4);}
// $3은 {$$=setFunctionDeclaratorSpecifier($2,$1);} 값을 가리킴
| declarator {$$=setFunctionDeclaratorSpecifier($1,makeSpecifier(int_type,0));} compound_statement {$$=setFunctionDeclaratorBody($2,$3);}
// 선언 지시자가 없는 함수 선언문은 반환 타입을 정수형으로 하기로 약속했기에 int_type의 타입 테이블을 가리킴
// $2은 {$$=setFunctionDeclaratorSpecifier($1,makeSpecifier(int_type,0));} 값을 가리킴
;
<declaration_specifier>는 선언지시자(storage_class_specifier와 type_specifier) 주소를 가리키고, <declarator>는 함수 명칭을 위한 심볼테이블 주소를 가리키며, <compound_statement>는 함수의 몸체를 위함 복합문 명령에 대한 신택스 트리의 루트 노드를 가리키게 됨.
함수 명칭을 위한 심볼 테이블은 함수 선언자가 간단한 형식일 때 는 리턴 타입의 정보가 없지만 포인터나 배열 등의 복잡한 형식을 가지더라도 이에 관한 타입 정보가 연결되어 있음.
함수의 머리줄 부분의 분석을 마치며(복합문 명령문 분석 바로 전에) 이런 함수 명칭을 위한 심볼 테이블에 선언지시자에 나타난 리턴 타입 정보를 저장함. 함수 명칭 앞에 타입 명시자가 생략된 경우에는 함수의 리턴 타입으로 정수형 타입 정보를 연결함. 함수 선언문 분석을 마치면서, 함수 명칭을 위한 심볼테이블에 함수 몸체를 가리키는 신택스 트리를 연결하고, <function_definition> 은 그 심볼 테이블 주소를 저장하도록 함.
- A_ID *setFunctionDeclaratorSpecifier(A_ID *, A_SPECIFIER *);
- 함수 명칭 심볼테이블과 몸체에 대한 신택스 트리 연결하는 함수
- 주어진 심볼테이블의 명칭이 함수 타입으로 잘 선언되었는지 검사
- 해당 타입 테이블에서 함수의 리턴 타입이 인자로 전달받은 선언지시자의 타입 정보로 설정
- 함수 명칭에 대한 중복 검사를 하고, 함수 프로토 타입이 선언되어 있는 경우, 그 프로토 타입 선언 내용(리턴 타입, 파라미터 개수와 타입)과 일치하는지 검사
- 스코프 범위 조절(함수 파라미터 명칭 목록을 몸체의 복합문 안에서 사용하기 위함)
// 함수 선언문을 위한 검사와 값 설정하는 함수
A_ID *setFunctionDeclaratorSpecifier(A_ID *id, A_SPECIFIER *p){
A_ID *a;
// storage class 검사 - 이미 존재하면 에러
if(p->stor) syntax_error(25);
setDefaultSpecifier(p);
// 함수 명칭이 파라미터 목록 바로 직전에 있는지 검사
if(id->type->kind != T_FUNC){
syntax_error(21);
return(id);
}else{
id=setDeclaratorElementType(id, p->type);
id->kind = ID_FUNC;
}
// 중복 선언 검사
a = searchIdentifierAtCurrentLevel(id->name, id->prev);
if(a)
if(a->kind!=ID_FUNC || a->type->expr) syntax_error(12, id->name);
else{ // 프로토타입 검사 : 파라미터와 반환타입 검사
if(isNotSameFormalParameters(a->type->field, id->type->fiedl)) syntax_error(22, id->name);
if(isNotSameType(a->type->element_type, id->type->element_type)) syntax_error(26,a->name);
}
// 스코프 범위 변경 및 빈 필드 검사
a = id->type->field;
while(a){
if(strlen(a->name)) current_id = a;
else if(a->type) syntax_error(23);
a=a->link;
}
return(id);
}
- A_ID *setFunctionDeclaratorBody(A_ID *, A_NODE *);
- 함수 몸체에서 명칭에 대한 심볼테이블과 신택스 트리 연결하는 함수
- 파라미터로 주어진 심볼테이블 <id> 타입이 함수 명칭인데, 그에 연결된 타입 테이블에서 <expr> 필드에 함수의 몸체 를 나타내는 신택스 트리의 루트노드의 주소인 <node>를 연결
// 함수 몸체에 신택스 트리 연결
A_ID *setFunctionDeclaratorBody(A_ID *id, A_NODE *n){
id->type->expr = n;
return(id);
}
- A_SPECIFIER *makeSpecifier(A_TYPE *, S_KIND);
- 선언 지시자 생성하는 함수
- 명시자 테이블을 하나 생성하여 그 주소를 리턴
- 명시자 테이블은 두 개의 필드 즉, <stor>과 <type>으로 이루어져 있는데 이곳에 <t>와 <s>를 각각 저장
// 새로운 선언 지시자 생성하는 함수
A_SPECIFIER *makeSpecifier(A_TYPE *t, S_KIND s){
A_SPECIFIER *p;
p = malloc(sizeof(A_SPECIFIER));
p->type = t;
p->stor = s;
p->line = line_no;
return(p);
}
- void setDefaultSpecifier(A_SPECIFIER *);
- 반환타입이나 storage class가 지정되지 않은 경우 기본값으로 설정하는 함수
// default Specifier 설정하는 함수
void setDefaultSpecifier(A_SPECIFIER *p){
A_TYPE *t ;
if(p->type == NIL) p->type = int_type; // 반환 타입이 지정되지 않았다면, 정수형 타입으로 설정
if(p->stor == S_NULL) p->stor = S_AUTO; // storage class가 없다면, auto로 설정
}
- A_ID *setDeclaratorElementType(A_ID*, A_TYPE *);
- 선언문이나 element의 타입을 설정하는 함수
// 선언문이나 element의 타입을 설정하는 함수
A_ID *setDeclaratorElementType(A_ID *id, A_TYPE *t){
A_TYPE *tt;
if(id->type==NIL) id->type = t;
else{
tt = id->type;
while(tt->element_type) tt = tt->element_type;
tt->element_type = t;
}
}
- A_ID *searchIdentifierAtCurrentLevel(char *, A_ID *);
- 현재 레벨에서 같은 명칭을 갖고 있는 심볼테이블을 반환하는 함수
// current_level의 범위에서 전달받은 명칭과 같은 함수 명칭을 갖는 심볼테이블 반환하는 함수
A_ID *searchIdentifierAtCurrentLevel(char *s, A_ID *id){
while(id){
if(id->level < current_level) return (NIL);
if(strcmp(id->name, s) == 0) break;
id=id->prev;
}
return(id);
}
- BOOLEAN isNotSameFormalParameters(A_ID *, A_ID *);
- 전달 받은 두 심볼테이블(파라미터 정보를 담은)이 같은지 확인하는 함수
// 프로토타입의 파라미터 일치 여부 확인하는 함수
BOOLEAN isNotSameFormalParameters(A_ID *a, A_ID *b){
if(a == NIL) return (FALSE); // 프로토타입에 파라미터 없는 경우 false 반환
while(a){
if(b==NIL || isNotSameType(a->type, b->type)) return (TRUE); // 다른 함수인 경우 비교할 필요 없으므로 true 반환
a=a->link;
b=b->link;
}
if(b) return (TRUE);
else return (FALSE);
}
- BOOLEAN isNotSameType(A_TYPE *, A_TYPE*);
- 전달받은 두 타입이 같은지 확인하는 함수
// 프로토타입의 반환 타입 일치 여부 확인하는 함수
BOOLEAN isNotSameType(A_TYPE *t1, A_TYPE *t2){
if(isPointerOrArrayType(t1) || isPointerOrArrayType(t2)) return (isNotSameType(t1->element_type, t2->element_type));
else return(t1!=t2);
}
- BOOLEAN isPointerOrArrayType(A_TYPE *);
- 타입이 pointer인지 array인지 확인하는 함수
// 전달받은 타입이 POINTER인지 ARRAY인지 확인하는 함수
BOOLEAN isPointerOrArrayType(A_TYPE *t){
if(t && (t->kind == T_POINTER || t->kind == T_ARRAY)) return (TRUE);
else return (FALSE);
}
'컴파일러' 카테고리의 다른 글
신택스 분석기 - (6) 초기화 선언자 분석 (0) | 2024.11.08 |
---|---|
신택스 분석기 - (5) 일반 선언문 분석 (0) | 2024.11.08 |
신택스 분석기 - (3) 프로그램 분석 (0) | 2024.11.06 |
신택스 분석기 - (2) 스코프 규칙과 명명 사용 (1) | 2024.11.06 |
신택스 분석기 - (1) 역할 (0) | 2024.11.06 |