我可以在parboiled2解析器中动态生成规则吗?用例是我已经定义了一堆规则,但是每次添加规则时都想添加更多而不是编译。
答案 0 :(得分:2)
如果你想在运行时生成规则(就像在Parboiled1中那样),那是不可能的。 Parboiled 2使用的是marco exressions,因此您无法在运行时生成规则。所有的事情都发生在编译阶段。
如果您有许多已定义的规则,并且希望以任意顺序组合它们,即使其中一些缺失也是如此。这是可能的。我做到了。
有两种已知选项,如何实现这一目标:
第一个选项(我尚未尝试)被称为DynamicRuleDispatch
,您可以在documentation中找到它并查看它的测试here。
第二个选项是手动执行调度(正如我所做的那样)。
您应该创建一组可以动态组合的规则。
这些规则必须具有Rule0类型。它们不应该影响值堆栈。
在规则评估之后,为这些规则添加副作用。副作用操作必须将捕获的数据保存在解析器状态中的某个位置。您应该使用capture
+ ~
+ run
捆绑来实现此目的,请查看以下示例:
def RuleWithSideEffect = rule { capture(EmailAddress)~run {address:String => saveItSomewhere(地址) } ~EOI
您需要在解析器中创建某种可变状态。保存解析结果的保存位置。它可以是hashmap。此Hashmap应存储所有可能的规则及其值。您不能使用值堆栈,因为您没有确定数量的匹配规则。 保持可变状态时要小心。每次通话后都必须清洁。
您需要一种规则对齐格式来对齐规则。 例如:
class Parser(输入:ParserInput,format:String)扩展Parser ....
然后你需要解析格式字符串并获取格式标记。
使用模式匹配将相应格式标记的列表分发给
下面的Rule0字段dispatchRule
方法。然后将字符串标记列表映射到规则。
如果您有规则列表,则需要执行以下操作:
// concatenates two rules. Must be inside rule block
def concatRules(f: Rule0, s: Rule0): Rule0 = rule {
f ~ s
}
val rootRule =
stringTokens map dispatchRule reduce concatRules
def RootRule: Rule0 = rule { mainRule ~ EOI }
def dispatchRule(token: String): Rule0 = match token {
case "DATE" => DateParser.DateRule
....
}
您可以通过在解析器构造函数中使用logformat来解析generater访问日志。因此,您需要一种数据模型来规范规则。