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