Scala:使用StandardTokenParser解析十六进制数字

时间:2010-08-13 16:50:51

标签: parsing scala

我通过扩展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解析器,但那里有类型问题。扩展词法分隔符和语法规则定义的其他方法导致找不到令牌!

2 个答案:

答案 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或数组。