我通过扩展scala.util.parsing.combinator.syntactical.StandardTokenParser
来使用Scala组合解析器。该类提供以下方法
def ident : Parser[String]
用于解析标识符和
def numericLit : Parser[String]
用于解析数字(我猜想小数)
我正在使用scala.util.parsing.combinator.lexical.Scanners
scala.util.parsing.combinator.lexical.StdLexical
来进行lexing。
我的要求是解析一个十六进制数(不带0x
前缀),可以是任意长度。基本上是一个语法,如:([0-9]|[a-f])+
我尝试集成Regex解析器,但那里有类型问题。扩展词法分隔符和语法规则定义的其他方法导致找不到令牌!
答案 0 :(得分:5)
我认为问题可以通过扩展Lexer而不是Parser的行为来解决。标准词法分析器只取十进制数字,所以我创建了一个新的词法分析器:
class MyLexer extends StdLexical {
override type Elem = Char
override def digit = ( super.digit | hexDigit )
lazy val hexDigits = Set[Char]() ++ "0123456789abcdefABCDEF".toArray
lazy val hexDigit = elem("hex digit", hexDigits.contains(_))
}
我的解析器(必须是StandardTokenParser)可以扩展如下:
object ParseAST extends StandardTokenParsers{
override val lexical:MyLexer = new MyLexer()
lexical.delimiters += ( "(" , ")" , "," , "@")
...
}
由数字构造“数字”由StdLexical类负责:
class StdLexical {
...
def token: Parser[Token] =
...
| digit~rep(digit)^^{case first ~ rest => NumericLit(first :: rest mkString "")}
}
由于StdLexical只将解析后的数字作为字符串给出,因此对我来说不是问题,因为我对数值也不感兴趣。
答案 1 :(得分:3)
您可以使用RegexParsers
与相关令牌相关联的操作。
import scala.util.parsing.combinator._
object HexParser extends RegexParsers {
val hexNum: Parser[Int] = """[0-9a-f]+""".r ^^
{ case s:String => Integer.parseInt(s,16) }
def seq: Parser[Any] = repsep(hexNum, ",")
}
这将定义一个解析器,该解析器读取逗号分隔的十六进制数,而不是先前的0x
。它实际上会返回Int
。
val result = HexParser.parse(HexParser.seq, "1, 2, f, 10, 1a2b34d")
scala> println(result)
[1.21] parsed: List(1, 2, 15, 16, 27439949)
没有办法区分小数表示法数字。我也在使用Integer.parseInt
,这仅限于Int
的大小。要获得任何长度,您可能必须创建自己的解析器并使用BigInteger
或数组。