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