Skip to main content

jj_cli/
template_parser.rs

1// Copyright 2020 The Jujutsu Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use 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
116/// Manages diagnostic messages emitted during template parsing and building.
117pub 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    /// Some other expression error.
189    pub fn expression(message: impl Into<String>, span: pest::Span<'_>) -> Self {
190        Self::with_span(TemplateParseErrorKind::Expression(message.into()), span)
191    }
192
193    /// If this is a `NoSuchKeyword` error, expands the candidates list with the
194    /// given `other_keywords`.
195    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    /// If this is a `NoSuchFunction` error, expands the candidates list with
210    /// the given `other_functions`.
211    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    /// Expands keyword/function candidates with the given aliases.
226    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    /// Original parsing error which typically occurred in an alias expression.
236    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    /// `<name>:<value>` where `<value>` is usually `String`.
296    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    /// Identity node to preserve the span in the source template text.
304    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                // Method call is syntactically different from function call.
331                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    /// `!`
374    LogicalNot,
375    /// `-`
376    Negate,
377}
378
379#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
380pub enum BinaryOp {
381    /// `||`
382    LogicalOr,
383    /// `&&`
384    LogicalAnd,
385    /// `==`
386    Eq,
387    /// `!=`
388    Ne,
389    /// `>=`
390    Ge,
391    /// `>`
392    Gt,
393    /// `<=`
394    Le,
395    /// `<`
396    Lt,
397    /// `+`
398    Add,
399    /// `-`
400    Sub,
401    /// `*`
402    Mul,
403    /// `/`
404    Div,
405    /// `%`
406    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        // Ignore inner span to preserve parenthesized expression as such.
535        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
630/// Parses text into AST nodes. No type/name checking is made at this stage.
631pub 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
690/// Parses text into AST nodes, and expands aliases.
691///
692/// No type/name checking is made at this stage.
693pub 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
701/// Unwraps inner value if the given `node` is a string literal.
702pub 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
712/// Unwraps inner value if the given `node` is a string pattern
713///
714/// This forces it to be static so that it need not be part of the type system.
715pub 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
731/// Unwraps inner node if the given `node` is a lambda.
732pub 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
744/// Applies the given function to the innermost `node` by unwrapping alias
745/// expansion nodes. Appends alias expansion stack to error and diagnostics.
746pub 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
790/// Looks up `table` by the given function name.
791pub 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
809/// Looks up `table` by the given method name.
810pub 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    /// Drops auxiliary data of AST so it can be compared with other node.
871    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        // Operator precedence
979        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        // Logical operator bounds more tightly than concatenation. This might
1012        // not be so intuitive, but should be harmless.
1013        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        // Expression span
1031        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        // Trailing comma isn't allowed for empty argument
1054        assert!(parse_template(r#" "".first_line() "#).is_ok());
1055        assert!(parse_template(r#" "".first_line(,) "#).is_err());
1056
1057        // Trailing comma is allowed for the last argument
1058        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        // Keyword arguments
1069        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        // Boolean literal cannot be used as a function name
1074        assert!(parse_template("false()").is_err());
1075        // Boolean literal cannot be used as a parameter name
1076        assert!(parse_template("f(false=0)").is_err());
1077        // Function arguments can be any expression
1078        assert!(parse_template("f(false)").is_ok());
1079
1080        // Expression span
1081        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        // Because we use the implicit WHITESPACE rule, we have little control
1085        // over leading/trailing whitespaces.
1086        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        // Expression span
1102        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        // No body
1127        assert!(parse_template("||").is_err());
1128
1129        // Binding
1130        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        // Lambda vs logical operator: weird, but this is type error anyway
1144        assert_eq!(parse_normalized("x||||y"), parse_normalized("x || (|| y)"));
1145        assert_eq!(parse_normalized("||||x"), parse_normalized("|| (|| x)"));
1146
1147        // Trailing comma
1148        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        // Formal parameter can't be redefined
1156        assert_eq!(
1157            parse_template("|x, x| a").unwrap_err().kind,
1158            TemplateParseErrorKind::RedefinedFunctionParameter
1159        );
1160
1161        // Boolean literal cannot be used as a parameter name
1162        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        // Keyword literals are case sensitive
1170        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        // Keyword cannot be used as pattern or function name
1179        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        // Whitespace in string literal should be preserved
1192        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        // "\<char>" escapes
1202        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        // Invalid "\<char>" escape
1208        assert_eq!(
1209            parse_into_kind(r#" "\y" "#),
1210            Err(TemplateParseErrorKind::SyntaxError),
1211        );
1212
1213        // Single-quoted raw string
1214        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        // Hex bytes
1232        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        // Whitespace isn't allowed in between
1289        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        // Whitespace is allowed in parenthesized value expression
1305        assert_eq!(
1306            parse_normalized("exact:( 'foo' )"),
1307            parse_normalized("exact:'foo'"),
1308        );
1309
1310        // Functions and method calls are allowed
1311        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        // Negation operations are also allowed
1314        assert_eq!(parse_normalized("x:-y"), parse_normalized("x:(-y)"));
1315        assert_eq!(parse_normalized("x:!y"), parse_normalized("x:(!y)"));
1316        // Other operators have lower binding strength
1317        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        // Pattern prefix is like (type)x cast, so is evaluated from right
1321        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        // Pattern names with dash
1327        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        // Formal parameter 'a' can't be redefined
1403        assert_eq!(
1404            aliases_map.insert("f(a, a)", r#""""#).unwrap_err().kind,
1405            TemplateParseErrorKind::RedefinedFunctionParameter
1406        );
1407
1408        // Boolean literal cannot be used as a symbol, pattern, function, or
1409        // parameter name
1410        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        // Trailing comma isn't allowed for empty parameter
1417        assert!(aliases_map.insert("f(,)", r#"""#).is_err());
1418        // Trailing comma is allowed for the last parameter
1419        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        // Kind of string pattern should not be substituted, which is similar to
1440        // function name.
1441        assert_eq!(
1442            with_aliases([("A", "'a'")]).parse_normalized("A:b"),
1443            parse_normalized("A:b")
1444        );
1445
1446        // Value of string pattern can be substituted if it's an identifier.
1447        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        // Multi-level substitution.
1457        assert_eq!(
1458            with_aliases([("A", "BC"), ("BC", "b ++ C"), ("C", "c")]).parse_normalized("A"),
1459            parse_normalized("b ++ c"),
1460        );
1461
1462        // Operator expression can be expanded in concatenation.
1463        assert_eq!(
1464            with_aliases([("AB", "a || b")]).parse_normalized("AB ++ c"),
1465            parse_normalized("(a || b) ++ c"),
1466        );
1467
1468        // Operands should be expanded.
1469        assert_eq!(
1470            with_aliases([("A", "a"), ("B", "b")]).parse_normalized("A || !B"),
1471            parse_normalized("a || !b"),
1472        );
1473
1474        // Method receiver and arguments should be expanded.
1475        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        // Lambda expression body should be expanded.
1485        assert_eq!(
1486            with_aliases([("A", "a")]).parse_normalized("|| A"),
1487            parse_normalized("|| a"),
1488        );
1489        // No matter if 'A' is a formal parameter. Alias substitution isn't scoped.
1490        // If we don't like this behavior, maybe we can turn off alias substitution
1491        // for lambda parameters.
1492        assert_eq!(
1493            with_aliases([("A", "a ++ b")]).parse_normalized("|A| A"),
1494            parse_normalized("|A| (a ++ b)"),
1495        );
1496
1497        // Infinite recursion, where the top-level error isn't of RecursiveAlias kind.
1498        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        // Error in alias definition.
1511        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        // Argument should be resolved in the current scope.
1525        assert_eq!(
1526            with_aliases([("P:x", "x ++ a")]).parse_normalized("P:x"),
1527            parse_normalized("x ++ a")
1528        );
1529        // P:a -> if(Q:a, y) -> if((x ++ a), y)
1530        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        // Pattern parameter should precede the symbol alias.
1536        assert_eq!(
1537            with_aliases([("P:X", "X"), ("X", "x")]).parse_normalized("P:a ++ X"),
1538            parse_normalized("a ++ x")
1539        );
1540
1541        // Pattern parameter shouldn't be expanded in symbol alias.
1542        assert_eq!(
1543            with_aliases([("P:x", "x ++ A"), ("A", "x")]).parse_normalized("P:a"),
1544            parse_normalized("a ++ x")
1545        );
1546
1547        // Pattern and symbol aliases reside in separate namespaces.
1548        assert_eq!(
1549            with_aliases([("A:x", "A"), ("A", "a")]).parse_normalized("A:x"),
1550            parse_normalized("a")
1551        );
1552
1553        // Formal parameter shouldn't be substituted by alias parameter, but
1554        // the expression should be substituted.
1555        assert_eq!(
1556            with_aliases([("P:x", "|x| x")]).parse_normalized("P:a"),
1557            parse_normalized("|x| a"),
1558        );
1559
1560        // Infinite recursion, where the top-level error isn't of RecursiveAlias kind.
1561        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        // Not recursion because functions are overloaded by arity.
1586        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        // Arguments should be resolved in the current scope.
1592        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        // F(a) -> if(G(a), y) -> if((x ++ a), y)
1597        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        // F(G(a)) -> F(x ++ a) -> if(G(x ++ a), y) -> if((x ++ (x ++ a)), y)
1602        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        // Function parameter should precede the symbol alias.
1608        assert_eq!(
1609            with_aliases([("F(X)", "X"), ("X", "x")]).parse_normalized("F(a) ++ X"),
1610            parse_normalized("a ++ x"),
1611        );
1612
1613        // Function parameter shouldn't be expanded in symbol alias.
1614        assert_eq!(
1615            with_aliases([("F(x)", "x ++ A"), ("A", "x")]).parse_normalized("F(a)"),
1616            parse_normalized("a ++ x"),
1617        );
1618
1619        // Function and symbol aliases reside in separate namespaces.
1620        assert_eq!(
1621            with_aliases([("A()", "A"), ("A", "a")]).parse_normalized("A()"),
1622            parse_normalized("a"),
1623        );
1624
1625        // Method call shouldn't be substituted by function alias.
1626        assert_eq!(
1627            with_aliases([("F()", "f()")]).parse_normalized("x.F()"),
1628            parse_normalized("x.F()"),
1629        );
1630
1631        // Formal parameter shouldn't be substituted by alias parameter, but
1632        // the expression should be substituted.
1633        assert_eq!(
1634            with_aliases([("F(x)", "|x| x")]).parse_normalized("F(a ++ b)"),
1635            parse_normalized("|x| (a ++ b)"),
1636        );
1637
1638        // Invalid number of arguments.
1639        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        // Infinite recursion, where the top-level error isn't of RecursiveAlias kind.
1656        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}