forked from mozilla/mentat
-
Notifications
You must be signed in to change notification settings - Fork 0
/
edn.rustpeg
106 lines (83 loc) · 2.49 KB
/
edn.rustpeg
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
use std::collections::{BTreeSet, BTreeMap, LinkedList};
use std::iter::FromIterator;
use types::{Pair, Value};
use ordered_float::OrderedFloat;
// Goal: Be able to parse https://github.com/edn-format/edn
// Also extensible to help parse http://docs.datomic.com/query.html
// TODO: Support tagged elements
// TODO: Support comments
// TODO: Support discard
#[export]
nil -> Value = "nil" {
Value::Nil
}
#[export]
boolean -> Value =
"true" { Value::Boolean(true) } /
"false" { Value::Boolean(false) }
digit = [0-9]
sign = "-" / "+"
#[export]
integer -> Value = i:$( sign? digit+ ) {
Value::Integer(i.parse::<i32>().unwrap())
}
frac = sign? digit+ "." digit+
exp = sign? digit+ ("e" / "E") sign? digit+
frac_exp = sign? digit+ "." digit+ ("e" / "E") sign? digit+
// The order here is important - frac_exp must come before (exp / frac) or the
// parser assumes exp or frac when the float is really a frac_exp and fails
#[export]
float -> Value = f:$( frac_exp / exp / frac ) {
Value::Float(OrderedFloat(f.parse::<f64>().unwrap()))
}
// TODO: \newline, \return, \space and \tab
special_char = quote / tab
quote = "\\\""
tab = "\\tab"
char = [^"] / special_char
#[export]
text -> Value = "\"" t:$( char* ) "\"" {
Value::Text(t.to_string())
}
// TODO: Be more picky here
symbol_char_initial = [a-z] / [A-Z] / [0-9] / [*!_?$%&=<>/.]
symbol_char_subsequent = [a-z] / [A-Z] / [0-9] / [*!_?$%&=<>/.] / "-"
#[export]
symbol -> Value = s:$( symbol_char_initial symbol_char_subsequent* ) {
Value::Symbol(s.to_string())
}
keyword_char_initial = ":"
// TODO: More chars here?
keyword_char_subsequent = [a-z] / [A-Z] / [0-9] / "/"
#[export]
keyword -> Value = k:$( keyword_char_initial keyword_char_subsequent+ ) {
Value::Keyword(k.to_string())
}
#[export]
list -> Value = "(" __ v:(__ value)* __ ")" {
Value::List(LinkedList::from_iter(v))
}
#[export]
vector -> Value = "[" __ v:(__ value)* __ "]" {
Value::Vector(v)
}
#[export]
set -> Value = "#{" __ v:(__ value)* __ "}" {
Value::Set(BTreeSet::from_iter(v))
}
pair -> (Value, Value) = k:(value) " " v:(value) ", "? {
(k, v)
}
#[export]
map -> Value = "{" __ v:(pair)* __ "}" {
Value::Map(BTreeMap::from_iter(v))
}
// It's important that float comes before integer or the parser assumes that
// floats are integers and fails to parse
#[export]
value -> Value
= nil / boolean / float / integer / text /
keyword / symbol /
list / vector / map / set
whitespace = (" " / "\r" / "\n" / "\t")
__ = whitespace*