เมื่อคุณใช้ดีบักเกอร์ไวยากรณ์จะช่วยให้คุณเห็นได้อย่างชัดเจนว่าเอ็นจิ้นวิเคราะห์สตริงอย่างไร - ล้มเหลวเป็นปกติและคาดว่า การพิจารณาเช่นการจับคู่กับสตริงa+b*
aab
คุณควรได้รับการจับคู่สองตัวสำหรับ 'a' แล้วตามด้วยการล้มเหลว (เพราะb
ไม่ใช่a
) แต่จากนั้นจะลองอีกครั้งb
และจับคู่สำเร็จ
สิ่งนี้อาจเห็นได้ง่ายขึ้นหากคุณทำการสลับกับ||
(ซึ่งบังคับให้ลำดับ) ถ้าคุณมี
token TOP { I have a <fruit> }
token fruit { apple || orange || kiwi }
และคุณแยกประโยค "ฉันมีกีวี" คุณจะเห็นมันตรงกับครั้งแรก "ฉันมี" ตามด้วยสองล้มเหลวด้วย "แอปเปิ้ล" และ "ส้ม" และในที่สุดก็ตรงกับ "กีวี"
ตอนนี้เรามาดูกรณีของคุณ:
TOP # Trying to match top (need >1 match of score)
| score # Trying to match score (need >1 match of lc/uc)
| | lc # Trying to match lc
| | * MATCH "a" # lc had a successful match! ("a")
| * MATCH "a " # and as a result so did score! ("a ")
| score # Trying to match score again (because <score>+)
| | lc # Trying to match lc
| | * MATCH "b" # lc had a successful match! ("b")
| * MATCH "b " # and as a result so did score! ("b ")
…………… # …so forth and so on until…
| score # Trying to match score again (because <score>+)
| | uc # Trying to match uc
| | * MATCH "G" # uc had a successful match! ("G")
| * MATCH "G\n" # and as a result, so did score! ("G\n")
| score # Trying to match *score* again (because <score>+)
| * FAIL # failed to match score, because no lc/uc.
|
| # <-------------- At this point, the question is, did TOP match?
| # Remember, TOP is <score>+, so we match TOP if there
| # was at least one <score> token that matched, there was so...
|
* MATCH "a b c d e f g\nA B C D E F G\n" # this is the TOP match
ความล้มเหลวที่นี่เป็นเรื่องปกติ: ในบางครั้งเราจะหมด<score>
โทเค็นดังนั้นความล้มเหลวจึงหลีกเลี่ยงไม่ได้ เมื่อสิ่งนั้นเกิดขึ้นเอ็นจินไวยากรณ์สามารถย้ายไปยังสิ่งใดก็ตามที่<score>+
อยู่ในไวยากรณ์ของคุณ เนื่องจากไม่มีสิ่งใดเลยความล้มเหลวจึงส่งผลให้เกิดการจับคู่ของสตริงทั้งหมด (เนื่องจากTOP
ตรงกันกับโดยนัย/^…$/
)
นอกจากนี้คุณอาจลองเขียนไวยากรณ์ของคุณใหม่ด้วยกฎที่แทรก <.ws> * โดยอัตโนมัติ (เว้นแต่ว่ามันสำคัญที่จะต้องมีพื้นที่เดียวเท่านั้น):
grammar test {
rule TOP { <score>+ }
token score {
[
| <uc>
| <lc>
]+
}
token uc { <[A..G]> }
token lc { <[a..g]> }
}
นอกจากนี้ IME คุณอาจต้องการเพิ่มโทเค็นโปรโตสำหรับ uc / lc เพราะเมื่อคุณมี[ <foo> | <bar> ]
คุณจะมีหนึ่งในนั้นไม่ได้กำหนดซึ่งสามารถทำให้การประมวลผลในระดับการกระทำที่น่ารำคาญเล็กน้อย คุณสามารถลอง:
grammar test {
rule TOP { <score> + }
token score { <letter> + }
proto token letter { * }
token letter:uc { <[A..G]> }
token letter:lc { <[a..g]> }
}
$<letter>
จะถูกกำหนดด้วยวิธีนี้เสมอ