aboutsummaryrefslogtreecommitdiff
path: root/src/lux/parser.clj
blob: 85074be7dadff9afe723e0cb1010882896c4c662 (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
89
90
91
(ns lux.parser
  (:require [clojure.template :refer [do-template]]
            [clojure.core.match :as M :refer [matchv]]
            clojure.core.match.array
            (lux [base :as & :refer [|do return fail]]
                 [lexer :as &lexer])))

;; [Utils]
(do-template [<name> <close-tag> <description> <tag>]
  (defn <name> [parse]
    (|do [elems (&/repeat% parse)
          token &lexer/lex]
      (matchv ::M/objects [token]
        [["lux;Meta" [meta [<close-token> _]]]]
        (return (&/V <tag> (&/fold &/|++ (&/|list) elems)))
        
        [_]
        (fail (str "[Parser Error] Unbalanced " <description> ".")))))

  ^:private parse-form  "Close_Paren"   "parantheses" "lux;Form"
  ^:private parse-tuple "Close_Bracket" "brackets"    "lux;Tuple"
  )

(defn ^:private parse-record [parse]
  (|do [;; :let [_ (prn 'parse-record 0)]
        elems* (&/repeat% parse)
        ;; :let [_ (prn 'parse-record 1)]
        token &lexer/lex
        ;; :let [_ (prn 'parse-record 2)]
        :let [elems (&/fold &/|++ (&/|list) elems*)]
        ;; :let [_ (prn 'parse-record 3)]
        ]
    (matchv ::M/objects [token]
      [["lux;Meta" [meta ["Close_Brace" _]]]]
      (if (even? (&/|length elems))
        (do ;; (prn 'PARSED_RECORD (&/|length elems))
          (return (&/V "lux;Record" (&/|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 [_ (prn 'parse/token token)]
        ;; :let [_ (prn 'parse (aget token 0))]
        ]
    (matchv ::M/objects [token]
      [["lux;Meta" [meta ["White_Space" _]]]]
      (return (&/|list))

      [["lux;Meta" [meta ["Comment" _]]]]
      (return (&/|list))
      
      [["lux;Meta" [meta ["Bool" ?value]]]]
      (return (&/|list (&/V "lux;Meta" (&/T meta (&/V "lux;Bool" (Boolean/parseBoolean ?value))))))

      [["lux;Meta" [meta ["Int" ?value]]]]
      (return (&/|list (&/V "lux;Meta" (&/T meta (&/V "lux;Int" (Integer/parseInt ?value))))))

      [["lux;Meta" [meta ["Real" ?value]]]]
      (return (&/|list (&/V "lux;Meta" (&/T meta (&/V "lux;Real" (Float/parseFloat ?value))))))

      [["lux;Meta" [meta ["Char" ?value]]]]
      (return (&/|list (&/V "lux;Meta" (&/T meta (&/V "lux;Char" (.charAt ?value 0))))))

      [["lux;Meta" [meta ["Text" ?value]]]]
      (return (&/|list (&/V "lux;Meta" (&/T meta (&/V "lux;Text" ?value)))))

      [["lux;Meta" [meta ["Symbol" ?ident]]]]
      (return (&/|list (&/V "lux;Meta" (&/T meta (&/V "lux;Symbol" ?ident)))))

      [["lux;Meta" [meta ["Tag" ?ident]]]]
      (return (&/|list (&/V "lux;Meta" (&/T meta (&/V "lux;Tag" ?ident)))))

      [["lux;Meta" [meta ["Open_Paren" _]]]]
      (|do [syntax (parse-form parse)]
        (return (&/|list (&/V "lux;Meta" (&/T meta syntax)))))
      
      [["lux;Meta" [meta ["Open_Bracket" _]]]]
      (|do [syntax (parse-tuple parse)]
        (return (&/|list (&/V "lux;Meta" (&/T meta syntax)))))

      [["lux;Meta" [meta ["Open_Brace" _]]]]
      (|do [syntax (parse-record parse)]
        (return (&/|list (&/V "lux;Meta" (&/T meta syntax)))))

      [_]
      (fail "[Parser Error] Unknown lexer token.")
      )))