diff options
| -rw-r--r-- | src/lexer.rs | 2 | ||||
| -rw-r--r-- | src/lib.rs | 7 | ||||
| -rw-r--r-- | src/parser.rs | 113 |
3 files changed, 87 insertions, 35 deletions
diff --git a/src/lexer.rs b/src/lexer.rs index 902bb64..4225b32 100644 --- a/src/lexer.rs +++ b/src/lexer.rs | |||
| @@ -229,7 +229,7 @@ impl<'a> Lexer<'a> { | |||
| 229 | } else { | 229 | } else { |
| 230 | Some(Symbol::new( match s { | 230 | Some(Symbol::new( match s { |
| 231 | "fragment" => SymbolType::Fragment, | 231 | "fragment" => SymbolType::Fragment, |
| 232 | "section" => SymbolType::Section, | 232 | "show" => SymbolType::Show, |
| 233 | "output" => SymbolType::Output, | 233 | "output" => SymbolType::Output, |
| 234 | _ => SymbolType::Token(s) | 234 | _ => SymbolType::Token(s) |
| 235 | }, start_pos, end_pos )) | 235 | }, start_pos, end_pos )) |
| @@ -40,10 +40,10 @@ enum FragmentSource { | |||
| 40 | struct Fragment { | 40 | struct Fragment { |
| 41 | name: String, | 41 | name: String, |
| 42 | source: usize, | 42 | source: usize, |
| 43 | sections: HashMap<String, Section>, | 43 | sections: HashMap<String, Output>, |
| 44 | } | 44 | } |
| 45 | 45 | ||
| 46 | struct Section { | 46 | struct Output { |
| 47 | name: String, | 47 | name: String, |
| 48 | ast_root: Token, | 48 | ast_root: Token, |
| 49 | } | 49 | } |
| @@ -53,7 +53,8 @@ type Properties = HashMap<String, String>; | |||
| 53 | enum Token { | 53 | enum Token { |
| 54 | Root(Vec<Token>), | 54 | Root(Vec<Token>), |
| 55 | Fragment(String,Properties,Vec<Token>), | 55 | Fragment(String,Properties,Vec<Token>), |
| 56 | Section(String,Properties,Vec<Token>), | 56 | Output(String,Properties,Vec<Token>), |
| 57 | Show(String,Properties), | ||
| 57 | Text(String), | 58 | Text(String), |
| 58 | Literal(String), | 59 | Literal(String), |
| 59 | /* | 60 | /* |
diff --git a/src/parser.rs b/src/parser.rs index 2d845cd..368a246 100644 --- a/src/parser.rs +++ b/src/parser.rs | |||
| @@ -5,7 +5,7 @@ use core::error::Error; | |||
| 5 | use std::fmt; | 5 | use std::fmt; |
| 6 | 6 | ||
| 7 | #[derive(Debug)] | 7 | #[derive(Debug)] |
| 8 | struct ParseError { | 8 | pub struct ParseError { |
| 9 | position: Position, | 9 | position: Position, |
| 10 | what: String, | 10 | what: String, |
| 11 | } | 11 | } |
| @@ -18,6 +18,8 @@ impl fmt::Display for ParseError { | |||
| 18 | 18 | ||
| 19 | impl Error for ParseError { } | 19 | impl Error for ParseError { } |
| 20 | 20 | ||
| 21 | pub type ParseResult<T> = Result<T, ParseError>; | ||
| 22 | |||
| 21 | struct Context<'a> { | 23 | struct Context<'a> { |
| 22 | cur: [Option<Symbol<'a>>;2], | 24 | cur: [Option<Symbol<'a>>;2], |
| 23 | icur: usize, | 25 | icur: usize, |
| @@ -51,6 +53,19 @@ impl<'a> Context<'a> { | |||
| 51 | } | 53 | } |
| 52 | } | 54 | } |
| 53 | 55 | ||
| 56 | impl Option<Symbol> { | ||
| 57 | pub fn is<T: Fn( &SymbolType ) -> bool>(&self, f: T ) -> ParseError<bool> { | ||
| 58 | if let Some(st) = self { | ||
| 59 | Ok(f( &self.symbol )) | ||
| 60 | } else { | ||
| 61 | Err(ParseError{ | ||
| 62 | position: Position::new(0,0), | ||
| 63 | what: "Unexpeceted end of stream.".to_string() | ||
| 64 | }) | ||
| 65 | } | ||
| 66 | } | ||
| 67 | } | ||
| 68 | |||
| 54 | pub struct Parser { | 69 | pub struct Parser { |
| 55 | } | 70 | } |
| 56 | 71 | ||
| @@ -137,21 +152,21 @@ impl Parser { | |||
| 137 | } | 152 | } |
| 138 | } | 153 | } |
| 139 | 154 | ||
| 140 | fn lex_error(&self, error: &Symbol) -> Result<Token,Box<dyn Error>> { | 155 | fn lex_error(&self, error: &Symbol) -> ParseResult<Token> { |
| 141 | if let SymbolType::Error{what} = error.symbol() { | 156 | if let SymbolType::Error{what} = error.symbol() { |
| 142 | Err(Box::new(ParseError { | 157 | Err(ParseError { |
| 143 | position: error.start().clone(), | 158 | position: error.start().clone(), |
| 144 | what: format!("What: {:?}", *what) | 159 | what: format!("What: {:?}", *what) |
| 145 | })) | 160 | }) |
| 146 | } else { | 161 | } else { |
| 147 | Err(Box::new(ParseError { | 162 | Err(ParseError { |
| 148 | position: Position::new(0,0), | 163 | position: Position::new(0,0), |
| 149 | what: "Not an error?".to_string(), | 164 | what: "Not an error?".to_string(), |
| 150 | })) | 165 | }) |
| 151 | } | 166 | } |
| 152 | } | 167 | } |
| 153 | 168 | ||
| 154 | pub fn parse(&mut self, src: &str ) -> Result<Token,Box<dyn Error>> { | 169 | pub fn parse(&mut self, src: &str ) -> ParseResult<Token> { |
| 155 | let mut ll = Lexer::new( src ); | 170 | let mut ll = Lexer::new( src ); |
| 156 | let mut ctx = Context::new( ll ); | 171 | let mut ctx = Context::new( ll ); |
| 157 | 172 | ||
| @@ -159,7 +174,7 @@ impl Parser { | |||
| 159 | self.p_input( &mut ctx ) | 174 | self.p_input( &mut ctx ) |
| 160 | } | 175 | } |
| 161 | 176 | ||
| 162 | fn p_input(&mut self, ctx: &mut Context ) -> Result<Token, Box<dyn Error>> { | 177 | fn p_input(&mut self, ctx: &mut Context ) -> ParseResult<Token> { |
| 163 | let mut children = Vec::new(); | 178 | let mut children = Vec::new(); |
| 164 | loop { | 179 | loop { |
| 165 | if ctx.cur().is_none() { | 180 | if ctx.cur().is_none() { |
| @@ -182,7 +197,7 @@ impl Parser { | |||
| 182 | Ok(Token::Root(children)) | 197 | Ok(Token::Root(children)) |
| 183 | } | 198 | } |
| 184 | 199 | ||
| 185 | fn parse_tag(&mut self, ctx: &mut Context) -> Result<Token, Box<dyn Error>> { | 200 | fn parse_tag(&mut self, ctx: &mut Context) -> ParseResult<TagBuilder> { |
| 186 | let mut tb = TagBuilder::new(); | 201 | let mut tb = TagBuilder::new(); |
| 187 | 202 | ||
| 188 | println!("--> Begin parse_tag <--"); | 203 | println!("--> Begin parse_tag <--"); |
| @@ -193,28 +208,23 @@ impl Parser { | |||
| 193 | 208 | ||
| 194 | if ctx.next().is_some() { | 209 | if ctx.next().is_some() { |
| 195 | match ctx.cur().unwrap().symbol() { | 210 | match ctx.cur().unwrap().symbol() { |
| 196 | SymbolType::Fragment | SymbolType::Section | | 211 | SymbolType::Fragment | SymbolType::Show | |
| 197 | SymbolType::Output => { | 212 | SymbolType::Output => { |
| 198 | let name_sym = ctx.cur().unwrap(); | 213 | let name_sym = ctx.cur().unwrap(); |
| 199 | ctx.next(); | 214 | ctx.next(); |
| 200 | tb.set_name( name_sym ); | 215 | tb.set_name( name_sym ); |
| 201 | } | 216 | } |
| 202 | _ => { | 217 | _ => { |
| 203 | return Err(Box::new(ParseError{position: ctx.cur().unwrap().start().clone(), what: "Unexpecetd symbol".to_string()})); | 218 | return Err(ParseError{position: ctx.cur().unwrap().start().clone(), what: "Unexpecetd symbol".to_string()}); |
| 204 | } | 219 | } |
| 205 | } | 220 | } |
| 206 | } else { | 221 | } else { |
| 207 | return Err(Box::new(ParseError{position: Position::new(0,0), what: "Unexpecetd end of stream".to_string()})); | 222 | return Err(ParseError{position: Position::new(0,0), what: "Unexpecetd end of stream".to_string()}); |
| 208 | } | 223 | } |
| 209 | 224 | ||
| 210 | println!("--> Begin parse_tag_params <--"); | ||
| 211 | self.parse_tag_params( ctx, &mut tb )?; | 225 | self.parse_tag_params( ctx, &mut tb )?; |
| 212 | println!("--> End parse_tag_params <--"); | ||
| 213 | println!("--> Begin parse_tag_props <--"); | ||
| 214 | self.parse_tag_props( ctx, &mut tb )?; | 226 | self.parse_tag_props( ctx, &mut tb )?; |
| 215 | println!("--> End parse_tag_props <--"); | ||
| 216 | 227 | ||
| 217 | println!("---> {:?}", ctx.cur() ); | ||
| 218 | if let Some(end_sym) = ctx.cur() { | 228 | if let Some(end_sym) = ctx.cur() { |
| 219 | match end_sym.symbol() { | 229 | match end_sym.symbol() { |
| 220 | SymbolType::EndPoint => { | 230 | SymbolType::EndPoint => { |
| @@ -224,19 +234,57 @@ impl Parser { | |||
| 224 | tb.set_type( TagType::Unary ); | 234 | tb.set_type( TagType::Unary ); |
| 225 | } | 235 | } |
| 226 | _ => { | 236 | _ => { |
| 227 | return Err(Box::new(ParseError{position: Position::new(0,0), what: "Unexpecetd end of stream".to_string()})); | 237 | return Err(ParseError{position: Position::new(0,0), what: "Unexpecetd end of stream".to_string()}); |
| 228 | } | 238 | } |
| 229 | } | 239 | } |
| 230 | } | 240 | } |
| 231 | 241 | ||
| 232 | tb.build() | 242 | Ok(tb) |
| 233 | } | 243 | } |
| 234 | 244 | ||
| 235 | fn parse_tag_params(&mut self, ctx: &mut Context, tb: &mut TagBuilder ) -> Result<(), Box<dyn Error>> { | 245 | fn parse_end_tag(&mut self, ctx: &mut Context ) -> &'a str { |
| 246 | if !ctx.cur().is(|s| matches!(s, Symbol::StartPoint))? { | ||
| 247 | return Err(ParseError{ | ||
| 248 | position: ctx.cur(). | ||
| 249 | }); | ||
| 250 | } | ||
| 251 | ctx.next() | ||
| 252 | } | ||
| 253 | |||
| 254 | fn parse_tag_body(&mut self, ctx: &mut Context, tb: &mut TagBuilder ) -> ParseResult<()> { | ||
| 236 | loop { | 255 | loop { |
| 237 | if ctx.cur().is_none() { | 256 | if ctx.cur().is_none() { |
| 257 | return Err(ParseError{position: Position::new(0,0), what: "Unexpecetd end of stream".to_string()}); | ||
| 258 | } | ||
| 259 | match ctx.cur().unwrap().symbol() { | ||
| 260 | SymbolType::Text(s) => { | ||
| 261 | tb.add_child(Token:: Text(s.to_string())); | ||
| 262 | } | ||
| 263 | SymbolType::StartFlat => { | ||
| 264 | tb.add_child( self.parse_tag( ctx )? ); | ||
| 265 | } | ||
| 266 | SymbolType::StartPoint => { | ||
| 267 | let end_tag = self.parse_end_tag( ctx )?; | ||
| 238 | 268 | ||
| 239 | return Err(Box::new(ParseError{position: Position::new(0,0), what: "Unexpecetd end of stream".to_string()})); | 269 | } |
| 270 | SymbolType::Error{..} => { | ||
| 271 | return self.lex_error( &ctx.cur().unwrap() ); | ||
| 272 | } | ||
| 273 | _ => { | ||
| 274 | |||
| 275 | } | ||
| 276 | } | ||
| 277 | ctx.next(); | ||
| 278 | } | ||
| 279 | Ok(Token::Root(children)) | ||
| 280 | Ok(()) | ||
| 281 | } | ||
| 282 | |||
| 283 | fn parse_tag_params(&mut self, ctx: &mut Context, tb: &mut TagBuilder ) -> ParseResult<()> { | ||
| 284 | loop { | ||
| 285 | if ctx.cur().is_none() { | ||
| 286 | |||
| 287 | return Err(ParseError{position: Position::new(0,0), what: "Unexpecetd end of stream".to_string()}); | ||
| 240 | } | 288 | } |
| 241 | match ctx.cur().unwrap().symbol() { | 289 | match ctx.cur().unwrap().symbol() { |
| 242 | SymbolType::Literal(s) => { | 290 | SymbolType::Literal(s) => { |
| @@ -251,10 +299,10 @@ impl Parser { | |||
| 251 | Ok(()) | 299 | Ok(()) |
| 252 | } | 300 | } |
| 253 | 301 | ||
| 254 | fn parse_tag_props(&mut self, ctx: &mut Context, tb: &mut TagBuilder ) -> Result<(), Box<dyn Error>> { | 302 | fn parse_tag_props(&mut self, ctx: &mut Context, tb: &mut TagBuilder ) -> ParseResult<()> { |
| 255 | loop { | 303 | loop { |
| 256 | if ctx.cur().is_none() { | 304 | if ctx.cur().is_none() { |
| 257 | return Err(Box::new(ParseError{position: Position::new(0,0), what: "Unexpecetd end of stream".to_string()})); | 305 | return Err(ParseError{position: Position::new(0,0), what: "Unexpecetd end of stream".to_string()}); |
| 258 | } | 306 | } |
| 259 | if let SymbolType::Token(s) = ctx.cur().unwrap().symbol() { | 307 | if let SymbolType::Token(s) = ctx.cur().unwrap().symbol() { |
| 260 | if ctx.peek().is_some_and(|s|s.check_type(|t| matches!(t,SymbolType::Equals))) { | 308 | if ctx.peek().is_some_and(|s|s.check_type(|t| matches!(t,SymbolType::Equals))) { |
| @@ -263,10 +311,10 @@ impl Parser { | |||
| 263 | let SymbolType::Literal(lv) = sym.symbol() { | 311 | let SymbolType::Literal(lv) = sym.symbol() { |
| 264 | tb.add_prop( s.to_string(), lv.to_string() ); | 312 | tb.add_prop( s.to_string(), lv.to_string() ); |
| 265 | } else { | 313 | } else { |
| 266 | return Err(Box::new(ParseError{position: Position::new(0,0), what: "Expected quoted literal string".to_string()})); | 314 | return Err(ParseError{position: Position::new(0,0), what: "Expected quoted literal string".to_string()}); |
| 267 | } | 315 | } |
| 268 | } else { | 316 | } else { |
| 269 | return Err(Box::new(ParseError{position:Position::new(0,0), what: "Expected = ".to_string()})); | 317 | return Err(ParseError{position:Position::new(0,0), what: "Expected = ".to_string()}); |
| 270 | } | 318 | } |
| 271 | } else { | 319 | } else { |
| 272 | break; | 320 | break; |
| @@ -343,28 +391,31 @@ impl<'a> TagBuilder<'a> { | |||
| 343 | self.tag_type = tag_type; | 391 | self.tag_type = tag_type; |
| 344 | } | 392 | } |
| 345 | 393 | ||
| 346 | pub fn build(mut self) -> Result<Token,Box<dyn Error>> { | 394 | pub fn build(mut self) -> ParseResult<Token> { |
| 347 | if let Some(sym) = self.name { | 395 | if let Some(sym) = self.name { |
| 348 | match sym.symbol() { | 396 | match sym.symbol() { |
| 349 | SymbolType::Fragment => { | 397 | SymbolType::Fragment => { |
| 350 | Ok(Token::Fragment(self.params.swap_remove(0), self.props, self.children)) | 398 | Ok(Token::Fragment(self.params.swap_remove(0), self.props, self.children)) |
| 351 | } | 399 | } |
| 352 | SymbolType::Output => { | 400 | SymbolType::Output => { |
| 353 | Ok(Token::Section(self.params.swap_remove(0), self.props, self.children)) | 401 | Ok(Token::Output(self.params.swap_remove(0), self.props, self.children)) |
| 402 | } | ||
| 403 | SymbolType::Show => { | ||
| 404 | Ok(Token::Show(self.params.swap_remove(0), self.props)) | ||
| 354 | } | 405 | } |
| 355 | _ => { | 406 | _ => { |
| 356 | println!("Unkown tag type"); | 407 | println!("Unkown tag type"); |
| 357 | Err(Box::new(ParseError { | 408 | Err(ParseError { |
| 358 | position: Position::new(0,0), | 409 | position: Position::new(0,0), |
| 359 | what: "Bad tag type".to_string(), | 410 | what: "Bad tag type".to_string(), |
| 360 | })) | 411 | }) |
| 361 | } | 412 | } |
| 362 | } | 413 | } |
| 363 | } else { | 414 | } else { |
| 364 | Err(Box::new(ParseError { | 415 | Err(ParseError { |
| 365 | position: Position::new(0,0), | 416 | position: Position::new(0,0), |
| 366 | what: "Bad tag type".to_string(), | 417 | what: "Bad tag type".to_string(), |
| 367 | })) | 418 | }) |
| 368 | } | 419 | } |
| 369 | } | 420 | } |
| 370 | } | 421 | } |
