hack_assembler/
parser.rs

1use std::fmt::*;
2
3#[derive(Debug, Clone, PartialEq, Eq)]
4pub struct Located<A> {
5  pub value: A,
6  pub from: Location,
7  pub to: Location,
8}
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub struct Location {
12  pub row: usize,
13  pub col: usize,
14}
15
16#[derive(Debug, PartialEq, Eq)]
17pub enum ParseResult<'a, Output, State> {
18  ParseOk {
19    input: &'a str,
20    location: Location,
21    output: Output,
22    state: State,
23  },
24  ParseError {
25    message: String,
26    from: Location,
27    to: Location,
28    state: State,
29  },
30}
31
32impl<'a, T, S: Clone> ParseResult<'a, T, S> {
33  pub fn map<U, F: FnOnce(T) -> U>(self, func: F) -> ParseResult<'a, U, S> {
34    match self {
35      ParseResult::ParseOk { input, location, output, state } =>
36        ParseResult::ParseOk {
37          input,
38          location,
39          output: func(output),
40          state,
41        },
42      ParseResult::ParseError { message, from, to, state } =>
43        ParseResult::ParseError { message, from, to, state },
44    }
45  }
46  pub fn map_with_state<U, F: FnOnce(T, S) -> U>(self, func: F) -> ParseResult<'a, U, S> {
47    match self {
48      ParseResult::ParseOk { input, location, output, state } =>
49        ParseResult::ParseOk {
50          input,
51          location,
52          output: func(output, state.clone()),
53          state: state,
54        },
55      ParseResult::ParseError { message, from, to, state } =>
56        ParseResult::ParseError { message, from, to, state },
57    }
58  }
59  pub fn map_err<F: FnOnce(String) -> String>(self, func: F) -> ParseResult<'a, T, S> {
60    match self {
61      ParseResult::ParseOk { input, location, output, state } =>
62        ParseResult::ParseOk {
63          input,
64          location,
65          output,
66          state,
67        },
68      ParseResult::ParseError { message, from, to, state } =>
69        ParseResult::ParseError {
70          message: func(message),
71          from,
72          to,
73          state,
74        }
75    }
76  }
77  pub fn and_then<U, F: FnOnce(&'a str, T, Location, S) -> ParseResult<'a, U, S>>(self, func: F) -> ParseResult<'a, U, S> {
78    match self {
79      ParseResult::ParseOk { input, output, location, state } =>
80        func(input, output, location, state),
81      ParseResult::ParseError { message, from, to, state } =>
82        ParseResult::ParseError { message, from, to, state },
83    }
84  }
85}
86
87pub trait Parser<'a, Output, State: Clone> {
88  fn parse(&self, input: &'a str, location: Location, state: State) -> ParseResult<'a, Output, State>;
89  fn map<F, NewOutput>(self, map_fn: F) -> BoxedParser<'a, NewOutput, State>
90    where
91        Self: Sized + 'a,
92        Output: 'a,
93        NewOutput: 'a,
94        State: 'a,
95        F: Fn(Output) -> NewOutput + 'a,
96  {
97      BoxedParser::new(map(self, map_fn))
98  }
99  fn map_with_state<F, NewOutput>(self, map_fn: F) -> BoxedParser<'a, NewOutput, State>
100  where
101      Self: Sized + 'a,
102      Output: 'a,
103      NewOutput: 'a,
104      State: 'a,
105      F: Fn(Output, State) -> NewOutput + 'a,
106  {
107      BoxedParser::new(map_with_state(self, map_fn))
108  }
109  fn map_err<F>(self, map_fn: F) -> BoxedParser<'a, Output, State>
110    where
111        Self: Sized + 'a,
112        Output: 'a,
113        State: 'a,
114        F: Fn(String) -> String + 'a,
115  {
116      BoxedParser::new(map_err(self, map_fn))
117  }
118  fn and_then<F, NextParser, NewOutput>(self, f: F) -> BoxedParser<'a, NewOutput, State>
119  where
120    Self: Sized + 'a,
121    Output: 'a,
122    NewOutput: 'a,
123    State: 'a,
124    NextParser: Parser<'a, NewOutput, State> + 'a,
125    F: Fn(Output) -> NextParser + 'a,
126  {
127      BoxedParser::new(and_then(self, f))
128  }
129  fn pred<F>(self, predicate: F, expecting: &'a str) -> BoxedParser<'a, Output, State>
130  where
131    Self: Sized + 'a,
132    Output: std::fmt::Display + 'a,
133    State: 'a,
134    F: Fn(&Output) -> bool + 'a,
135  {
136    BoxedParser::new(pred(self, predicate, expecting))
137  }
138  fn ignore(self) -> BoxedParser<'a, (), State>
139    where
140      Self: Sized + 'a,
141      Output: 'a,
142      State: 'a,
143  {
144      BoxedParser::new(map(self, |_| ()))
145  }
146  fn update_state<F>(self, f: F) -> BoxedParser<'a, Output, State>
147  where
148    Self: Sized + 'a,
149    State: 'a,
150    Output: Clone + 'a,
151    F: Fn(Output, State) -> State + 'a,
152  {
153    BoxedParser::new(update_state(self, f))
154  }
155}
156
157impl<'a, F, Output, State: 'a> Parser<'a, Output, State> for F
158where
159  F: Fn(&'a str, Location, State) -> ParseResult<'a, Output,State>,
160  State: Clone,
161{
162  fn parse(&self, input: &'a str, location: Location, state: State) -> ParseResult<'a, Output, State> {
163    self(input, location, state)
164  }
165}
166
167pub struct BoxedParser<'a, Output, State> {
168  parser: Box<dyn Parser<'a, Output, State> + 'a>,
169}
170
171impl<'a, Output,State> BoxedParser<'a, Output, State> {
172  pub fn new<P>(parser: P) -> Self
173  where
174      P: Parser<'a, Output, State> + 'a,
175      State: Clone,
176  {
177      BoxedParser {
178          parser: Box::new(parser),
179      }
180  }
181}
182
183impl<'a, Output, State> Parser<'a, Output, State> for BoxedParser<'a, Output, State>
184  where
185    State: Clone,
186  {
187  fn parse(&self, input: &'a str, location: Location, state: State) -> ParseResult<'a, Output, State> {
188      self.parser.parse(input, location, state)
189  }
190}
191
192fn and_then<'a, P, F, A, B, S: Clone + 'a, NextP>(parser: P, f: F) -> impl Parser<'a, B, S>
193  where
194    P: Parser<'a, A, S>,
195    NextP: Parser<'a, B, S>,
196    F: Fn(A) -> NextP,
197    S: Clone,
198{
199  move |input, location, state| parser.parse(input, location, state)
200    .and_then(| next_input, next_output, next_location, next_state: S |
201      f(next_output).parse(next_input, next_location, next_state)
202    )
203}
204
205pub fn token<'a, S: Clone + 'a>(expected: &'static str) -> BoxedParser<'a, &str, S> {
206  BoxedParser::new(
207    move |input: &'a str, location: Location, state: S| {
208    let found = input.get(0..expected.len());
209    match found {
210      Some(next) if next == expected => ParseResult::ParseOk {
211        input: &input[expected.len()..],
212        output: expected,
213        location: increment_col(expected.len(), location),
214        state,
215      },
216      _ => ParseResult::ParseError {
217        message: format!(
218          "I'm expecting a `{}` but found {}.",
219          expected,
220          display_token(found)
221        ),
222        from: location,
223        to: match found {
224          Some(found_str) => Location {
225            row: location.row + found_str.len(),
226            col: location.col,
227          },
228          None => location,
229        },
230        state,
231      },
232    }
233  })
234}
235
236pub fn increment_col(additional_col: usize, location: Location) -> Location {
237  Location {
238    col: location.col + additional_col,
239    ..location
240  }
241}
242
243pub fn increment_row(additional_row: usize, location: Location) -> Location {
244  Location {
245    row: location.row + additional_row,
246    col: 1,
247  }
248}
249
250pub fn display_token<T: Display>(token: Option<T>) -> String {
251  match token {
252    Some(token_content) => format!("`{}`", token_content).replace("\n", "\\n"),
253    None => "nothing".to_string(),
254  }
255}
256
257pub fn pair<'a, P1, P2, R1, R2, S: Clone + 'a>(parser1: P1, parser2: P2) -> impl Parser<'a, (R1, R2), S>
258where
259  P1: Parser<'a, R1, S>,
260  P2: Parser<'a, R2, S>,
261{
262  move |input, location, state|
263    parser1.parse(input, location, state)
264      .and_then(| next_input, first_output, next_location, next_state: S |
265        parser2.parse(next_input, next_location, next_state).map(| second_output |
266          (first_output, second_output)
267        )
268      )
269}
270
271pub fn quadruple<'a, P1: 'a, P2: 'a, P3: 'a, P4: 'a, R1: 'a, R2: 'a, R3: 'a, R4: 'a, S: Clone + 'a>
272  (parser1: P1, parser2: P2, parser3: P3, parser4: P4)
273  -> BoxedParser<'a, (R1, R2, R3, R4), S>
274  where
275    P1: Parser<'a, R1, S>,
276    P2: Parser<'a, R2, S>,
277    P3: Parser<'a, R3, S>,
278    P4: Parser<'a, R4, S>,
279{
280  pair(
281    pair(parser1, parser2),
282    pair(parser3, parser4),
283  )
284  .map(|((result1, result2), (result3, result4))|
285    (result1, result2, result3, result4)
286  )
287}
288
289pub fn map<'a, P: 'a, F: 'a, A, B, S: Clone + 'a>(parser: P, map_fn: F) -> BoxedParser<'a, B, S>
290where
291  P: Parser<'a, A, S>,
292  F: Fn(A) -> B,
293{
294  BoxedParser::new(
295    move |input, location, state| parser.parse(input, location, state).map(
296    |output| map_fn(output)
297  ))
298}
299
300pub fn map_with_state<'a, P: 'a, F: 'a, A, B, S: Clone + 'a>(parser: P, map_fn: F) -> BoxedParser<'a, B, S>
301where
302  P: Parser<'a, A, S>,
303  F: Fn(A, S) -> B,
304{
305  BoxedParser::new(
306    move |input, location, state: S| match parser.parse(input, location, state.clone()) {
307      ParseResult::ParseOk {
308        input: next_input,
309        output,
310        location: next_location,
311        state: next_state,
312      } => ParseResult::ParseOk {
313        input: next_input,
314        location: next_location,
315        output: map_fn(output, next_state.clone()),
316        state: next_state,
317      },
318      ParseResult::ParseError {
319        message,
320        from,
321        to,
322        state: error_state,
323      } => ParseResult::ParseError {
324        message,
325        from,
326        to,
327        state: error_state,
328      }
329    }
330  )
331}
332
333pub fn map_err<'a, P, F, A, S: Clone + 'a>(parser: P, map_fn: F) -> impl Parser<'a, A, S>
334where
335  P: Parser<'a, A, S>,
336  F: Fn(String) -> String,
337{
338  move |input, location, state| parser.parse(input, location, state).map_err(
339    |error_message| map_fn(error_message)
340  )
341}
342
343fn map2<'a, P1, P2, F, A, B, C, S: Clone + 'a>(parser1: P1, parser2: P2, map_fn: F) -> impl Parser<'a, C, S>
344where
345  P1: Parser<'a, A, S>,
346  P2: Parser<'a, B, S>,
347  F: Fn(A, B) -> C,
348{
349  move |input, location, state| parser1.parse(input, location, state).and_then(
350    |input1, output1, location1, state1 | parser2.parse(input1, location1, state1).map(
351      |output2| map_fn(output1, output2)
352    )
353  )
354}
355
356pub fn left<'a, P1: 'a, P2: 'a, R1: 'a, R2: 'a, S: Clone + 'a>(parser1: P1, parser2: P2) -> BoxedParser<'a, R1, S>
357where
358  P1: Parser<'a, R1, S>,
359  P2: Parser<'a, R2, S>,
360{
361  map(pair(parser1, parser2), |(left, _right)| left)
362}
363
364pub fn right<'a, P1: 'a, P2: 'a, R1: 'a, R2: 'a, S: Clone + 'a>(parser1: P1, parser2: P2) -> BoxedParser<'a, R2, S>
365where
366  P1: Parser<'a, R1, S>,
367  P2: Parser<'a, R2, S>,
368{
369  map(pair(parser1, parser2), |(_left, right)| right)
370}
371
372pub fn one_or_more<'a, P, A, S: Clone + 'a>(parser: P) -> impl Parser<'a, Vec<A>, S>
373where
374  P: Parser<'a, A, S>,
375{
376  one_or_more_with_ending(false, parser)
377}
378
379pub fn one_or_more_till_end<'a, P, A, S: Clone + 'a>(parser: P) -> impl Parser<'a, Vec<A>, S>
380where
381  P: Parser<'a, A, S>,
382{
383  one_or_more_with_ending(true, parser)
384} 
385
386pub fn one_or_more_with_ending<'a, P, A, S: Clone + 'a>(till_end: bool, parser: P) -> impl Parser<'a, Vec<A>, S>
387where
388  P: Parser<'a, A, S>,
389{
390  move |mut input, mut location, mut state: S| {
391    let mut result = Vec::new();
392
393    match parser.parse(input, location, state.clone()) {
394      ParseResult::ParseOk {
395        input: next_input,
396        output: first_item,
397        location: next_location,
398        state: next_state,
399      } => {
400        input = next_input;
401        location = next_location;
402        state = next_state;
403        result.push(first_item);
404      }
405      ParseResult::ParseError {
406        message: error_message,
407        from,
408        to,
409        state
410      } => {
411        return ParseResult::ParseError {
412          message: error_message,
413          from,
414          to,
415          state,
416        };
417      }
418    }
419
420    loop {
421      match parser.parse(input, location, state.clone()) {
422        ParseResult::ParseOk {
423          input: next_input,
424          output: next_item,
425          location: next_location,
426          state: next_state,
427        } => {
428          input = next_input;
429          location = next_location;
430          state = next_state;
431          result.push(next_item);
432        },
433        ParseResult::ParseError {
434          message: error_message,
435          from,
436          to,
437          state,
438        } => if till_end && input != "" {
439          return ParseResult::ParseError {
440            message: error_message,
441            from,
442            to,
443            state,
444          };
445        } else {
446          break;
447        }
448      }
449    }
450
451    ParseResult::ParseOk {
452      input: input,
453      output: result,
454      location: location,
455      state: state,
456    }
457  }
458}
459
460pub fn zero_or_more<'a, P: 'a, A, S: Clone + 'a>(parser: P) -> BoxedParser<'a, Vec<A>, S>
461where
462  P: Parser<'a, A, S>,
463{
464  BoxedParser::new(
465    move |mut input, mut location, mut state: S| {
466    let mut result = Vec::new();
467
468    while let ParseResult::ParseOk {
469      input: next_input,
470      output: next_item,
471      location: next_location,
472      state: next_state,
473    } = parser.parse(input, location, state.clone())
474    {
475      input = next_input;
476      location = next_location;
477      state = next_state;
478      result.push(next_item);
479    }
480
481    ParseResult::ParseOk {
482      input: input,
483      output: result,
484      location: location,
485      state: state,
486    }
487  })
488}
489
490pub fn any_char<'a, S: Clone + 'a>() -> impl Parser<'a, char, S> {
491  |input: &'a str, location: Location, state| match input.chars().next() {
492    Some(character) => ParseResult::ParseOk {
493      input: &input[character.len_utf8()..],
494      output: character,
495      location: increment_col(character.len_utf8(), location),
496      state,
497    },
498    _ => ParseResult::ParseError {
499      message: "I'm expecting any character but reached the end of input.".to_string(),
500      from: location,
501      to: location,
502      state,
503    },
504  }
505}
506
507fn pred<'a, P, F, A: std::fmt::Display, S: Clone + 'a>(parser: P, predicate: F, expecting: &'a str) -> impl Parser<'a, A, S>
508where
509  P: Parser<'a, A, S>,
510  F: Fn(&A) -> bool,
511{
512  move |input, location, state: S| match parser.parse(input, location, state.clone()) {
513    ParseResult::ParseOk {
514      input: next_input,
515      output: content,
516      location: next_location,
517      state: next_state,
518    } => if predicate(&content) {
519      ParseResult::ParseOk {
520        input: next_input,
521        output: content,
522        location: next_location,
523        state: next_state,
524      }
525    } else {
526      ParseResult::ParseError {
527        message: format!(
528          "I'm expecting {} but found {}.",
529          expecting,
530          display_token(Some(content)),
531        )
532        .to_string(),
533        from: location,
534        to: next_location,
535        state: next_state,
536        }
537    },
538    _ => ParseResult::ParseError {
539      message: format!(
540        "I'm expecting {} but found {}.",
541        expecting,
542        display_token(input.chars().next())
543      )
544      .to_string(),
545      from: location,
546      to: location,
547      state,
548    },
549  }
550}
551
552pub fn space_char<'a, S: Clone + 'a>() -> BoxedParser<'a, (), S> {
553  any_char().pred(
554    |character| *character == ' ',
555    "a whitespace",
556  ).ignore()
557}
558
559pub fn newline_char<'a, S: Clone + 'a>() -> BoxedParser<'a, (), S> {
560  BoxedParser::new(
561    (move |input, location, state: S| {
562      let mut next_input: &str = input;
563      let mut next_location: Location = location;
564      let mut next_state: S = state.clone();
565      let result1 = any_char().pred(
566        |character| *character == '\r',
567        "a carriage return",
568      ).parse(input, location, state);
569      match result1 {
570        ParseResult::ParseOk {
571          input,
572          location,
573          state,
574          ..
575        } => {
576          next_input = input;
577          next_location = location;
578          next_state = state;
579        }
580        _ => {}
581      }
582      let result = any_char().pred(
583        |character| *character == '\n',
584        "a newline",
585      ).parse(next_input, next_location, next_state);
586      match result {
587        ParseResult::ParseOk {
588          input: next_input,
589          output,
590          location: next_location,
591          state: next_state,
592        } => ParseResult::ParseOk {
593          input: next_input,
594          output: output,
595          location: increment_row(1, next_location),
596          state: next_state,
597        },
598        ParseResult::ParseError {
599          message: error_message,
600          from,
601          to,
602          state,
603        } => ParseResult::ParseError {
604          message: error_message,
605          from,
606          to,
607          state,
608        }
609      }
610    }).ignore()
611  )
612}
613
614fn newline0<'a, S: Clone + 'a>(indentations: usize) -> BoxedParser<'a, (), S> {
615  zero_or_more(
616    ignore_chain(vec![
617      indents(indentations),
618      newline_char(),
619    ])
620  ).ignore()
621}
622
623pub fn newline1<'a, S: Clone + 'a>(indentations: usize) -> BoxedParser<'a, (), S> {
624  ignore_chain(vec![
625    newline_char(),
626    newline0(indentations),
627  ])
628}
629
630pub fn space0<'a, S: Clone + 'a>() -> BoxedParser<'a, (), S> {
631  zero_or_more(space_char()).ignore()
632}
633
634pub fn space1<'a, S: Clone + 'a>() -> BoxedParser<'a, (), S> {
635  one_or_more(space_char()).ignore()
636}
637
638pub fn indent<'a, S: Clone + 'a>() -> BoxedParser<'a, (), S> {
639  ignore_chain(vec![
640    space_char(),
641    space_char(),
642  ]).map_err(|_| "I'm expecting an indentation.\nAll indentations should be two spaces.".to_string())
643}
644
645pub fn indents<'a, S: Clone + 'a>(indentations: usize) -> BoxedParser<'a, (), S> {
646  repeat(
647    indentations,
648    indent(),
649  ).map_err(|_| "I'm expecting an indentation.\nAll indentations should be two spaces.".to_string())
650  .ignore()
651}
652
653fn repeat<'a, A, P, S: Clone + 'a>(times: usize, parser: P)
654  -> impl Parser<'a, Vec<A>, S>
655  where
656    P: Parser<'a, A, S>
657{
658  move |mut input, mut location, mut state: S| {
659    let mut result = Vec::new();
660
661    if times == 0 {
662      return ParseResult::ParseOk {
663        input,
664        location,
665        output: result,
666        state,
667      }
668    }
669
670    let mut counter = 0;
671
672    while let ParseResult::ParseOk {
673      input: next_input,
674      output: next_item,
675      location: next_location,
676      state: next_state,
677      ..
678    } = parser.parse(input, location, state.clone())
679    {
680      if counter >= times {
681        break;
682      }
683      input = next_input;
684      location = next_location;
685      state = next_state;
686      result.push(next_item);
687      counter = counter + 1;
688    }
689
690    ParseResult::ParseOk {
691      input: input,
692      output: result,
693      location: location,
694      state: state,
695    }
696  }
697}
698
699pub fn choose3<'a, A: 'a, P: 'a, S: Clone + 'a>(parser1: P, parser2: P, parser3: P)
700  -> BoxedParser<'a, A, S>
701  where
702    P: Parser<'a, A, S>
703{
704  either(
705    BoxedParser::new(parser1),
706    either(
707      parser2,
708      parser3,
709    )
710  )
711}
712
713pub fn either<'a, A, P: 'a, S: Clone + 'a>(parser1: P, parser2: P)
714  -> BoxedParser<'a, A, S>
715  where
716    P: Parser<'a, A, S>
717{
718  BoxedParser::new(
719    move |input, location, state: S| {
720      let result = match parser1.parse(input, location, state.clone()) {
721        ok @ ParseResult::ParseOk {..} => ok,
722        ParseResult::ParseError {..} =>
723          parser2.parse(input, location, state)
724      };
725      // println!("either result state: {:#?}", match result {
726      //   ParseResult::ParseOk { state, ..} => state,
727      //   ParseResult::ParseError { state, ..} => state,
728      // });
729      result
730    }
731  )
732}
733
734pub fn optional<'a, A: Clone + 'a, P: 'a, S: Clone + 'a>(default: A, parser: P)
735  -> BoxedParser<'a, A, S>
736  where
737    P: Parser<'a, A, S>
738{
739  either(
740    BoxedParser::new(
741      parser
742    ),
743    BoxedParser::new(
744      move |input, location, state|
745      ParseResult::ParseOk {
746          input,
747          location,
748          output: default.clone(),
749          state,
750        }
751      )
752  )
753}
754
755pub fn newline_with_comment<'a, S: Clone + 'a>(comment_symbol: &'static str) -> impl Parser<'a, (), S> {
756  either(
757    ignore_chain(vec![
758      space0(),
759      line_comment(comment_symbol),
760    ]),
761    ignore_chain(vec![
762      space0(),
763      newline_char()
764    ]),
765  )
766}
767
768pub fn line_comment<'a, S: Clone + 'a>(comment_symbol: &'static str) -> BoxedParser<'a, (), S> {
769  ignore_chain(vec![
770    token(comment_symbol).ignore(),
771    zero_or_more(any_char().pred(
772      |character| *character != '\n' && *character != '\r',
773      "any character",
774    )).ignore(),
775    newline_char(),
776  ])
777}
778
779pub fn line_comments<'a, S: Clone + 'a>(indentations: usize) -> BoxedParser<'a, (), S> {
780  either(
781    one_or_more(
782      ignore_chain(vec![
783        newline0(indentations),
784        indents(indentations),
785        token("--").ignore(),
786        zero_or_more(any_char().pred(
787          |character| *character != '\n' && *character != '\r',
788          "any character",
789        )).ignore(),
790        newline1(indentations),
791      ])
792    ).ignore(),
793    newline0(indentations),
794  )
795}
796
797pub fn ignore_chain<'a, S: Clone + 'a>(parsers: Vec<BoxedParser<'a, (), S>>) -> BoxedParser<'a, (), S>
798{
799  BoxedParser::new(
800    move | mut input, mut location, mut state | {
801    for parser in &parsers {
802      match parser.parse(input, location, state) {
803        ParseResult::ParseOk {
804          input: next_input,
805          location: next_location,
806          state: next_state,
807          ..
808        } => {
809          input = next_input;
810          location = next_location;
811          state = next_state;
812        },
813        error @ ParseResult::ParseError {..} => {
814          return error;
815        }
816      }
817    }
818    ParseResult::ParseOk {
819      input,
820      location,
821      output: (),
822      state,
823    }
824  })
825}
826
827pub fn whole_decimal<'a, S: Clone + 'a>() -> impl Parser<'a, usize, S> {
828  one_or_more(
829    any_char().pred(
830    | character |
831      character.is_digit(10)
832    , "a whole decimal number"
833    )
834  ).map(| digits | digits.iter().collect::<String>().parse().unwrap())
835}
836
837pub fn located<'a, P: 'a, A, S: Clone + 'a>(parser: P) -> impl Parser<'a, Located<A>, S>
838  where
839    P: Parser<'a, A, S>
840{
841  move |input, location, state|
842  match parser.parse(input, location, state) {
843    ParseResult::ParseOk {
844      input: next_input,
845      output,
846      location: next_location,
847      state: next_state,
848    } => ParseResult::ParseOk {
849        input: next_input,
850        output: Located {
851          value: output,
852          from: Location {
853            row: location.row,
854            col: location.col,
855          },
856          to: Location {
857            row: next_location.row,
858            col: next_location.col,
859          },
860        },
861        location: next_location,
862        state: next_state,
863      },
864    ParseResult::ParseError {
865      message: error_message,
866      from,
867      to,
868      state,
869    } =>
870      ParseResult::ParseError {
871        message: error_message,
872        from,
873        to,
874        state,
875      }
876  }
877}
878
879pub fn display_error(source: &str, error_message: String, from: Location, to: Location) -> String {
880  let row = from.row;
881  let col = from.col;
882  let error_length = if to.col == from.col {
883    1
884  } else {
885    to.col - from.col
886  };
887  let error_line = row.to_string() + "| " + source.split("\n").collect::<Vec<&str>>()[row - 1];
888  let error_pointer = " ".repeat(col - 1 + row.to_string().len() + 2) + &"^".repeat(error_length);
889  let error_report =
890    error_line + "\n" + &error_pointer + "\n" + "⚠️" + &error_message;
891  error_report
892}
893
894pub fn update_state<'a, P, A: Clone, S: Clone + 'a, F>(parser: P, f: F) -> impl Parser<'a, A, S>
895  where
896    P: Parser<'a, A, S>,
897    F: Fn(A, S) -> S
898{
899  move |input, location, state| {
900    match parser.parse(input, location, state) {
901      ParseResult::ParseOk {
902        input: next_input,
903        location: next_location,
904        state: next_state,
905        output,
906      } =>
907        ParseResult::ParseOk {
908          input: next_input,
909          output: output.clone(),
910          location: next_location,
911          state: f(output, next_state),
912        },
913      ParseResult::ParseError {
914        message,
915        from,
916        to,
917        state,
918      } =>
919        ParseResult::ParseError {
920          message,
921          from,
922          to,
923          state,
924        }
925    }
926  }
927}