Add a module for getting reserved words (#1171)
This is helpful for writing syntax highlighters (e.g., https://github.com/hylang/hy/pull/1170).
This commit is contained in:
parent
b3d7069fb3
commit
5b85990d87
1
AUTHORS
1
AUTHORS
@ -72,3 +72,4 @@
|
||||
* Jakub Wilk <jwilk@jwilk.net>
|
||||
* Kodi Arfer <git@arfer.net>
|
||||
* Karan Sharma <karansharma1295@gmail.com>
|
||||
* Sergey Sobko <s.sobko@profitware.ru>
|
||||
|
@ -1261,3 +1261,22 @@ Returns an iterator from *coll* as long as *pred* returns ``True``.
|
||||
=> (list (take-while neg? [ 1 2 3 -4 5]))
|
||||
[]
|
||||
|
||||
|
||||
Other Built-Ins
|
||||
===============
|
||||
|
||||
hy.core.reserved
|
||||
----------------
|
||||
|
||||
Usage: ``(hy.core.reserved.names)``
|
||||
|
||||
This module can be used to get a list (actually, a ``frozenset``) of the
|
||||
names of Hy's built-in functions, macros, and special forms. The output
|
||||
also includes all Python reserved words. All names are in unmangled form
|
||||
(e.g., ``list-comp`` rather than ``list_comp``).
|
||||
|
||||
.. code-block:: hy
|
||||
|
||||
=> (import hy)
|
||||
=> (in "defclass" (hy.core.reserved.names))
|
||||
True
|
||||
|
@ -1,3 +1,5 @@
|
||||
from . import reserved # noqa
|
||||
|
||||
STDLIB = [
|
||||
"hy.core.language",
|
||||
"hy.core.shadow"
|
||||
|
41
hy/core/reserved.hy
Normal file
41
hy/core/reserved.hy
Normal file
@ -0,0 +1,41 @@
|
||||
;;; Get a frozenset of Hy reserved words
|
||||
;;
|
||||
;; Copyright (c) 2016 Paul Tagliamonte <paultag@debian.org>
|
||||
;;
|
||||
;; Permission is hereby granted, free of charge, to any person obtaining a
|
||||
;; copy of this software and associated documentation files (the "Software"),
|
||||
;; to deal in the Software without restriction, including without limitation
|
||||
;; the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
;; and/or sell copies of the Software, and to permit persons to whom the
|
||||
;; Software is furnished to do so, subject to the following conditions:
|
||||
;;
|
||||
;; The above copyright notice and this permission notice shall be included in
|
||||
;; all copies or substantial portions of the Software.
|
||||
;;
|
||||
;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
;; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
;; THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
;; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
;; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
;; DEALINGS IN THE SOFTWARE.
|
||||
|
||||
(import hy sys keyword)
|
||||
|
||||
(setv _cache None)
|
||||
|
||||
(defn names []
|
||||
"Return a frozenset of reserved symbol names.
|
||||
|
||||
The result of the first call is cached."
|
||||
(global _cache)
|
||||
(if (is _cache None) (do
|
||||
(setv unmangle (. sys.modules ["hy.lex.parser"] hy_symbol_unmangle))
|
||||
(setv _cache (frozenset (map unmangle (+
|
||||
hy.core.language.*exports*
|
||||
hy.core.shadow.*exports*
|
||||
(list (.keys (get hy.macros._hy_macros None)))
|
||||
keyword.kwlist
|
||||
(list-comp k [k (.keys hy.compiler.-compile-table)]
|
||||
(isinstance k hy._compat.string-types))))))))
|
||||
_cache)
|
@ -61,6 +61,30 @@ def hy_symbol_mangle(p):
|
||||
return p
|
||||
|
||||
|
||||
def hy_symbol_unmangle(p):
|
||||
# hy_symbol_mangle is one-way, so this can't be perfect.
|
||||
# But it can be useful till we have a way to get the original
|
||||
# symbol (https://github.com/hylang/hy/issues/360).
|
||||
|
||||
from hy._compat import str_type
|
||||
p = str_type(p)
|
||||
|
||||
if p.endswith("_bang") and p != "_bang":
|
||||
p = p[:-len("_bang")] + "!"
|
||||
|
||||
if p.startswith("is_") and p != "is_":
|
||||
p = p[len("is_"):] + "?"
|
||||
|
||||
if "_" in p and p != "_":
|
||||
p = p.replace("_", "-")
|
||||
|
||||
if (all([c.isalpha() and c.isupper() or c == '_' for c in p]) and
|
||||
any([c.isalpha() for c in p])):
|
||||
p = '*' + p.lower() + '*'
|
||||
|
||||
return p
|
||||
|
||||
|
||||
def set_boundaries(fun):
|
||||
@wraps(fun)
|
||||
def wrapped(p):
|
||||
|
@ -360,6 +360,24 @@ def test_lex_mangling_bang():
|
||||
assert entry == [HySymbol(".foo_bang.bar.baz_bang")]
|
||||
|
||||
|
||||
def test_unmangle():
|
||||
import sys
|
||||
f = sys.modules["hy.lex.parser"].hy_symbol_unmangle
|
||||
|
||||
assert f("FOO") == "*foo*"
|
||||
assert f("<") == "<"
|
||||
assert f("FOOa") == "FOOa"
|
||||
|
||||
assert f("foo_bar") == "foo-bar"
|
||||
assert f("_") == "_"
|
||||
|
||||
assert f("is_foo") == "foo?"
|
||||
assert f("is_") == "is-"
|
||||
|
||||
assert f("foo_bang") == "foo!"
|
||||
assert f("_bang") == "-bang"
|
||||
|
||||
|
||||
def test_simple_cons():
|
||||
"""Check that cons gets tokenized correctly"""
|
||||
entry = tokenize("(a . b)")[0]
|
||||
|
@ -612,3 +612,17 @@
|
||||
[1 3 6 10 15])
|
||||
(assert-equal (list (accumulate [1 -2 -3 -4 -5] -))
|
||||
[1 3 6 10 15]))
|
||||
|
||||
(defn test-reserved []
|
||||
(import [hy.core.reserved [names]])
|
||||
(assert (is (type (names)) frozenset))
|
||||
(assert (in "and" (names)))
|
||||
(when PY3
|
||||
(assert (in "False" (names))))
|
||||
(assert (in "pass" (names)))
|
||||
(assert (in "class" (names)))
|
||||
(assert (in "defclass" (names)))
|
||||
(assert (in "->" (names)))
|
||||
(assert (in "keyword?" (names)))
|
||||
(assert (not-in "foo" (names)))
|
||||
(assert (not-in "hy" (names))))
|
||||
|
Loading…
x
Reference in New Issue
Block a user