1use ast::ParseError;
4use rand::{RngCore, seq::IndexedRandom};
5
6use crate::tokenizer::{Token, TokenTag};
7
8pub mod ast;
9
10pub const VALID_ENDS: &[TokenTag<'static>] = &[
12 TokenTag::Semicolon,
13 TokenTag::Dot,
14 TokenTag::Identifier("done"),
15];
16
17pub const PAREN_PROB: &[bool] = &[true, true, false];
19
20pub struct Parser<'tok> {
22 tokens: &'tok [Token<'tok>],
24 idx: usize,
26 rules: ParserRules,
28}
29
30pub struct ParserRules {
32 pub statements_end_with: TokenTag<'static>,
34 pub parenthesis: bool,
36}
37
38impl<'tok> Parser<'tok> {
39 pub fn from_rng<RNG: RngCore>(rng: &mut RNG) -> Self {
41 let statements_end_with = *VALID_ENDS.choose(rng).unwrap();
43 let parenthesis = *PAREN_PROB.choose(rng).unwrap();
45
46 let rules = ParserRules {
47 statements_end_with,
48 parenthesis,
49 };
50
51 Self {
52 tokens: &[],
53 idx: 0,
54 rules,
55 }
56 }
57
58 pub fn with_tokens(mut self, tokens: &'tok [Token<'tok>]) -> Self {
60 self.tokens = tokens;
61
62 self
63 }
64
65 #[inline]
67 pub fn peek(&self) -> TokenTag<'tok> {
68 self.tokens[self.idx.min(self.tokens.len() - 1)].tag
69 }
70
71 #[inline]
73 pub fn peek_token(&self) -> Token<'tok> {
74 self.tokens[self.idx.min(self.tokens.len() - 1)]
75 }
76
77 #[inline]
79 pub fn peek_back(&self) -> TokenTag<'tok> {
80 self.tokens[self.idx - 1].tag
81 }
82
83 fn at_end(&self) -> bool {
85 self.peek() == TokenTag::EOF
86 }
87
88 pub fn advance(&mut self) -> TokenTag<'tok> {
90 if !self.at_end() {
91 self.idx += 1
92 }
93
94 if self.idx == 0 {
95 self.tokens[0].tag
96 } else {
97 self.tokens[self.idx - 1].tag
98 }
99 }
100
101 pub fn consume(&mut self, token: &TokenTag<'_>) -> Result<(), ParseError> {
103 if &self.peek() == token {
104 self.idx += 1;
105 Ok(())
106 } else {
107 let Token {
108 tag,
109 line,
110 col,
111 len,
112 } = self.peek_token();
113 Err(ParseError {
114 message: format!("Expected `{token:?}`, found `{tag:?}`"),
115 line,
116 col,
117 len,
118 })
119 }
120 }
121
122 pub fn consume_end(&mut self) -> Result<(), ParseError> {
124 let tok = self.rules.statements_end_with;
125 self.consume(&tok)
126 }
127
128 pub fn consume_close_paren_if_necessary(&mut self) -> Result<(), ParseError> {
130 if self.rules.parenthesis {
131 if let Ok(_) = self.consume(&TokenTag::CloseParen) {
132 Ok(())
133 } else {
134 let Token {
135 tag: _,
136 line,
137 col,
138 len,
139 } = self.peek_token();
140 Err(ParseError {
141 message: format!("No closing parenthesis found for statement"),
142 line,
143 col,
144 len,
145 })
146 }
147 } else {
148 Ok(())
149 }
150 }
151
152 pub fn consume_open_paren_if_necessary(&mut self) -> Result<(), ParseError> {
154 if self.rules.parenthesis {
155 if let Ok(_) = self.consume(&TokenTag::OpenParen) {
156 Ok(())
157 } else {
158 let Token {
159 tag: _,
160 line,
161 col,
162 len,
163 } = self.peek_token();
164 Err(ParseError {
165 message: format!("No opening parenthesis found for statement"),
166 line,
167 col,
168 len,
169 })
170 }
171 } else {
172 Ok(())
173 }
174 }
175}