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.