일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 프로그래머스
- 사용자정의예외
- EC2
- 파이썬 #python #예외처리 #exception
- 파이썬 #python #docstring
- 민감 정보 관리
- 파이썬 #python #가변매개변수 #키워드가변매개변수 #args #kwargs
- 파이썬 #python #전역변수 #지역변수 #eval
- aw3
- 파이썬 #python #file #i/o #input #output
- PostgreSQL
- 약수 수하기
- 파이썬 #python #lambda #람다
- aws
- 파이썬기본문법 #파이썬 #python
- Git
- 파이썬 #python #os #os.path #glob
- 파이썬 #python #Comprehension
- spring boot
- jsonb
- 파이썬 #python #enumerate
- redis
- 파이썬 #python #모듈 #module #import #random #time #calendar #sys
- 파이썬 #python #함수 #function
- 파이썬 #python #filter #map #reduce
- docker
- 파이썬 #python #class #클래스 #상속
- 연산자메서드
- 배포
- 파이썬 #python #지역함수
- Today
- Total
Yeonnnnny
신택스 분석기 - (9) 수식 분석 본문
1. 기본 수식 (Primary_expression) 분석
primary_expression
: IDENTIFIER {$$=makeNode(N_EXP_IDENT, 0, getIdentifierDeclared($1),0);}
| INTEGER_CONSTANT {$$=makeNode(N_EXP_INT_CONST, 0, $1, 0);}
| FLOAT_CONSTANT {$$=makeNode(N_EXP_FLOAT_CONST, 0, $1, 0);}
| CHARACTER_CONSTANT {$$=makeNode(N_EXP_CHAR_CONST, 0, $1, 0);}
| STRING_LITERAL {$$=makeNode(N_EXP_STRING_LITERAL, 0, $1, 0);}
| LP expression RP {$$=$2;}
;
기본 수식은 간단한 명칭이나 상수 혹은 일반 수식에 소괄호를 묶은 형식으로 가장 먼서 계산되는 피연산자를 말함. 기본 수식을 분석한 후 <primary_expression>은 다음과 같이 새롭게 생성되는 신택스 트리를 가리킴.
- 명칭인 경우, 수식에서 사용할 수 있는 명칭이어야 하므로, 그 종류가 올바른 명칭인지 검사하고, N_EXP_IDNET 이름의 노드를 한 개 가지는 새로운 신택스 트리를 만듦. 노드의 자식은 명칭을 위한 심볼 테이블을 가리키도록 함.
- 정수형 상수인 경우, N_EXP_INT_CONST 이름의 노드를 한 개 가지는 새로운 신택스 트리를 만듦, 노드의 자식은 정수 값을 가지도록 함.
- 실수형 상수인 경우에, N_EXP_FLOAT_CONST 이름의 노드를 한 개 가지는 새로운 신택스 트리를 만듦. 노드의 자식은 실수 스트링을 가리키도록 함.
- 문자형 상수인 경우, N_EXP_CHAR_CONST 이름의 노드를 한 개 가지는 새로운 신택스 트리를 만듦, 노드의 자식은 문자값을 가지도록 함.
- 스트링 리터럴인 경우, N_EXP_STRING_LITERAL 이름의 노드를 한 개 가지는 새로운 신택스 트리를 만듦. 노드의 자식은 스트링을 가리키도록 함.
소괄호로 묶인 수식의 형식인 경우에 <expression> 수식을 분석하여 만든 신택스 트리의 루트 노드를 그대로 가리킴.
2. 후위 수식(Postfix_expression) 분석
postfix_expression
: primary_expression {$$=$1;}
| postfix_expression LB expression RB {$$=makeNode(N_EXP_ARRAY, $1, 0, $3);}
| postfix_expression LP arg_expression_list_opt RP {$$=makeNode(N_EXP_FUNCTION_CALL, $1, 0, $3);}
| postfix_expression PERIOD IDENTIFIER {$$=makeNode(N_EXP_STRUCT, $1, 0, $3);}
| postfix_expression ARROW IDENTIFIER {$$=makeNode(N_EXP_ARROW, $1, 0, $3);}
| postfix_expression PLUSPLUS {$$=makeNode(N_EXP_POST_INC, 0, $1, 0);}
| postfix_expression MINUSMINUS {$$=makeNode(N_EXP_POST_DEC, 0, $1, 0);}
;
arg_expression_list_opt
: /* empty */ {$$=makeNode(N_ARG_LIST_NIL, 0, 0, 0);}
| arg_expression_list {$$=$1;}
;
arg_expression_list
: assignment_expression {$$=makeNode(N_ARG_LIST, $1, 0, makeNode(N_ARG_LIST_NIL, 0, 0, 0);)}
| arg_expression_list COMMA assignment_expression {$$=makeNodeList(N_ARG_LIST,$1,$3);}
;
후위 수식을 분석한 후 <postfix_expression>은 다음과 같이 새롭게 생성되는 신택스 트리를 가리킴.
- 후위 수식 뒤에 대괄호와 수식, 즉 배열을 참조하는 형식인 경우, N_EXP_ARRAY 이름의 새로운 노드 아래 <postfix_expression>과 <expression>을 자식으로 연결한 신택스 트리를 만듦.
- 후위 수식 뒤에 소괄호, 즉 함수를 호출하는 형식인 경우, N_EXP_FUNCTION_CALL 이름의 새로운 노드 아래 <postfix_expression>과 <arg_expression_list_opt>를 자식으로 연결한 신택스 트리를 만듦. <arg_expression_list_opt>는 함수를 호출할 때 사용되는 실 매개 변수 목록을 나타내는 신택스 트리를 가리킴.
- 후위 수식 뒤에 마침표, 즉 구조체의 필드를 참조하는 형식인 경우, N_EXP_STRUCT 이름의 새로운 노드 아래 <postfix_expression>과 필드 명칭 스트링을 자식으로 연결한 신택스 트리를 만듦.
- 후위 수식 뒤에 화살표, 즉 포인터를 이용하여 간점 참조하는 형식인 경우에는 N_EXP_ARROW 이름의 새로운 노드 아래 <postfix_expression>과 필드명칭 스트링을 자식으로 연결한 신택스 트리를 만듦.
- 후위 수식 뒤에 후위 증감 연산자가 있는 경우에는, N_EXP_POST_INC나 N_EXP_POST_DEC 이름의 새로운 노드 아래 <postfix_expression>을 자식으로 연결한 신택스 트리를 만듦.
후위 수식이 기본 수식(primary_expression)과 같은 형식인 경우에, <postfix_expression>은 <primary_expression>이 가리키는 신택스 트리를 그대로 가리키도록 함.
함수 호출 형식의 후위 수식에는 매개변수 수식 목록이 나올 수 있는데, <arg_expression_list_opt>는 매개변수 수식 목록을 위한 신택스 트리를 가리키도록 함. 매개변수 수식 목록을 위한 신택스 트리는 다음과 같이 구성함.
- 매개변수 수식이 없는 경우, N_ARG_LIST_NIL 이름의 노드 하나로 구성
- 매개변수 수식이 하나 이상 여러 개인 경우, N_ARG_LIST 이름의 노드를 루트로 하여, 좌측 자식이 수식을 위한 신택스 트리를 가리키고, 우측 자식은 다음의 매개변수 수식 목록을 위한 신택스 트리를 재귀적으로 가리키도록 함.
- 매개변수 수식을 위한 신택스 트리는 가장 우측의 단말노드가 항상 N_ARG_LIST_NIL이 되도록 함.
후위수식 사용 예시)
... kim[i+3]...
... lee[10].a->b++ ...
... fun(c, d+10) ...
3. 단항 수식(Unary_expression)과 타입 변환 수식(Cast_expression) 분석
// 단항 수식
unary_expression
: postfix_expression {$$=$1;}
| PLUSPLUS unary_expression {$$=makeNode(N_EXP_PRE_INC, 0, $2, 0);}
| MINUSMINUS unary_expression {$$=makeNode(N_EXP_PRE_DEC, 0, $2, 0);}
| AMP cast_expression {$$=makeNode(N_EXP_AMP, 0, $2, 0);}
| STAR cast_expression {$$=makeNode(N_EXP_STAR, 0, $2, 0);}
| EXCL cast_expression {$$=makeNode(N_EXP_NOT, 0, $2, 0);}
| MINUS cast_expression {$$=makeNode(N_EXP_MINUS, 0, $2, 0);}
| PLUS cast_expression {$$=makeNode(N_EXP_PLUS, 0, $2, 0);}
| SIZEOF_SYM unary_expression {$$=makeNode(N_EXP_SIZE_EXP, $2, 0, 0);}
| SIZEOF_SYM LP type_name RP {$$=makeNode(N_EXP_SIZE_TYPE, $3, 0, 0);}
;
// 타입 변환 수식
cast_expression
: unary_expression {$$=$1;}
| LP type_name RP cast_expression {$$=makeNode(N_EXP_CAST, $2, $4, 0);}
;
type_name
: declaration_specifiers abstract_declarator_opt {$$=setTypeNameSpecifier($2,$1);}
;
단항 수식이 후위 수식과 같은 형식인 경우, <unary_expression>은 <postfix_expression>이 가리키는 신택스 트리를 그대로 가리키도록 함. 타입 변환 수식이 단항 수식과 같은 형식인 경우, <cast_expression>은 <unary_expression>이 가리키는 신택스 트리를 그대로 가리키도록 함. 단항 연산자를 포함하는 수식을 분석한 후 <unary_expression>이나 <casting_expression>은 다음과 같이 새롭게 생성되는 신택스 트리를 가리킴.
- 단항 수식 앞에 전위 증감 연산자가 있는 경우, N_EXP_PRE_INC나 N_EXP_PRE_DEC 이름의 새로운 노드 아래 <unary_expression>을 자식으로 연결한 신택스 트리를 만듦.
- 타입 변환 수식 앞에 주소 계산(&), 간접 참조(*), 논리역(!), 마이너스(-), 플러스(+) 같은 연산자가 있는 경우, N_EXP_AMP, N_EXP_STAR, N_EXP_NOT, N_EXP_MINUS나 N_EXP_PLUS 이름의 새로운 노드 아래 <cast_expression>을 자식으로 연결한 신택스 트리를 만듦.
- 단항 수식 앞에 수식의 크기를 계산하는 sizeof 연산자가 있는 경우, N_EXP_SIZEOF_EXP 이름의 새로운 노드 아래 <unary_expression>을 자식으로 연결한 신택스 트리를 만듦.
- 타입의 크기를 계산하는 sizeof 연산자 다음에 소괄호와 타입이 나오는 수식인 경우,<type_name>은 해당 타입 테이블 주소를 가리키고 있으므로, N_EXP_SIZEOF_TYPE이름의 새로운 노드 아래 <type_name>을 자식으로 연결한 신택스 트리를 만듦.
- 타입 변환 연산을 위한 수식의 경우, N_EXP_CAST 이름의 새로운 노드 아래 <cast_expression>이 가리키는 신택스 트리를 자식으로 연결한 신택스 트리를 만듦.
- <type_name>은 타입 명시자(즉, 단순 타입 명칭, 구조체나 나열형 타입 명시자)로만 되어있는 경우와, 복잡하게는 타입 명시자 뒤에 추상 선언자(즉, 포인터나 배열구조를 복합적으로 나타내는 타입 선언 형식)가 있는 경우가 있는데, 그 타입을 분석하여 타입 테이블을 만들고, <type_name>은 그 주소를 가리키도록 함.
- A_TYPE *setTypeNameSpecifier(A_TYPE *, A_SPECIFIER *);
- 두 번쨰 매개 변수로 받은 타입 명시자가 기억 장소 명시자를 포함하고 있는지 검사
- 있는 경우 에러 처리
- 생략된 타입 명시자를 확인하여 설정 (없는 경우, int형으로 설정)
- 첫 번째 매개 변수로 받은 타입의 엘리먼트 타입으로 타입 명시자의 타입 정보 저장
A_TYPE *setTypeNameSpecifier(A_TYPE *t, A_SPECIFIER *p){
// 타입 명시자에 기억 장소 명시자(storage class)가 있는지 검사
if(p->stor) syntax_error(20);
setDefaultSpecifier(p);
t = setTypeElementType(t, p->type);
return(t);
}
4. 이항 연산 수식(산술 수식, 관계 수식, 논리 수식)
// 산술 수식
multiplicative_expression
: cast_expression {$$=$1;}
| multiplicative_expression STAR cast_expression {$$=makeNode(N_EXP_MUL, $1, 0, $3);}
| multiplicative_expression SLASH cast_expression {$$=makeNode(N_EXP_DIV, $1, 0, $3);}
| multiplicative_expression PERCENT cast_expression {$$=makeNode(N_EXP_MOD, $1, 0, $3);}
;
additive_expression
: multiplicative_expression {$$=$1;}
| additive_expression PLUS multiplicative_expression {$$=makeNode(N_EXP_ADD, $1, 0, $3);}
| additive_expression MINUS multiplicative_expression {$$=makeNode(N_EXP_SUB, $1, 0, $3);}
;
// 관계 수식
relational_expression
: additive_expression {$$=$1;}
| relational_expression LSS additive_expression {$$=makeNode(N_EXP_LSS, $1, 0, $3);}
| relational_expression GTR additive_expression {$$=makeNode(N_EXP_GTR, $1, 0, $3);}
| relational_expression LEQ additive_expression {$$=makeNode(N_EXP_LEQ, $1, 0, $3);}
| relational_expression GEQ additive_expression {$$=makeNode(N_EXP_GEQ, $1, 0, $3);}
;
// 논리 수식
equality_expression
: relational_expression {$$=$1;}
| equality_expression EQL relational_expression {$$=makeNode(N_EXP_EQL, $1, 0, $3);}
| equality_expression NEQ relational_expression {$$=makeNode(N_EXP_NEQ, $1, 0, $3);}
;
logical_and_expression
: equality_expression {$$=$1;}
| logical_and_expression AMPAMP equality_expression {$$=makeNode(N_EXP_AND, $1, 0, $3);}
;
logical_or_expression
: logical_and_expression {$$=$1;}
| logical_or_expression BARBAR logical_and_expression {$$=makeNode(N_EXP_OR, $1, 0, $3);}
;
이항 연산자를 포함하는 수식을 분석하면 <logical_expression> 등은 다음과 같이 새롭게 생성되는 신택스 트리를 가리킴
- 이항 연산자 (*, /, %, +, -, <, >, <=, >=, !=, ==, &&, ||) 를 포함하는 수식이 나오는 경우, 연산자 우선순위에 맞게 새로운 노드를 만들어, 좌측 자식으로 연산자 앞의 수식을 위한 신택스 트리를 연결하고 , 우측 자식으로 연산자 뒤의 수식을 위한 신택스 트리를 연결함.
5. 상수 수식과 일반 수식
// 상수 수식
constant_expression_opt
: /*empty*/ {$$=NIL;}
| constant_expression {$$=$1;}
;
constant_expression
: expression {$$=$1;}
;
// 일반 수식
expression
: assignment_expression {$$=$1;}
;
assignment_expression
: logical_or_expression {$$=$1;}
| unary_expression ASSIGN assignment_expression {$$=makeNode(N_EXP_ASSIGN, $1, NIL, $3);}
;
상수 수식은 일반 수식과 그 문법적 형식은 같아서 신택스 트리의 구성 형태는 같지만 컴파일 단계에서 즉시 계산할 수 있는 수식을 의미함. 치환 연산자를 포함하는 수식을 분석하면 <expression>은 다음과 같이 새롭게 생성되는 신택스 트리를 가리킴.
- 치환 연산자(=)가 나오는 경우, N_EXP_ASSIGN 을 만들어, 좌측 자식으로 연산자 앞의 수식을 위한 신택스 트리를 연결하고, 우측 자식으로 연산자 뒤의 수식을 위한 신택스 트리를 연결.
'컴파일러' 카테고리의 다른 글
신택스 분석기 - (11) 신택스 에러 메시지 (0) | 2024.11.10 |
---|---|
신택스 분석기 - (10) 명령문 분석 (0) | 2024.11.10 |
신택스 분석기 - (8) 선언자 분석 (0) | 2024.11.09 |
신택스 분석기 - (7) 타입 명시자 분석 (1) | 2024.11.08 |
신택스 분석기 - (6) 초기화 선언자 분석 (0) | 2024.11.08 |