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
}
}
};