Ruby Whittle解析器条件规则激活
我正在使用解析模板语言,并希望匹配规则中未包含的任何内容。我很了解其他模板引擎,但这更多的是一个学术练习,而不是一个生产案例 我遇到的问题是解析器忽略了Ruby Whittle解析器条件规则激活,ruby,regex,parsing,Ruby,Regex,Parsing,我正在使用解析模板语言,并希望匹配规则中未包含的任何内容。我很了解其他模板引擎,但这更多的是一个学术练习,而不是一个生产案例 我遇到的问题是解析器忽略了:id在:raw之上的优先级,仍然在{{之后等待:raw标记 如何告诉解析器不允许在表达式中应用:raw规则,而只允许在表达式中应用:spc规则 解析器代码 class Parser < Whittle::Parser # Skip whitespaces (should not apply in :raw) rule(:s
:id
在:raw
之上的优先级,仍然在{{
之后等待:raw
标记
如何告诉解析器不允许在表达式中应用:raw
规则,而只允许在表达式中应用:spc
规则
解析器代码
class Parser < Whittle::Parser
# Skip whitespaces (should not apply in :raw)
rule(:spc => /\s+/).skip!
# Various delimiters
rule("{{") ^ 4
rule("}}") ^ 4
rule("{%") ^ 4
rule("%}") ^ 4
rule("|") ^ 4
rule("end") ^ 4
# Defines an id (very large match)
rule(:id => /[a-zA-Z_.$<>=!:]+(\((\w+|\s+|,|")+\))?/) ^ 2
# inline tag
rule(:inline) do |r|
r["{{", :inline_head, "}}"].as { |_,id,_| Tag::Inline.new(id) }
end
# inline tag contents
# allows "|" chaining
rule(:inline_head) do |r|
r[:inline_head, "|", :id].as { |head, _, id| head << id }
r[:id].as { |id| [id] }
r[].as { [] }
end
# block tag
rule(:block) do |r|
r["{%", :block_head, "%}", :all, "{%", "end", "%}"].as { |_,head,_,tags,_,_,_|
Tag::Block.new(head, tags)
}
end
# block tag heading
# separates all the keywords
rule(:block_head) do |r|
r[:block_head, :id].as { |head, id| head << id }
#r[:id].as { |id| [id] }
r[].as { [] }
end
# one rule to match them all
rule(:all) do |r|
r[:all,:inline].as { |all, inline| all << inline }
r[:all, :block].as { |all, block| all << block }
r[:all, :raw].as { |all, raw| all << raw }
r[].as { [] }
end
# the everything but tags rule
rule(:raw => /[^\{\}%]+/).as { |text| Tag::Raw.new(text) } ^ 1
# starting rule
start(:all)
end
类解析器/\s+/)。跳过!
#各种分隔符
规则(“{”)^4
规则(“}”)^4
规则(“{%”)^4
规则(“%}”)^4
规则(“|”)^4
规则(“结束”)^4
#定义一个id(非常大的匹配)
规则(:id=>/[a-zA-Z.$=!:]+(\((\w+\s+\s+,“)”+\)?/)^2
#内联标签
规则(:inline)do|r|
r[{{,:inline_head,}}}].as{{{124;},id,{124; Tag::inline.new(id)}
结束
#内联标记内容
#允许“|”链接
规则(:inline_head)do|r|
r[:inline_head,“|”,:id]。作为{head,|,id | head我不认为运算符优先级支持在这里起作用。运算符优先级仅在解决表达式(如foo=6+7
)中的歧义时起作用,其中表达式可以解释为(foo=6)+7
或foo=(6+7)
。赋予非运算符优先级实际上没有任何作用
也许还不清楚解析器的实际功能。它基本上是重复循环的,将所有终端规则与输入字符串匹配。对于找到的规则,它使用最长的一个,并尝试在当前状态下找到一个适合它的规则。因此解析器将始终找到您的空白并丢弃它,因为这是第一个r你的语法有问题
我认为你实际上不想跳过空格,因为它在你的语法中很重要。你想把它包括在你的规则中,这样会使你的语法更加冗长,但(目前)是不可避免的
因此,:raw
变得类似于以下内容,将所有空白和非语法标记吞并到一个字符串中:
rule(:raw => /[^\s\{\}%]+/)
rule(:text) do |r|
r[:text, :raw].as { |text, raw| text << raw }
r[:text, :spc].as { |text, spc| text << spc }
r[:spc]
r[:raw]
end
我一直在考虑如何提供在不同状态下匹配不同令牌的能力,但我担心编写lex/flex的克隆,我认为这太令人困惑了,因此我尝试提出一种方法,使用块在彼此内部嵌套规则来传达状态之间的关系;尽管这并不简单创建一个易于理解的DSL来实现这一点;)我还想提供一个可选的DSL来隐藏用于重复的算法;可能提供一种PEG层来转换为LR解析器。这仍然是一个(非常)young project;)我不认为运算符优先级支持在这里起作用。运算符优先级仅在解决诸如foo=6+7
之类表达式中的歧义时起作用,其中表达式可以解释为(foo=6)+7
或foo=(6+7)
。赋予非运算符优先级实际上没有任何作用
也许还不清楚解析器的实际功能。它基本上是重复循环的,将所有终端规则与输入字符串匹配。对于找到的规则,它使用最长的一个,并尝试在当前状态下找到一个适合它的规则。因此解析器将始终找到您的空白并丢弃它,因为这是第一个r你的语法有问题
我认为你实际上不想跳过空格,因为它在你的语法中很重要。你想把它包括在你的规则中,这样会使你的语法更加冗长,但(目前)是不可避免的
因此,:raw
变得类似于以下内容,将所有空白和非语法标记吞并到一个字符串中:
rule(:raw => /[^\s\{\}%]+/)
rule(:text) do |r|
r[:text, :raw].as { |text, raw| text << raw }
r[:text, :spc].as { |text, spc| text << spc }
r[:spc]
r[:raw]
end
我一直在考虑如何提供在不同状态下匹配不同令牌的能力,但我担心编写lex/flex的克隆,我认为这太令人困惑了,因此我尝试提出一种方法,使用块在彼此内部嵌套规则来传达状态之间的关系;尽管这并不简单创建一个易于理解的DSL来实现这一点;)我还想提供一个可选的DSL来隐藏用于重复的算法;可能提供一种PEG层来转换为LR解析器。这仍然是一个(非常)young project;)Woah来自作者本人!我正在尽快尝试此功能。感谢您在几次调整后解决了我的所有问题。伟大的项目!Woah来自作者本人!我正在尽快尝试此功能。感谢您在几次调整后解决了我的所有问题。伟大的项目!
rule(:all) do |r|
# ... snip ...
r[:all, :text].as { |all, text| all << Tag::Raw.new(text) }
# ... snip ...
end