我正在尝试为与Milner的CCS非常相似的语言编写解析器。基本上我到目前为止解析的是以下类型的表达式:
表达式必须以字母开头(不包括t),并且可以在第一个字母后面加上任意数量的字母(以“。”分隔)。表达式必须以数字结束(为简单起见,我现在选择0到2之间的数字)。我想为Scala使用Parser Combinators,但这是我第一次使用它们。这就是我到目前为止所做的:
import scala.util.parsing.combinator._
class SimpleParser extends RegexParsers {
def alpha: Parser[String] = """[^t]{1}""".r ^^ { _.toString }
def digit: Parser[Int] = """[0-2]{1}""".r ^^ { _.toInt }
def expr: Parser[Any] = alpha ~ "." ~ digit ^^ {
case al ~ "." ~ di => List(al, di)
}
def simpleExpression: Parser[Any] = alpha ~ "." ~ rep(alpha ~ ".") ~ digit //^^ { }
}
正如您在def expr :Parser[Any]
中看到的那样,我试图将结果作为列表返回,因为Scala中的列表非常容易使用(在我看来)。这是如何将Parser [Any]结果转换为List的正确方法吗?任何人都可以向我提供有关如何为def simpleExpression:Parser[Any]
执行此操作的任何提示。
我想使用Lists的主要原因是因为在解析和Expression之后我希望能够使用它。例如,给定表达式 ab1 ,如果我得到'a',我想使用表达式以最终得到一个新表达式: b.1 (即 ab1 - >(a) - > b.1 )。这背后的想法是模拟有限状态自动机。关于如何改进我的实施的任何提示都表示赞赏。
答案 0 :(得分:5)
为了保证事物类型安全,我建议使用一个解析器来生成字符串列表和int的元组。也就是说,输入a.b.a.1
将被解析为(List("a", "b", "a"), 1)
。另请注意,修改了alpha的正则表达式以排除任何不是小写字母的内容(除了t)。
class SimpleParser extends RegexParsers {
def alpha: Parser[String] = """[a-su-z]{1}""".r ^^ { _.toString }
def digit: Parser[Int] = """[0-2]{1}""".r ^^ { _.toInt }
def repAlpha: Parser[List[String]] = rep1sep(alpha, ".")
def expr: Parser[(List[String], Int)] = repAlpha ~ "." ~ digit ^^ {
case alphas ~ _ ~ num =>
(alphas, num)
}
}
使用此SimpleParser
的实例,这是我得到的输出:
println(parser.parse(parser.expr, "a.b.a.1"))
// [1.8] parsed: (List(a, b, a),1)
println(parser.parse(parser.expr, "a.0"))
// [1.4] parsed: (List(a),0)