1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;; Code:
(defconst emmet-mode:version "1.0.10")
(require 'cl)
(defmacro emmet-defparameter (symbol &optional initvalue docstring)
`(progn
(defvar ,symbol nil ,docstring)
(setq ,symbol ,initvalue)))
(defun emmet-join-string (lis joiner)
(mapconcat 'identity lis joiner))
(defun emmet-get-keys-of-hash (hash)
(let ((ks nil))
(maphash #'(lambda (k v) (setq ks (cons k ks))) hash)
ks))
(defun emmet-get-vals-of-hash (hash)
(let ((vs nil))
(maphash #'(lambda (k v) (setq vs (cons v vs))) hash)
vs))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Generic parsing macros and utilities
(defmacro emmet-aif (test-form then-form &rest else-forms)
"Anaphoric if. Temporary variable `it' is the result of test-form."
`(let ((it ,test-form))
(if it ,then-form ,@(or else-forms '(it)))))
(defmacro emmet-pif (test-form then-form &rest else-forms)
"Parser anaphoric if. Temporary variable `it' is the result of test-form."
`(let ((it ,test-form))
(if (not (eq 'error (car it))) ,then-form ,@(or else-forms '(it)))))
(defmacro emmet-parse (regex nums label &rest body)
"Parse according to a regex and update the `input' variable."
`(emmet-aif (emmet-regex ,regex input ',(number-sequence 0 nums))
(let ((input (elt it ,nums)))
,@body)
`,`(error ,(concat "expected " ,label))))
(defmacro emmet-run (parser then-form &rest else-forms)
"Run a parser and update the input properly, extract the parsed
expression."
`(emmet-pif (,parser input)
(let ((input (cdr it))
(expr (car it)))
,then-form)
,@(or else-forms '(it))))
(defmacro emmet-por (parser1 parser2 then-form &rest else-forms)
"OR two parsers. Try one parser, if it fails try the next."
`(emmet-pif (,parser1 input)
(let ((input (cdr it))
(expr (car it)))
,then-form)
(emmet-pif (,parser2 input)
(let ((input (cdr it))
(expr (car it)))
,then-form)
,@else-forms)))
(defmacro emmet-find (direction regexp &optional limit-of-search repeat-count)
"Regexp-search in given direction, returning the position (or nil)
and leaving the point in place."
`(save-excursion
(if (,(intern (concat "re-search-" direction))
,regexp ,limit-of-search t ,repeat-count)
(match-beginning 0))))
(defun emmet-regex (regexp string refs)
"Return a list of (`ref') matches for a `regex' on a `string' or nil."
(if (string-match (concat "^" regexp "\\([^\n]*\\)$") string)
(mapcar (lambda (ref) (match-string ref string))
(if (sequencep refs) refs (list refs)))
nil))
|