EOS에서 Raku 문법 중지 (문자열 끝)


9

Raku DSL 기능을 배우기위한 변명으로 한 음악 언어의 번역자를 다른 언어로 번역하는 과정에서 (ABC에서 Alda로), 나는 .parse! 단축 된 데모 코드는 다음과 같습니다.

#!/home/hsmyers/rakudo741/bin/perl6
use v6d;

# use Grammar::Debugger;
use Grammar::Tracer;

my $test-n01 = q:to/EOS/;
a b c d e f g
A B C D E F G
EOS

grammar test {
  token TOP { <score>+ }
  token score {
      <.ws>?
      [
          | <uc>
          | <lc>
      ]+
      <.ws>?
  }
  token uc { <[A..G]> }
  token lc { <[a..g]> }
}

test.parse($test-n01).say;

그리고 그것은 내 문제를 보여주는 Grammer :: Tracer 디스플레이의 마지막 부분입니다.

|  score
|  |  uc
|  |  * MATCH "G"
|  * MATCH "G\n"
|  score
|  * FAIL
* MATCH "a b c d e f g\nA B C D E F G\n"
「a b c d e f g
A B C D E F G
」

두 번째 줄에서 마지막 줄에 FAIL이라는 단어는 .parse 실행이 종료 될 방법이 없음을 나타냅니다. 이것이 올바른지 궁금합니다. .say는 모든 것을 표시해야하므로 FAIL이 얼마나 실제적인지 잘 모르겠습니다. "오류없이 여러 줄을 구문 분석하는 문법을 올바르게 작성하려면 어떻게해야합니까?"


나는 당신의 학습 과정을 방해하고 싶지 않지만, 당신이 모르는 경우에 대비하여 ABC 모듈이 있습니다.
raiph

1
글쎄, 적어도 우리는 같은 곡을 테스트하지 않았습니다!
hsmyers

답변:


10

문법 디버거를 사용하면 엔진이 문자열을 구문 분석하는 방식을 정확하게 볼 수 있습니다. 실패는 정상이며 예상되는 것입니다. 예를 들어 a+b*string과 일치하는 것으로 간주 aab됩니다. 'a'에 대해 두 개의 일치 항목을 가져오고 실패한 경우 ( bis 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> 항상 이런 식으로 정의됩니다.


이것은 일치 객체가 'FAIL'과 함께 '그렇게 참'을 반환했다는 사실을 설명합니다. 나는 그럴지도 모른다고 생각했다. 실제 프로젝트에 필요한 토큰을 추가하는 단계로 돌아가겠습니다.)
hsmyers

실제 문법은 <.ws> *를 자동으로 삽입하는 것을 좋아하지 않습니다. <score> 이외의 추가 계층으로 인해 발생했을 수 있습니다. 프로토 타입 사용에 대한 제안은 기술을 머릿속에 감쌀 수있게 되 자마자 좋아 보인다…
hsmyers


필자가 필요로하지 않는 코드를 가지고있는 것을 싫어한다. 더 많은 디버그를해야한다. 실제 문제는 ABC가 공백에 대해 망설이지 않는다는 것입니다. 몇 가지 예외가 있지만 대체로 거의 모든 곳에서 발생할 수 있습니다. '사용'사례는 큰 숫자 문자열의 쉼표와 같은 가독성 문제입니다. 문제를 이해하고이를 최소화 할 때까지 필요에 따라 문제를 다시 방문 할 것입니다.
hsmyers

1
hsmyers : 고맙게도 이해 proto하는 것은 그리 어렵지 않으며, 일단 숙취 하면 인생이 훨씬 쉬워집니다.
user0721090601
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.