Parsing (几乎)平凡语法的Scala解析器组合

Parsing (几乎)平凡语法的Scala解析器组合,parsing,scala,parser-combinators,Parsing,Scala,Parser Combinators,我一直在尝试为一种(非常)简单的语言制作一个解析器,如下所示: block{you are a cow too blkA{ but maybe not} and so is he} hear me moo blockZ{moooooo} expr -> block -> expr -> text.+ (until all input is consumed) 我可以使用正则表达式将其分解: .*?[^ ]*?\\{ .*?\\} 它基本上会一直吃字符,直到找到与[^]*?

我一直在尝试为一种(非常)简单的语言制作一个解析器,如下所示:

block{you are a cow too blkA{ but maybe not} and so is he} hear me moo blockZ{moooooo}
expr -> block -> expr -> text.+ (until all input is consumed)
我可以使用正则表达式将其分解:

.*?[^ ]*?\\{
.*?\\}
它基本上会一直吃字符,直到找到与
[^]*?\{
\}
匹配的东西:一个块的开始或结束。我的问题是,如果我想使用Scala的解析器组合器,我该怎么做?我目前有:

   def expr: Parser[Any] = (block | text)+
   def text = ".+?".r
   def block = "[^ ]*?\\{".r ~ expr ~ "}"
但这不起作用:

parsed: List(b, l, o, c, k, {, y, o, u, a, r, e, a, c, o, w, t, o, o, b, l, k, A, {, b, u, t, m, a, y, b, e, n, o, t, }, a, n, d, s, o, i, s, h, e, }, h, e, a, r, m, e, m, o, o)
似乎
解析器没有被触发,因此
文本
解析器被反复触发。但是当我删除
文本
解析器时:

   def expr: Parser[Any] = (block)+
我得到:

failure: string matching regex `[^ ]*?\{' expected but `y' found

block{you are a cow too blkA{ but maybe not} and so is he} hear me moo  
      ^
因此,显然
解析器确实可以工作,除非
文本
解析器存在。发生了什么事?对于如此基本的语法,有没有一种“适当”的方法来做到这一点

编辑:更改了标题,因为它不再是关于不情愿,而只是解决问题

编辑:我现在有这个:

def expr: Parser[Any] = (block | text)+

def text = "[^\\}]".r

def block = "[^ ]*?\\{".r ~ expr ~ "}"
这背后的逻辑是,对于每个字符,它都会测试它是否是块的开头。如果不是,它将移动到下一个角色。这给了我:

parsed: List(((block{~List(y, o, u, a, r, e, a, c, o, w, t, o, o, ((blkA{~List(b, u, t, m, a, y, b, e, n, o, t))~}), a, n, d, s, o, i, s, h, e))~}), h, e, a, r, m, e, m, o, o)

这有点正确。但是,它正在逐个解析非块字符,这可能是一个性能问题(我想是吧?)。有没有办法一次解析所有这些非块字符并将它们保留在一个大字符串中?

问题是
文本
正在使用所有的右大括号(
}
)。事情是这样的:

block{you are a cow too blkA{ but maybe not} and so is he} hear me moo blockZ{moooooo}
expr -> block -> expr -> text.+ (until all input is consumed)
此时,它退出
expr
,并尝试解析不存在的
}
,失败后返回到第一个
expr
上的
文本


您可以使用
log
查看解析时发生了什么。

这就引出了一个问题:如何才能阻止
text
吃掉我的结束语
}
?就像在正则表达式中一样,我可以匹配
+?[^]*?\{
+?\}
来获取所有文本,直到下一个打开块或关闭块符号,但在PC库中没有
+?
(据我所知)。有没有其他方法可以达到同样的效果?@LiHaoyi好吧,
.*.
相当于
+?
,但是为什么不干脆做
[^{}]+
?如果你有嵌套的大括号,你需要将
text
转换成递归解析器,而不是正则表达式——正则表达式不处理递归。请不要向现有问题添加新问题。当然,要加强,但要针对新问题提出新问题。它一个接一个地解析,因为你使用了一个非贪婪的星。不要贪心了。