diff --git a/src/error.rs b/src/error.rs index d2b7729..ce87b3c 100644 --- a/src/error.rs +++ b/src/error.rs @@ -54,7 +54,7 @@ impl fmt::Display for Error { if let Some(code) = &self.code { let mut lines = code.lines(); - let linect = match lines.nth(*line) { + let linect = match lines.nth(*line - 1) { Some(l) => l, None => return Ok(()), // there should probably be an error if the line number is somehow out of range }; diff --git a/src/lib.rs b/src/lib.rs index b84ce40..b5fe136 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -196,7 +196,7 @@ impl CodeIter { reader, code: String::new(), pos: 0, - line: 0, + line: 1, column: 0, } } @@ -319,4 +319,4 @@ impl Runtime { ._values(parser.trees(tokenizer.peekable())) .map(|r| r.map_err(|e| e.code(self.code()).file(self.filename.clone()))) } -} +} \ No newline at end of file diff --git a/src/parser.rs b/src/parser.rs index 4e05902..3b39489 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -69,13 +69,13 @@ impl Parser { items.into_iter().fold(self, |acc, (k, v)| acc.add_global(k, v)) } - pub(crate) fn add_local(mut self, k: String, v: Type) -> Self { + pub(crate) fn _add_local(mut self, k: String, v: Type) -> Self { self.locals.insert(k, v); self } - pub(crate) fn add_locals>(self, items: Items) -> Self { - items.fold(self, |acc, (key, value)| acc.add_local(key, value)) + pub(crate) fn _add_locals>(self, items: Items) -> Self { + items.fold(self, |acc, (key, value)| acc._add_local(key, value)) } fn add_local_mut(&mut self, k: String, v: Type) -> &mut Self { diff --git a/src/tokenizer.rs b/src/tokenizer.rs index ad730fb..8d4d446 100644 --- a/src/tokenizer.rs +++ b/src/tokenizer.rs @@ -240,10 +240,15 @@ impl Tokenizer { while let Some(c) = self.next_char() { match c { - '"' => break, + '"' => { + let (line, col) = self.getpos(); + + return Ok(Some(Token::new(TokenType::Constant( + Value::String(token.clone())), token, line, col))); + } '\n' => return Err( Error::new("Unclosed string literal".into()) - .location(line, col..self.getpos().1) + .location(line, col..col+token.len()+1) .note("newlines are not allowed in string literals (try \\n)".into())), '\\' => match self.next_char() { Some('\\') => token.push('\\'), @@ -254,17 +259,16 @@ impl Tokenizer { Some(c) => token.push(c), None => return Err( Error::new("Unclosed string literal".into()) - .location(line, col..self.getpos().1) + .location(line, col..token.len()+1) .note("end of file found before \"".into())), } _ => token.push(c), - } + }; } - let (line, col) = self.getpos(); - - Ok(Some(Token::new(TokenType::Constant( - Value::String(token.clone())), token, line, col))) + Err(Error::new("Unclosed string literal".into()) + .location(line, col..self.getpos().1+1) + .note("end of file found before \"".into())) } else if operators.keys().any(|x| x.starts_with(c)) { let mut token = String::from(c); @@ -349,9 +353,8 @@ impl Tokenizer { } else { let (line, col) = self.getpos(); - return Err( - Error::new(format!("an unidentified character {c} was found")) - .location(line, col - 1..col)); + Err(Error::new(format!("an unidentified character {c} was found")) + .location(line, col..col+1)) } } }