Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions commons/src/err/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ impl fmt::Display for PositionedError {
};

let before = &line[0..self.start.col - 1];
let target = &line[self.start.col - 1..self.end.col].cyan().underline();
let after = &line[self.end.col..];
let target = &line[self.start.col - 1..self.end.col - 1].cyan().underline();
let after = &line[self.end.col - 1..];

writeln!(f, "{}{}{}", before, target, after)?;
writeln!(f, "")?;
Expand Down
5 changes: 5 additions & 0 deletions examples/math.qf
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
func test() {
var i32 e = !56

eee
}
46 changes: 44 additions & 2 deletions lexer/src/lexer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::{fs, hash::{DefaultHasher, Hash, Hasher}, io::Error};

use commons::Position;

use crate::{LexerParseResult, LexerParsingError, token::LexerToken, token::LexerTokenType};
use crate::{LexerParseResult, LexerParsingError, token::{LexerToken, LexerTokenType}, toks::math::MathOperator};

const FUNC_KEYWORD_HASH: u64 = 17439195341824537259;
const RET_KEYWORD_HASH: u64 = 9222097151127739705;
Expand Down Expand Up @@ -72,6 +72,14 @@ pub fn lexer_parse_file(file_path: &String) -> LexerParseResult<Vec<LexerToken>>
continue;
}

if c == '+' || c == '-' || c == '*' || c == '/' {
let col = i - last_line_break + 1;

tokens.push(parse_math_operator(&contents, &mut i, Position::new(file_path.to_string(), line, col))?);

continue;
}

i += c.len_utf8();


Expand All @@ -93,7 +101,7 @@ pub fn lexer_parse_file(file_path: &String) -> LexerParseResult<Vec<LexerToken>>
'&' => tokens.push(LexerToken::make_single_sized(pos, LexerTokenType::AMPERSAND)),
'<' => tokens.push(LexerToken::make_single_sized(pos, LexerTokenType::ANGEL_BRACKET_OPEN)),
'>' => tokens.push(LexerToken::make_single_sized(pos, LexerTokenType::ANGEL_BRACKET_CLOSE)),
_ => continue
_ => continue
}

}
Expand All @@ -103,6 +111,40 @@ pub fn lexer_parse_file(file_path: &String) -> LexerParseResult<Vec<LexerToken>>
Ok(tokens)
}

fn parse_math_operator(contents: &String, ind: &mut usize, start_pos: Position) -> LexerParseResult<LexerToken> {
let operatorChar = contents.chars().nth(*ind).unwrap();

let operator = match operatorChar {
'+' => MathOperator::ADD,
'-' => MathOperator::SUBSTRACT,
'*' => MathOperator::MULTIPLY,
'/' => MathOperator::DIVIDE,
_ => return Err(LexerParsingError::new(String::from("Invalid operator sign!"), 0))
};

*ind += 1;

let assigns = match contents.chars().nth(*ind) {
Some(v) => v == '=',
None => false
};

if assigns {
*ind += 1;
}

let mut incrementCount = 1;

if assigns {
incrementCount += 1;
}

let end = start_pos.increment_by(incrementCount);

return Ok(LexerToken::new(start_pos, end, LexerTokenType::MATH_OPERATOR(operator, assigns)));

}

fn parse_number_token(str: &String, ind: &mut usize, start_pos: Position) -> LexerParseResult<LexerToken> {
let start = *ind + 1;
let mut end: usize = start;
Expand Down
1 change: 1 addition & 0 deletions lexer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use core::fmt;

pub mod token;
pub mod lexer;
pub mod toks;

type LexerParseResult<T> = std::result::Result<T, LexerParsingError>;

Expand Down
14 changes: 13 additions & 1 deletion lexer/src/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::any::Any;

use commons::{Position, err::{PositionedError, PositionedResult}};

use crate::{LexerParseResult, LexerParsingError};
use crate::{LexerParseResult, LexerParsingError, toks::math::MathOperator};

/// The token type for the lexer
#[derive(PartialEq, Debug)]
Expand All @@ -19,6 +19,11 @@ pub enum LexerTokenType {
LAYOUT,
LAY,

/// 0: the operator
/// 1: does the operator affect the original variable!
MATH_OPERATOR(MathOperator, bool),


/// Represent the ret keyword
RETURN,

Expand Down Expand Up @@ -91,6 +96,13 @@ impl LexerToken {
};
}

pub fn expects_math_operator(&self) -> PositionedResult<(MathOperator, bool)> {
match &self.tok_type {
LexerTokenType::MATH_OPERATOR(a, b) => return Ok((a.clone(), *b)),
_ => return Err(self.make_err("Expected math operator here!"))
};
}

pub fn expects_string_lit(&self) -> PositionedResult<String> {
match &self.tok_type {
LexerTokenType::STRING_LIT(v) => return Ok(v.to_string()),
Expand Down
10 changes: 10 additions & 0 deletions lexer/src/toks/math.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
///! Maths token related utils

/// The different operators
#[derive(Debug, PartialEq, Clone)]
pub enum MathOperator {
ADD,
SUBSTRACT,
MULTIPLY,
DIVIDE
}
1 change: 1 addition & 0 deletions lexer/src/toks/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod math;
18 changes: 18 additions & 0 deletions parser/src/ast/math.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
use commons::err::PositionedResult;
use lexer::token::LexerToken;

use crate::ast::{parse_ast_value, tree::ASTTreeNode};

pub fn parse_math_operation(tokens: &Vec<LexerToken>, ind: &mut usize, original: Box<ASTTreeNode>, restricts_to_assigns: bool) -> PositionedResult<Box<ASTTreeNode>> {
let oper = tokens[*ind].expects_math_operator()?;

if !oper.1 && restricts_to_assigns {
return Err(tokens[*ind].make_err("Using math operation without assigments is forbidden here!"));
}

*ind += 1;

let rightMember = parse_ast_value(tokens, ind)?;

return Ok(Box::new(ASTTreeNode::MathResult { lval: original, rval: rightMember, operator: oper.0, assigns: oper.1 }))
}
40 changes: 30 additions & 10 deletions parser/src/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,17 @@ use commons::err::PositionedResult;
use lexer::token::{LexerToken, LexerTokenType};
use utils::hash::WithHash;

use crate::{ParserError, ParserResult, ast::{cond::operators::parse_condition_operator, control::{forloop::parse_for_loop, ifelse::parse_if_statement, whileblock::parse_while_block}, func::{call::parse_function_call, decl::parse_function_declaraction}, literals::{parse_integer_literal, parse_string_literal}, tree::ASTTreeNode, var::decl::parse_variable_declaration}};
use crate::{ParserError, ParserResult, ast::{cond::operators::parse_condition_operator, control::{forloop::parse_for_loop, ifelse::parse_if_statement, whileblock::parse_while_block}, func::{call::parse_function_call, decl::parse_function_declaraction}, literals::{parse_integer_literal, parse_string_literal}, math::parse_math_operation, tree::ASTTreeNode, var::decl::parse_variable_declaration}};

pub mod tree;
pub mod func;
pub mod var;
pub mod literals;
pub mod cond;
pub mod control;
pub mod math;

pub fn parse_ast_value_post_l(tokens: &Vec<LexerToken>, ind: &mut usize, original: PositionedResult<Box<ASTTreeNode>>) -> PositionedResult<Box<ASTTreeNode>> {
pub fn parse_ast_value_post_l(tokens: &Vec<LexerToken>, ind: &mut usize, original: PositionedResult<Box<ASTTreeNode>>, invoked_on_body: bool) -> PositionedResult<Box<ASTTreeNode>> {
match &tokens[*ind].tok_type {
LexerTokenType::DOT => {
let o = &original?;
Expand All @@ -43,6 +44,13 @@ pub fn parse_ast_value_post_l(tokens: &Vec<LexerToken>, ind: &mut usize, origina
return Err(tokens[*ind].make_err("Invalid token type to use dot access!"));
},

LexerTokenType::MATH_OPERATOR(_, _) => {
let o = &original?;
let k = Box::new(ASTTreeNode::clone(o.as_ref()));

return Ok(parse_math_operation(tokens, ind, k, invoked_on_body)?);
},

LexerTokenType::ANGEL_BRACKET_CLOSE | LexerTokenType::EQUAL_SIGN | LexerTokenType::ANGEL_BRACKET_OPEN => {
let operator = parse_condition_operator(tokens, ind)?;

Expand Down Expand Up @@ -75,28 +83,28 @@ pub fn parse_ast_value(tokens: &Vec<LexerToken>, ind: &mut usize) -> PositionedR

LexerTokenType::INT_LIT(_) => {
let int = parse_integer_literal(tokens, ind);
return parse_ast_value_post_l(tokens, ind, int);
return parse_ast_value_post_l(tokens, ind, int, false);
},

LexerTokenType::STRING_LIT(_) => {
let str = parse_string_literal(tokens, ind);
return parse_ast_value_post_l(tokens, ind, str);
return parse_ast_value_post_l(tokens, ind, str, false);
},

LexerTokenType::KEYWORD(str, _) => {
if tokens[*ind + 1].tok_type == LexerTokenType::PAREN_OPEN {
let call = parse_function_call(tokens, ind);
return parse_ast_value_post_l(tokens, ind, call);
return parse_ast_value_post_l(tokens, ind, call, false);
}

let n = Ok(Box::new(ASTTreeNode::VariableReference(WithHash::new(String::clone(str)))));

*ind += 1;

return parse_ast_value_post_l(tokens, ind, n);
return parse_ast_value_post_l(tokens, ind, n, false);
}

_ => return Err(tokens[*ind].make_err("Cannot be parsed as value!"))
_ => return Err(tokens[*ind].make_err("Invalid token to parse as a value!"))
}
}

Expand All @@ -122,11 +130,23 @@ pub fn parse_ast_node(tokens: &Vec<LexerToken>, ind: &mut usize) -> PositionedRe

LexerTokenType::FOR => {
return parse_for_loop(tokens, ind);
}
},

LexerTokenType::KEYWORD(str, _) => {
if tokens[*ind + 1].tok_type == LexerTokenType::PAREN_OPEN {
let call = parse_function_call(tokens, ind);
return parse_ast_value_post_l(tokens, ind, call, true);
}

let n = Ok(Box::new(ASTTreeNode::VariableReference(WithHash::new(String::clone(str)))));

*ind += 1;

return parse_ast_value_post_l(tokens, ind, n, true);
},

_ => {
return Err(tokens[*ind].make_err("Invalid token type! Shouldn't be there!"));
return Err(tokens[*ind].make_err("Expected valid token type in this context!"));
}

}
}
5 changes: 4 additions & 1 deletion parser/src/ast/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
//! AST tree related definitions.
//!

use lexer::toks::math::MathOperator;
use utils::hash::{TypeHash, WithHash};

use crate::ast::cond::operators::ConditionOperator;
use crate::ast::{cond::operators::ConditionOperator};

#[derive(Debug, PartialEq, Clone)]
pub struct FunctionDeclarationArgument {
Expand All @@ -26,6 +27,8 @@ pub enum ASTTreeNode {
OperatorBasedConditionMember { lval: Box<ASTTreeNode>, rval: Box<ASTTreeNode>, operator: ConditionOperator },
BooleanBasedConditionMember { val: Box<ASTTreeNode>, negate: bool },

MathResult { lval: Box<ASTTreeNode>, rval: Box<ASTTreeNode>, operator: MathOperator, assigns: bool },

VariableReference(WithHash<String>),

VarDeclaration { varName: WithHash<String>, varType: TypeHash, value: Option<Box<ASTTreeNode>> },
Expand Down