1use lexer_rs::PosnInCharStream;
3use lexer_rs::SimpleParseError;
4use lexer_rs::{CharStream, FmtContext, Lexer, LexerOfStr, LexerOfString, LexerParseResult};
5use lexer_rs::{LineColumn, StreamCharPos, StreamCharSpan};
6
7#[derive(Debug, Clone, Copy)]
10pub enum SimpleToken<P, K>
11where
12 P: PosnInCharStream,
13 K: std::fmt::Debug + Copy + Clone + Sized,
14{
15 CommentLine(StreamCharSpan<P>),
17 Id(StreamCharSpan<P>),
19 Digits(StreamCharSpan<P>),
21 OpenBra(P, char),
23 CloseBra(P, char),
25 Whitespace(StreamCharSpan<P>),
27 Keyword(P, K),
29 Newline(P),
31 Char(P, char),
33}
34
35impl<P, K> SimpleToken<P, K>
37where
38 P: PosnInCharStream,
39 K: std::fmt::Debug + Copy + Clone + Sized,
40{
41 pub fn parse_char<L>(
43 stream: &L,
44 state: L::State,
45 ch: char,
46 ) -> LexerParseResult<P, Self, L::Error>
47 where
48 L: CharStream<P>,
49 L: Lexer<Token = Self, State = P>,
50 {
51 let pos = state;
52 match ch {
53 '\n' => Ok(Some((stream.consumed(state, 1), Self::Newline(pos)))),
54 '(' | '[' | '{' => Ok(Some((stream.consumed(state, 1), Self::OpenBra(pos, ch)))),
55 ')' | ']' | '}' => Ok(Some((stream.consumed(state, 1), Self::CloseBra(pos, ch)))),
56 ch => Ok(Some((stream.consumed_char(state, ch), Self::Char(pos, ch)))),
57 }
58 }
59
60 pub fn parse_comment_line<L>(
62 stream: &L,
63 state: L::State,
64 ch: char,
65 ) -> LexerParseResult<P, Self, L::Error>
66 where
67 L: CharStream<P>,
68 L: Lexer<Token = Self, State = P>,
69 {
70 match stream.do_while(state, ch, &|n, ch| {
71 ((n < 2) && (ch == '/')) || ((n >= 2) && ch != '\n')
72 }) {
73 (state, Some((start, _n))) => {
74 let span = StreamCharSpan::new(start, state);
75 Ok(Some((state, SimpleToken::CommentLine(span))))
76 }
77 (_, None) => Ok(None),
78 }
79 }
80
81 pub fn parse_digits<L>(
83 stream: &L,
84 state: L::State,
85 ch: char,
86 ) -> LexerParseResult<P, Self, L::Error>
87 where
88 L: CharStream<P>,
89 L: Lexer<Token = Self, State = P>,
90 {
91 match stream.do_while(state, ch, &|_, ch| ch.is_ascii_digit()) {
92 (state, Some((start, _n))) => {
93 let span = StreamCharSpan::new(start, state);
94 Ok(Some((state, SimpleToken::Digits(span))))
95 }
96 (_, None) => Ok(None),
97 }
98 }
99
100 pub fn parse_whitespace<L>(
102 stream: &L,
103 state: L::State,
104 ch: char,
105 ) -> LexerParseResult<P, Self, L::Error>
106 where
107 L: CharStream<P>,
108 L: Lexer<Token = Self, State = P>,
109 {
110 match stream.do_while(state, ch, &|_, ch| (ch == ' ' || ch == '\t')) {
111 (state, Some((start, _))) => {
112 let span = StreamCharSpan::new(start, state);
113 Ok(Some((state, SimpleToken::Whitespace(span))))
114 }
115 (_, None) => Ok(None),
116 }
117 }
118
119 pub fn parse_id<L, F1, F2>(
121 stream: &L,
122 state: L::State,
123 ch: char,
124 is_id_start: F1,
125 is_id: F2,
126 ) -> LexerParseResult<P, Self, L::Error>
127 where
128 L: CharStream<P>,
129 L: Lexer<Token = Self, State = P>,
130 F1: Fn(char) -> bool,
131 F2: Fn(char) -> bool,
132 {
133 match stream.do_while(state, ch, &|n, ch| {
134 (n == 0 && is_id_start(ch)) || ((n > 0) && is_id(ch))
135 }) {
136 (state, Some((start, _))) => {
137 let span = StreamCharSpan::new(start, state);
138 Ok(Some((state, SimpleToken::Id(span))))
139 }
140 (_, None) => Ok(None),
141 }
142 }
143
144 pub fn parse_keyword<L>(
146 stream: &L,
147 state: L::State,
148 _ch: char,
149 keywords: &[(&[u8], K)],
150 ) -> LexerParseResult<P, Self, L::Error>
151 where
152 L: CharStream<P>,
153 L: Lexer<Token = Self, State = P>,
154 {
155 for (k, v) in keywords {
156 if stream.matches_bytes(&state, k) {
157 let n = k.len();
158 let next_state = stream.consumed(state, n);
159 return Ok(Some((next_state, SimpleToken::Keyword(state, *v))));
160 }
161 }
162 Ok(None)
163 }
164
165 }
167
168type TextPos = StreamCharPos<LineColumn>;
170type LexToken = SimpleToken<TextPos, ()>;
171type LexError = SimpleParseError<TextPos>;
172type TextStream<'stream> = LexerOfStr<'stream, TextPos, LexToken, LexError>;
173
174type BoxDynLexTokenLexFn<'a> = Box<
175 dyn for<'call, 'stream> Fn(
176 &'call TextStream<'stream>,
177 TextPos,
178 char,
179 ) -> LexerParseResult<TextPos, LexToken, LexError>
180 + 'a,
181>;
182use std::env;
183#[derive(Default)]
184struct ParserVec<'a> {
185 pub parsers: Vec<BoxDynLexTokenLexFn<'a>>,
186}
187impl<'a> ParserVec<'a> {
188 pub fn new() -> Self {
189 let parsers = Vec::new();
190 Self { parsers }
191 }
192 pub fn add_parser<F>(&mut self, f: F)
193 where
194 F: Fn(&TextStream, TextPos, char) -> LexerParseResult<TextPos, LexToken, LexError>
195 + 'static,
196 {
197 self.parsers.push(Box::new(f));
198 }
199}
200
201fn main() -> Result<(), String> {
202 let args: Vec<String> = env::args().collect();
203 if args.len() < 2 {
204 return Err(format!("Usage: {} <expression>", args[0]));
205 }
206 let args_as_string = args[1..].join(" ");
207
208 let mut parsers = ParserVec::new();
209 parsers.add_parser(|a, b, c| LexToken::parse_whitespace(a, b, c));
210 parsers.add_parser(|a, b, c| LexToken::parse_comment_line(a, b, c));
211 parsers.add_parser(|a, b, c| LexToken::parse_digits(a, b, c));
212 parsers.add_parser(|a, b, c| LexToken::parse_char(a, b, c));
213
214 let l = LexerOfString::default().set_text(args_as_string);
215 let ts = l.lexer();
216 let tokens = ts.iter(&parsers.parsers);
217
218 println!("Parsing");
219 for t in tokens {
220 let t = {
221 match t {
222 Err(e) => {
223 println!();
224 let mut s = String::new();
225 l.fmt_context(&mut s, &e.pos, &e.pos).unwrap();
226 eprintln!("{}", s);
227 return Err(format!("{}", e));
228 }
229 Ok(t) => t,
230 }
231 };
232 println!("{:?}", t);
233 }
234 println!();
235 println!("Text parsed okay");
236 Ok(())
237}