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
59
60
61
use nom::multi::{many0, many1};
use nom::sequence::tuple;
use nom::Parser;
use nom_supreme::ParserExt;

use kodept_core::structure::rlt;

use crate::parser::nom::{match_token, newline_separated};
use crate::parser::top_level;
use crate::{
    function,
    lexer::{Identifier::*, Keyword::*, Operator::*, Symbol::*, Token},
    match_token,
    token_stream::TokenStream,
};
use crate::{match_any_token, ParseResult};

fn module_statement(input: TokenStream) -> ParseResult<rlt::Module> {
    tuple((
        match_token(Module),
        match_token!(Token::Identifier(Type(_))),
        match_token(LBrace),
        newline_separated(top_level::grammar),
        match_token(RBrace).cut(),
    ))
    .context(function!())
    .map(|it| rlt::Module::Ordinary {
        keyword: it.0.span.into(),
        id: it.1.span.into(),
        lbrace: it.2.span.into(),
        rest: it.3.into_boxed_slice(),
        rbrace: it.4.span.into(),
    })
    .parse(input)
}

fn global_module_statement(input: TokenStream) -> ParseResult<rlt::Module> {
    tuple((
        match_token(Module),
        match_token!(Token::Identifier(Type(_))),
        match_token(Flow),
        many0(top_level::grammar).cut(),
    ))
    .context(function!())
    .map(|it| rlt::Module::Global {
        keyword: it.0.span.into(),
        id: it.1.span.into(),
        flow: it.2.span.into(),
        rest: it.3.into_boxed_slice(),
    })
    .parse(input)
}

pub fn grammar(input: TokenStream) -> ParseResult<rlt::File> {
    many1(module_statement)
        .map(|m| rlt::File::new(m.into_boxed_slice()))
        .or(global_module_statement.map(|m| rlt::File::new(Box::new([m]))))
        .terminated(match_any_token!(Token::Ignore(_)).opt())
        .context(function!())
        .parse(input)
}