วลีการเปลี่ยนแปลงกับ LR การแยก


16

วลีเปลี่ยนแปลงเป็นส่วนขยายมาตรฐาน (E) BNF บริบทฟรีไวยากรณ์คำจำกัดความ: วลีเปลี่ยนแปลงมีnโปรดักชั่น (หรือเท่ากัน nonterminals) 1ผ่านn ที่ตำแหน่งของวลีการเปลี่ยนรูปเราต้องการเห็นทุกการผลิตเหล่านี้เพียงครั้งเดียว แต่เราไม่สนใจที่จะจัดลำดับของผู้ไม่ประสงค์ออกนามเหล่านี้{A1,...,An}nA1An

ตัวอย่างเช่น:

S <- X { A, B, C } Y

เทียบเท่ากับ:

S <- X  A B C  Y
S <- X  A C B  Y
S <- X  B A C  Y
S <- X  B C A  Y
S <- X  C A B  Y
S <- X  C B A  Y

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

กระดาษ"การแยกวิเคราะห์วลีการเปลี่ยนแปลง"อธิบายวิธีการแยกวลีการเปลี่ยนแปลงโดยใช้ตัวแยกวิเคราะห์ parser นี่เป็นเพียงเอกสารสองฉบับที่ฉันได้พบว่าพูดถึงวลีเกี่ยวกับการเปลี่ยนแปลงและวิธีการแยกวิเคราะห์

เมื่อเห็นว่าเราสามารถแยกวิเคราะห์วลีเรียงสับเปลี่ยนเหล่านี้ได้อย่างง่ายดายด้วยตัวแยกวิเคราะห์แบบ LL (1) ฉันเดาว่าฉันจะทำแบบเดียวกันกับตัวแยกวิเคราะห์สไตล์ LR (1) คำถามของฉันคือ:

ไวยากรณ์ที่มีวลีการเรียงสับเปลี่ยนสามารถแยกวิเคราะห์เป็นเส้นตรงเวลาในขนาดสตริงอินพุตโดยใช้เครื่องจักร LR (1) ในขณะที่รักษาตารางที่มีขนาดเหมาะสมได้หรือไม่?

วลีการเปลี่ยนแปลงไม่ได้เพิ่มพลังของภาษาที่ไม่มีบริบท: ในตัวอย่างของฉันข้างต้นเราสามารถระบุการเรียงสับเปลี่ยนที่เป็นไปได้ทั้งหมด แต่ไวยากรณ์แล้วระเบิดเป็นไวยากรณ์ส่งผลให้สามารถมีขนาด ) วิธีนี้ช่วยให้สามารถวิเคราะห์เวลาแบบเส้นตรงได้ แต่ขนาดของไวยากรณ์จะใหญ่เกินไปO(|G|!)

O(2|G|)

แม้ว่าสิ่งนี้จะดีกว่า แต่แน่นอนว่าไม่ดีพอ - การใช้วลีที่มีการเปลี่ยนแปลง 30 รายการจะทำให้ไวยากรณ์ใช้ไม่ได้ ยังมีอีกส่วนหนึ่งของการวิเคราะห์คำ LR ที่เรายังไม่ได้แตะและนั่นคือขั้นตอนการประมวลผลตามจริงที่ใช้สำหรับการแยกวิเคราะห์ ฉันจินตนาการว่าการจัดเก็บตัวนับบนสแต็กอาจสามารถแก้ปัญหาได้ แต่ฉันไม่แน่ใจว่าจะทำอย่างไร

ขณะนี้ฉันกำลังใช้ตัวแยกวิเคราะห์และในวลีการเปลี่ยนแปลงโดเมนปัญหาจะเป็นของขวัญจากสวรรค์ ในขณะที่ฉันใช้เครื่องจักร LR (1) คำถามข้างต้นก็ตามมา


ความซับซ้อนของการแยกวิเคราะห์ LR (1) นั้นมีความซับซ้อนในขนาดของไวยากรณ์โดยไม่มีการเรียงสับเปลี่ยนวลี - ยกเว้นถ้าคุณใช้การคำนวณแบบ "ทันที" ของตัวแยกวิเคราะห์ แต่ก็ให้ความรู้สึกคล้ายกับตัวแยกวิเคราะห์ Earley มากกว่าแบบ ของแท้ LR (1) หนึ่ง
Sylvain

2
เกี่ยวกับคำถามที่เหลือของคุณ: cstheory.stackexchange.com/questions/4962/…แสดงขอบเขตล่างแบบเอ็กซ์โปเนนเชียลของขนาดของ CFG สำหรับการเรียงสับเปลี่ยนและจากการสร้างพหุนามแบบปกติของ CFG จาก PDAs สิ่งนี้จะทำให้ขอบเขตล่างแบบเอ็กซ์โพเนนเชียล ขนาดของ PDA เช่นกัน
Sylvain

1
ฉันไม่ได้ดูที่เอกสารเกี่ยวกับ LL (1) อันที่จริงโปรแกรมแยกวิเคราะห์ที่นำมาใช้ไม่ใช่พีดีเออีกต่อไป ฉันยังคงไม่เชื่อในการมีอยู่ของ "ตารางที่มีขนาดพอสมควร" เนื่องจากการเป็นสมาชิกของแกรมม่าแบบปลอดบริบทสับเปลี่ยนเป็น NP-complete (ดูตัวอย่างเช่นdx.doi.org/10.3233/FI-1997-3112 ) แต่มันเป็นเรื่องจริง ว่ากรณียากอาจไม่ได้ LR (1)
Sylvain

2
@Sylvain: คุณช่วยอธิบายได้ไหมว่าคำถาม 4962 เกี่ยวข้องกับคำถามนี้อย่างไร ในคำถาม 4962 การเรียงสับเปลี่ยนได้รับการแก้ไขสำหรับแต่ละความยาวอินพุตและสตริงที่ต้องเปลี่ยนแปลงเปลี่ยนแปลง ในคำถามปัจจุบันเราไม่แก้ไขการเปลี่ยนแปลง ดังนั้นฉันจึงไม่เห็นการเชื่อมต่อที่แท้จริงระหว่างพวกเขา
Tsuyoshi Ito

2
@Tsuyoshito Ito: ใน LR (1) การแยก DPDA ที่เทียบเท่ากับไวยากรณ์อินพุตจะถูกสร้างขึ้นเป็นครั้งแรกและจากนั้นเรียกใช้กับสตริงที่จะรับรู้ เนื่องจากมี CFG ขนาดเชิงเส้นที่มีวลีเกี่ยวกับการเปลี่ยนแปลงทุกภาษากระดาษของ Yuval Filmus (ซึ่งครอบคลุมมากกว่าคำตอบของเขาใน cstheory: ดูcs.toronto.edu/~yuvalf/CFG-LB.pdf ) แสดงให้เห็นว่าไม่มี DPDA ดังกล่าวอาจมีขนาดพหุนามในขนาดของไวยากรณ์อินพุต
Sylvain

คำตอบ:


1

คุณคิดว่าการแปลงสิ่งนี้เป็นปัญหาทางความหมายหรือไม่ แทนที่จะเป็นกฎไวยากรณ์สำหรับการเปลี่ยนลำดับทั้งหมดของ nonterminals {A, B, C} เพียงแค่มีกฎหนึ่งข้อที่จะรับรู้ (A | B | C) ^ 3 พร้อมกับรหัสภายในพิเศษที่ทำให้แน่ใจว่ามีเพียงหนึ่งตัวเท่านั้นที่รู้จัก ข้อผิดพลาด ฉันจะแทรกการผลิตที่ว่างเปล่าก่อนส่วนคำสั่งด้านบนซึ่งการลดทริกเกอร์การเริ่มต้นของสิ่งที่คุณใช้ในการนับ A, B, และ C และหลังจากนั้นการลดทริกเกอร์การตรวจสอบที่เคาน์เตอร์และ (ถ้าจำเป็น) ยืนยันข้อผิดพลาด (แน่นอนว่านี่อาจเป็นเรื่องยุ่งยากเล็กน้อยหากไวยากรณ์ซ้ำผ่าน A, B และ / หรือ C)


0

ฉันไม่คิดว่าจะต้องมีเคาน์เตอร์ เป็นหลักคุณเพียงแค่ตรวจสอบการเปลี่ยนลำดับทั้งหมด แต่ทำลาย

หลอกรหัส:

perm-match(input, pattern)
     if pattern = nil return true

     foreach(rule in pattern)
         if (match(input, rule))
             perm-match(input - matchedpart, pattern - rule)
             break
         end
     end
     return false
end

นี่คือตัวอย่างที่เป็นรูปธรรมมากขึ้น

สมมติว่าเราพยายามจับคู่การเปลี่ยนแปลง abcd และสตริงของเราคือ bcda

  • ขั้นตอนที่ 1: ค้นหาสัญลักษณ์ที่ตรงกันแรก ในกรณีนี้มันคือ b
  • ขั้นตอนที่ 2: ลบสัญลักษณ์นั้นออกจากรูปแบบของเราและลดสตริง: เช่นเหลือ acd และ cda
  • ขั้นตอนที่ 3: ทำซ้ำขั้นตอนที่ 1 ในสายอักขระใหม่
    • ตรงกับ cda ซึ่งทำให้เรามีโฆษณาและดา
    • การแข่งขันในดาซึ่งทำให้เรามีวันและวัน
    • d ตรงกันใน d ซึ่งทำให้เรามีศูนย์ในทั้งสองสตริง

ดังนั้นคุณจะเห็นอัลกอริทึมง่าย ๆ นี้สามารถตรวจสอบการเปลี่ยนแปลงได้ง่าย ๆ เพียงแค่เปรียบเทียบ "สตริง" ที่ไม่เป็นระเบียบ โปรดทราบว่าความซับซ้อนของฟังก์ชั่นคือกรณีที่แย่กว่า O (n!) และ O (1) กรณีที่ดีที่สุด ในแง่หนึ่งเรากำลังทำการนับโดยการเก็บสัญลักษณ์เพื่อจับคู่ในอาร์เรย์ ฉันคิดว่านี่จะเป็น "เร็ว" โดยทั่วไปเนื่องจากไม่มีใครจัดการกับ n ที่มีขนาดใหญ่มากในกรณีส่วนใหญ่


2
nn=50
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.