Если вы действительно хотите использовать синтаксический анализ на основе токенов и повторно использовать StdLexical, я бы посоветовал обновить синтаксис для «TargetFolder», чтобы значение после знака равенства было правильным строковым литералом. Или, другими словами, сделайте так, чтобы путь был заключен в кавычки. С этого момента вам больше не нужно расширять StdLexical.
Затем возникает проблема преобразования регулярного выражения в парсер. Scala уже имеет RegexParsers
для этого (что неявно преобразует регулярное выражение в Parser [String]
), но, к сожалению, здесь вы не хотите, потому что он работает с потоками Char
( type Elem = Char
в RegexParsers
)), пока вы работаете над строкой токенов.
Поэтому нам действительно нужно определить наше собственное преобразование из 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"
^
Обратите внимание, что здесь также исправлено ваше регулярное выражение «целевая папка», у вас отсутствовали парсеры вокруг двух альтернатив, а также ненужные пробелы.