diff --git a/src/parsing.rs b/src/parsing.rs index ebcdeef42..a2a39ee6d 100644 --- a/src/parsing.rs +++ b/src/parsing.rs @@ -7,7 +7,7 @@ use std::mem::swap; use std::ops::Deref; use crate::syntax::*; -use crate::func::{Scope, BodyTokens}; +use crate::func::Scope; use crate::utility::{Splinor, Spline, Splined, StrExt}; use unicode_segmentation::{UnicodeSegmentation, UWordBounds}; @@ -225,8 +225,6 @@ enum ParserState { FirstNewline, /// We wrote a newline. WroteNewline, - /// Inside a function header. - Function, } impl<'s, T> Parser<'s, T> where T: Iterator> { @@ -251,12 +249,10 @@ impl<'s, T> Parser<'s, T> where T: Iterator> { } /// Parse into an abstract syntax tree. - pub(crate) fn parse(mut self) -> ParseResult { + pub fn parse(mut self) -> ParseResult { use ParserState as PS; - while let Some(token) = self.tokens.peek() { - let token = *token; - + while let Some(&token) = self.tokens.peek() { // Skip over comments. if token == Token::Hashtag { self.skip_while(|&t| t != Token::Newline); @@ -291,7 +287,7 @@ impl<'s, T> Parser<'s, T> where T: Iterator> { Token::Word(word) => self.append_consumed(Node::Word(word.to_owned())), // Functions - Token::LeftBracket => self.switch_consumed(PS::Function), + Token::LeftBracket => self.parse_function()?, Token::RightBracket => { return Err(ParseError::new("unexpected closing bracket")); }, @@ -304,72 +300,71 @@ impl<'s, T> Parser<'s, T> where T: Iterator> { // Should not happen Token::Colon | Token::Equals | Token::Hashtag => unreachable!(), }, - - PS::Function => { - let name = if let Token::Word(word) = token { - match Ident::new(word) { - Some(ident) => ident, - None => return Err(ParseError::new("invalid identifier")), - } - } else { - return Err(ParseError::new("expected identifier")); - }; - self.advance(); - - // Expect the header closing bracket. - if self.tokens.next() != Some(Token::RightBracket) { - return Err(ParseError::new("expected closing bracket")); - } - - // Store the header information of the function invocation. - let header = FuncHeader { - name: name.clone(), - args: vec![], - kwargs: HashMap::new(), - }; - - // This function has a body. - let mut tokens = if let Some(Token::LeftBracket) = self.tokens.peek() { - self.advance(); - Some(FuncTokens::new(&mut self.tokens)) - } else { - None - }; - - // A mutably borrowed view over the tokens. - let borrow_tokens: BodyTokens<'_> = tokens.as_mut().map(|toks| { - Box::new(toks) as Box>> - }); - - // Run the parser over the tokens. - let body = if let Some(parser) = self.scope.get_parser(&name) { - parser(&header, borrow_tokens, &self.scope)? - } else { - return Err(ParseError::new(format!("unknown function: '{}'", &name))); - }; - - // Expect the closing bracket if it had a body. - if let Some(tokens) = tokens { - if tokens.unexpected_end { - return Err(ParseError::new("expected closing bracket")); - } - } - - // Finally this function is parsed to the end. - self.append(Node::Func(FuncCall { - header, - body, - })); - - self.switch(PS::Body); - }, - } } Ok(self.tree) } + /// Parse a function from the current position. + fn parse_function(&mut self) -> ParseResult<()> { + // This should only be called if a left bracket was seen. + debug_assert!(self.tokens.next() == Some(Token::LeftBracket)); + + // The next token should be the name of the function. + let name = match self.tokens.next() { + Some(Token::Word(word)) => { + Ident::new(word).ok_or_else(|| ParseError::new("invalid identifier")) + }, + _ => Err(ParseError::new("expected identifier")), + }?; + + // Now the header should be closed. + if self.tokens.next() != Some(Token::RightBracket) { + return Err(ParseError::new("expected closing bracket")); + } + + // Store the header information of the function invocation. + let header = FuncHeader { + name, + args: vec![], + kwargs: HashMap::new(), + }; + + // Whether the function has a body. + let has_body = self.tokens.peek() == Some(&Token::LeftBracket); + if has_body { + self.advance(); + } + + // Now we want to parse this function dynamically. + let parser = self.scope.get_parser(&header.name) + .ok_or_else(|| ParseError::new(format!("unknown function: '{}'", &header.name)))?; + + // Do the parsing dependend on whether the function has a body. + let body = if has_body { + let mut func_tokens = FuncTokens::new(&mut self.tokens); + let borrowed = Box::new(&mut func_tokens) as Box>>; + + let body = parser(&header, Some(borrowed), &self.scope)?; + if func_tokens.unexpected_end { + return Err(ParseError::new("expected closing bracket")); + } + + body + } else { + parser(&header, None, &self.scope)? + }; + + // Finally this function is parsed to the end. + self.append(Node::Func(FuncCall { + header, + body, + })); + + Ok(self.switch(ParserState::Body)) + } + /// Advance the iterator by one step. fn advance(&mut self) { self.tokens.next(); @@ -380,36 +375,34 @@ impl<'s, T> Parser<'s, T> where T: Iterator> { self.tree.nodes.push(node); } - /// Advance and return the given node. - fn append_consumed(&mut self, node: Node) { self.advance(); self.append(node); } - /// Append a space if there is not one already. fn append_space(&mut self) { - if self.last() != Some(&Node::Space) { + if self.tree.nodes.last() != Some(&Node::Space) { self.append(Node::Space); } } + /// Switch the state. + fn switch(&mut self, state: ParserState) { + self.state = state; + } + + /// Advance and return the given node. + fn append_consumed(&mut self, node: Node) { + self.advance(); + self.append(node); + } + /// Advance and append a space if there is not one already. fn append_space_consumed(&mut self) { self.advance(); self.append_space(); } - /// Switch the state. - fn switch(&mut self, state: ParserState) { - self.state = state; - } - /// Advance and switch the state. fn switch_consumed(&mut self, state: ParserState) { self.advance(); - self.state = state; - } - - /// The last appended node of the tree. - fn last(&self) -> Option<&Node> { - self.tree.nodes.last() + self.switch(state); } /// Skip tokens until the condition is met.