summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorLaurenz <laurmaedje@gmail.com>2019-04-29 11:24:35 +0200
committerLaurenz <laurmaedje@gmail.com>2019-04-29 11:24:35 +0200
commit383d8365cfd07d7e4c552293a537c519cd2d9c86 (patch)
treee62e1c2658dece9a6d308c0531a22a167afb3185 /src
parent14c9ff571d41e01fe46fb842aa5ea1b93497c4ab (diff)
Refactor function parsing ♻
Diffstat (limited to 'src')
-rw-r--r--src/parsing.rs145
1 files changed, 69 insertions, 76 deletions
diff --git a/src/parsing.rs b/src/parsing.rs
index ebcdeef4..a2a39ee6 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<Item=Token<'s>> {
@@ -251,12 +249,10 @@ impl<'s, T> Parser<'s, T> where T: Iterator<Item=Token<'s>> {
}
/// Parse into an abstract syntax tree.
- pub(crate) fn parse(mut self) -> ParseResult<SyntaxTree> {
+ pub fn parse(mut self) -> ParseResult<SyntaxTree> {
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<Item=Token<'s>> {
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,70 +300,69 @@ impl<'s, T> Parser<'s, T> where T: Iterator<Item=Token<'s>> {
// 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"));
- }
+ Ok(self.tree)
+ }
- // Store the header information of the function invocation.
- let header = FuncHeader {
- name: name.clone(),
- args: vec![],
- kwargs: HashMap::new(),
- };
+ /// 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));
- // 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
- };
+ // 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")),
+ }?;
- // A mutably borrowed view over the tokens.
- let borrow_tokens: BodyTokens<'_> = tokens.as_mut().map(|toks| {
- Box::new(toks) as Box<dyn Iterator<Item=Token<'_>>>
- });
+ // Now the header should be closed.
+ if self.tokens.next() != Some(Token::RightBracket) {
+ return Err(ParseError::new("expected closing bracket"));
+ }
- // 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)));
- };
+ // Store the header information of the function invocation.
+ let header = FuncHeader {
+ name,
+ args: vec![],
+ kwargs: HashMap::new(),
+ };
- // 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"));
- }
- }
+ // Whether the function has a body.
+ let has_body = self.tokens.peek() == Some(&Token::LeftBracket);
+ if has_body {
+ self.advance();
+ }
- // Finally this function is parsed to the end.
- self.append(Node::Func(FuncCall {
- header,
- body,
- }));
+ // 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)))?;
- self.switch(PS::Body);
- },
+ // 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<dyn Iterator<Item=Token<'_>>>;
+ let body = parser(&header, Some(borrowed), &self.scope)?;
+ if func_tokens.unexpected_end {
+ return Err(ParseError::new("expected closing bracket"));
}
- }
- Ok(self.tree)
+ 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.
@@ -380,36 +375,34 @@ impl<'s, T> Parser<'s, T> where T: Iterator<Item=Token<'s>> {
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.