구문 분석
최 광 훈
전남대학교
1
목차
2
구문 분석
3
공통 주제 | - 오토마톤(결정적, 비결정적), 문법, 언어 - 촘스키 계층 |
어휘 분석 주제 | - 가장 작은 구문 요소 분석 - 유한 오토마타 - 정규식 ( == 오토마톤 == 문법 == 언어) - 어휘 분석기 구조 |
구문 분석 주제 | - 구문 구조 분석 - LR 오토마톤 (LR 파싱) - Generalized LR (GLR, 모호한 문법 처리) - 구문 에러 처리 - LR 구문 분석기 구조 |
While 프로그래밍언어
4
구문 분석: 어휘 분석
data Token =
TkEndOfTokens
| TkCInt Int -- 1, 2, 3
| TkCBool Bool -- true, false
| TkIdentifier String -- x, y, abc123, _z
| TkTyInt -- int
| TkTyBool -- bool
5
구문 분석: 어휘 분석
data Token =
…
| TkAdd -- +
| TkSub -- -
| TkMul -- *
| TkDiv -- /
| TkMod -- %
6
| TkLessThan -- <
| TkGreaterThan -- >
| TkLessThanEqualTo -- <=
| TkGreaterThanEqualTo -- >=
| TkEqualTo -- ==
| TkNotEqualTo -- !=
| TkAnd -- &&
| TkOr -- ||
| TkNot -- !
구문 분석: 어휘 분석
data Token =
…
| TkSkip -- skip (keyword)
| TkSemicolon -- ;
| TkAssign -- =
| TkRead -- read
| TkWrite -- write
7
| TkIf -- if
| TkThen -- then
| TkElse -- else
| TkWhile -- while
| TkOpenBrace -- {
| TkCloseBrace -- }
| TkOpenParen -- (
| TkCloseParen -- )
8
int at (6, 1): TkTyInt
t at (6, 5): TkIdentifier
; at (6, 6): TkSemicolon
int at (7, 1): TkTyInt
p at (7, 5): TkIdentifier
; at (7, 6): TkSemicolon
int at (8, 1): TkTyInt
q at (8, 5): TkIdentifier
; at (8, 6): TkSemicolon
read at (10, 1): read
( at (10, 5): TkOpenParen
p at (10, 6): TkIdentifier
) at (10, 7): TkCloseParen
; at (10, 8): TkSemicolon
read at (11, 1): TkRead
( at (11, 5): TkOpenParen
q at (11, 6): TkIdentifier
) at (11, 7): TkCloseParen
; at (11, 8): TkSemicolon
if at (13, 1): TkIf
( at (13, 4): TkOpenParen
q at (13, 5): TkIdentifier
<= at (13, 7): TkLessThan
p at (13, 10): TkIdentifier
) at (13, 11): TkCloseParen
then at (14, 1): TkThen
skip at (15, 3): TkSkip
else at (16, 1): TkElse
{ at (17, 3): TkOpenBrace
t at (18, 5): TkIdentifier
= at (18, 7): TkAssign
p at (18, 9): TkIdentifier
; at (18, 10): TkSemicolon
p at (19, 5): TkIdentifier
= at (19, 7): TkAssign
q at (19, 9): TkIdentifier
; at (19, 10): TkSemicolon
q at (20, 5): TkIdentifier
= at (20, 7): TkAssign
t at (20, 9): TkIdentifier
; at (20, 10): TkSemicolon
} at (21, 3): TkCloseBrace
; at (21, 4): TkSemicolon
while at (23, 1): while
( at (23, 7): TkOpenParen
p at (23, 8): TkIdentifier
% at (23, 10): TkMod
q at (23, 12): TkIdentifier
!= at (23, 14): TkNotEqualTo
0 at (23, 17): TkCInt
) at (23, 18): TkCloseParen
{ at (24, 3): TkOpenBrace
t at (25, 5): TkIdentifier
= at (25, 7): TkAssign
p at (25, 9): TkIdentifier
% at (25, 11): TkMod
q at (25, 13): TkIdentifier
; at (25, 14): TkSemicolon
p at (27, 5): TkIdentifier
= at (27, 7): TkAssign
q at (27, 9): TkIdentifier
; at (27, 10): TkSemicolon
q at (28, 5): TkIdentifier
= at (28, 7): TkAssign
t at (28, 9): TkIdentifier
; at (28, 10): TkSemicolon
} at (29, 3): TkCloseBrace
; at (29, 4): TkSemicolon
write at (31, 1): TkWrite
( at (31, 7): TkOpenParen
q at (31, 8): TkIdentifier
) at (31, 9): TkCloseParen
어휘 분석 결과 예시:
각 토큰에 대하여:
구문 분석: 어휘 분석
Q. 여러분이 사용하는 프로그래밍언어를 하나 선택하고 (C, C++, Java, Python, JavaScript 등) 어휘 분석 결과를 표현할 수 있는 자료 구조를 작성하시오.
9
구문 분석
10
data Prog = Prog { progDecls :: Decls, progComms :: Comms }
type Decl = (Type, VarName) -- 타입과 변수명의 쌍
type Decls = [ Decl ] -- Decl 원소들의 리스트
type Comms = [ Comm ] -- Comm 원소들의 리스트
data Type = TyInt | TyBool -- 두 가지 종류의 타입 int, bool
구문 분석
11
data Comm =
CSkip
| CSeq Comm Comm
| CAssign VarName Expr
| CRead VarName
| CWrite Expr
| CIf Expr Comm Comm
| CWhile Expr Comm
data Expr =
ECst Const
| EVar VarName
| EBinOp Op Expr Expr
| EUnaryOp Op Expr
data Const =
CInt Int
| CBool Bool
data Op =
OpAdd
| OpSub
| OpMul
| OpDiv
| OpMod
| OpLessThan
| OpEqual
| OpAnd
| OpOr
| OpNot
12
Prog {
progDecls = [ (TyInt,"t"), (TyInt,"p"), (TyInt,"q") ],
progComms = [
CRead "p",
CRead "q",
CIf (EBinOp OpOr
(EBinOp OpLessThan (EVar "q") (EVar "p"))
(EBinOp OpEqual (EVar "q") (EVar "p")))
CSkip
(CSeq (CAssign "t" (EVar "p"))
(CSeq (CAssign "p" (EVar "q"))
(CAssign "q" (EVar "t")))),
CWhile (EUnaryOp OpNot ,
(EBinOp OpEqual (EBinOp OpMod (EVar "p") (EVar "q")) (ECst 0)))
(CSeq (CAssign "t" (EBinOp OpMod (EVar "p") (EVar "q")))
(CSeq (CAssign "p" (EVar "q"))
(CAssign "q" (EVar "t")))),
CWrite (EVar "q")
]
}
구문 분석 결과 예시:
구문 분석
Q. 앞의 구문 분석 결과 예시를 보고 분석 대상이 되었던 소스 프로그램의 텍스트를 복원해보시오.
Q. 어휘/토큰 리스트에는 나타난 어휘들 중 구문 트리에서는 사라진 어휘들은 무엇인가? 그 이유는 무엇인가?
Q. 여러분이 사용하는 프로그래밍언어를 하나 선택하고 (C, C++, Java, Python, JavaScript 등) 구문 분석 결과를 표현할 수 있는 자료 구조를 작성하시오.
13
실습
6 <= (입력) 6번째 피보나치 수
8 => (출력) 1 1 2 3 5 8의 8을 출력
14
하스켈 stack 프로그램 설치 : https://docs.haskellstack.org/en/stable/install_and_upgrade/
구문 분석기
Q. 여러분이 사용하는 프로그래밍언어를 지원하는 어휘 분석기 생성 도구와 구문 분석기 생성 도구를 조사하시오. (lex, yacc, javacc 등등)
15
목차
16
구문 분석
17
구문 분석
(참고)
18
개요
[한글의 어휘 분석]
19
개요
[한글 구문 분석]
20
국민대 자연어 연구실 : http://nlp.kookmin.ac.kr/cgi-bin/parse.cgi
어휘 분석과 구문 분석
21
어휘 분석(lexical analysis)
“position = initial + rate * 60”
==>
<id,“position”>, <=>, <id,“initial”>, <+>, <id,“rate”>, <*>, <number, “60”>
<id, “position”> : 토큰(의 종류, 태그)
id : 토큰 (대표) 이름
“position” : 토큰 텍스트 내용(lexeme)
Q. 특정 토큰들에는 왜 그 내용이 없나? 예) <=>, <+>, <*>
Q. 심볼 테이블 항목 숫자를 토큰 내용으로 두기도 한다. 두 형식을 비교하시오.
22
구문 분석: 어휘 분석
23
| 명세 작성 방법 | 명세 구현 방법 |
어휘 분석기 | 정규식 | 유한 오토마타 |
구문 분석기 | 문맥자유문법(Context-free grammar) | 푸시다운 오토마타(Push-down automata) |
어휘 분석 명세
24
digit -> [0-9]
digits -> digit+
number -> digits ( . digits)? (E [+-]? digits)?
letter -> [A-Za-z]
id -> letter ( letter | digit )*
if -> if
then -> then
else -> else
relop -> < | > | <= | >= | = | <>
ws -> ( blank | tab | newline )+
어휘 분석 명세
25
Lexemes | Token name | 속성 값 |
ws 매칭 | - | |
if | if | |
then | then | |
else | else | |
id 매칭 | id | id 매칭 문자열 |
number 매칭 | number | number 매칭 문자열 |
< | relop | LT |
<= | relop | LE |
= | relop | EQ |
<> | relop | NE |
> | relop | GT |
>= | relop | GE |
어휘 분석 명세
26
abstract class Token {
private int line, col;
// getter, setter
}
class TkIdentifier extends Token {
private String text;
public Identifier (String text) { this.text = text; }
public String getText() { return text; }
}
class TkIf extends Token { }
class TkThen extends Token { }
class TkElse extends Token { }
기본 정규식
(참고: r,s는 정규식, L(r)은 정규식 r이 표현하는 언어)
Q. 다음 정규식이 나타내는 집합은?
27
정규식 정의
(참고: di는 심볼, ri는 정규식, ri에 기본 알파벳(∑)과 함께 di가 나타남)
예) C언어 식별자로 이루어진 언어를 표현하는 정규식 정의
28
정규식 정의
Q) 부호없는 숫자 (정수 또는 실수)는 5280, 0.01234, 6.336E4, 1.89E-4와 같은 형식의 문자열이다. 정규식 정의를 완성하시오.
(힌트: optionalFraction의 예시: 0.01234의 .01234 또는 5280의 epsilon)
(힌트: optionalExponent의 예시: 6.336E4의 E4 또는 그 변형 E+4, E-4, epsilon)
29
확장 정규식
Q. C언어 식별자로 구성된 언어를 표현하는 정규식 정의를 확장 정규식 표기법으로 간략하게 작성하시오.
30
확장 정규식
Q) 부호없는 숫자 (정수 또는 실수)를 표현하는 정규식 정의를 확장 정규식 표기법으로 간략하게 작성하시오.
31
확장 정규식: Lex 프로그램
32
정규식 온라인 테스트 https://regexr.com/
어휘 분석 명세 예시
33
배경: 언어, 문법, 오토마타
- 유효한 문자열의 집합
예) L1 = { a, ab, abb, abbb, … } 예) abbbb : 유효, bbb 유효하지 않음
L2 = { }
L3 = { empty_string }
- 유효한지 여부는 누가 결정? 언어를 만드는 사람의 필요에 의해 결정
34
cf. 아무것도 없는 심볼
- λ (lambda)
- ε (epsilon)
- empty_string => “”
배경: 언어, 문법, 오토마타
1) 문법(grammar) :
* 터미널(terminal) 심볼, 넌터미널(non-terminal) 심볼, 생산 (production)
* 언어에 포함된 모든 유효한 문자열만 유도(derivation, =>)
예) G(L1): S -> a
S -> S b
S => S b => S b b => S b b b => a b b b
35
터미널: a, b
넌터미널: S
시작 (넌터미널) 심볼: S
유도 과정 : … => …
G(L1) : L1 언어를 생성하는 문법
배경: 언어, 문법, 오토마타
2) 오토마톤(automaton) :
* 상태, 상태 전이 규칙,
* 언어에 포함된 모든 유효한 문자열만 인식
36
상태: q0, q1
상태 전이 규칙:
q0 -a->a1 (또는, delta ( q0, a, q1 ) )
q1 -b-> q1 (또는, delta ( q1, b, q1) )
시작 상태: q0
종료 상태: q1
a
b
배경: 언어, 문법, 오토마타
1) 정규 문법 (regular grammar) => 정규 언어
2) 문맥 자유 문법 (contrext-free grammar) => 문맥 자유 언어
3) 문맥 의존 문법 (context-sensitive grammar) => 문맥 의존 언어
4) 무제약 문법 (unrestricted grammar) => 재귀적 열거 가능 언어(recursively enurable set)
37
https://ko.wikipedia.org/wiki/촘스키_위계
배경: 언어, 문법, 오토마타
1) 유한 상태 오토마타(finite state automata) => 정규 언어
2) 비결정론적 푸시다운 오토마타(Nondeterministic push-down automata) => 문맥 자유 언어
3) 선형 제약 비결정론적 튜링 기계(Liniearly bounded nondeterministic turing machine) => 문맥 의존 언어
4) 튜링 기계 (Turing machine) => 재귀적 열거 가능 언어
38
https://ko.wikipedia.org/wiki/촘스키_위계
배경: 언어, 문법, 오토마타
=> 정규식(regular expression): 제3유형의 언어를 기술하는 또다른 편리한 방법!
39
https://ko.wikipedia.org/wiki/촘스키_위계
a, b : 터미널
A : 넌터미널
alpha, beta : 터미널과 넌터미널 심볼 리스트 (비어있는 리스트도 가능)
정규식에 매칭하는 문자열 인식
- 정규식 ( == 오토마톤 == 문법 == 언어)
- 정규식 -> 비결정 유한 오토마타 -> 결정 유한 오토마타
Q1. 왜 문법이 아니고 정규식으로 어휘 분석기 명세 작성?
=> 정규 언어의 경우 문법 보다 정규식이 간결하게 명세 작성 가능
Q2. 왜 정규식을 바로 결정 유한 오토마타로 변환하지 않나?
=> 정규식을 비결정 유한 오토마타로 옮기기 쉬움
=> 비결정 유한 오토마타를 결정 유한 오토마타로 변환하는 알고리즘 존재
40
정규식에 매칭하는 문자열 인식
41
q0
q1
q2
a
a
q0
q1
q2
a
λ
q0에서 입력을 취하지 않고 (λ) q1으로 이동
비결정 유한 오토마타
결정 유한 오토마타
q0
q1
q2
a
b
q0
q1
q2
b
q0에서 입력 a를 받으면 에러
정규식에 매칭하는 문자열 인식
=> 정규식을 정규 오토마타로 바꾸어 정규식 매칭 문자열을 효율적으로 인식
( 어휘 분석기의 일반적인 구현 방법 )
42
정규식 => 비결정 유한 오토마타
(ns0에서 a를 입력 받으면 ns0 또는 ns1로 임의로 선택하여 이동. 비결정 상태 전이 Nondeterministic state transition!!)
43
정규식 => 비결정 유한 오토마타
Q. 앞 슬라이드 예시 비결정 유한 오토마타의 전이 규칙을 모두 나열하시오.
Q. 정규식에서 기술한 문자열이 주어진 비결정 유한 오토마타에 의해 모두 인식될 수 있음을 직관적으로 설명하시오.
44
정규식 => 비결정 유한 오토마타
45
표기법:
정규식 r에 매칭되는 문자열만을 인식하는 유한 오토마타 M(r)
정규식 => 비결정 유한 오토마타
46
cf. lambda λ
=> 아무것도 없는 심볼
=> “”
정규식 => 비결정 유한 오토마타
47
정규식 => 비결정 유한 오토마타
48
정규식 => 비결정 유한 오토마타
49
비결정 => 결정 유한 오토마타(NFA/DFA)
50
비결정 => 결정 유한 오토마타(NFA/DFA)
Q. 앞 슬라이드의 결정 유한 오토마타의 상태 전이 규칙을 모두 작성하시오.
Q. 앞 슬라이드의결정 유한 오토마타가 주어진 정규식의 문자열을 모두 인식하는지 살펴보시오.
51
비결정 => 결정 유한 오토마타(NFA/DFA)
Q. NFA와 DFA가 동일한 문자열 집합을 인식함을 직관적으로 설명하시오.
(힌트: NFA에서 비결정적으로 전이 가능한 상태들의 집합을 DFA의 1개의 상태로 매핑)
52
NFA
DFA
(a | b)* a b b
비결정 => 결정 유한 오토마타(NFA/DFA)
- 각 입력에서 nfa에서 이동 후 상태들의 집합을 dfa의 상태로 도입
- 예) Fig 2.14 => Fig. 2.15 (중간 단계) => Fig 2.16 (완성)
53
비결정 => 결정 유한 오토마타(NFA/DFA)
54
비결정 => 결정 유한 오토마타(NFA/DFA)
55
어휘 분석기 도구 설계
- 어휘 분석 명세를 상태 전이 테이블로 변환하고, 유한 오토마타 시뮬레이터를 통해 어휘 부석 수행
56
어휘 분석기 도구 설계
- 프로그램의 패턴 중 어느 하나와 일치하는 lexeme을 인식할 수 있는 하나의 오토마톤이 필요,
- 새로운 시작 상태를 도입하여 NFA들을 하나로 결합
- 이 새로운 시작 상태에서 각각의 패턴 p_i에 대한 NFA (N_i)의 시작 상태로 자동 전이(epsilon transitions)를 추가
57
p_1 { action A1 }
p_2 { action A2 }
…
p_n { action An }
어휘 분석기 도구 설계
-
58
N_1
N_2
N_3
어휘 분석기 도구 설계
- 입력(의 prefixs들)이 여러 패턴에 동시에 매치될 때 (conflicts!)
1) 길이가 긴 prefix를 선택
예) aabbbba 입력에서 p3에 aab, aabb, aabbb, aabbbb 중 aabbbb를 선택
(최대한 많은 b를, 그 이후 a가 나올때 까지)
59
N_1
N_2
N_3
어휘 분석기 도구 설계
- 입력(의 prefixs들)이 여러 패턴에 동시에 매치될 때 (conflicts!)
2) 가장 긴 prefix가 둘 이상 패턴에 매치되면 명세 순서 상 앞의 패턴 선택
예) abba 입력에서 abb가 p2와 p3가 매치되고, 이중 p2를 선택
(명세 순서에서 p2가 p3를 앞에 위치)
60
N_1
N_2
N_3
어휘 분석기 도구 설계
- 예) aaba
61
N_1
N_2
N_3
[NFA 기반 패턴 매칭]
1) 각 입력 지점에서 상태 집합을 계산
2) 더이상 다음 상태가 없을 때까지 (상태 집합이 빌 때까지) 진행
3) final states를 포함하는 집합까지 다시 뒤로 돌아감
4) final state가 여러 개인 경우 명세 선언 순서에서 가장 앞에 위치한 패턴을 선택
목차
62
구문 분석
63
구문 분석
production1 { action1 }
production2 { action2 }
…
productionN { actionN }
예) E -> E + F 생산 규칙(production) ⇒ 토큰들을 트리로 만드는 방법
64
구문 분석: 어휘 분석
65
| 명세 작성 방법 | 명세 구현 방법 |
어휘 분석기 | 정규식 | 유한 오토마타 |
구문 분석기 | 문맥자유문법 (Context-free grammar) | 푸시다운 오토마타 (Push-down automata) |
문법 (Grammar)
66
문법 (Grammar)
(a b a b b의 유도 과정 derivation)
67
문법 (Grammar)
Q. 위 문법은 정규식 (a | b)* a b b에 매칭되는 모든 문자열들을 유도할 수 있음을 설명하시오. (동일한 언어를 명세하는 점에서 이 문법과 이 정규식은 동치)
68
문법 (Grammar)의 종류
69
[ 촘스키 계층 (Chomsky Hierarchy) ]
문법 (Grammar)의 종류
왼편(lhs, left-hand side)은 비단말 기호 1개 (예: A -> a A)
오른편(rhs, right-hand side)은 최대 1개의 비단말 기호 사용
왼편(lhs)은 비단말 기호 오직 1개 (예: A -> a A b)
생산규칙 x -> y : x, y ∈ (N U T)+ 이고 |x| <= |y|
(N: 넌터미널 기호들의 집합, T: 터미널 기호들의 집합)
(예: x A y -> x a A b y vs. A -> a A b)
70
문법 (Grammar)의 종류
S -> A, A -> a A, A -> epsilon (epsilon: 비어있음)
S -> A , A -> a A b, A -> epsilon
S -> a b c | a A b c
A b -> b A
A c -> B b c c
b B -> B b
a B -> a a | a a A
Q. a^2 b^2 c^2을 유도하시오. a^4b^4 c^4을 유도하시오.
71
(*) a^3 b^3 c^3 유도 예시
S => a A b c => a b A c => a b B b c c
=> a B b b c c => a a A b b c c => a a b A b c c
=> a a b b A c c => a a b b B b c c c
=> a a b B b b c c c => a a B b b b c c c
=> a a a b b b c c c
문법 (Grammar)의 종류
(참고: 타입 분석은 정적 프로그램 분석의 한 가지이기도 함)
72
문법 자유 문법
Q. 시작 기호를 E로 가정하고, 두 문장 x + y * z와 (x + y) * z를 위 문법으로부터 유도하시오.
73
문법 자유 문법
Q. 위 문법을 더 간단하게 아래와 같이 작성하면 어떤 문제가 있나? (모호한 문법: ambiguous grammar)
74
문법 자유 문법
75
문법 명세 예시
76
파싱 개요
77
파싱 종류 | 파싱 알고리즘 | 문법 클래스 |
Top-down parsing | Recursive-descent parsing | LL(k) |
Bottom-up parsing | Shift-Reduce parsing | LR(k) |
하향식 파싱 vs. 상향식 파싱
78
하향식 파싱 예 : id * id
79
상향식 파싱 예 : id * id
80
Shift-Reduce 파싱
81
Shift-Reduce 파싱
(생산 규칙 A -> alpha)
82
LR 파싱
(LR 파싱 오토마톤을 만드는 알고리즘, 드래곤북 4장 참고)
83
예) LR(0) 파싱
상태 : LR(0) 아이템의 집합
전이 : Shift 터미널
Reduce 넌터미널(+ Goto)
예) I11에서 I0, I4, I6으로 갈까?
84
예) LR(0) 파싱
85
LR 파싱
- LR 아이템: 예) A -> X Y Z
A -> . X Y Z, A -> X . Y Z, A -> X Y . Z, A -> X Y Z .
예) A ->
A -> .
- 각 LR 아이템은 해당 생산 규칙에서 어디까지 지나왔고, 앞으로 무엇을 기대하는지를 나타냄
예) A -> . X Y Z : 그 다음 입력에서 X Y Z로부터 유도 가능한 문자열을 기대
예) A -> X . Y Z : X에서 유도 가능한 문자열을 바로 전 입력에서 보았고,
Y Z에서 유도 가능한 문자열을 그 다음 입력에서 기대
- LR 아이템의 집합은 어떤 문자열을 바로 전 입력에서 보았을때 이를 수 있는 동일한 위치를 나타내는 LR 아이템들을 모아 놓은 집합
86
LR 파싱
- 예) I0 -- E --> I1 E’ -> . E E’ -> E . Goto E
- 예) I0 -- id --> I5 F -> . id F -> id . Shift 5 for id
- E’ -> E . 아이템을 포함하는 I1 상태 Accept
- 예) I11 에서 어디로 돌아갈지? F -> ( E ) . Reduce F -> ( E )
I0 == ( ==> I4 == E ==> I8 == ) ==> I11 이면 I0로 돌아가고,
I7 == ( ==> I4 == E ==> I8 == ) ==> I11 이면 I7로 돌아간다.
어느 방향으로 I11에 도달하였는지 그 궤적을 저장하기 위한 스택이 필요!
87
예) LR 오토마타 예시
88
0: E' -> E
1: E -> E + T
2: E -> T
3: T -> T * F
4: T -> F
5: F -> ( E )
6: F -> id
0 ( Shift 4
0 id Shift 5
1 + Shift 6
1 $ Accept
2 ) Reduce 2
2 * Shift 7
2 + Reduce 2
2 $ Reduce 2
3 ) Reduce 4
3 * Reduce 4
3 + Reduce 4
3 $ Reduce 4
4 ( Shift 4
4 id Shift 5
5 ) Reduce 6
5 * Reduce 6
5 + Reduce 6
5 $ Reduce 6
6 ( Shift 4
6 id Shift 5
7 ( Shift 4
7 id Shift 5
8 ) Shift 11
8 + Shift 6
9 ) Reduce 1
9 * Shift 7
9 + Reduce 1
9 $ Reduce 1
10 ) Reduce 3
10 * Reduce 3
10 + Reduce 3
10 $ Reduce 3
11 ) Reduce 5
11 * Reduce 5
11 + Reduce 5
11 $ Reduce 5
0 E 1
0 T 2
0 F 3
4 E 8
4 T 2
4 F 3
6 T 9
6 F 3
7 F 10
생산규칙
액션 테이블
Goto 테이블
LR 파싱
89
LR 파싱
1) Shift j: 현재 토큰을 스택에 넣고 상태 j를 스택에 넣기
2) Reduce (k: A -> beta): beta 길이 2배 만큼 스택 원소들을 빼고, Goto 테이블 [뺀 다음 스택 top의 상태, A]의 다음 상태 i를 구하고, 스택에 A를 먼저 넣고, 그 다음 상태 i를 넣기
3) Accept: 파서는 입력 토큰 시퀀스를 Accept하고 종료
4) 그 이외의 경우는 파싱 에러!
90
LR 파싱
Q. 토큰 시퀀스 id + id * id $ 에 대하여 LR 파싱을 진행해보시오.
91
[REMIND] 토큰 시퀀스 id + id * id $는 식 “x + y * z”을 어휘 분석하여 얻은 토큰 시퀀스에 특수 토큰 (EndOfToken $)을 추가한 것으로 id는 토큰 이름, x, y, z는 각 id 토큰의 lexeme들이다.
LR 파싱
Q. 앞서 진행한 LR 파싱의 3번째 컬럼의 유도 과정을 조합하여 얻을 수 있는 구문 트리는 무엇인가?
92
id
+
*
id
id
LR 파싱 Reduce 액션과 구문 트리
93
LR 파싱 Reduce 액션과 구문 트리
Q. 앞서 구문 트리를 만드는 각 과정을 여러분이 익숙한 프로그래밍언어를 사용하여 구현하시오.
public class Add extends Tree {
private Tree left, right; // getters are assumed to be available
public Add (Tree left, Tree right) { this.left = left; this.right = right; }
}
94
LR 파싱 Reduce 액션과 구문 트리
Q. 5: F -> ( E )에서 괄호를 구문 트리에 따로 저장하지 않았다. 그 이유는 무엇인지 설명하시오.
95
While 언어 문법 : LR(1)
96
참고)
LALR (Lookahead-LR) :
문법 작성하기
:모호한 문법: 주어진 문자열에 대해 두 가지 이상의 구문 트리를 만들 수 있는 문법
97
실습 : Tree-sitter (깃허브)
98
[참고]
https://lazyswamp.blogspot.com/2024/09/how-to-build-rust-implementation-of.html
실습 : PMD
99
실습 : PMD
run.sh pmd -d MySmallBasic/MySmallBasic/src/com/coducation/smallbasic/ -R rulesets/java/quickstart.xml
100
실습 : PMD
101
khchoi@khchoi-ThinkPad-X1-Carbon-5th:~/work/sav/pmd$ run.sh pmd -d MySmallBasic/MySmallBasic/src/com/coducation/smallbasic/ -R rulesets/java/quickstart.xml
9월 20, 2022 4:03:23 오후 net.sourceforge.pmd.PMD encourageToUseIncrementalAnalysis
경고: This analysis could be faster, please consider using Incremental Analysis: https://pmd.github.io/pmd-6.49.0/pmd_userdocs_incremental_analysis.html
/home/khchoi/work/sav/pmd/MySmallBasic/MySmallBasic/src/com/coducation/smallbasic/ArithExpr.java:21: MethodNamingConventions: The instance method name 'GetOp' doesn't match '[a-z][a-zA-Z0-9]*'
/home/khchoi/work/sav/pmd/MySmallBasic/MySmallBasic/src/com/coducation/smallbasic/ArithExpr.java:25: MethodNamingConventions: The instance method name 'GetOperand' doesn't match '[a-z][a-zA-Z0-9]*'
/home/khchoi/work/sav/pmd/MySmallBasic/MySmallBasic/src/com/coducation/smallbasic/ArithExpr.java:35: LocalVariableNamingConventions: The local variable name 'temp_ex' doesn't match '[a-z][a-zA-Z0-9]*'
/home/khchoi/work/sav/pmd/MySmallBasic/MySmallBasic/src/com/coducation/smallbasic/ArithExpr.java:36: OneDeclarationPerLine: Use one line for each declaration, it enhances code readability.
/home/khchoi/work/sav/pmd/MySmallBasic/MySmallBasic/src/com/coducation/smallbasic/ArithExpr.java:38: LocalVariableNamingConventions: The local variable name 'parsed_float1' doesn't match '[a-z][a-zA-Z0-9]*'
/home/khchoi/work/sav/pmd/MySmallBasic/MySmallBasic/src/com/coducation/smallbasic/ArithExpr.java:38: LocalVariableNamingConventions: The local variable name 'parsed_float2' doesn't match '[a-z][a-zA-Z0-9]*'
실습 : SonarQube
sonar-scanner에서 대상 프로그램을 분석하고 웹 서버에 전달
sonarqube-9.6.1.59531.zip 을 다운받아 같은 이름의 폴더에 풀기
ln -s sonarqube-9.6.1.5953/bin/linux-x86-64 bin
./bin/sonar.sh console
ID/PW: admin/admin
102
실습 : SonarQube
https://docs.sonarqube.org/latest/analysis/scan/sonarscanner/
sonar-scanner-4.7.0.2747-linux.zip 다운받아 같은 이름의 폴더에 풀기
export PATH=$MYHOME:/sonar-scanner-4.7.0.2747-linux/bin:$PATH
sonar-scanner -Dsonar.projectKey=MySmallBasic_Project -Dsonar.sources=./MySmallBasic/src -Dsonar.host.url=http://localhost:9000 -Dsonar.login=sqp_49ec5788961b7f269bd793244e1a27cd89764f87 -Dsonar.java.binaries=./MySmallBasic/bin
기본적으로 Java 소스 프로그램과 바이너리 (클래스) 프로그램이 모두 필요.
바이너리가 없을 때 configuration에서 분석 범위에서 제외
103
토큰은 본인 환경에서 새로 생성
(다음 슬라이드 참고)
실습 : SonarQube
104
분석할 프로젝트를 새로 만들 때 sonarqube 웹 (http://localhost:9000)에서 이 프로젝트 토큰을 만들고 나중에 분석할 때 옵션으로 이 토큰을 지정하면 분석 결과가 해당 프로젝트로 전달됨.
Now that you're logged in to your local SonarQube instance, let's analyze a project:
After successfully analyzing your code, you'll see your first analysis on SonarQube:
실습 : SonarQube
105