一段时间以来,我一直在使用 Scala 解析器组合器,并学习了一些方法,使其表现良好并使用内置函数完成我想要的大部分事情。
但是如何制作嵌入式语言(如 php 或 ruby 的 erb)?在实际代码的嵌入之外,它要求空格不能被忽略。
我设法制作了一个简单的解析器,它将所有文本与给定的正则表达式匹配,但我正在寻找一种更好、更漂亮的方法来做到这一点。可能有一些已经定义的函数可以完成所需的工作。
测试语言解析如下文本:
now: [[ millis; ]]
and now: [[; millis; ]]
并由以下代码生成:
package test
import scala.util.parsing.combinator.RegexParsers
import scala.util.matching.Regex
sealed abstract class Statement
case class Print(s: String) extends Statement
case class Millis() extends Statement
object SimpleLang extends RegexParsers {
def until(r: Regex): Parser[String] = new Parser[String]{
def apply(in: Input) = {
val source = in.source
val offset = in.offset
val start = offset
(r.findFirstMatchIn( source.subSequence(offset, source.length) )) match {
case Some(matched) =>
Success(source.subSequence(offset, offset + matched.start).toString, in.drop(matched.start))
case None =>
Failure("string matching regex `"+ r +"' expected but `"+ in.first +"' found", in.drop(0))
}
}
}
def until(s: String): Parser[String] = until(java.util.regex.Pattern.quote(s).r)
def interpret(stats: List[Statement]): Unit = stats match {
case Print(s) :: rest => {
print(s)
interpret(rest)
}
case Millis() :: rest => {
print(System.currentTimeMillis)
interpret(rest)
}
case Nil => ()
}
def apply(input: String) : List[Statement] = parseAll(beginning, input) match {
case Success(tree,_) => tree
case e: NoSuccess => throw new RuntimeException("Syntax error: " + e)
}
/** GRAMMAR **/
def beginning = (
"[[" ~> stats |
until("[[") ~ "[[" ~ stats ^^ {
case s ~ _ ~ ss => Print(s) :: ss
}
)
def stats = rep1sep(stat, ";")
def stat = (
"millis" ^^^ { Millis() } |
"]]" ~> ( (until("[[") <~ "[[") | until("\\z".r)) ^^ {
case s => Print(s)
}
)
def main(args: Array[String]){
val tree = SimpleLang("now: [[ millis; ]]\nand now: [[; millis; ]]")
println(tree)
interpret(tree)
}
}