gpt4 book ai didi

scala - 如何将解析器与不同类型的 Elem 结合使用

转载 作者:行者123 更新时间:2023-12-01 01:11:10 24 4
gpt4 key购买 nike

我正在尝试创建一个结合了 Regex 解析器和我拥有的自定义解析器的解析器。我看过 Scala: How to combine parser combinators from different objects ,但该问题和答案涉及具有相同类型的解析器 Elem .

假设我有一些 RegexParsers,还有一个用于查找字符串的解析器:

trait NumbersParsers extends RegexParsers {
def number = """\d+""".r
}

trait LookupParsers extends Parsers {
type Elem = String
def word = elem("word", (potential:String) => dictionary.exists(_.equals(x))
}

如果我天真地结合这些解析器
object MyParser extends NumbersParsers with RegexParsers {
def quantitive = number ~ word
}

由于 Elem 的不同类型,我显然会遇到类型错误.我如何组合这些解析器?

最佳答案

既然问了又回答了Scala: How to combine parser combinators from different objects我觉得有点责任回答这个问题.

快速回答是,您不能组合不同类型的 Elem .解决此问题的另一种优雅方式使用 ^?用额外的过滤来增加正则表达式解析器。

阅读 Combinator Parsing 可能会有所帮助在 Scala 编程中:

Parser Input

Sometimes, a parser reads a stream of tokens instead of a raw sequence of characters. A separate lexical analyzer is then used to convert a stream of raw characters into a stream of tokens. The type of parser inputs is defined as follows:

type Input = Reader[Elem]   

The class Reader comes from the package scala.util.parsing.input. It is similar to a Stream, but also keeps track of the positions of all the elements it reads. The type Elem represents individual input elements. It is an abstract type member of the Parsers trait:

type Elem

This means that subclasses and subtraits of Parsers need to instantiate class Elem to the type of input elements that are being parsed. For instance, RegexParsers and JavaTokenParsers fix Elem to be equal to Char.



所以 Elem由词法分析器使用,它负责将您的输入流分成解析器想要处理的最小可能的标记。既然要处理正则表达式,你的 ElemChar .

不过别担心。仅仅因为你的词法分析器给了你 Char s 这并不意味着您的解析器也被它们困住了。什么 RegexParsers给你一个从正则表达式到 Parser[String] 的隐式转换器.您可以使用 ^^ 进一步转换它们运算符(完全映射输入)和 ^?运算符(部分映射输入)。

让我们将它们合并到您的解析器中:
import scala.util.parsing.combinator._

scala> val dictionary = Map("Foo" -> "x")
dictionary: scala.collection.immutable.Map[String,String] = Map(Foo -> x)

scala> trait NumbersParsers extends RegexParsers {
| def number: Parser[Int] = """\d+""".r ^^ { _.toInt }
| }
defined trait NumbersParsers

scala> trait LookupParsers extends RegexParsers {
| def token: Parser[String] = """\w+""".r
| def word =
| token ^? ({
| case x if dictionary.contains(x) => x
| }, {
| case s => s + " is not found in the dictionary!"
| })
| }
defined trait LookupParsers

scala> object MyParser extends NumbersParsers with LookupParsers {
| def quantitive = number ~ word
|
| def main(args: Array[String]) {
| println(parseAll(quantitive, args(0) ))
| }
| }
defined module MyParser

scala> MyParser.main(Array("1 Foo"))
[1.6] parsed: (1~Foo)

scala> MyParser.main(Array("Foo"))
[1.1] failure: string matching regex `\d+' expected but `F' found

Foo
^

scala> MyParser.main(Array("2 Bar"))
[1.6] failure: Bar is not found in the dictionary!

2 Bar
^

关于scala - 如何将解析器与不同类型的 Elem 结合使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15458666/

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