ตัวแยกวิเคราะห์ CSV ใช้ในปลั๊กอินjquery-csv
มันเป็นตัวแยกวิเคราะห์ไวยากรณ์พื้นฐาน Chomsky Type III
tokenizer ของ regex ใช้ในการประเมินข้อมูลแบบ char-by-char เมื่อพบตัวควบคุมถ่านรหัสจะถูกส่งไปยังคำสั่งสลับเพื่อการประเมินผลเพิ่มเติมตามสถานะเริ่มต้น อักขระที่ไม่ได้ควบคุมจะถูกจัดกลุ่มและคัดลอก en masse เพื่อลดจำนวนการดำเนินการคัดลอกสตริงที่จำเป็น
tokenizer:
var tokenizer = /("|,|\n|\r|[^",\r\n]+)/;
การจับคู่ชุดแรกคืออักขระควบคุม: ตัวคั่นค่า (") ตัวคั่นค่า (,) และตัวคั่นรายการ (การขึ้นบรรทัดใหม่ทั้งหมด) การจับคู่ครั้งสุดท้ายจัดการการจัดกลุ่มถ่านที่ไม่ได้ควบคุม
มีกฎ 10 ข้อที่ parser ต้องเป็นไปตาม:
- กฎ # 1 - หนึ่งรายการต่อบรรทัดแต่ละบรรทัดลงท้ายด้วยขึ้นบรรทัดใหม่
- กฎ # 2 - การขึ้นบรรทัดใหม่ที่ท้ายไฟล์ถูกตัดออก
- กฎ # 3 - แถวแรกมีข้อมูลส่วนหัว
- กฎ # 4 - ช่องว่างถือเป็นข้อมูลและรายการไม่ควรมีเครื่องหมายจุลภาคต่อท้าย
- กฎ # 5 - เส้นอาจหรือไม่ถูกคั่นด้วยเครื่องหมายคำพูดคู่
- กฎ # 6 - ฟิลด์ที่มีตัวแบ่งบรรทัดอัญประกาศคู่และเครื่องหมายจุลภาคควรอยู่ในเครื่องหมายคำพูดคู่
- กฎ # 7 - หากใช้เครื่องหมายอัญประกาศคู่เพื่อใส่เขตข้อมูลดังนั้นเครื่องหมายอัญประกาศคู่ที่ปรากฏภายในเขตข้อมูลจะต้องถูกหลีกเลี่ยงโดยนำหน้าด้วยเครื่องหมายคำพูดคู่อื่น
- การแก้ไข # 1 - ฟิลด์ที่ไม่มีเครื่องหมายอัญประกาศอาจหรืออาจ
- แก้ไข # 2 - ฟิลด์ที่ยกมาอาจหรือไม่
- การแก้ไข # 3 - ฟิลด์สุดท้ายในรายการอาจมีค่า Null หรือไม่ก็ได้
หมายเหตุ: ด้านบน 7 กฎจะได้มาโดยตรงจากIETF RFC 4180 มีการเพิ่ม 3 รายการล่าสุดเพื่อครอบคลุมกรณีขอบที่แนะนำโดยแอปสเปรดชีตที่ทันสมัย (เช่น Excel, Google Spreadsheet) ที่ไม่ได้กำหนดขอบเขต (เช่นอัญประกาศ) ค่าทั้งหมดเป็นค่าเริ่มต้น ฉันลองบริจาคการเปลี่ยนแปลงกลับไปที่ RFC แต่ยังไม่ได้ยินการตอบกลับคำถามของฉัน
เพียงพอกับลมขึ้นนี่คือแผนภาพ:
สหรัฐอเมริกา:
- สถานะเริ่มต้นสำหรับรายการและ / หรือค่า
- พบคำพูดเปิด
- พบคำพูดที่สอง
- พบค่าที่ไม่ยกมา
การเปลี่ยน:
- ตรวจสอบทั้งค่าที่ยกมา (1), ค่าที่ไม่ยกมา (3), ค่า Null (0), รายการ Null (0), และรายการใหม่ (0)
- ข ตรวจสอบถ่านคำพูดที่สอง (2)
- ค ตรวจสอบใบเสนอราคาที่หลบหนี (1), จุดสิ้นสุดของค่า (0), และจุดสิ้นสุดของรายการ (0)
- d ตรวจสอบจุดสิ้นสุดของค่า (0) และจุดสิ้นสุดของรายการ (0)
หมายเหตุ: จริง ๆ แล้วมันไม่มีสถานะ ควรมีบรรทัดจาก 'c' -> 'b' ที่มีสถานะ '1' เนื่องจากตัวคั่นตัวที่สองที่ใช้ค่า Escape หมายความว่าตัวคั่นตัวแรกยังคงเปิดอยู่ ในความเป็นจริงมันอาจจะดีกว่าที่จะแสดงว่ามันเป็นช่วงการเปลี่ยนภาพอื่น การสร้างสิ่งเหล่านี้เป็นศิลปะไม่มีวิธีที่ถูกต้องเพียงอย่างเดียว
หมายเหตุ: นอกจากนี้ยังขาดสถานะออก แต่ในข้อมูลที่ถูกต้องตัวแยกวิเคราะห์จะสิ้นสุดในช่วงการเปลี่ยนภาพ 'a' และไม่มีสถานะใดที่เป็นไปได้เนื่องจากไม่มีสิ่งใดที่จะแยกวิเคราะห์
ความแตกต่างระหว่างรัฐและช่วงการเปลี่ยนภาพ:
รัฐมีขอบเขต จำกัด ซึ่งหมายความว่าสามารถอนุมานได้ว่าหมายถึงสิ่งเดียวเท่านั้น
ช่วงการเปลี่ยนภาพหมายถึงการไหลระหว่างรัฐดังนั้นมันอาจหมายถึงหลายสิ่งหลายอย่าง
โดยพื้นฐานแล้วความสัมพันธ์ของการเปลี่ยนสถานะ -> คือ 1 -> * (เช่นหนึ่งต่อหลายรายการ) รัฐจะกำหนดว่า 'มันคืออะไร' และการเปลี่ยนผ่านจะกำหนด 'วิธีจัดการ'
หมายเหตุ: ไม่ต้องกังวลหากแอปพลิเคชันของสถานะ / ช่วงการเปลี่ยนภาพไม่รู้สึกเป็นธรรมชาติ แต่ก็ไม่ง่าย มันครอบคลุมบางส่วนที่สอดคล้องกับใครบางคนที่ฉลาดกว่าฉันก่อนที่ฉันจะได้แนวคิดในการติด
รหัสหลอก:
csv = // csv input string
// init all state & data
state = 0
value = ""
entry = []
output = []
endOfValue() {
entry.push(value)
value = ""
}
endOfEntry() {
endOfValue()
output.push(entry)
entry = []
}
tokenizer = /("|,|\n|\r|[^",\r\n]+)/gm
// using the match extension of string.replace. string.exec can also be used in a similar manner
csv.replace(tokenizer, function (match) {
switch(state) {
case 0:
if(opening delimiter)
state = 1
break
if(new-line)
endOfEntry()
state = 0
break
if(un-delimited data)
value += match
state = 3
break
case 1:
if(second delimiter encountered)
state = 2
break
if(non-control char data)
value += match
state = 1
break
case 2:
if(escaped delimiter)
state = 1
break
if(separator)
endOfValue()
state = 0
break
if(newline)
endOfEntry()
state = 0
break
case 3:
if(separator)
endOfValue()
state = 0
break
if(newline)
endOfEntry()
state = 0
break
}
}
หมายเหตุ: นี่คือส่วนสำคัญในทางปฏิบัติมีมากขึ้นที่จะต้องพิจารณา ตัวอย่างเช่นการตรวจสอบข้อผิดพลาดค่า Null, บรรทัดว่างต่อท้าย (เช่นที่ถูกต้อง) ฯลฯ
ในกรณีนี้สถานะเป็นเงื่อนไขของสิ่งต่าง ๆ เมื่อบล็อกการจับคู่ regex สิ้นสุดการวนซ้ำ การเปลี่ยนแปลงถูกแสดงเป็นคำสั่ง case
ในฐานะมนุษย์เรามีแนวโน้มที่จะทำให้การปฏิบัติงานระดับต่ำเป็นนามธรรมที่สูงขึ้นได้ง่ายขึ้น แต่การทำงานกับ FSM กำลังทำงานกับการดำเนินงานระดับต่ำ ในขณะที่รัฐและช่วงการเปลี่ยนภาพนั้นง่ายมากที่จะทำงานกับบุคคลมันเป็นเรื่องยากที่จะเห็นภาพรวมทั้งหมดในครั้งเดียว ฉันพบว่ามันง่ายที่สุดในการติดตามแต่ละเส้นทางของการดำเนินการซ้ำไปซ้ำมาจนกว่าฉันจะรู้ได้ว่าการเปลี่ยนภาพนั้นเล่นออกมาได้อย่างไร มันเป็นราชาแห่งการเรียนรู้คณิตศาสตร์ขั้นพื้นฐานคุณจะไม่สามารถประเมินโค้ดจากระดับที่สูงขึ้นจนกว่ารายละเอียดระดับต่ำจะเริ่มเป็นอัตโนมัติ
นอกเหนือจาก: หากคุณดูการใช้งานจริงมีรายละเอียดมากมายที่หายไป ก่อนอื่นเส้นทางที่เป็นไปไม่ได้ทั้งหมดจะส่งข้อยกเว้นเฉพาะ มันเป็นไปไม่ได้ที่จะตีพวกเขา แต่ถ้ามีอะไรผิดพลาดพวกเขาจะก่อให้เกิดข้อยกเว้นอย่างแน่นอนในนักวิ่งทดสอบ ประการที่สองกฎ parser สำหรับสิ่งที่ได้รับอนุญาตในสตริงข้อมูล CSV "ถูกกฎหมาย" จะค่อนข้างหลวมดังนั้นรหัสที่จำเป็นในการจัดการกับกรณีขอบจำนวนมาก นี่เป็นกระบวนการที่ใช้ในการเยาะเย้ย FSM ก่อนการแก้ไขบั๊กส่วนขยายและการปรับแต่งทั้งหมด
เช่นเดียวกับการออกแบบส่วนใหญ่มันไม่ได้เป็นตัวแทนที่แท้จริงของการใช้งาน แต่มันสรุปส่วนที่สำคัญ ในทางปฏิบัติจริง ๆ แล้วมีฟังก์ชันแยกวิเคราะห์ที่แตกต่างกัน 3 ฟังก์ชันที่ได้รับจากการออกแบบนี้: ตัวแยกบรรทัดเฉพาะ csv, ตัวแยกวิเคราะห์บรรทัดเดียวและตัวแยกวิเคราะห์หลายบรรทัดที่สมบูรณ์ พวกเขาทั้งหมดทำงานในลักษณะที่คล้ายกันพวกเขาต่างกันในวิธีที่พวกเขาจัดการกับอักขระขึ้นบรรทัดใหม่