gpt4 book ai didi

ruby - 如何使用 Parslet 在 Ruby 中处理 C 风格的注释?

转载 作者:数据小太阳 更新时间:2023-10-29 08:38:19 24 4
gpt4 key购买 nike

Parslet 中的代码示例作为起点自己的创建者(在此 link 中可用)我需要对其进行扩展,以便从以类 C 语法编写的文件中检索所有未注释的文本。

提供的示例能够成功解析 C 风格注释,将这些区域视为常规行空间。但是,这个简单的示例只需要文件的非注释区域中的 'a' 字符,例如输入示例:

         a
// line comment
a a a // line comment
a /* inline comment */ a
/* multiline
comment */

用于检测非注释文本的规则很简单:

   rule(:expression) { (str('a').as(:a) >> spaces).as(:exp) }

因此,我需要的是概括之前的规则以从更通用的文件中获取所有其他(未注释的)文本,例如:

     word0
// line comment
word1 // line comment
phrase /* inline comment */ something
/* multiline
comment */

我是解析表达式语法的新手,我之前的两次尝试都没有成功。

最佳答案

一般的想法是,在序列 ///* 出现之前,一切都是代码(也称为非注释)。你可以用这样的规则来反射(reflect)这一点:

rule(:code) {
(str('/*').absent? >> str('//').absent? >> any).repeat(1).as(:code)
}

正如我在评论中提到的,字符串存在一个小问题。当注释出现在字符串中时,它显然是字符串的一部分。如果您要从代码中删除注释,那么您将改变这段代码的含义。因此,我们必须让解析器知道字符串是什么,里面的任何字符都属于它。另一件事是转义序列。例如字符串 "foo\"bar/*baz*/",它包含一个文字双引号,实际上会被解析为 "foo\",后跟一些再次编写代码。这当然是需要解决的问题。我已经编写了一个完整的解析器来处理上述所有情况:

require 'parslet'

class CommentParser < Parslet::Parser
rule(:eof) {
any.absent?
}

rule(:block_comment_text) {
(str('*/').absent? >> any).repeat.as(:comment)
}

rule(:block_comment) {
str('/*') >> block_comment_text >> str('*/')
}

rule(:line_comment_text) {
(str("\n").absent? >> any).repeat.as(:comment)
}

rule(:line_comment) {
str('//') >> line_comment_text >> (str("\n").present? | eof)
}

rule(:string_text) {
(str('"').absent? >> str('\\').maybe >> any).repeat
}

rule(:string) {
str('"') >> string_text >> str('"')
}

rule(:code_without_strings) {
(str('"').absent? >> str('/*').absent? >> str('//').absent? >> any).repeat(1)
}

rule(:code) {
(code_without_strings | string).repeat(1).as(:code)
}

rule(:code_with_comments) {
(code | block_comment | line_comment).repeat
}

root(:code_with_comments)
end

它将解析你的输入

     word0
// line comment
word1 // line comment
phrase /* inline comment */ something
/* multiline
comment */

到这个 AST

[{:code=>"\n   word0\n "@0},
{:comment=>" line comment"@13},
{:code=>"\n word1 "@26},
{:comment=>" line comment"@37},
{:code=>"\n phrase "@50},
{:comment=>" inline comment "@61},
{:code=>" something \n "@79},
{:comment=>" multiline\n comment "@94},
{:code=>"\n"@116}]

要提取除评论之外的所有内容,您可以执行以下操作:

input = <<-CODE
word0
// line comment
word1 // line comment
phrase /* inline comment */ something
/* multiline
comment */
CODE

ast = CommentParser.new.parse(input)
puts ast.map{|node| node[:code] }.join

会产生

   word0

word1
phrase something

关于ruby - 如何使用 Parslet 在 Ruby 中处理 C 风格的注释?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20985076/

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