diff options
Diffstat (limited to 'src/parser.rs')
-rw-r--r-- | src/parser.rs | 103 |
1 files changed, 59 insertions, 44 deletions
diff --git a/src/parser.rs b/src/parser.rs index 8058aeb..973d0b2 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,24 +1,28 @@ use crate::error::SiteError; -use crate::token::{Token, TokenParser, TokenPatterns}; +use crate::token::{TokenKind, TokenParser, TokenPatterns}; use crate::wikitext::{ParsedDirective, Snippet, WikiLink}; -use log::trace; +use line_col::LineColLookup; +use log::{debug, trace}; use std::collections::HashMap; #[derive(Debug)] pub struct WikitextParser { - tokens: Vec<Token>, + tokens: Vec<(TokenKind, usize, usize)>, } impl WikitextParser { pub fn new(input: &str, patterns: &TokenPatterns) -> Self { + let linecol = LineColLookup::new(input); let mut p = TokenParser::new(input, patterns); let mut tokens = vec![]; loop { let token = p.parse(); - if token == Token::End { + debug!("token {:?}", token); + if token.token == TokenKind::End { break; } - tokens.push(token); + let (line, col) = linecol.get(token.pos); + tokens.push((token.token, line, col)); } Self { tokens } @@ -29,58 +33,67 @@ impl WikitextParser { return Ok(None); } + let (_, line, col) = self.tokens[0]; + debug!("token at {}:{}", line, col); let snippet = match &self.tokens[..] { - [Token::OpenBrackets, Token::Word(target), Token::CloseBrackets, ..] => { + [(TokenKind::OpenBrackets, _, _), (TokenKind::Word(target), _, _), (TokenKind::CloseBrackets, _, _), ..] => { let wikilink = WikiLink::new(target, target); let snippet = Snippet::WikiLink(wikilink); self.tokens.drain(..3); snippet } - [Token::OpenBrackets, Token::Word(word), ..] => { + [(TokenKind::OpenBrackets, _, _), (TokenKind::Word(word), _, _), ..] => { trace!("match [[{:?}", word); let mut link_text = word.to_string(); let mut target = None; self.tokens.drain(..2); loop { + let (_, line, col) = self.tokens[0]; match &self.tokens[..] { - [Token::Spaces(_), ..] => { + [(TokenKind::Spaces(_), _, _), ..] => { trace!("match space"); self.tokens.drain(..1); link_text.push(' '); } - [Token::Markdown(s), ..] => { + [(TokenKind::Markdown(s), _, _), ..] => { trace!("match markdown {:?}", s); link_text.push_str(s); self.tokens.drain(..1); } - [Token::OpenParens, Token::Word(word), ..] => { + [(TokenKind::OpenParens, _, _), (TokenKind::Word(word), _, _), ..] => { trace!("match ({:?}", word); link_text.push('('); link_text.push_str(word); self.tokens.drain(..2); } - [Token::Word(word), ..] => { + [(TokenKind::Word(word), _, _), ..] => { trace!("match {:?}", word); link_text.push_str(word); self.tokens.drain(..1); } - [Token::ClosedParens, ..] => { + [(TokenKind::ClosedParens, _, _), ..] => { trace!("match )"); link_text.push(')'); self.tokens.drain(..1); } - [Token::CloseBrackets, ..] => { + [(TokenKind::CloseBrackets, _, _), ..] => { trace!("match ]]"); self.tokens.drain(..1); break; } - [Token::Pipe, Token::Word(word), Token::CloseBrackets, ..] => { + [(TokenKind::Pipe, _, _), (TokenKind::Word(word), _, _), (TokenKind::CloseBrackets, _, _), ..] => { trace!("match |{:?}]]", word); target = Some(word.to_string()); self.tokens.drain(..3); break; } - _ => panic!("can't parse: {:?}", &self.tokens[..5]), + [(TokenKind::Pipe, _, _), (TokenKind::Spaces(_), _, _), (TokenKind::Word(word), _, _), (TokenKind::CloseBrackets, _, _), ..] => { + trace!("match |{:?}]]", word); + target = Some(word.to_string()); + self.tokens.drain(..3); + break; + } + _ => panic!("a can't parse line {} column {}: {:?}", line, col, &self.tokens[..5]), } } if target.is_none() { @@ -89,141 +102,143 @@ impl WikitextParser { let wikilink = WikiLink::new(&link_text, &target.unwrap()); Snippet::WikiLink(wikilink) } - [Token::OpenBrackets, Token::Bang, Token::Word(name), ..] => { + [(TokenKind::OpenBrackets, _, _), (TokenKind::Bang, _, _), (TokenKind::Word(name), _, _), ..] => { trace!("match [[!{:?}", name); let name = name.to_string(); let mut args = HashMap::new(); self.tokens.drain(..3); loop { + let (_, line, col) = self.tokens[0]; match &self.tokens[..] { - [Token::Spaces(_), ..] => { + [(TokenKind::Spaces(_), _, _), ..] => { trace!("match spaces"); self.tokens.drain(..1); } - [Token::CloseBrackets, ..] => { + [(TokenKind::CloseBrackets, _, _), ..] => { trace!("match ]]"); self.tokens.drain(..1); break; } - [Token::Word(word), Token::Spaces(_), ..] => { + [(TokenKind::Word(word), _, _), (TokenKind::Spaces(_), _, _), ..] => { trace!("match {:?} spaces", word); args.insert(word.to_string(), "".to_string()); self.tokens.drain(..2); } - [Token::Word(word), Token::CloseBrackets, ..] => { + [(TokenKind::Word(word), _, _), (TokenKind::CloseBrackets, _, _), ..] => { trace!("match {:?}]]", word); args.insert(word.to_string(), "".to_string()); self.tokens.drain(..2); break; } - [Token::Word(name), Token::Equals, Token::Word(value), ..] => { + [(TokenKind::Word(name), _, _), (TokenKind::Equals, _, _), (TokenKind::Word(value), _, _), ..] => { trace!("match {:?}={:?}", name, value); args.insert(name.to_string(), value.to_string()); self.tokens.drain(..3); } - [Token::Word(name), Token::Equals, Token::QuotedValue(value), ..] => { + [(TokenKind::Word(name), _, _), (TokenKind::Equals, _, _), (TokenKind::QuotedValue(value), _, _), ..] => { trace!("match {:?}={:?}", name, value); args.insert(name.to_string(), value.to_string()); self.tokens.drain(..3); } - [Token::QuotedValue(value), ..] => { + [(TokenKind::QuotedValue(value), _, _), ..] => { trace!("match {:?}", value); args.insert(value.to_string(), "".to_string()); self.tokens.drain(..1); } - _ => panic!("can't parse: {:?}", &self.tokens[..5]), + _ => panic!("b can't parse line {} column {}: {:?}", line, col, &self.tokens[..5]), } } Snippet::Directive(ParsedDirective::new(&name, args)?) } - [Token::Bang, Token::OpenBracket, ..] => { + [(TokenKind::Bang, _, _), (TokenKind::OpenBracket, _, _), ..] => { let mut link_text = String::new(); #[allow(unused_assignments)] let mut target = None; self.tokens.drain(..2); loop { + let (_, line, col) = self.tokens[0]; match &self.tokens[..] { - [Token::Word(word), ..] => { + [(TokenKind::Word(word), _, _), ..] => { link_text.push_str(word); self.tokens.drain(..1); } - [Token::Spaces(_), ..] => { + [(TokenKind::Spaces(_), _, _), ..] => { link_text.push(' '); self.tokens.drain(..1); } - [Token::ClosedBracket, Token::OpenParens, Token::Word(word), Token::ClosedParens, ..] => + [(TokenKind::ClosedBracket, _, _), (TokenKind::OpenParens, _, _), (TokenKind::Word(word), _, _), (TokenKind::ClosedParens, _, _), ..] => { target = Some(word.to_string()); self.tokens.drain(..4); break; } - _ => panic!("can't parse: {:?}", &self.tokens[..5]), + _ => panic!("c can't parse line {} column {}: {:?}", line, col, &self.tokens[..5]), } } Snippet::Markdown(format!("![{}]({})", link_text, target.unwrap())) } - [Token::Markdown(text), ..] => { + [(TokenKind::Markdown(text), _, _), ..] => { let snippet = Snippet::Markdown(text.to_string()); self.tokens.drain(..1); snippet } - [Token::Spaces(s), ..] => { + [(TokenKind::Spaces(s), _, _), ..] => { let snippet = Snippet::Markdown(s.to_string()); self.tokens.drain(..1); snippet } - [Token::Word(text), ..] => { + [(TokenKind::Word(text), _, _), ..] => { let snippet = Snippet::Markdown(text.to_string()); self.tokens.drain(..1); snippet } - [Token::Equals, ..] => { + [(TokenKind::Equals, _, _), ..] => { self.tokens.drain(..1); Snippet::Markdown("=".into()) } - [Token::Bang, ..] => { + [(TokenKind::Bang, _, _), ..] => { self.tokens.drain(..1); Snippet::Markdown("!".into()) } - [Token::Pipe, ..] => { + [(TokenKind::Pipe, _, _), ..] => { self.tokens.drain(..1); Snippet::Markdown("|".into()) } - [Token::PageName(s), ..] => { + [(TokenKind::PageName(s), _, _), ..] => { let snippet = Snippet::Markdown(s.to_string()); self.tokens.drain(..1); snippet } - [Token::QuotedValue(s), ..] => { + [(TokenKind::QuotedValue(s), _, _), ..] => { let snippet = Snippet::Markdown(format!("\"{}\"", s)); self.tokens.drain(..1); snippet } - [Token::OpenParens, ..] => { + [(TokenKind::OpenParens, _, _), ..] => { self.tokens.drain(..1); Snippet::Markdown("(".into()) } - [Token::ClosedParens, ..] => { + [(TokenKind::ClosedParens, _, _), ..] => { self.tokens.drain(..1); Snippet::Markdown(")".into()) } - [Token::OpenBracket, ..] => { + [(TokenKind::OpenBracket, _, _), ..] => { self.tokens.drain(..1); Snippet::Markdown("[".into()) } - [Token::ClosedBracket, ..] => { + [(TokenKind::ClosedBracket, _, _), ..] => { self.tokens.drain(..1); Snippet::Markdown("]".into()) } - [Token::OpenBrackets, ..] => { + [(TokenKind::OpenBrackets, _, _), ..] => { self.tokens.drain(..1); Snippet::Markdown("[[".into()) } - [Token::CloseBrackets, ..] => { + [(TokenKind::CloseBrackets, _, _), ..] => { self.tokens.drain(..1); Snippet::Markdown("]]".into()) } - _ => panic!("eeek: {:?}", self.tokens), + _ => panic!("d can't parse line {} column {}: {:?}", line, col, self.tokens), }; Ok(Some(snippet)) } |