use nom::combinator::{not, opt, peek};
use nom::multi::many1;
use nom::sequence::{terminated, tuple};
use nom::{bytes::complete::tag, sequence::pair};
use crate::puppet_lang::expression::{Accessor, CaseVariant};
use crate::puppet_lang::ExtraGetter;
use crate::puppet_parser::common::{
capture_comment, fold_many0_with_const_init, space0_delimimited, spaced_word,
square_brackets_comma_separated1,
};
use crate::puppet_parser::range::Range;
use crate::puppet_parser::term::parse_term;
use crate::puppet_parser::{IResult, ParseError, Span};
use nom::{branch::alt, combinator::map};
pub fn parse_accessor(input: Span) -> IResult<Option<Accessor<Range>>> {
opt(map(
many1(square_brackets_comma_separated1(
false,
map(crate::puppet_parser::expression::parse_expression, Box::new),
)),
|list| Accessor {
extra: Range::from((list.first().unwrap().0, list.last().unwrap().2)),
list: list.into_iter().map(|(_, elt, _)| elt).collect(),
},
))(input)
}
pub(crate) fn parse_match_variant(
input: Span,
) -> IResult<crate::puppet_lang::expression::Expression<Range>> {
let (input, (comment, left_term, accessor, tag_variant)) = tuple((
capture_comment,
space0_delimimited(crate::puppet_parser::term::parse_term),
parse_accessor,
space0_delimimited(alt((tag("=~"), tag("!~")))),
))(input)?;
let left_expr = crate::puppet_lang::expression::Expression {
extra: Range::from((&left_term.extra, &accessor, &left_term.extra)),
value: crate::puppet_lang::expression::ExpressionVariant::Term(left_term),
accessor,
comment,
};
let parser_match_regex = map(
pair(capture_comment, crate::puppet_parser::regex::parse),
|(comment, regex)| match *tag_variant {
"=~" => crate::puppet_lang::expression::Expression {
extra: (&left_expr.extra, ®ex.extra).into(),
value: crate::puppet_lang::expression::ExpressionVariant::MatchRegex((
Box::new(left_expr.clone()),
regex,
)),
accessor: None,
comment,
},
"!~" => crate::puppet_lang::expression::Expression {
extra: (&left_expr.extra, ®ex.extra).into(),
value: crate::puppet_lang::expression::ExpressionVariant::NotMatchRegex((
Box::new(left_expr.clone()),
regex,
)),
accessor: None,
comment,
},
_ => unreachable!(),
},
);
let parser_match_type = map(
pair(capture_comment, crate::puppet_parser::typing::parse_type_specification),
|(comment, t)| match *tag_variant {
"=~" => crate::puppet_lang::expression::Expression {
extra: (&left_expr.extra, &t.extra).into(),
value: crate::puppet_lang::expression::ExpressionVariant::MatchType((
Box::new(left_expr.clone()),
Box::new(t),
)),
accessor: None,
comment,
},
"!~" => crate::puppet_lang::expression::Expression {
extra: (&left_expr.extra, &t.extra).into(),
value: crate::puppet_lang::expression::ExpressionVariant::NotMatchType((
Box::new(left_expr.clone()),
Box::new(t),
)),
accessor: None,
comment,
},
_ => unreachable!(),
},
);
let parser = alt((parser_match_regex, parser_match_type));
let mut parser = ParseError::protect(
|_| "Regex or type specification expected after match operator".to_string(),
parser,
);
parser(input)
}
fn parse_not(input: Span) -> IResult<crate::puppet_lang::expression::Expression<Range>> {
let parser = tuple((
capture_comment,
space0_delimimited(tag("!")),
parse_expression,
));
map(parser, |(comment, op, expr)| {
crate::puppet_lang::expression::Expression {
extra: (op, &expr.extra).into(),
value: crate::puppet_lang::expression::ExpressionVariant::Not(Box::new(expr)),
comment,
accessor: None,
}
})(input)
}
pub fn parse_case_variant(input: Span) -> IResult<CaseVariant<Range>> {
map(parse_term, |t| {
if matches!(
&t.value,
crate::puppet_lang::expression::TermVariant::String(s) if crate::puppet_tool::string::raw_content(s) == "default"
) {
CaseVariant::Default(crate::puppet_lang::expression::Default { extra: t.extra })
} else {
CaseVariant::Term(t)
}
})(input)
}
pub fn parse_term_expr(input: Span) -> IResult<crate::puppet_lang::expression::Expression<Range>> {
map(
tuple((capture_comment, crate::puppet_parser::term::parse_term, parse_accessor)),
|(comment, term, accessor)| crate::puppet_lang::expression::Expression {
extra: Range::from((&term.extra, &accessor, &term.extra)),
value: crate::puppet_lang::expression::ExpressionVariant::Term(term),
comment,
accessor,
},
)(input)
}
pub fn parse_string_expr(input: Span) -> IResult<crate::puppet_lang::expression::Expression<Range>> {
map(
tuple((
capture_comment,
crate::puppet_parser::term::parse_string_variant,
parse_accessor,
)),
|(comment, term, accessor)| crate::puppet_lang::expression::Expression {
extra: Range::from((&term.extra, &accessor, &term.extra)),
value: crate::puppet_lang::expression::ExpressionVariant::Term(
crate::puppet_lang::expression::Term {
extra: Range::from((&term.extra, &accessor, &term.extra)),
value: crate::puppet_lang::expression::TermVariant::String(term),
},
),
comment,
accessor,
},
)(input)
}
pub fn parse_lambda(input: Span) -> IResult<crate::puppet_lang::expression::Lambda<Range>> {
map(
pair(
crate::puppet_parser::common::pipes_delimimited(
crate::puppet_parser::common::comma_separated_list0_with_last_comment(crate::puppet_parser::argument::parse),
),
space0_delimimited(ParseError::protect(
|_| "'{' expected".to_string(),
crate::puppet_parser::statement::parse_statement_block,
)),
),
|((left_pipe, args, _right_pipe), (_left_curly, body, right_curly))| {
crate::puppet_lang::expression::Lambda {
args,
body,
extra: (left_pipe, right_curly).into(),
}
},
)(input)
}
fn parse_funcall(input: Span) -> IResult<crate::puppet_lang::expression::Expression<Range>> {
map(
tuple((
capture_comment,
crate::puppet_parser::identifier::anycase_identifier_with_ns,
space0_delimimited(crate::puppet_parser::common::round_brackets_comma_separated0(
crate::puppet_parser::expression::parse_expression,
)),
opt(space0_delimimited(parse_lambda)),
parse_accessor,
)),
|(comment, identifier, (_left_paren, args, right_paren), lambda, accessor)| {
let end_range = match &accessor {
Some(v) => v.extra.clone(),
None => match &lambda {
Some(v) => v.extra.clone(),
None => Range::from((right_paren, right_paren)),
},
};
crate::puppet_lang::expression::Expression {
extra: (&identifier.extra, &accessor, &end_range).into(),
value: crate::puppet_lang::expression::ExpressionVariant::FunctionCall(
crate::puppet_lang::expression::FunctionCall {
extra: (&identifier.extra, &end_range).into(),
identifier,
args,
lambda,
},
),
accessor,
comment,
}
},
)(input)
}
fn parse_l0(input: Span) -> IResult<crate::puppet_lang::expression::Expression<Range>> {
space0_delimimited(alt((
parse_not,
parse_match_variant,
crate::puppet_parser::builtin::parse_builtin,
parse_funcall,
parse_term_expr,
)))(input)
}
fn parse_chain_call_right(input: Span) -> IResult<crate::puppet_lang::expression::FunctionCall<Range>> {
let parse_just_identifier = map(crate::puppet_parser::identifier::lowercase_identifier, |identifier| {
crate::puppet_lang::identifier::LowerIdentifier {
extra: Range::from((identifier, identifier)),
name: vec![identifier.to_string()],
is_toplevel: false,
}
});
map(
tuple((
parse_just_identifier,
opt(space0_delimimited(
crate::puppet_parser::common::round_brackets_comma_separated0(crate::puppet_parser::expression::parse_expression),
)),
opt(space0_delimimited(parse_lambda)),
)),
|(identifier, args, lambda)| {
let end_range = match &lambda {
Some(v) => v.extra.clone(),
None => match args {
Some((_, _, right_bracket)) => Range::from((right_bracket, right_bracket)),
None => identifier.extra.clone(),
},
};
let args = args.map(|v| v.1).unwrap_or_default();
crate::puppet_lang::expression::FunctionCall {
extra: (&identifier.extra, &end_range).into(),
identifier,
args,
lambda,
}
},
)(input)
}
fn parse_chain_call(input: Span) -> IResult<crate::puppet_lang::expression::Expression<Range>> {
let (input, left_expr) = parse_l0(input)?;
let mut parser = fold_many0_with_const_init(
pair(
space0_delimimited(tag(".")),
ParseError::protect(
|_| "Second argument of chain operator is expected".to_string(),
parse_chain_call_right,
),
),
left_expr,
|left, (_op, right)| crate::puppet_lang::expression::Expression {
extra: Range::from((&left.extra, &right.extra)),
value: crate::puppet_lang::expression::ExpressionVariant::ChainCall(
crate::puppet_lang::expression::ChainCall {
extra: Range::from((&left.extra, &right.extra)),
left: Box::new(left),
right: Box::new(right),
},
),
comment: vec![],
accessor: None,
},
);
parser(input)
}
fn parse_in_expr(input: Span) -> IResult<crate::puppet_lang::expression::Expression<Range>> {
let parser = pair(
parse_chain_call,
opt(pair(
spaced_word("in"),
ParseError::protect(
|_| "Expression expected after 'in'".to_string(),
parse_chain_call,
),
)),
);
map(parser, |(left, tail)| match tail {
Some((_op, right)) => crate::puppet_lang::expression::Expression {
extra: Range::from((&left.extra, &right.extra)),
value: crate::puppet_lang::expression::ExpressionVariant::In((
Box::new(left),
Box::new(right),
)),
comment: vec![],
accessor: None,
},
None => left,
})(input)
}
fn parse_selector_case(input: Span) -> IResult<crate::puppet_lang::expression::SelectorCase<Range>> {
let parser = tuple((
capture_comment,
parse_case_variant,
space0_delimimited(tag("=>")),
ParseError::protect(
|_| "A value for selector case is expected".to_string(),
parse_expression,
),
));
map(parser, |(comment, case, _tag, body)| {
crate::puppet_lang::expression::SelectorCase {
extra: Range::from((case.extra(), &body.extra)),
case,
body: Box::new(body),
comment,
}
})(input)
}
fn parse_selector(input: Span) -> IResult<crate::puppet_lang::expression::Expression<Range>> {
let parser = pair(
parse_in_expr,
opt(tuple((
space0_delimimited(tag("?")),
ParseError::protect(
|_| "Opening '{' of selector is expected".to_string(),
tag("{"),
),
space0_delimimited(crate::puppet_parser::common::comma_separated_list0_with_last_comment(
parse_selector_case,
)),
ParseError::protect(
|_| "Closing '}' of selector is expected".to_string(),
tag("}"),
),
))),
);
map(parser, |(condition, tail)| match tail {
Some((_op, _, cases, right_curly)) => crate::puppet_lang::expression::Expression {
extra: Range::from((&condition.extra, right_curly)),
value: crate::puppet_lang::expression::ExpressionVariant::Selector(
crate::puppet_lang::expression::Selector {
extra: Range::from((&condition.extra, right_curly)),
condition: Box::new(condition),
cases,
},
),
comment: vec![],
accessor: None,
},
None => condition,
})(input)
}
pub(crate) fn parse_l1(input: Span) -> IResult<crate::puppet_lang::expression::Expression<Range>> {
let (input, left_expr) = parse_selector(input)?;
let mut parser = fold_many0_with_const_init(
pair(
alt((
tag("*"),
terminated(tag("/"), peek(not(tag("*")))),
tag("%"),
)),
space0_delimimited(ParseError::protect(
|_| "Second argument of operator is expected".to_string(),
parse_l1,
)),
),
left_expr,
|prev, (op, cur)| match *op {
"*" => crate::puppet_lang::expression::Expression {
extra: Range::from((&prev.extra, &cur.extra)),
value: crate::puppet_lang::expression::ExpressionVariant::Multiply((
Box::new(prev),
Box::new(cur),
)),
comment: Vec::new(),
accessor: None,
},
"/" => crate::puppet_lang::expression::Expression {
extra: Range::from((&prev.extra, &cur.extra)),
value: crate::puppet_lang::expression::ExpressionVariant::Divide((
Box::new(prev),
Box::new(cur),
)),
comment: Vec::new(),
accessor: None,
},
"%" => crate::puppet_lang::expression::Expression {
extra: Range::from((&prev.extra, &cur.extra)),
value: crate::puppet_lang::expression::ExpressionVariant::Modulo((
Box::new(prev),
Box::new(cur),
)),
comment: Vec::new(),
accessor: None,
},
_ => unreachable!(),
},
);
parser(input)
}
fn parse_l2(input: Span) -> IResult<crate::puppet_lang::expression::Expression<Range>> {
let (input, left_expr) = space0_delimimited(parse_l1)(input)?;
let mut parser = fold_many0_with_const_init(
pair(
alt((tag("+"), terminated(tag("-"), peek(not(tag(">")))))),
space0_delimimited(ParseError::protect(
|_| "Second argument of operator is expected".to_string(),
parse_l1,
)),
),
left_expr,
|prev, (op, cur)| match *op {
"+" => crate::puppet_lang::expression::Expression {
extra: Range::from((&prev.extra, &cur.extra)),
value: crate::puppet_lang::expression::ExpressionVariant::Plus((
Box::new(prev),
Box::new(cur),
)),
comment: Vec::new(),
accessor: None,
},
"-" => crate::puppet_lang::expression::Expression {
extra: Range::from((&prev.extra, &cur.extra)),
value: crate::puppet_lang::expression::ExpressionVariant::Minus((
Box::new(prev),
Box::new(cur),
)),
comment: Vec::new(),
accessor: None,
},
_ => unreachable!(),
},
);
parser(input)
}
fn parse_l3(input: Span) -> IResult<crate::puppet_lang::expression::Expression<Range>> {
let (input, left_expr) = space0_delimimited(parse_l2)(input)?;
let mut parser = fold_many0_with_const_init(
pair(
alt((tag("<<"), tag(">>"))),
space0_delimimited(ParseError::protect(
|_| "Second argument of operator is expected".to_string(),
parse_l2,
)),
),
left_expr,
|prev, (op, cur)| match *op {
"<<" => crate::puppet_lang::expression::Expression {
extra: Range::from((&prev.extra, &cur.extra)),
value: crate::puppet_lang::expression::ExpressionVariant::ShiftLeft((
Box::new(prev),
Box::new(cur),
)),
comment: Vec::new(),
accessor: None,
},
">>" => crate::puppet_lang::expression::Expression {
extra: Range::from((&prev.extra, &cur.extra)),
value: crate::puppet_lang::expression::ExpressionVariant::ShiftRight((
Box::new(prev),
Box::new(cur),
)),
comment: Vec::new(),
accessor: None,
},
_ => unreachable!(),
},
);
parser(input)
}
fn parse_l4(input: Span) -> IResult<crate::puppet_lang::expression::Expression<Range>> {
let (input, left_expr) = space0_delimimited(parse_l3)(input)?;
let mut parser = fold_many0_with_const_init(
pair(
alt((
tag("=="),
tag("!="),
tag(">="),
tag("<="),
terminated(tag(">"), peek(not(tag(">")))),
tag("<"),
)),
space0_delimimited(ParseError::protect(
|_| "Second argument of operator is expected".to_string(),
parse_l3,
)),
),
left_expr,
|prev, (op, cur)| match *op {
"==" => crate::puppet_lang::expression::Expression {
extra: Range::from((&prev.extra, &cur.extra)),
value: crate::puppet_lang::expression::ExpressionVariant::Equal((
Box::new(prev),
Box::new(cur),
)),
comment: Vec::new(),
accessor: None,
},
"!=" => crate::puppet_lang::expression::Expression {
extra: Range::from((&prev.extra, &cur.extra)),
value: crate::puppet_lang::expression::ExpressionVariant::NotEqual((
Box::new(prev),
Box::new(cur),
)),
comment: Vec::new(),
accessor: None,
},
">" => crate::puppet_lang::expression::Expression {
extra: Range::from((&prev.extra, &cur.extra)),
value: crate::puppet_lang::expression::ExpressionVariant::Gt((
Box::new(prev),
Box::new(cur),
)),
comment: Vec::new(),
accessor: None,
},
">=" => crate::puppet_lang::expression::Expression {
extra: Range::from((&prev.extra, &cur.extra)),
value: crate::puppet_lang::expression::ExpressionVariant::GtEq((
Box::new(prev),
Box::new(cur),
)),
comment: Vec::new(),
accessor: None,
},
"<" => crate::puppet_lang::expression::Expression {
extra: Range::from((&prev.extra, &cur.extra)),
value: crate::puppet_lang::expression::ExpressionVariant::Lt((
Box::new(prev),
Box::new(cur),
)),
comment: Vec::new(),
accessor: None,
},
"<=" => crate::puppet_lang::expression::Expression {
extra: Range::from((&prev.extra, &cur.extra)),
value: crate::puppet_lang::expression::ExpressionVariant::LtEq((
Box::new(prev),
Box::new(cur),
)),
comment: Vec::new(),
accessor: None,
},
_ => unreachable!(),
},
);
parser(input)
}
fn parse_l5(input: Span) -> IResult<crate::puppet_lang::expression::Expression<Range>> {
let (input, left_expr) = space0_delimimited(parse_l4)(input)?;
let mut parser = fold_many0_with_const_init(
pair(
alt((spaced_word("and"), spaced_word("or"))),
space0_delimimited(ParseError::protect(
|_| "Second argument of operator is expected".to_string(),
parse_l4,
)),
),
left_expr,
|prev, (op, cur)| match *op {
"and" => crate::puppet_lang::expression::Expression {
extra: Range::from((&prev.extra, &cur.extra)),
value: crate::puppet_lang::expression::ExpressionVariant::And((
Box::new(prev),
Box::new(cur),
)),
comment: Vec::new(),
accessor: None,
},
"or" => crate::puppet_lang::expression::Expression {
extra: Range::from((&prev.extra, &cur.extra)),
value: crate::puppet_lang::expression::ExpressionVariant::Or((
Box::new(prev),
Box::new(cur),
)),
comment: Vec::new(),
accessor: None,
},
_ => unreachable!(),
},
);
parser(input)
}
pub fn parse_expression(input: Span) -> IResult<crate::puppet_lang::expression::Expression<Range>> {
let (input, left_expr) = space0_delimimited(parse_l5)(input)?;
let mut parser = fold_many0_with_const_init(
pair(
terminated(tag("="), peek(not(alt((tag(">"), tag("~")))))),
space0_delimimited(parse_l5),
),
left_expr,
|prev, (op, cur)| match *op {
"=" => crate::puppet_lang::expression::Expression {
extra: Range::from((&prev.extra, &cur.extra)),
value: crate::puppet_lang::expression::ExpressionVariant::Assign((
Box::new(prev),
Box::new(cur),
)),
comment: Vec::new(),
accessor: None,
},
_ => unreachable!(),
},
);
parser(input)
}
#[test]
fn test_multiply() {
assert_eq!(
parse_expression(Span::new("2*3")).unwrap().1,
crate::puppet_lang::expression::Expression {
accessor: None,
comment: vec![],
value: crate::puppet_lang::expression::ExpressionVariant::Multiply((
Box::new(crate::puppet_lang::expression::Expression {
accessor: None,
comment: vec![],
value: crate::puppet_lang::expression::ExpressionVariant::Term(
crate::puppet_lang::expression::Term {
value: crate::puppet_lang::expression::TermVariant::Integer(
crate::puppet_lang::expression::Integer {
extra: Range::new(0, 1, 1, 0, 1, 1),
value: 2,
}
),
extra: Range::new(0, 1, 1, 0, 1, 1)
}
),
extra: Range::new(0, 1, 1, 0, 1, 1)
}),
Box::new(crate::puppet_lang::expression::Expression {
accessor: None,
comment: vec![],
value: crate::puppet_lang::expression::ExpressionVariant::Term(
crate::puppet_lang::expression::Term {
value: crate::puppet_lang::expression::TermVariant::Integer(
crate::puppet_lang::expression::Integer {
extra: Range::new(2, 1, 3, 2, 1, 3),
value: 3,
}
),
extra: Range::new(2, 1, 3, 2, 1, 3)
}
),
extra: Range::new(2, 1, 3, 2, 1, 3)
}),
)),
extra: Range::new(0, 1, 1, 2, 1, 3)
}
);
}
#[test]
fn test_operators_precendence() {
use crate::puppet_lang::expression::Expression;
use crate::puppet_lang::expression::ExpressionVariant;
use crate::puppet_lang::expression::Integer;
use crate::puppet_lang::expression::Term;
use crate::puppet_lang::expression::TermVariant;
assert_eq!(
parse_expression(Span::new("(1 +2) * 3* 4 - 10")).unwrap().1,
Expression {
accessor: None,
comment: vec![],
value: ExpressionVariant::Minus((
Box::new(Expression {
accessor: None,
comment: vec![],
value: ExpressionVariant::Multiply((
Box::new(Expression {
accessor: None,
comment: vec![],
value: ExpressionVariant::Term(Term {
value: TermVariant::Parens(crate::puppet_lang::expression::Parens {
value: Box::new(Expression {
accessor: None,
comment: vec![],
value: ExpressionVariant::Plus((
Box::new(Expression {
accessor: None,
comment: vec![],
value: ExpressionVariant::Term(Term {
value: TermVariant::Integer(Integer {
value: 1,
extra: Range::new(1, 1, 2, 1, 1, 2)
}),
extra: Range::new(1, 1, 2, 1, 1, 2)
}),
extra: Range::new(1, 1, 2, 1, 1, 2)
}),
Box::new(Expression {
accessor: None,
comment: vec![],
value: ExpressionVariant::Term(Term {
value: TermVariant::Integer(Integer {
value: 2,
extra: Range::new(4, 1, 5, 4, 1, 5)
}),
extra: Range::new(4, 1, 5, 4, 1, 5)
}),
extra: Range::new(4, 1, 5, 4, 1, 5)
})
)),
extra: Range::new(1, 1, 2, 4, 1, 5)
}),
extra: Range::new(0, 1, 1, 5, 1, 6)
}),
extra: Range::new(0, 1, 1, 5, 1, 6)
}),
extra: Range::new(0, 1, 1, 5, 1, 6)
}),
Box::new(Expression {
accessor: None,
comment: vec![],
value: ExpressionVariant::Multiply((
Box::new(Expression {
accessor: None,
comment: vec![],
value: ExpressionVariant::Term(Term {
value: TermVariant::Integer(Integer {
value: 3,
extra: Range::new(9, 1, 10, 9, 1, 10)
}),
extra: Range::new(9, 1, 10, 9, 1, 10)
}),
extra: Range::new(9, 1, 10, 9, 1, 10)
}),
Box::new(Expression {
accessor: None,
comment: vec![],
value: ExpressionVariant::Term(Term {
value: TermVariant::Integer(Integer {
value: 4,
extra: Range::new(12, 1, 13, 12, 1, 13)
}),
extra: Range::new(12, 1, 13, 12, 1, 13)
}),
extra: Range::new(12, 1, 13, 12, 1, 13)
})
)),
extra: Range::new(9, 1, 10, 12, 1, 13)
})
)),
extra: Range::new(0, 1, 1, 12, 1, 13)
}),
Box::new(Expression {
accessor: None,
comment: vec![],
value: ExpressionVariant::Term(Term {
value: TermVariant::Integer(Integer {
value: 10,
extra: Range::new(16, 1, 17, 17, 1, 18)
}),
extra: Range::new(16, 1, 17, 17, 1, 18)
}),
extra: Range::new(16, 1, 17, 17, 1, 18)
})
)),
extra: Range::new(0, 1, 1, 17, 1, 18)
}
);
}
#[test]
fn test_function_call() {
assert_eq!(
parse_funcall(Span::new("lookup('ask8s::docker::gpu_nvidia')"))
.unwrap()
.1,
crate::puppet_lang::expression::Expression {
accessor: None,
comment: vec![],
value: crate::puppet_lang::expression::ExpressionVariant::FunctionCall(
crate::puppet_lang::expression::FunctionCall {
identifier: crate::puppet_lang::identifier::LowerIdentifier {
name: vec!["lookup".to_owned()],
is_toplevel: false,
extra: Range::new(0, 1, 1, 5, 1, 6)
},
args: vec![crate::puppet_lang::expression::Expression {
accessor: None,
comment: vec![],
value: crate::puppet_lang::expression::ExpressionVariant::Term(
crate::puppet_lang::expression::Term {
value: crate::puppet_lang::expression::TermVariant::String(
crate::puppet_lang::string::StringExpr {
data: crate::puppet_lang::string::StringVariant::SingleQuoted(
vec![crate::puppet_lang::string::StringFragment::Literal(
crate::puppet_lang::string::Literal {
data: "ask8s::docker::gpu_nvidia".to_owned(),
extra: Range::new(8, 1, 9, 32, 1, 33)
}
)]
),
extra: Range::new(7, 1, 8, 33, 1, 34),
}
),
extra: Range::new(7, 1, 8, 33, 1, 34)
}
),
extra: Range::new(7, 1, 8, 33, 1, 34)
},],
lambda: None,
extra: Range::new(0, 1, 1, 34, 1, 35),
}
),
extra: Range::new(0, 1, 1, 34, 1, 35)
}
);
}
#[test]
fn test_in_with_parens() {
assert_eq!(
parse_expression(Span::new("(1 in $a)")).unwrap().1,
crate::puppet_lang::expression::Expression {
accessor: None,
comment: vec![],
value: crate::puppet_lang::expression::ExpressionVariant::Term(
crate::puppet_lang::expression::Term {
value: crate::puppet_lang::expression::TermVariant::Parens(crate::puppet_lang::expression::Parens {
value: Box::new(crate::puppet_lang::expression::Expression {
accessor: None,
comment: vec![],
value: crate::puppet_lang::expression::ExpressionVariant::In((
Box::new(crate::puppet_lang::expression::Expression {
accessor: None,
comment: vec![],
value: crate::puppet_lang::expression::ExpressionVariant::Term(
crate::puppet_lang::expression::Term {
value: crate::puppet_lang::expression::TermVariant::Integer(
crate::puppet_lang::expression::Integer {
value: 1,
extra: Range::new(1,1,2, 1, 1, 2)
}
),
extra: Range::new(1,1,2, 1, 1, 2)
}
),
extra: Range::new(1,1,2, 1, 1, 2)
}),
Box::new(crate::puppet_lang::expression::Expression {
accessor: None,
comment: vec![],
value: crate::puppet_lang::expression::ExpressionVariant::Term(
crate::puppet_lang::expression::Term {
value: crate::puppet_lang::expression::TermVariant::Variable(
crate::puppet_lang::expression::Variable {
identifier:
crate::puppet_lang::identifier::LowerIdentifier {
name: vec!["a".to_owned()],
is_toplevel: false,
extra: Range::new(7,1,8, 7, 1, 8)
},
is_local_scope: false,
extra: Range::new(6,1,7, 7, 1, 8)
}
),
extra: Range::new(6,1,7, 7, 1, 8)
}
),
extra: Range::new(6,1,7, 7, 1, 8)
})
)),
extra: Range::new(1,1,2, 7, 1, 8)
}),
extra: Range::new(0,1,1, 8, 1, 9)
}),
extra: Range::new(0,1,1, 8, 1, 9)
}
),
extra: Range::new(0,1,1, 8, 1, 9)
}
);
}
#[test]
fn test_accessor() {
assert_eq!(
parse_expression(Span::new("$a[ 1 ]['z']")).unwrap().1,
crate::puppet_lang::expression::Expression {
extra: Range::new(0, 1, 1, 11, 1, 12),
accessor: Some(crate::puppet_lang::expression::Accessor {
list: vec![
vec![Box::new(crate::puppet_lang::expression::Expression {
accessor: None,
comment: vec![],
value: crate::puppet_lang::expression::ExpressionVariant::Term(
crate::puppet_lang::expression::Term {
value: crate::puppet_lang::expression::TermVariant::Integer(
crate::puppet_lang::expression::Integer {
extra: Range::new(4, 1, 5, 4, 1, 5),
value: 1,
}
),
extra: Range::new(4, 1, 5, 4, 1, 5)
}
),
extra: Range::new(4, 1, 5, 4, 1, 5)
})],
vec![Box::new(crate::puppet_lang::expression::Expression {
accessor: None,
comment: vec![],
value: crate::puppet_lang::expression::ExpressionVariant::Term(
crate::puppet_lang::expression::Term {
value: crate::puppet_lang::expression::TermVariant::String(
crate::puppet_lang::string::StringExpr {
data: crate::puppet_lang::string::StringVariant::SingleQuoted(
vec![crate::puppet_lang::string::StringFragment::Literal(
crate::puppet_lang::string::Literal {
data: "z".to_owned(),
extra: Range::new(9, 1, 10, 9, 1, 10),
}
)]
),
extra: Range::new(8, 1, 9, 10, 1, 11),
}
),
extra: Range::new(8, 1, 9, 10, 1, 11)
}
),
extra: Range::new(8, 1, 9, 10, 1, 11)
})]
],
extra: Range::new(2, 1, 3, 11, 1, 12)
}),
comment: vec![],
value: crate::puppet_lang::expression::ExpressionVariant::Term(
crate::puppet_lang::expression::Term {
extra: Range::new(0, 1, 1, 1, 1, 2),
value: crate::puppet_lang::expression::TermVariant::Variable(
crate::puppet_lang::expression::Variable {
identifier: crate::puppet_lang::identifier::LowerIdentifier {
name: vec!["a".to_owned()],
is_toplevel: false,
extra: Range::new(1, 1, 2, 1, 1, 2)
},
is_local_scope: false,
extra: Range::new(0, 1, 1, 1, 1, 2),
}
)
}
)
}
)
}