Skip to content

Commit

Permalink
list expected and found variables
Browse files Browse the repository at this point in the history
  • Loading branch information
vic1707 committed Oct 6, 2023
1 parent acdd955 commit 60e9c24
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 5 deletions.
3 changes: 2 additions & 1 deletion src/context.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* Built-in imports */
use std::collections::HashMap;
use std::collections::{HashMap, HashSet};
/* Crate imports */
use crate::utils::Function;

Expand All @@ -8,4 +8,5 @@ use crate::utils::Function;
pub struct Context {
pub vars: HashMap<String, f64>,
pub funcs: HashMap<String, Function>,
pub expected_vars: Option<HashSet<String>>,
}
45 changes: 41 additions & 4 deletions src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#![allow(clippy::std_instead_of_core)]
/* Built-in imports */
use core::str;
use std::collections::HashSet;
/* Crate imports */
use crate::{
context::Context,
Expand Down Expand Up @@ -42,35 +43,57 @@ impl Parser {

#[inline]
pub fn parse<'a>(&'a self, input: &'a str) -> Result<Xprs<'a>, Error> {
ParserImpl::parse(input, &self.ctx)
let xprs = ParserImpl::parse(input, &self.ctx)?;

// Check if no unknown variable was found
// Double `if-let` better than `.as_ref().and_then(...)`?
#[allow(clippy::ref_patterns)]
if let Some(ref expected) = self.ctx.expected_vars {
if let Some(unknown_var) =
xprs.found_vars.difference(expected).next()
{
yeet!(Error::new_variable_not_declared(
&ParserImpl::new(input, &self.ctx),
unknown_var.clone(),
))
}
}

Ok(xprs)
}
}

struct ParserImpl<'a> {
input: &'a [u8],
cursor: usize,
ctx: &'a Context,
found_vars: HashSet<String>,
}

impl<'a> ParserImpl<'a> {
#[inline]
#[must_use]
const fn new(input: &'a str, ctx: &'a Context) -> Self {
fn new(input: &'a str, ctx: &'a Context) -> Self {
Self {
input: input.as_bytes(),
cursor: 0,
ctx,
found_vars: HashSet::new(),
}
}
#[inline]
pub fn parse(input: &'a str, ctx: &'a Context) -> Result<Xprs<'a>, Error> {
let mut parser_impl = Self::new(input, ctx);

let root = parser_impl.element(NO_PERCEDENCE)?;

if let Some(&tok) = parser_impl.next() {
yeet!(Error::new_unexpected_token(&parser_impl, tok));
}
Ok(Xprs { root })
Ok(Xprs {
root,
found_vars: parser_impl.found_vars,
})
}

fn element(&mut self, precedence: usize) -> Result<Element<'a>, Error> {
Expand Down Expand Up @@ -148,7 +171,10 @@ impl<'a> ParserImpl<'a> {

let el = match ident {
Identifier::Constant(val) => Element::Number(val),
Identifier::Variable(var) => Element::Variable(var),
Identifier::Variable(var) => {
self.found_vars.insert(var.to_owned());
Element::Variable(var)
},
Identifier::Function(func) if Some(&b'(') == self.next() => {
let el = self.element(precedence::FN_PRECEDENCE)?;
Element::Function(Box::new(FunctionCall::new(func, el)))
Expand All @@ -157,6 +183,7 @@ impl<'a> ParserImpl<'a> {
yeet!(Error::new_expected_token(self, b'('))
},
};

Ok(el)
}

Expand Down Expand Up @@ -262,6 +289,8 @@ pub enum ErrorKind {
IllegalCharacter(char),
#[error("Expected token: `{0}`")]
ExpectedToken(char),
#[error("Variable not previously declared: `{0}`")]
VariableNotDeclared(String),
}

impl Error {
Expand Down Expand Up @@ -307,4 +336,12 @@ impl Error {
src: trust_me!(str::from_utf8_unchecked(parser.input)).to_owned(),
}
}

fn new_variable_not_declared(parser: &ParserImpl, var: String) -> Self {
Self {
kind: ErrorKind::VariableNotDeclared(var),
span: (0, parser.input.len()).into(),
src: trust_me!(str::from_utf8_unchecked(parser.input)).to_owned(),
}
}
}
2 changes: 2 additions & 0 deletions src/xprs.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
/* Build-it imports */
use core::fmt;
use std::collections::HashSet;
/* Crate imports */
use crate::element::Element;

#[derive(Debug, PartialEq)]
#[non_exhaustive]
pub struct Xprs<'a> {
pub root: Element<'a>,
pub found_vars: HashSet<String>,
}

impl fmt::Display for Xprs<'_> {
Expand Down

0 comments on commit 60e9c24

Please sign in to comment.