europalang / Europa-Lang

A fun and simple language with NO classes whatsoever!
MIT License
22 stars 3 forks source link

Tips #2

Closed alexapostolu closed 3 years ago

alexapostolu commented 3 years ago

I added a version command if that's helpful :)

Also just some things I noticed


For your lexer, instead of getting all the tokens at once, you could also get them when you need them, like this:

fn parser() {
    tok = lexer.eat(); // get next token
    if tok.type == TokType::IF {
        // get next token; if next token is not an open bracket, throw error
        tok = lexer.eat(TokType::OPEN_BRACKET, "expected open bracket after 'if' keyword");
    }
}

It doesn't really matter which way you do it. I kinda like the second way thought since you have more control over the lexing process, and it's much easier to deal with syntax errors.


For your parser, you have a lot of duplicate code with your functions: comp, add, mult, unary. I would just suggest having unary and binary.

Same thing with types.rs, there's a bunch of duplicate code. I'm not sure how it works in Rust, but you could try to have a generic binary expression function, and just pass in a lambda like this:

pub fn evaluate_binary_expression(
    &self,
    other: &Type,
    operation:   &dyn Fn(i32, i32) -> TResult,        // lambda function
    div_by_zero: bool,                                // if false, and division by 0 is encountered, throw error
    op_name:     &str                                 // name of the operator to display in the error message
) -> TResult {

        if let (Self::Float(a), Self::Float(b)) = (self, other) {
            if !div_by_zero && *b == 0f32 {
                return Err("Division by 0.".into());
            }

            return Ok(Self::Float(operation(a, b)));
        }

        // not sure how str concat work in rust :/
        Err("Operator '" + op + "' can only be applied to numbers.".into())
}

Hope it helps :D

cursorweb commented 3 years ago
  1. lexer -- the solution you proposed doesn't exactly show how you can show the expression part: if <expression> {. Indeed, it is useful, but it also confuses the parsing step with the parser, which I would like to keep distinct, unless there really is a better way to do it -- I'm all ears!
  2. Yeah, I might make a macro to handle that, but I have to keep the functions distinct to have operator precedence.
  3. Good idea, I'll have to read up on lambdas. Thanks!
cursorweb commented 3 years ago

Thank you! I will create a new issue with all the ideas you discussed.

cursorweb commented 3 years ago

I think this would be better if we just started using an argument parser, it'll be better in the long run.

yeah, true