summaryrefslogtreecommitdiff
path: root/src/parser.rs
diff options
context:
space:
mode:
authorMike Buland <mike@xagasoft.com>2026-06-05 14:46:35 -0700
committerMike Buland <mike@xagasoft.com>2026-06-05 14:46:35 -0700
commit3dd9ca69340512e42867b43db689e494bada2000 (patch)
tree8834a0736873139302c8555bc5a7768cd739f74b /src/parser.rs
parent11f5bc0c5a8bcfb6ac8fef8abc33297c4addc81b (diff)
downloadcrimtag-3dd9ca69340512e42867b43db689e494bada2000.tar.gz
crimtag-3dd9ca69340512e42867b43db689e494bada2000.tar.bz2
crimtag-3dd9ca69340512e42867b43db689e494bada2000.tar.xz
crimtag-3dd9ca69340512e42867b43db689e494bada2000.zip
Symbols have a wrapper with positional data now.
It required some weird changes, I'm not sure I'm happy with them all yet, but I"m getting closer. It parses all basics, now we need to build an AST so it's actually useful :-P
Diffstat (limited to 'src/parser.rs')
-rw-r--r--src/parser.rs56
1 files changed, 34 insertions, 22 deletions
diff --git a/src/parser.rs b/src/parser.rs
index 54b77ac..e5ea1f5 100644
--- a/src/parser.rs
+++ b/src/parser.rs
@@ -6,8 +6,7 @@ use std::fmt;
6 6
7#[derive(Debug)] 7#[derive(Debug)]
8struct ParseError { 8struct ParseError {
9 line: u32, 9 position: Position,
10 row: u32,
11 what: String, 10 what: String,
12} 11}
13 12
@@ -138,15 +137,15 @@ impl Parser {
138 } 137 }
139 138
140 fn lex_error(&self, error: &Symbol) -> Result<(),Box<dyn Error>> { 139 fn lex_error(&self, error: &Symbol) -> Result<(),Box<dyn Error>> {
141 if let Symbol::Error{line,row,what} = error { 140 if let SymbolType::Error{what} = error.symbol() {
142 Err(Box::new(ParseError { 141 Err(Box::new(ParseError {
143 line: *line, 142 position: error.start().clone(),
144 row: *row,
145 what: format!("What: {:?}", *what) 143 what: format!("What: {:?}", *what)
146 })) 144 }))
147 } else { 145 } else {
148 Err(Box::new(ParseError { 146 Err(Box::new(ParseError {
149 line: 0, row: 0, what: "Not an error?".to_string() 147 position: Position::new(0,0),
148 what: "Not an error?".to_string(),
150 })) 149 }))
151 } 150 }
152 } 151 }
@@ -166,12 +165,12 @@ impl Parser {
166 if ctx.cur().is_none() { 165 if ctx.cur().is_none() {
167 break; 166 break;
168 } 167 }
169 match ctx.cur() { 168 match ctx.cur().unwrap().symbol() {
170 Some(Symbol::Text(_)) => { /* Skip top level text */ } 169 SymbolType::Text(_) => { /* Skip top level text */ }
171 Some(Symbol::StartFlat) => { 170 SymbolType::StartFlat => {
172 self.parse_tag( ctx ); 171 self.parse_tag( ctx );
173 } 172 }
174 Some(Symbol::Error{..}) => { 173 SymbolType::Error{..} => {
175 return self.lex_error( &ctx.cur().unwrap() ); 174 return self.lex_error( &ctx.cur().unwrap() );
176 } 175 }
177 _ => { 176 _ => {
@@ -188,10 +187,14 @@ impl Parser {
188 187
189 let start_sym = ctx.cur().unwrap(); 188 let start_sym = ctx.cur().unwrap();
190 189
191 if let Some(Symbol::Token(s)) = ctx.next() { 190 if ctx.next().is_some() {
192 tb.set_name( s.to_string() ); 191 if let SymbolType::Token(s) = ctx.next().unwrap().symbol() {
192 tb.set_name( s.to_string() );
193 } else {
194 return Err(Box::new(ParseError{position: ctx.cur().unwrap().start().clone(), what: "Unexpecetd symbol".to_string()}));
195 }
193 } else { 196 } else {
194 return Err(Box::new(ParseError{line: 0, row: 0, what: "Unexpecetd symbol".to_string()})); 197 return Err(Box::new(ParseError{position: Position::new(0,0), what: "Unexpecetd end of stream".to_string()}));
195 } 198 }
196 199
197 self.parse_tag_params( ctx, &mut tb )?; 200 self.parse_tag_params( ctx, &mut tb )?;
@@ -202,10 +205,15 @@ impl Parser {
202 205
203 fn parse_tag_params(&mut self, ctx: &mut Context, tb: &mut TagBuilder ) -> Result<(), Box<dyn Error>> { 206 fn parse_tag_params(&mut self, ctx: &mut Context, tb: &mut TagBuilder ) -> Result<(), Box<dyn Error>> {
204 loop { 207 loop {
205 if let Some(Symbol::Token(s)) = ctx.cur() { 208 if ctx.cur().is_none() {
206 if matches!(ctx.peek(), Some(Symbol::Equals)) { 209
207 // Done with parameters 210 return Err(Box::new(ParseError{position: Position::new(0,0), what: "Unexpecetd end of stream".to_string()}));
208 break; 211 }
212 if let SymbolType::Token(s) = ctx.cur().unwrap().symbol() {
213 if let Some(p) = ctx.peek() {
214 if p.check_type(|t| matches!(t, SymbolType::Equals)) {
215 break;
216 }
209 } 217 }
210 else { 218 else {
211 tb.add_param( s.to_string() ); 219 tb.add_param( s.to_string() );
@@ -218,16 +226,20 @@ impl Parser {
218 226
219 fn parse_tag_props(&mut self, ctx: &mut Context, tb: &mut TagBuilder ) -> Result<(), Box<dyn Error>> { 227 fn parse_tag_props(&mut self, ctx: &mut Context, tb: &mut TagBuilder ) -> Result<(), Box<dyn Error>> {
220 loop { 228 loop {
221 if let Some(Symbol::Token(s)) = ctx.cur() { 229 if ctx.cur().is_none() {
222 if matches!(ctx.peek(), Some(Symbol::Equals)) { 230 return Err(Box::new(ParseError{position: Position::new(0,0), what: "Unexpecetd end of stream".to_string()}));
231 }
232 if let SymbolType::Token(s) = ctx.cur().unwrap().symbol() {
233 if ctx.peek().is_some_and(|s|s.check_type(|t| matches!(t,SymbolType::Equals))) {
223 ctx.next(); 234 ctx.next();
224 if let Some(Symbol::Literal(lv)) = ctx.next() { 235 if let Some(sym) = ctx.next() &&
236 let SymbolType::Literal(lv) = sym.symbol() {
225 tb.add_prop( s.to_string(), lv.to_string() ); 237 tb.add_prop( s.to_string(), lv.to_string() );
226 } else { 238 } else {
227 return Err(Box::new(ParseError{line: 0, row: 0, what: "Expected quoted literal string".to_string()})); 239 return Err(Box::new(ParseError{position: Position::new(0,0), what: "Expected quoted literal string".to_string()}));
228 } 240 }
229 } else { 241 } else {
230 return Err(Box::new(ParseError{line: 0, row: 0, what: "Expected = ".to_string()})); 242 return Err(Box::new(ParseError{position:Position::new(0,0), what: "Expected = ".to_string()}));
231 } 243 }
232 } else { 244 } else {
233 break; 245 break;