|
6 | 6 | [the.parsatron :refer :all] |
7 | 7 | [naga.schema.structs :as st])) |
8 | 8 |
|
9 | | -(defn choice* |
| 9 | +(defn choice* |
10 | 10 | "choice with backtracking." |
11 | 11 | [& args] |
12 | 12 | (apply choice (map attempt args))) |
|
60 | 60 |
|
61 | 61 | ;; This does not include all legal characters. |
62 | 62 | ;; Consider some others in future, especially > |
63 | | -(def ns-word (many1 (choice (letter) (char \_) (char \-) (char \:)))) |
| 63 | +(def ns-word (many1 (choice (letter) (digit) (char \_) (char \-) (char \:)))) |
64 | 64 |
|
65 | 65 | (def word (many1 (letter))) |
66 | 66 |
|
|
73 | 73 |
|
74 | 74 | (defparser integer [] |
75 | 75 | (let->> [i (either digits (signed-digits))] |
76 | | - (always (Long/parseLong (apply str i))))) |
| 76 | + (always (Long/parseLong (str/join i))))) |
77 | 77 |
|
78 | 78 | (defparser floating-point [] |
79 | 79 | (let->> [i (either digits (signed-digits)) |
80 | 80 | f (>> (char \.) (many1 (digit)))] |
81 | | - (always (Double/parseDouble (apply str (apply str i) \. f))))) |
| 81 | + (always (Double/parseDouble (apply str (str/join i) \. f))))) |
82 | 82 |
|
83 | 83 | (def number (either* (floating-point) (integer))) |
84 | 84 |
|
85 | 85 | ;; parses strings of the form: 'it''s a string!' |
86 | 86 | (defparser pstring1 [] |
87 | | - (let->> [s (many1 (between (char \') (char \') (many non-squote))) ] |
88 | | - (always (apply str (flatten (interpose \' s)))))) |
| 87 | + (let->> [s (many1 (between (char \') (char \') (many non-squote)))] |
| 88 | + (always (str/join (flatten (interpose \' s)))))) |
89 | 89 |
|
90 | 90 | ;; parses strings of the form: "She said, ""Hello,"" to me." |
91 | 91 | (defparser pstring2 [] |
92 | 92 | (let->> [s (many1 (between (char \") (char \") (many non-dquote)))] |
93 | | - (always (apply str (flatten (interpose \" s)))))) |
| 93 | + (always (str/join (flatten (interpose \" s)))))) |
94 | 94 |
|
95 | 95 | (def pstring (either (pstring1) (pstring2))) |
96 | 96 |
|
97 | 97 | ;; variables start with a capital. Internally they start with ? |
98 | 98 | (defparser variable [] |
99 | 99 | (let->> [f (upper-case-letter) |
100 | | - r (many (letter))] |
101 | | - (always (symbol (apply str "?" (Character/toLowerCase f) r) )))) |
| 100 | + r (many (choice (letter) (digit) (char \_) (char \-)))] |
| 101 | + (always (symbol (apply str "?" (Character/toLowerCase f) r))))) |
102 | 102 |
|
103 | 103 | (defn build-keyword |
104 | 104 | "Creates a keyword from a parsed word token" |
105 | 105 | [wrd] |
106 | 106 | (let [[kns kname :as w] (str/split wrd #":") |
107 | 107 | parts (count w)] |
108 | 108 | ;; use cond without a default to return nil |
109 | | - (cond (= 2 parts) (cond (empty? kns) (keyword kname) |
| 109 | + (cond (Character/isDigit (first wrd)) nil |
| 110 | + (= 2 parts) (cond (empty? kns) (keyword kname) |
110 | 111 | (seq kname) (keyword kns kname)) |
111 | 112 | (= 1 parts) (if-not (str/ends-with? wrd ":") |
112 | 113 | (keyword kns))))) |
113 | 114 |
|
114 | 115 | ;; atomic values, like a predicate, are represented as a keyword |
115 | 116 | (defparser kw [] |
116 | 117 | (let->> [r ns-word] |
117 | | - (let [wrd (apply str r)] |
| 118 | + (let [wrd (str/join r)] |
118 | 119 | (if-let [k (build-keyword wrd)] |
119 | 120 | (always k) |
120 | 121 | (throw (fail (str "Invalid identifier: " wrd))))))) |
|
0 commit comments