1use std::{
2 fmt::{self, Display, Write},
3 ops::Deref,
4};
5
6use logos::Logos;
7
8#[derive(Logos, Debug, PartialEq, Clone)]
9pub enum Token {
10 #[regex("[a-zA-Z]+", |lex| lex.slice().chars().next().unwrap())]
11 Ident(char),
12 #[token("(")]
13 OpenParen,
14 #[token(")")]
15 CloseParen,
16 #[token("[")]
17 OpenBracket,
18 #[token("]")]
19 CloseBracket,
20 #[token("{")]
21 OpenCurlyBrace,
22 #[token("}")]
23 CloseCurlyBrace,
24 #[token("not", |_| '¬')]
25 #[token("!", |_| '¬')]
26 #[token("¬", |_| '¬')]
27 #[token("∼", |_| '¬')]
28 #[token("~", |_| '¬')]
29 Not(char),
30 #[token("->", |_| '→')]
31 #[token("=>", |_| '→')]
32 #[token("⇒", |_| '→')]
33 #[token("→", |_| '→')]
34 #[token("⊃", |_| '→')]
35 Implication(char),
36 #[token("<->", |_| '↔')]
37 #[token("<=>", |_| '↔')]
38 #[token("⇔", |_| '↔')]
39 #[token("↔", |_| '↔')]
40 #[token("iff", |_| '↔')]
41 #[token("xnor", |_| '↔')]
42 Biconditional(char),
43 #[token("and", |_| '∧')]
44 #[token("&", |_| '∧')]
45 #[token("&&", |_| '∧')]
46 #[token("∧", |_| '∧')]
47 And(char),
48 #[token("or", |_| '∨')]
49 #[token("|", |_| '∨')]
50 #[token("||", |_| '∨')]
51 #[token("∨", |_| '∨')]
52 Or(char),
53 #[token("xor", |_| '⊕')]
54 #[token("⊕", |_| '⊕')]
55 XOr(char),
56 #[token("=", |_| '≡')]
57 #[token("==", |_| '≡')]
58 #[token("eq", |_| '≡')]
59 #[token("≡", |_| '≡')]
60 Equals(char),
61 #[token("!=", |_| '≠')]
62 #[token("≠", |_| '≠')]
63 NotEquals(char),
64 #[token("0")]
65 #[token("false")]
66 #[token("False")]
67 False,
68 #[token("1")]
69 #[token("true")]
70 #[token("True")]
71 True,
72}
73
74impl Into<bool> for Token {
75 fn into(self) -> bool{
76 if let Token::True = self {
77 return true;
78 }
79 false
80 }
81}
82
83impl From<bool> for Token {
84 fn from(value: bool) -> Self {
85 if value {
86 return Token::True;
87 }
88 Token::False
89 }
90}
91
92#[derive(Debug)]
93pub struct Tokens {
94 tokens: Vec<Token>,
95}
96
97impl Tokens {
98 pub fn from_text(text: &str) -> Self {
99 Self {
100 tokens: Token::lexer(text).filter_map(|result| result.ok()).collect(),
101 }
102 }
103
104 pub fn enclose(&mut self, left: Token,right: Token) {
105 self.tokens.insert(0, left);
106 self.tokens.push(right);
107 }
108}
109
110impl Deref for Tokens {
111 type Target = [Token];
112 fn deref(&self) -> &Self::Target {
113 &self.tokens
114 }
115}
116
117impl Display for Tokens {
118 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
119 for token in self.tokens.iter() {
120 match token {
121 Token::Ident(c) => f.write_char(*c),
122 Token::OpenParen => f.write_char('('),
123 Token::CloseParen => f.write_char(')'),
124 Token::OpenBracket => f.write_char('['),
125 Token::CloseBracket => f.write_char(']'),
126 Token::OpenCurlyBrace => f.write_char('{'),
127 Token::CloseCurlyBrace => f.write_char('}'),
128 Token::Not(symb) |
129 Token::Implication(symb) |
130 Token::Biconditional(symb) |
131 Token::And(symb) |
132 Token::Or(symb) |
133 Token::XOr(symb) |
134 Token::Equals(symb) |
135 Token::NotEquals(symb) => f.write_str(&format!(" {} ",symb.to_string())),
136 Token::False => f.write_char('0'),
137 Token::True => f.write_char('1'),
138 }?
139 }
140 Ok(())
141 }
142}
143
144#[cfg(test)]
145mod tests {
146 use super::*;
147
148 #[test]
149 fn implication() {
150 let s = "a -> b";
151 assert_eq!(
152 Tokens::from_text(s).tokens,
153 vec![Token::Ident('a'), Token::Implication('→'), Token::Ident('b')]
154 );
155 }
156
157 #[test]
158 fn equals() {
159 let s = "a == b";
160 assert_eq!(
161 Tokens::from_text(s).tokens,
162 vec![Token::Ident('a'), Token::Equals('≡'), Token::Ident('b')]
163 );
164 }
165
166 #[test]
167 fn not_equals() {
168 let s = "a != b";
169 assert_eq!(
170 Tokens::from_text(s).tokens,
171 vec![Token::Ident('a'), Token::NotEquals('≠'), Token::Ident('b')]
172 );
173 }
174
175 #[test]
176 fn not() {
177 let s = "(not a)";
178 let tokens = Tokens::from_text(s).tokens;
179 assert_eq!(
180 tokens,
181 vec![Token::OpenParen,Token::Not('¬'), Token::Ident('a'),Token::CloseParen]
182 );
183 }
184
185 #[test]
186 fn and() {
187 let symbols = ["and", "&", "&&", "∧"];
188 for s in symbols {
189 let expr = format!("a {} b",s);
190 let tokens = Tokens::from_text(&expr).tokens;
191 assert_eq!(
192 tokens,
193 vec![Token::Ident('a'),Token::And('∧'), Token::Ident('b')]
194 );
195 }
196 }
197
198 #[test]
199 fn or() {
200 let symbols = ["or", "|", "||", "∨"];
201 for s in symbols {
202 let expr = format!("a {} b",s);
203 let tokens = Tokens::from_text(&expr).tokens;
204 assert_eq!(
205 tokens,
206 vec![Token::Ident('a'),Token::Or('∨'), Token::Ident('b')]
207 );
208 }
209 }
210}