1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
//! # Regen
//!
//! Regen is a language that defines a language. See [README](https://github.com/Pistonite/regen-lang) on GitHub

use crate::core::Language;

use sdk::{ASTParser, CreateParseTree, Error, ParseTreeResult, TokenStream};

pub mod core;
pub mod dynamic;
pub mod emit;
pub mod grammar;
pub mod sdk;

/// Create a language from a grammar string
///
/// This is a convienience wrapper for the underlying lexer and parser.
/// It is used by the CLI and does not have many options.
///
/// If you need more control over the language creation process, see the source code
/// and use the underlying parser directly.
pub fn parse_language_from_grammar(
    grammar: &str,
    stack_size: usize,
) -> Result<Language, Vec<Error>> {
    // Parse the language from the grammar
    let lex_output = grammar::tokenize(grammar);
    let mut ts = TokenStream::new(&lex_output.tokens, stack_size);
    let ast_parser = grammar::Parser;
    let asts = match ast_parser.parse_ast_all(&mut ts) {
        Err((_, errors)) => {
            // if errors occur when parsing AST, ignore the ASTs generated and return
            // the errors
            return Err(errors);
        }
        Ok(asts) => asts,
    };
    // create language builder
    let mut lang_builder = Box::default();
    let mut errors = vec![];
    let mut pts = vec![];
    for ast in &asts {
        match ast.parse_pt(lang_builder) {
            ParseTreeResult::Err { ctx, err, .. } => {
                errors.extend(err);
                lang_builder = ctx;
            }
            ParseTreeResult::Ok { pt, ctx } => {
                pts.push(pt);
                lang_builder = ctx;
            }
        }
    }
    if !errors.is_empty() {
        return Err(errors);
    }
    lang_builder.build(&pts)
}