gpt4 book ai didi

parsing - 在 StandardTokenParsers 中使用正则表达式

转载 作者:行者123 更新时间:2023-12-02 17:52:46 24 4
gpt4 key购买 nike

我正在尝试在基于 StandardTokenParsers 的解析器中使用正则表达式。为此,我将 StdLexical 进行了子类化,如下所示:

class CustomLexical extends StdLexical{
def regex(r: Regex): Parser[String] = new Parser[String] {
def apply(in:Input) = r.findPrefixMatchOf(in.source.subSequence(in.offset, in.source.length)) match {
case Some(matched) => Success(in.source.subSequence(in.offset, in.offset + matched.end).toString,
in.drop(matched.end))
case None => Failure("string matching regex `" + r + "' expected but " + in.first + " found", in)
}
}

override def token: Parser[Token] =
( regex("[a-zA-Z]:\\\\[\\w\\\\?]* | /[\\w/]*".r) ^^ { StringLit(_) }
| identChar ~ rep( identChar | digit ) ^^ { case first ~ rest => processIdent(first :: rest mkString "") }
| ...

但是我对如何定义利用这一点的解析器有点困惑。我有一个解析器定义为:

def mTargetFolder: Parser[String] = "TargetFolder" ~> "=" ~> mFilePath

应用于识别有效的文件路径。我当时尝试过:

def mFilePath: Parser[String] = "[a-zA-Z]:\\\\[\\w\\\\?]* | /[\\w/]*".r

但这显然是不对的。我收到错误:

scala: type mismatch;
found : scala.util.matching.Regex
required: McfpDSL.this.Parser[String]
def mFilePath: Parser[String] = "[a-zA-Z]:\\\\[\\w\\\\?]* | /[\\w/]*".r
^

使用 StdLexical 子类上的扩展的正确方法是什么?

最佳答案

如果您确实想使用基于标记的解析,并重用 StdLexical,我建议更新“TargetFolder”的语法,以便等号后面的值是正确的字符串文字。或者换句话说,使路径应该用引号引起来。从那时起,您不再需要扩展 StdLexical。

然后就是将正则表达式转换为解析器的问题。 Scala 已经有 RegexParsers为此(它隐式地将 regexp 转换为 Parser[String] ),但不幸的是这不是您想要的,因为它适用于 Char 的流。 ( type Elem = CharRegexParsers )当您处理 token 流时。因此,我们确实必须定义自己的从 Regex 到 Parser[String] 的转换。 (但在句法级别而不是词汇级别,或者换句话说在标记解析器中)。

import scala.util.parsing.combinator.syntactical._
import scala.util.matching.Regex
import scala.util.parsing.input._

object MyParser extends StandardTokenParsers {
import lexical.StringLit
def regexStringLit(r: Regex): Parser[String] = acceptMatch(
"string literal matching regex " + r,
{ case StringLit( s ) if r.unapplySeq(s).isDefined => s }
)
lexical.delimiters += "="
lexical.reserved += "TargetFolder"
lazy val mTargetFolder: Parser[String] = "TargetFolder" ~> "=" ~> mFilePath
lazy val mFilePath: Parser[String] = regexStringLit("([a-zA-Z]:\\\\[\\w\\\\?]*)|(/[\\w/]*)".r)
def parseTargetFolder( s: String ) = { mTargetFolder( new lexical.Scanner( s ) ) }
}

示例:

scala> MyParser.parseTargetFolder("""TargetFolder = "c:\Dir1\Dir2" """)
res12: MyParser.ParseResult[String] = [1.31] parsed: c:\Dir1\Dir2

scala> MyParser.parseTargetFolder("""TargetFolder = "/Dir1/Dir2" """)
res13: MyParser.ParseResult[String] = [1.29] parsed: /Dir1/Dir2

scala> MyParser.parseTargetFolder("""TargetFolder = "Hello world" """)
res14: MyParser.ParseResult[String] =
[1.16] failure: identifier matching regex ([a-zA-Z]:\\[\w\\?]*)|(/[\w/]*) expected
TargetFolder = "Hello world"
^

请注意,还修复了此处的“目标文件夹”正则表达式,两个替代项周围缺少括号,以及不需要的空格。

关于parsing - 在 StandardTokenParsers 中使用正则表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14237586/

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