我正在编写一个需要接受非结构化输入的解析器。我的意思是它需要接收一个原始信号(在本例中是文本)并在累积非信号文本的同时寻找有意义的字符序列。

例如,给定以下输入:

Hello! I am a block of noisy text. This is a \symbol significant symbol \end and the surrounding is not.

我应该可以分析出 \symbol ... \end 字符,同时仍在收集周围的文本。

我使用了一个解析器组合器库来完成这个任务,但是我怀疑这个用例与大多数parse组合器libs所构建的用例是不同的。大多数用例涉及一个完全已知的结构化域(电话号码、电子邮件地址、编程语言)。解析器将一组基于封闭域的规则应用于输入,并对在该域之外遇到的所有内容抛出错误。然而,我的案例(理想情况下)要求接受声明域之外的所有内容。

我之所以说理想化,是因为显然有一种方法可以使用标准的解析器组合器来完成我的工作:

# pseudo code:
symbol_start = word("\symbol")
symbol_end = word("\end")
word = many(char())
between_sym = between(symbol_start(), symbol_end())
any_text = many(word() + or(space(), word(), punctuation()) + between_sym()

我可以使用一组解析器声明英语的整个域。然而,我发现这是一个冗长而脆弱的过程——最终解析器的稳定性充其量是令人怀疑的。我更愿意允许积累原始的、嘈杂的文本并解析其中的符号:

# pseudo code
symbol_start = word("\symbol")
symbol_end = word("\end")
any_text = any_char() + between(symbol_start(), symbol_end())

这是一种新的问题吗?还是我攻击的方式不对?

最佳回复

大多数组合符允许某种排除类型的解析器:"接受除\"之外的所有字符"

然后就可以很直接地创建这样一个东西:您的开始/结束是一个解析器,"其他的一切"是另一个,组合在一起 zero-or-more(either()) 某种构造。

如果需要嵌套开始/结束符号,则可能会出现此问题。一旦你需要开始做像计算括号这样的事情,你就会进入上下文相关的语言,这些语言通常不会被简单的组合器很好地处理。