Allow multiplication with parenthesis without star symbol

This commit is contained in:
PaddiM8 2020-12-13 23:16:47 +01:00
parent 4f02a0f0a3
commit 483e82fb03

View File

@ -30,6 +30,7 @@ pub struct Context {
/// When a unit declaration is being parsed, this value will be set /// When a unit declaration is being parsed, this value will be set
/// whenever a unit in the expression is found. Eg. unit a = 3b, it will be set to Some("b") /// whenever a unit in the expression is found. Eg. unit a = 3b, it will be set to Some("b")
unit_decl_base_unit: Option<String>, unit_decl_base_unit: Option<String>,
parsing_identifier_stmt: bool,
} }
impl Context { impl Context {
@ -41,6 +42,7 @@ impl Context {
angle_unit: DEFAULT_ANGLE_UNIT.into(), angle_unit: DEFAULT_ANGLE_UNIT.into(),
parsing_unit_decl: false, parsing_unit_decl: false,
unit_decl_base_unit: None, unit_decl_base_unit: None,
parsing_identifier_stmt: false,
}; };
parse(&mut context, crate::prelude::INIT).unwrap(); parse(&mut context, crate::prelude::INIT).unwrap();
@ -128,7 +130,9 @@ fn parse_stmt(context: &mut Context) -> Result<Stmt, CalcError> {
fn parse_identifier_stmt(context: &mut Context) -> Result<Stmt, CalcError> { fn parse_identifier_stmt(context: &mut Context) -> Result<Stmt, CalcError> {
let began_at = context.pos; let began_at = context.pos;
context.parsing_identifier_stmt = true;
let primary = parse_primary(context)?; // Since function declarations and function calls look the same at first, simply parse a "function call", and re-use the data. let primary = parse_primary(context)?; // Since function declarations and function calls look the same at first, simply parse a "function call", and re-use the data.
context.parsing_identifier_stmt = false;
// If `primary` is followed by an equal sign, it is a function declaration. // If `primary` is followed by an equal sign, it is a function declaration.
if let TokenKind::Equals = peek(context).kind { if let TokenKind::Equals = peek(context).kind {
@ -159,7 +163,7 @@ fn parse_identifier_stmt(context: &mut Context) -> Result<Stmt, CalcError> {
Err(CalcError::Unknown) Err(CalcError::Unknown)
} else { } else {
// It is a function call, not a function declaration. // It is a function call or eg. x(x + 3), not a function declaration.
// Redo the parsing for this specific part. // Redo the parsing for this specific part.
context.pos = began_at; context.pos = began_at;
Ok(Stmt::Expr(Box::new(parse_expr(context)?))) Ok(Stmt::Expr(Box::new(parse_expr(context)?)))
@ -257,10 +261,14 @@ fn parse_factor(context: &mut Context) -> Result<Expr, CalcError> {
|| match_token(context, TokenKind::Percent) || match_token(context, TokenKind::Percent)
|| match_token(context, TokenKind::Identifier) || match_token(context, TokenKind::Identifier)
|| match_token(context, TokenKind::Literal) || match_token(context, TokenKind::Literal)
|| match_token(context, TokenKind::OpenParenthesis)
{ {
// If the token is an identifier, assume it's multiplication. Eg. 3y // If the token is an identifier, literal, or open parenthesis,
// assume it's multiplication. Eg. 3y or (3x + 2)(2 + 3)
let op = match peek(context).kind { let op = match peek(context).kind {
TokenKind::Identifier | TokenKind::Literal => TokenKind::Star, TokenKind::Identifier | TokenKind::Literal | TokenKind::OpenParenthesis => {
TokenKind::Star
}
_ => advance(context).kind, _ => advance(context).kind,
}; };
@ -380,8 +388,15 @@ fn parse_identifier(context: &mut Context) -> Result<Expr, CalcError> {
} }
} }
let parse_as_var_instead = match_token(context, TokenKind::OpenParenthesis)
&& !context.parsing_identifier_stmt
&& !context.symbol_table.contains_fn(&identifier.value);
// Eg. sqrt(64) // Eg. sqrt(64)
if match_token(context, TokenKind::OpenParenthesis) { // If the function doesn't exist, parse it as a variable and multiplication instead.
// Although, if the parse_identifier_stmt function called this function,
// parse it as a function anyway, since it might be creating one.
if !parse_as_var_instead && match_token(context, TokenKind::OpenParenthesis) {
advance(context); advance(context);
let mut parameters = Vec::new(); let mut parameters = Vec::new();
@ -398,7 +413,7 @@ fn parse_identifier(context: &mut Context) -> Result<Expr, CalcError> {
} }
// Eg. x // Eg. x
if context.symbol_table.contains_var(&identifier.value) { if parse_as_var_instead || context.symbol_table.contains_var(&identifier.value) {
Ok(Expr::Var(identifier.value)) Ok(Expr::Var(identifier.value))
} else if context.parsing_unit_decl { } else if context.parsing_unit_decl {
context.unit_decl_base_unit = Some(identifier.value); context.unit_decl_base_unit = Some(identifier.value);