chronlang_parser/
lib.rs

1mod parser;
2pub use parser::parse;
3
4pub mod ast;
5
6#[cfg(test)]
7mod test {
8  use super::*;
9
10  use crate::ast::{Stmt, Spanned};
11
12  use ariadne::{
13    Report,
14    Label,
15    Source as SourceCode,
16    ReportKind, Color,
17  };
18  
19  use chumsky::{error::SimpleReason, prelude::Simple};
20
21  fn display_errs(src: &str, errs: &Vec<Simple<char>>) {
22    let start = errs.iter()
23      .map(|err| err.span())
24      .fold(src.len(), |min, cur| if cur.start < min { cur.start } else { min });
25
26    Report::build(ReportKind::Error, (), start)
27      .with_labels(
28        errs.iter()
29          .map(|err| {
30            Label::new(err.span())
31            .with_message(match err.reason() {
32              SimpleReason::Unexpected => err.to_string(),
33              SimpleReason::Unclosed { span: _, delimiter } => format!("Unmatched delimited {}", delimiter),
34              SimpleReason::Custom(msg) => msg.clone(),
35            })
36            .with_color(Color::Red)
37          })
38      )
39      .finish()
40      .eprint(SourceCode::from(src.clone()))
41      .unwrap();
42  }
43
44  fn _parse(src: &str) -> Result<Vec<Spanned<Stmt>>, Vec<Simple<char>>> {
45    let res = parse(src);
46
47    match res {
48      Ok(ast) => Ok(ast),
49      Err(errs) => {
50        display_errs(&src, &errs);
51        Err(errs)
52      },
53    }
54  }
55
56  #[test]
57  fn it_works() {
58    let res = _parse("
59      import * from @core/ipa
60      
61      series F = { i, e, ε, æ }
62
63      class X encodes (Place Manner) {
64        ℂ = velar trill,
65        ℤ = labiodental lateral_fricative ,
66      }
67
68      lang OEng : Old English
69      lang OEng < AmEng : American English
70      lang OEng < RP : Received Pronunciation
71      
72      @ 1000, OEng
73      
74      - water /ˈwæ.ter/ {
75        noun. liquid that forms the seas, lakes, rivers, and rain
76        verb. pour or sprinkle water over a plant or area
77      }
78      
79      @ 1940, AmEng
80      
81      $ [C+alveolar+stop] > [+flap] / V_V : Alveolar stops lenite to flaps intervocallically
82    ");
83
84    println!("{:#?}", res);
85
86    assert!(res.is_ok())
87  }
88}