grammar - 乐语法 : Use named regex without consuming matching string

标签 grammar raku

我有一个可能很容易回答 Raku 语法问题。我不会解析日志文件并通过日志条目取回条目日志条目。日志条目可以只是一行或多行字符串。

我的草稿代码如下所示:

grammar Grammar::Entries {
    rule TOP { <logentries>+ }

    token logentries { <loglevel> <logentry> }
    token loglevel { 'DEBUG' | 'WARN' | 'INFO ' | 'ERROR' }
    token logentry { .*? <.finish> }
    token finish { <.loglevel> || $ }
}

这仅适用于第一行,因为在第二行中日志级别被第一行匹配消耗,尽管我使用了 '.'在正则表达式 <> 中,据我所知意味着非捕获。

以下是日志示例:
INFO    2020-01-22T11:07:38Z    PID[8528]   TID[6736]:  Current process-name: C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
INFO    2020-01-22T11:07:38Z    PID[8528]   TID[6736]:  Session data:
    PID: 1234
    TID: 1234
    Session: 1
INFO    2020-01-22T11:07:38Z    PID[8528]   TID[6736]:  Clean up.

即使对于多行日志条目,恢复日志条目的正确方法是什么?
谢谢!

最佳答案

.*?有效但效率低下。
它必须做很多回溯。

要改进它,您可以使用 \N*它匹配除换行符之外的所有内容。

grammar Grammar::Entries {
    rule TOP { <logentries>+ }

    token logentries { <loglevel> <logentry> }
    token loglevel { 'DEBUG' | 'WARN' | 'INFO' | 'ERROR' }
    token logentry { \N* \n }
}

然后您必须重新添加换行符匹配。

    token logentry {
      <logline>* %% \n
    }
    token logline { <!before \w> \N* }

这会起作用,但它仍然不是很好。

我会更像你试图解析的东西来构建语法。

grammar Grammar::Entries {
    token TOP { <logentries>+ }

    token logentries { <loglevel> <logentry> }
    token loglevel { 'DEBUG' | 'WARN' | 'INFO' | 'ERROR' }
    token logentry { <logline>* }
    token logline { '    ' <(\N+)> \n? }
}

由于我注意到日志行总是以 4 个空格开头,我们可以使用它来确保只有以 4 个空格开头的行才算作 logline .这也处理带有日志级别的行上的剩余数据。

我真的不喜欢你有一个复数名称只匹配一件事的标记。
基本上我会命名 logentrieslogentry .当然这意味着logentry也需要改名。

grammar Grammar::Entries {
    token TOP { <logentry>+ }

    token logentry { <loglevel> <logdata> }
    token loglevel { 'DEBUG' | 'WARN' | 'INFO' | 'ERROR' }
    token logdata { <logline>* }
    token logline { '    ' <(\N+)> \n? }
}

我也不喜欢多余的 log附加到每个 token 。

grammar Grammar::Entries {
    token TOP { <entry>+ }

    token entry { <level> <data> }
    token level { 'DEBUG' | 'WARN' | 'INFO' | 'ERROR' }
    token data { <line>* }
    token line { '    ' <(\N+)> \n? }
}

所以这意味着一个 Grammar::Entries至少包含一个 entry .
entrylevel 开头, 并以一些 data 结尾.data由任意数量的 line 组成秒
一个 line以四个空格开头,至少一个非换行符,并且可能以换行符结尾。

我试图提出的观点是按照与数据结构相同的方式来构建语法。

您甚至可以添加用于提取信息的结构,这样您就不必将其作为第二步。

关于grammar - 乐语法 : Use named regex without consuming matching string,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61954735/

相关文章:

sockets - perl6 IO::Socket::INET 与去年相比的变化以及违背的 promise

java - Java 语言的语法描述

unicode - Perl 6 将如何处理新的组合表情符号长度?

raku - 为什么在 Perl 6 REPL 中 if False 产生一个空列表之后的命令?

concurrency - 点击 IO::Notifications 时出现错误 "emit without supply or react"

arrays - 结构数组作为Perl 6 NativeCall结构的属性

parsing - 如何手工计算FIRST集

javascript - JavaCC中如何实现JavaScript自动插入分号?

assembly - ARM 统一汇编语言语法和解析器?

java - 需要帮助编译 ANTLR 语法文件