diff options
author | Eduardo Julian | 2014-11-26 19:26:22 -0400 |
---|---|---|
committer | Eduardo Julian | 2014-11-26 19:26:22 -0400 |
commit | a96bb768a5f02c2dc9c0de1e50dc14376d2e7f35 (patch) | |
tree | 2387d0bf4cf171475f0f564c9006e0546bac48e3 /src/lang/lexer.clj | |
parent | 5bf50ef978eb88e2e61c40f3bb0fea523115e770 (diff) |
+ Can now define functions.
% However, they currently access Clojure's environment, instead of the interpreter's.
Diffstat (limited to 'src/lang/lexer.clj')
-rw-r--r-- | src/lang/lexer.clj | 55 |
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] |