#[macro_use]
use crate::*;
#[cfg(not(feature = "no-std"))] use core::fmt;
#[cfg(feature = "no-std")] use alloc::fmt;
#[cfg(feature = "no-std")] use alloc::string::String;
#[cfg(feature = "no-std")] use alloc::vec::Vec;
use nom::{
branch::alt,
bytes::complete::tag,
character::complete::{anychar, char as nom_char, digit1, satisfy},
combinator::{map, map_res, opt},
multi::{many0, many1, separated_list1},
sequence::{delimited, preceded, tuple as nom_tuple},
IResult,
};
use std::collections::HashMap;
use colored::*;
use crate::*;
pub fn grammar(input: ParseString) -> ParseResult<Grammar> {
let ((input, rules)) = many1(rule)(input)?;
let (input, _) = new_line(input)?;
Ok((input, Grammar { rules }))
}
fn grammar_identifier(input: ParseString) -> ParseResult<GrammarIdentifier> {
let (input, first) = alpha_token(input)?;
let (input, mut rest) = many0(alt((alpha_token, digit_token, dash)))(input)?;
let mut id = vec![first];
id.extend(rest);
let name = Token::merge_tokens(&mut id).unwrap();
Ok((input, GrammarIdentifier{name}))
}
fn rule(input: ParseString) -> ParseResult<Rule> {
let ((input, name)) = grammar_identifier(input)?;
let ((input, _)) = define_operator(input)?;
let ((input, expr)) = grammar_expression(input)?;
let ((input, _)) = semicolon(input)?;
Ok((input, Rule { name, expr }))
}
fn grammar_expression(input: ParseString) -> ParseResult<GrammarExpression> {
let (input, first) = term(input)?;
let (input, rest) = many0(nom_tuple((bar, term)))(input)?;
if rest.len() == 0 {
Ok((input,first))
} else {
let mut choice = vec![first];
choice.extend(rest.into_iter().map(|(_, term)| term));
Ok((input, GrammarExpression::Choice(choice)))
}
}
fn term(input: ParseString) -> ParseResult<GrammarExpression> {
let (input, first) = factor(input)?;
let (input, rest) = many0(nom_tuple((comma, factor)))(input)?;
let mut seq: Vec<GrammarExpression> = vec![first];
seq.extend(rest.into_iter().map(|(_, factor)| factor));
if seq.len() == 1 {
return Ok((input, seq.pop().unwrap()));
}
Ok((input, GrammarExpression::Sequence(seq)))
}
fn definition(input: ParseString) -> ParseResult<GrammarExpression> {
let (input, id) = grammar_identifier(input)?;
Ok((input, GrammarExpression::Definition(id)))
}
fn repeat0(input: ParseString) -> ParseResult<GrammarExpression> {
let (input, _) = asterisk(input)?;
let (input, expr) = factor(input)?;
Ok((input, GrammarExpression::Repeat0(Box::new(expr))))
}
fn repeat1(input: ParseString) -> ParseResult<GrammarExpression> {
let (input, _) = plus(input)?;
let (input, expr) = factor(input)?;
Ok((input, GrammarExpression::Repeat1(Box::new(expr))))
}
fn optional(input: ParseString) -> ParseResult<GrammarExpression> {
let (input, _) = question(input)?;
let (input, expr) = factor(input)?;
Ok((input, GrammarExpression::Optional(Box::new(expr))))
}
fn peek(input: ParseString) -> ParseResult<GrammarExpression> {
let (input, _) = right_angle(input)?;
let (input, expr) = factor(input)?;
Ok((input, GrammarExpression::Peek(Box::new(expr))))
}
fn not(input: ParseString) -> ParseResult<GrammarExpression> {
let (input, _) = negate(input)?;
let (input, expr) = factor(input)?;
Ok((input, GrammarExpression::Not(Box::new(expr))))
}
fn list(input: ParseString) -> ParseResult<GrammarExpression> {
let (input, _) = left_bracket(input)?;
let (input, first) = factor(input)?;
let (input, _) = comma(input)?;
let (input, second) = factor(input)?;
let (input, _) = right_bracket(input)?;
Ok((input, GrammarExpression::List(Box::new(first), Box::new(second))))
}
fn g_range(input: ParseString) -> ParseResult<GrammarExpression> {
let (input, start) = terminal_token(input)?;
let (input, _) = tuple((period,period))(input)?;
let (input, end) = terminal_token(input)?;
Ok((input, GrammarExpression::Range(start, end)))
}
fn factor(input: ParseString) -> ParseResult<GrammarExpression> {
alt((
repeat0,
repeat1,
optional,
peek,
not,
group,
list,
definition,
g_range,
terminal,
))(input)
}
fn group(input: ParseString) -> ParseResult<GrammarExpression> {
let (input, expr) = delimited(left_parenthesis, grammar_expression, right_parenthesis)(input)?;
Ok((input, GrammarExpression::Group(Box::new(expr))))
}
fn terminal(input: ParseString) -> ParseResult<GrammarExpression> {
let (input, trminl) = terminal_token(input)?;
Ok((input, GrammarExpression::Terminal(trminl)))
}
fn terminal_token(input: ParseString) -> ParseResult<Token> {
let (input, _) = quote(input)?;
let (input, mut t) = many0(tuple((is_not(quote),any_token)))(input)?;
let (input, _) = quote(input)?;
let mut t = t.into_iter().map(|(_,b)| b).collect::<Vec<Token>>();
let token = Token::merge_tokens(&mut t).unwrap();
Ok((input,token))
}