ast_description_lang/ast/
mod.rs1use crate::{Ident, InvalidIdent, Specs};
2use anyhow::{anyhow, Context, Result};
3use proc_macro2::TokenStream;
4use std::{
5 fmt::{self, Display, Formatter},
6 str::FromStr,
7};
8
9mod collapsed;
10mod lex;
11mod parsed;
12mod print;
13mod raw;
14
15pub fn generate_ast_mod(text: &str, specs: &Specs<'_>, config: &Config<'_>) -> Result<TokenStream> {
16 let error = TokenStream::from_str(config.error)
17 .map_err(|err| anyhow!("{err}"))
18 .context("failed to lex the error type")?;
19 let tokens_mod = TokenStream::from_str(config.tokens_mod)
20 .map_err(|err| anyhow!("{err}"))
21 .context("failed to lex the tokens mod path")?;
22 let span = match config.span {
23 Some(span) => Some(
24 TokenStream::from_str(span)
25 .map_err(|err| anyhow!("{err}"))
26 .context("failed to lex the span type")?,
27 ),
28 None => None,
29 };
30 let ast = raw::Ast::parse(text).context("failed to lex AST description")?;
31 let ast = ast
32 .transform(specs)
33 .context("failed to parse AST description")?;
34 let ast = ast
35 .transform()
36 .context("failed to collapse AST description")?;
37 let ast = ast.print(specs, error, tokens_mod, span);
38 Ok(ast)
39}
40
41#[non_exhaustive]
42pub struct Config<'c> {
43 pub error: &'c str,
44 pub tokens_mod: &'c str,
45 pub span: Option<&'c str>,
46}
47
48#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
49enum Modifier {
50 Repeat,
51 Csv,
52 OnePlus,
53 CsvOnePlus,
54 Optional,
55 Boxed,
56}
57
58impl<'i> Ident<'i> {
59 pub fn new(ident: &'i str) -> Result<Self, InvalidIdent> {
60 if ident.chars().all(|c| raw::IDENT_CHARS.contains(c)) {
61 Ok(Ident(ident))
62 } else {
63 Err(InvalidIdent(String::from(ident)))
64 }
65 }
66}
67
68impl Default for Config<'_> {
69 fn default() -> Self {
70 Self {
71 error: "::chumsky::error::Simple<Token>",
72 tokens_mod: "crate::tokens",
73 span: None,
74 }
75 }
76}
77
78impl Display for Modifier {
79 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
80 match self {
81 Modifier::Repeat => write!(f, "*"),
82 Modifier::Csv => write!(f, ",*"),
83 Modifier::OnePlus => write!(f, "+"),
84 Modifier::CsvOnePlus => write!(f, ",+"),
85 Modifier::Optional => write!(f, "?"),
86 Modifier::Boxed => write!(f, "~"),
87 }
88 }
89}