문법 디버거를 사용하면 엔진이 문자열을 구문 분석하는 방식을 정확하게 볼 수 있습니다. 실패는 정상이며 예상되는 것입니다. 예를 들어 a+b*
string과 일치하는 것으로 간주 aab
됩니다. 'a'에 대해 두 개의 일치 항목을 가져오고 실패한 경우 ( b
is not not a
) 다시 시도 b
하고 성공적으로 일치시킵니다.
||
(순서를 시행 하는)로 교체하면 더 쉽게 볼 수 있습니다 . 당신이 가지고 있다면
token TOP { I have a <fruit> }
token fruit { apple || orange || kiwi }
"I 키위가 있습니다"라는 문장을 구문 분석하면 먼저 "I have a"와 일치하고 "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에 대한 프로토 토큰을 추가하고 싶을 수도 있습니다. 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>
항상 이런 식으로 정의됩니다.