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