我想我会在scala-reflect或scala-compiler中找到它,但我无法为此找到一个记录的API。有没有办法在运行时执行此操作?
e.g。 def isValidIdentifer(s:String)
(我对保留关键字的实际列表不感兴趣,我可以自己编写阅读手册)
基于@sschaef的答案,附加规范:它应该处理任何类型的输入,如果s
是单个有效标识符,则返回true
我尝试扩展这个答案:
import scala.tools.reflect.{ToolBox, ToolBoxError}
lazy val tb = scala.reflect.runtime.universe.runtimeMirror(getClass.getClassLoader).mkToolBox()
def isIdentifier(ident: String): Boolean = {
if (ident.startsWith(" ") || ident.endsWith(" ")) {
return false
}
try {
val tree = tb.parse(s"val $ident:Int = 0")
if (tree.toString().length != ident.length + 13) {
return false
}
tree.children match {
case c0 :: c1 :: Nil if
c0.children.isEmpty && c0.productArity == 1 && c0.productElement(0).toString == "Int"
&& c1.children.isEmpty && c1.productArity == 1 && c1.productElement(0).toString == "Constant(0)" => true
case _ => false
}
} catch {
case _: ToolBoxError => false
}
}
以下恶意案例成功:b:Int
,b = 0; c
,b/*comment*/
答案 0 :(得分:2)
查看编译器,我发现了这个:
case 'A' | 'B' | 'C' | 'D' | 'E' |
'F' | 'G' | 'H' | 'I' | 'J' |
'K' | 'L' | 'M' | 'N' | 'O' |
'P' | 'Q' | 'R' | 'S' | 'T' |
'U' | 'V' | 'W' | 'X' | 'Y' |
'Z' | '$' | '_' |
'a' | 'b' | 'c' | 'd' | 'e' |
'f' | 'g' | 'h' | 'i' | 'j' |
'k' | 'l' | 'm' | 'n' | 'o' |
'p' | 'q' | 'r' | 's' | 't' |
'u' | 'v' | 'w' | 'x' | 'y' | // scala-mode: need to understand multi-line case patterns
'z' =>
putChar(ch)
nextChar()
getIdentRest()
这是scanner的一部分。此外,请查看解析标识符rest的section。看起来您不能轻易复制或使用代码。
我建议使用工具箱:
scala> import scala.tools.reflect.{ToolBox, ToolBoxError}
import scala.tools.reflect.{ToolBox, ToolBoxError}
scala> val tb = scala.reflect.runtime.universe.runtimeMirror(
getClass.getClassLoader).mkToolBox()
tb: scala.tools.reflect.ToolBox[reflect.runtime.universe.type] = scala.tools.reflect.ToolBoxFactory$ToolBoxImpl@6c865bc6
scala> def isIdentifier(ident: String) =
try { tb.parse(s"val ($ident) = 0"); true }
catch { case _: ToolBoxError => false }
isIdentifier: (ident: String)Boolean
scala> isIdentifier("hello")
res0: Boolean = true
scala> isIdentifier("hello_-")
res1: Boolean = true
scala> isIdentifier("hello-")
res2: Boolean = false
scala> isIdentifier("`hello-`")
res3: Boolean = true