use std::fmt::{Display, Error, Formatter};
use serde_derive::{Deserialize, Serialize};
use crate::text::{TextContext, TextPosition, TextSpan};
use crate::tokens::Token;
#[derive(Copy, Clone, Eq, PartialEq)]
pub enum SymbolType {
Terminal,
Variable,
Virtual
}
pub const SID_NOTHING: u32 = 0;
pub const SID_EPSILON: u32 = 1;
pub const SID_DOLLAR: u32 = 2;
#[derive(Debug, Copy, Clone, Eq, PartialEq, Serialize, Deserialize)]
pub struct Symbol<'a> {
pub id: u32,
pub name: &'a str
}
impl<'a> Display for Symbol<'a> {
fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
write!(f, "{}", self.name)
}
}
pub trait SemanticElementTrait<'s, 'a> {
fn get_position(&self) -> Option<TextPosition>;
fn get_span(&self) -> Option<TextSpan>;
fn get_context(&self) -> Option<TextContext<'a>>;
fn get_symbol(&self) -> Symbol<'s>;
fn get_value(&self) -> Option<&'a str>;
}
pub enum SemanticElement<'s, 't, 'a> {
Token(Token<'s, 't, 'a>),
Terminal(Symbol<'s>),
Variable(Symbol<'s>),
Virtual(Symbol<'s>)
}
impl<'s, 't, 'a> SemanticElementTrait<'s, 'a> for SemanticElement<'s, 't, 'a> {
fn get_position(&self) -> Option<TextPosition> {
match self {
SemanticElement::Token(token) => token.get_position(),
SemanticElement::Terminal(_symbol) => None,
SemanticElement::Variable(_symbol) => None,
SemanticElement::Virtual(_symbol) => None
}
}
fn get_span(&self) -> Option<TextSpan> {
match self {
SemanticElement::Token(token) => token.get_span(),
SemanticElement::Terminal(_symbol) => None,
SemanticElement::Variable(_symbol) => None,
SemanticElement::Virtual(_symbol) => None
}
}
fn get_context(&self) -> Option<TextContext<'a>> {
match self {
SemanticElement::Token(token) => token.get_context(),
SemanticElement::Terminal(_symbol) => None,
SemanticElement::Variable(_symbol) => None,
SemanticElement::Virtual(_symbol) => None
}
}
fn get_symbol(&self) -> Symbol<'s> {
match self {
SemanticElement::Token(token) => token.get_symbol(),
SemanticElement::Terminal(symbol) => *symbol,
SemanticElement::Variable(symbol) => *symbol,
SemanticElement::Virtual(symbol) => *symbol
}
}
fn get_value(&self) -> Option<&'a str> {
match self {
SemanticElement::Token(token) => token.get_value(),
SemanticElement::Terminal(_symbol) => None,
SemanticElement::Variable(_symbol) => None,
SemanticElement::Virtual(_symbol) => None
}
}
}
impl<'s, 't, 'a> SemanticElement<'s, 't, 'a> {
pub fn get_symbol_type(&self) -> SymbolType {
match self {
SemanticElement::Token(_token) => SymbolType::Terminal,
SemanticElement::Terminal(_symbol) => SymbolType::Terminal,
SemanticElement::Variable(_symbol) => SymbolType::Variable,
SemanticElement::Virtual(_symbol) => SymbolType::Virtual
}
}
}
pub trait SemanticBody {
fn get_element_at(&self, index: usize) -> SemanticElement;
fn length(&self) -> usize;
}
pub type SemanticAction = dyn FnMut(Symbol, &dyn SemanticBody);