1use std::collections::HashMap;
16use std::error;
17use std::mem;
18use std::sync::LazyLock;
19
20use itertools::Itertools as _;
21use jj_lib::dsl_util;
22use jj_lib::dsl_util::AliasDeclaration;
23use jj_lib::dsl_util::AliasDeclarationParser;
24use jj_lib::dsl_util::AliasDefinitionParser;
25use jj_lib::dsl_util::AliasExpandError;
26use jj_lib::dsl_util::AliasExpandableExpression;
27use jj_lib::dsl_util::AliasId;
28use jj_lib::dsl_util::AliasesMap;
29use jj_lib::dsl_util::Diagnostics;
30use jj_lib::dsl_util::ExpressionFolder;
31use jj_lib::dsl_util::FoldableExpression;
32use jj_lib::dsl_util::FunctionCallParser;
33use jj_lib::dsl_util::InvalidArguments;
34use jj_lib::dsl_util::StringLiteralParser;
35use jj_lib::dsl_util::collect_similar;
36use jj_lib::str_util::StringPattern;
37use pest::Parser as _;
38use pest::iterators::Pair;
39use pest::iterators::Pairs;
40use pest::pratt_parser::Assoc;
41use pest::pratt_parser::Op;
42use pest::pratt_parser::PrattParser;
43use pest_derive::Parser;
44use thiserror::Error;
45
46#[derive(Parser)]
47#[grammar = "template.pest"]
48struct TemplateParser;
49
50const STRING_LITERAL_PARSER: StringLiteralParser<Rule> = StringLiteralParser {
51 content_rule: Rule::string_content,
52 escape_rule: Rule::string_escape,
53};
54const FUNCTION_CALL_PARSER: FunctionCallParser<Rule> = FunctionCallParser {
55 function_name_rule: Rule::identifier,
56 function_arguments_rule: Rule::function_arguments,
57 keyword_argument_rule: Rule::keyword_argument,
58 argument_name_rule: Rule::identifier,
59 argument_value_rule: Rule::template,
60};
61
62impl Rule {
63 fn to_symbol(self) -> Option<&'static str> {
64 match self {
65 Self::EOI => None,
66 Self::WHITESPACE => None,
67 Self::string_escape => None,
68 Self::string_content_char => None,
69 Self::string_content => None,
70 Self::string_literal => None,
71 Self::raw_string_content => None,
72 Self::raw_string_literal => None,
73 Self::integer_literal => None,
74 Self::identifier => None,
75 Self::concat_op => Some("++"),
76 Self::logical_or_op => Some("||"),
77 Self::logical_and_op => Some("&&"),
78 Self::eq_op => Some("=="),
79 Self::ne_op => Some("!="),
80 Self::ge_op => Some(">="),
81 Self::gt_op => Some(">"),
82 Self::le_op => Some("<="),
83 Self::lt_op => Some("<"),
84 Self::add_op => Some("+"),
85 Self::sub_op => Some("-"),
86 Self::mul_op => Some("*"),
87 Self::div_op => Some("/"),
88 Self::rem_op => Some("%"),
89 Self::logical_not_op => Some("!"),
90 Self::negate_op => Some("-"),
91 Self::pattern_kind_op => Some(":"),
92 Self::prefix_ops => None,
93 Self::infix_ops => None,
94 Self::function => None,
95 Self::keyword_argument => None,
96 Self::argument => None,
97 Self::function_arguments => None,
98 Self::lambda => None,
99 Self::formal_parameters => None,
100 Self::string_pattern_identifier => None,
101 Self::string_pattern => None,
102 Self::primary => None,
103 Self::term => None,
104 Self::expression => None,
105 Self::template => None,
106 Self::program => None,
107 Self::function_alias_declaration => None,
108 Self::alias_declaration => None,
109 }
110 }
111}
112
113pub type TemplateDiagnostics = Diagnostics<TemplateParseError>;
115
116pub type TemplateParseResult<T> = Result<T, TemplateParseError>;
117
118#[derive(Debug, Error)]
119#[error("{pest_error}")]
120pub struct TemplateParseError {
121 kind: TemplateParseErrorKind,
122 pest_error: Box<pest::error::Error<Rule>>,
123 source: Option<Box<dyn error::Error + Send + Sync>>,
124}
125
126#[derive(Clone, Debug, Eq, Error, PartialEq)]
127pub enum TemplateParseErrorKind {
128 #[error("Syntax error")]
129 SyntaxError,
130 #[error("Keyword `{name}` doesn't exist")]
131 NoSuchKeyword {
132 name: String,
133 candidates: Vec<String>,
134 },
135 #[error("Function `{name}` doesn't exist")]
136 NoSuchFunction {
137 name: String,
138 candidates: Vec<String>,
139 },
140 #[error("Method `{name}` doesn't exist for type `{type_name}`")]
141 NoSuchMethod {
142 type_name: String,
143 name: String,
144 candidates: Vec<String>,
145 },
146 #[error("Function `{name}`: {message}")]
147 InvalidArguments { name: String, message: String },
148 #[error("Redefinition of function parameter")]
149 RedefinedFunctionParameter,
150 #[error("{0}")]
151 Expression(String),
152 #[error("In alias `{0}`")]
153 InAliasExpansion(String),
154 #[error("In function parameter `{0}`")]
155 InParameterExpansion(String),
156 #[error("Alias `{0}` expanded recursively")]
157 RecursiveAlias(String),
158}
159
160impl TemplateParseError {
161 pub fn with_span(kind: TemplateParseErrorKind, span: pest::Span<'_>) -> Self {
162 let message = kind.to_string();
163 let pest_error = Box::new(pest::error::Error::new_from_span(
164 pest::error::ErrorVariant::CustomError { message },
165 span,
166 ));
167 Self {
168 kind,
169 pest_error,
170 source: None,
171 }
172 }
173
174 pub fn with_source(mut self, source: impl Into<Box<dyn error::Error + Send + Sync>>) -> Self {
175 self.source = Some(source.into());
176 self
177 }
178
179 pub fn expected_type(expected: &str, actual: &str, span: pest::Span<'_>) -> Self {
180 let message =
181 format!("Expected expression of type `{expected}`, but actual type is `{actual}`");
182 Self::expression(message, span)
183 }
184
185 pub fn expression(message: impl Into<String>, span: pest::Span<'_>) -> Self {
187 Self::with_span(TemplateParseErrorKind::Expression(message.into()), span)
188 }
189
190 pub fn extend_keyword_candidates<I>(mut self, other_keywords: I) -> Self
193 where
194 I: IntoIterator,
195 I::Item: AsRef<str>,
196 {
197 if let TemplateParseErrorKind::NoSuchKeyword { name, candidates } = &mut self.kind {
198 let other_candidates = collect_similar(name, other_keywords);
199 *candidates = itertools::merge(mem::take(candidates), other_candidates)
200 .dedup()
201 .collect();
202 }
203 self
204 }
205
206 pub fn extend_function_candidates<I>(mut self, other_functions: I) -> Self
209 where
210 I: IntoIterator,
211 I::Item: AsRef<str>,
212 {
213 if let TemplateParseErrorKind::NoSuchFunction { name, candidates } = &mut self.kind {
214 let other_candidates = collect_similar(name, other_functions);
215 *candidates = itertools::merge(mem::take(candidates), other_candidates)
216 .dedup()
217 .collect();
218 }
219 self
220 }
221
222 pub fn extend_alias_candidates(self, aliases_map: &TemplateAliasesMap) -> Self {
224 self.extend_keyword_candidates(aliases_map.symbol_names())
225 .extend_function_candidates(aliases_map.function_names())
226 }
227
228 pub fn kind(&self) -> &TemplateParseErrorKind {
229 &self.kind
230 }
231
232 pub fn origin(&self) -> Option<&Self> {
234 self.source.as_ref().and_then(|e| e.downcast_ref())
235 }
236}
237
238impl AliasExpandError for TemplateParseError {
239 fn invalid_arguments(err: InvalidArguments<'_>) -> Self {
240 err.into()
241 }
242
243 fn recursive_expansion(id: AliasId<'_>, span: pest::Span<'_>) -> Self {
244 Self::with_span(TemplateParseErrorKind::RecursiveAlias(id.to_string()), span)
245 }
246
247 fn within_alias_expansion(self, id: AliasId<'_>, span: pest::Span<'_>) -> Self {
248 let kind = match id {
249 AliasId::Symbol(_) | AliasId::Function(..) => {
250 TemplateParseErrorKind::InAliasExpansion(id.to_string())
251 }
252 AliasId::Parameter(_) => TemplateParseErrorKind::InParameterExpansion(id.to_string()),
253 };
254 Self::with_span(kind, span).with_source(self)
255 }
256}
257
258impl From<pest::error::Error<Rule>> for TemplateParseError {
259 fn from(err: pest::error::Error<Rule>) -> Self {
260 Self {
261 kind: TemplateParseErrorKind::SyntaxError,
262 pest_error: Box::new(rename_rules_in_pest_error(err)),
263 source: None,
264 }
265 }
266}
267
268impl From<InvalidArguments<'_>> for TemplateParseError {
269 fn from(err: InvalidArguments<'_>) -> Self {
270 let kind = TemplateParseErrorKind::InvalidArguments {
271 name: err.name.to_owned(),
272 message: err.message,
273 };
274 Self::with_span(kind, err.span)
275 }
276}
277
278fn rename_rules_in_pest_error(err: pest::error::Error<Rule>) -> pest::error::Error<Rule> {
279 err.renamed_rules(|rule| {
280 rule.to_symbol()
281 .map(|sym| format!("`{sym}`"))
282 .unwrap_or_else(|| format!("<{rule:?}>"))
283 })
284}
285
286#[derive(Clone, Debug, PartialEq)]
287pub enum ExpressionKind<'i> {
288 Identifier(&'i str),
289 Boolean(bool),
290 Integer(i64),
291 String(String),
292 Pattern {
295 kind: &'i str,
296 value: Box<ExpressionNode<'i>>,
297 },
298 Unary(UnaryOp, Box<ExpressionNode<'i>>),
299 Binary(BinaryOp, Box<ExpressionNode<'i>>, Box<ExpressionNode<'i>>),
300 Concat(Vec<ExpressionNode<'i>>),
301 FunctionCall(Box<FunctionCallNode<'i>>),
302 MethodCall(Box<MethodCallNode<'i>>),
303 Lambda(Box<LambdaNode<'i>>),
304 AliasExpanded(AliasId<'i>, Box<ExpressionNode<'i>>),
306}
307
308impl<'i> FoldableExpression<'i> for ExpressionKind<'i> {
309 fn fold<F>(self, folder: &mut F, span: pest::Span<'i>) -> Result<Self, F::Error>
310 where
311 F: ExpressionFolder<'i, Self> + ?Sized,
312 {
313 match self {
314 Self::Identifier(name) => folder.fold_identifier(name, span),
315 Self::Boolean(_) | Self::Integer(_) | Self::String(_) => Ok(self),
316 Self::Pattern { kind, value } => {
317 let value = Box::new(folder.fold_expression(*value)?);
318 Ok(Self::Pattern { kind, value })
319 }
320 Self::Unary(op, arg) => {
321 let arg = Box::new(folder.fold_expression(*arg)?);
322 Ok(Self::Unary(op, arg))
323 }
324 Self::Binary(op, lhs, rhs) => {
325 let lhs = Box::new(folder.fold_expression(*lhs)?);
326 let rhs = Box::new(folder.fold_expression(*rhs)?);
327 Ok(Self::Binary(op, lhs, rhs))
328 }
329 Self::Concat(nodes) => Ok(Self::Concat(dsl_util::fold_expression_nodes(
330 folder, nodes,
331 )?)),
332 Self::FunctionCall(function) => folder.fold_function_call(function, span),
333 Self::MethodCall(method) => {
334 let method = Box::new(MethodCallNode {
336 object: folder.fold_expression(method.object)?,
337 function: dsl_util::fold_function_call_args(folder, method.function)?,
338 });
339 Ok(Self::MethodCall(method))
340 }
341 Self::Lambda(lambda) => {
342 let lambda = Box::new(LambdaNode {
343 params: lambda.params,
344 params_span: lambda.params_span,
345 body: folder.fold_expression(lambda.body)?,
346 });
347 Ok(Self::Lambda(lambda))
348 }
349 Self::AliasExpanded(id, subst) => {
350 let subst = Box::new(folder.fold_expression(*subst)?);
351 Ok(Self::AliasExpanded(id, subst))
352 }
353 }
354 }
355}
356
357impl<'i> AliasExpandableExpression<'i> for ExpressionKind<'i> {
358 fn identifier(name: &'i str) -> Self {
359 ExpressionKind::Identifier(name)
360 }
361
362 fn function_call(function: Box<FunctionCallNode<'i>>) -> Self {
363 ExpressionKind::FunctionCall(function)
364 }
365
366 fn alias_expanded(id: AliasId<'i>, subst: Box<ExpressionNode<'i>>) -> Self {
367 ExpressionKind::AliasExpanded(id, subst)
368 }
369}
370
371#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
372pub enum UnaryOp {
373 LogicalNot,
375 Negate,
377}
378
379#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
380pub enum BinaryOp {
381 LogicalOr,
383 LogicalAnd,
385 Eq,
387 Ne,
389 Ge,
391 Gt,
393 Le,
395 Lt,
397 Add,
399 Sub,
401 Mul,
403 Div,
405 Rem,
407}
408
409pub type ExpressionNode<'i> = dsl_util::ExpressionNode<'i, ExpressionKind<'i>>;
410pub type FunctionCallNode<'i> = dsl_util::FunctionCallNode<'i, ExpressionKind<'i>>;
411
412#[derive(Clone, Debug, PartialEq)]
413pub struct MethodCallNode<'i> {
414 pub object: ExpressionNode<'i>,
415 pub function: FunctionCallNode<'i>,
416}
417
418#[derive(Clone, Debug, PartialEq)]
419pub struct LambdaNode<'i> {
420 pub params: Vec<&'i str>,
421 pub params_span: pest::Span<'i>,
422 pub body: ExpressionNode<'i>,
423}
424
425fn parse_identifier_or_literal(pair: Pair<Rule>) -> ExpressionKind {
426 assert_eq!(pair.as_rule(), Rule::identifier);
427 match pair.as_str() {
428 "false" => ExpressionKind::Boolean(false),
429 "true" => ExpressionKind::Boolean(true),
430 name => ExpressionKind::Identifier(name),
431 }
432}
433
434fn parse_identifier_name(pair: Pair<'_, Rule>) -> TemplateParseResult<&str> {
435 let span = pair.as_span();
436 if let ExpressionKind::Identifier(name) = parse_identifier_or_literal(pair) {
437 Ok(name)
438 } else {
439 Err(TemplateParseError::expression("Expected identifier", span))
440 }
441}
442
443fn parse_formal_parameters(params_pair: Pair<'_, Rule>) -> TemplateParseResult<Vec<&str>> {
444 assert_eq!(params_pair.as_rule(), Rule::formal_parameters);
445 let params_span = params_pair.as_span();
446 let params: Vec<_> = params_pair
447 .into_inner()
448 .map(parse_identifier_name)
449 .try_collect()?;
450 if params.iter().all_unique() {
451 Ok(params)
452 } else {
453 Err(TemplateParseError::with_span(
454 TemplateParseErrorKind::RedefinedFunctionParameter,
455 params_span,
456 ))
457 }
458}
459
460fn parse_lambda_node(pair: Pair<Rule>) -> TemplateParseResult<LambdaNode> {
461 assert_eq!(pair.as_rule(), Rule::lambda);
462 let mut inner = pair.into_inner();
463 let params_pair = inner.next().unwrap();
464 let params_span = params_pair.as_span();
465 let body_pair = inner.next().unwrap();
466 let params = parse_formal_parameters(params_pair)?;
467 let body = parse_template_node(body_pair)?;
468 Ok(LambdaNode {
469 params,
470 params_span,
471 body,
472 })
473}
474
475fn parse_string_literal(pair: Pair<Rule>) -> String {
476 match pair.as_rule() {
477 Rule::string_literal => STRING_LITERAL_PARSER.parse(pair.into_inner()),
478 Rule::raw_string_literal => {
479 let [content] = pair.into_inner().collect_array().unwrap();
480 assert_eq!(content.as_rule(), Rule::raw_string_content);
481 content.as_str().to_owned()
482 }
483 other => panic!("unexpected string literal: {other:?}"),
484 }
485}
486
487fn parse_term_node(pair: Pair<Rule>) -> TemplateParseResult<ExpressionNode> {
488 assert_eq!(pair.as_rule(), Rule::term);
489 let mut inner = pair.into_inner();
490 let primary = inner.next().unwrap();
491 assert_eq!(primary.as_rule(), Rule::primary);
492 let primary_span = primary.as_span();
493 let expr = primary.into_inner().next().unwrap();
494 let primary_kind = match expr.as_rule() {
495 Rule::string_literal | Rule::raw_string_literal => {
496 ExpressionKind::String(parse_string_literal(expr))
497 }
498 Rule::integer_literal => {
499 let value = expr.as_str().parse().map_err(|err| {
500 TemplateParseError::expression("Invalid integer literal", expr.as_span())
501 .with_source(err)
502 })?;
503 ExpressionKind::Integer(value)
504 }
505 Rule::string_pattern => {
506 let [lhs, op, rhs] = expr.into_inner().collect_array().unwrap();
507 assert_eq!(lhs.as_rule(), Rule::string_pattern_identifier);
508 assert_eq!(op.as_rule(), Rule::pattern_kind_op);
509 let kind = lhs.as_str();
510 let value_span = rhs.as_span();
511 let value_expr = match rhs.as_rule() {
512 Rule::identifier => ExpressionKind::Identifier(parse_identifier_name(rhs)?),
513 _ => ExpressionKind::String(parse_string_literal(rhs)),
514 };
515 let value = Box::new(ExpressionNode::new(value_expr, value_span));
516 ExpressionKind::Pattern { kind, value }
517 }
518 Rule::identifier => parse_identifier_or_literal(expr),
519 Rule::function => {
520 let function = Box::new(FUNCTION_CALL_PARSER.parse(
521 expr,
522 parse_identifier_name,
523 parse_template_node,
524 )?);
525 ExpressionKind::FunctionCall(function)
526 }
527 Rule::lambda => {
528 let lambda = Box::new(parse_lambda_node(expr)?);
529 ExpressionKind::Lambda(lambda)
530 }
531 Rule::template => parse_template_node(expr)?.kind,
533 other => panic!("unexpected term: {other:?}"),
534 };
535 let primary_node = ExpressionNode::new(primary_kind, primary_span);
536 inner.try_fold(primary_node, |object, chain| {
537 assert_eq!(chain.as_rule(), Rule::function);
538 let span = object.span.start_pos().span(&chain.as_span().end_pos());
539 let method = Box::new(MethodCallNode {
540 object,
541 function: FUNCTION_CALL_PARSER.parse(
542 chain,
543 parse_identifier_name,
544 parse_template_node,
545 )?,
546 });
547 Ok(ExpressionNode::new(
548 ExpressionKind::MethodCall(method),
549 span,
550 ))
551 })
552}
553
554fn parse_expression_node(pair: Pair<Rule>) -> TemplateParseResult<ExpressionNode> {
555 assert_eq!(pair.as_rule(), Rule::expression);
556 static PRATT: LazyLock<PrattParser<Rule>> = LazyLock::new(|| {
557 PrattParser::new()
558 .op(Op::infix(Rule::logical_or_op, Assoc::Left))
559 .op(Op::infix(Rule::logical_and_op, Assoc::Left))
560 .op(Op::infix(Rule::eq_op, Assoc::Left) | Op::infix(Rule::ne_op, Assoc::Left))
561 .op(Op::infix(Rule::ge_op, Assoc::Left)
562 | Op::infix(Rule::gt_op, Assoc::Left)
563 | Op::infix(Rule::le_op, Assoc::Left)
564 | Op::infix(Rule::lt_op, Assoc::Left))
565 .op(Op::infix(Rule::add_op, Assoc::Left) | Op::infix(Rule::sub_op, Assoc::Left))
566 .op(Op::infix(Rule::mul_op, Assoc::Left)
567 | Op::infix(Rule::div_op, Assoc::Left)
568 | Op::infix(Rule::rem_op, Assoc::Left))
569 .op(Op::prefix(Rule::logical_not_op) | Op::prefix(Rule::negate_op))
570 });
571 PRATT
572 .map_primary(parse_term_node)
573 .map_prefix(|op, rhs| {
574 let op_kind = match op.as_rule() {
575 Rule::logical_not_op => UnaryOp::LogicalNot,
576 Rule::negate_op => UnaryOp::Negate,
577 r => panic!("unexpected prefix operator rule {r:?}"),
578 };
579 let rhs = Box::new(rhs?);
580 let span = op.as_span().start_pos().span(&rhs.span.end_pos());
581 let expr = ExpressionKind::Unary(op_kind, rhs);
582 Ok(ExpressionNode::new(expr, span))
583 })
584 .map_infix(|lhs, op, rhs| {
585 let op_kind = match op.as_rule() {
586 Rule::logical_or_op => BinaryOp::LogicalOr,
587 Rule::logical_and_op => BinaryOp::LogicalAnd,
588 Rule::eq_op => BinaryOp::Eq,
589 Rule::ne_op => BinaryOp::Ne,
590 Rule::ge_op => BinaryOp::Ge,
591 Rule::gt_op => BinaryOp::Gt,
592 Rule::le_op => BinaryOp::Le,
593 Rule::lt_op => BinaryOp::Lt,
594 Rule::add_op => BinaryOp::Add,
595 Rule::sub_op => BinaryOp::Sub,
596 Rule::mul_op => BinaryOp::Mul,
597 Rule::div_op => BinaryOp::Div,
598 Rule::rem_op => BinaryOp::Rem,
599 r => panic!("unexpected infix operator rule {r:?}"),
600 };
601 let lhs = Box::new(lhs?);
602 let rhs = Box::new(rhs?);
603 let span = lhs.span.start_pos().span(&rhs.span.end_pos());
604 let expr = ExpressionKind::Binary(op_kind, lhs, rhs);
605 Ok(ExpressionNode::new(expr, span))
606 })
607 .parse(pair.into_inner())
608}
609
610fn parse_template_node(pair: Pair<Rule>) -> TemplateParseResult<ExpressionNode> {
611 assert_eq!(pair.as_rule(), Rule::template);
612 let span = pair.as_span();
613 let inner = pair.into_inner();
614 let mut nodes: Vec<_> = inner
615 .filter_map(|pair| match pair.as_rule() {
616 Rule::concat_op => None,
617 Rule::expression => Some(parse_expression_node(pair)),
618 r => panic!("unexpected template item rule {r:?}"),
619 })
620 .try_collect()?;
621 if nodes.len() == 1 {
622 Ok(nodes.pop().unwrap())
623 } else {
624 Ok(ExpressionNode::new(ExpressionKind::Concat(nodes), span))
625 }
626}
627
628pub fn parse_template(template_text: &str) -> TemplateParseResult<ExpressionNode<'_>> {
630 let mut pairs: Pairs<Rule> = TemplateParser::parse(Rule::program, template_text)?;
631 let first_pair = pairs.next().unwrap();
632 if first_pair.as_rule() == Rule::EOI {
633 let span = first_pair.as_span();
634 Ok(ExpressionNode::new(ExpressionKind::Concat(vec![]), span))
635 } else {
636 parse_template_node(first_pair)
637 }
638}
639
640pub type TemplateAliasesMap = AliasesMap<TemplateAliasParser, String>;
641
642#[derive(Clone, Debug, Default)]
643pub struct TemplateAliasParser;
644
645impl AliasDeclarationParser for TemplateAliasParser {
646 type Error = TemplateParseError;
647
648 fn parse_declaration(&self, source: &str) -> Result<AliasDeclaration, Self::Error> {
649 let mut pairs = TemplateParser::parse(Rule::alias_declaration, source)?;
650 let first = pairs.next().unwrap();
651 match first.as_rule() {
652 Rule::identifier => {
653 let name = parse_identifier_name(first)?.to_owned();
654 Ok(AliasDeclaration::Symbol(name))
655 }
656 Rule::function_alias_declaration => {
657 let mut inner = first.into_inner();
658 let name_pair = inner.next().unwrap();
659 let params_pair = inner.next().unwrap();
660 let name = parse_identifier_name(name_pair)?.to_owned();
661 let params = parse_formal_parameters(params_pair)?
662 .into_iter()
663 .map(|s| s.to_owned())
664 .collect();
665 Ok(AliasDeclaration::Function(name, params))
666 }
667 r => panic!("unexpected alias declaration rule {r:?}"),
668 }
669 }
670}
671
672impl AliasDefinitionParser for TemplateAliasParser {
673 type Output<'i> = ExpressionKind<'i>;
674 type Error = TemplateParseError;
675
676 fn parse_definition<'i>(&self, source: &'i str) -> Result<ExpressionNode<'i>, Self::Error> {
677 parse_template(source)
678 }
679}
680
681pub fn parse<'i>(
685 template_text: &'i str,
686 aliases_map: &'i TemplateAliasesMap,
687) -> TemplateParseResult<ExpressionNode<'i>> {
688 let node = parse_template(template_text)?;
689 dsl_util::expand_aliases(node, aliases_map)
690}
691
692pub fn expect_string_literal<'a>(node: &'a ExpressionNode<'_>) -> TemplateParseResult<&'a str> {
694 catch_aliases_no_diagnostics(node, |node| match &node.kind {
695 ExpressionKind::String(s) => Ok(s.as_str()),
696 _ => Err(TemplateParseError::expression(
697 "Expected string literal",
698 node.span,
699 )),
700 })
701}
702
703pub fn expect_string_pattern(node: &ExpressionNode<'_>) -> TemplateParseResult<StringPattern> {
707 catch_aliases_no_diagnostics(node, |node| match &node.kind {
708 ExpressionKind::Pattern { kind, value } => {
709 let value = expect_string_literal(value)?;
710 StringPattern::from_str_kind(value, kind).map_err(|err| {
711 TemplateParseError::expression("Bad string pattern", node.span).with_source(err)
712 })
713 }
714 ExpressionKind::String(string) => Ok(StringPattern::Substring(string.clone())),
715 _ => Err(TemplateParseError::expression(
716 "Expected string pattern",
717 node.span,
718 )),
719 })
720}
721
722pub fn expect_lambda<'a, 'i>(
724 node: &'a ExpressionNode<'i>,
725) -> TemplateParseResult<&'a LambdaNode<'i>> {
726 catch_aliases_no_diagnostics(node, |node| match &node.kind {
727 ExpressionKind::Lambda(lambda) => Ok(lambda.as_ref()),
728 _ => Err(TemplateParseError::expression(
729 "Expected lambda expression",
730 node.span,
731 )),
732 })
733}
734
735pub fn catch_aliases<'a, 'i, T>(
738 diagnostics: &mut TemplateDiagnostics,
739 node: &'a ExpressionNode<'i>,
740 f: impl FnOnce(&mut TemplateDiagnostics, &'a ExpressionNode<'i>) -> TemplateParseResult<T>,
741) -> TemplateParseResult<T> {
742 let (node, stack) = skip_aliases(node);
743 if stack.is_empty() {
744 f(diagnostics, node)
745 } else {
746 let mut inner_diagnostics = TemplateDiagnostics::new();
747 let result = f(&mut inner_diagnostics, node);
748 diagnostics.extend_with(inner_diagnostics, |diag| attach_aliases_err(diag, &stack));
749 result.map_err(|err| attach_aliases_err(err, &stack))
750 }
751}
752
753fn catch_aliases_no_diagnostics<'a, 'i, T>(
754 node: &'a ExpressionNode<'i>,
755 f: impl FnOnce(&'a ExpressionNode<'i>) -> TemplateParseResult<T>,
756) -> TemplateParseResult<T> {
757 let (node, stack) = skip_aliases(node);
758 f(node).map_err(|err| attach_aliases_err(err, &stack))
759}
760
761fn skip_aliases<'a, 'i>(
762 mut node: &'a ExpressionNode<'i>,
763) -> (&'a ExpressionNode<'i>, Vec<(AliasId<'i>, pest::Span<'i>)>) {
764 let mut stack = Vec::new();
765 while let ExpressionKind::AliasExpanded(id, subst) = &node.kind {
766 stack.push((*id, node.span));
767 node = subst;
768 }
769 (node, stack)
770}
771
772fn attach_aliases_err(
773 err: TemplateParseError,
774 stack: &[(AliasId<'_>, pest::Span<'_>)],
775) -> TemplateParseError {
776 stack
777 .iter()
778 .rfold(err, |err, &(id, span)| err.within_alias_expansion(id, span))
779}
780
781pub fn lookup_function<'a, V>(
783 table: &'a HashMap<&str, V>,
784 function: &FunctionCallNode,
785) -> TemplateParseResult<&'a V> {
786 if let Some(value) = table.get(function.name) {
787 Ok(value)
788 } else {
789 let candidates = collect_similar(function.name, table.keys());
790 Err(TemplateParseError::with_span(
791 TemplateParseErrorKind::NoSuchFunction {
792 name: function.name.to_owned(),
793 candidates,
794 },
795 function.name_span,
796 ))
797 }
798}
799
800pub fn lookup_method<'a, V>(
802 type_name: impl Into<String>,
803 table: &'a HashMap<&str, V>,
804 function: &FunctionCallNode,
805) -> TemplateParseResult<&'a V> {
806 if let Some(value) = table.get(function.name) {
807 Ok(value)
808 } else {
809 let candidates = collect_similar(function.name, table.keys());
810 Err(TemplateParseError::with_span(
811 TemplateParseErrorKind::NoSuchMethod {
812 type_name: type_name.into(),
813 name: function.name.to_owned(),
814 candidates,
815 },
816 function.name_span,
817 ))
818 }
819}
820
821#[cfg(test)]
822mod tests {
823 use assert_matches::assert_matches;
824 use jj_lib::dsl_util::KeywordArgument;
825
826 use super::*;
827
828 #[derive(Debug)]
829 struct WithTemplateAliasesMap(TemplateAliasesMap);
830
831 impl WithTemplateAliasesMap {
832 fn parse<'i>(&'i self, template_text: &'i str) -> TemplateParseResult<ExpressionNode<'i>> {
833 parse(template_text, &self.0)
834 }
835
836 fn parse_normalized<'i>(&'i self, template_text: &'i str) -> ExpressionNode<'i> {
837 normalize_tree(self.parse(template_text).unwrap())
838 }
839 }
840
841 fn with_aliases(
842 aliases: impl IntoIterator<Item = (impl AsRef<str>, impl Into<String>)>,
843 ) -> WithTemplateAliasesMap {
844 let mut aliases_map = TemplateAliasesMap::new();
845 for (decl, defn) in aliases {
846 aliases_map.insert(decl, defn).unwrap();
847 }
848 WithTemplateAliasesMap(aliases_map)
849 }
850
851 fn parse_into_kind(template_text: &str) -> Result<ExpressionKind<'_>, TemplateParseErrorKind> {
852 parse_template(template_text)
853 .map(|node| node.kind)
854 .map_err(|err| err.kind)
855 }
856
857 fn parse_normalized(template_text: &str) -> ExpressionNode<'_> {
858 normalize_tree(parse_template(template_text).unwrap())
859 }
860
861 fn normalize_tree(node: ExpressionNode) -> ExpressionNode {
863 fn empty_span() -> pest::Span<'static> {
864 pest::Span::new("", 0, 0).unwrap()
865 }
866
867 fn normalize_list(nodes: Vec<ExpressionNode>) -> Vec<ExpressionNode> {
868 nodes.into_iter().map(normalize_tree).collect()
869 }
870
871 fn normalize_function_call(function: FunctionCallNode) -> FunctionCallNode {
872 FunctionCallNode {
873 name: function.name,
874 name_span: empty_span(),
875 args: normalize_list(function.args),
876 keyword_args: function
877 .keyword_args
878 .into_iter()
879 .map(|arg| KeywordArgument {
880 name: arg.name,
881 name_span: empty_span(),
882 value: normalize_tree(arg.value),
883 })
884 .collect(),
885 args_span: empty_span(),
886 }
887 }
888
889 let normalized_kind = match node.kind {
890 ExpressionKind::Identifier(_)
891 | ExpressionKind::Boolean(_)
892 | ExpressionKind::Integer(_)
893 | ExpressionKind::String(_) => node.kind,
894 ExpressionKind::Pattern { kind, value } => {
895 let value = Box::new(normalize_tree(*value));
896 ExpressionKind::Pattern { kind, value }
897 }
898 ExpressionKind::Unary(op, arg) => {
899 let arg = Box::new(normalize_tree(*arg));
900 ExpressionKind::Unary(op, arg)
901 }
902 ExpressionKind::Binary(op, lhs, rhs) => {
903 let lhs = Box::new(normalize_tree(*lhs));
904 let rhs = Box::new(normalize_tree(*rhs));
905 ExpressionKind::Binary(op, lhs, rhs)
906 }
907 ExpressionKind::Concat(nodes) => ExpressionKind::Concat(normalize_list(nodes)),
908 ExpressionKind::FunctionCall(function) => {
909 let function = Box::new(normalize_function_call(*function));
910 ExpressionKind::FunctionCall(function)
911 }
912 ExpressionKind::MethodCall(method) => {
913 let method = Box::new(MethodCallNode {
914 object: normalize_tree(method.object),
915 function: normalize_function_call(method.function),
916 });
917 ExpressionKind::MethodCall(method)
918 }
919 ExpressionKind::Lambda(lambda) => {
920 let lambda = Box::new(LambdaNode {
921 params: lambda.params,
922 params_span: empty_span(),
923 body: normalize_tree(lambda.body),
924 });
925 ExpressionKind::Lambda(lambda)
926 }
927 ExpressionKind::AliasExpanded(_, subst) => normalize_tree(*subst).kind,
928 };
929 ExpressionNode {
930 kind: normalized_kind,
931 span: empty_span(),
932 }
933 }
934
935 #[test]
936 fn test_parse_tree_eq() {
937 assert_eq!(
938 normalize_tree(parse_template(r#" commit_id.short(1 ) ++ description"#).unwrap()),
939 normalize_tree(parse_template(r#"commit_id.short( 1 )++(description)"#).unwrap()),
940 );
941 assert_ne!(
942 normalize_tree(parse_template(r#" "ab" "#).unwrap()),
943 normalize_tree(parse_template(r#" "a" ++ "b" "#).unwrap()),
944 );
945 assert_ne!(
946 normalize_tree(parse_template(r#" "foo" ++ "0" "#).unwrap()),
947 normalize_tree(parse_template(r#" "foo" ++ 0 "#).unwrap()),
948 );
949 }
950
951 #[test]
952 fn test_parse_whitespace() {
953 let ascii_whitespaces: String = ('\x00'..='\x7f')
954 .filter(char::is_ascii_whitespace)
955 .collect();
956 assert_eq!(
957 parse_normalized(&format!("{ascii_whitespaces}f()")),
958 parse_normalized("f()"),
959 );
960 assert_eq!(parse_normalized(&ascii_whitespaces), parse_normalized(""));
961 }
962
963 #[test]
964 fn test_parse_operator_syntax() {
965 assert_eq!(parse_normalized("!!x"), parse_normalized("!(!x)"));
967 assert_eq!(
968 parse_normalized("!x.f() || !g()"),
969 parse_normalized("(!(x.f())) || (!(g()))"),
970 );
971 assert_eq!(
972 parse_normalized("!x.f() <= !x.f()"),
973 parse_normalized("((!(x.f())) <= (!(x.f())))"),
974 );
975 assert_eq!(
976 parse_normalized("!x.f() < !x.f() == !x.f() >= !x.f() || !g() != !g()"),
977 parse_normalized(
978 "((!(x.f()) < (!(x.f()))) == ((!(x.f())) >= (!(x.f())))) || ((!(g())) != (!(g())))"
979 ),
980 );
981 assert_eq!(
982 parse_normalized("x.f() || y == y || z"),
983 parse_normalized("((x.f()) || (y == y)) || z"),
984 );
985 assert_eq!(
986 parse_normalized("x || y == y && z.h() > z"),
987 parse_normalized("x || ((y == y) && ((z.h()) > z))"),
988 );
989 assert_eq!(
990 parse_normalized("x == y || y != z && !z"),
991 parse_normalized("(x == y) || ((y != z) && (!z))"),
992 );
993 assert_eq!(
994 parse_normalized("a + b * c / d % e - -f == g"),
995 parse_normalized("((a + (((b * c) / d) % e)) - (-f)) == g"),
996 );
997
998 assert_eq!(
1001 parse_normalized(r"x && y ++ z"),
1002 parse_normalized(r"(x && y) ++ z"),
1003 );
1004 assert_eq!(
1005 parse_normalized(r"x ++ y || z"),
1006 parse_normalized(r"x ++ (y || z)"),
1007 );
1008 assert_eq!(
1009 parse_normalized(r"x == y ++ z"),
1010 parse_normalized(r"(x == y) ++ z"),
1011 );
1012 assert_eq!(
1013 parse_normalized(r"x != y ++ z"),
1014 parse_normalized(r"(x != y) ++ z"),
1015 );
1016
1017 assert_eq!(parse_template(" ! x ").unwrap().span.as_str(), "! x");
1019 assert_eq!(parse_template(" x ||y ").unwrap().span.as_str(), "x ||y");
1020 assert_eq!(parse_template(" (x) ").unwrap().span.as_str(), "(x)");
1021 assert_eq!(
1022 parse_template(" ! (x ||y) ").unwrap().span.as_str(),
1023 "! (x ||y)"
1024 );
1025 assert_eq!(
1026 parse_template("(x ++ y ) ").unwrap().span.as_str(),
1027 "(x ++ y )"
1028 );
1029 }
1030
1031 #[test]
1032 fn test_function_call_syntax() {
1033 fn unwrap_function_call(node: ExpressionNode<'_>) -> Box<FunctionCallNode<'_>> {
1034 match node.kind {
1035 ExpressionKind::FunctionCall(function) => function,
1036 _ => panic!("unexpected expression: {node:?}"),
1037 }
1038 }
1039
1040 assert!(parse_template(r#" "".first_line() "#).is_ok());
1042 assert!(parse_template(r#" "".first_line(,) "#).is_err());
1043
1044 assert!(parse_template(r#" "".contains("") "#).is_ok());
1046 assert!(parse_template(r#" "".contains("",) "#).is_ok());
1047 assert!(parse_template(r#" "".contains("" , ) "#).is_ok());
1048 assert!(parse_template(r#" "".contains(,"") "#).is_err());
1049 assert!(parse_template(r#" "".contains("",,) "#).is_err());
1050 assert!(parse_template(r#" "".contains("" , , ) "#).is_err());
1051 assert!(parse_template(r#" label("","") "#).is_ok());
1052 assert!(parse_template(r#" label("","",) "#).is_ok());
1053 assert!(parse_template(r#" label("",,"") "#).is_err());
1054
1055 assert!(parse_template("f(foo = bar)").is_ok());
1057 assert!(parse_template("f( foo=bar )").is_ok());
1058 assert!(parse_template("x.f(foo, bar=0, baz=1)").is_ok());
1059
1060 assert!(parse_template("false()").is_err());
1062 assert!(parse_template("f(false=0)").is_err());
1064 assert!(parse_template("f(false)").is_ok());
1066
1067 let function =
1069 unwrap_function_call(parse_template("foo( a, (b) , -(c), d = (e) )").unwrap());
1070 assert_eq!(function.name_span.as_str(), "foo");
1071 assert_eq!(function.args_span.as_str(), "a, (b) , -(c), d = (e) ");
1074 assert_eq!(function.args[0].span.as_str(), "a");
1075 assert_eq!(function.args[1].span.as_str(), "(b)");
1076 assert_eq!(function.args[2].span.as_str(), "-(c)");
1077 assert_eq!(function.keyword_args[0].name_span.as_str(), "d");
1078 assert_eq!(function.keyword_args[0].value.span.as_str(), "(e)");
1079 }
1080
1081 #[test]
1082 fn test_method_call_syntax() {
1083 assert_eq!(
1084 parse_normalized("x.f().g()"),
1085 parse_normalized("(x.f()).g()"),
1086 );
1087
1088 assert_eq!(parse_template(" x.f() ").unwrap().span.as_str(), "x.f()");
1090 assert_eq!(
1091 parse_template(" x.f().g() ").unwrap().span.as_str(),
1092 "x.f().g()",
1093 );
1094 }
1095
1096 #[test]
1097 fn test_lambda_syntax() {
1098 fn unwrap_lambda(node: ExpressionNode<'_>) -> Box<LambdaNode<'_>> {
1099 match node.kind {
1100 ExpressionKind::Lambda(lambda) => lambda,
1101 _ => panic!("unexpected expression: {node:?}"),
1102 }
1103 }
1104
1105 let lambda = unwrap_lambda(parse_template("|| a").unwrap());
1106 assert_eq!(lambda.params.len(), 0);
1107 assert_eq!(lambda.body.kind, ExpressionKind::Identifier("a"));
1108 let lambda = unwrap_lambda(parse_template("|foo| a").unwrap());
1109 assert_eq!(lambda.params.len(), 1);
1110 let lambda = unwrap_lambda(parse_template("|foo, b| a").unwrap());
1111 assert_eq!(lambda.params.len(), 2);
1112
1113 assert!(parse_template("||").is_err());
1115
1116 assert_eq!(
1118 parse_normalized("|| x ++ y"),
1119 parse_normalized("|| (x ++ y)"),
1120 );
1121 assert_eq!(
1122 parse_normalized("f( || x, || y)"),
1123 parse_normalized("f((|| x), (|| y))"),
1124 );
1125 assert_eq!(
1126 parse_normalized("|| x ++ || y"),
1127 parse_normalized("|| (x ++ (|| y))"),
1128 );
1129
1130 assert_eq!(parse_normalized("x||||y"), parse_normalized("x || (|| y)"));
1132 assert_eq!(parse_normalized("||||x"), parse_normalized("|| (|| x)"));
1133
1134 assert!(parse_template("|,| a").is_err());
1136 assert!(parse_template("|x,| a").is_ok());
1137 assert!(parse_template("|x , | a").is_ok());
1138 assert!(parse_template("|,x| a").is_err());
1139 assert!(parse_template("| x,y,| a").is_ok());
1140 assert!(parse_template("|x,,y| a").is_err());
1141
1142 assert_eq!(
1144 parse_template("|x, x| a").unwrap_err().kind,
1145 TemplateParseErrorKind::RedefinedFunctionParameter
1146 );
1147
1148 assert!(parse_template("|false| a").is_err());
1150 }
1151
1152 #[test]
1153 fn test_keyword_literal() {
1154 assert_eq!(parse_into_kind("false"), Ok(ExpressionKind::Boolean(false)));
1155 assert_eq!(parse_into_kind("(true)"), Ok(ExpressionKind::Boolean(true)));
1156 assert_eq!(
1158 parse_into_kind("False"),
1159 Ok(ExpressionKind::Identifier("False")),
1160 );
1161 assert_eq!(
1162 parse_into_kind("tRue"),
1163 Ok(ExpressionKind::Identifier("tRue")),
1164 );
1165 }
1166
1167 #[test]
1168 fn test_string_literal() {
1169 assert_eq!(
1171 parse_into_kind(r#" " " "#),
1172 Ok(ExpressionKind::String(" ".to_owned())),
1173 );
1174 assert_eq!(
1175 parse_into_kind(r#" ' ' "#),
1176 Ok(ExpressionKind::String(" ".to_owned())),
1177 );
1178
1179 assert_eq!(
1181 parse_into_kind(r#" "\t\r\n\"\\\0\e" "#),
1182 Ok(ExpressionKind::String("\t\r\n\"\\\0\u{1b}".to_owned())),
1183 );
1184
1185 assert_eq!(
1187 parse_into_kind(r#" "\y" "#),
1188 Err(TemplateParseErrorKind::SyntaxError),
1189 );
1190
1191 assert_eq!(
1193 parse_into_kind(r#" '' "#),
1194 Ok(ExpressionKind::String("".to_owned())),
1195 );
1196 assert_eq!(
1197 parse_into_kind(r#" 'a\n' "#),
1198 Ok(ExpressionKind::String(r"a\n".to_owned())),
1199 );
1200 assert_eq!(
1201 parse_into_kind(r#" '\' "#),
1202 Ok(ExpressionKind::String(r"\".to_owned())),
1203 );
1204 assert_eq!(
1205 parse_into_kind(r#" '"' "#),
1206 Ok(ExpressionKind::String(r#"""#.to_owned())),
1207 );
1208
1209 assert_eq!(
1211 parse_into_kind(r#""\x61\x65\x69\x6f\x75""#),
1212 Ok(ExpressionKind::String("aeiou".to_owned())),
1213 );
1214 assert_eq!(
1215 parse_into_kind(r#""\xe0\xe8\xec\xf0\xf9""#),
1216 Ok(ExpressionKind::String("àèìðù".to_owned())),
1217 );
1218 assert_eq!(
1219 parse_into_kind(r#""\x""#),
1220 Err(TemplateParseErrorKind::SyntaxError),
1221 );
1222 assert_eq!(
1223 parse_into_kind(r#""\xf""#),
1224 Err(TemplateParseErrorKind::SyntaxError),
1225 );
1226 assert_eq!(
1227 parse_into_kind(r#""\xgg""#),
1228 Err(TemplateParseErrorKind::SyntaxError),
1229 );
1230 }
1231
1232 #[test]
1233 fn test_string_pattern() {
1234 assert_matches!(
1235 parse_into_kind(r#"regex:"meow""#),
1236 Ok(ExpressionKind::Pattern { kind: "regex", value })
1237 if value.kind == ExpressionKind::String("meow".to_owned())
1238 );
1239 assert_matches!(
1240 parse_into_kind(r#"regex:'\r\n'"#),
1241 Ok(ExpressionKind::Pattern { kind: "regex", value })
1242 if value.kind == ExpressionKind::String(r#"\r\n"#.to_owned())
1243 );
1244 assert_matches!(
1245 parse_into_kind(r#"regex-i:'\r\n'"#),
1246 Ok(ExpressionKind::Pattern { kind: "regex-i", value })
1247 if value.kind == ExpressionKind::String(r#"\r\n"#.to_owned())
1248 );
1249 assert_matches!(
1250 parse_into_kind("regex:meow"),
1251 Ok(ExpressionKind::Pattern { kind: "regex", value })
1252 if value.kind == ExpressionKind::Identifier("meow")
1253 );
1254 assert_matches!(
1255 parse_into_kind("regex:false"),
1256 Err(TemplateParseErrorKind::Expression(_)),
1257 "boolean literal isn't an identifier"
1258 );
1259 assert_matches!(
1260 parse_into_kind("regex:0"),
1261 Err(TemplateParseErrorKind::SyntaxError),
1262 "integer literal isn't an identifier"
1263 );
1264 assert_eq!(
1265 parse_into_kind("regex: 'with spaces'"),
1266 Err(TemplateParseErrorKind::SyntaxError),
1267 "no spaces after"
1268 );
1269 assert_eq!(
1270 parse_into_kind("regex :'with spaces'"),
1271 Err(TemplateParseErrorKind::SyntaxError),
1272 "no spaces before either"
1273 );
1274 assert_eq!(
1275 parse_into_kind("regex : 'with spaces'"),
1276 Err(TemplateParseErrorKind::SyntaxError),
1277 "certainly not both"
1278 );
1279 }
1280
1281 #[test]
1282 fn test_integer_literal() {
1283 assert_eq!(parse_into_kind("0"), Ok(ExpressionKind::Integer(0)));
1284 assert_eq!(parse_into_kind("(42)"), Ok(ExpressionKind::Integer(42)));
1285 assert_eq!(
1286 parse_into_kind("00"),
1287 Err(TemplateParseErrorKind::SyntaxError),
1288 );
1289
1290 assert_eq!(
1291 parse_into_kind(&format!("{}", i64::MAX)),
1292 Ok(ExpressionKind::Integer(i64::MAX)),
1293 );
1294 assert_matches!(
1295 parse_into_kind(&format!("{}", (i64::MAX as u64) + 1)),
1296 Err(TemplateParseErrorKind::Expression(_))
1297 );
1298 }
1299
1300 #[test]
1301 fn test_parse_alias_decl() {
1302 let mut aliases_map = TemplateAliasesMap::new();
1303 aliases_map.insert("sym", r#""is symbol""#).unwrap();
1304 aliases_map.insert("func()", r#""is function 0""#).unwrap();
1305 aliases_map
1306 .insert("func(a, b)", r#""is function 2""#)
1307 .unwrap();
1308 aliases_map.insert("func(a)", r#""is function a""#).unwrap();
1309 aliases_map.insert("func(b)", r#""is function b""#).unwrap();
1310
1311 let (id, defn) = aliases_map.get_symbol("sym").unwrap();
1312 assert_eq!(id, AliasId::Symbol("sym"));
1313 assert_eq!(defn, r#""is symbol""#);
1314
1315 let (id, params, defn) = aliases_map.get_function("func", 0).unwrap();
1316 assert_eq!(id, AliasId::Function("func", &[]));
1317 assert!(params.is_empty());
1318 assert_eq!(defn, r#""is function 0""#);
1319
1320 let (id, params, defn) = aliases_map.get_function("func", 1).unwrap();
1321 assert_eq!(id, AliasId::Function("func", &["b".to_owned()]));
1322 assert_eq!(params, ["b"]);
1323 assert_eq!(defn, r#""is function b""#);
1324
1325 let (id, params, defn) = aliases_map.get_function("func", 2).unwrap();
1326 assert_eq!(
1327 id,
1328 AliasId::Function("func", &["a".to_owned(), "b".to_owned()])
1329 );
1330 assert_eq!(params, ["a", "b"]);
1331 assert_eq!(defn, r#""is function 2""#);
1332
1333 assert!(aliases_map.get_function("func", 3).is_none());
1334
1335 assert_eq!(
1337 aliases_map.insert("f(a, a)", r#""""#).unwrap_err().kind,
1338 TemplateParseErrorKind::RedefinedFunctionParameter
1339 );
1340
1341 assert!(aliases_map.insert("false", r#"""#).is_err());
1343 assert!(aliases_map.insert("true()", r#"""#).is_err());
1344 assert!(aliases_map.insert("f(false)", r#"""#).is_err());
1345
1346 assert!(aliases_map.insert("f(,)", r#"""#).is_err());
1348 assert!(aliases_map.insert("g(a,)", r#"""#).is_ok());
1350 assert!(aliases_map.insert("h(a , )", r#"""#).is_ok());
1351 assert!(aliases_map.insert("i(,a)", r#"""#).is_err());
1352 assert!(aliases_map.insert("j(a,,)", r#"""#).is_err());
1353 assert!(aliases_map.insert("k(a , , )", r#"""#).is_err());
1354 assert!(aliases_map.insert("l(a,b,)", r#"""#).is_ok());
1355 assert!(aliases_map.insert("m(a,,b)", r#"""#).is_err());
1356 }
1357
1358 #[test]
1359 fn test_expand_symbol_alias() {
1360 assert_eq!(
1361 with_aliases([("AB", "a ++ b")]).parse_normalized("AB ++ c"),
1362 parse_normalized("(a ++ b) ++ c"),
1363 );
1364 assert_eq!(
1365 with_aliases([("AB", "a ++ b")]).parse_normalized("if(AB, label(c, AB))"),
1366 parse_normalized("if((a ++ b), label(c, (a ++ b)))"),
1367 );
1368
1369 assert_eq!(
1372 with_aliases([("A", "'a'")]).parse_normalized("A:b"),
1373 parse_normalized("A:b")
1374 );
1375
1376 assert_eq!(
1378 with_aliases([("A", "'a'")]).parse_normalized("exact:A"),
1379 parse_normalized("exact:'a'")
1380 );
1381 assert_eq!(
1382 with_aliases([("A", "'a'")]).parse_normalized("exact:'A'"),
1383 parse_normalized("exact:'A'")
1384 );
1385
1386 assert_eq!(
1388 with_aliases([("A", "BC"), ("BC", "b ++ C"), ("C", "c")]).parse_normalized("A"),
1389 parse_normalized("b ++ c"),
1390 );
1391
1392 assert_eq!(
1394 with_aliases([("AB", "a || b")]).parse_normalized("AB ++ c"),
1395 parse_normalized("(a || b) ++ c"),
1396 );
1397
1398 assert_eq!(
1400 with_aliases([("A", "a"), ("B", "b")]).parse_normalized("A || !B"),
1401 parse_normalized("a || !b"),
1402 );
1403
1404 assert_eq!(
1406 with_aliases([("A", "a")]).parse_normalized("A.f()"),
1407 parse_normalized("a.f()"),
1408 );
1409 assert_eq!(
1410 with_aliases([("A", "a"), ("B", "b")]).parse_normalized("x.f(A, B)"),
1411 parse_normalized("x.f(a, b)"),
1412 );
1413
1414 assert_eq!(
1416 with_aliases([("A", "a")]).parse_normalized("|| A"),
1417 parse_normalized("|| a"),
1418 );
1419 assert_eq!(
1423 with_aliases([("A", "a ++ b")]).parse_normalized("|A| A"),
1424 parse_normalized("|A| (a ++ b)"),
1425 );
1426
1427 assert_eq!(
1429 with_aliases([("A", "A")]).parse("A").unwrap_err().kind,
1430 TemplateParseErrorKind::InAliasExpansion("A".to_owned()),
1431 );
1432 assert_eq!(
1433 with_aliases([("A", "B"), ("B", "b ++ C"), ("C", "c ++ B")])
1434 .parse("A")
1435 .unwrap_err()
1436 .kind,
1437 TemplateParseErrorKind::InAliasExpansion("A".to_owned()),
1438 );
1439
1440 assert_eq!(
1442 with_aliases([("A", "a(")]).parse("A").unwrap_err().kind,
1443 TemplateParseErrorKind::InAliasExpansion("A".to_owned()),
1444 );
1445 }
1446
1447 #[test]
1448 fn test_expand_function_alias() {
1449 assert_eq!(
1450 with_aliases([("F( )", "a")]).parse_normalized("F()"),
1451 parse_normalized("a"),
1452 );
1453 assert_eq!(
1454 with_aliases([("F( x )", "x")]).parse_normalized("F(a)"),
1455 parse_normalized("a"),
1456 );
1457 assert_eq!(
1458 with_aliases([("F( x, y )", "x ++ y")]).parse_normalized("F(a, b)"),
1459 parse_normalized("a ++ b"),
1460 );
1461
1462 assert_eq!(
1464 with_aliases([("F(x)", "F(x,b)"), ("F(x,y)", "x ++ y")]).parse_normalized("F(a)"),
1465 parse_normalized("a ++ b")
1466 );
1467
1468 assert_eq!(
1470 with_aliases([("F(x,y)", "if(x, y)")]).parse_normalized("F(a ++ y, b ++ x)"),
1471 parse_normalized("if((a ++ y), (b ++ x))"),
1472 );
1473 assert_eq!(
1475 with_aliases([("F(x)", "if(G(x), y)"), ("G(y)", "x ++ y")]).parse_normalized("F(a)"),
1476 parse_normalized("if((x ++ a), y)"),
1477 );
1478 assert_eq!(
1480 with_aliases([("F(x)", "if(G(x), y)"), ("G(y)", "x ++ y")]).parse_normalized("F(G(a))"),
1481 parse_normalized("if((x ++ (x ++ a)), y)"),
1482 );
1483
1484 assert_eq!(
1486 with_aliases([("F(X)", "X"), ("X", "x")]).parse_normalized("F(a) ++ X"),
1487 parse_normalized("a ++ x"),
1488 );
1489
1490 assert_eq!(
1492 with_aliases([("F(x)", "x ++ A"), ("A", "x")]).parse_normalized("F(a)"),
1493 parse_normalized("a ++ x"),
1494 );
1495
1496 assert_eq!(
1498 with_aliases([("A()", "A"), ("A", "a")]).parse_normalized("A()"),
1499 parse_normalized("a"),
1500 );
1501
1502 assert_eq!(
1504 with_aliases([("F()", "f()")]).parse_normalized("x.F()"),
1505 parse_normalized("x.F()"),
1506 );
1507
1508 assert_eq!(
1511 with_aliases([("F(x)", "|x| x")]).parse_normalized("F(a ++ b)"),
1512 parse_normalized("|x| (a ++ b)"),
1513 );
1514
1515 assert_matches!(
1517 with_aliases([("F()", "x")]).parse("F(a)").unwrap_err().kind,
1518 TemplateParseErrorKind::InvalidArguments { .. }
1519 );
1520 assert_matches!(
1521 with_aliases([("F(x)", "x")]).parse("F()").unwrap_err().kind,
1522 TemplateParseErrorKind::InvalidArguments { .. }
1523 );
1524 assert_matches!(
1525 with_aliases([("F(x,y)", "x ++ y")])
1526 .parse("F(a,b,c)")
1527 .unwrap_err()
1528 .kind,
1529 TemplateParseErrorKind::InvalidArguments { .. }
1530 );
1531
1532 assert_eq!(
1534 with_aliases([("F(x)", "G(x)"), ("G(x)", "H(x)"), ("H(x)", "F(x)")])
1535 .parse("F(a)")
1536 .unwrap_err()
1537 .kind,
1538 TemplateParseErrorKind::InAliasExpansion("F(x)".to_owned()),
1539 );
1540 assert_eq!(
1541 with_aliases([("F(x)", "F(x,b)"), ("F(x,y)", "F(x|y)")])
1542 .parse("F(a)")
1543 .unwrap_err()
1544 .kind,
1545 TemplateParseErrorKind::InAliasExpansion("F(x)".to_owned())
1546 );
1547 }
1548}