mirror of
https://github.com/PaddiM8/kalker.git
synced 2025-01-07 14:09:02 +01:00
Made it possible for the parser to parse combined variables, eg. xy
, so that the user does not have to write the multiplication sign.
This commit is contained in:
parent
01aa30c2c1
commit
0dac28bb42
@ -10,16 +10,6 @@ pub struct Context<'a> {
|
||||
|
||||
impl<'a> Context<'a> {
|
||||
pub fn new(angle_unit: Unit, symbol_table: &'a mut SymbolTable) -> Self {
|
||||
for constant in prelude::CONSTANTS {
|
||||
symbol_table.insert(
|
||||
constant.0,
|
||||
Stmt::VarDecl(
|
||||
constant.0.to_string(),
|
||||
Box::new(Expr::Literal(constant.1.to_string())),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Context {
|
||||
angle_unit: angle_unit.clone(),
|
||||
symbol_table,
|
||||
@ -119,6 +109,12 @@ fn eval_unit_expr(context: &mut Context, expr: &Expr, kind: &TokenKind) -> Resul
|
||||
}
|
||||
|
||||
fn eval_var_expr(context: &mut Context, identifier: &str) -> Result<f64, String> {
|
||||
// If there is a constant with this name, return a literal expression with its value
|
||||
if let Some(value) = prelude::CONSTANTS.get(identifier) {
|
||||
return eval_expr(context, &Expr::Literal(value.to_string()));
|
||||
}
|
||||
|
||||
// Look for the variable in the symbol table
|
||||
let var_decl = context.symbol_table.get(identifier).cloned();
|
||||
match var_decl {
|
||||
Some(Stmt::VarDecl(_, expr)) => eval_expr(context, &expr),
|
||||
|
@ -121,15 +121,13 @@ fn parse_factor(context: &mut Context) -> Result<Expr, String> {
|
||||
while match_token(context, TokenKind::Star)
|
||||
|| match_token(context, TokenKind::Slash)
|
||||
|| match_token(context, TokenKind::Identifier)
|
||||
|| match_token(context, TokenKind::Literal)
|
||||
{
|
||||
let mut op = peek(context).kind.clone();
|
||||
|
||||
// If the next token is an identifier, assume it's multiplication. Eg. 3y
|
||||
if let TokenKind::Identifier = op {
|
||||
op = TokenKind::Star;
|
||||
} else {
|
||||
advance(context);
|
||||
}
|
||||
let op = match peek(context).kind {
|
||||
TokenKind::Identifier | TokenKind::Literal => TokenKind::Star,
|
||||
_ => advance(context).kind.clone(),
|
||||
};
|
||||
|
||||
let right = parse_unary(context)?;
|
||||
left = Expr::Binary(Box::new(left), op, Box::new(right));
|
||||
@ -221,7 +219,24 @@ fn parse_identifier(context: &mut Context) -> Result<Expr, String> {
|
||||
}
|
||||
|
||||
// Eg. x
|
||||
Ok(Expr::Var(identifier.value))
|
||||
if context.symbol_table.contains_var(&identifier.value) {
|
||||
return Ok(Expr::Var(identifier.value));
|
||||
} else {
|
||||
let mut chars = identifier.value.chars();
|
||||
let mut left = Expr::Var(chars.next().unwrap().to_string());
|
||||
|
||||
// Turn each individual character into its own variable reference.
|
||||
// This parses eg `xy` as `x*y` instead of *one* variable.
|
||||
for c in chars {
|
||||
left = Expr::Binary(
|
||||
Box::new(left),
|
||||
TokenKind::Star,
|
||||
Box::new(Expr::Var(c.to_string())),
|
||||
);
|
||||
}
|
||||
|
||||
return Ok(left);
|
||||
}
|
||||
}
|
||||
|
||||
fn peek<'a>(context: &'a mut Context) -> &'a Token {
|
||||
|
@ -1,14 +1,14 @@
|
||||
use FuncType::*;
|
||||
|
||||
pub const CONSTANTS: &[(&str, &str)] = &[
|
||||
("pi", "3.14159265"),
|
||||
("π", "3.14159265"),
|
||||
("e", "2.71828182"),
|
||||
("tau", "6.28318530"),
|
||||
("τ", "6.28318530"),
|
||||
("phi", "1.61803398"),
|
||||
("ϕ", "1.61803398"),
|
||||
];
|
||||
pub const CONSTANTS: phf::Map<&'static str, &'static str> = phf::phf_map! {
|
||||
"pi" => "3.14159265",
|
||||
"π" => "3.14159265",
|
||||
"e" => "2.71828182",
|
||||
"tau" => "6.28318530",
|
||||
"τ" => "6.28318530",
|
||||
"phi" => "1.61803398",
|
||||
"ϕ" => "1.61803398",
|
||||
};
|
||||
|
||||
use crate::ast::Unit;
|
||||
use funcs::*;
|
||||
|
@ -20,9 +20,13 @@ impl SymbolTable {
|
||||
self.hashmap.get(key)
|
||||
}
|
||||
|
||||
pub fn contains_func(&self, key: &str) -> bool {
|
||||
prelude::UNARY_FUNCS.contains_key(key)
|
||||
|| prelude::UNARY_FUNCS.contains_key(key)
|
||||
|| self.hashmap.contains_key(&format!("{}()", key))
|
||||
pub fn contains_var(&self, identifier: &str) -> bool {
|
||||
prelude::CONSTANTS.contains_key(identifier) || self.hashmap.contains_key(identifier)
|
||||
}
|
||||
|
||||
pub fn contains_func(&self, identifier: &str) -> bool {
|
||||
prelude::UNARY_FUNCS.contains_key(identifier)
|
||||
|| prelude::UNARY_FUNCS.contains_key(identifier)
|
||||
|| self.hashmap.contains_key(&format!("{}()", identifier))
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user