use crate::{expr::{Expr, Index}, parse::rule::RuleBuilder, value::Value, parse::helpers::*};
use std::str::FromStr;
grammar;
extern {
type Error = RevalParseError;
}
match {
"=" => OP_EQ1,
"==" => OP_EQ2,
"!=" => OP_NEQ,
">" => OP_GT,
"<" => OP_LT,
">=" => OP_GTE,
"<=" => OP_LTE,
"+" => OP_ADD,
"-" => OP_SUB,
"*" => OP_MULT,
"/" => OP_DIV,
"%" => OP_REM,
"!" => OP_NOT,
"&" => OP_BIT_AND,
"|" => OP_BIT_OR,
"^" => OP_BIT_XOR,
"@" => OP_META,
"and" => KWD_AND,
"or" => KWD_OR,
"if" => KWD_IF,
"then" => KWD_THEN,
"else" => KWD_ELSE,
"is_some" => KWD_IS_SOME,
"is_none" => KWD_IS_NONE,
"none" => KWD_NONE,
"some" => KWD_SOME,
"int" => KWD_INT,
"float" => KWD_FLOAT,
"dec" => KWD_DEC,
"contains" => KWD_CONTAINS,
"in" => KWD_IN,
"date_time" => KWD_DATE_TIME,
"datetime" => KWD_DATETIME,
"duration" => KWD_DURATION,
"to_upper" => KWD_TO_UPPER,
"to_lower" => KWD_TO_LOWER,
"uppercase" => KWD_UPPERCASE,
"lowercase" => KWD_LOWERCASE,
"trim" => KWD_TRIM,
"round" => KWD_ROUND,
"floor" => KWD_FLOOR,
"fract" => KWD_FRACT,
"year" => KWD_YEAR,
"month" => KWD_MONTH,
"week" => KWD_WEEK,
"day" => KWD_DAY,
"hour" => KWD_HOUR,
"minute" => KWD_MINUTE,
"second" => KWD_SECOND,
"starts" => KWD_STARTS,
"ends" => KWD_ENDS,
"," => COMMA,
":" => COLON,
";" => SEMICOLON,
"." => DOT,
"(" => LPAREN,
")" => RPAREN,
"[" => LBRACKET,
"]" => RBRACKET,
"{" => LBRACE,
"}" => RBRACE,
r#""[^"\\]*(?:\\.[^"\\]*)*""# => STRING,
r"i[+-]?[0-9]+" => INT,
r"0x[0-9a-fA-F]+" => HEX_INT,
r"0o[0-8]+" => OCT_INT,
r"0b[01]+" => BIN_INT,
r"f[+-]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?" => FLOAT,
r"d[+-]?[0-9]*\.?[0-9]+" => DECIMAL,
"true" => TRUE,
"false" => FALSE,
r"\s*" => { }, // The default whitespace skipping is disabled if an `ignore pattern` is specified
r"//[^\n\r]*[\n\r]*" => { }, // Skip `// comments`
}
else {
r"[a-zA-Z][_a-zA-Z0-9]*" => IDENT,
r"[0-9]+" => INDEX,
}
pub Rule: RuleBuilder = <m:(<MetaItem>)*> <e: Expr> =>? Ok(RuleBuilder::parse(m, e)?);
MetaItem: (String, Expr) = OP_META <k:IDENT> COLON <e:Expr> SEMICOLON => (k.to_string(), e);
pub Expr: Expr = IfExpr;
IfExpr: Expr = {
KWD_IF <iif:IfExpr> KWD_THEN <thn:IfExpr> KWD_ELSE <els:IfExpr> => Expr::iif(iif, thn, els),
LogExpr
}
LogExpr: Expr = {
<l:LogExpr> KWD_AND <r:EqExpr> => Expr::and(l, r),
<l:LogExpr> KWD_OR <r:EqExpr> => Expr::or(l, r),
EqExpr
}
EqExpr: Expr = {
<l:EqExpr> OP_EQ1 <r:AddExpr> => Expr::eq(l, r),
<l:EqExpr> OP_EQ2 <r:AddExpr> => Expr::eq(l, r),
<l:EqExpr> OP_NEQ <r:AddExpr> => Expr::neq(l, r),
<l:EqExpr> OP_GT <r:AddExpr> => Expr::gt(l, r),
<l:EqExpr> OP_LT <r:AddExpr> => Expr::lt(l, r),
<l:EqExpr> OP_GTE <r:AddExpr> => Expr::gte(l, r),
<l:EqExpr> OP_LTE <r:AddExpr> => Expr::lte(l, r),
AddExpr
}
AddExpr: Expr = {
<l:AddExpr> OP_ADD <r:MultExpr> => Expr::add(l, r),
<l:AddExpr> OP_SUB <r:MultExpr> => Expr::sub(l, r),
MultExpr
}
MultExpr: Expr = {
<l:MultExpr> OP_MULT <r:BitExpr> => Expr::mult(l, r),
<l:MultExpr> OP_DIV <r:BitExpr> => Expr::div(l, r),
<l:MultExpr> OP_REM <r:BitExpr> => Expr::rem(l, r),
BitExpr
}
BitExpr: Expr = {
<l:BitExpr> OP_BIT_AND <r:SubStringExpr> => Expr::bitwise_and(l, r),
<l:BitExpr> OP_BIT_OR <r:SubStringExpr> => Expr::bitwise_or(l, r),
<l:BitExpr> OP_BIT_XOR <r:SubStringExpr> => Expr::bitwise_xor(l, r),
SubStringExpr
}
SubStringExpr: Expr = {
<l:IndexExpr> KWD_CONTAINS <r:IndexExpr> => Expr::contains(l, r),
<l:IndexExpr> KWD_IN <r:IndexExpr> => Expr::contains(r, l),
<l:IndexExpr> KWD_STARTS <r:IndexExpr> => Expr::starts(l, r),
<l:IndexExpr> KWD_ENDS <r:IndexExpr> => Expr::ends(l, r),
UnaryExpr
}
UnaryExpr: Expr = {
OP_SUB <e:UnaryExpr> => Expr::neg(e),
OP_NOT <e:UnaryExpr> => Expr::not(e),
IndexExpr
}
IndexExpr: Expr = {
<l:IndexExpr> DOT <r:IDENT> => Expr::index(l, Index::from(r)),
<l:IndexExpr> DOT <r:INDEX> => Expr::index(l, Index::from(usize::from_str(r).unwrap())),
Term
}
Term: Expr = {
Func,
Ref,
Symbol,
VecExpr,
MapExpr,
Value => Expr::Value(<>),
LPAREN <Expr> RPAREN
};
Func: Expr = {
KWD_INT LPAREN <e:Expr> RPAREN => Expr::int(e),
KWD_FLOAT LPAREN <e:Expr> RPAREN => Expr::float(e),
KWD_DEC LPAREN <e:Expr> RPAREN => Expr::dec(e),
KWD_DATE_TIME LPAREN <e:Expr> RPAREN => Expr::datetime(e),
KWD_DATETIME LPAREN <e:Expr> RPAREN => Expr::datetime(e),
KWD_DURATION LPAREN <e:Expr> RPAREN => Expr::duration(e),
KWD_IS_SOME LPAREN <e:Expr> RPAREN => Expr::some(e),
KWD_IS_NONE LPAREN <e:Expr> RPAREN => Expr::none(e),
KWD_SOME LPAREN <e:Expr> RPAREN => Expr::some(e),
KWD_NONE LPAREN <e:Expr> RPAREN => Expr::none(e),
KWD_TO_UPPER LPAREN <e:Expr> RPAREN => Expr::uppercase(e),
KWD_TO_LOWER LPAREN <e:Expr> RPAREN => Expr::lowercase(e),
KWD_UPPERCASE LPAREN <e:Expr> RPAREN => Expr::uppercase(e),
KWD_LOWERCASE LPAREN <e:Expr> RPAREN => Expr::lowercase(e),
KWD_TRIM LPAREN <e:Expr> RPAREN => Expr::trim(e),
KWD_ROUND LPAREN <e:Expr> RPAREN => Expr::round(e),
KWD_FLOOR LPAREN <e:Expr> RPAREN => Expr::floor(e),
KWD_FRACT LPAREN <e:Expr> RPAREN => Expr::fract(e),
KWD_YEAR LPAREN <e:Expr> RPAREN => Expr::year(e),
KWD_MONTH LPAREN <e:Expr> RPAREN => Expr::month(e),
KWD_WEEK LPAREN <e:Expr> RPAREN => Expr::week(e),
KWD_DAY LPAREN <e:Expr> RPAREN => Expr::day(e),
KWD_HOUR LPAREN <e:Expr> RPAREN => Expr::hour(e),
KWD_MINUTE LPAREN <e:Expr> RPAREN => Expr::minute(e),
KWD_SECOND LPAREN <e:Expr> RPAREN => Expr::second(e),
<f:IDENT> LPAREN <e:Expr> RPAREN => Expr::func(f, e),
}
Ref: Expr = <s:IDENT> => Expr::reff(<>);
Symbol: Expr = COLON <s:IDENT> => Expr::symbol(s);
VecExpr: Expr = LBRACKET <e0:(<Expr> COMMA)*> <e1:Expr?> RBRACKET => Expr::Vec(e0.into_iter().chain(e1).collect());
MapExpr: Expr = LBRACE <kv0:(<MapItem> COMMA)*> <kv1:MapItem?> RBRACE => Expr::Map(kv0.into_iter().chain(kv1).collect());
MapItem: (String, Expr) = <k:IDENT> COLON <e:Expr> => (k.to_string(), e);
Value: Value = {
StringValue,
IntValue,
HexIntValue,
OctIntValue,
BinIntValue,
FloatValue,
DecimalValue,
BoolValue,
NoneValue,
};
StringValue: Value = <s:STRING> =>? Ok(parse_string_literal(s)?);
IntValue: Value = <s:INT> =>? Ok(parse_int_value(s)?);
HexIntValue: Value = <s:HEX_INT> =>? Ok(parse_hex_int_value(s)?);
OctIntValue: Value = <s:OCT_INT> =>? Ok(parse_oct_int_value(s)?);
BinIntValue: Value = <s:BIN_INT> =>? Ok(parse_bin_int_value(s)?);
FloatValue: Value = <s:FLOAT> =>? Ok(parse_float_value(s)?);
DecimalValue: Value = <s:DECIMAL> =>? Ok(parse_decimal_value(s)?);
BoolValue: Value = {
TRUE => Value::Bool(true),
FALSE => Value::Bool(false)
};
NoneValue: Value = KWD_NONE => Value::None;