use std::fmt::{Debug, Display};
use pest::iterators::Pair;
use crate::ccarp::error::{rule_err, rule_mismatch, safe_unwrap, CCErr, Result};
use super::defs::{list_ast, print_vec, Rule, AST};
#[derive(Debug, PartialEq, Eq, Clone, Default)]
pub struct TokenTree(pub Vec<Token>);
list_ast!(TokenTree : Token where tokentree => token);
impl Display for TokenTree {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f,"{}",print_vec(&self.0, " "))
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum Token {
Keyword(Keyword),
Identifier(Identifier),
Literal(Literal),
Punctuator(Punctuator),
Include(Include)
}
impl AST for Token {
fn take(pair: Pair<Rule>) -> Result<Self> {
match pair.as_rule() {
Rule::token => {
let pair=safe_unwrap!(pair.into_inner().next(),"Token");
match pair.as_rule() {
Rule::keyword => Ok(Self::Keyword(Keyword::take(pair)?)),
Rule::ident => Ok(Self::Identifier(Identifier::take(pair)?)),
Rule::lit => Ok(Self::Literal(Literal::take(pair)?)),
Rule::punct => Ok(Self::Punctuator(Punctuator::take(pair)?)),
Rule::include => Ok(Self::Include(Include::take(pair)?)),
_ => Err(rule_mismatch!(pair))
}
},
_ => Err(rule_mismatch!(pair,token))
}
}
}
impl Display for Token {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Keyword(keyword) => write!(f,"{keyword}"),
Self::Identifier(identifier) => write!(f,"{identifier}"),
Self::Literal(literal) => write!(f,"{literal}"),
Self::Punctuator(punctuator) => write!(f,"{punctuator}"),
Self::Include(_) => write!(f,"")
}
}
}
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct Keyword(pub String);
impl AST for Keyword {
fn take(pair: Pair<Rule>) -> Result<Self> {
match pair.as_rule() {
Rule::keyword => Ok(Self(pair.as_str().to_string())),
_ => Err(rule_mismatch!(pair,keyword))
}
}
}
impl Display for Keyword {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f,"{}",self.0)
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub enum Literal {
Int(String),
Float(String),
Char(String),
String(String)
}
impl AST for Literal {
fn take(mut pair: Pair<Rule>) -> Result<Self> {
if pair.as_rule()==Rule::tok_lit { pair=safe_unwrap!(pair.into_inner().next(),"Literal token"); }
match pair.as_rule() {
Rule::lit => {
pair=safe_unwrap!(pair.into_inner().next(),"Literal");
match pair.as_rule() {
Rule::float => Ok(Self::Float(pair.as_str().to_string())),
Rule::int => Ok(Self::Int(pair.as_str().to_string())),
Rule::char => Ok(Self::Char(pair.as_str().to_string())),
Rule::string => Ok(Self::String(pair.as_str().to_string())),
_ => Err(rule_mismatch!(pair))
}
},
_ => Err(rule_mismatch!(pair,lit))
}
}
}
impl Display for Literal {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Int(lit)|Self::Float(lit)|Self::Char(lit)|Self::String(lit) => write!(f,"#l{lit}#l"),
}
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Identifier(pub String);
impl AST for Identifier {
fn take(mut pair: Pair<Rule>) -> Result<Self> {
if pair.as_rule()==Rule::tok_ident { pair=safe_unwrap!(pair.into_inner().next(),"Identifier token"); }
match pair.as_rule() {
Rule::ident => Ok(Self(pair.as_str().to_string())),
_ => Err(rule_mismatch!(pair,ident))
}
}
}
impl Display for Identifier {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f,"#i{}#i",self.0)
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Punctuator(pub String);
impl AST for Punctuator {
fn take(pair: Pair<Rule>) -> Result<Self> {
match pair.as_rule() {
Rule::punct => Ok(Self(pair.as_str().to_string())),
_ => Err(rule_mismatch!(pair,punct))
}
}
}
impl Display for Punctuator {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f,"#p{}#p",self.0)
}
}
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct Include(pub String);
impl AST for Include {
fn take(pair: Pair<Rule>) -> Result<Self> {
match pair.as_rule() {
Rule::include => {
let pair=safe_unwrap!(pair.into_inner().next(),"Include");
match pair.as_rule() {
Rule::header_name => Ok(Self(pair.as_str().to_string())),
_ => Err(rule_mismatch!(pair,header_name))
}
},
_ => Err(rule_mismatch!(pair,include))
}
}
}
impl Include {
pub fn get_name(self) -> String {
let mut out=self.0.chars();
out.next();
out.next_back();
out.collect()
}
}