320 likes | 1.02k Views
구문과 의미론. 용어. 어휘항목 (lexeme) 프로그래밍 언어의 가장 낮은 수준의 구문 단위 식별자 (identifier), 리터럴 (literal), 연산자 (operator), 특수어 (special word) 등 토큰 (token) 어휘항목의 부류 예 ) C 문장 : index = 2 * count + 17 어휘항목 토큰 Index 식별자 = equal_sign 2 int_literal
E N D
용어 • 어휘항목(lexeme) • 프로그래밍 언어의 가장 낮은 수준의 구문 단위 • 식별자(identifier), 리터럴(literal), 연산자(operator), 특수어(special word) 등 • 토큰(token) • 어휘항목의 부류 예) C 문장: index = 2 * count + 17 어휘항목토큰 Index 식별자 = equal_sign 2 int_literal * mult_operator Count 식별자 + plus_operator 17 int_literal ; semicolon
BNF • Backus-Naur Form • 프로그래밍 언어의 구문을 기술하기 위한 메타언어 • 메타언어(metalanguage) • 다른 언어를 서술하기 위해 사용되는 언어 • ALGOL 58의 구문을 기술하기 위해 Backus 가 사용한 형식적 표기법을 • ALGOL 60의 구문을 기술하기 위해 Naur가 약간 수정하여 사용한 방법
BNF의 기본 원리 • 추상화를 사용한 구문 구조 기술 • 각 괄호: 문법 단위의 이름을 구분하기 위해 사용 예) C의 배정문 <assign> <var> = <expression> • LHS(left-hand side:좌변): 정의되고 있는 추상화 • RHS(right-hand side:우변): 정의—토큰, 어휘항목, 다른 추상화에 대한 참조 등으로 구성 • 규칙(rule)/생성(production)이라고도 함 • 추상화: nonterminal/nonterminal symbol 이라고도 함 • 토큰, 어휘항목: terminal/terminal symbol 이라고도 함
BNF의 기본 원리(계속) • 하나의 nonterminal이 두 개 이상의 다른 정의를 가질 때는 ‘|’로 연결 예) <if_stmt> if <logic_expr> then <stmt> | if <logic_expr> then <stmt> else <stmt>
BNF로 리스트 명세하기 • 리스트의 예 • 1, 2, … • BNF에는 생략기호가 없음 재귀(recursion)을 사용 <ident_list> identifier | identifier, <ident_list>
BNF:유도(derivation) • 유도란? • 문법으로부터 문장을 생성하는 것 • 시작기호(start symbol) • Nonterminal • 문법으로부터 문장을 유도할 때 처음 거치는 기호 • 보통 <program> 으로 이름 붙임
BNF: 유도 (계속) • 교 p 131, 예제 3.1 작은 언어를 위한 문법 • 배정문(들)을 생성 • 유도과정: nonterminal을 포함하지 않을 때까지 계속 <program> => begin <stmt_list> end => begin <stmt> ;<stmt_list> end => begin <var> := <expression> ;<stmt_list> end . . . . . . => begin A := B + C; B := <var> end => begin A := B + C; B := C end • 용어 • => : 유도한다(drive) • 좌단유도(leftmost derivation):가장 왼쪽에 있는 nonterminal 부터 대체 • 문장형태(sentential form): 유도과정에서 생성되는 스트링 • 생성된 문장(generated sentence): terminal, 즉 어휘항목만 포함하는 문장형태 시작기호
BNF: 유도 (계속) • 교 p 132 단순 배정문을 위한 문법 참조 • 질문 • 시작기호는? • 문장형태는? • 생성된 문장은?
파스 트리 • 파스 트리(parse tree)란? • 문법이 정의한 언어의 문장에 대한 계층적 구문 구조 • 예) 교 p 133 그림 3.1 • 단순문 A := B*(A+C)의 파스 트리 • 내부 노드 nonterminal 기호의 레이블 가짐 • 잎 노드 terminal 기호의 레이블 가짐
모호한 문법 • 둘 이상의 파스 트리를 갖는 문장을 생성하는 문법 • 교 p 134 의 문법은 그림 3.2처럼 두 가지 파스 트리 생성 모호 • <assign> | <id> := <expr> | | A <expr> */+ <expr>
모호한 문법(계속) • 원인 [원문법] [모호한 문법] <assign> -> <id> := <expr> <assign> -> <id> := <expr> <id> -> A|B|C <id> -> A|B|C <expr> -> <id> + <expr> <expr> -> <expr> + <expr> | <id> * <expr> | <expr> * <expr> | (<expr>) | (<expr>) | <id> | <id> * 오른쪽으로만 성장 허용 * 양쪽으로 성장 허용
연산자 우선 순위 • 교 p 132 예제 3.2의 문법을 이용해 식 A := B*A+C의 유도과정을 표시해보자 • 파스 트리: 연산자 우선 순위 위반 <assign> | <id> := <expr> | | A <id> * <expr> | | B <id> + <expr> | | A <id> | C
연산자 우선순위 (계속) • 모호성의 해결 • 다른 우선순위를 갖는 연산자의 피연산자에 대해 별도를 추상화를 사용 <assign> -> <id> := <expr> (참고) <assign> -> <id> := <expr> <id> -> A|B|C <id> -> A|B|C <expr> -> <expr> + <term> <expr> -> <expr> + <expr> | <term> | <expr> * <expr> <term> -> <term> * <factor> | (<expr>) | <factor> | <id> <factor> -> ( <expr> ) | <id> • 교 p 136 아래부분 및 p 137 그림 3.3 참조
<assign> -> <id> := <expr> <id> -> A|B|C <expr> -> <expr> + <term> | <term> <term> -> <term> * <factor> | <factor> <factor> -> ( <expr> ) | <id> 원식에서 더 왼쪽에 나오는 것이 파스 트리의 왼쪽에서 나오므로 연산순서가 맞음 옆의 문법에 의하여 A:=B+C+A에 대한 파스트리를 그려보라. <assign> | <id> := <expr> | | A <expr> + <term> | | <expr> + <term> <factor> | | | <term> <factor> <id> | | | <factor> <id> A | | <id> C | B 연산자 결합 법칙
우순환적(right recursive) 규칙 우결합법칙을 나타낼 수 있음 예) 지수의 표현 <factor>-><exp>**<factor> | <exp> <exp> -> (<exp>) | <id> A**B의 파스트리 <factor> | <exp> ** <factor> | | <id> <exp> | | A <id> | B 연산자 결합법칙
If-then-else를 위한 모호하지 않은 문법 다음 문법을 생각해 보자. <if_stmt> if <logic_expr> then <stmt> | if <logic_expr> then <stmt> else <stmt> <stmt> <if_stmt> •모호한 예: If <logic_expr> then if <logic_expr> then <stmt> else <stmt> •교 p 140 그림 3.5 참조 모호하지 않은 문법: p 140 아래~p 141 윗부분
확장 BNF(EBNF) • 선택부분: [ ]로 표현 예) <selection>if (<exp>)<stmt>[else<stmt>]; • 생략 또는 무한 반복: { }로 표현 예) <ident_list><identifier> {, <identifier>} • 다중선택: ( | )로 표현 예) Pascal for 문장 <for_stmt>for <var>:=<expr> (to | downto) <expr> do <stmt> 예) 교 p 142 예제 3.5
구문 그래프(syntax graph) • BNF/EBNF를 유향 그래프로 표현한 것 • 판독성 향상 • 예) 교 p 143 그림 3.6
재귀 하강 파싱(recursive descent parsing) • 하향식 파싱 • 문법의 각 nonterminal에 대해서 부프로그램이 존재하는 방식 예) 다음 산술식의 문법에 대한 파서를 만들어보자. • <expr> <term> { (+|-) <term>} • <term> <factor> { (*|/) <factor>} • <factor> <id>|(<expr>)
재귀 하강 파싱(계속) • <expr> <term> { (+|-) <term>} • 어휘분석기 • 입력문자들을 어휘항목으로 구성 • 어휘항목에 연관된 토큰을 반환 예) A + B 어휘항목 토큰 A id_code(identifier) + plus_code B id_code(identifier) void expr() { term(); while (next_token == plus_code || next_token == minus_code){ lexical(); /* 어휘분석기: 입력으로부터 다음 토큰을 가져옴 */ term(); } }
재귀 하강 파싱(계속) • <factor> <id>|(<expr>) void factor() { if (next_token == id_code) { lexical(); return; } else if (next_token == left_paren_code) { lexical(); expr(); if (next_token == right_paren_code) { lexical(); return; } else error(); /*오른쪽 괄호 기대 */ } else error(); /* id가 없거나 왼쪽괄호가 없다*/ }
재귀 하강 파서의 문제점 • 좌순환 문법은 취급 불능 • 예) <A> <A> + <B> • 자기 자신을 호출하는 과정이 계속 진행됨
정적 의미론(static semantics) • BNF로 기술하기 어려운 언어 규칙을 기술하는 기법 • 술어함수(predicate function)의 형태로 문법규칙에 연관시켜 의미를 부여
속성 문법(attribute grammer) • 문법기호, 의미함수, 술어함수로 기술 • 의미함수 • 각 문법기호에 술어를 사용하여 의미 기술 • 술어함수 • 어떤 Nonterminal에 연관된 술어 값이 참이어야 하는지 기술
속성문법의 정의 • 각 문법기호 X에 속성들의 집합 A(X)를 연관시킴 • 종류 • 합성속성: 파스 트리의 윗 방향으로 의미 정보를 전달하는 데 사용 • 상속속성: 파스 트리의 아래 방향으로 의미 정보를 전달하는 데 사용
속성문법의 정의(계속) • 의미 값의 계산 • 규칙 X0 X1…Xn에 대해서 • 합성속성의 의미 값 결정 • S(X0) = f(A(X1),…,A(Xn)) • 즉, 자식 노드들의 속성값에 의존 • 상속속성의 의미 값 결정 • I(Xj) = f(A(X0),…,A(Xn)), 1j n • 즉, 부모 및 형제 노드들의 속성값에 의존 • 술어함수 • 속성집합 {A(X0),…,A(Xn)}에 대한 Boolean 식으로 표시
속성 문법의 예 1 • Ada 프로시저의 end에 있는 이름이 해당 프로시저의 이름과 일치해야 한다 • 속성문법 구문규칙: <proc_def> procedure <proc_name>[1] <proc_body> end <proc_name>[2]; 의미론규칙: <proc_name>[1].string = <proc_name>[2].string ※[1],[2] • nonterminal이 두 번 이상 나타날 경우 각각을 구분 • 언어의 일부는 아님 속성
속성 문법의 예2 상속속성:부모,형제의 속성값에 의존 합성속성:자식의 속성값에 의존 • 교 p 151 [예제] 단순 배정문에 대한 속성 문법 1. 구문규칙: <assign><var>:=<expr> 의미론규칙: <expr>.expected_type <var>.actual_type 2.구문규칙:<expr> <var>[2]+<var>[3] 의미론규칙:<expr>.actual_type If (<var>[2].actual_type = int) and . . . . . . 술어함수:<expr>.actual_type=<expr>.expected_type . . . . . . • P 153 그림 3.8, 3.9 참조
연산 의미론(operational semantics) • 명령어의 의미 = 이 명령어의 실행으로 발생한 컴퓨터 상태의 변화 • 컴퓨터의 상태 • 레지스터와 기억장소에 저장된 값 • 명령어의 실행에 의한 컴퓨터의 상태변화를 모의실험에 의해 파악