mech_syntax/
base.rs

1#[macro_use]
2use crate::parser::*;
3use crate::*;
4use crate::label;
5use crate::labelr;
6use nom::{
7  multi::separated_list0,
8  sequence::tuple as nom_tuple,
9};
10use crate::nodes::Kind;
11
12macro_rules! leaf {
13  ($name:ident, $byte:expr, $token:expr) => (
14    pub fn $name(input: ParseString) -> ParseResult<Token> {
15      if input.is_empty() {
16        return Err(nom::Err::Error(ParseError::new(input, "Unexpected eof")))
17      }
18      let start = input.loc();
19      let byte = input.graphemes[input.cursor];
20      let (input, _) = tag($byte)(input)?;
21      let end = input.loc();
22      let src_range = SourceRange { start, end };
23      Ok((input, Token{kind: $token, chars: $byte.chars().collect::<Vec<char>>(), src_range}))
24    }
25  )
26}
27
28leaf!{at, "@", TokenKind::At}
29leaf!{hashtag, "#", TokenKind::HashTag}
30leaf!{period, ".", TokenKind::Period}
31leaf!{colon, ":", TokenKind::Colon}
32leaf!{comma, ",", TokenKind::Comma}
33leaf!{percent, "%", TokenKind::Percent}
34leaf!{apostrophe, "'", TokenKind::Apostrophe}
35leaf!{left_bracket, "[", TokenKind::LeftBracket}
36leaf!{right_bracket, "]", TokenKind::RightBracket}
37leaf!{left_parenthesis, "(", TokenKind::LeftParenthesis}
38leaf!{right_parenthesis, ")", TokenKind::RightParenthesis}
39leaf!{left_brace, "{", TokenKind::LeftBrace}
40leaf!{right_brace, "}", TokenKind::RightBrace}
41leaf!{dollar, "$", TokenKind::Dollar}
42leaf!{equal, "=", TokenKind::Equal}
43leaf!{left_angle, "<", TokenKind::LeftAngle}
44leaf!{right_angle, ">", TokenKind::RightAngle}
45leaf!{exclamation, "!", TokenKind::Exclamation}
46leaf!{question, "?", TokenKind::Question}
47leaf!{plus, "+", TokenKind::Plus}
48leaf!{dash, "-", TokenKind::Dash}
49leaf!{underscore, "_", TokenKind::Underscore}
50leaf!{asterisk, "*", TokenKind::Asterisk}
51leaf!{slash, "/", TokenKind::Slash}
52leaf!{backslash, "\\", TokenKind::Backslash}
53leaf!{caret, "^", TokenKind::Caret}
54leaf!{space, " ", TokenKind::Space}
55leaf!{tab, "\t", TokenKind::Tab}
56leaf!{tilde, "~", TokenKind::Tilde}
57leaf!{grave, "`", TokenKind::Grave}
58leaf!{bar, "|", TokenKind::Bar}
59leaf!{quote, "\"", TokenKind::Quote}
60leaf!{ampersand, "&", TokenKind::Ampersand}
61leaf!{semicolon, ";", TokenKind::Semicolon}
62leaf!{new_line_char, "\n", TokenKind::Newline}
63leaf!{carriage_return, "\r", TokenKind::CarriageReturn}
64leaf!{carriage_return_new_line, "\r\n", TokenKind::CarriageReturn}
65leaf!{english_true_literal, "true", TokenKind::True}
66leaf!{english_false_literal, "false", TokenKind::False}
67leaf!{check_mark, "✓", TokenKind::True}
68leaf!{cross, "✗", TokenKind::False}
69leaf!{box_tl_round, "╭", TokenKind::BoxDrawing}
70leaf!{box_tr_round, "╮", TokenKind::BoxDrawing}
71leaf!{box_bl_round, "╰", TokenKind::BoxDrawing}
72leaf!{box_br_round, "╯", TokenKind::BoxDrawing}
73leaf!{box_tl, "┌", TokenKind::BoxDrawing}
74leaf!{box_tr, "┐", TokenKind::BoxDrawing}
75leaf!{box_bl, "└", TokenKind::BoxDrawing}
76leaf!{box_br, "┘", TokenKind::BoxDrawing}
77leaf!{box_cross, "┼", TokenKind::BoxDrawing}
78leaf!{box_horz, "─", TokenKind::BoxDrawing}
79leaf!{box_t_left, "├", TokenKind::BoxDrawing}
80leaf!{box_t_right, "┤", TokenKind::BoxDrawing}
81leaf!{box_t_top, "┬", TokenKind::BoxDrawing}
82leaf!{box_t_bottom, "┴", TokenKind::BoxDrawing}
83leaf!{box_vert, "│", TokenKind::BoxDrawing}
84
85// emoji_grapheme := ?emoji_grapheme_literal? ;
86pub fn emoji_grapheme(mut input: ParseString) -> ParseResult<String> {
87  if let Some(matched) = input.consume_emoji() {
88    Ok((input, matched))
89  } else {
90    Err(nom::Err::Error(ParseError::new(input, "Unexpected character")))
91  }
92}
93
94// alpha := ?alpha_literal? ;
95pub fn alpha(mut input: ParseString) -> ParseResult<String> {
96  if let Some(matched) = input.consume_alpha() {
97    Ok((input, matched))
98  } else {
99    Err(nom::Err::Error(ParseError::new(input, "Unexpected character")))
100  }
101}
102
103// digit := ?digit_literal? ;
104pub fn digit(mut input: ParseString) -> ParseResult<String> {
105  if let Some(matched) = input.consume_digit() {
106    Ok((input, matched))
107  } else {
108    Err(nom::Err::Error(ParseError::new(input, "Unexpected character")))
109  }
110}
111
112// any := ?any_character? ;
113pub fn any(mut input: ParseString) -> ParseResult<String> {
114  if let Some(matched) = input.consume_one() {
115    Ok((input, matched))
116  } else {
117    Err(nom::Err::Error(ParseError::new(input, "Unexpected eof")))
118  }
119}
120
121// forbidden_emoji := box_drawing | other_forbidden_shapes ;
122pub fn forbidden_emoji(input: ParseString) -> ParseResult<Token> {
123  alt((box_tl, box_br, box_bl, box_tr, box_t_left,box_tl_round,box_br_round, box_tr_round, box_bl_round, box_vert, box_cross, box_horz, box_t_right, box_t_top, box_t_bottom))(input)
124}
125
126// emoji := emoji_grapheme+ ;
127pub fn emoji(input: ParseString) -> ParseResult<Token> {
128  let msg1 = "Cannot be a box-drawing emoji";
129  let start = input.loc();
130  let (input, _) = is_not(forbidden_emoji)(input)?;
131  let (input, g) = emoji_grapheme(input)?;
132  let end = input.loc();
133  let src_range = SourceRange { start, end };
134  Ok((input, Token{kind: TokenKind::Emoji, chars: g.chars().collect::<Vec<char>>(), src_range}))
135}
136
137// alpha_token := alpha_literal_token ;
138pub fn alpha_token(input: ParseString) -> ParseResult<Token> {
139  let (input, (g, src_range)) = range(alpha)(input)?;
140  Ok((input, Token{kind: TokenKind::Alpha, chars: g.chars().collect::<Vec<char>>(), src_range}))
141}
142
143// digit_token := digit_literal_token ;
144pub fn digit_token(input: ParseString) -> ParseResult<Token> {
145  let (input, (g, src_range)) = range(digit)(input)?;
146  Ok((input, Token{kind: TokenKind::Digit, chars: g.chars().collect::<Vec<char>>(), src_range}))
147}
148
149// underscore_digit := underscore, digit ;
150pub fn underscore_digit(input: ParseString) -> ParseResult<Token> {
151  let (input, _) = underscore(input)?;
152  let (input, digit) = digit_token(input)?;
153  Ok((input,digit))
154}
155
156// digit_sequence := digit, (underscore_digit | digit)*
157pub fn digit_sequence(input: ParseString) -> ParseResult<Vec<Token>> {
158  let (input, mut start) = digit_token(input)?;
159  let (input, mut tokens) = many0(alt((underscore_digit,digit_token)))(input)?;
160  let mut all = vec![start];
161  all.append(&mut tokens);
162  Ok((input,all))
163}
164
165// grouping_symbol := left_parenthesis | right_parenthesis | left_angle | right_angle | left_brace | right_brace | left_bracket | right_bracket
166pub fn grouping_symbol(input: ParseString) -> ParseResult<Token> {
167  let (input, grouping) = alt((left_parenthesis, right_parenthesis, left_angle, right_angle, left_brace, right_brace, left_bracket, right_bracket))(input)?;
168  Ok((input, grouping))
169}
170
171// punctuation := period | exclamation | question | comma | colon | semicolon | quote | apostrophe ;
172pub fn punctuation(input: ParseString) -> ParseResult<Token> {
173  let (input, punctuation) = alt((period, exclamation, question, comma, colon, semicolon, quote, apostrophe))(input)?;
174  Ok((input, punctuation))
175}
176
177// escaped_char := "\" ,  symbol | punctuation ;
178pub fn escaped_char(input: ParseString) -> ParseResult<Token> {
179  let (input, _) = backslash(input)?;
180  let (input, symbol) = alt((symbol, punctuation))(input)?;
181  Ok((input, symbol))
182}
183
184// symbol := ampersand | bar | at | slash | hashtag | equal | backslash | tilde | plus | dash | asterisk | caret | underscore ;
185pub fn symbol(input: ParseString) -> ParseResult<Token> {
186  let (input, symbol) = alt((ampersand, bar, at, slash, hashtag, equal, backslash, tilde, plus, dash, asterisk, caret, underscore))(input)?;
187  Ok((input, symbol))
188}
189
190// text := (alpha | digit | space | tabe | escaped_char | punctuation | grouping_symbol | symbol)+ ;
191pub fn text(input: ParseString) -> ParseResult<Token> {
192  let (input, text) = alt((alpha_token, digit_token, space, tab, escaped_char, punctuation, grouping_symbol, symbol))(input)?;
193  Ok((input, text))
194}
195
196// identifier := (alpha | emoji), (alpha | digit | symbol | emoji)* ;
197pub fn identifier(input: ParseString) -> ParseResult<Identifier> {
198  let (input, (first, mut rest)) = nom_tuple((alt((alpha_token, emoji)), many0(alt((alpha_token, digit_token, symbol, emoji)))))(input)?;
199  let mut tokens = vec![first];
200  tokens.append(&mut rest);
201  let mut merged = Token::merge_tokens(&mut tokens).unwrap();
202  merged.kind = TokenKind::Identifier; 
203  Ok((input, Identifier{name: merged}))
204}
205
206// boolean_literal := true_literal | false_literal ;
207pub fn boolean(input: ParseString) -> ParseResult<Token> {
208  let (input, boolean) = alt((true_literal, false_literal))(input)?;
209  Ok((input, boolean))
210}
211
212// true_literal := english_true_literal | check_mark ;
213pub fn true_literal(input: ParseString) -> ParseResult<Token> {
214  let (input, token) = alt((english_true_literal, check_mark))(input)?;
215  Ok((input, token))
216}
217
218// false_literal := english_false_literal | cross ;
219pub fn false_literal(input: ParseString) -> ParseResult<Token> {
220  let (input, token) = alt((english_false_literal, cross))(input)?;
221  Ok((input, token))
222}
223
224// new_line := new_line_char | carriage_new_line ;
225pub fn new_line(input: ParseString) -> ParseResult<Token> {
226  let (input, result) = alt((carriage_return_new_line,new_line_char,carriage_return, ))(input)?;
227  Ok((input, result))
228}
229
230// whitespace := space | new_line | carriage_return | tabe ;
231pub fn whitespace(input: ParseString) -> ParseResult<Token> {
232  let (input, space) = alt((space,tab,new_line))(input)?;
233  Ok((input, space))
234}
235
236// whitespace0 := whitespace* ;
237pub fn whitespace0(input: ParseString) -> ParseResult<()> {
238  let (input, _) = many0(whitespace)(input)?;
239  Ok((input, ()))
240}
241
242// whitespace1 := one_or_more_whitespaces ;
243pub fn whitespace1(input: ParseString) -> ParseResult<()> {
244  let (input, _) = many1(whitespace)(input)?;
245  Ok((input, ()))
246}
247
248// space_tab := space | tab ;
249pub fn space_tab(input: ParseString) -> ParseResult<Token> {
250  let (input, space) = alt((space,tab))(input)?;
251  Ok((input, space))
252}
253
254// list_separator := whitespace*, ",", whitespace* ;
255pub fn list_separator(input: ParseString) -> ParseResult<()> {
256  let (input,_) = nom_tuple((whitespace0,tag(","),whitespace0))(input)?;
257  Ok((input, ()))
258}
259
260// enum_separator := whitespace*, "|", whitespace* ;
261pub fn enum_separator(input: ParseString) -> ParseResult<()> {
262  let (input,_) = nom_tuple((whitespace0,tag("|"),whitespace0))(input)?;
263  Ok((input, ()))
264}
265
266
267// number-literal := (integer | hexadecimal | octal | binary | decimal | float | rational | scientific) ;
268
269pub fn number(input: ParseString) -> ParseResult<Number> {
270  let (input, real_num) = real_number(input)?;
271  match tag("i")(input.clone()) {
272    Ok((input,_)) => {
273      return Ok((input, Number::Imaginary(
274        ComplexNumber{
275          real: None, 
276          imaginary: ImaginaryNumber{number: real_num}
277        })));
278      }
279    _ => match nom_tuple((plus,real_number,tag("i")))(input.clone()) {
280      Ok((input, (_,imaginary_num,_))) => {
281        return Ok((input, Number::Imaginary(
282          ComplexNumber{
283            real: Some(real_num), 
284            imaginary: ImaginaryNumber{number: imaginary_num},
285          })));
286        }
287      _ => ()
288    }
289  }
290  Ok((input, Number::Real(real_num)))
291}
292
293// real_number := optional_dash (hexadecimal_literal | decimal_literal | octal_literal | binary_literal | scientific_literal | rational_literal | float_literal | integer_literal) ;
294pub fn real_number(input: ParseString) -> ParseResult<RealNumber> {
295  let (input, neg) = opt(dash)(input)?;
296  let (input, result) = alt((hexadecimal_literal, decimal_literal, octal_literal, binary_literal, scientific_literal, rational_literal, float_literal, integer_literal))(input)?;
297  let result = match neg {
298    Some(_) => RealNumber::Negated(Box::new(result)),
299    None => result,
300  };
301  Ok((input, result))
302}
303
304// rational_literal := integer_literal "/" integer_literal ;
305pub fn rational_literal(input: ParseString) -> ParseResult<RealNumber> {
306  let (input, RealNumber::Integer(numerator)) = integer_literal(input)? else { unreachable!() };
307  let (input, _) = slash(input)?;
308  let (input, RealNumber::Integer(denominator)) = integer_literal(input)? else { unreachable!() };
309  Ok((input, RealNumber::Rational((numerator,denominator))))
310}
311
312// scientific_literal := (float_literal | integer_literal) ("e" | "E") (optional_plus | ε) (optional_dash | ε) (float_literal | integer_literal) ;
313pub fn scientific_literal(input: ParseString) -> ParseResult<RealNumber> {
314  let (input, base) = match float_literal(input.clone()) {
315    Ok((input, RealNumber::Float(base))) => {
316      (input, base)
317    }
318    _ => match integer_literal(input.clone()) {
319      Ok((input, RealNumber::Integer(base))) => {
320        (input, (base, Token::default()))
321      }
322      Err(err) => {return Err(err);}
323      _ => unreachable!(),
324    }
325  };
326  let (input, _) = alt((tag("e"), tag("E")))(input)?;
327  let (input, _) = opt(plus)(input)?;
328  let (input, neg) = opt(dash)(input)?;
329  let (input, (ex_whole,ex_part)) = match float_literal(input.clone()) {
330    Ok((input, RealNumber::Float(exponent))) => {
331      (input, exponent)
332    }
333    _ => match integer_literal(input.clone()) {
334      Ok((input, RealNumber::Integer(exponent))) => {
335        (input, (exponent, Token::default()))
336      }
337      Err(err) => {return Err(err);}
338      _ => unreachable!(),
339    }
340  };
341  let ex_sign = match neg {
342    Some(_) => true,
343    None => false,
344  };
345  Ok((input, RealNumber::Scientific((base,(ex_sign,ex_whole,ex_part)))))
346}
347
348// float_decimal_start := ".", digit_sequence ;
349pub fn float_decimal_start(input: ParseString) -> ParseResult<RealNumber> {
350  let (input, _) = period(input)?;
351  let (input, part) = digit_sequence(input)?;
352  let mut tokens2 = part.clone();
353  let mut merged = Token::merge_tokens(&mut tokens2).unwrap();
354  merged.kind = TokenKind::Number;
355  Ok((input, RealNumber::Float((Token::default(),merged))))
356}
357
358// float_full := digit_sequence, ".", digit_sequnce ;
359pub fn float_full(input: ParseString) -> ParseResult<RealNumber> {
360  let (input, mut whole) = digit_sequence(input)?;
361  let (input, _) = period(input)?;
362  let (input, mut part) = digit_sequence(input)?;
363  let mut whole = Token::merge_tokens(&mut whole).unwrap();
364  let mut part = Token::merge_tokens(&mut part).unwrap();
365  whole.kind = TokenKind::Number;
366  part.kind = TokenKind::Number;
367  Ok((input, RealNumber::Float((whole,part))))
368}
369
370// float_literal := "."?, digit1, "."?, digit0 ;
371pub fn float_literal(input: ParseString) -> ParseResult<RealNumber> {
372  let (input, result) = alt((float_decimal_start,float_full))(input)?;
373  Ok((input, result))
374}
375
376// integer := digit1 ;
377pub fn integer_literal(input: ParseString) -> ParseResult<RealNumber> {
378  let (input, mut digits) = digit_sequence(input)?;
379  let mut merged = Token::merge_tokens(&mut digits).unwrap();
380  merged.kind = TokenKind::Number; 
381  Ok((input, RealNumber::Integer(merged)))
382}
383
384// decimal_literal := "0d", <digit1> ;
385pub fn decimal_literal(input: ParseString) -> ParseResult<RealNumber> {
386  let msg = "Expects decimal digits after \"0d\"";
387  let input = tag("0d")(input);
388  let (input, _) = input?;
389  let (input, mut tokens) = label!(digit_sequence, msg)(input)?;
390  let mut merged = Token::merge_tokens(&mut tokens).unwrap();
391  merged.kind = TokenKind::Number; 
392  Ok((input, RealNumber::Decimal(merged)))
393}
394
395// hexadecimal_literal := "0x", <hex_digit+> ;
396pub fn hexadecimal_literal(input: ParseString) -> ParseResult<RealNumber> {
397  let msg = "Expects hexadecimal digits after \"0x\"";
398  let input = tag("0x")(input);
399  let (input, _) = input?;
400  let (input, mut tokens) = label!(many1(alt((digit_token,underscore,alpha_token))), msg)(input)?;
401  let mut merged = Token::merge_tokens(&mut tokens).unwrap();
402  merged.kind = TokenKind::Number; 
403  Ok((input, RealNumber::Hexadecimal(merged)))
404}
405
406// octal_literal := "0o", <oct_digit+> ;
407pub fn octal_literal(input: ParseString) -> ParseResult<RealNumber> {
408  let msg = "Expects octal digits after \"0o\"";
409  let input = tag("0o")(input);
410  let (input, _) = input?;
411  let (input, mut tokens) = label!(many1(alt((digit_token,underscore,alpha_token))), msg)(input)?;
412  let mut merged = Token::merge_tokens(&mut tokens).unwrap();
413  merged.kind = TokenKind::Number; 
414  Ok((input, RealNumber::Octal(merged)))
415}
416
417// binary_literal := "0b", <bin_digit+> ;
418pub fn binary_literal(input: ParseString) -> ParseResult<RealNumber> {
419  let msg = "Expects binary digits after \"0b\"";
420  let input = tag("0b")(input);
421  let (input, _) = input?;
422  let (input, mut tokens) = label!(many1(alt((digit_token,underscore,alpha_token))), msg)(input)?;
423  let mut merged = Token::merge_tokens(&mut tokens).unwrap();
424  merged.kind = TokenKind::Number; 
425  Ok((input, RealNumber::Binary(merged)))
426}
427
428// empty := underscore+ ;
429pub fn empty(input: ParseString) -> ParseResult<Token> {
430  let (input, (g, src_range)) = range(many1(tag("_")))(input)?;
431  Ok((input, Token{kind: TokenKind::Empty, chars: g.join("").chars().collect(), src_range}))
432}
433
434// #### Kind Annotations
435
436// kind_annotation := left_angle, kind, right_angle ;
437pub fn kind_annotation(input: ParseString) -> ParseResult<KindAnnotation> {
438  let msg2 = "Expects at least one unit in kind annotation";
439  let msg3 = "Expects right angle";
440  let (input, (_, r)) = range(left_angle)(input)?;
441  let (input, kind) = kind(input)?;
442  let (input, _) = label!(right_angle, msg3, r)(input)?;
443  Ok((input, KindAnnotation{ kind }))
444}
445
446// kind := empty | atom | tuple | scalar | bracket | map | brace ;
447pub fn kind(input: ParseString) -> ParseResult<Kind> {
448  let (input, kind) = alt((kind_fxn,kind_empty,kind_atom,kind_tuple, kind_scalar, kind_bracket, kind_map, kind_brace))(input)?;
449  Ok((input, kind))
450}
451
452// kind_empty := underscore+ ;
453pub fn kind_empty(input: ParseString) -> ParseResult<Kind> {
454  let (input, _) = many1(underscore)(input)?;
455  Ok((input, Kind::Empty))
456}
457
458// kind_atom := "`", identifier ;
459pub fn kind_atom(input: ParseString) -> ParseResult<Kind> {
460  let (input, _) = grave(input)?;
461  let (input, atm) = identifier(input)?;
462  Ok((input, Kind::Atom(atm)))
463}
464
465// kind_map = "{", kind, ":", kind, "}" ;
466pub fn kind_map(input: ParseString) -> ParseResult<Kind> {
467  let (input, _) = left_brace(input)?;
468  let (input, key_kind) = kind(input)?;
469  let (input, _) = colon(input)?;
470  let (input, value_kind) = kind(input)?;
471  let (input, _) = right_brace(input)?;
472  Ok((input, Kind::Map(Box::new(key_kind),Box::new(value_kind))))
473}
474
475// kind_fxn := "(" kind (list_separator kind)* ")" "=" "(" kind (list_separator kind)* ")" ;
476pub fn kind_fxn(input: ParseString) -> ParseResult<Kind> {
477  let (input, _) = left_parenthesis(input)?;
478  let (input, input_kinds) = separated_list0(list_separator,kind)(input)?;
479  let (input, _) = right_parenthesis(input)?;
480  let (input, _) = equal(input)?;
481  let (input, _) = left_parenthesis(input)?;
482  let (input, output_kinds) = separated_list0(list_separator,kind)(input)?;
483  let (input, _) = right_parenthesis(input)?;
484  Ok((input, Kind::Function(input_kinds,output_kinds)))
485}
486
487// kind_brace = "{", list1(",",kind) "}", [":"], list0(",",literal) ;
488pub fn kind_brace(input: ParseString) -> ParseResult<Kind> {
489  let (input, _) = left_brace(input)?;
490  let (input, kinds) = separated_list1(list_separator,kind)(input)?;
491  let (input, _) = right_brace(input)?;
492  let (input, _) = opt(colon)(input)?;
493  let (input, size) = separated_list0(list_separator,literal)(input)?;
494  Ok((input, Kind::Brace((kinds,size))))
495}
496
497// kind_bracket = "[", list1(",",kind) "]", [":"], list0(",",literal) ;
498pub fn kind_bracket(input: ParseString) -> ParseResult<Kind> {
499  let (input, _) = left_bracket(input)?;
500  let (input, kinds) = separated_list1(list_separator,kind)(input)?;
501  let (input, _) = right_bracket(input)?;
502  let (input, _) = opt(colon)(input)?;
503  let (input, size) = separated_list0(list_separator,literal)(input)?;
504  Ok((input, Kind::Bracket((kinds,size))))
505}
506
507// kind_tuple = "(", list1(",",kind) ")" ;
508pub fn kind_tuple(input: ParseString) -> ParseResult<Kind> {
509  let (input, _) = left_parenthesis(input)?;
510  let (input, kinds) = separated_list1(list_separator, kind)(input)?;
511  let (input, _) = right_parenthesis(input)?;
512  Ok((input, Kind::Tuple(kinds)))
513}
514
515// kind_scalar := identifier ;
516pub fn kind_scalar(input: ParseString) -> ParseResult<Kind> {
517  let (input, kind) = identifier(input)?;
518  Ok((input, Kind::Scalar(kind)))
519}