add function call syntax
This commit is contained in:
parent
df5793b204
commit
7d525cbaa6
2 changed files with 33 additions and 1 deletions
|
@ -1,5 +1,6 @@
|
||||||
use super::super::*;
|
use super::super::*;
|
||||||
use anyhow::*;
|
use anyhow::*;
|
||||||
|
use itertools::Itertools;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
@ -61,6 +62,7 @@ pub enum AttrValExpr {
|
||||||
UnaryOp(UnaryOp, Box<AttrValExpr>),
|
UnaryOp(UnaryOp, Box<AttrValExpr>),
|
||||||
IfElse(Box<AttrValExpr>, Box<AttrValExpr>, Box<AttrValExpr>),
|
IfElse(Box<AttrValExpr>, Box<AttrValExpr>, Box<AttrValExpr>),
|
||||||
JsonAccess(Box<AttrValExpr>, Box<AttrValExpr>),
|
JsonAccess(Box<AttrValExpr>, Box<AttrValExpr>),
|
||||||
|
FunctionCall(String, Vec<AttrValExpr>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Display for AttrValExpr {
|
impl std::fmt::Display for AttrValExpr {
|
||||||
|
@ -72,6 +74,7 @@ impl std::fmt::Display for AttrValExpr {
|
||||||
AttrValExpr::UnaryOp(op, x) => write!(f, "{}{}", op, x),
|
AttrValExpr::UnaryOp(op, x) => write!(f, "{}{}", op, x),
|
||||||
AttrValExpr::IfElse(a, b, c) => write!(f, "(if {} then {} else {})", a, b, c),
|
AttrValExpr::IfElse(a, b, c) => write!(f, "(if {} then {} else {})", a, b, c),
|
||||||
AttrValExpr::JsonAccess(value, index) => write!(f, "{}[{}]", value, index),
|
AttrValExpr::JsonAccess(value, index) => write!(f, "{}[{}]", value, index),
|
||||||
|
AttrValExpr::FunctionCall(function_name, args) => write!(f, "{}({})", function_name, args.iter().join(", ")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -106,6 +109,9 @@ impl AttrValExpr {
|
||||||
Ok(IfElse(box a.resolve_refs(variables)?, box b.resolve_refs(variables)?, box c.resolve_refs(variables)?))
|
Ok(IfElse(box a.resolve_refs(variables)?, box b.resolve_refs(variables)?, box c.resolve_refs(variables)?))
|
||||||
}
|
}
|
||||||
JsonAccess(box a, box b) => Ok(JsonAccess(box a.resolve_refs(variables)?, box b.resolve_refs(variables)?)),
|
JsonAccess(box a, box b) => Ok(JsonAccess(box a.resolve_refs(variables)?, box b.resolve_refs(variables)?)),
|
||||||
|
FunctionCall(function_name, args) => {
|
||||||
|
Ok(FunctionCall(function_name, args.into_iter().map(|a| a.resolve_refs(variables)).collect::<Result<_>>()?))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -131,6 +137,7 @@ impl AttrValExpr {
|
||||||
refs.append(&mut b.var_refs());
|
refs.append(&mut b.var_refs());
|
||||||
refs
|
refs
|
||||||
}
|
}
|
||||||
|
FunctionCall(_, args) => args.iter().flat_map(|a| a.var_refs()).collect_vec(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -196,6 +203,10 @@ impl AttrValExpr {
|
||||||
_ => bail!("Unable to index into value {}", val),
|
_ => bail!("Unable to index into value {}", val),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
AttrValExpr::FunctionCall(function_name, args) => {
|
||||||
|
let args = args.into_iter().map(|a| a.eval(values)).collect::<Result<_>>()?;
|
||||||
|
call_expr_function(&function_name, args)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,3 +219,17 @@ impl AttrValExpr {
|
||||||
parsed.context("Failed to parse expression")
|
parsed.context("Failed to parse expression")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn call_expr_function(name: &str, args: Vec<PrimVal>) -> Result<PrimVal> {
|
||||||
|
match name {
|
||||||
|
"round" => match args.as_slice() {
|
||||||
|
[num, digits] => {
|
||||||
|
let num = num.as_f64()?;
|
||||||
|
let digits = digits.as_i32()?;
|
||||||
|
Ok(PrimVal::from(format!("{:.1$}", num, digits as usize)))
|
||||||
|
}
|
||||||
|
_ => Err(anyhow!("Incorrect number of arguments given to {}", name)),
|
||||||
|
},
|
||||||
|
_ => Err(anyhow!("Unknown function {}", name)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ use nom::{
|
||||||
character::complete::{multispace0 as multispace, *},
|
character::complete::{multispace0 as multispace, *},
|
||||||
combinator::{map, map_res, *},
|
combinator::{map, map_res, *},
|
||||||
error::{context, ParseError, VerboseError},
|
error::{context, ParseError, VerboseError},
|
||||||
multi::many0,
|
multi::{many0, separated_list0},
|
||||||
sequence::{delimited, preceded, *},
|
sequence::{delimited, preceded, *},
|
||||||
IResult, Parser,
|
IResult, Parser,
|
||||||
};
|
};
|
||||||
|
@ -49,6 +49,12 @@ fn parse_unary_op(i: &str) -> IResult<&str, UnaryOp, VerboseError<&str>> {
|
||||||
value(UnaryOp::Not, tag("!"))(i)
|
value(UnaryOp::Not, tag("!"))(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_function_call(i: &str) -> IResult<&str, AttrValExpr, VerboseError<&str>> {
|
||||||
|
let (i, name) = take_while(|c: char| c.is_ascii_alphanumeric() || c == '_')(i)?;
|
||||||
|
let (i, args) = delimited(tag("("), separated_list0(tag(","), ws(parse_factor)), tag(")"))(i)?;
|
||||||
|
Ok((i, AttrValExpr::FunctionCall(name.to_string(), args)))
|
||||||
|
}
|
||||||
|
|
||||||
/////////////////
|
/////////////////
|
||||||
// actual tree //
|
// actual tree //
|
||||||
/////////////////
|
/////////////////
|
||||||
|
@ -58,6 +64,7 @@ fn parse_factor(i: &str) -> IResult<&str, AttrValExpr, VerboseError<&str>> {
|
||||||
let (i, factor) = alt((
|
let (i, factor) = alt((
|
||||||
context("expression", ws(delimited(tag("("), parse_expr, tag(")")))),
|
context("expression", ws(delimited(tag("("), parse_expr, tag(")")))),
|
||||||
context("if-expression", ws(parse_ifelse)),
|
context("if-expression", ws(parse_ifelse)),
|
||||||
|
context("function-call", ws(parse_function_call)),
|
||||||
context("literal", map(ws(parse_literal), |x| AttrValExpr::Literal(AttrVal::parse_string(x)))),
|
context("literal", map(ws(parse_literal), |x| AttrValExpr::Literal(AttrVal::parse_string(x)))),
|
||||||
context("identifier", map(ws(parse_identifier), |x| AttrValExpr::VarRef(VarName(x.to_string())))),
|
context("identifier", map(ws(parse_identifier), |x| AttrValExpr::VarRef(VarName(x.to_string())))),
|
||||||
))(i)?;
|
))(i)?;
|
||||||
|
|
Loading…
Add table
Reference in a new issue