mech_syntax/
literals.rs

1#[macro_use]
2use crate::*;
3use nom::{
4  multi::separated_list0,
5  sequence::tuple as nom_tuple,
6};
7use crate::nodes::Kind;
8
9// Literals
10// =============================================================================
11
12// literal := (number | string | atom | boolean | empty | kind-annotation), kind-annotation? ;
13pub fn literal(input: ParseString) -> ParseResult<Literal> {
14  let (input, result) = match number(input.clone()) {
15    Ok((input, num)) => (input, Literal::Number(num)),
16    _ => match string(input.clone()) {
17      Ok((input, s)) => (input, Literal::String(s)),
18      _ => match atom(input.clone()) {
19        Ok((input, atm)) => (input, Literal::Atom(atm)),
20        _ => match boolean(input.clone()) {
21          Ok((input, boolean)) => (input, Literal::Boolean(boolean)),
22          _ => match empty(input.clone()) {
23            Ok((input, empty)) => (input, Literal::Empty(empty)), 
24            Err(err) => match kind_annotation(input.clone()) {
25              Ok((input, knd)) => (input, Literal::Kind(knd.kind)),
26              Err(err) => return Err(err),
27            }
28          }
29        }
30      }
31    }
32  };
33  let (input, result) = match opt(kind_annotation)(input.clone()) {
34    Ok((input, Some(knd))) => ((input, Literal::TypedLiteral((Box::new(result),knd)))),
35    Ok((input, None)) => (input,result),
36    Err(err) => {return Err(err);}
37  };
38  Ok((input, result))
39}
40
41// atom := "`", identifier ;
42pub fn atom(input: ParseString) -> ParseResult<Atom> {
43  let (input, _) = grave(input)?;
44  let (input, name) = identifier(input)?;
45  Ok((input, Atom{name}))
46}
47
48
49// string := quote, *(¬quote, (text | new-line)), quote ;
50pub fn string(input: ParseString) -> ParseResult<MechString> {
51  let msg = "Character not allowed in string";
52  let (input, _) = quote(input)?;
53  let (input, matched) = many0(nom_tuple((is_not(quote), alt((text,new_line)))))(input)?;
54  let (input, _) = quote(input)?;
55  let (_, mut text): ((), Vec<_>) = matched.into_iter().unzip();
56  let mut merged = Token::merge_tokens(&mut text).unwrap();
57  merged.kind = TokenKind::String;
58  Ok((input, MechString { text: merged }))
59}
60
61// Boolean
62// ----------------------------------------------------------------------------
63
64// boolean_literal := true_literal | false_literal ;
65pub fn boolean(input: ParseString) -> ParseResult<Token> {
66  let (input, boolean) = alt((true_literal, false_literal))(input)?;
67  Ok((input, boolean))
68}
69
70// true_literal := english_true_literal | check_mark ;
71pub fn true_literal(input: ParseString) -> ParseResult<Token> {
72  let (input, token) = alt((english_true_literal, check_mark))(input)?;
73  Ok((input, token))
74}
75
76// false_literal := english_false_literal | cross ;
77pub fn false_literal(input: ParseString) -> ParseResult<Token> {
78  let (input, token) = alt((english_false_literal, cross))(input)?;
79  Ok((input, token))
80}
81
82// Number
83// ----------------------------------------------------------------------------
84
85// number := complex-number | real-number ;
86pub fn number(input: ParseString) -> ParseResult<Number> {
87  match complex_number(input.clone()) {
88    Ok((input, complex_num)) => Ok((input, Number::Complex(complex_num))),
89    _ => match real_number(input.clone()) {
90      Ok((input, real_num)) => Ok((input, Number::Real(real_num))),
91      Err(err) => return Err(err),
92    },
93  }
94}
95
96// complex-number := real-number, ("i"|"j")? | (("+"|"-"), real-number, ("i"|"j")) ;
97pub fn complex_number(input: ParseString) -> ParseResult<C64Node> {
98  let (input, real_num) = real_number(input)?;
99  if let Ok((input, _)) = alt((tag("i"), tag("j")))(input.clone()) {
100    return Ok((
101      input,
102      C64Node {
103        real: None,
104        imaginary: ImaginaryNumber { number: real_num },
105      },
106    ));
107  }
108  if let Ok((input, (sign, imaginary_num, _))) = 
109    nom_tuple((alt((plus, dash)), real_number, alt((tag("i"), tag("j")))))(input.clone())
110  {
111    let imaginary = match sign.kind {
112      TokenKind::Plus => imaginary_num,
113      TokenKind::Dash => RealNumber::Negated(Box::new(imaginary_num)),
114      _ => unreachable!(),
115    };
116    return Ok((
117      input,
118      C64Node {
119        real: Some(real_num),
120        imaginary: ImaginaryNumber { number: imaginary },
121      },
122    ));
123  } else {
124    return Err(nom::Err::Error(nom::error::make_error(
125      input,
126      nom::error::ErrorKind::Alt,
127    )));
128  }
129}
130
131// real-number := ?dash, (hexadecimal-literal | decimal-literal | octal-literal | binary-literal | scientific-literal | rational-literal | float-literal | integer-literal) ;
132pub fn real_number(input: ParseString) -> ParseResult<RealNumber> {
133  let (input, neg) = opt(dash)(input)?;
134  let (input, result) = alt((hexadecimal_literal, decimal_literal, octal_literal, binary_literal, scientific_literal, rational_literal, float_literal, integer_literal))(input)?;
135  let result = match neg {
136    Some(_) => RealNumber::Negated(Box::new(result)),
137    None => result,
138  };
139  Ok((input, result))
140}
141
142// rational-literal := integer-literal, slash, integer-literal ;
143pub fn rational_literal(input: ParseString) -> ParseResult<RealNumber> {
144  let (input, RealNumber::Integer(numerator)) = integer_literal(input)? else { unreachable!() };
145  let (input, _) = slash(input)?;
146  let (input, RealNumber::Integer(denominator)) = integer_literal(input)? else { unreachable!() };
147  Ok((input, RealNumber::Rational((numerator,denominator))))
148}
149
150// scientific-literal := (float-literal | integer-literal), ("e" | "E"), ?plus, ?dash, (float-literal | integer-literal) ;
151pub fn scientific_literal(input: ParseString) -> ParseResult<RealNumber> {
152  let (input, base) = match float_literal(input.clone()) {
153    Ok((input, RealNumber::Float(base))) => {
154      (input, base)
155    }
156    _ => match integer_literal(input.clone()) {
157      Ok((input, RealNumber::Integer(base))) => {
158        (input, (base, Token::default()))
159      }
160      Err(err) => {return Err(err);}
161      _ => unreachable!(),
162    }
163  };
164  let (input, _) = alt((tag("e"), tag("E")))(input)?;
165  let (input, _) = opt(plus)(input)?;
166  let (input, neg) = opt(dash)(input)?;
167  let (input, (ex_whole,ex_part)) = match float_literal(input.clone()) {
168    Ok((input, RealNumber::Float(exponent))) => {
169      (input, exponent)
170    }
171    _ => match integer_literal(input.clone()) {
172      Ok((input, RealNumber::Integer(exponent))) => {
173        (input, (exponent, Token::default()))
174      }
175      Err(err) => {return Err(err);}
176      _ => unreachable!(),
177    }
178  };
179  let ex_sign = match neg {
180    Some(_) => true,
181    None => false,
182  };
183  Ok((input, RealNumber::Scientific((base,(ex_sign,ex_whole,ex_part)))))
184}
185
186// float-decimal-start := ".", digit-sequence ;
187pub fn float_decimal_start(input: ParseString) -> ParseResult<RealNumber> {
188  let (input, _) = period(input)?;
189  let (input, part) = digit_sequence(input)?;
190  let mut tokens2 = part.clone();
191  let mut merged = Token::merge_tokens(&mut tokens2).unwrap();
192  merged.kind = TokenKind::Number;
193  Ok((input, RealNumber::Float((Token::default(),merged))))
194}
195
196// float-full := digit-sequence, ".", digit-sequnce ;
197pub fn float_full(input: ParseString) -> ParseResult<RealNumber> {
198  let (input, mut whole) = digit_sequence(input)?;
199  let (input, _) = period(input)?;
200  let (input, mut part) = digit_sequence(input)?;
201  let mut whole = Token::merge_tokens(&mut whole).unwrap();
202  let mut part = Token::merge_tokens(&mut part).unwrap();
203  whole.kind = TokenKind::Number;
204  part.kind = TokenKind::Number;
205  Ok((input, RealNumber::Float((whole,part))))
206}
207
208// float-literal := float-decimal-start | float-full;
209pub fn float_literal(input: ParseString) -> ParseResult<RealNumber> {
210  let (input, result) = alt((float_decimal_start,float_full))(input)?;
211  Ok((input, result))
212}
213
214// integer := digit1 ;
215pub fn integer_literal(input: ParseString) -> ParseResult<RealNumber> {
216  let (input, mut digits) = digit_sequence(input)?;
217  let mut merged = Token::merge_tokens(&mut digits).unwrap();
218  merged.kind = TokenKind::Number; 
219  Ok((input, RealNumber::Integer(merged)))
220}
221
222// decimal_literal := "0d", <digit1> ;
223pub fn decimal_literal(input: ParseString) -> ParseResult<RealNumber> {
224  let msg = "Expects decimal digits after \"0d\"";
225  let input = tag("0d")(input);
226  let (input, _) = input?;
227  let (input, mut tokens) = label!(digit_sequence, msg)(input)?;
228  let mut merged = Token::merge_tokens(&mut tokens).unwrap();
229  merged.kind = TokenKind::Number; 
230  Ok((input, RealNumber::Decimal(merged)))
231}
232
233// hexadecimal_literal := "0x", <hex_digit+> ;
234pub fn hexadecimal_literal(input: ParseString) -> ParseResult<RealNumber> {
235  let msg = "Expects hexadecimal digits after \"0x\"";
236  let input = tag("0x")(input);
237  let (input, _) = input?;
238  let (input, mut tokens) = label!(many1(alt((digit_token,underscore,alpha_token))), msg)(input)?;
239  let mut merged = Token::merge_tokens(&mut tokens).unwrap();
240  merged.kind = TokenKind::Number; 
241  Ok((input, RealNumber::Hexadecimal(merged)))
242}
243
244// octal_literal := "0o", <oct_digit+> ;
245pub fn octal_literal(input: ParseString) -> ParseResult<RealNumber> {
246  let msg = "Expects octal digits after \"0o\"";
247  let input = tag("0o")(input);
248  let (input, _) = input?;
249  let (input, mut tokens) = label!(many1(alt((digit_token,underscore,alpha_token))), msg)(input)?;
250  let mut merged = Token::merge_tokens(&mut tokens).unwrap();
251  merged.kind = TokenKind::Number; 
252  Ok((input, RealNumber::Octal(merged)))
253}
254
255// binary_literal := "0b", <bin_digit+> ;
256pub fn binary_literal(input: ParseString) -> ParseResult<RealNumber> {
257  let msg = "Expects binary digits after \"0b\"";
258  let input = tag("0b")(input);
259  let (input, _) = input?;
260  let (input, mut tokens) = label!(many1(alt((digit_token,underscore,alpha_token))), msg)(input)?;
261  let mut merged = Token::merge_tokens(&mut tokens).unwrap();
262  merged.kind = TokenKind::Number; 
263  Ok((input, RealNumber::Binary(merged)))
264}
265
266// empty := underscore+ ;
267pub fn empty(input: ParseString) -> ParseResult<Token> {
268  let (input, (g, src_range)) = range(many1(tag("_")))(input)?;
269  Ok((input, Token{kind: TokenKind::Empty, chars: g.join("").chars().collect(), src_range}))
270}
271
272// Kind Annotations
273// ----------------------------------------------------------------------------
274
275// kind_annotation := left_angle, kind, ?question, right_angle ;
276pub fn kind_annotation(input: ParseString) -> ParseResult<KindAnnotation> {
277  let msg2 = "Expects at least one unit in kind annotation";
278  let msg3 = "Expects right angle";
279  let (input, (_, r)) = range(left_angle)(input)?;
280  let (input, kind) = kind(input)?;
281  let (input, optional) = opt(question)(input)?;
282  let (input, _) = label!(right_angle, msg3, r)(input)?;
283  let kind = match optional {
284    Some(_) => Kind::Option(Box::new(kind)),
285    None => kind,
286  };
287  Ok((input, KindAnnotation{ kind }))
288}
289
290// kind := kind-fxn | kind-empty | kind-record | kind-atom | kind-tuple | kind-scalar | kind-matrix | kind-map ;
291pub fn kind(input: ParseString) -> ParseResult<Kind> {
292  let (input, kind) = alt((
293    kind_any,
294    kind_atom,
295    kind_empty,
296    kind_map,
297    kind_matrix,
298    kind_record,
299    kind_scalar,
300    kind_set,
301    kind_table, 
302    kind_tuple,
303  ))(input)?;
304  Ok((input, kind))
305}
306
307// kind-table := "|" , list1(",", (identifier, kind)), "|", ":", list0(",", literal) ;
308pub fn kind_table(input: ParseString) -> ParseResult<Kind> {
309  let (input, _) = bar(input)?;
310  let (input, elements) = separated_list1(alt((null(list_separator),null(many1(space_tab)))), nom_tuple((identifier, kind_annotation)))(input)?;
311  let (input, _) = bar(input)?;
312  let (input, size) = opt(tuple((colon,literal)))(input)?;
313  let size = size.map(|(_, ltrl)| ltrl).unwrap_or_else(|| Literal::Empty(Token::default()));
314  let elements = elements.into_iter().map(|(id, knd)| (id, knd.kind)).collect();
315  Ok((input, Kind::Table((elements, Box::new(size)))))
316}
317
318// kind-any := "*";
319pub fn kind_any(input: ParseString) -> ParseResult<Kind> {
320  let (input, _) = asterisk(input)?;
321  Ok((input, Kind::Any))
322}
323
324// kind-empty := underscore+ ;
325pub fn kind_empty(input: ParseString) -> ParseResult<Kind> {
326  let (input, _) = many1(underscore)(input)?;
327  Ok((input, Kind::Empty))
328}
329
330// kind-atom := "`", identifier ;
331pub fn kind_atom(input: ParseString) -> ParseResult<Kind> {
332  let (input, _) = grave(input)?;
333  let (input, atm) = identifier(input)?;
334  Ok((input, Kind::Atom(atm)))
335}
336
337// kind-set := "{", kind, "}", (":", literal)? ;
338pub fn kind_set(input: ParseString) -> ParseResult<Kind> {
339  let (input, _) = left_brace(input)?;
340  let (input, kind) = kind(input)?;
341  let (input, _) = right_brace(input)?;
342  let (input, opt_lit) = opt(nom_tuple((colon, literal)))(input)?;
343  let ltrl = match opt_lit {
344    Some((_, ltrl)) => Some(Box::new(ltrl)),
345    None => None,
346  };
347  Ok((input, Kind::Set(Box::new(kind), ltrl)))
348}
349
350// kind-map := "{", kind, ":", kind, "}" ;
351pub fn kind_map(input: ParseString) -> ParseResult<Kind> {
352  let (input, _) = left_brace(input)?;
353  let (input, key_kind) = kind(input)?;
354  let (input, _) = colon(input)?;
355  let (input, value_kind) = kind(input)?;
356  let (input, _) = right_brace(input)?;
357  Ok((input, Kind::Map(Box::new(key_kind),Box::new(value_kind))))
358}
359
360// kind-record := "{", list1(",", (identifier, kind)), "}" ;
361pub fn kind_record(input: ParseString) -> ParseResult<Kind> {
362  let (input, _) = left_brace(input)?;
363  let (input, elements) = separated_list1(list_separator, nom_tuple((identifier, kind_annotation)))(input)?;
364  let (input, _) = right_brace(input)?;
365  let elements = elements.into_iter().map(|(id, knd)| (id, knd.kind)).collect();
366  Ok((input, Kind::Record(elements)))
367}
368
369// kind-fxn := "(", list0(list_separator, kind), ")", "=", "(", list0(list_separator, kind), ")" ;
370/*pub fn kind_fxn(input: ParseString) -> ParseResult<Kind> {
371  let (input, _) = left_parenthesis(input)?;
372  let (input, input_kinds) = separated_list0(list_separator,kind)(input)?;
373  let (input, _) = right_parenthesis(input)?;
374  let (input, _) = equal(input)?;
375  let (input, _) = left_parenthesis(input)?;
376  let (input, output_kinds) = separated_list0(list_separator,kind)(input)?;
377  let (input, _) = right_parenthesis(input)?;
378  Ok((input, Kind::Function(input_kinds,output_kinds)))
379}*/
380
381// kind-matrox := "[", list1(",",kind), "]", ":"?, list0(",", literal) ;
382pub fn kind_matrix(input: ParseString) -> ParseResult<Kind> {
383  let (input, _) = left_bracket(input)?;
384  let (input, kind) = kind(input)?;
385  let (input, _) = right_bracket(input)?;
386  let (input, _) = opt(colon)(input)?;
387  let (input, size) = separated_list0(list_separator,literal)(input)?;
388  Ok((input, Kind::Matrix((Box::new(kind),size))))
389}
390
391// kind-tuple := "(", list1(",", kind), ")" ;
392pub fn kind_tuple(input: ParseString) -> ParseResult<Kind> {
393  let (input, _) = left_parenthesis(input)?;
394  let (input, kinds) = separated_list1(list_separator, kind)(input)?;
395  let (input, _) = right_parenthesis(input)?;
396  Ok((input, Kind::Tuple(kinds)))
397}
398
399// kind-scalar := identifier, [":", range_expression] ;
400pub fn kind_scalar(input: ParseString) -> ParseResult<Kind> {
401  let (input, kind) = identifier(input)?;
402  let (input, range) = opt(tuple((colon,range_expression)))(input)?;
403  Ok((input, Kind::Scalar(kind)))
404}