aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/lux/data
diff options
context:
space:
mode:
Diffstat (limited to 'stdlib/source/lux/data')
-rw-r--r--stdlib/source/lux/data/bit.lux4
-rw-r--r--stdlib/source/lux/data/collection/dictionary.lux10
-rw-r--r--stdlib/source/lux/data/collection/list.lux22
-rw-r--r--stdlib/source/lux/data/collection/sequence.lux13
-rw-r--r--stdlib/source/lux/data/format/css.lux2
-rw-r--r--stdlib/source/lux/data/format/html.lux18
-rw-r--r--stdlib/source/lux/data/format/json.lux40
-rw-r--r--stdlib/source/lux/data/format/xml.lux22
-rw-r--r--stdlib/source/lux/data/maybe.lux13
-rw-r--r--stdlib/source/lux/data/number.lux232
-rw-r--r--stdlib/source/lux/data/text.lux76
-rw-r--r--stdlib/source/lux/data/text/lexer.lux255
-rw-r--r--stdlib/source/lux/data/text/regex.lux109
13 files changed, 464 insertions, 352 deletions
diff --git a/stdlib/source/lux/data/bit.lux b/stdlib/source/lux/data/bit.lux
index 026f8bcab..8cf671429 100644
--- a/stdlib/source/lux/data/bit.lux
+++ b/stdlib/source/lux/data/bit.lux
@@ -45,7 +45,7 @@
## [Values]
(def: #export complement
- {#.doc "Generates the complement of a predicate.
- That is a predicate that returns the oposite of the original predicate."}
+ {#.doc (doc "Generates the complement of a predicate."
+ "That is a predicate that returns the oposite of the original predicate.")}
(All [a] (-> (-> a Bit) (-> a Bit)))
(compose not))
diff --git a/stdlib/source/lux/data/collection/dictionary.lux b/stdlib/source/lux/data/collection/dictionary.lux
index e61d657a5..503ea312d 100644
--- a/stdlib/source/lux/data/collection/dictionary.lux
+++ b/stdlib/source/lux/data/collection/dictionary.lux
@@ -623,18 +623,16 @@
)
(def: #export (merge dict2 dict1)
- {#.doc "Merges 2 dictionaries.
-
- If any collisions with keys occur, the values of dict2 will overwrite those of dict1."}
+ {#.doc (doc "Merges 2 dictionaries."
+ "If any collisions with keys occur, the values of dict2 will overwrite those of dict1.")}
(All [k v] (-> (Dictionary k v) (Dictionary k v) (Dictionary k v)))
(list/fold (function (_ [key val] dict) (put key val dict))
dict1
(entries dict2)))
(def: #export (merge-with f dict2 dict1)
- {#.doc "Merges 2 dictionaries.
-
- If any collisions with keys occur, a new value will be computed by applying 'f' to the values of dict2 and dict1."}
+ {#.doc (doc "Merges 2 dictionaries."
+ "If any collisions with keys occur, a new value will be computed by applying 'f' to the values of dict2 and dict1.")}
(All [k v] (-> (-> v v v) (Dictionary k v) (Dictionary k v) (Dictionary k v)))
(list/fold (function (_ [key val2] dict)
(case (get key dict)
diff --git a/stdlib/source/lux/data/collection/list.lux b/stdlib/source/lux/data/collection/list.lux
index d11f0a080..c49a7ba9f 100644
--- a/stdlib/source/lux/data/collection/list.lux
+++ b/stdlib/source/lux/data/collection/list.lux
@@ -53,9 +53,8 @@
[(filter p xs) (filter (complement p) xs)])
(def: #export (as-pairs xs)
- {#.doc "Cut the list into pairs of 2.
-
- Caveat emptor: If the list has an uneven number of elements, the last one will be skipped."}
+ {#.doc (doc "Cut the list into pairs of 2."
+ "Caveat emptor: If the list has an uneven number of elements, the last one will be skipped.")}
(All [a] (-> (List a) (List [a a])))
(case xs
(^ (#.Cons [x1 (#.Cons [x2 xs'])]))
@@ -436,8 +435,8 @@
(identifier$ ("lux text concat" base "'"))]))))
pattern (` [(~+ (map (function (_ [v vs]) (` (#.Cons (~ v) (~ vs))))
vars+lists))])
- g!step (identifier$ "\tstep\t")
- g!blank (identifier$ "\t_\t")
+ g!step (identifier$ "0step0")
+ g!blank (identifier$ "0_0")
list-vars (map product.right vars+lists)
code (` (: (~ zip-type)
(function ((~ g!step) (~+ list-vars))
@@ -467,8 +466,8 @@
(if (n/> 0 num-lists)
(let [(^open ".") Functor<List>
indices (..indices num-lists)
- g!return-type (identifier$ "\treturn-type\t")
- g!func (identifier$ "\tfunc\t")
+ g!return-type (identifier$ "0return-type0")
+ g!func (identifier$ "0func0")
type-vars (: (List Code) (map (|>> nat/encode identifier$) indices))
zip-type (` (All [(~+ type-vars) (~ g!return-type)]
(-> (-> (~+ type-vars) (~ g!return-type))
@@ -483,8 +482,8 @@
(identifier$ ("lux text concat" base "'"))]))))
pattern (` [(~+ (map (function (_ [v vs]) (` (#.Cons (~ v) (~ vs))))
vars+lists))])
- g!step (identifier$ "\tstep\t")
- g!blank (identifier$ "\t_\t")
+ g!step (identifier$ "0step0")
+ g!blank (identifier$ "0_0")
list-vars (map product.right vars+lists)
code (` (: (~ zip-type)
(function ((~ g!step) (~ g!func) (~+ list-vars))
@@ -517,9 +516,8 @@
(last xs')))
(def: #export (inits xs)
- {#.doc "For a list of size N, returns the first N-1 elements.
-
- Empty lists will result in a #.None value being returned instead."}
+ {#.doc (doc "For a list of size N, returns the first N-1 elements."
+ "Empty lists will result in a #.None value being returned instead.")}
(All [a] (-> (List a) (Maybe (List a))))
(case xs
#.Nil
diff --git a/stdlib/source/lux/data/collection/sequence.lux b/stdlib/source/lux/data/collection/sequence.lux
index 6529a1ced..06209f4d6 100644
--- a/stdlib/source/lux/data/collection/sequence.lux
+++ b/stdlib/source/lux/data/collection/sequence.lux
@@ -41,9 +41,8 @@
(pending [x (repeat x)]))
(def: #export (cycle xs)
- {#.doc "Go over the elements of a list forever.
-
- The list should not be empty."}
+ {#.doc (doc "Go over the elements of a list forever."
+ "The list should not be empty.")}
(All [a]
(-> (List a) (Maybe (Sequence a))))
(case xs
@@ -111,11 +110,9 @@
(filter p xs'))))
(def: #export (partition p xs)
- {#.doc "Split a sequence in two based on a predicate.
-
- The left side contains all entries for which the predicate is #1.
-
- The right side contains all entries for which the predicate is #0."}
+ {#.doc (doc "Split a sequence in two based on a predicate."
+ "The left side contains all entries for which the predicate is #1."
+ "The right side contains all entries for which the predicate is #0.")}
(All [a] (-> (-> a Bit) (Sequence a) [(Sequence a) (Sequence a)]))
[(filter p xs) (filter (complement p) xs)])
diff --git a/stdlib/source/lux/data/format/css.lux b/stdlib/source/lux/data/format/css.lux
index 083195972..fbdad1885 100644
--- a/stdlib/source/lux/data/format/css.lux
+++ b/stdlib/source/lux/data/format/css.lux
@@ -37,7 +37,7 @@
(if (list.empty? style)
""
(format selector "{" (inline style) "}"))))
- (text.join-with "\n")))
+ (text.join-with text.new-line)))
(def: #export (rgb color)
(-> Color Value)
diff --git a/stdlib/source/lux/data/format/html.lux b/stdlib/source/lux/data/format/html.lux
index cc5e6d0e9..45a7117ad 100644
--- a/stdlib/source/lux/data/format/html.lux
+++ b/stdlib/source/lux/data/format/html.lux
@@ -18,7 +18,7 @@
(text.replace-all "&" "&amp;")
(text.replace-all "<" "&lt;")
(text.replace-all ">" "&gt;")
- (text.replace-all "\"" "&quot;")
+ (text.replace-all text.double-quote "&quot;")
(text.replace-all "'" "&#x27;")
(text.replace-all "/" "&#x2F;")))
@@ -28,7 +28,7 @@
(def: attrs-to-text
(-> Attributes Text)
- (|>> (list/map (function (_ [key val]) (format key "=" "\"" (text val) "\"")))
+ (|>> (list/map (function (_ [key val]) (format key "=" text.double-quote (text val) text.double-quote)))
(text.join-with " ")))
(def: #export (tag name attrs children)
@@ -39,13 +39,15 @@
"</" name ">"))
(do-template [<name> <doc-type>]
- [(def: #export (<name> document)
+ [(def: #export <name>
(-> HTML HTML)
- (format <doc-type>
- document))]
+ (let [doc-type <doc-type>]
+ (function (_ document)
+ (format doc-type
+ document))))]
[html-5 "<!DOCTYPE html>"]
- [html-4_01 "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">"]
- [xhtml-1_0 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">"]
- [xhtml-1_1 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.1//EN\" \"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd\">"]
+ [html-4_01 (format "<!DOCTYPE HTML PUBLIC " text.double-quote "-//W3C//DTD HTML 4.01//EN" text.double-quote " " text.double-quote "http://www.w3.org/TR/html4/strict.dtd" text.double-quote ">")]
+ [xhtml-1_0 (format "<!DOCTYPE html PUBLIC " text.double-quote "-//W3C//DTD XHTML 1.0 Strict//EN" text.double-quote " " text.double-quote "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" text.double-quote ">")]
+ [xhtml-1_1 (format "<!DOCTYPE html PUBLIC " text.double-quote "-//W3C//DTD XHTML 1.1//EN" text.double-quote " " text.double-quote "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd" text.double-quote ">")]
)
diff --git a/stdlib/source/lux/data/format/json.lux b/stdlib/source/lux/data/format/json.lux
index 3594ef28c..20f059503 100644
--- a/stdlib/source/lux/data/format/json.lux
+++ b/stdlib/source/lux/data/format/json.lux
@@ -1,6 +1,5 @@
-(.module: {#.doc "Functionality for reading and writing values in the JSON format.
-
- For more information, please see: http://www.json.org/"}
+(.module: {#.doc (.doc "Functionality for reading and writing values in the JSON format."
+ "For more information, please see: http://www.json.org/")}
[lux #*
[control
["." monad (#+ do Monad)]
@@ -114,10 +113,10 @@
(#e.Success value)
#.None
- (#e.Error ($_ text/compose "Missing field \"" key "\" on object.")))
+ (#e.Error ($_ text/compose "Missing field '" key "' on object.")))
_
- (#e.Error ($_ text/compose "Cannot get field \"" key "\" of a non-object."))))
+ (#e.Error ($_ text/compose "Cannot get field '" key "' of a non-object."))))
(def: #export (set key value json)
{#.doc "A JSON object field setter."}
@@ -127,7 +126,7 @@
(#e.Success (#Object (dict.put key value obj)))
_
- (#e.Error ($_ text/compose "Cannot set field \"" key "\" of a non-object."))))
+ (#e.Error ($_ text/compose "Cannot set field '" key "' of a non-object."))))
(do-template [<name> <tag> <type> <desc>]
[(def: #export (<name> key json)
@@ -353,7 +352,7 @@
(fail error))
_
- (fail ($_ text/compose "JSON object does not have field \"" field-name "\".")))
+ (fail ($_ text/compose "JSON object does not have field '" field-name "'.")))
_
(fail "JSON value is not an object."))))
@@ -453,22 +452,29 @@
(def: escaped~
(l.Lexer Text)
($_ p.either
- (p.after (l.this "\\t") (parser/wrap "\t"))
- (p.after (l.this "\\b") (parser/wrap "\b"))
- (p.after (l.this "\\n") (parser/wrap "\n"))
- (p.after (l.this "\\r") (parser/wrap "\r"))
- (p.after (l.this "\\f") (parser/wrap "\f"))
- (p.after (l.this "\\\"") (parser/wrap "\""))
- (p.after (l.this "\\\\") (parser/wrap "\\"))))
+ (p.after (l.this "\t")
+ (parser/wrap text.tab))
+ (p.after (l.this "\b")
+ (parser/wrap text.back-space))
+ (p.after (l.this "\n")
+ (parser/wrap text.new-line))
+ (p.after (l.this "\r")
+ (parser/wrap text.carriage-return))
+ (p.after (l.this "\f")
+ (parser/wrap text.form-feed))
+ (p.after (l.this (text/compose "\" text.double-quote))
+ (parser/wrap text.double-quote))
+ (p.after (l.this "\\")
+ (parser/wrap "\"))))
(def: string~
(l.Lexer String)
- (<| (l.enclosed ["\"" "\""])
+ (<| (l.enclosed [text.double-quote text.double-quote])
(loop [_ []])
(do p.Monad<Parser>
- [chars (l.some (l.none-of "\\\""))
+ [chars (l.some (l.none-of (text/compose "\" text.double-quote)))
stop l.peek])
- (if (text/= "\\" stop)
+ (if (text/= "\" stop)
(do @
[escaped escaped~
next-chars (recur [])]
diff --git a/stdlib/source/lux/data/format/xml.lux b/stdlib/source/lux/data/format/xml.lux
index 61215813b..0ed744b46 100644
--- a/stdlib/source/lux/data/format/xml.lux
+++ b/stdlib/source/lux/data/format/xml.lux
@@ -33,7 +33,7 @@
(p.after (l.this "&gt;") (parser/wrap ">"))
(p.after (l.this "&amp;") (parser/wrap "&"))
(p.after (l.this "&apos;") (parser/wrap "'"))
- (p.after (l.this "&quot;") (parser/wrap "\""))))
+ (p.after (l.this "&quot;") (parser/wrap text.double-quote))))
(def: xml-unicode-escape-char^
(l.Lexer Text)
@@ -56,7 +56,7 @@
(def: xml-char^
(l.Lexer Text)
- (p.either (l.none-of "<>&'\"")
+ (p.either (l.none-of ($_ text/compose "<>&'" text.double-quote))
xml-escape-char^))
(def: xml-identifier
@@ -92,7 +92,7 @@
(def: attr-value^
(l.Lexer Text)
(let [value^ (l.some xml-char^)]
- (p.either (l.enclosed ["\"" "\""] value^)
+ (p.either (l.enclosed [text.double-quote text.double-quote] value^)
(l.enclosed ["'" "'"] value^))))
(def: attrs^
@@ -110,9 +110,9 @@
spaced^
(p.after (l.this "/"))
(l.enclosed ["<" ">"]))]
- (p.assert ($_ text/compose "Close tag does not match open tag.\n"
- "Expected: " (name/encode expected) "\n"
- " Actual: " (name/encode actual) "\n")
+ (p.assert ($_ text/compose "Close tag does not match open tag." text.new-line
+ "Expected: " (name/encode expected) text.new-line
+ " Actual: " (name/encode actual) text.new-line)
(name/= expected actual))))
(def: comment^
@@ -181,7 +181,7 @@
(text.replace-all "<" "&lt;")
(text.replace-all ">" "&gt;")
(text.replace-all "'" "&apos;")
- (text.replace-all "\"" "&quot;")))
+ (text.replace-all text.double-quote "&quot;")))
(def: (write-tag [namespace name])
(-> Tag Text)
@@ -194,12 +194,12 @@
(|> attrs
d.entries
(list/map (function (_ [key value])
- ($_ text/compose (write-tag key) "=" "\""(sanitize-value value) "\"")))
+ ($_ text/compose (write-tag key) "=" text.double-quote (sanitize-value value) text.double-quote)))
(text.join-with " ")))
(def: xml-header
Text
- "<?xml version=\"1.0\" encoding=\"UTF-8\"?>")
+ ($_ text/compose "<?xml version=" text.double-quote "1.0" text.double-quote " encoding=" text.double-quote "UTF-8" text.double-quote "?>"))
(def: #export (write input)
(-> XML Text)
@@ -254,10 +254,12 @@
(exception: #export (wrong-tag {tag Name})
(name/encode tag))
+(def: blank-line ($_ text/compose text.new-line text.new-line))
+
(exception: #export (unconsumed-inputs {inputs (List XML)})
(|> inputs
(list/map (:: Codec<Text,XML> encode))
- (text.join-with "\n\n")))
+ (text.join-with blank-line)))
(def: #export text
(Reader Text)
diff --git a/stdlib/source/lux/data/maybe.lux b/stdlib/source/lux/data/maybe.lux
index 57ff95727..d0dfe1886 100644
--- a/stdlib/source/lux/data/maybe.lux
+++ b/stdlib/source/lux/data/maybe.lux
@@ -82,11 +82,14 @@
(monad.lift Monad<M> (:: Monad<Maybe> wrap)))
(macro: #export (default tokens state)
- {#.doc "## Allows you to provide a default value that will be used
- ## if a (Maybe x) value turns out to be #.None.
- (default +20 (#.Some +10)) => +10
-
- (default +20 #.None) => +20"}
+ {#.doc (doc "Allows you to provide a default value that will be used"
+ "if a (Maybe x) value turns out to be #.None."
+ (default +20 (#.Some +10))
+ "=>"
+ +10
+ (default +20 #.None)
+ "=>"
+ +20)}
(case tokens
(^ (list else maybe))
(let [g!temp (: Code [dummy-cursor (#.Identifier ["" ""])])
diff --git a/stdlib/source/lux/data/number.lux b/stdlib/source/lux/data/number.lux
index 4b3b786b4..efd965d1b 100644
--- a/stdlib/source/lux/data/number.lux
+++ b/stdlib/source/lux/data/number.lux
@@ -178,9 +178,11 @@
)
## [Values & Syntax]
-(def: (get-char full idx)
- (-> Text Nat (Maybe Text))
- ("lux text clip" full idx (inc idx)))
+(type: Char Nat)
+
+(def: (get-char! full idx)
+ (-> Text Nat Char)
+ ("lux text char" full idx))
(def: (binary-character value)
(-> Nat (Maybe Text))
@@ -190,10 +192,10 @@
_ #.None))
(def: (binary-value digit)
- (-> Text (Maybe Nat))
+ (-> Char (Maybe Nat))
(case digit
- "0" (#.Some 0)
- "1" (#.Some 1)
+ (^ (char "0")) (#.Some 0)
+ (^ (char "1")) (#.Some 1)
_ #.None))
(def: (octal-character value)
@@ -210,16 +212,16 @@
_ #.None))
(def: (octal-value digit)
- (-> Text (Maybe Nat))
+ (-> Char (Maybe Nat))
(case digit
- "0" (#.Some 0)
- "1" (#.Some 1)
- "2" (#.Some 2)
- "3" (#.Some 3)
- "4" (#.Some 4)
- "5" (#.Some 5)
- "6" (#.Some 6)
- "7" (#.Some 7)
+ (^ (char "0")) (#.Some 0)
+ (^ (char "1")) (#.Some 1)
+ (^ (char "2")) (#.Some 2)
+ (^ (char "3")) (#.Some 3)
+ (^ (char "4")) (#.Some 4)
+ (^ (char "5")) (#.Some 5)
+ (^ (char "6")) (#.Some 6)
+ (^ (char "7")) (#.Some 7)
_ #.None))
(def: (decimal-character value)
@@ -238,18 +240,18 @@
_ #.None))
(def: (decimal-value digit)
- (-> Text (Maybe Nat))
+ (-> Char (Maybe Nat))
(case digit
- "0" (#.Some 0)
- "1" (#.Some 1)
- "2" (#.Some 2)
- "3" (#.Some 3)
- "4" (#.Some 4)
- "5" (#.Some 5)
- "6" (#.Some 6)
- "7" (#.Some 7)
- "8" (#.Some 8)
- "9" (#.Some 9)
+ (^ (char "0")) (#.Some 0)
+ (^ (char "1")) (#.Some 1)
+ (^ (char "2")) (#.Some 2)
+ (^ (char "3")) (#.Some 3)
+ (^ (char "4")) (#.Some 4)
+ (^ (char "5")) (#.Some 5)
+ (^ (char "6")) (#.Some 6)
+ (^ (char "7")) (#.Some 7)
+ (^ (char "8")) (#.Some 8)
+ (^ (char "9")) (#.Some 9)
_ #.None))
(def: (hexadecimal-character value)
@@ -274,24 +276,24 @@
_ #.None))
(def: (hexadecimal-value digit)
- (-> Text (Maybe Nat))
+ (-> Char (Maybe Nat))
(case digit
- "0" (#.Some 0)
- "1" (#.Some 1)
- "2" (#.Some 2)
- "3" (#.Some 3)
- "4" (#.Some 4)
- "5" (#.Some 5)
- "6" (#.Some 6)
- "7" (#.Some 7)
- "8" (#.Some 8)
- "9" (#.Some 9)
- (^or "a" "A") (#.Some 10)
- (^or "b" "B") (#.Some 11)
- (^or "c" "C") (#.Some 12)
- (^or "d" "D") (#.Some 13)
- (^or "e" "E") (#.Some 14)
- (^or "f" "F") (#.Some 15)
+ (^ (char "0")) (#.Some 0)
+ (^ (char "1")) (#.Some 1)
+ (^ (char "2")) (#.Some 2)
+ (^ (char "3")) (#.Some 3)
+ (^ (char "4")) (#.Some 4)
+ (^ (char "5")) (#.Some 5)
+ (^ (char "6")) (#.Some 6)
+ (^ (char "7")) (#.Some 7)
+ (^ (char "8")) (#.Some 8)
+ (^ (char "9")) (#.Some 9)
+ (^or (^ (char "a")) (^ (char "A"))) (#.Some 10)
+ (^or (^ (char "b")) (^ (char "B"))) (#.Some 11)
+ (^or (^ (char "c")) (^ (char "C"))) (#.Some 12)
+ (^or (^ (char "d")) (^ (char "D"))) (#.Some 13)
+ (^or (^ (char "e")) (^ (char "E"))) (#.Some 14)
+ (^or (^ (char "f")) (^ (char "F"))) (#.Some 15)
_ #.None))
(do-template [<struct> <base> <to-character> <to-value> <error>]
@@ -312,14 +314,13 @@
(loop [idx 0
output 0]
(if (n/< input-size idx)
- (let [digit (maybe.assume (get-char repr idx))]
- (case (<to-value> digit)
- #.None
- (#error.Error ("lux text concat" <error> repr))
-
- (#.Some digit-value)
- (recur (inc idx)
- (|> output (n/* <base>) (n/+ digit-value)))))
+ (case (<to-value> (get-char! repr idx))
+ #.None
+ (#error.Error ("lux text concat" <error> repr))
+
+ (#.Some digit-value)
+ (recur (inc idx)
+ (|> output (n/* <base>) (n/+ digit-value))))
(#error.Success output)))
(#error.Error ("lux text concat" <error> repr))))))]
@@ -337,29 +338,28 @@
(def: (int/sign?? representation)
(-> Text (Maybe Int))
- (case (get-char representation 0)
- (^ (#.Some "-"))
+ (case (get-char! representation 0)
+ (^ (char "-"))
(#.Some -1)
- (^ (#.Some "+"))
+ (^ (char "+"))
(#.Some +1)
_
#.None))
(def: (int-decode-loop input-size repr sign <base> <to-value> <error>)
- (-> Nat Text Int Int (-> Text (Maybe Nat)) Text (Error Int))
+ (-> Nat Text Int Int (-> Char (Maybe Nat)) Text (Error Int))
(loop [idx 1
output +0]
(if (n/< input-size idx)
- (let [digit (maybe.assume (get-char repr idx))]
- (case (<to-value> digit)
- #.None
- (#error.Error <error>)
+ (case (<to-value> (get-char! repr idx))
+ #.None
+ (#error.Error <error>)
- (#.Some digit-value)
- (recur (inc idx)
- (|> output (i/* <base>) (i/+ (.int digit-value))))))
+ (#.Some digit-value)
+ (recur (inc idx)
+ (|> output (i/* <base>) (i/+ (.int digit-value)))))
(#error.Success (i/* sign output)))))
(do-template [<struct> <base> <to-character> <to-value> <error>]
@@ -396,35 +396,39 @@
(def: (de-prefix input)
(-> Text Text)
- (maybe.assume ("lux text clip" input 1 ("lux text size" input))))
+ ("lux text clip" input 1 ("lux text size" input)))
(do-template [<struct> <nat> <char-bit-size> <error>]
- [(structure: #export <struct> (Codec Text Rev)
- (def: (encode value)
- (let [raw-output (de-prefix (:: <nat> encode (:coerce Nat value)))
- max-num-chars (n// <char-bit-size> 64)
- raw-size ("lux text size" raw-output)
- zero-padding (loop [zeroes-left (n/- raw-size max-num-chars)
- output ""]
- (if (n/= 0 zeroes-left)
- output
- (recur (dec zeroes-left)
- ("lux text concat" "0" output))))
- padded-output ("lux text concat" zero-padding raw-output)]
- ("lux text concat" "." padded-output)))
-
- (def: (decode repr)
- (let [repr-size ("lux text size" repr)]
- (if (n/>= 2 repr-size)
- (case ("lux text char" repr 0)
- (^multi (^ (#.Some (char ".")))
- [(:: <nat> decode (de-prefix repr))
- (#error.Success output)])
- (#error.Success (:coerce Rev output))
-
- _
- (#error.Error ("lux text concat" <error> repr)))
- (#error.Error ("lux text concat" <error> repr))))))]
+ [(with-expansions [<error-output> (as-is (#error.Error ("lux text concat" <error> repr)))]
+ (structure: #export <struct> (Codec Text Rev)
+ (def: (encode value)
+ (let [raw-output (de-prefix (:: <nat> encode (:coerce Nat value)))
+ max-num-chars (n// <char-bit-size> 64)
+ raw-size ("lux text size" raw-output)
+ zero-padding (loop [zeroes-left (n/- raw-size max-num-chars)
+ output ""]
+ (if (n/= 0 zeroes-left)
+ output
+ (recur (dec zeroes-left)
+ ("lux text concat" "0" output))))
+ padded-output ("lux text concat" zero-padding raw-output)]
+ ("lux text concat" "." padded-output)))
+
+ (def: (decode repr)
+ (let [repr-size ("lux text size" repr)]
+ (if (n/>= 2 repr-size)
+ (case ("lux text char" repr 0)
+ (^ (char "."))
+ (case (:: <nat> decode (de-prefix repr))
+ (#error.Success output)
+ (#error.Success (:coerce Rev output))
+
+ _
+ <error-output>)
+
+ _
+ <error-output>)
+ <error-output>)))))]
[Binary@Codec<Text,Rev> Binary@Codec<Text,Nat> 1 "Invalid binary syntax: "]
[Octal@Codec<Text,Rev> Octal@Codec<Text,Nat> 3 "Invalid octal syntax: "]
@@ -444,17 +448,16 @@
(if (f/= +0.0 dec-left)
("lux text concat" "." output)
(let [shifted (f/* <base> dec-left)
- digit (|> shifted (f/% <base>) frac-to-int .nat
- (get-char <char-set>) maybe.assume)]
+ digit-idx (|> shifted (f/% <base>) frac-to-int .nat)]
(recur (f/% +1.0 shifted)
- ("lux text concat" output digit))))))]
+ ("lux text concat" output ("lux text clip" <char-set> digit-idx (inc digit-idx))))))))]
("lux text concat" whole-part decimal-part)))
(def: (decode repr)
(case ("lux text index" repr "." 0)
(#.Some split-index)
- (let [whole-part (maybe.assume ("lux text clip" repr 0 split-index))
- decimal-part (maybe.assume ("lux text clip" repr (inc split-index) ("lux text size" repr)))]
+ (let [whole-part ("lux text clip" repr 0 split-index)
+ decimal-part ("lux text clip" repr (inc split-index) ("lux text size" repr))]
(case [(:: <int> decode whole-part)
(:: <int> decode decimal-part)]
(^multi [(#error.Success whole) (#error.Success decimal)]
@@ -498,8 +501,8 @@
(if (n/<= chunk-size num-digits)
(list digits)
(let [boundary (n/- chunk-size num-digits)
- chunk (maybe.assume ("lux text clip" digits boundary num-digits))
- remaining (maybe.assume ("lux text clip" digits 0 boundary))]
+ chunk ("lux text clip" digits boundary num-digits)
+ remaining ("lux text clip" digits 0 boundary)]
(list& chunk (segment-digits chunk-size remaining)))))))
(def: (bin-segment-to-hex input)
@@ -627,10 +630,10 @@
(let [sign (:: Number<Frac> signum value)
raw-bin (:: Binary@Codec<Text,Frac> encode value)
dot-idx (maybe.assume ("lux text index" raw-bin "." 0))
- whole-part (maybe.assume ("lux text clip" raw-bin
- (if (f/= -1.0 sign) 1 0)
- dot-idx))
- decimal-part (maybe.assume ("lux text clip" raw-bin (inc dot-idx) ("lux text size" raw-bin)))
+ whole-part ("lux text clip" raw-bin
+ (if (f/= -1.0 sign) 1 0)
+ dot-idx)
+ decimal-part ("lux text clip" raw-bin (inc dot-idx) ("lux text size" raw-bin))
hex-output (|> (<from> #0 decimal-part)
("lux text concat" ".")
("lux text concat" (<from> #1 whole-part))
@@ -646,8 +649,8 @@
+1.0)]
(case ("lux text index" repr "." 0)
(#.Some split-index)
- (let [whole-part (maybe.assume ("lux text clip" repr 1 split-index))
- decimal-part (maybe.assume ("lux text clip" repr (inc split-index) ("lux text size" repr)))
+ (let [whole-part ("lux text clip" repr 1 split-index)
+ decimal-part ("lux text clip" repr (inc split-index) ("lux text size" repr))
as-binary (|> (<to> decimal-part)
("lux text concat" ".")
("lux text concat" (<to> whole-part))
@@ -674,15 +677,13 @@
encoding
" number, generates a Nat, an Int, a Rev or a Frac.")
underscore "Allows for the presence of underscore in the numbers."
- description [cursor (#.Text ($_ "lux text concat"
- encoding "\n"
- underscore))]]
+ description [cursor (#.Text ($_ "lux text concat" encoding " " underscore))]]
(#error.Success [state (list (` (doc (~ description)
(~ example-1)
(~ example-2))))]))
_
- (#error.Error "Wrong syntax for \"encoding-doc\".")))
+ (#error.Error "Wrong syntax for 'encoding-doc'.")))
(def: (underscore-prefixed? number)
(-> Text Bit)
@@ -831,14 +832,13 @@
(loop [idx 0
output (make-digits [])]
(if (n/< length idx)
- (let [char (maybe.assume (get-char input idx))]
- (case ("lux text index" "+0123456789" char 0)
- #.None
- #.None
-
- (#.Some digit)
- (recur (inc idx)
- (digits-put idx digit output))))
+ (case ("lux text index" "+0123456789" ("lux text clip" input idx (inc idx)) 0)
+ #.None
+ #.None
+
+ (#.Some digit)
+ (recur (inc idx)
+ (digits-put idx digit output)))
(#.Some output)))
#.None)))
@@ -902,9 +902,7 @@
#0)]
(if (and dotted?
(n/<= (inc i64.width) length))
- (case (|> ("lux text clip" input 1 length)
- maybe.assume
- text-to-digits)
+ (case (text-to-digits ("lux text clip" input 1 length))
(#.Some digits)
(loop [digits digits
idx 0
diff --git a/stdlib/source/lux/data/text.lux b/stdlib/source/lux/data/text.lux
index 48f35febe..18ad49032 100644
--- a/stdlib/source/lux/data/text.lux
+++ b/stdlib/source/lux/data/text.lux
@@ -16,13 +16,31 @@
[compiler
["." host]]])
+(def: #export from-code
+ (-> Nat Text)
+ (|>> (:coerce Int) "lux int char"))
+
+(do-template [<name> <code>]
+ [(def: #export <name> (from-code <code>))]
+
+ [back-space 8]
+ [tab 9]
+ [new-line 10]
+ [vertical-tab 11]
+ [form-feed 12]
+ [carriage-return 13]
+ [double-quote 34]
+ )
+
(def: #export (size x)
(-> Text Nat)
("lux text size" x))
(def: #export (nth idx input)
(-> Nat Text (Maybe Nat))
- ("lux text char" input idx))
+ (if (n/< ("lux text size" input) idx)
+ (#.Some ("lux text char" input idx))
+ #.None))
(def: #export (index-of' pattern from input)
(-> Text Nat Text (Maybe Nat))
@@ -89,11 +107,17 @@
(def: #export (clip from to input)
(-> Nat Nat Text (Maybe Text))
- ("lux text clip" input from to))
+ (if (and (n/<= to from)
+ (n/<= ("lux text size" input) to))
+ (#.Some ("lux text clip" input from to))
+ #.None))
(def: #export (clip' from input)
(-> Nat Text (Maybe Text))
- ("lux text clip" input from (size input)))
+ (let [size ("lux text size" input)]
+ (if (n/<= size from)
+ (#.Some ("lux text clip" input from size))
+ #.None)))
(def: #export (split at x)
(-> Nat Text (Maybe [Text Text]))
@@ -122,7 +146,7 @@
(#.Cons sample #.Nil)))
(def: #export split-lines
- (..split-all-with "\n"))
+ (..split-all-with ..new-line))
(def: #export (replace-once pattern value template)
(-> Text Text Text Text)
@@ -182,12 +206,11 @@
(loop [idx 0
hash 0]
(if (n/< length idx)
- (let [char (|> idx ("lux text char" input) (maybe.default 0))]
- (recur (inc idx)
- (|> hash
- (i64.left-shift 5)
- (n/- hash)
- (n/+ char))))
+ (recur (inc idx)
+ (|> hash
+ (i64.left-shift 5)
+ (n/- hash)
+ (n/+ ("lux text char" input idx))))
hash)))))))
(def: #export concat
@@ -218,28 +241,19 @@
(def: #export encode
(-> Text Text)
- (|>> (replace-all "\\" "\\\\")
- (replace-all "\t" "\\t")
- (replace-all "\v" "\\v")
- (replace-all "\b" "\\b")
- (replace-all "\n" "\\n")
- (replace-all "\r" "\\r")
- (replace-all "\f" "\\f")
- (replace-all "\"" "\\\"")
- (..enclose' "\"")))
-
-(def: #export from-code
- (-> Nat Text)
- (|>> (:coerce Int) "lux int char"))
+ (..enclose' ..double-quote))
(def: #export (space? char)
{#.doc "Checks whether the character is white-space."}
(-> Nat Bit)
- (case char
- (^or (^ (char "\t")) (^ (char "\v"))
- (^ (char " ")) (^ (char "\n"))
- (^ (char "\r")) (^ (char "\f")))
- #1
-
- _
- #0))
+ (`` (case char
+ (^or (^ (char (~~ (static ..tab))))
+ (^ (char (~~ (static ..vertical-tab))))
+ (^ (char " "))
+ (^ (char (~~ (static ..new-line))))
+ (^ (char (~~ (static ..carriage-return))))
+ (^ (char (~~ (static ..form-feed)))))
+ #1
+
+ _
+ #0)))
diff --git a/stdlib/source/lux/data/text/lexer.lux b/stdlib/source/lux/data/text/lexer.lux
index 481d17b0a..21aba8360 100644
--- a/stdlib/source/lux/data/text/lexer.lux
+++ b/stdlib/source/lux/data/text/lexer.lux
@@ -4,25 +4,29 @@
[monad (#+ do Monad)]
["p" parser]]
[data
- ["." text ("text/." Monoid<Text>)]
["." product]
["." maybe]
["e" error]
[collection
- ["." list]]]
+ ["." list ("list/." Fold<List>)]]]
[macro
- ["." code]]])
+ ["." code]]]
+ ["." // ("text/." Monoid<Text>)])
-(type: Offset Nat)
+(type: #export Offset Nat)
(def: start-offset Offset 0)
(type: #export Lexer
(p.Parser [Offset Text]))
+(type: #export Slice
+ {#basis Offset
+ #distance Offset})
+
(def: (remaining offset tape)
(-> Offset Text Text)
- (|> tape (text.split offset) maybe.assume product.right))
+ (|> tape (//.split offset) maybe.assume product.right))
(def: cannot-lex-error Text "Cannot lex from empty text.")
@@ -37,54 +41,85 @@
(#e.Error msg)
(#e.Success [[end-offset _] output])
- (if (n/= end-offset (text.size input))
+ (if (n/= end-offset (//.size input))
(#e.Success output)
(#e.Error (unconsumed-input-error end-offset input)))
))
+(def: #export offset
+ (Lexer Offset)
+ (function (_ (^@ input [offset tape]))
+ (#e.Success [input offset])))
+
+(def: (with-slices lexer)
+ (-> (Lexer (List Slice)) (Lexer Slice))
+ (do p.Monad<Parser>
+ [offset ..offset
+ slices lexer]
+ (wrap (list/fold (function (_ [slice::basis slice::distance]
+ [total::basis total::distance])
+ [total::basis ("lux i64 +" slice::distance total::distance)])
+ {#basis offset
+ #distance 0}
+ slices))))
+
(def: #export any
{#.doc "Just returns the next character without applying any logic."}
(Lexer Text)
(function (_ [offset tape])
- (case (text.nth offset tape)
+ (case (//.nth offset tape)
(#.Some output)
- (#e.Success [[(inc offset) tape] (text.from-code output)])
+ (#e.Success [[("lux i64 +" 1 offset) tape] (//.from-code output)])
_
- (#e.Error cannot-lex-error))
- ))
+ (#e.Error cannot-lex-error))))
-(def: #export (not p)
- {#.doc "Produce a character if the lexer fails."}
- (All [a] (-> (Lexer a) (Lexer Text)))
- (function (_ input)
- (case (p input)
- (#e.Error msg)
- (any input)
-
- _
- (#e.Error "Expected to fail; yet succeeded."))))
+(def: #export any!
+ {#.doc "Just returns the next character without applying any logic."}
+ (Lexer Slice)
+ (function (_ [offset tape])
+ (#e.Success [[("lux i64 +" 1 offset) tape]
+ {#basis offset
+ #distance 1}])))
+
+(do-template [<name> <type> <any>]
+ [(def: #export (<name> p)
+ {#.doc "Produce a character if the lexer fails."}
+ (All [a] (-> (Lexer a) (Lexer <type>)))
+ (function (_ input)
+ (case (p input)
+ (#e.Error msg)
+ (<any> input)
+
+ _
+ (#e.Error "Expected to fail; yet succeeded."))))]
+
+ [not Text ..any]
+ [not! Slice ..any!]
+ )
(def: #export (this reference)
{#.doc "Lex a text if it matches the given sample."}
(-> Text (Lexer Any))
(function (_ [offset tape])
- (case (text.index-of' reference offset tape)
+ (case (//.index-of' reference offset tape)
(#.Some where)
(if (n/= offset where)
- (#e.Success [[(n/+ (text.size reference) offset) tape] []])
- (#e.Error ($_ text/compose "Could not match: " (text.encode reference) " @ " (maybe.assume (text.clip' offset tape)))))
+ (#e.Success [[("lux i64 +" (//.size reference) offset) tape]
+ []])
+ (#e.Error ($_ text/compose "Could not match: " (//.encode reference) " @ " (maybe.assume (//.clip' offset tape)))))
_
- (#e.Error ($_ text/compose "Could not match: " (text.encode reference))))))
+ (#e.Error ($_ text/compose "Could not match: " (//.encode reference))))))
(def: #export (this? reference)
{#.doc "Lex a text if it matches the given sample."}
(-> Text (Lexer Bit))
(function (_ (^@ input [offset tape]))
- (case (text.index-of' reference offset tape)
+ (case (//.index-of' reference offset tape)
(^multi (#.Some where) (n/= offset where))
- (#e.Success [[(n/+ (text.size reference) offset) tape] #1])
+ (#e.Success [[("lux i64 +" (//.size reference) offset) tape]
+ #1])
_
(#e.Success [input #0]))))
@@ -93,7 +128,7 @@
{#.doc "Ensure the lexer's input is empty."}
(Lexer Any)
(function (_ (^@ input [offset tape]))
- (if (n/= offset (text.size tape))
+ (if (n/= offset (//.size tape))
(#e.Success [input []])
(#e.Error (unconsumed-input-error offset tape)))))
@@ -101,19 +136,18 @@
{#.doc "Ask if the lexer's input is empty."}
(Lexer Bit)
(function (_ (^@ input [offset tape]))
- (#e.Success [input (n/= offset (text.size tape))])))
+ (#e.Success [input (n/= offset (//.size tape))])))
(def: #export peek
{#.doc "Lex the next character (without consuming it from the input)."}
(Lexer Text)
(function (_ (^@ input [offset tape]))
- (case (text.nth offset tape)
+ (case (//.nth offset tape)
(#.Some output)
- (#e.Success [input (text.from-code output)])
+ (#e.Success [input (//.from-code output)])
_
- (#e.Error cannot-lex-error))
- ))
+ (#e.Error cannot-lex-error))))
(def: #export get-input
{#.doc "Get all of the remaining input (without consuming it)."}
@@ -126,8 +160,8 @@
(-> Nat Nat (Lexer Text))
(do p.Monad<Parser>
[char any
- #let [char' (maybe.assume (text.nth 0 char))]
- _ (p.assert ($_ text/compose "Character is not within range: " (text.from-code bottom) "-" (text.from-code top))
+ #let [char' (maybe.assume (//.nth 0 char))]
+ _ (p.assert ($_ text/compose "Character is not within range: " (//.from-code bottom) "-" (//.from-code top))
(.and (n/>= bottom char')
(n/<= top char')))]
(wrap char)))
@@ -162,43 +196,59 @@
(range (char "a") (char "f"))
(range (char "A") (char "F"))))
-(def: #export (one-of options)
- {#.doc "Only lex characters that are part of a piece of text."}
- (-> Text (Lexer Text))
- (function (_ [offset tape])
- (case (text.nth offset tape)
- (#.Some output)
- (let [output (text.from-code output)]
- (if (text.contains? output options)
- (#e.Success [[(inc offset) tape] output])
- (#e.Error ($_ text/compose "Character (" output ") is not one of: " options))))
-
- _
- (#e.Error cannot-lex-error))))
-
-(def: #export (none-of options)
- {#.doc "Only lex characters that are not part of a piece of text."}
- (-> Text (Lexer Text))
- (function (_ [offset tape])
- (case (text.nth offset tape)
- (#.Some output)
- (let [output (text.from-code output)]
- (if (.not (text.contains? output options))
- (#e.Success [[(inc offset) tape] output])
- (#e.Error ($_ text/compose "Character (" output ") is one of: " options))))
+(do-template [<name> <description-modifier> <modifier>]
+ [(def: #export (<name> options)
+ {#.doc (code.text ($_ text/compose "Only lex characters that are" <description-modifier> " part of a piece of text."))}
+ (-> Text (Lexer Text))
+ (function (_ [offset tape])
+ (case (//.nth offset tape)
+ (#.Some output)
+ (let [output (//.from-code output)]
+ (if (<modifier> (//.contains? output options))
+ (#e.Success [[("lux i64 +" 1 offset) tape] output])
+ (#e.Error ($_ text/compose "Character (" output
+ ") is should " <description-modifier>
+ "be one of: " options))))
+
+ _
+ (#e.Error cannot-lex-error))))]
+
+ [one-of "" |>]
+ [none-of " not" .not]
+ )
- _
- (#e.Error cannot-lex-error))))
+(do-template [<name> <description-modifier> <modifier>]
+ [(def: #export (<name> options)
+ {#.doc (code.text ($_ text/compose "Only lex characters that are" <description-modifier> " part of a piece of text."))}
+ (-> Text (Lexer Slice))
+ (function (_ [offset tape])
+ (case (//.nth offset tape)
+ (#.Some output)
+ (let [output (//.from-code output)]
+ (if (<modifier> (//.contains? output options))
+ (#e.Success [[("lux i64 +" 1 offset) tape]
+ {#basis offset
+ #distance 1}])
+ (#e.Error ($_ text/compose "Character (" output
+ ") is should " <description-modifier>
+ "be one of: " options))))
+
+ _
+ (#e.Error cannot-lex-error))))]
+
+ [one-of! "" |>]
+ [none-of! " not" .not]
+ )
(def: #export (satisfies p)
{#.doc "Only lex characters that satisfy a predicate."}
(-> (-> Nat Bit) (Lexer Text))
(function (_ [offset tape])
- (case (text.nth offset tape)
+ (case (//.nth offset tape)
(#.Some output)
(if (p output)
- (#e.Success [[(inc offset) tape] (text.from-code output)])
- (#e.Error ($_ text/compose "Character does not satisfy predicate: " (text.from-code output))))
+ (#e.Success [[("lux i64 +" 1 offset) tape] (//.from-code output)])
+ (#e.Error ($_ text/compose "Character does not satisfy predicate: " (//.from-code output))))
_
(#e.Error cannot-lex-error))))
@@ -206,7 +256,7 @@
(def: #export space
{#.doc "Only lex white-space."}
(Lexer Text)
- (satisfies text.space?))
+ (satisfies //.space?))
(def: #export (and left right)
(-> (Lexer Text) (Lexer Text) (Lexer Text))
@@ -215,33 +265,64 @@
=right right]
(wrap ($_ text/compose =left =right))))
-(do-template [<name> <base> <doc>]
- [(def: #export (<name> p)
- {#.doc <doc>}
+(def: #export (and! left right)
+ (-> (Lexer Slice) (Lexer Slice) (Lexer Slice))
+ (do p.Monad<Parser>
+ [[left::basis left::distance] left
+ [right::basis right::distance] right]
+ (wrap [left::basis ("lux i64 +" left::distance right::distance)])))
+
+(do-template [<name> <base> <doc-modifier>]
+ [(def: #export (<name> lexer)
+ {#.doc (code.text ($_ text/compose "Lex " <doc-modifier> " characters as a single continuous text."))}
(-> (Lexer Text) (Lexer Text))
- (|> p <base> (:: p.Monad<Parser> map text.concat)))]
+ (|> lexer <base> (:: p.Monad<Parser> map //.concat)))]
- [some p.some "Lex some characters as a single continuous text."]
- [many p.many "Lex many characters as a single continuous text."]
+ [some p.some "some"]
+ [many p.many "many"]
)
-(do-template [<name> <base> <doc>]
- [(def: #export (<name> n p)
- {#.doc <doc>}
+(do-template [<name> <base> <doc-modifier>]
+ [(def: #export (<name> lexer)
+ {#.doc (code.text ($_ text/compose "Lex " <doc-modifier> " characters as a single continuous text."))}
+ (-> (Lexer Slice) (Lexer Slice))
+ (with-slices (<base> lexer)))]
+
+ [some! p.some "some"]
+ [many! p.many "many"]
+ )
+
+(do-template [<name> <base> <doc-modifier>]
+ [(def: #export (<name> amount lexer)
+ {#.doc (code.text ($_ text/compose "Lex " <doc-modifier> " N characters."))}
(-> Nat (Lexer Text) (Lexer Text))
- (do p.Monad<Parser>
- []
- (|> p (<base> n) (:: @ map text.concat))))]
+ (|> lexer (<base> amount) (:: p.Monad<Parser> map //.concat)))]
+
+ [exactly p.exactly "exactly"]
+ [at-most p.at-most "at most"]
+ [at-least p.at-least "at least"]
+ )
- [exactly p.exactly "Lex exactly N characters."]
- [at-most p.at-most "Lex at most N characters."]
- [at-least p.at-least "Lex at least N characters."]
+(do-template [<name> <base> <doc-modifier>]
+ [(def: #export (<name> amount lexer)
+ {#.doc (code.text ($_ text/compose "Lex " <doc-modifier> " N characters."))}
+ (-> Nat (Lexer Slice) (Lexer Slice))
+ (with-slices (<base> amount lexer)))]
+
+ [exactly! p.exactly "exactly"]
+ [at-most! p.at-most "at most"]
+ [at-least! p.at-least "at least"]
)
-(def: #export (between from to p)
+(def: #export (between from to lexer)
{#.doc "Lex between N and M characters."}
(-> Nat Nat (Lexer Text) (Lexer Text))
- (|> p (p.between from to) (:: p.Monad<Parser> map text.concat)))
+ (|> lexer (p.between from to) (:: p.Monad<Parser> map //.concat)))
+
+(def: #export (between! from to lexer)
+ {#.doc "Lex between N and M characters."}
+ (-> Nat Nat (Lexer Slice) (Lexer Slice))
+ (with-slices (p.between from to lexer)))
(def: #export (enclosed [start end] lexer)
(All [a] (-> [Text Text] (Lexer a) (Lexer a)))
@@ -259,3 +340,15 @@
(#e.Success value)
(#e.Success [real-input value]))))
+
+(def: #export (slice lexer)
+ (-> (Lexer Slice) (Lexer Text))
+ (do p.Monad<Parser>
+ [[basis distance] lexer]
+ (function (_ (^@ input [offset tape]))
+ (case (//.clip basis ("lux i64 +" basis distance) tape)
+ (#.Some output)
+ (#e.Success [input output])
+
+ #.None
+ (#e.Error "Cannot slice.")))))
diff --git a/stdlib/source/lux/data/text/regex.lux b/stdlib/source/lux/data/text/regex.lux
index ffd937d8e..ba0128b7b 100644
--- a/stdlib/source/lux/data/text/regex.lux
+++ b/stdlib/source/lux/data/text/regex.lux
@@ -7,25 +7,25 @@
["." product]
["e" error]
["." maybe]
- ["." number ("int/." Codec<Text,Int>)]
- ["." text
- ["l" lexer]
- format]
+ ["." number (#+ hex) ("int/." Codec<Text,Int>)]
[collection
["." list ("list/." Fold<List> Monad<List>)]]]
["." macro (#+ with-gensyms)
["." code]
- ["s" syntax (#+ syntax:)]]])
+ ["s" syntax (#+ syntax:)]]]
+ ["." //
+ ["l" lexer]
+ format])
## [Utils]
(def: regex-char^
(l.Lexer Text)
- (l.none-of "\\.|&()[]{}"))
+ (l.none-of "\.|&()[]{}"))
(def: escaped-char^
(l.Lexer Text)
(do p.Monad<Parser>
- [? (l.this? "\\")]
+ [? (l.this? "\")]
(if ?
l.any
regex-char^)))
@@ -50,11 +50,11 @@
(-> (l.Lexer (List Text)) (l.Lexer Text))
(do p.Monad<Parser>
[parts part^]
- (wrap (text.join-with "" parts))))
+ (wrap (//.join-with "" parts))))
(def: name-char^
(l.Lexer Text)
- (l.none-of "[]{}()s\"#.<>"))
+ (l.none-of (format "[]{}()s#.<>" //.double-quote)))
(def: name-part^
(l.Lexer Text)
@@ -75,15 +75,15 @@
(def: (re-var^ current-module)
(-> Text (l.Lexer Code))
(do p.Monad<Parser>
- [name (l.enclosed ["\\@<" ">"] (name^ current-module))]
+ [name (l.enclosed ["\@<" ">"] (name^ current-module))]
(wrap (` (: (l.Lexer Text) (~ (code.identifier name)))))))
(def: re-range^
(l.Lexer Code)
(do p.Monad<Parser>
- [from (|> regex-char^ (:: @ map (|>> (text.nth 0) maybe.assume)))
+ [from (|> regex-char^ (:: @ map (|>> (//.nth 0) maybe.assume)))
_ (l.this "-")
- to (|> regex-char^ (:: @ map (|>> (text.nth 0) maybe.assume)))]
+ to (|> regex-char^ (:: @ map (|>> (//.nth 0) maybe.assume)))]
(wrap (` (l.range (~ (code.nat from)) (~ (code.nat to)))))))
(def: re-char^
@@ -122,20 +122,21 @@
(def: blank^
(l.Lexer Text)
- (l.one-of " \t"))
+ (l.one-of (format " " //.tab)))
(def: ascii^
(l.Lexer Text)
- (l.range (char "\u0000") (char "\u007F")))
+ (l.range (hex "0") (hex "7F")))
(def: control^
(l.Lexer Text)
- (p.either (l.range (char "\u0000") (char "\u001F"))
- (l.one-of "\u007F")))
+ (p.either (l.range (hex "0") (hex "1F"))
+ (l.one-of (//.from-code (hex "7F")))))
(def: punct^
(l.Lexer Text)
- (l.one-of "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"))
+ (l.one-of (format "!#$%&'()*+,-./:;<=>?@[\]^_`{|}~"
+ //.double-quote)))
(def: graph^
(l.Lexer Text)
@@ -144,7 +145,7 @@
(def: print^
(l.Lexer Text)
(p.either graph^
- (l.one-of "\u0020")))
+ (l.one-of (//.from-code (hex "20")))))
(def: re-system-class^
(l.Lexer Code)
@@ -152,27 +153,27 @@
[]
($_ p.either
(p.after (l.this ".") (wrap (` l.any)))
- (p.after (l.this "\\d") (wrap (` l.decimal)))
- (p.after (l.this "\\D") (wrap (` (l.not l.decimal))))
- (p.after (l.this "\\s") (wrap (` l.space)))
- (p.after (l.this "\\S") (wrap (` (l.not l.space))))
- (p.after (l.this "\\w") (wrap (` (~! word^))))
- (p.after (l.this "\\W") (wrap (` (l.not (~! word^)))))
-
- (p.after (l.this "\\p{Lower}") (wrap (` l.lower)))
- (p.after (l.this "\\p{Upper}") (wrap (` l.upper)))
- (p.after (l.this "\\p{Alpha}") (wrap (` l.alpha)))
- (p.after (l.this "\\p{Digit}") (wrap (` l.decimal)))
- (p.after (l.this "\\p{Alnum}") (wrap (` l.alpha-num)))
- (p.after (l.this "\\p{Space}") (wrap (` l.space)))
- (p.after (l.this "\\p{HexDigit}") (wrap (` l.hexadecimal)))
- (p.after (l.this "\\p{OctDigit}") (wrap (` l.octal)))
- (p.after (l.this "\\p{Blank}") (wrap (` (~! blank^))))
- (p.after (l.this "\\p{ASCII}") (wrap (` (~! ascii^))))
- (p.after (l.this "\\p{Contrl}") (wrap (` (~! control^))))
- (p.after (l.this "\\p{Punct}") (wrap (` (~! punct^))))
- (p.after (l.this "\\p{Graph}") (wrap (` (~! graph^))))
- (p.after (l.this "\\p{Print}") (wrap (` (~! print^))))
+ (p.after (l.this "\d") (wrap (` l.decimal)))
+ (p.after (l.this "\D") (wrap (` (l.not l.decimal))))
+ (p.after (l.this "\s") (wrap (` l.space)))
+ (p.after (l.this "\S") (wrap (` (l.not l.space))))
+ (p.after (l.this "\w") (wrap (` (~! word^))))
+ (p.after (l.this "\W") (wrap (` (l.not (~! word^)))))
+
+ (p.after (l.this "\p{Lower}") (wrap (` l.lower)))
+ (p.after (l.this "\p{Upper}") (wrap (` l.upper)))
+ (p.after (l.this "\p{Alpha}") (wrap (` l.alpha)))
+ (p.after (l.this "\p{Digit}") (wrap (` l.decimal)))
+ (p.after (l.this "\p{Alnum}") (wrap (` l.alpha-num)))
+ (p.after (l.this "\p{Space}") (wrap (` l.space)))
+ (p.after (l.this "\p{HexDigit}") (wrap (` l.hexadecimal)))
+ (p.after (l.this "\p{OctDigit}") (wrap (` l.octal)))
+ (p.after (l.this "\p{Blank}") (wrap (` (~! blank^))))
+ (p.after (l.this "\p{ASCII}") (wrap (` (~! ascii^))))
+ (p.after (l.this "\p{Contrl}") (wrap (` (~! control^))))
+ (p.after (l.this "\p{Punct}") (wrap (` (~! punct^))))
+ (p.after (l.this "\p{Graph}") (wrap (` (~! graph^))))
+ (p.after (l.this "\p{Print}") (wrap (` (~! print^))))
)))
(def: re-class^
@@ -188,11 +189,11 @@
(def: re-back-reference^
(l.Lexer Code)
(p.either (do p.Monad<Parser>
- [_ (l.this "\\")
+ [_ (l.this "\")
id number^]
(wrap (` ((~! ..copy) (~ (code.identifier ["" (int/encode (.int id))]))))))
(do p.Monad<Parser>
- [_ (l.this "\\k<")
+ [_ (l.this "\k<")
captured-name name-part^
_ (l.this ">")]
(wrap (` ((~! ..copy) (~ (code.identifier ["" captured-name]))))))))
@@ -278,7 +279,7 @@
[idx
names
(list& (list g!temp complex
- (' #let) (` [(~ g!total) (:: (~! text.Monoid<Text>) (~' compose) (~ g!total) (~ g!temp))]))
+ (' #let) (` [(~ g!total) (:: (~! //.Monoid<Text>) (~' compose) (~ g!total) (~ g!temp))]))
steps)]
(#.Right [(#Capturing [?name num-captures]) scoped])
@@ -294,7 +295,7 @@
[idx!
(list& name! names)
(list& (list name! scoped
- (' #let) (` [(~ g!total) (:: (~! text.Monoid<Text>) (~' compose) (~ g!total) (~ access))]))
+ (' #let) (` [(~ g!total) (:: (~! //.Monoid<Text>) (~' compose) (~ g!total) (~ access))]))
steps)])
)))
[+0
@@ -410,11 +411,11 @@
(regex ".")
"Escaping"
- (regex "\\.")
+ (regex "\.")
"Character classes"
- (regex "\\d")
- (regex "\\p{Lower}")
+ (regex "\d")
+ (regex "\p{Lower}")
(regex "[abc]")
(regex "[a-z]")
(regex "[a-zA-Z]")
@@ -448,11 +449,11 @@
"Groups"
(regex "a(.)c")
(regex "a(b+)c")
- (regex "(\\d{3})-(\\d{3})-(\\d{4})")
- (regex "(\\d{3})-(?:\\d{3})-(\\d{4})")
- (regex "(?<code>\\d{3})-\\k<code>-(\\d{4})")
- (regex "(?<code>\\d{3})-\\k<code>-(\\d{4})-\\0")
- (regex "(\\d{3})-((\\d{3})-(\\d{4}))")
+ (regex "(\d{3})-(\d{3})-(\d{4})")
+ (regex "(\d{3})-(?:\d{3})-(\d{4})")
+ (regex "(?<code>\d{3})-\k<code>-(\d{4})")
+ (regex "(?<code>\d{3})-\k<code>-(\d{4})-\0")
+ (regex "(\d{3})-((\d{3})-(\d{4}))")
"Alternation"
(regex "a|b")
@@ -464,7 +465,7 @@
(p.before l.end)
(l.run pattern))
(#e.Error error)
- (macro.fail (format "Error while parsing regular-expression:\n"
+ (macro.fail (format "Error while parsing regular-expression:" //.new-line
error))
(#e.Success regex)
@@ -476,11 +477,11 @@
{branches (p.many s.any)})
{#.doc (doc "Allows you to test text against regular expressions."
(case some-text
- (^regex "(\\d{3})-(\\d{3})-(\\d{4})"
+ (^regex "(\d{3})-(\d{3})-(\d{4})"
[_ country-code area-code place-code])
do-some-thing-when-number
- (^regex "\\w+")
+ (^regex "\w+")
do-some-thing-when-word
_