aboutsummaryrefslogtreecommitdiff
path: root/src/lang/lexer.clj
diff options
context:
space:
mode:
Diffstat (limited to 'src/lang/lexer.clj')
-rw-r--r--src/lang/lexer.clj55
1 files changed, 33 insertions, 22 deletions
diff --git a/src/lang/lexer.clj b/src/lang/lexer.clj
index 191686cb8..bbb92da95 100644
--- a/src/lang/lexer.clj
+++ b/src/lang/lexer.clj
@@ -1,5 +1,6 @@
(ns lang.lexer
- (:require [clojure.core.match :refer [match]]
+ (:require [clojure.template :refer [do-template]]
+ [clojure.core.match :refer [match]]
[lang.util :as &util :refer [exec return* return fail fail*
repeat-m try-m try-all-m]]))
@@ -10,13 +11,13 @@
(fn [text]
(if-let [[match] (re-find regex text)]
(return* (.substring text (.length match)) match)
- (fail* "Pattern failed."))))
+ (fail* (str "Pattern failed: " regex " -- " text)))))
-(defn ^:private lex-str [str]
+(defn ^:private lex-str [prefix]
(fn [text]
- (if (.startsWith text str)
- (return* (.substring text (.length str)) str)
- (fail* "String failed."))))
+ (if (.startsWith text prefix)
+ (return* (.substring text (.length prefix)) prefix)
+ (fail* (str "String failed: " prefix " -- " text)))))
;; [Lexers]
(def ^:private lex-white-space (lex-regex #"^(\s+)"))
@@ -27,33 +28,43 @@
_ (lex-str ")")]
(return [::list members])))
-(def ^:private lex-ident
- (exec [token (lex-regex #"^([a-zA-Z!@$%^&*<>\.,/\\\|][a-zA-Z0-9!@$%^&*<>\.,/\\\|]*)")]
- (return [::ident token])))
+(def ^:private lex-tuple
+ (exec [_ (lex-str "[")
+ members (repeat-m lex-form)
+ _ (lex-str "]")]
+ (return [::tuple members])))
+
+(def +ident-re+ #"^([a-zA-Z\-\+\_\=!@$%^&*<>\.,/\\\|'][a-zA-Z0-9\-\+\_\=!@$%^&*<>\.,/\\\|']*)")
+
+(do-template [<name> <tag> <regex>]
+ (def <name>
+ (exec [token (lex-regex <regex>)]
+ (return [<tag> token])))
+
+ ^:private lex-int ::int #"^(0|[1-9][0-9]*)"
+ ^:private lex-ident ::ident +ident-re+)
-(def ^:private lex-int
- (exec [token (lex-regex #"^([1-9][0-9]*)")]
- (return [::int token])))
+(def ^:private lex-tag
+ (exec [_ (lex-str "#")
+ token (lex-regex +ident-re+)]
+ (return [::tag token])))
(def ^:private lex-form
(exec [_ (try-m lex-white-space)
- form (try-all-m [lex-list
+ form (try-all-m [lex-int
lex-ident
- lex-int
- ])
+ lex-tag
+ lex-list
+ lex-tuple])
_ (try-m lex-white-space)]
(return form)))
;; [Interface]
(defn lex [text]
- (match ((exec [_ (try-m lex-white-space)
- form lex-list
- _ (try-m lex-white-space)]
- (return form))
- text)
- [::&util/ok [?state ?datum]]
+ (match ((repeat-m lex-form) text)
+ [::&util/ok [?state ?forms]]
(if (empty? ?state)
- ?datum
+ ?forms
(assert false (str "Unconsumed input: " ?state)))
[::&util/failure ?message]