文法デバッガーを使用すると、エンジンが文字列を解析する方法を正確に確認できます。失敗は正常で予期されるものです。たとえば、a+b*
文字列との一致が考えられますaab
。'a'の2つの一致が表示され、その後に失敗します(b
isでないためa
)が、再試行しb
て正常に一致します。
これは、||
(順序を強制する)を交互に実行すると、より簡単に確認できます。あなたが持っている場合
token TOP { I have a <fruit> }
token fruit { apple || orange || kiwi }
「I have a kiwi」という文を解析すると、最初に「I have a」と一致し、次に「apple」と「orange」で2つ失敗し、最後に「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> ]
できます。これは、常に持っていると、それらの1つが未定義になり、アクションクラスでの処理が少し面倒になる可能性があるためです。あなたは試すことができます:
grammar test {
rule TOP { <score> + }
token score { <letter> + }
proto token letter { * }
token letter:uc { <[A..G]> }
token letter:lc { <[a..g]> }
}
$<letter>
常にこのように定義されます。