scala组合分析器以保持原始输入
我想从另一个解析器组成一个解析器,将使用的输入作为ast构造的参数 说我有scala组合分析器以保持原始输入,scala,parser-combinators,Scala,Parser Combinators,我想从另一个解析器组成一个解析器,将使用的输入作为ast构造的参数 说我有 def ingredient = amount ~ nameOfIngredient ^^ { case amount ~ name => Ingredient(name, amount) } 我要寻找的是一种让另一个解析器构造以下元素的方法: case class RecipeRow(orginalText: String, ingredient: Ingredient) 因此,我正在寻找一种方法,在合成
def ingredient = amount ~ nameOfIngredient ^^ {
case amount ~ name => Ingredient(name, amount)
}
我要寻找的是一种让另一个解析器构造以下元素的方法:
case class RecipeRow(orginalText: String, ingredient: Ingredient)
因此,我正在寻找一种方法,在合成中检索解析器的原始消耗输入。可能是这样的:
def recipeRow = ingredient withConsumedInput ^^ {
case (amount ~ name, consumed) => RecipeRow(consumed, Ingredient(name, amount))
}
我猜这种情况下的签名是:
def withConsumedInput [U](p: => Parser[U]): Parser[(U, String)]
有没有其他简单的方法来得到我想要的东西,或者我需要写那个东西?感觉这可能是一种更好的方式…实际上并不容易
让我们从解析器开始:它能给我们什么?嗯,Parser
扩展了Input=>ParseResult
,因此我们必须从其中任何一个提取信息
类型Input
是RegexParsers
上的别名,用于scala.util.parsing.Input.Reader[Char]
。除非它恰好是字符序列
的读取器
,在这种情况下,我们可以使用源代码
和偏移量
。那我们就用这个吧
现在,ParseResult
有许多子类,但我们只对Success
感兴趣,它有一个next:Input
字段。利用这一点,我们可以尝试以下方法:
def withConsumedInput [U](p: => Parser[U]): Parser[(U, String)] = new Parser[(U, String)] {
def apply(in: Input) = p(in) match {
case Success(result, next) =>
val parsedString = in.source.subSequence(in.offset, next.offset).toString
Success(result -> parsedString, next)
case other: NoSuccess => other
}
}
不过,它将捕获任何跳过的空白。您可以对其进行调整以自动避免:
def withConsumedInput [U](p: => Parser[U]): Parser[(U, String)] = new Parser[(U, String)] {
def apply(in: Input) = p(in) match {
case Success(result, next) =>
val parsedString = in.source.subSequence(handleWhiteSpace(in.source, in.offset), next.offset).toString
Success(result -> parsedString, next)
case other: NoSuccess => other
}
}
其实不容易
让我们从解析器开始:它能给我们什么?嗯,Parser
扩展了Input=>ParseResult
,因此我们必须从其中任何一个提取信息
类型Input
是RegexParsers
上的别名,用于scala.util.parsing.Input.Reader[Char]
。除非它恰好是字符序列
的读取器
,在这种情况下,我们可以使用源代码
和偏移量
。那我们就用这个吧
现在,ParseResult
有许多子类,但我们只对Success
感兴趣,它有一个next:Input
字段。利用这一点,我们可以尝试以下方法:
def withConsumedInput [U](p: => Parser[U]): Parser[(U, String)] = new Parser[(U, String)] {
def apply(in: Input) = p(in) match {
case Success(result, next) =>
val parsedString = in.source.subSequence(in.offset, next.offset).toString
Success(result -> parsedString, next)
case other: NoSuccess => other
}
}
不过,它将捕获任何跳过的空白。您可以对其进行调整以自动避免:
def withConsumedInput [U](p: => Parser[U]): Parser[(U, String)] = new Parser[(U, String)] {
def apply(in: Input) = p(in) match {
case Success(result, next) =>
val parsedString = in.source.subSequence(handleWhiteSpace(in.source, in.offset), next.offset).toString
Success(result -> parsedString, next)
case other: NoSuccess => other
}
}
这对你有用吗?不,我看不出来。这对你有用吗?不,我看不出来。