【问题标题】:Programmatically checking whether a string is a reserved word in Scala以编程方式检查字符串是否是 Scala 中的保留字
【发布时间】:2014-02-26 09:43:57
【问题描述】:

有没有简单的方法来实现以下功能?

即决定在生成代码时是否需要用反引号引用给定的文本。

def isReservedWord(text: String): Boolean

isReservedWord("type") // true
isReservedWord("foo")  // false

当然,我可以根据语言规范末尾的 Scala 语法摘要维护一个关键字列表,然后检查它,但有更好的方法吗?

【问题讨论】:

    标签: scala keyword reserved-words


    【解决方案1】:

    编译器维护一个可以轻松访问的关键字列表:

    scala> import scala.tools.nsc._
    import scala.tools.nsc._
    
    scala> val compiler = new Global(new Settings)
    compiler: scala.tools.nsc.Global = scala.tools.nsc.Global@29935953
    
    scala> compiler.nme.keywords
    res0: Set[compiler.TermName] = Set(abstract, >:, true, val, do, throw, <-, package, _, macro, @, object, false, this, if, then, var, trait, ., catch, with, def, else, class, type, #, lazy, null, =, <:, override, protected, =>, private, sealed, finally, new, implicit, extends, final, for, return, case, import, forSome, :, super, while, yield, try, match, <%)
    
    scala> compiler.javanme.keywords
    res1: Set[compiler.TermName] = Set(abstract, strictfp, short, int, do, goto, interface, throw, float, package, implements, enum, this, long, if, switch, native, throws, boolean, catch, else, const, class, assert, public, void, instanceof, protected, static, default, private, finally, synchronized, new, char, extends, final, volatile, for, return, continue, case, import, double, super, byte, while, break, try, transient)
    

    幸运的是,Scala 已经提供了反射 API,它只不过是由公共 API 访问的编译器。当您将公共类型转换为内部类型时,您可以访问包含所有定义的符号表:

    scala> val st = scala.reflect.runtime.universe.asInstanceOf[scala.reflect.internal.SymbolTable]
    st: scala.reflect.internal.SymbolTable = scala.reflect.runtime.JavaUniverse@472250c4
    
    scala> st.nme.keywords
    res10: Set[st.TermName] = Set(abstract, >:, true, val, do, throw, <-, package, _, macro, @, object, false, this, if, then, var, trait, ., catch, with, def, else, class, type, #, lazy, null, =, <:, override, protected, =>, private, sealed, finally, new, implicit, extends, final, for, return, case, import, forSome, :, super, while, yield, try, match, <%)
    

    在 REPL 内部,您还可以使用 :power 模式直接访问编译器:

    scala> :power
    ** Power User mode enabled - BEEP WHIR GYVE **
    ** :phase has been set to 'typer'.          **
    ** scala.tools.nsc._ has been imported      **
    ** global._, definitions._ also imported    **
    ** Try  :help, :vals, power.<tab>           **
    
    scala> nme.keywords
    res3: Set[$r.intp.global.TermName] = Set(abstract, >:, true, val, do, throw, <-, package, _, macro, @, object, false, this, if, then, var, trait, ., catch, with, def, else, class, type, #, lazy, null, =, <:, override, protected, =>, private, sealed, finally, new, implicit, extends, final, for, return, case, import, forSome, :, super, while, yield, try, match, <%)
    
    scala> javanme.keywords
    res4: Set[$r.intp.global.TermName] = Set(abstract, strictfp, short, int, do, goto, interface, throw, float, package, implements, enum, this, long, if, switch, native, throws, boolean, catch, else, const, class, assert, public, void, instanceof, protected, static, default, private, finally, synchronized, new, char, extends, final, volatile, for, return, continue, case, import, double, super, byte, while, break, try, transient)
    

    【讨论】:

    • 谢谢!太完美了。
    【解决方案2】:

    grepping编译器源码,发现如下:

    scala.tools.nsc.doc.html.SyntaxHigh.reserved
    

    这是html 的私有包,因此您可能需要编写一个包装器。可能更容易将该数组复制到您自己的源中。

    内部 API 中有更多内容,例如scala.reflect.internal.StdNames。而scala.reflect.internal.Printers 有一个方法quotedName,但你需要整个蛋糕才能访问这些。也许您可以通过官方反射 API 获得其中任何一个?

    【讨论】:

      猜你喜欢
      • 2016-11-06
      • 1970-01-01
      • 1970-01-01
      • 2015-09-11
      • 2021-10-30
      • 1970-01-01
      • 2013-12-13
      • 2021-10-10
      相关资源
      最近更新 更多