use crate::input::Token;
const fn new_token(n: crate::indices::PlainToken) -> Token {
match Token::new(n) {
Some(token) => token,
None => panic!("`Token` cannot be 0"),
}
}
pub(crate) fn collect<T: Copy, C>(slice: &[T]) -> C
where
C: FromIterator<T>,
{
slice.iter().copied().collect()
}
pub(crate) mod tokens {
use crate::{input::Token, test_common::new_token};
pub(crate) const T1: Token = new_token(1);
pub(crate) const T2: Token = new_token(2);
pub(crate) const T3: Token = new_token(3);
pub(crate) const T4: Token = new_token(4);
pub(crate) const T5: Token = new_token(5);
pub(crate) const INT: Token = new_token(6);
pub(crate) const PLUS: Token = new_token(7);
pub(crate) const MINUS: Token = new_token(8);
pub(crate) const TIMES: Token = new_token(9);
pub(crate) const DIV: Token = new_token(10);
pub(crate) const EQUAL: Token = new_token(11);
pub(crate) const NEQUAL: Token = new_token(12);
pub(crate) const MORE: Token = new_token(13);
pub(crate) const LESS: Token = new_token(14);
pub(crate) const MOREEQ: Token = new_token(15);
pub(crate) const LESSEQ: Token = new_token(16);
pub(crate) const AND: Token = new_token(17);
pub(crate) const OR: Token = new_token(18);
pub(crate) const XOR: Token = new_token(19);
pub(crate) const RANGE: Token = new_token(20);
pub(crate) const OPEN_RANGE: Token = new_token(21);
pub(crate) const BITAND: Token = new_token(22);
pub(crate) const BITOR: Token = new_token(23);
pub(crate) const BITXOR: Token = new_token(24);
pub(crate) const LSHIFT: Token = new_token(25);
pub(crate) const RSHIFT: Token = new_token(26);
pub(crate) const ASSIGN: Token = new_token(27);
pub(crate) const ASSIGN_ADD: Token = new_token(28);
pub(crate) const ASSIGN_SUB: Token = new_token(29);
pub(crate) const ASSIGN_MUL: Token = new_token(30);
pub(crate) const ASSIGN_DIV: Token = new_token(31);
pub(crate) const ASSIGN_MOD: Token = new_token(32);
pub(crate) const ASSIGN_BITAND: Token = new_token(33);
pub(crate) const ASSIGN_BITOR: Token = new_token(34);
pub(crate) const ASSIGN_BITXOR: Token = new_token(35);
pub(crate) const QUESTION: Token = new_token(36);
pub(crate) const CALL: Token = new_token(37);
pub(crate) const INDEX: Token = new_token(38);
pub(crate) const IF: Token = new_token(39);
pub(crate) const PUB: Token = new_token(40);
pub(crate) const FN: Token = new_token(41);
}
pub(crate) mod nodes {
use crate::input::Node;
pub(crate) const START: Node = Node(0);
pub(crate) const N1: Node = Node(1);
pub(crate) const N2: Node = Node(2);
pub(crate) const N3: Node = Node(3);
pub(crate) const N4: Node = Node(4);
pub(crate) const N5: Node = Node(5);
pub(crate) const N6: Node = Node(6);
pub(crate) const N7: Node = Node(7);
pub(crate) const N8: Node = Node(8);
pub(crate) const E: Node = Node(9);
pub(crate) const FUNCTION: Node = Node(10);
pub(crate) const ITEM: Node = Node(11);
pub(crate) const ITEMS: Node = Node(12);
pub(crate) const VISIBILITY: Node = Node(13);
}
pub(crate) mod expressions {
use crate::{
input::{
Grammar, Node, ProdIdx,
Symbol::{self, Node as N, Token as T},
Token,
},
lr::LRTable,
};
pub(crate) mod symbols {
pub(crate) use crate::test_common::{
nodes::{E, START},
tokens::*,
};
}
pub(crate) fn get_grammar_with_precedence() -> (Grammar, [ProdIdx; 5]) {
use symbols::*;
let mut grammar = Grammar::new();
let add_prod = grammar
.add_production(E, vec![N(E), T(PLUS), N(E)])
.unwrap();
let sub_prod = grammar
.add_production(E, vec![N(E), T(MINUS), N(E)])
.unwrap();
let mul_prod = grammar
.add_production(E, vec![N(E), T(TIMES), N(E)])
.unwrap();
let neg_prod = grammar.add_production(E, vec![T(MINUS), N(E)]).unwrap();
let if_prod = grammar.add_production(E, vec![T(IF), N(E)]).unwrap();
let family = grammar.add_precedence_family();
grammar
.get_production_mut(add_prod)
.unwrap()
.set_left_precedence(family, 2)
.set_right_precedence(family, 3);
grammar
.get_production_mut(sub_prod)
.unwrap()
.set_left_precedence(family, 2)
.set_right_precedence(family, 3);
grammar
.get_production_mut(mul_prod)
.unwrap()
.set_left_precedence(family, 4)
.set_right_precedence(family, 5);
grammar
.get_production_mut(neg_prod)
.unwrap()
.set_right_precedence(family, 6);
grammar
.get_production_mut(if_prod)
.unwrap()
.set_right_precedence(family, 1);
(grammar, [add_prod, sub_prod, mul_prod, neg_prod, if_prod])
}
#[derive(Clone, Copy)]
pub(crate) struct DisplayTable<'a, Kind>(&'a LRTable<Kind>);
impl<Kind: 'static> DisplayTable<'_, Kind> {
fn token_str(token: Token) -> &'static str {
match token {
symbols::PLUS => "+",
symbols::MINUS => "-",
symbols::TIMES => "×",
symbols::IF => "if",
_ => unreachable!(),
}
}
fn node_str(node: Node) -> &'static str {
match node {
symbols::START => "START",
symbols::E => "E",
_ => unreachable!(),
}
}
fn symbol_str(symbol: Symbol) -> &'static str {
match symbol {
T(t) => Self::token_str(t),
N(n) => Self::node_str(n),
}
}
}
impl<Kind: 'static> std::fmt::Display for DisplayTable<'_, Kind> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let (grammar, _) = get_grammar_with_precedence();
f.write_str("Table {\n")?;
for (state_idx, state) in self.0.states.iter().enumerate() {
writeln!(f, " State({state_idx}) {{")?;
f.write_str(" items: [\n")?;
for (item_idx, item) in state.items.iter().enumerate() {
writeln!(f, " LRItem({item_idx}): {{")?;
writeln!(f, " {} →", Self::node_str(item.prod_idx.lhs))?;
let rhs = grammar.get_rhs(item.prod_idx).unwrap_or_default();
for (idx, s) in rhs.iter().enumerate() {
f.write_str(if item.index as usize == idx {
"∙"
} else {
" "
})?;
f.write_str(Self::symbol_str(*s))?;
}
if rhs.len() == item.index as usize {
f.write_str("∙")?;
}
f.write_str(" [")?;
if let Some(&Some(left)) = item.annotations.forbidden_left.get(0) {
write!(f, "{left}")?;
} else {
f.write_str("_")?;
}
f.write_str(", ")?;
if let Some(&Some(right)) = item.annotations.forbidden_right.get(0) {
write!(f, "{right}")?;
} else {
f.write_str("_")?;
}
f.write_str("]\n")?;
writeln!(
f,
" directly_derives: {:?},",
item.directly_derives
)?;
writeln!(f, " derives: {:?},", item.derives)?;
f.write_str(" },\n")?;
}
f.write_str(" ],\n")?;
f.write_str(" },\n")?;
}
f.write_str("}")
}
}
}