gpt4 book ai didi

regex - Perl 6 语法与我认为的不匹配

转载 作者:行者123 更新时间:2023-12-04 14:09:02 24 4
gpt4 key购买 nike

我在做Advent of Code day 9 :

You sit for a while and record part of the stream (your puzzle input). The characters represent groups - sequences that begin with { and end with }. Within a group, there are zero or more other things, separated by commas: either another group or garbage. Since groups can contain other groups, a } only closes the most-recently-opened unclosed group - that is, they are nestable. Your puzzle input represents a single, large group which itself contains many smaller ones.

Sometimes, instead of a group, you will find garbage. Garbage begins with < and ends with >. Between those angle brackets, almost any character can appear, including { and }. Within garbage, < has no special meaning.

In a futile attempt to clean up the garbage, some program has canceled some of the characters within it using !: inside garbage, any character that comes after ! should be ignored, including <, >, and even another !.


当然,这对 Perl 6 语法大呼小叫……
grammar Stream
{
rule TOP { ^ <group> $ }

rule group { '{' [ <group> || <garbage> ]* % ',' '}' }
rule garbage { '<' [ <garbchar> | <garbignore> ]* '>' }

token garbignore { '!' . }
token garbchar { <-[ !> ]> }
}
这在简单的例子上似乎工作得很好,但在两个 garbchar 上却出错了。连续:
say Stream.parse('{<aa>}');
Nil . Grammar::Tracer没有帮助:
TOP
| group
| | group
| | * FAIL
| | garbage
| | | garbchar
| | | * MATCH "a"
| | * FAIL
| * FAIL
* FAIL
Nil
多个 garbignore s没有问题:
say Stream.parse('{<!!a!a>}');
给出:
「{<!!a!a>}」
group => 「{<!!a!a>}」
garbage => 「<!!a!a>」
garbignore => 「!!」
garbchar => 「a」
garbignore => 「!a」
有任何想法吗?

最佳答案

UPD 鉴于代码问题的出现没有提到空格,您不应该使用 rule完全构建。只需切换所有rule转至 token s,你应该被设置。一般来说,遵循 Brad 的建议——使用 token除非你知道你需要一个 rule (下面讨论)或 regex (如果您需要回溯)。

我在下面的原始答案探讨了为什么 rule没有工作。我暂时把它留在那里。

TL;博士 <garbchar> |包含一个空格。紧跟在任何 atom 后面的空格在 rule表示标记化中断。你可以简单地删除这个不合适的空间,即写 <garbchar>|相反(或者更好,<.garbchar>|,如果您不需要捕获垃圾)以获得您想要的结果。

正如您最初的问题所允许的那样,这不是错误,只是您的心理模型已关闭。
您的回答正确识别了问题:tokenization .
所以我们剩下的是你的后续问题,这是关于你的标记化心理模型,或者至少 Perl 6 默认情况下如何标记化:

why ... my second example ... goes wrong with two garbchars in a row:

'{<aa>}'
简单地说,问题是如何将其标记化:
aa
简单的高级答案是,在解析白话时, aa通常将被视为一个标记,而不是两个,并且默认情况下,Perl 6 假定此普通定义。这就是您遇到的问题。
您可以否决这个普通定义以获得您想要实现的任何标记化结果。但是很少有必要这样做,而且在这种简单的情况下肯定不是这样。
我将提供两条多余的路径,希望可以引导人们找到正确的心智模型:
  • 对于那些喜欢直接深入细节的人,有 a reddit comment I wrote recently about tokenization in Perl 6 .
  • 这个 SO 答案的其余部分提供了一个高层次的讨论,补充了我在 reddit 评论中的低层次解释。

  • 摘自 the "Obstacles" section of the wikipedia page on tokenization ,并将摘录与 P6 的具体讨论交织在一起:

    Typically, tokenization occurs at the word level. However, it is sometimes difficult to define what is meant by a "word". Often a tokenizer relies on simple heuristics, for example:

    • Punctuation and whitespace may or may not be included in the resulting list of tokens.

    在 Perl 6 中,您可以使用与标记化正交的捕获功能来控制解析树中包含或不包含的内容。
    • All contiguous strings of alphabetic characters are part of one token; likewise with numbers.

    • Tokens are separated by whitespace characters, such as a space or line break, or by punctuation characters.


    默认情况下,Perl 6 设计体现了这两种启发式方法的等效项。
    要获得的关键是它是 rule处理一串标记的构造,复数。 token构造用于定义每个调用的单个 token 。
    我想我会在这里结束我的回答,因为它已经很长了。请使用评论帮助我们改进此答案。我希望我到目前为止所写的内容有所帮助。

    关于regex - Perl 6 语法与我认为的不匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47728466/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com