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::pattern_identifier => None,
101 Self::pattern => None,
102 Self::pattern_value_expression => None,
103 Self::primary => None,
104 Self::term => None,
105 Self::prefixed_term => None,
106 Self::expression => None,
107 Self::template => None,
108 Self::program => None,
109 Self::function_alias_declaration => None,
110 Self::pattern_alias_declaration => None,
111 Self::alias_declaration => None,
112 }
113 }
114}
115
116pub type TemplateDiagnostics = Diagnostics<TemplateParseError>;
118
119pub type TemplateParseResult<T> = Result<T, TemplateParseError>;
120
121#[derive(Debug, Error)]
122#[error("{pest_error}")]
123pub struct TemplateParseError {
124 kind: TemplateParseErrorKind,
125 pest_error: Box<pest::error::Error<Rule>>,
126 source: Option<Box<dyn error::Error + Send + Sync>>,
127}
128
129#[derive(Clone, Debug, Eq, Error, PartialEq)]
130pub enum TemplateParseErrorKind {
131 #[error("Syntax error")]
132 SyntaxError,
133 #[error("Keyword `{name}` doesn't exist")]
134 NoSuchKeyword {
135 name: String,
136 candidates: Vec<String>,
137 },
138 #[error("Function `{name}` doesn't exist")]
139 NoSuchFunction {
140 name: String,
141 candidates: Vec<String>,
142 },
143 #[error("Method `{name}` doesn't exist for type `{type_name}`")]
144 NoSuchMethod {
145 type_name: String,
146 name: String,
147 candidates: Vec<String>,
148 },
149 #[error("Function `{name}`: {message}")]
150 InvalidArguments { name: String, message: String },
151 #[error("Redefinition of function parameter")]
152 RedefinedFunctionParameter,
153 #[error("{0}")]
154 Expression(String),
155 #[error("In alias `{0}`")]
156 InAliasExpansion(String),
157 #[error("In function parameter `{0}`")]
158 InParameterExpansion(String),
159 #[error("Alias `{0}` expanded recursively")]
160 RecursiveAlias(String),
161}
162
163impl TemplateParseError {
164 pub fn with_span(kind: TemplateParseErrorKind, span: pest::Span<'_>) -> Self {
165 let message = kind.to_string();
166 let pest_error = Box::new(pest::error::Error::new_from_span(
167 pest::error::ErrorVariant::CustomError { message },
168 span,
169 ));
170 Self {
171 kind,
172 pest_error,
173 source: None,
174 }
175 }
176
177 pub fn with_source(mut self, source: impl Into<Box<dyn error::Error + Send + Sync>>) -> Self {
178 self.source = Some(source.into());
179 self
180 }
181
182 pub fn expected_type(expected: &str, actual: &str, span: pest::Span<'_>) -> Self {
183 let message =
184 format!("Expected expression of type `{expected}`, but actual type is `{actual}`");
185 Self::expression(message, span)
186 }
187
188 pub fn expression(message: impl Into<String>, span: pest::Span<'_>) -> Self {
190 Self::with_span(TemplateParseErrorKind::Expression(message.into()), span)
191 }
192
193 pub fn extend_keyword_candidates<I>(mut self, other_keywords: I) -> Self
196 where
197 I: IntoIterator,
198 I::Item: AsRef<str>,
199 {
200 if let TemplateParseErrorKind::NoSuchKeyword { name, candidates } = &mut self.kind {
201 let other_candidates = collect_similar(name, other_keywords);
202 *candidates = itertools::merge(mem::take(candidates), other_candidates)
203 .dedup()
204 .collect();
205 }
206 self
207 }
208
209 pub fn extend_function_candidates<I>(mut self, other_functions: I) -> Self
212 where
213 I: IntoIterator,
214 I::Item: AsRef<str>,
215 {
216 if let TemplateParseErrorKind::NoSuchFunction { name, candidates } = &mut self.kind {
217 let other_candidates = collect_similar(name, other_functions);
218 *candidates = itertools::merge(mem::take(candidates), other_candidates)
219 .dedup()
220 .collect();
221 }
222 self
223 }
224
225 pub fn extend_alias_candidates(self, aliases_map: &TemplateAliasesMap) -> Self {
227 self.extend_keyword_candidates(aliases_map.symbol_names())
228 .extend_function_candidates(aliases_map.function_names())
229 }
230
231 pub fn kind(&self) -> &TemplateParseErrorKind {
232 &self.kind
233 }
234
235 pub fn origin(&self) -> Option<&Self> {
237 self.source.as_ref().and_then(|e| e.downcast_ref())
238 }
239}
240
241impl AliasExpandError for TemplateParseError {
242 fn invalid_arguments(err: InvalidArguments<'_>) -> Self {
243 err.into()
244 }
245
246 fn recursive_expansion(id: AliasId<'_>, span: pest::Span<'_>) -> Self {
247 Self::with_span(TemplateParseErrorKind::RecursiveAlias(id.to_string()), span)
248 }
249
250 fn within_alias_expansion(self, id: AliasId<'_>, span: pest::Span<'_>) -> Self {
251 let kind = match id {
252 AliasId::Symbol(_) | AliasId::Pattern(..) | AliasId::Function(..) => {
253 TemplateParseErrorKind::InAliasExpansion(id.to_string())
254 }
255 AliasId::Parameter(_) => TemplateParseErrorKind::InParameterExpansion(id.to_string()),
256 };
257 Self::with_span(kind, span).with_source(self)
258 }
259}
260
261impl From<pest::error::Error<Rule>> for TemplateParseError {
262 fn from(err: pest::error::Error<Rule>) -> Self {
263 Self {
264 kind: TemplateParseErrorKind::SyntaxError,
265 pest_error: Box::new(rename_rules_in_pest_error(err)),
266 source: None,
267 }
268 }
269}
270
271impl From<InvalidArguments<'_>> for TemplateParseError {
272 fn from(err: InvalidArguments<'_>) -> Self {
273 let kind = TemplateParseErrorKind::InvalidArguments {
274 name: err.name.to_owned(),
275 message: err.message,
276 };
277 Self::with_span(kind, err.span)
278 }
279}
280
281fn rename_rules_in_pest_error(err: pest::error::Error<Rule>) -> pest::error::Error<Rule> {
282 err.renamed_rules(|rule| {
283 rule.to_symbol()
284 .map(|sym| format!("`{sym}`"))
285 .unwrap_or_else(|| format!("<{rule:?}>"))
286 })
287}
288
289#[derive(Clone, Debug, PartialEq)]
290pub enum ExpressionKind<'i> {
291 Identifier(&'i str),
292 Boolean(bool),
293 Integer(i64),
294 String(String),
295 Pattern(Box<PatternNode<'i>>),
297 Unary(UnaryOp, Box<ExpressionNode<'i>>),
298 Binary(BinaryOp, Box<ExpressionNode<'i>>, Box<ExpressionNode<'i>>),
299 Concat(Vec<ExpressionNode<'i>>),
300 FunctionCall(Box<FunctionCallNode<'i>>),
301 MethodCall(Box<MethodCallNode<'i>>),
302 Lambda(Box<LambdaNode<'i>>),
303 AliasExpanded(AliasId<'i>, Box<ExpressionNode<'i>>),
305}
306
307impl<'i> FoldableExpression<'i> for ExpressionKind<'i> {
308 fn fold<F>(self, folder: &mut F, span: pest::Span<'i>) -> Result<Self, F::Error>
309 where
310 F: ExpressionFolder<'i, Self> + ?Sized,
311 {
312 match self {
313 Self::Identifier(name) => folder.fold_identifier(name, span),
314 Self::Boolean(_) | Self::Integer(_) | Self::String(_) => Ok(self),
315 Self::Pattern(pattern) => folder.fold_pattern(pattern, span),
316 Self::Unary(op, arg) => {
317 let arg = Box::new(folder.fold_expression(*arg)?);
318 Ok(Self::Unary(op, arg))
319 }
320 Self::Binary(op, lhs, rhs) => {
321 let lhs = Box::new(folder.fold_expression(*lhs)?);
322 let rhs = Box::new(folder.fold_expression(*rhs)?);
323 Ok(Self::Binary(op, lhs, rhs))
324 }
325 Self::Concat(nodes) => Ok(Self::Concat(dsl_util::fold_expression_nodes(
326 folder, nodes,
327 )?)),
328 Self::FunctionCall(function) => folder.fold_function_call(function, span),
329 Self::MethodCall(method) => {
330 let method = Box::new(MethodCallNode {
332 object: folder.fold_expression(method.object)?,
333 function: dsl_util::fold_function_call_args(folder, method.function)?,
334 });
335 Ok(Self::MethodCall(method))
336 }
337 Self::Lambda(lambda) => {
338 let lambda = Box::new(LambdaNode {
339 params: lambda.params,
340 params_span: lambda.params_span,
341 body: folder.fold_expression(lambda.body)?,
342 });
343 Ok(Self::Lambda(lambda))
344 }
345 Self::AliasExpanded(id, subst) => {
346 let subst = Box::new(folder.fold_expression(*subst)?);
347 Ok(Self::AliasExpanded(id, subst))
348 }
349 }
350 }
351}
352
353impl<'i> AliasExpandableExpression<'i> for ExpressionKind<'i> {
354 fn identifier(name: &'i str) -> Self {
355 ExpressionKind::Identifier(name)
356 }
357
358 fn pattern(pattern: Box<PatternNode<'i>>) -> Self {
359 ExpressionKind::Pattern(pattern)
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>>;
411pub type PatternNode<'i> = dsl_util::PatternNode<'i, ExpressionKind<'i>>;
412
413#[derive(Clone, Debug, PartialEq)]
414pub struct MethodCallNode<'i> {
415 pub object: ExpressionNode<'i>,
416 pub function: FunctionCallNode<'i>,
417}
418
419#[derive(Clone, Debug, PartialEq)]
420pub struct LambdaNode<'i> {
421 pub params: Vec<&'i str>,
422 pub params_span: pest::Span<'i>,
423 pub body: ExpressionNode<'i>,
424}
425
426fn parse_identifier_or_literal(pair: Pair<Rule>) -> ExpressionKind {
427 assert!(matches!(
428 pair.as_rule(),
429 Rule::identifier | Rule::pattern_identifier
430 ));
431 match pair.as_str() {
432 "false" => ExpressionKind::Boolean(false),
433 "true" => ExpressionKind::Boolean(true),
434 name => ExpressionKind::Identifier(name),
435 }
436}
437
438fn parse_identifier_name(pair: Pair<'_, Rule>) -> TemplateParseResult<&str> {
439 let span = pair.as_span();
440 if let ExpressionKind::Identifier(name) = parse_identifier_or_literal(pair) {
441 Ok(name)
442 } else {
443 Err(TemplateParseError::expression("Expected identifier", span))
444 }
445}
446
447fn parse_formal_parameters(params_pair: Pair<'_, Rule>) -> TemplateParseResult<Vec<&str>> {
448 assert_eq!(params_pair.as_rule(), Rule::formal_parameters);
449 let params_span = params_pair.as_span();
450 let params: Vec<_> = params_pair
451 .into_inner()
452 .map(parse_identifier_name)
453 .try_collect()?;
454 if params.iter().all_unique() {
455 Ok(params)
456 } else {
457 Err(TemplateParseError::with_span(
458 TemplateParseErrorKind::RedefinedFunctionParameter,
459 params_span,
460 ))
461 }
462}
463
464fn parse_lambda_node(pair: Pair<Rule>) -> TemplateParseResult<LambdaNode> {
465 assert_eq!(pair.as_rule(), Rule::lambda);
466 let mut inner = pair.into_inner();
467 let params_pair = inner.next().unwrap();
468 let params_span = params_pair.as_span();
469 let body_pair = inner.next().unwrap();
470 let params = parse_formal_parameters(params_pair)?;
471 let body = parse_template_node(body_pair)?;
472 Ok(LambdaNode {
473 params,
474 params_span,
475 body,
476 })
477}
478
479fn parse_string_literal(pair: Pair<Rule>) -> String {
480 match pair.as_rule() {
481 Rule::string_literal => STRING_LITERAL_PARSER.parse(pair.into_inner()),
482 Rule::raw_string_literal => {
483 let [content] = pair.into_inner().collect_array().unwrap();
484 assert_eq!(content.as_rule(), Rule::raw_string_content);
485 content.as_str().to_owned()
486 }
487 other => panic!("unexpected string literal: {other:?}"),
488 }
489}
490
491fn parse_term_node(pair: Pair<Rule>) -> TemplateParseResult<ExpressionNode> {
492 assert_eq!(pair.as_rule(), Rule::term);
493 let mut inner = pair.into_inner();
494 let primary = inner.next().unwrap();
495 assert_eq!(primary.as_rule(), Rule::primary);
496 let primary_span = primary.as_span();
497 let expr = primary.into_inner().next().unwrap();
498 let primary_kind = match expr.as_rule() {
499 Rule::string_literal | Rule::raw_string_literal => {
500 ExpressionKind::String(parse_string_literal(expr))
501 }
502 Rule::integer_literal => {
503 let value = expr.as_str().parse().map_err(|err| {
504 TemplateParseError::expression("Invalid integer literal", expr.as_span())
505 .with_source(err)
506 })?;
507 ExpressionKind::Integer(value)
508 }
509 Rule::pattern => {
510 let [lhs, op, rhs] = expr.into_inner().collect_array().unwrap();
511 assert_eq!(op.as_rule(), Rule::pattern_kind_op);
512 assert_eq!(rhs.as_rule(), Rule::pattern_value_expression);
513 let name_span = lhs.as_span();
514 let pattern = Box::new(PatternNode {
515 name: parse_identifier_name(lhs)?,
516 name_span,
517 value: parse_expression_node(rhs)?,
518 });
519 ExpressionKind::Pattern(pattern)
520 }
521 Rule::identifier => parse_identifier_or_literal(expr),
522 Rule::function => {
523 let function = Box::new(FUNCTION_CALL_PARSER.parse(
524 expr,
525 parse_identifier_name,
526 parse_template_node,
527 )?);
528 ExpressionKind::FunctionCall(function)
529 }
530 Rule::lambda => {
531 let lambda = Box::new(parse_lambda_node(expr)?);
532 ExpressionKind::Lambda(lambda)
533 }
534 Rule::template => parse_template_node(expr)?.kind,
536 other => panic!("unexpected term: {other:?}"),
537 };
538 let primary_node = ExpressionNode::new(primary_kind, primary_span);
539 inner.try_fold(primary_node, |object, chain| {
540 assert_eq!(chain.as_rule(), Rule::function);
541 let span = object.span.start_pos().span(&chain.as_span().end_pos());
542 let method = Box::new(MethodCallNode {
543 object,
544 function: FUNCTION_CALL_PARSER.parse(
545 chain,
546 parse_identifier_name,
547 parse_template_node,
548 )?,
549 });
550 Ok(ExpressionNode::new(
551 ExpressionKind::MethodCall(method),
552 span,
553 ))
554 })
555}
556
557fn parse_expression_node(pair: Pair<Rule>) -> TemplateParseResult<ExpressionNode> {
558 static PRATT: LazyLock<PrattParser<Rule>> = LazyLock::new(|| {
559 PrattParser::new()
560 .op(Op::infix(Rule::logical_or_op, Assoc::Left))
561 .op(Op::infix(Rule::logical_and_op, Assoc::Left))
562 .op(Op::infix(Rule::eq_op, Assoc::Left) | Op::infix(Rule::ne_op, Assoc::Left))
563 .op(Op::infix(Rule::ge_op, Assoc::Left)
564 | Op::infix(Rule::gt_op, Assoc::Left)
565 | Op::infix(Rule::le_op, Assoc::Left)
566 | Op::infix(Rule::lt_op, Assoc::Left))
567 .op(Op::infix(Rule::add_op, Assoc::Left) | Op::infix(Rule::sub_op, Assoc::Left))
568 .op(Op::infix(Rule::mul_op, Assoc::Left)
569 | Op::infix(Rule::div_op, Assoc::Left)
570 | Op::infix(Rule::rem_op, Assoc::Left))
571 .op(Op::prefix(Rule::logical_not_op) | Op::prefix(Rule::negate_op))
572 });
573 PRATT
574 .map_primary(parse_term_node)
575 .map_prefix(|op, rhs| {
576 let op_kind = match op.as_rule() {
577 Rule::logical_not_op => UnaryOp::LogicalNot,
578 Rule::negate_op => UnaryOp::Negate,
579 r => panic!("unexpected prefix operator rule {r:?}"),
580 };
581 let rhs = Box::new(rhs?);
582 let span = op.as_span().start_pos().span(&rhs.span.end_pos());
583 let expr = ExpressionKind::Unary(op_kind, rhs);
584 Ok(ExpressionNode::new(expr, span))
585 })
586 .map_infix(|lhs, op, rhs| {
587 let op_kind = match op.as_rule() {
588 Rule::logical_or_op => BinaryOp::LogicalOr,
589 Rule::logical_and_op => BinaryOp::LogicalAnd,
590 Rule::eq_op => BinaryOp::Eq,
591 Rule::ne_op => BinaryOp::Ne,
592 Rule::ge_op => BinaryOp::Ge,
593 Rule::gt_op => BinaryOp::Gt,
594 Rule::le_op => BinaryOp::Le,
595 Rule::lt_op => BinaryOp::Lt,
596 Rule::add_op => BinaryOp::Add,
597 Rule::sub_op => BinaryOp::Sub,
598 Rule::mul_op => BinaryOp::Mul,
599 Rule::div_op => BinaryOp::Div,
600 Rule::rem_op => BinaryOp::Rem,
601 r => panic!("unexpected infix operator rule {r:?}"),
602 };
603 let lhs = Box::new(lhs?);
604 let rhs = Box::new(rhs?);
605 let span = lhs.span.start_pos().span(&rhs.span.end_pos());
606 let expr = ExpressionKind::Binary(op_kind, lhs, rhs);
607 Ok(ExpressionNode::new(expr, span))
608 })
609 .parse(pair.into_inner())
610}
611
612fn parse_template_node(pair: Pair<Rule>) -> TemplateParseResult<ExpressionNode> {
613 assert_eq!(pair.as_rule(), Rule::template);
614 let span = pair.as_span();
615 let inner = pair.into_inner();
616 let mut nodes: Vec<_> = inner
617 .filter_map(|pair| match pair.as_rule() {
618 Rule::concat_op => None,
619 Rule::expression => Some(parse_expression_node(pair)),
620 r => panic!("unexpected template item rule {r:?}"),
621 })
622 .try_collect()?;
623 if nodes.len() == 1 {
624 Ok(nodes.pop().unwrap())
625 } else {
626 Ok(ExpressionNode::new(ExpressionKind::Concat(nodes), span))
627 }
628}
629
630pub fn parse_template(template_text: &str) -> TemplateParseResult<ExpressionNode<'_>> {
632 let mut pairs: Pairs<Rule> = TemplateParser::parse(Rule::program, template_text)?;
633 let first_pair = pairs.next().unwrap();
634 if first_pair.as_rule() == Rule::EOI {
635 let span = first_pair.as_span();
636 Ok(ExpressionNode::new(ExpressionKind::Concat(vec![]), span))
637 } else {
638 parse_template_node(first_pair)
639 }
640}
641
642pub type TemplateAliasesMap = AliasesMap<TemplateAliasParser, String>;
643
644#[derive(Clone, Debug, Default)]
645pub struct TemplateAliasParser;
646
647impl AliasDeclarationParser for TemplateAliasParser {
648 type Error = TemplateParseError;
649
650 fn parse_declaration(&self, source: &str) -> Result<AliasDeclaration, Self::Error> {
651 let mut pairs = TemplateParser::parse(Rule::alias_declaration, source)?;
652 let first = pairs.next().unwrap();
653 match first.as_rule() {
654 Rule::identifier => {
655 let name = parse_identifier_name(first)?.to_owned();
656 Ok(AliasDeclaration::Symbol(name))
657 }
658 Rule::pattern_alias_declaration => {
659 let [name_pair, op, param_pair] = first.into_inner().collect_array().unwrap();
660 assert_eq!(op.as_rule(), Rule::pattern_kind_op);
661 let name = parse_identifier_name(name_pair)?.to_owned();
662 let param = parse_identifier_name(param_pair)?.to_owned();
663 Ok(AliasDeclaration::Pattern(name, param))
664 }
665 Rule::function_alias_declaration => {
666 let mut inner = first.into_inner();
667 let name_pair = inner.next().unwrap();
668 let params_pair = inner.next().unwrap();
669 let name = parse_identifier_name(name_pair)?.to_owned();
670 let params = parse_formal_parameters(params_pair)?
671 .into_iter()
672 .map(|s| s.to_owned())
673 .collect();
674 Ok(AliasDeclaration::Function(name, params))
675 }
676 r => panic!("unexpected alias declaration rule {r:?}"),
677 }
678 }
679}
680
681impl AliasDefinitionParser for TemplateAliasParser {
682 type Output<'i> = ExpressionKind<'i>;
683 type Error = TemplateParseError;
684
685 fn parse_definition<'i>(&self, source: &'i str) -> Result<ExpressionNode<'i>, Self::Error> {
686 parse_template(source)
687 }
688}
689
690pub fn parse<'i>(
694 template_text: &'i str,
695 aliases_map: &'i TemplateAliasesMap,
696) -> TemplateParseResult<ExpressionNode<'i>> {
697 let node = parse_template(template_text)?;
698 dsl_util::expand_aliases(node, aliases_map)
699}
700
701pub fn expect_string_literal<'a>(node: &'a ExpressionNode<'_>) -> TemplateParseResult<&'a str> {
703 catch_aliases_no_diagnostics(node, |node| match &node.kind {
704 ExpressionKind::String(s) => Ok(s.as_str()),
705 _ => Err(TemplateParseError::expression(
706 "Expected string literal",
707 node.span,
708 )),
709 })
710}
711
712pub fn expect_string_pattern(node: &ExpressionNode<'_>) -> TemplateParseResult<StringPattern> {
716 catch_aliases_no_diagnostics(node, |node| match &node.kind {
717 ExpressionKind::Pattern(pattern) => {
718 let value = expect_string_literal(&pattern.value)?;
719 StringPattern::from_str_kind(value, pattern.name).map_err(|err| {
720 TemplateParseError::expression("Bad string pattern", node.span).with_source(err)
721 })
722 }
723 ExpressionKind::String(string) => Ok(StringPattern::Substring(string.clone())),
724 _ => Err(TemplateParseError::expression(
725 "Expected string pattern",
726 node.span,
727 )),
728 })
729}
730
731pub fn expect_lambda<'a, 'i>(
733 node: &'a ExpressionNode<'i>,
734) -> TemplateParseResult<&'a LambdaNode<'i>> {
735 catch_aliases_no_diagnostics(node, |node| match &node.kind {
736 ExpressionKind::Lambda(lambda) => Ok(lambda.as_ref()),
737 _ => Err(TemplateParseError::expression(
738 "Expected lambda expression",
739 node.span,
740 )),
741 })
742}
743
744pub fn catch_aliases<'a, 'i, T>(
747 diagnostics: &mut TemplateDiagnostics,
748 node: &'a ExpressionNode<'i>,
749 f: impl FnOnce(&mut TemplateDiagnostics, &'a ExpressionNode<'i>) -> TemplateParseResult<T>,
750) -> TemplateParseResult<T> {
751 let (node, stack) = skip_aliases(node);
752 if stack.is_empty() {
753 f(diagnostics, node)
754 } else {
755 let mut inner_diagnostics = TemplateDiagnostics::new();
756 let result = f(&mut inner_diagnostics, node);
757 diagnostics.extend_with(inner_diagnostics, |diag| attach_aliases_err(diag, &stack));
758 result.map_err(|err| attach_aliases_err(err, &stack))
759 }
760}
761
762fn catch_aliases_no_diagnostics<'a, 'i, T>(
763 node: &'a ExpressionNode<'i>,
764 f: impl FnOnce(&'a ExpressionNode<'i>) -> TemplateParseResult<T>,
765) -> TemplateParseResult<T> {
766 let (node, stack) = skip_aliases(node);
767 f(node).map_err(|err| attach_aliases_err(err, &stack))
768}
769
770fn skip_aliases<'a, 'i>(
771 mut node: &'a ExpressionNode<'i>,
772) -> (&'a ExpressionNode<'i>, Vec<(AliasId<'i>, pest::Span<'i>)>) {
773 let mut stack = Vec::new();
774 while let ExpressionKind::AliasExpanded(id, subst) = &node.kind {
775 stack.push((*id, node.span));
776 node = subst;
777 }
778 (node, stack)
779}
780
781fn attach_aliases_err(
782 err: TemplateParseError,
783 stack: &[(AliasId<'_>, pest::Span<'_>)],
784) -> TemplateParseError {
785 stack
786 .iter()
787 .rfold(err, |err, &(id, span)| err.within_alias_expansion(id, span))
788}
789
790pub fn lookup_function<'a, V>(
792 table: &'a HashMap<&str, V>,
793 function: &FunctionCallNode,
794) -> TemplateParseResult<&'a V> {
795 if let Some(value) = table.get(function.name) {
796 Ok(value)
797 } else {
798 let candidates = collect_similar(function.name, table.keys());
799 Err(TemplateParseError::with_span(
800 TemplateParseErrorKind::NoSuchFunction {
801 name: function.name.to_owned(),
802 candidates,
803 },
804 function.name_span,
805 ))
806 }
807}
808
809pub fn lookup_method<'a, V>(
811 type_name: impl Into<String>,
812 table: &'a HashMap<&str, V>,
813 function: &FunctionCallNode,
814) -> TemplateParseResult<&'a V> {
815 if let Some(value) = table.get(function.name) {
816 Ok(value)
817 } else {
818 let candidates = collect_similar(function.name, table.keys());
819 Err(TemplateParseError::with_span(
820 TemplateParseErrorKind::NoSuchMethod {
821 type_name: type_name.into(),
822 name: function.name.to_owned(),
823 candidates,
824 },
825 function.name_span,
826 ))
827 }
828}
829
830#[cfg(test)]
831mod tests {
832 use assert_matches::assert_matches;
833 use jj_lib::dsl_util::KeywordArgument;
834
835 use super::*;
836
837 #[derive(Debug)]
838 struct WithTemplateAliasesMap(TemplateAliasesMap);
839
840 impl WithTemplateAliasesMap {
841 fn parse<'i>(&'i self, template_text: &'i str) -> TemplateParseResult<ExpressionNode<'i>> {
842 parse(template_text, &self.0)
843 }
844
845 fn parse_normalized<'i>(&'i self, template_text: &'i str) -> ExpressionNode<'i> {
846 normalize_tree(self.parse(template_text).unwrap())
847 }
848 }
849
850 fn with_aliases(
851 aliases: impl IntoIterator<Item = (impl AsRef<str>, impl Into<String>)>,
852 ) -> WithTemplateAliasesMap {
853 let mut aliases_map = TemplateAliasesMap::new();
854 for (decl, defn) in aliases {
855 aliases_map.insert(decl, defn).unwrap();
856 }
857 WithTemplateAliasesMap(aliases_map)
858 }
859
860 fn parse_into_kind(template_text: &str) -> Result<ExpressionKind<'_>, TemplateParseErrorKind> {
861 parse_template(template_text)
862 .map(|node| node.kind)
863 .map_err(|err| err.kind)
864 }
865
866 fn parse_normalized(template_text: &str) -> ExpressionNode<'_> {
867 normalize_tree(parse_template(template_text).unwrap())
868 }
869
870 fn normalize_tree(node: ExpressionNode) -> ExpressionNode {
872 fn empty_span() -> pest::Span<'static> {
873 pest::Span::new("", 0, 0).unwrap()
874 }
875
876 fn normalize_list(nodes: Vec<ExpressionNode>) -> Vec<ExpressionNode> {
877 nodes.into_iter().map(normalize_tree).collect()
878 }
879
880 fn normalize_function_call(function: FunctionCallNode) -> FunctionCallNode {
881 FunctionCallNode {
882 name: function.name,
883 name_span: empty_span(),
884 args: normalize_list(function.args),
885 keyword_args: function
886 .keyword_args
887 .into_iter()
888 .map(|arg| KeywordArgument {
889 name: arg.name,
890 name_span: empty_span(),
891 value: normalize_tree(arg.value),
892 })
893 .collect(),
894 args_span: empty_span(),
895 }
896 }
897
898 let normalized_kind = match node.kind {
899 ExpressionKind::Identifier(_)
900 | ExpressionKind::Boolean(_)
901 | ExpressionKind::Integer(_)
902 | ExpressionKind::String(_) => node.kind,
903 ExpressionKind::Pattern(pattern) => {
904 let pattern = Box::new(PatternNode {
905 name: pattern.name,
906 name_span: empty_span(),
907 value: normalize_tree(pattern.value),
908 });
909 ExpressionKind::Pattern(pattern)
910 }
911 ExpressionKind::Unary(op, arg) => {
912 let arg = Box::new(normalize_tree(*arg));
913 ExpressionKind::Unary(op, arg)
914 }
915 ExpressionKind::Binary(op, lhs, rhs) => {
916 let lhs = Box::new(normalize_tree(*lhs));
917 let rhs = Box::new(normalize_tree(*rhs));
918 ExpressionKind::Binary(op, lhs, rhs)
919 }
920 ExpressionKind::Concat(nodes) => ExpressionKind::Concat(normalize_list(nodes)),
921 ExpressionKind::FunctionCall(function) => {
922 let function = Box::new(normalize_function_call(*function));
923 ExpressionKind::FunctionCall(function)
924 }
925 ExpressionKind::MethodCall(method) => {
926 let method = Box::new(MethodCallNode {
927 object: normalize_tree(method.object),
928 function: normalize_function_call(method.function),
929 });
930 ExpressionKind::MethodCall(method)
931 }
932 ExpressionKind::Lambda(lambda) => {
933 let lambda = Box::new(LambdaNode {
934 params: lambda.params,
935 params_span: empty_span(),
936 body: normalize_tree(lambda.body),
937 });
938 ExpressionKind::Lambda(lambda)
939 }
940 ExpressionKind::AliasExpanded(_, subst) => normalize_tree(*subst).kind,
941 };
942 ExpressionNode {
943 kind: normalized_kind,
944 span: empty_span(),
945 }
946 }
947
948 #[test]
949 fn test_parse_tree_eq() {
950 assert_eq!(
951 normalize_tree(parse_template(r#" commit_id.short(1 ) ++ description"#).unwrap()),
952 normalize_tree(parse_template(r#"commit_id.short( 1 )++(description)"#).unwrap()),
953 );
954 assert_ne!(
955 normalize_tree(parse_template(r#" "ab" "#).unwrap()),
956 normalize_tree(parse_template(r#" "a" ++ "b" "#).unwrap()),
957 );
958 assert_ne!(
959 normalize_tree(parse_template(r#" "foo" ++ "0" "#).unwrap()),
960 normalize_tree(parse_template(r#" "foo" ++ 0 "#).unwrap()),
961 );
962 }
963
964 #[test]
965 fn test_parse_whitespace() {
966 let ascii_whitespaces: String = ('\x00'..='\x7f')
967 .filter(char::is_ascii_whitespace)
968 .collect();
969 assert_eq!(
970 parse_normalized(&format!("{ascii_whitespaces}f()")),
971 parse_normalized("f()"),
972 );
973 assert_eq!(parse_normalized(&ascii_whitespaces), parse_normalized(""));
974 }
975
976 #[test]
977 fn test_parse_operator_syntax() {
978 assert_eq!(parse_normalized("!!x"), parse_normalized("!(!x)"));
980 assert_eq!(
981 parse_normalized("!x.f() || !g()"),
982 parse_normalized("(!(x.f())) || (!(g()))"),
983 );
984 assert_eq!(
985 parse_normalized("!x.f() <= !x.f()"),
986 parse_normalized("((!(x.f())) <= (!(x.f())))"),
987 );
988 assert_eq!(
989 parse_normalized("!x.f() < !x.f() == !x.f() >= !x.f() || !g() != !g()"),
990 parse_normalized(
991 "((!(x.f()) < (!(x.f()))) == ((!(x.f())) >= (!(x.f())))) || ((!(g())) != (!(g())))"
992 ),
993 );
994 assert_eq!(
995 parse_normalized("x.f() || y == y || z"),
996 parse_normalized("((x.f()) || (y == y)) || z"),
997 );
998 assert_eq!(
999 parse_normalized("x || y == y && z.h() > z"),
1000 parse_normalized("x || ((y == y) && ((z.h()) > z))"),
1001 );
1002 assert_eq!(
1003 parse_normalized("x == y || y != z && !z"),
1004 parse_normalized("(x == y) || ((y != z) && (!z))"),
1005 );
1006 assert_eq!(
1007 parse_normalized("a + b * c / d % e - -f == g"),
1008 parse_normalized("((a + (((b * c) / d) % e)) - (-f)) == g"),
1009 );
1010
1011 assert_eq!(
1014 parse_normalized(r"x && y ++ z"),
1015 parse_normalized(r"(x && y) ++ z"),
1016 );
1017 assert_eq!(
1018 parse_normalized(r"x ++ y || z"),
1019 parse_normalized(r"x ++ (y || z)"),
1020 );
1021 assert_eq!(
1022 parse_normalized(r"x == y ++ z"),
1023 parse_normalized(r"(x == y) ++ z"),
1024 );
1025 assert_eq!(
1026 parse_normalized(r"x != y ++ z"),
1027 parse_normalized(r"(x != y) ++ z"),
1028 );
1029
1030 assert_eq!(parse_template(" ! x ").unwrap().span.as_str(), "! x");
1032 assert_eq!(parse_template(" x ||y ").unwrap().span.as_str(), "x ||y");
1033 assert_eq!(parse_template(" (x) ").unwrap().span.as_str(), "(x)");
1034 assert_eq!(
1035 parse_template(" ! (x ||y) ").unwrap().span.as_str(),
1036 "! (x ||y)"
1037 );
1038 assert_eq!(
1039 parse_template("(x ++ y ) ").unwrap().span.as_str(),
1040 "(x ++ y )"
1041 );
1042 }
1043
1044 #[test]
1045 fn test_function_call_syntax() {
1046 fn unwrap_function_call(node: ExpressionNode<'_>) -> Box<FunctionCallNode<'_>> {
1047 match node.kind {
1048 ExpressionKind::FunctionCall(function) => function,
1049 _ => panic!("unexpected expression: {node:?}"),
1050 }
1051 }
1052
1053 assert!(parse_template(r#" "".first_line() "#).is_ok());
1055 assert!(parse_template(r#" "".first_line(,) "#).is_err());
1056
1057 assert!(parse_template(r#" "".contains("") "#).is_ok());
1059 assert!(parse_template(r#" "".contains("",) "#).is_ok());
1060 assert!(parse_template(r#" "".contains("" , ) "#).is_ok());
1061 assert!(parse_template(r#" "".contains(,"") "#).is_err());
1062 assert!(parse_template(r#" "".contains("",,) "#).is_err());
1063 assert!(parse_template(r#" "".contains("" , , ) "#).is_err());
1064 assert!(parse_template(r#" label("","") "#).is_ok());
1065 assert!(parse_template(r#" label("","",) "#).is_ok());
1066 assert!(parse_template(r#" label("",,"") "#).is_err());
1067
1068 assert!(parse_template("f(foo = bar)").is_ok());
1070 assert!(parse_template("f( foo=bar )").is_ok());
1071 assert!(parse_template("x.f(foo, bar=0, baz=1)").is_ok());
1072
1073 assert!(parse_template("false()").is_err());
1075 assert!(parse_template("f(false=0)").is_err());
1077 assert!(parse_template("f(false)").is_ok());
1079
1080 let function =
1082 unwrap_function_call(parse_template("foo( a, (b) , -(c), d = (e) )").unwrap());
1083 assert_eq!(function.name_span.as_str(), "foo");
1084 assert_eq!(function.args_span.as_str(), "a, (b) , -(c), d = (e) ");
1087 assert_eq!(function.args[0].span.as_str(), "a");
1088 assert_eq!(function.args[1].span.as_str(), "(b)");
1089 assert_eq!(function.args[2].span.as_str(), "-(c)");
1090 assert_eq!(function.keyword_args[0].name_span.as_str(), "d");
1091 assert_eq!(function.keyword_args[0].value.span.as_str(), "(e)");
1092 }
1093
1094 #[test]
1095 fn test_method_call_syntax() {
1096 assert_eq!(
1097 parse_normalized("x.f().g()"),
1098 parse_normalized("(x.f()).g()"),
1099 );
1100
1101 assert_eq!(parse_template(" x.f() ").unwrap().span.as_str(), "x.f()");
1103 assert_eq!(
1104 parse_template(" x.f().g() ").unwrap().span.as_str(),
1105 "x.f().g()",
1106 );
1107 }
1108
1109 #[test]
1110 fn test_lambda_syntax() {
1111 fn unwrap_lambda(node: ExpressionNode<'_>) -> Box<LambdaNode<'_>> {
1112 match node.kind {
1113 ExpressionKind::Lambda(lambda) => lambda,
1114 _ => panic!("unexpected expression: {node:?}"),
1115 }
1116 }
1117
1118 let lambda = unwrap_lambda(parse_template("|| a").unwrap());
1119 assert_eq!(lambda.params.len(), 0);
1120 assert_eq!(lambda.body.kind, ExpressionKind::Identifier("a"));
1121 let lambda = unwrap_lambda(parse_template("|foo| a").unwrap());
1122 assert_eq!(lambda.params.len(), 1);
1123 let lambda = unwrap_lambda(parse_template("|foo, b| a").unwrap());
1124 assert_eq!(lambda.params.len(), 2);
1125
1126 assert!(parse_template("||").is_err());
1128
1129 assert_eq!(
1131 parse_normalized("|| x ++ y"),
1132 parse_normalized("|| (x ++ y)"),
1133 );
1134 assert_eq!(
1135 parse_normalized("f( || x, || y)"),
1136 parse_normalized("f((|| x), (|| y))"),
1137 );
1138 assert_eq!(
1139 parse_normalized("|| x ++ || y"),
1140 parse_normalized("|| (x ++ (|| y))"),
1141 );
1142
1143 assert_eq!(parse_normalized("x||||y"), parse_normalized("x || (|| y)"));
1145 assert_eq!(parse_normalized("||||x"), parse_normalized("|| (|| x)"));
1146
1147 assert!(parse_template("|,| a").is_err());
1149 assert!(parse_template("|x,| a").is_ok());
1150 assert!(parse_template("|x , | a").is_ok());
1151 assert!(parse_template("|,x| a").is_err());
1152 assert!(parse_template("| x,y,| a").is_ok());
1153 assert!(parse_template("|x,,y| a").is_err());
1154
1155 assert_eq!(
1157 parse_template("|x, x| a").unwrap_err().kind,
1158 TemplateParseErrorKind::RedefinedFunctionParameter
1159 );
1160
1161 assert!(parse_template("|false| a").is_err());
1163 }
1164
1165 #[test]
1166 fn test_keyword_literal() {
1167 assert_eq!(parse_into_kind("false"), Ok(ExpressionKind::Boolean(false)));
1168 assert_eq!(parse_into_kind("(true)"), Ok(ExpressionKind::Boolean(true)));
1169 assert_eq!(
1171 parse_into_kind("False"),
1172 Ok(ExpressionKind::Identifier("False")),
1173 );
1174 assert_eq!(
1175 parse_into_kind("tRue"),
1176 Ok(ExpressionKind::Identifier("tRue")),
1177 );
1178 assert_matches!(
1180 parse_into_kind("false:'x'"),
1181 Err(TemplateParseErrorKind::Expression(_))
1182 );
1183 assert_matches!(
1184 parse_into_kind("true()"),
1185 Err(TemplateParseErrorKind::Expression(_))
1186 );
1187 }
1188
1189 #[test]
1190 fn test_string_literal() {
1191 assert_eq!(
1193 parse_into_kind(r#" " " "#),
1194 Ok(ExpressionKind::String(" ".to_owned())),
1195 );
1196 assert_eq!(
1197 parse_into_kind(r#" ' ' "#),
1198 Ok(ExpressionKind::String(" ".to_owned())),
1199 );
1200
1201 assert_eq!(
1203 parse_into_kind(r#" "\t\r\n\"\\\0\e" "#),
1204 Ok(ExpressionKind::String("\t\r\n\"\\\0\u{1b}".to_owned())),
1205 );
1206
1207 assert_eq!(
1209 parse_into_kind(r#" "\y" "#),
1210 Err(TemplateParseErrorKind::SyntaxError),
1211 );
1212
1213 assert_eq!(
1215 parse_into_kind(r#" '' "#),
1216 Ok(ExpressionKind::String("".to_owned())),
1217 );
1218 assert_eq!(
1219 parse_into_kind(r#" 'a\n' "#),
1220 Ok(ExpressionKind::String(r"a\n".to_owned())),
1221 );
1222 assert_eq!(
1223 parse_into_kind(r#" '\' "#),
1224 Ok(ExpressionKind::String(r"\".to_owned())),
1225 );
1226 assert_eq!(
1227 parse_into_kind(r#" '"' "#),
1228 Ok(ExpressionKind::String(r#"""#.to_owned())),
1229 );
1230
1231 assert_eq!(
1233 parse_into_kind(r#""\x61\x65\x69\x6f\x75""#),
1234 Ok(ExpressionKind::String("aeiou".to_owned())),
1235 );
1236 assert_eq!(
1237 parse_into_kind(r#""\xe0\xe8\xec\xf0\xf9""#),
1238 Ok(ExpressionKind::String("àèìðù".to_owned())),
1239 );
1240 assert_eq!(
1241 parse_into_kind(r#""\x""#),
1242 Err(TemplateParseErrorKind::SyntaxError),
1243 );
1244 assert_eq!(
1245 parse_into_kind(r#""\xf""#),
1246 Err(TemplateParseErrorKind::SyntaxError),
1247 );
1248 assert_eq!(
1249 parse_into_kind(r#""\xgg""#),
1250 Err(TemplateParseErrorKind::SyntaxError),
1251 );
1252 }
1253
1254 #[test]
1255 fn test_pattern() {
1256 fn unwrap_pattern(kind: ExpressionKind<'_>) -> (&str, ExpressionKind<'_>) {
1257 match kind {
1258 ExpressionKind::Pattern(pattern) => (pattern.name, pattern.value.kind),
1259 _ => panic!("unexpected expression: {kind:?}"),
1260 }
1261 }
1262
1263 assert_eq!(
1264 unwrap_pattern(parse_into_kind(r#"regex:"meow""#).unwrap()),
1265 ("regex", ExpressionKind::String("meow".to_owned()))
1266 );
1267 assert_eq!(
1268 unwrap_pattern(parse_into_kind(r#"regex:'\r\n'"#).unwrap()),
1269 ("regex", ExpressionKind::String(r#"\r\n"#.to_owned()))
1270 );
1271 assert_eq!(
1272 unwrap_pattern(parse_into_kind(r#"regex-i:'\r\n'"#).unwrap()),
1273 ("regex-i", ExpressionKind::String(r#"\r\n"#.to_owned()))
1274 );
1275 assert_eq!(
1276 unwrap_pattern(parse_into_kind("regex:meow").unwrap()),
1277 ("regex", ExpressionKind::Identifier("meow"))
1278 );
1279 assert_eq!(
1280 unwrap_pattern(parse_into_kind("regex:false").unwrap()),
1281 ("regex", ExpressionKind::Boolean(false))
1282 );
1283 assert_eq!(
1284 unwrap_pattern(parse_into_kind("regex:0").unwrap()),
1285 ("regex", ExpressionKind::Integer(0))
1286 );
1287
1288 assert_eq!(
1290 parse_into_kind("regex: 'with spaces'"),
1291 Err(TemplateParseErrorKind::SyntaxError),
1292 "no spaces after"
1293 );
1294 assert_eq!(
1295 parse_into_kind("regex :'with spaces'"),
1296 Err(TemplateParseErrorKind::SyntaxError),
1297 "no spaces before either"
1298 );
1299 assert_eq!(
1300 parse_into_kind("regex : 'with spaces'"),
1301 Err(TemplateParseErrorKind::SyntaxError),
1302 "certainly not both"
1303 );
1304 assert_eq!(
1306 parse_normalized("exact:( 'foo' )"),
1307 parse_normalized("exact:'foo'"),
1308 );
1309
1310 assert_eq!(parse_normalized("x:f(y)"), parse_normalized("x:(f(y))"));
1312 assert_eq!(parse_normalized("x:y.f(z)"), parse_normalized("x:(y.f(z))"));
1313 assert_eq!(parse_normalized("x:-y"), parse_normalized("x:(-y)"));
1315 assert_eq!(parse_normalized("x:!y"), parse_normalized("x:(!y)"));
1316 assert_eq!(parse_normalized("x:y*z"), parse_normalized("(x:y)*(z)"));
1318 assert_eq!(parse_normalized("x:y++z"), parse_normalized("(x:y)++(z)"));
1319
1320 assert_eq!(parse_normalized("x:y:z"), parse_normalized("x:(y:z)"));
1322 assert_eq!(parse_normalized("x:y:-z"), parse_normalized("x:(y:(-z))"));
1323 assert_eq!(parse_normalized("x:-y:z"), parse_normalized("x:(-(y:z))"));
1324 assert_eq!(parse_normalized("!x:y:z"), parse_normalized("!(x:(y:z))"));
1325
1326 assert_eq!(
1328 unwrap_pattern(parse_into_kind("x-y:z").unwrap()),
1329 ("x-y", ExpressionKind::Identifier("z"))
1330 );
1331 assert_eq!(
1332 parse_normalized("x+y-z:a"),
1333 parse_normalized("(x)+(y-z:(a))")
1334 );
1335 assert_eq!(
1336 parse_normalized("x-y+z:a"),
1337 parse_normalized("((x)-(y))+(z:(a))")
1338 );
1339 }
1340
1341 #[test]
1342 fn test_integer_literal() {
1343 assert_eq!(parse_into_kind("0"), Ok(ExpressionKind::Integer(0)));
1344 assert_eq!(parse_into_kind("(42)"), Ok(ExpressionKind::Integer(42)));
1345 assert_eq!(
1346 parse_into_kind("00"),
1347 Err(TemplateParseErrorKind::SyntaxError),
1348 );
1349
1350 assert_eq!(
1351 parse_into_kind(&format!("{}", i64::MAX)),
1352 Ok(ExpressionKind::Integer(i64::MAX)),
1353 );
1354 assert_matches!(
1355 parse_into_kind(&format!("{}", (i64::MAX as u64) + 1)),
1356 Err(TemplateParseErrorKind::Expression(_))
1357 );
1358 }
1359
1360 #[test]
1361 fn test_parse_alias_decl() {
1362 let mut aliases_map = TemplateAliasesMap::new();
1363 aliases_map.insert("sym", r#""is symbol""#).unwrap();
1364 aliases_map.insert("pat:a", r#""is pattern a""#).unwrap();
1365 aliases_map.insert("pat:b", r#""is pattern b""#).unwrap();
1366 aliases_map.insert("func()", r#""is function 0""#).unwrap();
1367 aliases_map
1368 .insert("func(a, b)", r#""is function 2""#)
1369 .unwrap();
1370 aliases_map.insert("func(a)", r#""is function a""#).unwrap();
1371 aliases_map.insert("func(b)", r#""is function b""#).unwrap();
1372
1373 let (id, defn) = aliases_map.get_symbol("sym").unwrap();
1374 assert_eq!(id, AliasId::Symbol("sym"));
1375 assert_eq!(defn, r#""is symbol""#);
1376
1377 let (id, param, defn) = aliases_map.get_pattern("pat").unwrap();
1378 assert_eq!(id, AliasId::Pattern("pat", "b"));
1379 assert_eq!(param, "b");
1380 assert_eq!(defn, r#""is pattern b""#);
1381
1382 let (id, params, defn) = aliases_map.get_function("func", 0).unwrap();
1383 assert_eq!(id, AliasId::Function("func", &[]));
1384 assert!(params.is_empty());
1385 assert_eq!(defn, r#""is function 0""#);
1386
1387 let (id, params, defn) = aliases_map.get_function("func", 1).unwrap();
1388 assert_eq!(id, AliasId::Function("func", &["b".to_owned()]));
1389 assert_eq!(params, ["b"]);
1390 assert_eq!(defn, r#""is function b""#);
1391
1392 let (id, params, defn) = aliases_map.get_function("func", 2).unwrap();
1393 assert_eq!(
1394 id,
1395 AliasId::Function("func", &["a".to_owned(), "b".to_owned()])
1396 );
1397 assert_eq!(params, ["a", "b"]);
1398 assert_eq!(defn, r#""is function 2""#);
1399
1400 assert!(aliases_map.get_function("func", 3).is_none());
1401
1402 assert_eq!(
1404 aliases_map.insert("f(a, a)", r#""""#).unwrap_err().kind,
1405 TemplateParseErrorKind::RedefinedFunctionParameter
1406 );
1407
1408 assert!(aliases_map.insert("false", r#"""#).is_err());
1411 assert!(aliases_map.insert("false:x", r#"""#).is_err());
1412 assert!(aliases_map.insert("p:true", r#"""#).is_err());
1413 assert!(aliases_map.insert("true()", r#"""#).is_err());
1414 assert!(aliases_map.insert("f(false)", r#"""#).is_err());
1415
1416 assert!(aliases_map.insert("f(,)", r#"""#).is_err());
1418 assert!(aliases_map.insert("g(a,)", r#"""#).is_ok());
1420 assert!(aliases_map.insert("h(a , )", r#"""#).is_ok());
1421 assert!(aliases_map.insert("i(,a)", r#"""#).is_err());
1422 assert!(aliases_map.insert("j(a,,)", r#"""#).is_err());
1423 assert!(aliases_map.insert("k(a , , )", r#"""#).is_err());
1424 assert!(aliases_map.insert("l(a,b,)", r#"""#).is_ok());
1425 assert!(aliases_map.insert("m(a,,b)", r#"""#).is_err());
1426 }
1427
1428 #[test]
1429 fn test_expand_symbol_alias() {
1430 assert_eq!(
1431 with_aliases([("AB", "a ++ b")]).parse_normalized("AB ++ c"),
1432 parse_normalized("(a ++ b) ++ c"),
1433 );
1434 assert_eq!(
1435 with_aliases([("AB", "a ++ b")]).parse_normalized("if(AB, label(c, AB))"),
1436 parse_normalized("if((a ++ b), label(c, (a ++ b)))"),
1437 );
1438
1439 assert_eq!(
1442 with_aliases([("A", "'a'")]).parse_normalized("A:b"),
1443 parse_normalized("A:b")
1444 );
1445
1446 assert_eq!(
1448 with_aliases([("A", "'a'")]).parse_normalized("exact:A"),
1449 parse_normalized("exact:'a'")
1450 );
1451 assert_eq!(
1452 with_aliases([("A", "'a'")]).parse_normalized("exact:'A'"),
1453 parse_normalized("exact:'A'")
1454 );
1455
1456 assert_eq!(
1458 with_aliases([("A", "BC"), ("BC", "b ++ C"), ("C", "c")]).parse_normalized("A"),
1459 parse_normalized("b ++ c"),
1460 );
1461
1462 assert_eq!(
1464 with_aliases([("AB", "a || b")]).parse_normalized("AB ++ c"),
1465 parse_normalized("(a || b) ++ c"),
1466 );
1467
1468 assert_eq!(
1470 with_aliases([("A", "a"), ("B", "b")]).parse_normalized("A || !B"),
1471 parse_normalized("a || !b"),
1472 );
1473
1474 assert_eq!(
1476 with_aliases([("A", "a")]).parse_normalized("A.f()"),
1477 parse_normalized("a.f()"),
1478 );
1479 assert_eq!(
1480 with_aliases([("A", "a"), ("B", "b")]).parse_normalized("x.f(A, B)"),
1481 parse_normalized("x.f(a, b)"),
1482 );
1483
1484 assert_eq!(
1486 with_aliases([("A", "a")]).parse_normalized("|| A"),
1487 parse_normalized("|| a"),
1488 );
1489 assert_eq!(
1493 with_aliases([("A", "a ++ b")]).parse_normalized("|A| A"),
1494 parse_normalized("|A| (a ++ b)"),
1495 );
1496
1497 assert_eq!(
1499 with_aliases([("A", "A")]).parse("A").unwrap_err().kind,
1500 TemplateParseErrorKind::InAliasExpansion("A".to_owned()),
1501 );
1502 assert_eq!(
1503 with_aliases([("A", "B"), ("B", "b ++ C"), ("C", "c ++ B")])
1504 .parse("A")
1505 .unwrap_err()
1506 .kind,
1507 TemplateParseErrorKind::InAliasExpansion("A".to_owned()),
1508 );
1509
1510 assert_eq!(
1512 with_aliases([("A", "a(")]).parse("A").unwrap_err().kind,
1513 TemplateParseErrorKind::InAliasExpansion("A".to_owned()),
1514 );
1515 }
1516
1517 #[test]
1518 fn test_expand_pattern_alias() {
1519 assert_eq!(
1520 with_aliases([("P:x", "x")]).parse_normalized("P:a"),
1521 parse_normalized("a")
1522 );
1523
1524 assert_eq!(
1526 with_aliases([("P:x", "x ++ a")]).parse_normalized("P:x"),
1527 parse_normalized("x ++ a")
1528 );
1529 assert_eq!(
1531 with_aliases([("P:x", "if(Q:x, y)"), ("Q:y", "x ++ y")]).parse_normalized("P:a"),
1532 parse_normalized("if((x ++ a), y)")
1533 );
1534
1535 assert_eq!(
1537 with_aliases([("P:X", "X"), ("X", "x")]).parse_normalized("P:a ++ X"),
1538 parse_normalized("a ++ x")
1539 );
1540
1541 assert_eq!(
1543 with_aliases([("P:x", "x ++ A"), ("A", "x")]).parse_normalized("P:a"),
1544 parse_normalized("a ++ x")
1545 );
1546
1547 assert_eq!(
1549 with_aliases([("A:x", "A"), ("A", "a")]).parse_normalized("A:x"),
1550 parse_normalized("a")
1551 );
1552
1553 assert_eq!(
1556 with_aliases([("P:x", "|x| x")]).parse_normalized("P:a"),
1557 parse_normalized("|x| a"),
1558 );
1559
1560 assert_eq!(
1562 with_aliases([("P:x", "Q:x"), ("Q:x", "R:x"), ("R:x", "P:x")])
1563 .parse("P:a")
1564 .unwrap_err()
1565 .kind,
1566 TemplateParseErrorKind::InAliasExpansion("P:x".to_owned())
1567 );
1568 }
1569
1570 #[test]
1571 fn test_expand_function_alias() {
1572 assert_eq!(
1573 with_aliases([("F( )", "a")]).parse_normalized("F()"),
1574 parse_normalized("a"),
1575 );
1576 assert_eq!(
1577 with_aliases([("F( x )", "x")]).parse_normalized("F(a)"),
1578 parse_normalized("a"),
1579 );
1580 assert_eq!(
1581 with_aliases([("F( x, y )", "x ++ y")]).parse_normalized("F(a, b)"),
1582 parse_normalized("a ++ b"),
1583 );
1584
1585 assert_eq!(
1587 with_aliases([("F(x)", "F(x,b)"), ("F(x,y)", "x ++ y")]).parse_normalized("F(a)"),
1588 parse_normalized("a ++ b")
1589 );
1590
1591 assert_eq!(
1593 with_aliases([("F(x,y)", "if(x, y)")]).parse_normalized("F(a ++ y, b ++ x)"),
1594 parse_normalized("if((a ++ y), (b ++ x))"),
1595 );
1596 assert_eq!(
1598 with_aliases([("F(x)", "if(G(x), y)"), ("G(y)", "x ++ y")]).parse_normalized("F(a)"),
1599 parse_normalized("if((x ++ a), y)"),
1600 );
1601 assert_eq!(
1603 with_aliases([("F(x)", "if(G(x), y)"), ("G(y)", "x ++ y")]).parse_normalized("F(G(a))"),
1604 parse_normalized("if((x ++ (x ++ a)), y)"),
1605 );
1606
1607 assert_eq!(
1609 with_aliases([("F(X)", "X"), ("X", "x")]).parse_normalized("F(a) ++ X"),
1610 parse_normalized("a ++ x"),
1611 );
1612
1613 assert_eq!(
1615 with_aliases([("F(x)", "x ++ A"), ("A", "x")]).parse_normalized("F(a)"),
1616 parse_normalized("a ++ x"),
1617 );
1618
1619 assert_eq!(
1621 with_aliases([("A()", "A"), ("A", "a")]).parse_normalized("A()"),
1622 parse_normalized("a"),
1623 );
1624
1625 assert_eq!(
1627 with_aliases([("F()", "f()")]).parse_normalized("x.F()"),
1628 parse_normalized("x.F()"),
1629 );
1630
1631 assert_eq!(
1634 with_aliases([("F(x)", "|x| x")]).parse_normalized("F(a ++ b)"),
1635 parse_normalized("|x| (a ++ b)"),
1636 );
1637
1638 assert_matches!(
1640 with_aliases([("F()", "x")]).parse("F(a)").unwrap_err().kind,
1641 TemplateParseErrorKind::InvalidArguments { .. }
1642 );
1643 assert_matches!(
1644 with_aliases([("F(x)", "x")]).parse("F()").unwrap_err().kind,
1645 TemplateParseErrorKind::InvalidArguments { .. }
1646 );
1647 assert_matches!(
1648 with_aliases([("F(x,y)", "x ++ y")])
1649 .parse("F(a,b,c)")
1650 .unwrap_err()
1651 .kind,
1652 TemplateParseErrorKind::InvalidArguments { .. }
1653 );
1654
1655 assert_eq!(
1657 with_aliases([("F(x)", "G(x)"), ("G(x)", "H(x)"), ("H(x)", "F(x)")])
1658 .parse("F(a)")
1659 .unwrap_err()
1660 .kind,
1661 TemplateParseErrorKind::InAliasExpansion("F(x)".to_owned()),
1662 );
1663 assert_eq!(
1664 with_aliases([("F(x)", "F(x,b)"), ("F(x,y)", "F(x|y)")])
1665 .parse("F(a)")
1666 .unwrap_err()
1667 .kind,
1668 TemplateParseErrorKind::InAliasExpansion("F(x)".to_owned())
1669 );
1670 }
1671}