mink 0.1.1

(WIP) Portable and modular scripting language for all
Documentation
use std::str::FromStr;

use crate::value::Value as InternalValue;
use crate::ast::{
    Token as InternalToken,
    Expr,
    OpCode,
};

grammar;

// Line
pub Line: InternalToken = {
    Expr => InternalToken::Expr(<>),
    FuncCall,
    Assign,
}

// Expression
Expr: Box<Expr> = {
    Expr ExprOp Factor => Box::new(Expr::Op(<>)),
    Factor,
};
ExprOp: OpCode = {
    "+" => OpCode::Add,
    "-" => OpCode::Sub,
};
Factor: Box<Expr> = {
    Factor FactorOp Term => Box::new(Expr::Op(<>)),
    Term,
};
FactorOp: OpCode = {
    "*" => OpCode::Mul,
    "/" => OpCode::Div,
};
Term: Box<Expr> = {
    Value => Box::new(Expr::Lit(<>)),
    "(" <Expr> ")",
};

// Assign
Assign: InternalToken = {
    <v:ValVar> ":" <e:Expr> => InternalToken::Assign(v, e),
};

// FuncCall
FuncCall: InternalToken = {
    <i:Alpha> "(" <a:List<Expr>> ")" => InternalToken::FuncCall(i.to_string(), a),
};

// Value
Value: InternalValue = {
    ValStr => InternalValue::Str(<>),
    ValNum => InternalValue::Num(<>),
    ValBool => InternalValue::Bool(<>),
    ValVar => InternalValue::Var(<>),
    ValArray => InternalValue::Array(Box::new(<>)),
};
ValStr: String = {
    <s:r#""[^"]*""#> => String::from(&s[1..s.len()-1]),
};
ValNum: f32 = {
    Digit+ => {
        let mut s = String::new();
        for d in <> {
            s += d;
        }
        f32::from_str(s.as_str()).unwrap()
    },
    <l:Digit+> "." <r:Digit+> => {
        let mut s = String::new();
        for d in l {
            s += d;
        }
        s += ".";
        for d in r {
            s += d;
        }
        f32::from_str(s.as_str()).unwrap()
    },
};
ValBool: bool = {
    "true" => true,
    "false" => false,
};
ValVar: String = {
    "$" Alpha => format!("{}{}", <>),
};
ValArray: Vec<InternalValue> = {
    "[" <l:List<Value>> "]" => l,
}

// Alphabet
Alpha = { r"[A-Za-z]+" }
Digit = { r"[0-9]" }

// Util
List<T>: Vec<T> = { // (1)
    <mut v:(<T> ",")*> <e:T?> => match e { // (2)
        None => v,
        Some(e) => {
            v.push(e);
            v
        }
    }
};