blob: 516b6a947835bd49dad3c11bb045642cecdefd52 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
;; Copyright (c) Eduardo Julian. All rights reserved.
;; This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
;; If a copy of the MPL was not distributed with this file,
;; You can obtain one at http://mozilla.org/MPL/2.0/.
(ns lux.parser
(:require [clojure.template :refer [do-template]]
clojure.core.match
clojure.core.match.array
(lux [base :as & :refer [deftags |do return fail |case]]
[lexer :as &lexer])))
;; [Utils]
(do-template [<name> <close-tag> <description> <tag>]
(defn <name> [parse]
(|do [elems (&/repeat% parse)
token &lexer/lex]
(|case token
[meta [<close-token> _]]
(return (&/V <tag> (&/fold &/|++ &/Nil$ elems)))
_
(fail (str "[Parser Error] Unbalanced " <description> ".")))))
^:private parse-form &lexer/$Close_Paren "parantheses" &/$FormS
^:private parse-tuple &lexer/$Close_Bracket "brackets" &/$TupleS
)
(defn ^:private parse-record [parse]
(|do [elems* (&/repeat% parse)
token &lexer/lex
:let [elems (&/fold &/|++ &/Nil$ elems*)]]
(|case token
[meta (&lexer/$Close_Brace _)]
(if (even? (&/|length elems))
(return (&/V &/$RecordS (&/|as-pairs elems)))
(fail (str "[Parser Error] Records must have an even number of elements.")))
_
(fail (str "[Parser Error] Unbalanced braces.")))))
;; [Interface]
(def parse
(|do [token &lexer/lex
:let [[meta token*] token]]
(|case token*
(&lexer/$White_Space _)
(return &/Nil$)
(&lexer/$Comment _)
(return &/Nil$)
(&lexer/$Bool ?value)
(return (&/|list (&/T meta (&/V &/$BoolS (Boolean/parseBoolean ?value)))))
(&lexer/$Int ?value)
(return (&/|list (&/T meta (&/V &/$IntS (Long/parseLong ?value)))))
(&lexer/$Real ?value)
(return (&/|list (&/T meta (&/V &/$RealS (Double/parseDouble ?value)))))
(&lexer/$Char ^String ?value)
(return (&/|list (&/T meta (&/V &/$CharS (.charAt ?value 0)))))
(&lexer/$Text ?value)
(return (&/|list (&/T meta (&/V &/$TextS ?value))))
(&lexer/$Symbol ?ident)
(return (&/|list (&/T meta (&/V &/$SymbolS ?ident))))
(&lexer/$Tag ?ident)
(return (&/|list (&/T meta (&/V &/$TagS ?ident))))
(&lexer/$Open_Paren _)
(|do [syntax (parse-form parse)]
(return (&/|list (&/T meta syntax))))
(&lexer/$Open_Bracket _)
(|do [syntax (parse-tuple parse)]
(return (&/|list (&/T meta syntax))))
(&lexer/$Open_Brace _)
(|do [syntax (parse-record parse)]
(return (&/|list (&/T meta syntax))))
_
(fail "[Parser Error] Unknown lexer token.")
)))
|