กำลังมองหาคำจำกัดความที่ชัดเจนว่า "tokenizer", "parser" และ "lexers" คืออะไรและเกี่ยวข้องอย่างไรกันและนำมาใช้อย่างไร


151

ฉันกำลังค้นหาคำจำกัดความที่ชัดเจนของสิ่งที่ "tokenizer", "parser" และ "lexer" คืออะไรและเกี่ยวข้องกันอย่างไร (เช่น parser ใช้ tokenizer หรือในทางกลับกัน)? ฉันต้องสร้างโปรแกรมจะผ่านไฟล์ต้นฉบับ c / h เพื่อแยกการประกาศข้อมูลและคำจำกัดความ

ฉันกำลังมองหาตัวอย่างและสามารถหาข้อมูลได้บ้าง แต่ฉันพยายามดิ้นรนเพื่อเข้าใจแนวคิดพื้นฐานเช่นกฎไวยากรณ์การแยกวิเคราะห์ต้นไม้และต้นไม้ไวยากรณ์ที่เป็นนามธรรมและวิธีที่พวกเขามีความสัมพันธ์ซึ่งกันและกัน ในที่สุดแนวคิดเหล่านี้จำเป็นต้องเก็บไว้ในโปรแกรมจริง แต่ 1) สิ่งที่พวกเขาดูเหมือน 2) มีการใช้งานทั่วไป

ฉันดูวิกิพีเดียในหัวข้อและโปรแกรมเหล่านี้เช่น Lex และ Yacc แต่ไม่เคยผ่านชั้นเรียนคอมไพเลอร์ (หลัก EE) ฉันพบว่ามันยากที่จะเข้าใจว่าเกิดอะไรขึ้น

คำตอบ:


166

โทเค็นไนเซอร์แบ่งกระแสข้อความเป็นโทเค็นโดยปกติแล้วจะมองหาช่องว่าง (แท็บช่องว่างบรรทัดใหม่)

lexer นั้นเป็นโทเค็นเนอร์ แต่โดยทั่วไปแล้วมันจะเพิ่มบริบทพิเศษให้กับโทเค็นโทเค็นนี้เป็นตัวเลขโทเค็นนั้นเป็นตัวอักษรของสตริงโทเค็นตัวอื่นจะเป็นตัวดำเนินการที่เท่าเทียมกัน

โปรแกรมแยกวิเคราะห์ใช้สตรีมของโทเค็นจาก lexer และเปลี่ยนเป็นแผนผังไวยากรณ์แบบนามธรรมแทนโปรแกรม (ปกติ) ที่แสดงด้วยข้อความต้นฉบับ

ครั้งล่าสุดที่ฉันตรวจสอบหนังสือที่ดีที่สุดในเรื่องคือ"ผู้เรียบเรียง: หลักการเทคนิคและเครื่องมือ"มักจะรู้จักกันในนาม "The Dragon Book"


8
ไม่ต้องสงสัยเลยว่า "The Dragon Book" เป็นหนังสือที่ดี แต่ไม่ต้องการให้ผู้อ่านมีพื้นฐานที่ดีใน CS หนังสือบางเล่มที่มีการอุทธรณ์ที่ใช้ประโยชน์ได้มากกว่าคือ "การเขียนคอมไพเลอร์และล่าม" โดย Ronald Mak, "Modern Compiler Implementation", Andrew Appel; "คอมไพเลอร์ก่อสร้าง", Niklaus Wirth; "การคอมไพล์ด้วย C # และ Java" และ "คอมไพเลอร์และคอมไพเลอร์ Generators: บทนำกับ C ++" โดย Pat Terry; และแน่นอน "การอ้างอิง ANTLR ขั้นสุดท้าย" โดย Terrence Parr
Andre Artus

5
เพียงเพื่อให้แน่ใจว่าฉันไม่ได้ทำตามคำแนะนำของคุณ "The Dragon Book" เป็นหนังสือเล่มแรกของฉันเกี่ยวกับเทคโนโลยีคอมไพเลอร์ แต่มันยากที่จะเปรียบเทียบกับพูดว่าหนังสือของ Wirth ซึ่งเป็นหนังสือที่คุณสามารถคลานได้ในเวลาไม่กี่ชั่วโมง ย้อนกลับไปตอนนั้นฉันมีตัวเลือกน้อยเพราะเป็นหนังสือเล่มเดียวที่ฉันสามารถทำได้ (เป็นปี 1991 ก่อนหน้า Amazon และ WWW) ฉันมีสิ่งนั้นและคอลเล็กชันของไฟล์ข้อความที่ผลิตโดย Jack W. Crenshaw เรียกว่า "LET'S BUILD A COMPILER" (ขอบคุณแจ็ค!) หนังสือเล่มนี้ยังคงเป็นหนังสือที่ช่วยให้เข้าใจหลักการที่สมบูรณ์ยิ่งขึ้น แต่โปรแกรมเมอร์ส่วนใหญ่ก็ต้องการการแนะนำอย่างจริงจัง
Andre Artus

10
ฉันจะไม่ยอมรับว่า parser / ตามคำนิยาม / สร้างต้นไม้ไวยากรณ์นามธรรม ตัวแยกวิเคราะห์สามารถสร้างเอาต์พุตที่แตกต่างกันได้ทุกประเภท ตัวอย่างเช่นมันเป็นเรื่องธรรมดาที่ parser สร้างลำดับของการโทรไปยังอินเทอร์เฟซผู้สร้างบางตัว - ดูรูปแบบของตัวสร้างในหนังสือรูปแบบ Gang of Four จุดสำคัญคือ parser วิเคราะห์ลำดับของโทเค็นเพื่อตรวจสอบว่าลำดับนั้นสอดคล้องกับไวยากรณ์ (โดยปกติบริบท) หรือไม่และอาจสร้างผลลัพธ์บางอย่างขึ้นอยู่กับโครงสร้างไวยากรณ์ของลำดับ
Theodore Norvell

2
"Let 's รูปร่างคอมไพเลอร์" อยู่ที่นี่: compilers.iecc.com/crenshaw ฉันพบลิงค์จากที่นี่: prog21.dadgum.com/30.html
Roger Lipscombe

1
@Pithkos: หากเป็นข้อ จำกัด เพียงอย่างเดียวสิ่งที่คุณพูดคือฟังก์ชั่นรับอินพุตในโดเมน (คณิตศาสตร์) ที่ไม่มีชื่อและสร้างและส่งออกในโดเมนที่ไม่มีชื่ออื่นเช่น F (X) -> Y ค่อนข้างมากนี่หมายความว่า คุณสามารถเรียกสิ่งนี้ว่า "ฟังก์ชั่น" เท่านั้น หากคุณยืนยันว่าโดเมนของ X คือ <StreamOfCharacter, Grammar> และโดเมนของ Y คือ Tree พร้อมด้วยคุณสมบัติที่สะท้อนรูปร่างของไวยากรณ์ดังนั้น F (X, G) -> T จะเป็นสิ่งที่ฉันจะเรียก parser บ่อยครั้งที่เราแกงกะหรี่ F ด้วยความเคารพต่อ G เพราะ G ไม่เปลี่ยนบ่อยดังนั้น F [G] (X) -> T เป็นสิ่งที่คุณมักจะเห็นว่าเป็น parser
Ira Baxter

18

ตัวอย่าง:

int x = 1;

lexer หรือ tokeniser จะแบ่งออกเป็นโทเค็น 'int', 'x', '=', '1', ';'

เครื่องมือแยกวิเคราะห์จะใช้โทเค็นเหล่านั้นและใช้เพื่อทำความเข้าใจในบางวิธี:

  • เรามีคำสั่ง
  • มันเป็นคำจำกัดความของจำนวนเต็ม
  • จำนวนเต็มเรียกว่า 'x'
  • 'x' ควรเริ่มต้นด้วยค่า 1

9
lexer จะทราบว่า "int", "=" และ ";" เป็นโทเค็นที่ไม่มีความหมายเพิ่มเติมว่า "x" เป็นชื่อตัวระบุหรือบางสิ่งบางอย่างค่า "x" และ "1" เป็นจำนวนเต็มหรือตัวเลขค่า "1" tokenizer ไม่จำเป็นต้องทำเช่นนั้น
David Thornley

5

ฉันจะบอกว่า lexer และ tokenizer นั้นเป็นสิ่งเดียวกันและพวกเขาทุบข้อความลงในส่วนขององค์ประกอบ ('tokens') parser จะแปลความหมายโทเค็นโดยใช้ไวยากรณ์

ฉันจะไม่เมาค้างกับการใช้คำศัพท์ที่แม่นยำเกินไป - ผู้คนมักใช้ 'การแยกวิเคราะห์' เพื่ออธิบายการกระทำใด ๆ ของการตีความเนื้อความของข้อความ


1
ด้วย PEG parsers ความแตกต่างระหว่าง tokenizer และ parser ก็ชัดเจนน้อยลง
Andre Artus

0

( เพิ่มในคำตอบที่ระบุ )

  • tokenizer จะยังลบความคิดเห็นใด ๆ และมีเพียงกลับราชสกุลเพื่อ Lexer
  • Lexer จะยังกำหนดขอบเขตสำหรับราชสกุลเหล่านั้น (ตัวแปร / ฟังก์ชั่น)
  • Parser จะสร้างโครงสร้างรหัส / โปรแกรม

1
สวัสดี @downvoter คุณช่วยอธิบายได้ไหมว่าทำไมคุณถึง downvote จริงๆ?
Koray Tugay

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

1) ฉันไม่เข้าใจความแตกต่างที่เห็นระหว่าง "lexer" และ "tokenizer" ฉันได้สร้างเครื่องมือแยกวิเคราะห์สำหรับภาษามากกว่า 50 ภาษาและฉันไม่เคยมีกลไกแยกสองอย่างที่แยกข้อความต้นฉบับออกเป็นอะตอมดังนั้นสำหรับฉันนี่เป็นเพียงคำพ้องความหมาย 2) หากคุณกำลังรวบรวมการลบความคิดเห็นและช่องว่างทำให้รู้สึกใน lexer หากคุณกำลังสร้างเครื่องมือการแปลงซอร์สไปยังซอร์สคุณจะไม่สามารถสูญเสียความคิดเห็นได้เนื่องจากจะต้องปรากฏขึ้นอีกครั้งในข้อความที่แปลงแล้ว ดังนั้นการลบความคิดเห็นจึงผิดเสมอ เราสามารถโต้เถียงเกี่ยวกับวิธีการจัดการเพื่อรักษาช่องว่าง ...
Ira Baxter

1
... [เครื่องมือที่ฉันสร้าง (ดูประวัติของฉัน) จับทั้งคู่ด้วยความเที่ยงตรงเพียงพอที่จะทำซ้ำมันในโค้ดที่ถูกแปลง เราดำเนินการต่อไปและจับรูปแบบของอะตอมรวมถึงสิ่งแปลกปลอมเช่นเครื่องหมายคำพูดที่ใช้กับสตริงอักขระและเลขฐาน / นำจำนวนศูนย์นับจากตัวเลขทั้งหมดนี้ให้บริการเพื่อหลีกเลี่ยงผู้ใช้ที่ปฏิเสธผลลัพธ์ที่เปลี่ยนแปลง ดังนั้นสิ่งที่คุณพลาดไม่เพียงทำให้ lexers ไม่จำเป็นต้องดึงข้อมูล แต่ในความเป็นจริงพวกเขาอาจจำเป็นต้องรวบรวมข้อมูลด้านบนและเหนือโทเค็น raw] ....
Ira Baxter

... 3) Lexers เพียงกำหนด "ขอบเขต" ในตัวแยกวิเคราะห์ที่ไม่เหมาะสมอย่างไม่มีหวัง ตัวแยกวิเคราะห์ C และ C ++ เป็นตัวอย่างที่ยอมรับได้; ดูการสนทนาของฉันได้ที่stackoverflow.com/a/1004737/120163 ) ไม่มีใครทำแบบนั้น (น่าเกลียด) ดังนั้นฉันจึงพบคำตอบของคุณเข้าใจผิด
Ira Baxter
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.