1use pest::prelude::*;
2use std::error;
3use std::fmt;
4use packet::{Location, WindSpeed, DataField, Packet};
5
6impl_rdp! {
7 grammar! {
21 digit = _{ ['0'..'9'] }
22 integer = { (["+"] | ["-"])? ~ digit+ }
23 decimal = { (["+"] | ["-"])? ~ digit+ ~ (["."] ~ digit+)? }
24
25 lowercase_letter = _{ ['a'..'z'] }
26 uppercase_letter = _{ ['A'..'Z'] }
27
28 letter = _{ lowercase_letter | uppercase_letter }
29 symbol = _{
30 [" "] | ["!"] | ["\""] | ["#"] | ["$"] | ["%"] | ["&"] | ["'"] |
31 ["("] | [")"] | ["*"] | ["+"] | [","] | ["-"] | ["."] | ["/"] |
32 [":"] | [";"] | ["<"] | ["="] | [">"] | ["?"] | ["@"] | ["\\"] |
33 ["^"] | ["_"] | ["`"] | ["{"] | ["|"] | ["}"] | ["~"]
34 }
35
36 repeat = { digit }
37 sequence = { lowercase_letter }
38
39 decimal_list= { decimal? ~ ( [","] ~ decimal? )* }
40
41 voltage = { ["V"] ~ decimal_list }
42 current = { ["I"] ~ decimal_list }
43 temperature = { ["T"] ~ decimal_list }
44 humidity = { ["H"] ~ decimal_list }
45 pressure = { ["P"] ~ decimal_list }
46 custom = { ["X"] ~ decimal_list }
47 sun = { ["S"] ~ decimal_list }
48 rssi = { ["R"] ~ decimal_list }
49 count = { ["C"] ~ decimal_list }
50 windspeed = { ["W"] ~ decimal? ~ ( [","] ~ decimal? )? }
51 location = { ["L"] ~ ( (decimal ~ [","] ~ decimal)? | [","] )
52 ~ ( [","] ~ decimal? )? }
53
54 zombie_mode = { ["0"] | ["1"] }
55 zombie = { ["Z"] ~ zombie_mode }
56
57 data_field = { voltage | current | temperature | humidity |
58 pressure | custom | sun | rssi | windspeed |
59 location | count | zombie }
60
61 data = { data_field* }
62
63 comment_content = { (letter | digit | symbol)* }
64 comment = { [":"] ~ comment_content }
65
66 node_name_content = { (letter | digit)* }
73 node_name = { node_name_content }
74
75 path = { ["["] ~ node_name ~ ( [","] ~ node_name )* ~ ["]"] }
76
77 packet = { repeat ~ sequence ~ data ~ comment? ~ path ~ eoi }
78 }
79
80 process! {
99 _repeat(&self) -> u8 {
100 (&repeat: repeat) => repeat.parse::<u8>().unwrap()
101 }
102
103 _sequence(&self) -> char {
104 (&sequence: sequence) =>
105 sequence.chars().nth(0).unwrap()
106 }
107
108 _location(&self) -> Location {
109 (&latitude: decimal, &longitude: decimal, &altitude: decimal) => {
110 let lat = latitude.parse::<f32>().unwrap();
111 let lng = longitude.parse::<f32>().unwrap();
112 let alt = altitude.parse::<f32>().unwrap();
113 Location{ latlng: Some((lat, lng)), alt: Some(alt) }
114 },
115 (&latitude: decimal, &longitude: decimal) => {
116 let lat = latitude.parse::<f32>().unwrap();
117 let lng = longitude.parse::<f32>().unwrap();
118 Location{ latlng: Some((lat, lng)), alt: None }
119 },
120 (&altitude: decimal) => {
121 let alt = altitude.parse::<f32>().unwrap();
122 Location{ latlng: None, alt: Some(alt) }
123 },
124 () => Location{ latlng: None, alt: None },
125 }
126
127 _windspeed(&self) -> WindSpeed {
128 (&speed: decimal, &bearing: decimal) => {
129 let speed = speed.parse::<f32>().unwrap();
130 let bearing = bearing.parse::<f32>().unwrap();
131 WindSpeed{speed: Some(speed), bearing: Some(bearing)}
132 },
133 (&speed: decimal) => {
134 let speed = speed.parse::<f32>().unwrap();
135 WindSpeed{speed: Some(speed), bearing: None}
136 },
137 () => WindSpeed{speed: None, bearing: None},
138 }
139
140 _decimal_list(&self) -> Vec<f32> {
141 (_: decimal_list, list: _decimal_list()) => list,
142 (&head: decimal, mut tail: _decimal_list()) => {
143 tail.insert(0, head.parse::<f32>().unwrap());
144 tail
145 },
146 () => Vec::<f32>::new(),
147 }
148
149 _zombie(&self) -> u8 {
150 (&mode: zombie_mode) => mode.parse::<u8>().unwrap()
151 }
152
153 _datafield(&self) -> DataField {
154 (_: voltage, voltages: _decimal_list()) =>
155 DataField::Voltage(voltages),
156 (_: current, currents: _decimal_list()) =>
157 DataField::Current(currents),
158 (_: temperature, temperatures: _decimal_list()) =>
159 DataField::Temperature(temperatures),
160 (_: humidity, humidities: _decimal_list()) =>
161 DataField::Humidity(humidities),
162 (_: pressure, pressures: _decimal_list()) =>
163 DataField::Pressure(pressures),
164 (_: custom, customs: _decimal_list()) =>
165 DataField::Custom(customs),
166 (_: sun, suns: _decimal_list()) =>
167 DataField::Sun(suns),
168 (_: rssi, rssis: _decimal_list()) =>
169 DataField::Rssi(rssis),
170 (_: count, counts: _decimal_list()) =>
171 DataField::Count(counts),
172 (_: windspeed, windspeed: _windspeed()) =>
173 DataField::WindSpeed(windspeed),
174 (_: location, location: _location()) =>
175 DataField::Location(location),
176 (_: zombie, zombie: _zombie()) =>
177 DataField::Zombie(zombie),
178 }
179
180 _data(&self) -> Vec<DataField> {
181 (_: data, fields: _data()) => fields,
182 (_: data_field, head: _datafield(), mut tail: _data()) => {
183 tail.insert(0, head);
184 tail
185 },
186 () => Vec::<DataField>::new(),
187 }
188
189 _comment(&self) -> Option<String> {
190 (_: comment, &comment: comment_content) =>
191 Some(comment.to_owned()),
192 () => None,
193 }
194
195 _node_name(&self) -> String {
196 (&name: node_name_content) => name.to_owned().to_uppercase()
197 }
198
199 _path(&self) -> Vec<String> {
200 (_: path, names: _path()) => names,
201 (_: node_name, head: _node_name(), mut tail: _path()) => {
202 tail.insert(0, head);
203 tail
204 },
205 () => Vec::<String>::new(),
206 }
207
208 parse(&self) -> Packet {
209 (_: packet, repeat: _repeat(), sequence: _sequence(),
210 data: _data(), comment: _comment(), path: _path()) =>
211 Packet{ repeat: repeat, sequence: sequence, data: data,
212 comment: comment, path: path }
213 }
214 }
215}
216
217#[derive(Debug)]
220pub struct ParserError {
221 pub position: usize,
222 pub expected: Vec<String>,
223}
224
225impl fmt::Display for ParserError {
226 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
227 write!(f, "Parser error at position {}", self.position)
228 }
229}
230
231impl error::Error for ParserError {
232 fn description(&self) -> &str { "Parser error" }
233 fn cause(&self) -> Option<&error::Error> { None }
234}
235
236impl ParserError {
237 pub fn from_parser<'a, T: Input<'a>>(parser: &mut Rdp<T>) -> ParserError {
239 let (expected, position) = parser.expected();
240 let exp = expected.iter().map(|r| { format!("{:?}", r) }).collect();
241 ParserError{ position: position, expected: exp }
242 }
243}