나는 등 생산에 FIRST() 규칙을 적용 할 방법 :LL (1) 구문 분석 - 재귀 첫 번째 대안으로 우선 (A)
A -> AAB | Ab | s
여기서 A는 비 종단이고 b, s는 종단입니다.
FIRST (A) 대안 1 & 2는 FIRST의 무한 응용 프로그램에서 끝납니다. 첫 번째 세트를 얻으려면 터미널이 필요합니다.
나는 등 생산에 FIRST() 규칙을 적용 할 방법 :LL (1) 구문 분석 - 재귀 첫 번째 대안으로 우선 (A)
A -> AAB | Ab | s
여기서 A는 비 종단이고 b, s는 종단입니다.
FIRST (A) 대안 1 & 2는 FIRST의 무한 응용 프로그램에서 끝납니다. 첫 번째 세트를 얻으려면 터미널이 필요합니다.
FIRST 집합을 계산하려면 일반적으로 고정 소수점 반복을 수행합니다. 즉, 작은 값 집합으로 시작한 다음 집합이 수렴 될 때까지 FIRST 집합을 반복적으로 다시 계산합니다.
이 경우, 생산 A → s는 FIRST (A)가 {s}을 포함해야한다는 것을 의미하는 것으로 시작합니다. 처음에는 FIRST (A) = {s}를 설정했습니다.
이제 각 산출물을 반복하고 지금까지 계산 한 FIRST 세트에 대한 지식을 기반으로 FIRST를 업데이트합니다. 예를 들어, 규칙
→ AAB
수단 먼저 (AAB)의 모든 요소를 포함하는 FIRST (A)를 업데이트해야하는. 이로 인해 FIRST (A)가 변경되지 않습니다. 그런 다음 방문
→ Ab의
당신은 또 다시 어떤 조합입니다 FIRST (AB)를 포함하는 FIRST (A)를 업데이트합니다. 마지막으로,
을의 방문 →의
그리고 FIRST (A)가 이미의를 포함하기 때문에,이 변화가 발생하지 않습니다
.이 반복에서 변경된 사항이 없으므로 FIRST (A) = {s}로 끝납니다. A에서 시작하는 파생은 궁극적으로 s
을 첫 번째 문자로 생성하기 때문에 실제로 맞습니다.
자세한 내용은 these lecture slides (여기 part two)을 참조하십시오. 그들은 하향식 파싱이 어떻게 작동하는지 그리고 FIRST 집합을 반복적으로 계산하는 방법을 자세히 설명합니다.
희망이 도움이됩니다.
문법 규칙은 이미 실현 했으므로 left recursion이고 LL 파서는 are not able to parse grammars with left recursion입니다.
그래서 왼쪽 재귀를 먼저 제거해야합니다. 그런 다음 규칙의 첫 번째 집합을 계산할 수 있어야합니다.
이것이 사실이지만, OP의 질문은 문법이 왼쪽 재귀 적 일지라도 가능한 FIRST 집합을 계산하는 문제라고 생각합니다. – templatetypedef
질문은 * FIRST * 집합을 계산하는 것에 관한 것이며, 이것은 왼쪽 재귀 문법에 대해 수행 할 수 있습니다. – Apalala
내 teaching notes은 스페인어로되어 있지만 알고리즘은 영어로되어 있습니다., ε
가 널 (null) 문자열, P
이 제작 (규칙)의 집합입니다, N
비 터미널의 집합입니다,
foreach a ∈ Σ do
F(a) := {a}
for each A ∈ N do
if A→ε ∈ P then
F(A) := {ε}
else
F(A) := ∅
repeat
for each A ∈ N do
F'(A) := F(A)
for each A → X1X2...Xn ∈ P do
if n > 0 then
F(A) := F(A) ∪ F'(X1) ⋅k F'(X2) ⋅k ... ⋅k F'(Xn)
until F(A) = F'(A) forall A ∈ N
FIRSTk(X) := F(X) forall X ∈ (Σ ∪ N)
Σ
알파벳 (터미널)입니다 :이 FIRST을 계산하는 방법 중 하나입니다 ⋅k
은 k
위치로 트림 된 연결입니다. ∅ ⋅k x = ∅
에 주목하고 두 세트를 연결하면 데카르트 제품의 요소가 연결됩니다.
FIRST을 손으로 계산하는 가장 쉬운 방법은 알고리즘 반복 당 하나의 테이블을 사용하는 것입니다.
F(A) = ∅
F'(A) = F(A) ⋅1 F(A) .1 F(b) U F(A) .1 F(b) U F(s)
F'(A) = ∅ ⋅1 ∅ ⋅1 {b} U ∅ ⋅1 {b} U {s}
F'(A) = ∅ U ∅ U {s}
F'(A) = {s}
F''(A) = F'(A) ⋅1 F'(A) .1 F'(b) U F'(A) .1 F'(b) U F'(s)
F''(A) = {s} ⋅1 {s} ⋅1 {b} U {s} ⋅1 {b} U {s}
F''(A) = {s} U {s} U {s}
F''(A) = {s}
그리고 우리가 완료 때문에 F' = F''
, 그래서 FIRST = F''
및 FIRST(A) = {s}
.
@ Apalala-이 점에 대해 확실합니까? 'b'기호는 FIRST (A)에 분명히 없습니다. FIRST 집합을 계산하기 위해 알고있는 알고리즘은 FIRST 집합을 터미널로 시작하는 모든 제작물에 시드 한 다음 거기에서부터 진행하여 작동합니다. – templatetypedef
@ Apalala- 또는 그런 식으로 모든 것을 시드하지 않으면, 비 터미널이 엡실론을 생성 할 수 없다면 첫 번째 세트의 비 터미널을 조사하여 FIRST 세트를 계산하지 않아도됩니다. 이는 업데이트 규칙이 FIRST (A)를 FIRST (A)에 추가하여 빈 세트를 자체에 추가하게됨을 의미합니다. – templatetypedef
'A -> b '형식의 규칙에 대해 터미널에 FIRST를 시드 할 수는 있지만 일반적으로 충분하지는 않습니다. 하지만 내 downvote에 대한 이유는 당신이 'A -> AAb'에서 FIRST를 계산할 때 첫 번째 A 만보아야한다는 것이고 이것이 잘못된 것입니다. 왜냐하면이 경우가 아니더라도 ' A = * => ε' 일 경우'FIRST (A)'에'b '가 들어갑니다. * FIRST *에 대한 일반적인 해결책은 내 대답을 참조하십시오. – Apalala