diff --git a/README.md b/README.md index 86ba9b9..7c9cdc3 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,6 @@ # TODO - Fix documentation and variable names - Function application - - Syntax check (parenthesis, argument type) # Eventually - tests diff --git a/src/parser.rs b/src/parser.rs index d4fbb3e..a884239 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -75,6 +75,8 @@ pub struct LineLocation { pub enum ParserError { InvalidChar, MissingCloseParen, + ExtraCloseParen, + EmptyGroup, Syntax, BadNumber } diff --git a/src/parser/tokenize.rs b/src/parser/tokenize.rs index b3f1daa..1b3fea2 100644 --- a/src/parser/tokenize.rs +++ b/src/parser/tokenize.rs @@ -128,6 +128,7 @@ fn push_token( pub fn tokenize(input: &String) -> Result { let mut t: Option = None; // The current token we're reading let mut g: Vec = Vec::with_capacity(8); // Vector of "grouping levels" + let mut i_level = 0; g.push(Token::PreGroup(LineLocation{pos: 0, len: 0}, VecDeque::with_capacity(8))); @@ -229,8 +230,29 @@ pub fn tokenize(input: &String) -> Result { '(' => { push_token(g_now, i, t)?; t = None; g.push(Token::PreGroup(LineLocation{pos: i, len: 0}, VecDeque::with_capacity(8))); + i_level += 1; }, ')' => { + // Catch extra close parens + if i_level == 0 { + return Err(( + LineLocation{pos: i, len: 1}, + ParserError::ExtraCloseParen + )) + } + i_level -= 1; + + // Catch empty groups + if t.is_none() { + let mut last = g.pop().unwrap(); + last = update_line_location(last, i+1); + let Token::PreGroup(l, _) = last else {panic!()}; + return Err(( + l, + ParserError::EmptyGroup + )) + } + push_token(g_now, i, t)?; t = Some(g.pop().unwrap()); },