✔️ 루트 노드부터 leaf 노드로 (Star from starting Non-terminal and work your way down)
✔️ Left-to-Right Scanning (input symbol을 왼쪽에서 오른쪽으로 읽는다)
✔️ Left parse for Derivation Tree Generation (Left-Most derivation)
이해하기 쉽다.
루프가 무한하게 존재할 수 있기 때문에(Left-recursion) 효율적이지 않다.
백트래킹은 시간이 많이 소요된다.
✔️ leaf 노드부터 시작하여 루트 노드로 (Start from terminals and work your way up!)
✔️ Left-to-Right Scanning (input symbol을 왼쪽에서 오른쪽으로 읽는다)
✔️ Right parse for Derivation Tree Genenration (Right-Most derivation)
Top-down Parsing의 단점
➡️ 루프가 무한하게 존재할 수 있기 때문에(Left-recursion) 효율적이지 않다.
➡️ 백트래킹은 시간이 많이 소요된다.
✔️ Top-down Parsing은 시작 symbol부터 시작하여 주어진 production rule을 기반으로 left-parse를 하는 기법이다.
✔️ 그런데 만약 사용된 production rule이 적절한 rule이 아닐 경우에, 다른 production rule을 적용해 가야 한다. 이러한 과정이 iterative하게 반복되는 것을 'backtracking'이라고 한다.
✔️ Backtracking은 시간이 많이 소요될뿐더러 효율적이지 않다.
✔️ Top-down Parsing을 할 때 production rule을 적용해보고, 생성되는 것을 왼쪽부터 target 문자열과 하나씩 비교해본다.(left- to- right scanning)
ex) 앞선 예시에서 S에서 aAd가 생성됐을 때, a부터 'accd'와 비교해보는 방식✔️ 그런데! 만약 비교대상이 non-terminal이라면, non-terminal은 어떠한 string으로 바뀔지 모르기 때문에 target character와 비교하지 못하고 계속 production rule을 적용해 보게된다.
✔️ 이러한 경우 Non-terminal이니까 잘못된 production rule이라고 결론을 내릴 수 없어서 계속해서 production rule을 적용해보면서 loop에 빠지게 되는 것이다.
➡️ 원인 : 비교 대상인 왼쪽 Symbol이 Non-terminal이기 때문에 비교를 할 수 없는 것
➡️ 해결법 : Left Recursion은 Infinite Loop를 초래하기 때문에 top-down parsing을 하고자 한다면, 프로그래밍 언어의 grammer에서 left recursion을 제거해야 한다.
1) Direct Left-Recursion
ex) A -> Aa | B
A->Aa 와 같이 Non-terminal이 동일한 Non-terminal이 되는 것2) Indirect Left-Recursion
ex) S -> Aa | b, A -> Ac|Sd|
S->Sa, A->Sd처럼 Non-terminal A이 다른 Non-terminal B이 되고, 다른 non-terminal B이 다시 그 Non-terminal A이 되는 것🌳 Non-terminal Mapping 🌳
Direct Recursion은 바로 찾을 수 있지만, CFG가 복잡하다면 Indirect Recursion 찾기는 어렵기 때문에 Non-terminal Mapping을 해서 찾을 수 있다. Terminal 부분은 제외하고 Mapping 해보기!
S -> A
A -> A
A -> S
이러한 Mapping을 통해서 S->A, A->S의 Cycle을 찾고 indirect recursion을 찾을 수 있다.