我想在基於StandardTokenParsers的解析器中使用正則表達式。對於這一點,我已經子類StdLexical如下:在StandardTokenParsers中使用正則表達式
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正在開發和處理「Z:\ ...」,所以它處理'Z'作爲標識符 - >'標識符Z',我得到這個錯誤:「string文字匹配正則表達式([a-zA-Z]:\\ [\ w \\?] *)|(/ [\ w /] *)在位置2,26處找到。在我使用自己的實現覆蓋詞法之後,它就消失了,它在達到標識符事件之前處理正則表達式。不太確定你爲什麼沒有得到那個錯誤。 – Dan
因爲我非常自由地改變語法:dir路徑必須是合適的字符串文字(帶引號)。沒有這個改變,一切都變得更加複雜。您可以將路徑標記作爲標識符(因此不需要引號),但是您需要在標識符中使用「/」,「:」和「\」(這是您顯然要做的),然後這會影響**每個**標識符(從而破壞解析)。核心問題是詞法分析器和解析器是分開的,如果你想要一個路徑或標識符(它沒有上下文),詞法分析器不知道它何時解析char流。 –
避免這些問題的另一個解決方案是簡單地不使用基於標記的解析(其中有兩個單獨的部分:詞法分析器和語法解析器),而是將所有內容都放在同一級別。通過示例定義'對象MyParser使用RegexParsers擴展StdLexical'並且在那裏做所有事情。因爲沒有分離,所以你知道每個地方的上下文,作爲一個獎勵,「RegexParsers」會自動將每個正則表達式轉換爲合適的分析器。 –