aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lux/base.clj4
-rw-r--r--src/lux/lexer.clj53
-rw-r--r--src/lux/parser.clj51
-rw-r--r--src/lux/reader.clj32
4 files changed, 94 insertions, 46 deletions
diff --git a/src/lux/base.clj b/src/lux/base.clj
index 532f56695..66b972f94 100644
--- a/src/lux/base.clj
+++ b/src/lux/base.clj
@@ -12,6 +12,10 @@
clojure.core.match.array))
;; [Tags]
+(defmacro deftags [prefix & names]
+ `(do ~@(for [name names]
+ `(def ~(symbol (str "$" name)) ~name))))
+
;; List
(def $Nil "lux;Nil")
(def $Cons "lux;Cons")
diff --git a/src/lux/lexer.clj b/src/lux/lexer.clj
index 22e1b3de1..e848cc3fd 100644
--- a/src/lux/lexer.clj
+++ b/src/lux/lexer.clj
@@ -8,10 +8,29 @@
(ns lux.lexer
(:require [clojure.template :refer [do-template]]
- (lux [base :as & :refer [|do return* return fail fail*]]
+ (lux [base :as & :refer [deftags |do return* return fail fail*]]
[reader :as &reader])
[lux.analyser.module :as &module]))
+;; [Tags]
+(deftags ""
+ "White_Space"
+ "Comment"
+ "Bool"
+ "Int"
+ "Real"
+ "Char"
+ "Text"
+ "Symbol"
+ "Tag"
+ "Open_Paren"
+ "Close_Paren"
+ "Open_Bracket"
+ "Close_Bracket"
+ "Open_Brace"
+ "Close_Brace"
+ )
+
;; [Utils]
(defn ^:private escape-char [escaped]
(cond (.equals ^Object escaped "\\t") (return "\t")
@@ -39,12 +58,12 @@
;; [Lexers]
(def ^:private lex-white-space
(|do [[meta white-space] (&reader/read-regex #"^(\s+)")]
- (return (&/V &/$Meta (&/T meta (&/V "White_Space" white-space))))))
+ (return (&/V &/$Meta (&/T meta (&/V $White_Space white-space))))))
(def ^:private lex-single-line-comment
(|do [_ (&reader/read-text "##")
[meta comment] (&reader/read-regex #"^(.*)$")]
- (return (&/V &/$Meta (&/T meta (&/V "Comment" comment))))))
+ (return (&/V &/$Meta (&/T meta (&/V $Comment comment))))))
(defn ^:private lex-multi-line-comment [_]
(|do [_ (&reader/read-text "#(")
@@ -63,7 +82,7 @@
(return (&/T meta (str pre "#(" inner ")#" post))))))
;; :let [_ (prn 'lex-multi-line-comment (str comment ")#"))]
_ (&reader/read-text ")#")]
- (return (&/V &/$Meta (&/T meta (&/V "Comment" comment))))))
+ (return (&/V &/$Meta (&/T meta (&/V $Comment comment))))))
(def ^:private lex-comment
(&/try-all% (&/|list lex-single-line-comment
@@ -74,9 +93,9 @@
(|do [[meta token] (&reader/read-regex <regex>)]
(return (&/V &/$Meta (&/T meta (&/V <tag> token))))))
- ^:private lex-bool "Bool" #"^(true|false)"
- ^:private lex-int "Int" #"^(-?0|-?[1-9][0-9]*)"
- ^:private lex-real "Real" #"^-?(-?0\.[0-9]+|-?[1-9][0-9]*\.[0-9]+)"
+ ^:private lex-bool $Bool #"^(true|false)"
+ ^:private lex-int $Int #"^(-?0|-?[1-9][0-9]*)"
+ ^:private lex-real $Real #"^-?(-?0\.[0-9]+|-?[1-9][0-9]*\.[0-9]+)"
)
(def ^:private lex-char
@@ -86,13 +105,13 @@
(|do [[_ char] (&reader/read-regex #"^(.)")]
(return char))))
_ (&reader/read-text "\"")]
- (return (&/V &/$Meta (&/T meta (&/V "Char" token))))))
+ (return (&/V &/$Meta (&/T meta (&/V $Char token))))))
(def ^:private lex-text
(|do [[meta _] (&reader/read-text "\"")
token (lex-text-body nil)
_ (&reader/read-text "\"")]
- (return (&/V &/$Meta (&/T meta (&/V "Text" token))))))
+ (return (&/V &/$Meta (&/T meta (&/V $Text token))))))
(def ^:private lex-ident
(&/try-all% (&/|list (|do [[meta token] (&reader/read-regex +ident-re+)]
@@ -118,24 +137,24 @@
(def ^:private lex-symbol
(|do [[meta ident] lex-ident]
- (return (&/V &/$Meta (&/T meta (&/V "Symbol" ident))))))
+ (return (&/V &/$Meta (&/T meta (&/V $Symbol ident))))))
(def ^:private lex-tag
(|do [[meta _] (&reader/read-text "#")
[_ ident] lex-ident]
- (return (&/V &/$Meta (&/T meta (&/V "Tag" ident))))))
+ (return (&/V &/$Meta (&/T meta (&/V $Tag ident))))))
(do-template [<name> <text> <tag>]
(def <name>
(|do [[meta _] (&reader/read-text <text>)]
(return (&/V &/$Meta (&/T meta (&/V <tag> nil))))))
- ^:private lex-open-paren "(" "Open_Paren"
- ^:private lex-close-paren ")" "Close_Paren"
- ^:private lex-open-bracket "[" "Open_Bracket"
- ^:private lex-close-bracket "]" "Close_Bracket"
- ^:private lex-open-brace "{" "Open_Brace"
- ^:private lex-close-brace "}" "Close_Brace"
+ ^:private lex-open-paren "(" $Open_Paren
+ ^:private lex-close-paren ")" $Close_Paren
+ ^:private lex-open-bracket "[" $Open_Bracket
+ ^:private lex-close-bracket "]" $Close_Bracket
+ ^:private lex-open-brace "{" $Open_Brace
+ ^:private lex-close-brace "}" $Close_Brace
)
(def ^:private lex-delimiter
diff --git a/src/lux/parser.clj b/src/lux/parser.clj
index 762e2582f..a8b2cfc16 100644
--- a/src/lux/parser.clj
+++ b/src/lux/parser.clj
@@ -10,9 +10,28 @@
(:require [clojure.template :refer [do-template]]
clojure.core.match
clojure.core.match.array
- (lux [base :as & :refer [|do return fail |case]]
+ (lux [base :as & :refer [deftags |do return fail |case]]
[lexer :as &lexer])))
+;; [Tags]
+(deftags ""
+ "White_Space"
+ "Comment"
+ "Bool"
+ "Int"
+ "Real"
+ "Char"
+ "Text"
+ "Symbol"
+ "Tag"
+ "Open_Paren"
+ "Close_Paren"
+ "Open_Bracket"
+ "Close_Bracket"
+ "Open_Brace"
+ "Close_Brace"
+ )
+
;; [Utils]
(do-template [<name> <close-tag> <description> <tag>]
(defn <name> [parse]
@@ -25,8 +44,8 @@
_
(fail (str "[Parser Error] Unbalanced " <description> ".")))))
- ^:private parse-form "Close_Paren" "parantheses" &/$FormS
- ^:private parse-tuple "Close_Bracket" "brackets" &/$TupleS
+ ^:private parse-form $Close_Paren "parantheses" &/$FormS
+ ^:private parse-tuple $Close_Bracket "brackets" &/$TupleS
)
(defn ^:private parse-record [parse]
@@ -34,7 +53,7 @@
token &lexer/lex
:let [elems (&/fold &/|++ (&/|list) elems*)]]
(|case token
- (&/$Meta meta ("Close_Brace" _))
+ (&/$Meta meta ($Close_Brace _))
(if (even? (&/|length elems))
(return (&/V &/$RecordS (&/|as-pairs elems)))
(fail (str "[Parser Error] Records must have an even number of elements.")))
@@ -47,42 +66,42 @@
(|do [token &lexer/lex
:let [(&/$Meta meta token*) token]]
(|case token*
- ("White_Space" _)
+ ($White_Space _)
(return (&/|list))
- ("Comment" _)
+ ($Comment _)
(return (&/|list))
- ("Bool" ?value)
+ ($Bool ?value)
(return (&/|list (&/V &/$Meta (&/T meta (&/V &/$BoolS (Boolean/parseBoolean ?value))))))
- ("Int" ?value)
+ ($Int ?value)
(return (&/|list (&/V &/$Meta (&/T meta (&/V &/$IntS (Integer/parseInt ?value))))))
- ("Real" ?value)
+ ($Real ?value)
(return (&/|list (&/V &/$Meta (&/T meta (&/V &/$RealS (Float/parseFloat ?value))))))
- ("Char" ^String ?value)
+ ($Char ^String ?value)
(return (&/|list (&/V &/$Meta (&/T meta (&/V &/$CharS (.charAt ?value 0))))))
- ("Text" ?value)
+ ($Text ?value)
(return (&/|list (&/V &/$Meta (&/T meta (&/V &/$TextS ?value)))))
- ("Symbol" ?ident)
+ ($Symbol ?ident)
(return (&/|list (&/V &/$Meta (&/T meta (&/V &/$SymbolS ?ident)))))
- ("Tag" ?ident)
+ ($Tag ?ident)
(return (&/|list (&/V &/$Meta (&/T meta (&/V &/$TagS ?ident)))))
- ("Open_Paren" _)
+ ($Open_Paren _)
(|do [syntax (parse-form parse)]
(return (&/|list (&/V &/$Meta (&/T meta syntax)))))
- ("Open_Bracket" _)
+ ($Open_Bracket _)
(|do [syntax (parse-tuple parse)]
(return (&/|list (&/V &/$Meta (&/T meta syntax)))))
- ("Open_Brace" _)
+ ($Open_Brace _)
(|do [syntax (parse-record parse)]
(return (&/|list (&/V &/$Meta (&/T meta syntax)))))
diff --git a/src/lux/reader.clj b/src/lux/reader.clj
index 7cdf9efdf..6aa8cca6d 100644
--- a/src/lux/reader.clj
+++ b/src/lux/reader.clj
@@ -10,7 +10,13 @@
(:require [clojure.string :as string]
clojure.core.match
clojure.core.match.array
- [lux.base :as & :refer [|do return* return fail fail* |let |case]]))
+ [lux.base :as & :refer [deftags |do return* return fail fail* |let |case]]))
+
+;; [Tags]
+(deftags ""
+ "No"
+ "Done"
+ "Yes")
;; [Utils]
(defn ^:private with-line [body]
@@ -22,14 +28,14 @@
(&/$Cons [[file-name line-num column-num] line]
more)
(|case (body file-name line-num column-num line)
- ("No" msg)
+ ($No msg)
(fail* msg)
- ("Done" output)
+ ($Done output)
(return* (&/set$ &/$SOURCE more state)
output)
- ("Yes" output line*)
+ ($Yes output line*)
(return* (&/set$ &/$SOURCE (&/|cons line* more) state)
output))
)))
@@ -79,10 +85,10 @@
match-length (.length match)
column-num* (+ column-num match-length)]
(if (= column-num* (.length line))
- (&/V "Done" (&/T (&/T file-name line-num column-num) match))
- (&/V "Yes" (&/T (&/T (&/T file-name line-num column-num) match)
+ (&/V $Done (&/T (&/T file-name line-num column-num) match))
+ (&/V $Yes (&/T (&/T (&/T file-name line-num column-num) match)
(&/T (&/T file-name line-num column-num*) line)))))
- (&/V "No" (str "[Reader Error] Pattern failed: " regex))))))
+ (&/V $No (str "[Reader Error] Pattern failed: " regex))))))
(defn read-regex2 [regex]
(with-line
@@ -92,10 +98,10 @@
(let [match-length (.length match)
column-num* (+ column-num match-length)]
(if (= column-num* (.length line))
- (&/V "Done" (&/T (&/T file-name line-num column-num) (&/T tok1 tok2)))
- (&/V "Yes" (&/T (&/T (&/T file-name line-num column-num) (&/T tok1 tok2))
+ (&/V $Done (&/T (&/T file-name line-num column-num) (&/T tok1 tok2)))
+ (&/V $Yes (&/T (&/T (&/T file-name line-num column-num) (&/T tok1 tok2))
(&/T (&/T file-name line-num column-num*) line)))))
- (&/V "No" (str "[Reader Error] Pattern failed: " regex))))))
+ (&/V $No (str "[Reader Error] Pattern failed: " regex))))))
(defn read-regex+ [regex]
(with-lines
@@ -127,10 +133,10 @@
(let [match-length (.length text)
column-num* (+ column-num match-length)]
(if (= column-num* (.length line))
- (&/V "Done" (&/T (&/T file-name line-num column-num) text))
- (&/V "Yes" (&/T (&/T (&/T file-name line-num column-num) text)
+ (&/V $Done (&/T (&/T file-name line-num column-num) text))
+ (&/V $Yes (&/T (&/T (&/T file-name line-num column-num) text)
(&/T (&/T file-name line-num column-num*) line)))))
- (&/V "No" (str "[Reader Error] Text failed: " text))))))
+ (&/V $No (str "[Reader Error] Text failed: " text))))))
(def ^:private ^String +source-dir+ "input/")
(defn from [^String file-name ^String file-content]