นิพจน์ทั่วไป


16

ถ้าฉันมีไวยากรณ์ประเภทที่ 3 มันสามารถถูกแสดงในออโตเมติกแบบกดลง (โดยไม่ต้องดำเนินการใด ๆ กับสแต็ก) ดังนั้นฉันจึงสามารถแสดงนิพจน์ทั่วไปโดยใช้ภาษาที่ไม่มีบริบท แต่ฉันจะรู้ได้อย่างไรว่าไวยากรณ์ 3 ประเภทคือ , L L ( 1 ) , S L R ( 1 )และอื่น ๆ โดยไม่ต้องสร้างตารางแยกวิเคราะห์?LR(1)LL(1)SLR(1)

คำตอบ:


15

ทุกภาษาปกติมีไวยากรณ์ LL (1) ในการรับไวยากรณ์ดังกล่าวให้ใช้ DFA ใด ๆ สำหรับภาษาปกติ (อาจทำโครงสร้างย่อยของ NFA ที่ได้รับจากนิพจน์ทั่วไป) จากนั้นแปลงเป็นไวยากรณ์ปกติแบบเรียกซ้ำ ไวยากรณ์นี้คือ LL (1), เพราะคู่ใด ๆ ของโปรดักชั่นสำหรับ nonterminal เดียวกันไม่ว่าจะเริ่มต้นด้วยสัญลักษณ์ที่แตกต่างกันหรืออย่างใดอย่างหนึ่งผลิตεและมี $ เป็นโทเค็น lookahead ดังนั้นภาษาปกติทั้งหมดจึงเป็น LR (1) เนื่องจากไวยากรณ์ LL (1) ใด ๆ คือ LR (1) นอกจากนี้การใช้ผลลัพธ์ที่สำคัญจากบทความนี้คุณสามารถแสดงให้เห็นว่าภาษา LR (1) ใด ๆ มีไวยากรณ์ SLR (1) ซึ่งหมายความว่าภาษาปกติใด ๆ ที่มีไวยากรณ์ SLR (1)

อย่างไรก็ตามภาษาทั่วไปไม่ใช่ LR (0) ทั้งหมด ภาษา LR (0) มีคุณสมบัติที่เฉพาะเจาะจงมากโดยเฉพาะอย่างยิ่งพวกเขาจะต้องปราศจากคำนำหน้า ดังนั้นภาษาปกติ {a, aa} ไม่ใช่ LR (0) ถึงแม้ว่ามันจะเป็นเรื่องปกติ (regex a | (aa)) อย่างไรก็ตามภาษา LR (0) ไม่ได้บรรจุอยู่ในภาษาปกติ ไวยากรณ์นี้สำหรับ {0 n 21 n | n ≥ 1} คือ LR (0) แต่ภาษาไม่ปกติ:

S -> E
E -> 0E1 | 2

หวังว่านี่จะช่วยได้!


2
ความจริงที่ว่าไวยากรณ์ปกติถูกต้องยอมรับว่าชุดของภาษาปกติมักจะทำในชั้นเรียน (หรือแม้กระทั่งการออกกำลังกาย) ดังนั้นคำตอบคือทันทีมากขึ้น
กราฟิลส์

2

(ธรรมดาเก่า) ไวยากรณ์นิพจน์ทั่วไป(คุณบอกว่า "การแสดง") คือ LR (0) คุณไม่จำเป็นต้องมี lookahead ในการแยกสตริงที่เป็นตัวแทนของ regex คุณสามารถตัดสินใจได้ง่าย ๆ ด้วยการรัน parser generator บนไวยากรณ์สำหรับ regexes: -} คุณยังสามารถเขียนโค๊ด recursive อย่างง่าย ๆ (LL (0)) parser สำหรับ regexps; อะไรก็ได้ที่ LL (0) คือ LR (0)

ฉันไม่ทราบว่าไวยากรณ์ของสิ่งที่ซับซ้อนกว่าเรียกว่า "regexps" เช่น Perl ของเป็นเช่นนี้; แต่ regexps ของ Perl นั้นมีประสิทธิภาพมากกว่า regexps อย่างเคร่งครัดดังนั้นจึงไม่ใช่ regexps แบบธรรมดา

ในการตรวจสอบว่าไวยากรณ์มีคุณสมบัติบางอย่างหรือไม่คุณต้องเรียกใช้เพรดิเคตบางประเภท ในการตรวจสอบว่าเป็น (S) LR (k) หรือไม่คุณต้องเรียกใช้เพรดิเคตที่สามารถตรวจสอบคุณสมบัตินั้นได้ ภาคแสดงผลใด ๆ จะต้องสร้างตารางในการแยกวิเคราะห์เพราะวิธีที่พวกเขากำหนดไว้


การแสดงออกปกติ Perl ทำงานบน NFA

คำถามไม่ได้เกี่ยวกับการทำงานของ Perl regexps มันเกี่ยวกับว่า (Perl?) regexps แยกวิเคราะห์ได้ด้วยเทคโนโลยีบางอย่าง ฉันสามารถเชื่อว่า Perl regexps ใช้ NFA เพื่อทำการจับคู่ของพวกเขาพร้อมกับการจับข้อมูลที่ไวต่อบริบทอื่น ๆ แต่ฉันไม่เห็นความเกี่ยวข้องกับคำถาม

3
-1 นิพจน์ทั่วไปไม่ใช่ LR (0) ภาษา LR (0) จะต้องไม่มีคำนำหน้า แต่การแสดงออกปกติa|(aa)อธิบายถึงภาษาที่ไม่ได้ใช้คำนำหน้าฟรี นอกจากนี้ภาษา LR (0) ไม่สามารถจัดการไวยากรณ์ด้วยการผลิตเอปไซลอนดังนั้นภาษาปกติ {epsilon, a} ไม่ใช่ LR (0) อย่างไรก็ตามภาษาปกติคือ LL (1) เพราะคุณสามารถเขียนเป็นไวยากรณ์ปกติและทำให้พวกเขาทั้งหมด LR (1) เนื่องจากภาษา LR (1) ใด ๆ มีไวยากรณ์ SLR (1) นั่นหมายความว่าภาษาทั่วไปทั้งหมดคือ SLR (1)
templatetypedef

1
เกี่ยวกับ LL (0) เป็นอีกวิธีหนึ่ง: LL (0) ภาษาเป็นส่วนย่อยที่เหมาะสมของภาษาปกติ โปรดทราบว่า LL (0) หมายความว่าคุณไม่ได้ใช้ lookahead ในการตัดสินใจเลือกระหว่างอนุพันธ์ต่าง ๆ - ซึ่งโดยทั่วไปหมายความว่าไม่มีการตัดสินใจและภาษานั้นประกอบด้วยคำเดียว ในทางตรงกันข้าม LR (0) เป็นคลาสที่มีประโยชน์อีกครั้งคุณไม่ได้ใช้ lookahead ในการตัดสินใจ (ที่นี่เพื่อลด) แต่ก็ยังมีความหลากหลายเนื่องจากความจริงที่ว่าการเลื่อนสามารถแยกความแตกต่างระหว่างการผลิตที่แตกต่างกัน

1
@ IraBaxter- ไวยากรณ์ของนิพจน์ทั่วไปไม่ใช่ LR (0) อย่างใดอย่างหนึ่งเนื่องจากนิพจน์ทั่วไปนั้นไม่มีค่านำหน้า ไม่ได้เป็น LL (0) เนื่องจาก LL (0) ภาษาสามารถมีได้เพียงสตริงเดียวเท่านั้น (หรือไม่มีสตริง)
templatetypedef
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.