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

Parsing Scala:使用StandardTokenParser解析十六进制数字,parsing,scala,Parsing,Scala,我通过扩展Scala.util.parsing.combinator.syntactic.StandardTokenParser来使用Scala组合解析器。此类提供以下方法 def ident:Parser[String]用于解析标识符和 def numericLit:Parser[String]解析数字(我想是十进制的) 我正在使用scala.util.parsing.combinator.lexical中的scala.util.parsing.combinator.lexical.StdLe

我通过扩展
Scala.util.parsing.combinator.syntactic.StandardTokenParser
来使用Scala组合解析器。此类提供以下方法

def ident:Parser[String]
用于解析标识符和

def numericLit:Parser[String]
解析数字(我想是十进制的)

我正在使用
scala.util.parsing.combinator.lexical
中的
scala.util.parsing.combinator.lexical.StdLexical
进行词法分析

我的要求是解析任意长度的十六进制数(不带
0x
前缀)。基本上是这样的语法:
([0-9]|[a-f])+


我尝试集成Regex解析器,但存在类型问题。扩展lexer分隔符定义和语法规则的其他方法会导致找不到标记

您可以将
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
的大小。要获得任何长度,您可能需要制作自己的解析器并使用
biginger
或数组

正如我所想,这个问题可以通过扩展Lexer而不是解析器的行为来解决。标准lexer只接受十进制数字,因此我创建了一个新的lexer:

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只将解析后的数字作为字符串给出,因此这对我来说不是问题,因为我对数值也不感兴趣。

如果我只解析十六进制数字,这将适合我。整体实现比正则表达式解析要大得多。我的目标是使用StandardTokenParser,在StandardTokenParser中调用parse(HexParser.seq)时,在其内部使用regex解析器会给出类型错误“found:HexParser.parser[Any]required:scratch.parser[?]”。我认为解决方案将涉及更改正在使用的lexer。可能,特别是如果它应该是上下文敏感的。我刚刚提供了一种将十六进制字符串转换为Int的方法。您正在解析什么类型的文件?也许你可以对它进行预处理,使它更易于Lexer。这个答案很有用-我需要了解如何处理hex和类似的构造。添加关于lexical.delimiters的注释特别有用。