Skip to main content

ironcalc_base/expressions/parser/
mod.rs

1/*!
2# GRAMMAR
3
4<pre class="rust">
5opComp   => '=' | '<' | '>' | '<=' } '>=' | '<>'
6opFactor => '*' | '/'
7unaryOp  => '-' | '+'
8
9expr    => concat (opComp concat)*
10concat  => term ('&' term)*
11term    => factor (opFactor factor)*
12factor  => prod (opProd prod)*
13prod    => power ('^' power)*
14power   => (unaryOp)* range '%'*
15range   => implicit (':' primary)?
16implicit=> '@' primary | primary '#' | primary
17primary => '(' expr ')'
18        => number
19        => function '(' f_args ')'
20        => LAMBDA '(' f_args ')' '(' f_args ')'
21        => name
22        => string
23        => '{' a_args '}'
24        => bool
25        => bool()
26        => error
27
28f_args  => e (',' e)*
29</pre>
30*/
31
32use std::collections::HashMap;
33
34use crate::functions::Function;
35use crate::language::get_default_language;
36use crate::language::get_language;
37use crate::language::Language;
38use crate::locale::get_default_locale;
39use crate::locale::get_locale;
40use crate::locale::Locale;
41use crate::types::Table;
42
43use super::lexer;
44use super::token;
45use super::token::OpUnary;
46use super::token::TableReference;
47use super::token::TokenType;
48use super::types::*;
49use super::utils::number_to_column;
50
51use token::OpCompare;
52
53mod lambda;
54pub mod move_formula;
55pub mod static_analysis;
56pub mod stringify;
57
58#[cfg(test)]
59mod tests;
60
61pub(crate) fn parse_range(formula: &str) -> Result<(i32, i32, i32, i32), String> {
62    let mut lexer = lexer::Lexer::new(
63        formula,
64        lexer::LexerMode::A1,
65        #[allow(clippy::expect_used)]
66        get_locale("en").expect(""),
67        #[allow(clippy::expect_used)]
68        get_language("en").expect(""),
69    );
70    if let TokenType::Range {
71        left,
72        right,
73        sheet: _,
74    } = lexer.next_token()
75    {
76        Ok((left.column, left.row, right.column, right.row))
77    } else {
78        Err("Not a range".to_string())
79    }
80}
81
82fn get_table_column_by_name(table_column_name: &str, table: &Table) -> Option<i32> {
83    for (index, table_column) in table.columns.iter().enumerate() {
84        if table_column.name == table_column_name {
85            return Some(index as i32);
86        }
87    }
88    None
89}
90
91// DefinedNameS is a tuple with the name of the defined name, the index of the sheet and the formula
92pub type DefinedNameS = (String, Option<u32>, String);
93
94pub(crate) struct Reference<'a> {
95    sheet_name: &'a Option<String>,
96    sheet_index: u32,
97    absolute_row: bool,
98    absolute_column: bool,
99    row: i32,
100    column: i32,
101}
102
103#[derive(PartialEq, Clone, Debug)]
104pub enum ArrayNode {
105    Boolean(bool),
106    Number(f64),
107    String(String),
108    Error(token::Error),
109    /// An empty (blank) cell from a range reference.
110    Empty,
111}
112
113#[derive(PartialEq, Clone, Debug)]
114pub struct NamedVariable {
115    pub(crate) name: String,
116    pub(crate) id: Option<u32>,
117    pub(crate) is_optional: bool,
118}
119
120#[derive(PartialEq, Clone, Debug, serde::Serialize)]
121pub enum ExpectedTokens {
122    // We know the next token could be a range
123    Range,
124    // We know the next token could be a function that starts with the given name
125    FunctionName(String),
126    // We know the next token could be an argument to a function (name, arg index)
127    Argument(String, u32),
128    Other,
129}
130
131/// What the grammar accepts at a cursor position, plus the span the UI should
132/// replace when it inserts a completion. Returned by [`Parser::parse_at_cursor`].
133#[derive(PartialEq, Clone, Debug, serde::Serialize)]
134pub struct CompletionContext {
135    /// What the grammar accepts at the cursor.
136    pub expecting: Vec<ExpectedTokens>,
137    /// The span `[replace_from, cursor)` the UI should replace — e.g. the `F`
138    /// in `A1+F`. Equals the cursor when there is nothing to replace (right
139    /// after `SUM(`).
140    pub replace_from: usize,
141}
142
143#[derive(PartialEq, Clone, Debug)]
144pub enum Node {
145    BooleanKind(bool),
146    NumberKind(f64),
147    StringKind(String),
148    ReferenceKind {
149        sheet_name: Option<String>,
150        sheet_index: u32,
151        absolute_row: bool,
152        absolute_column: bool,
153        row: i32,
154        column: i32,
155    },
156    RangeKind {
157        sheet_name: Option<String>,
158        sheet_index: u32,
159        absolute_row1: bool,
160        absolute_column1: bool,
161        row1: i32,
162        column1: i32,
163        absolute_row2: bool,
164        absolute_column2: bool,
165        row2: i32,
166        column2: i32,
167    },
168    WrongReferenceKind {
169        sheet_name: Option<String>,
170        absolute_row: bool,
171        absolute_column: bool,
172        row: i32,
173        column: i32,
174    },
175    WrongRangeKind {
176        sheet_name: Option<String>,
177        absolute_row1: bool,
178        absolute_column1: bool,
179        row1: i32,
180        column1: i32,
181        absolute_row2: bool,
182        absolute_column2: bool,
183        row2: i32,
184        column2: i32,
185    },
186    OpRangeKind {
187        left: Box<Node>,
188        right: Box<Node>,
189    },
190    OpConcatenateKind {
191        left: Box<Node>,
192        right: Box<Node>,
193    },
194    OpSumKind {
195        kind: token::OpSum,
196        left: Box<Node>,
197        right: Box<Node>,
198    },
199    OpProductKind {
200        kind: token::OpProduct,
201        left: Box<Node>,
202        right: Box<Node>,
203    },
204    OpPowerKind {
205        left: Box<Node>,
206        right: Box<Node>,
207    },
208    FunctionKind {
209        kind: Function,
210        args: Vec<Node>,
211    },
212    // LAMBDA(a,b, SQRT(a*a+b*b))
213    LambdaDefKind {
214        parameters: Vec<NamedVariable>,
215        body: Box<Node>,
216    },
217    // LAMBDA(a,b, SQRT(a*a+b*b))(3,4)
218    LambdaCallKind {
219        lambda: Box<Node>,
220        args: Vec<Node>,
221    },
222    NamedFunctionKind {
223        id: Option<u32>,
224        name: String,
225        args: Vec<Node>,
226    },
227    ArrayKind(Vec<Vec<ArrayNode>>),
228    DefinedNameKind(DefinedNameS),
229    TableNameKind(String),
230    NamedVariableKind {
231        name: String,
232        id: Option<u32>,
233    },
234    ImplicitIntersection {
235        automatic: bool,
236        child: Box<Node>,
237    },
238    SpillRangeOperator {
239        child: Box<Node>,
240    },
241    CompareKind {
242        kind: OpCompare,
243        left: Box<Node>,
244        right: Box<Node>,
245    },
246    UnaryKind {
247        kind: OpUnary,
248        right: Box<Node>,
249    },
250    ErrorKind(token::Error),
251    ParseErrorKind {
252        formula: String,
253        message: String,
254        position: usize,
255        // What tokens were expected at this position.
256        expecting: Vec<ExpectedTokens>,
257    },
258    EmptyArgKind,
259}
260
261#[derive(Clone)]
262pub struct Parser<'a> {
263    lexer: lexer::Lexer<'a>,
264    worksheets: Vec<String>,
265    defined_names: Vec<DefinedNameS>,
266    context: CellReferenceRC,
267    tables: HashMap<String, Table>,
268    locale: &'a Locale,
269    language: &'a Language,
270    /// Completion hint for the position currently being parsed. The deepest
271    /// frame that hits EOF stamps this onto its error. See `parse_at_cursor`.
272    expecting_here: Vec<ExpectedTokens>,
273    /// Set while parsing when an identifier turns out to be the last token in
274    /// the input (its `peek` is EOF): the user is mid-typing a name there.
275    /// Holds `(prefix, start_offset)`. Read by `parse_at_cursor` to offer
276    /// function/name completion even when the surrounding parse succeeds (`SU`,
277    /// `A1+F`) or fails for an unrelated reason (`IF(VLOOK`). See that method.
278    trailing_name: Option<(String, usize)>,
279}
280
281pub fn new_parser_english<'a>(
282    worksheets: Vec<String>,
283    defined_names: Vec<DefinedNameS>,
284    tables: HashMap<String, Table>,
285) -> Parser<'a> {
286    let locale = get_default_locale();
287    let language = get_default_language();
288    Parser::new(worksheets, defined_names, tables, locale, language)
289}
290
291impl<'a> Parser<'a> {
292    pub fn new(
293        worksheets: Vec<String>,
294        defined_names: Vec<DefinedNameS>,
295        tables: HashMap<String, Table>,
296        locale: &'a Locale,
297        language: &'a Language,
298    ) -> Parser<'a> {
299        let lexer = lexer::Lexer::new("", lexer::LexerMode::A1, locale, language);
300        let context = CellReferenceRC {
301            sheet: worksheets.first().map_or("", |v| v).to_string(),
302            column: 1,
303            row: 1,
304        };
305        Parser {
306            lexer,
307            worksheets,
308            defined_names,
309            context,
310            tables,
311            locale,
312            language,
313            expecting_here: vec![ExpectedTokens::Other],
314            trailing_name: None,
315        }
316    }
317    pub fn set_lexer_mode(&mut self, mode: lexer::LexerMode) {
318        self.lexer.set_lexer_mode(mode)
319    }
320
321    pub fn set_locale(&mut self, locale: &'a Locale) {
322        self.locale = locale;
323        self.lexer.set_locale(locale);
324    }
325
326    pub fn set_language(&mut self, language: &'a Language) {
327        self.language = language;
328        self.lexer.set_language(language);
329    }
330
331    pub fn set_worksheets_and_names(
332        &mut self,
333        worksheets: Vec<String>,
334        defined_names: Vec<DefinedNameS>,
335    ) {
336        self.worksheets = worksheets;
337        self.defined_names = defined_names;
338    }
339
340    pub fn parse(&mut self, formula: &str, context: &CellReferenceRC) -> Node {
341        self.lexer.set_formula(formula);
342        self.context = context.clone();
343        // At the top level a formula may start with an expression or a range.
344        self.expecting_here = vec![ExpectedTokens::Range, ExpectedTokens::Other];
345        self.trailing_name = None;
346        self.parse_expr()
347    }
348
349    /// Parses `formula` up to `cursor` (a char offset) and reports what the
350    /// grammar would accept at that position, so callers can offer completions.
351    pub fn parse_at_cursor(
352        &mut self,
353        formula: &str,
354        cursor: usize,
355        context: &CellReferenceRC,
356    ) -> CompletionContext {
357        let head: String = formula.chars().take(cursor).collect();
358
359        let node = self.parse(&head, context);
360
361        // If the cursor sits on an identifier the user is mid-typing, the parser
362        // recorded it as `trailing_name` while consuming it in a name position
363        // (see `parse_primary`). That takes priority over the parse outcome: it
364        // wins both when the surrounding parse *succeeds* (`SU`, `A1+F`) — where
365        // there is no error to carry an `expecting` — and when it *fails* for an
366        // unrelated reason (`IF(VLOOK`, where the EOF frame would otherwise
367        // report the "argument of IF" hint).
368        if let Some((prefix, start)) = self.trailing_name.take() {
369            return CompletionContext {
370                expecting: vec![ExpectedTokens::FunctionName(prefix)],
371                replace_from: start,
372            };
373        }
374
375        match node {
376            // (a) The prefix is incomplete: the EOF frame stamped `expecting`.
377            Node::ParseErrorKind {
378                expecting,
379                position,
380                ..
381            } => CompletionContext {
382                expecting,
383                replace_from: position,
384            },
385            // (b) The prefix parsed cleanly and there is no trailing bare name,
386            // so there is nothing grammar-specific to offer.
387            _ => CompletionContext {
388                expecting: vec![ExpectedTokens::Other],
389                replace_from: cursor,
390            },
391        }
392    }
393
394    // Returns the token used to separate arguments in functions and arrays
395    // If the locale decimal separator is '.', then it is a comma ','
396    // Otherwise, it is a semicolon ';'
397    fn get_argument_separator_token(&self) -> TokenType {
398        if self.locale.numbers.symbols.decimal == "." {
399            TokenType::Comma
400        } else {
401            TokenType::Semicolon
402        }
403    }
404
405    // Returns the token used to separate columns in arrays
406    // If the locale decimal separator is '.', then it is a semicolon ';'
407    fn get_column_separator_token(&self) -> TokenType {
408        if self.locale.numbers.symbols.decimal == "." {
409            TokenType::Semicolon
410        } else {
411            TokenType::Backslash
412        }
413    }
414
415    fn get_sheet_index_by_name(&self, name: &str) -> Option<u32> {
416        let worksheets = &self.worksheets;
417        for (i, sheet) in worksheets.iter().enumerate() {
418            if sheet == name {
419                return Some(i as u32);
420            }
421        }
422        None
423    }
424
425    // Returns:
426    //  * None: If there is no defined name by that name
427    //  * Some((Some(index), formula)): If there is a defined name local to that sheet
428    //  * Some(None): If there is a global defined name
429    fn get_defined_name(&self, name: &str, sheet: u32) -> Option<(Option<u32>, String)> {
430        for (df_name, df_scope, df_formula) in &self.defined_names {
431            if name.to_lowercase() == df_name.to_lowercase() && df_scope == &Some(sheet) {
432                return Some((*df_scope, df_formula.to_owned()));
433            }
434        }
435        for (df_name, df_scope, df_formula) in &self.defined_names {
436            if name.to_lowercase() == df_name.to_lowercase() && df_scope.is_none() {
437                return Some((None, df_formula.to_owned()));
438            }
439        }
440        None
441    }
442
443    fn parse_expr(&mut self) -> Node {
444        let mut t = self.parse_concat();
445        if let Node::ParseErrorKind { .. } = t {
446            return t;
447        }
448        let mut next_token = self.lexer.peek_token();
449        while let TokenType::Compare(op) = next_token {
450            self.lexer.advance_token();
451            let p = self.parse_concat();
452            if let Node::ParseErrorKind { .. } = p {
453                return p;
454            }
455            t = Node::CompareKind {
456                kind: op,
457                left: Box::new(t),
458                right: Box::new(p),
459            };
460            next_token = self.lexer.peek_token();
461        }
462        t
463    }
464
465    fn parse_concat(&mut self) -> Node {
466        let mut t = self.parse_term();
467        if let Node::ParseErrorKind { .. } = t {
468            return t;
469        }
470        let mut next_token = self.lexer.peek_token();
471        while next_token == TokenType::And {
472            self.lexer.advance_token();
473            let p = self.parse_term();
474            if let Node::ParseErrorKind { .. } = p {
475                return p;
476            }
477            t = Node::OpConcatenateKind {
478                left: Box::new(t),
479                right: Box::new(p),
480            };
481            next_token = self.lexer.peek_token();
482        }
483        t
484    }
485
486    fn parse_term(&mut self) -> Node {
487        let mut t = self.parse_factor();
488        if let Node::ParseErrorKind { .. } = t {
489            return t;
490        }
491        let mut next_token = self.lexer.peek_token();
492        while let TokenType::Addition(op) = next_token {
493            self.lexer.advance_token();
494            let p = self.parse_factor();
495            if let Node::ParseErrorKind { .. } = p {
496                return p;
497            }
498            t = Node::OpSumKind {
499                kind: op,
500                left: Box::new(t),
501                right: Box::new(p),
502            };
503
504            next_token = self.lexer.peek_token();
505        }
506        t
507    }
508
509    fn parse_factor(&mut self) -> Node {
510        let mut t = self.parse_prod();
511        if let Node::ParseErrorKind { .. } = t {
512            return t;
513        }
514        let mut next_token = self.lexer.peek_token();
515        while let TokenType::Product(op) = next_token {
516            self.lexer.advance_token();
517            let p = self.parse_prod();
518            if let Node::ParseErrorKind { .. } = p {
519                return p;
520            }
521            t = Node::OpProductKind {
522                kind: op,
523                left: Box::new(t),
524                right: Box::new(p),
525            };
526            next_token = self.lexer.peek_token();
527        }
528        t
529    }
530
531    fn parse_prod(&mut self) -> Node {
532        let mut t = self.parse_power();
533        if let Node::ParseErrorKind { .. } = t {
534            return t;
535        }
536        let mut next_token = self.lexer.peek_token();
537        while next_token == TokenType::Power {
538            self.lexer.advance_token();
539            let p = self.parse_power();
540            if let Node::ParseErrorKind { .. } = p {
541                return p;
542            }
543            t = Node::OpPowerKind {
544                left: Box::new(t),
545                right: Box::new(p),
546            };
547            next_token = self.lexer.peek_token();
548        }
549        t
550    }
551
552    fn parse_power(&mut self) -> Node {
553        let mut next_token = self.lexer.peek_token();
554        // Every minus is kept: two of them do not cancel out, `--x` turns `x`
555        // into a number, which is what it is written for. A plus does nothing
556        // at all, `+x` is `x`, text or boolean as it may be.
557        let mut minus_count = 0;
558        while let TokenType::Addition(op) = next_token {
559            self.lexer.advance_token();
560            if op == token::OpSum::Minus {
561                minus_count += 1;
562            }
563            next_token = self.lexer.peek_token();
564        }
565
566        let mut t = self.parse_range();
567        if let Node::ParseErrorKind { .. } = t {
568            return t;
569        }
570        for _ in 0..minus_count {
571            t = Node::UnaryKind {
572                kind: token::OpUnary::Minus,
573                right: Box::new(t),
574            }
575        }
576        next_token = self.lexer.peek_token();
577        while next_token == TokenType::Percent {
578            self.lexer.advance_token();
579            t = Node::UnaryKind {
580                kind: token::OpUnary::Percentage,
581                right: Box::new(t),
582            };
583            next_token = self.lexer.peek_token();
584        }
585        t
586    }
587
588    fn parse_range(&mut self) -> Node {
589        let t = self.parse_implicit();
590        if let Node::ParseErrorKind { .. } = t {
591            return t;
592        }
593        let next_token = self.lexer.peek_token();
594        if next_token == TokenType::Colon {
595            self.lexer.advance_token();
596            let p = self.parse_primary();
597            if let Node::ParseErrorKind { .. } = p {
598                return p;
599            }
600            return Node::OpRangeKind {
601                left: Box::new(t),
602                right: Box::new(p),
603            };
604        }
605        t
606    }
607
608    fn parse_implicit(&mut self) -> Node {
609        let next_token = self.lexer.peek_token();
610        if next_token == TokenType::At {
611            self.lexer.advance_token();
612            let t = self.parse_primary();
613            if let Node::ParseErrorKind { .. } = t {
614                return t;
615            }
616            return Node::ImplicitIntersection {
617                automatic: false,
618                child: Box::new(t),
619            };
620        }
621        let primary = self.parse_primary();
622        if let Node::ParseErrorKind { .. } = primary {
623            return primary;
624        }
625        let next_token = self.lexer.peek_token();
626        if next_token == TokenType::Spill {
627            self.lexer.advance_token();
628            return Node::SpillRangeOperator {
629                child: Box::new(primary),
630            };
631        }
632        primary
633    }
634
635    fn parse_array_row(&mut self) -> Result<Vec<ArrayNode>, Node> {
636        let mut row = Vec::new();
637        let column_separator_token = self.get_argument_separator_token();
638        // and array can only have numbers, string or booleans
639        // otherwise it is a syntax error
640        let first_element = match self.parse_expr() {
641            Node::BooleanKind(s) => ArrayNode::Boolean(s),
642            Node::NumberKind(s) => ArrayNode::Number(s),
643            Node::StringKind(s) => ArrayNode::String(s),
644            Node::ErrorKind(kind) => ArrayNode::Error(kind),
645            Node::UnaryKind {
646                kind: OpUnary::Minus,
647                right,
648            } => {
649                if let Node::NumberKind(n) = *right {
650                    ArrayNode::Number(-n)
651                } else {
652                    return Err(Node::ParseErrorKind {
653                        formula: self.lexer.get_formula(),
654                        expecting: vec![ExpectedTokens::Other],
655                        message: "Invalid value in array".to_string(),
656                        position: self.lexer.get_position() as usize,
657                    });
658                }
659            }
660            error @ Node::ParseErrorKind { .. } => return Err(error),
661            _ => {
662                return Err(Node::ParseErrorKind {
663                    formula: self.lexer.get_formula(),
664                    expecting: vec![ExpectedTokens::Other],
665                    message: "Invalid value in array".to_string(),
666                    position: self.lexer.get_position() as usize,
667                });
668            }
669        };
670        row.push(first_element);
671        let mut next_token = self.lexer.peek_token();
672        while next_token == column_separator_token {
673            self.lexer.advance_token();
674            let value = match self.parse_expr() {
675                Node::BooleanKind(s) => ArrayNode::Boolean(s),
676                Node::NumberKind(s) => ArrayNode::Number(s),
677                Node::StringKind(s) => ArrayNode::String(s),
678                Node::ErrorKind(kind) => ArrayNode::Error(kind),
679                Node::UnaryKind {
680                    kind: OpUnary::Minus,
681                    right,
682                } => {
683                    if let Node::NumberKind(n) = *right {
684                        ArrayNode::Number(-n)
685                    } else {
686                        return Err(Node::ParseErrorKind {
687                            formula: self.lexer.get_formula(),
688                            expecting: vec![ExpectedTokens::Other],
689                            message: "Invalid value in array".to_string(),
690                            position: self.lexer.get_position() as usize,
691                        });
692                    }
693                }
694                error @ Node::ParseErrorKind { .. } => return Err(error),
695                _ => {
696                    return Err(Node::ParseErrorKind {
697                        formula: self.lexer.get_formula(),
698                        expecting: vec![ExpectedTokens::Other],
699                        message: "Invalid value in array".to_string(),
700                        position: self.lexer.get_position() as usize,
701                    });
702                }
703            };
704            row.push(value);
705            next_token = self.lexer.peek_token();
706        }
707        Ok(row)
708    }
709
710    fn parse_primary(&mut self) -> Node {
711        let next_token = self.lexer.next_token();
712        match next_token {
713            TokenType::LeftParenthesis => {
714                let t = self.parse_expr();
715                if let Node::ParseErrorKind { .. } = t {
716                    return t;
717                }
718
719                if let Err(err) = self.lexer.expect(TokenType::RightParenthesis) {
720                    return Node::ParseErrorKind {
721                        formula: self.lexer.get_formula(),
722                        expecting: vec![ExpectedTokens::Other],
723                        position: err.position,
724                        message: err.message,
725                    };
726                }
727                t
728            }
729            TokenType::Number(s) => Node::NumberKind(s),
730            TokenType::String(s) => Node::StringKind(s),
731            TokenType::LeftBrace => {
732                // It's an array. It's a collection of rows all of the same dimension
733                let column_separator_token = self.get_column_separator_token();
734
735                let first_row = match self.parse_array_row() {
736                    Ok(s) => s,
737                    Err(error) => return error,
738                };
739                let length = first_row.len();
740
741                let mut matrix = Vec::new();
742                matrix.push(first_row);
743                let mut next_token = self.lexer.peek_token();
744                while next_token == column_separator_token {
745                    self.lexer.advance_token();
746                    let row = match self.parse_array_row() {
747                        Ok(s) => s,
748                        Err(error) => return error,
749                    };
750                    next_token = self.lexer.peek_token();
751                    if row.len() != length {
752                        return Node::ParseErrorKind {
753                            formula: self.lexer.get_formula(),
754                            expecting: vec![ExpectedTokens::Other],
755                            position: self.lexer.get_position() as usize,
756                            message: "All rows in an array should be the same length".to_string(),
757                        };
758                    }
759                    matrix.push(row);
760                }
761
762                if let Err(err) = self.lexer.expect(TokenType::RightBrace) {
763                    return Node::ParseErrorKind {
764                        formula: self.lexer.get_formula(),
765                        expecting: vec![ExpectedTokens::Other],
766                        position: err.position,
767                        message: err.message,
768                    };
769                }
770                Node::ArrayKind(matrix)
771            }
772            TokenType::Reference {
773                sheet,
774                row,
775                column,
776                absolute_column,
777                absolute_row,
778            } => {
779                let context = &self.context;
780                let sheet_index = match &sheet {
781                    Some(name) => self.get_sheet_index_by_name(name),
782                    None => self.get_sheet_index_by_name(&context.sheet),
783                };
784                let a1_mode = self.lexer.is_a1_mode();
785                let row = if absolute_row || !a1_mode {
786                    row
787                } else {
788                    row - context.row
789                };
790                let column = if absolute_column || !a1_mode {
791                    column
792                } else {
793                    column - context.column
794                };
795                match sheet_index {
796                    Some(index) => Node::ReferenceKind {
797                        sheet_name: sheet,
798                        sheet_index: index,
799                        row,
800                        column,
801                        absolute_row,
802                        absolute_column,
803                    },
804                    None => Node::WrongReferenceKind {
805                        sheet_name: sheet,
806                        row,
807                        column,
808                        absolute_row,
809                        absolute_column,
810                    },
811                }
812            }
813            TokenType::Range { sheet, left, right } => {
814                let context = &self.context;
815                let sheet_index = match &sheet {
816                    Some(name) => self.get_sheet_index_by_name(name),
817                    None => self.get_sheet_index_by_name(&context.sheet),
818                };
819                let mut row1 = left.row;
820                let mut column1 = left.column;
821                let mut row2 = right.row;
822                let mut column2 = right.column;
823
824                let mut absolute_column1 = left.absolute_column;
825                let mut absolute_column2 = right.absolute_column;
826                let mut absolute_row1 = left.absolute_row;
827                let mut absolute_row2 = right.absolute_row;
828
829                if self.lexer.is_a1_mode() {
830                    if row1 > row2 {
831                        (row2, row1) = (row1, row2);
832                        (absolute_row2, absolute_row1) = (absolute_row1, absolute_row2);
833                    }
834                    if column1 > column2 {
835                        (column2, column1) = (column1, column2);
836                        (absolute_column2, absolute_column1) = (absolute_column1, absolute_column2);
837                    }
838                }
839
840                if self.lexer.is_a1_mode() {
841                    if !absolute_row1 {
842                        row1 -= context.row
843                    };
844                    if !absolute_column1 {
845                        column1 -= context.column
846                    };
847                    if !absolute_row2 {
848                        row2 -= context.row
849                    };
850                    if !absolute_column2 {
851                        column2 -= context.column
852                    };
853                }
854
855                match sheet_index {
856                    Some(index) => Node::RangeKind {
857                        sheet_name: sheet,
858                        sheet_index: index,
859                        row1,
860                        column1,
861                        row2,
862                        column2,
863                        absolute_column1,
864                        absolute_column2,
865                        absolute_row1,
866                        absolute_row2,
867                    },
868                    None => Node::WrongRangeKind {
869                        sheet_name: sheet,
870                        row1,
871                        column1,
872                        row2,
873                        column2,
874                        absolute_column1,
875                        absolute_column2,
876                        absolute_row1,
877                        absolute_row2,
878                    },
879                }
880            }
881            TokenType::Ident(name) => {
882                let next_token = self.lexer.peek_token();
883                // If this identifier is the last token before the cursor (its
884                // peek is EOF), the user is mid-typing a name here. Record it so
885                // `parse_at_cursor` can offer function/name completion. We are in
886                // a name/operand position by construction, so this never fires
887                // for an identifier glued to a completed operand: the `m` in
888                // `1m` is leftover input, never reached as a primary.
889                if next_token == TokenType::EOF {
890                    let end = self.lexer.get_position() as usize;
891                    let start = end.saturating_sub(name.chars().count());
892                    self.trailing_name = Some((name.clone(), start));
893                }
894                if next_token == TokenType::LeftParenthesis {
895                    self.lexer.advance_token();
896                    // It's a function call "SUM(.."
897                    // _xlfn.LAMBDA(_xlpm.a,_xlpm.b, SQRT(_xlpm.a*_xlpm.a+_xlpm.b*_xlpm.b))(3,4)
898                    if &name == "_xlfn.LAMBDA" || &name.to_uppercase() == "LAMBDA" {
899                        return self.parse_lambda();
900                    }
901                    // The user-facing name, without the xlsx import prefixes.
902                    let display_name = name
903                        .trim_start_matches("_xlfn._xlws.")
904                        .trim_start_matches("_xlfn.")
905                        .trim_start_matches("_xlpm.")
906                        .to_string();
907                    let args = match self.parse_function_args(&display_name) {
908                        Ok(s) => s,
909                        Err(e) => return e,
910                    };
911                    if let Err(err) = self.lexer.expect(TokenType::RightParenthesis) {
912                        // `SUM(A1` parses a complete argument and then fails to
913                        // find the `)`. If we ran out of input we are still
914                        // inside the call, sitting right after a complete
915                        // argument: report the (correct) argument index so the
916                        // signature tooltip works, but NOT `Range` — a fresh
917                        // reference cannot begin after a complete operand. (A
918                        // separator or `)` is what is expected here.)
919                        let at_eof = err.position >= self.lexer.get_formula().chars().count();
920                        let expecting = if at_eof {
921                            let index = (args.len() as u32).max(1);
922                            vec![ExpectedTokens::Argument(display_name.clone(), index)]
923                        } else {
924                            vec![ExpectedTokens::Other]
925                        };
926                        return Node::ParseErrorKind {
927                            formula: self.lexer.get_formula(),
928                            expecting,
929                            position: err.position,
930                            message: err.message,
931                        };
932                    }
933                    // We should do this *only* importing functions from xlsx: Implicit Intersection
934                    if &name == "_xlfn.SINGLE" {
935                        if args.len() != 1 {
936                            return Node::ParseErrorKind {
937                                formula: self.lexer.get_formula(),
938                                expecting: vec![ExpectedTokens::Other],
939                                position: self.lexer.get_position() as usize,
940                                message: "Implicit Intersection requires just one argument"
941                                    .to_string(),
942                            };
943                        }
944                        return Node::ImplicitIntersection {
945                            automatic: false,
946                            child: Box::new(args[0].clone()),
947                        };
948                    }
949                    // We should do this *only* importing functions from xlsx: Spill Range Operator
950                    if &name == "_xlfn.ANCHORARRAY" {
951                        if args.len() != 1 {
952                            return Node::ParseErrorKind {
953                                formula: self.lexer.get_formula(),
954                                expecting: vec![ExpectedTokens::Other],
955                                position: self.lexer.get_position() as usize,
956                                message: "ANCHORARRAY requires one argument".to_string(),
957                            };
958                        }
959                        return Node::SpillRangeOperator {
960                            child: Box::new(args[0].clone()),
961                        };
962                    }
963                    // We should do this *only* importing functions from xlsx
964                    if let Some(function_kind) = self
965                        .language
966                        .functions
967                        .lookup(name.trim_start_matches("_xlfn._xlws."))
968                    {
969                        return Node::FunctionKind {
970                            kind: function_kind,
971                            args,
972                        };
973                    }
974
975                    if let Some(function_kind) = self
976                        .language
977                        .functions
978                        .lookup(name.trim_start_matches("_xlfn."))
979                    {
980                        return Node::FunctionKind {
981                            kind: function_kind,
982                            args,
983                        };
984                    }
985                    return Node::NamedFunctionKind {
986                        name: name.trim_start_matches("_xlpm.").to_string(),
987                        args,
988                        id: None,
989                    };
990                }
991                let context = &self.context;
992
993                let context_sheet_index = match self.get_sheet_index_by_name(&context.sheet) {
994                    Some(i) => i,
995                    None => {
996                        return Node::ParseErrorKind {
997                            formula: self.lexer.get_formula(),
998                            expecting: vec![ExpectedTokens::Other],
999                            position: 0,
1000                            message: format!("sheet not found: {}", context.sheet),
1001                        };
1002                    }
1003                };
1004
1005                // Could be a defined name or a table
1006                if let Some((scope, formula)) = self.get_defined_name(&name, context_sheet_index) {
1007                    return Node::DefinedNameKind((name, scope, formula));
1008                }
1009                let name_lower = name.to_lowercase();
1010                for table_name in self.tables.keys() {
1011                    if table_name.to_lowercase() == name_lower {
1012                        return Node::TableNameKind(name);
1013                    }
1014                }
1015                // xlpm: Excel Lambda Parameter
1016                let name = name.trim_start_matches("_xlpm.").to_string();
1017                Node::NamedVariableKind { name, id: None }
1018            }
1019            TokenType::Error(kind) => Node::ErrorKind(kind),
1020            TokenType::Illegal(error) => Node::ParseErrorKind {
1021                formula: self.lexer.get_formula(),
1022                expecting: vec![ExpectedTokens::Other],
1023                position: error.position,
1024                message: error.message,
1025            },
1026            TokenType::EOF => Node::ParseErrorKind {
1027                formula: self.lexer.get_formula(),
1028                // The deepest frame to reach EOF knows what it was expecting.
1029                expecting: self.expecting_here.clone(),
1030                position: self.lexer.get_position() as usize,
1031                message: "Unexpected end of input.".to_string(),
1032            },
1033            TokenType::Boolean(value) => {
1034                // Could be a function call "TRUE()"
1035                let next_token = self.lexer.peek_token();
1036                if next_token == TokenType::LeftParenthesis {
1037                    self.lexer.advance_token();
1038                    // We parse all the arguments, although technically this is moot
1039                    // But is has the upside of transforming `=TRUE( 4 )` into `=TRUE(4)`
1040                    let fn_name = if value { "TRUE" } else { "FALSE" };
1041                    let args = match self.parse_function_args(fn_name) {
1042                        Ok(s) => s,
1043                        Err(e) => return e,
1044                    };
1045                    if let Err(err) = self.lexer.expect(TokenType::RightParenthesis) {
1046                        return Node::ParseErrorKind {
1047                            formula: self.lexer.get_formula(),
1048                            expecting: vec![ExpectedTokens::Other],
1049                            position: err.position,
1050                            message: err.message,
1051                        };
1052                    }
1053                    if value {
1054                        return Node::FunctionKind {
1055                            kind: Function::True,
1056                            args,
1057                        };
1058                    } else {
1059                        return Node::FunctionKind {
1060                            kind: Function::False,
1061                            args,
1062                        };
1063                    }
1064                }
1065                Node::BooleanKind(value)
1066            }
1067            TokenType::Compare(_) => {
1068                // A primary Node cannot start with an operator
1069                Node::ParseErrorKind {
1070                    formula: self.lexer.get_formula(),
1071                    expecting: vec![ExpectedTokens::Other],
1072                    position: 0,
1073                    message: "Unexpected token: 'COMPARE'".to_string(),
1074                }
1075            }
1076            TokenType::Addition(_) => {
1077                // A primary Node cannot start with an operator
1078                Node::ParseErrorKind {
1079                    formula: self.lexer.get_formula(),
1080                    expecting: vec![ExpectedTokens::Other],
1081                    position: 0,
1082                    message: "Unexpected token: 'SUM'".to_string(),
1083                }
1084            }
1085            TokenType::Product(_) => {
1086                // A primary Node cannot start with an operator
1087                Node::ParseErrorKind {
1088                    formula: self.lexer.get_formula(),
1089                    expecting: vec![ExpectedTokens::Other],
1090                    position: 0,
1091                    message: "Unexpected token: 'PRODUCT'".to_string(),
1092                }
1093            }
1094            TokenType::Power => {
1095                // A primary Node cannot start with an operator
1096                Node::ParseErrorKind {
1097                    formula: self.lexer.get_formula(),
1098                    expecting: vec![ExpectedTokens::Other],
1099                    position: 0,
1100                    message: "Unexpected token: 'POWER'".to_string(),
1101                }
1102            }
1103            TokenType::At => {
1104                // A primary Node cannot start with an operator
1105                Node::ParseErrorKind {
1106                    formula: self.lexer.get_formula(),
1107                    expecting: vec![ExpectedTokens::Other],
1108                    position: 0,
1109                    message: "Unexpected token: '@'".to_string(),
1110                }
1111            }
1112            TokenType::RightParenthesis
1113            | TokenType::RightBracket
1114            | TokenType::Colon
1115            | TokenType::Semicolon
1116            | TokenType::Backslash
1117            | TokenType::RightBrace
1118            | TokenType::Comma
1119            | TokenType::Bang
1120            | TokenType::And
1121            | TokenType::Spill
1122            | TokenType::Percent => Node::ParseErrorKind {
1123                formula: self.lexer.get_formula(),
1124                expecting: vec![ExpectedTokens::Other],
1125                position: 0,
1126                message: format!("Unexpected token: '{next_token:?}'"),
1127            },
1128            TokenType::LeftBracket => Node::ParseErrorKind {
1129                formula: self.lexer.get_formula(),
1130                expecting: vec![ExpectedTokens::Other],
1131                position: 0,
1132                message: "Unexpected token: '['".to_string(),
1133            },
1134            TokenType::StructuredReference {
1135                table_name,
1136                specifier,
1137                table_reference,
1138            } => {
1139                // We will try to convert to a normal reference
1140                // table_name[column_name] => cell1:cell2
1141                // table_name[[#This Row], [column_name]:[column_name]] => cell1:cell2
1142                let context = &self.context;
1143                let context_sheet_index = match self.get_sheet_index_by_name(&context.sheet) {
1144                    Some(i) => i,
1145                    None => {
1146                        return Node::ParseErrorKind {
1147                            formula: self.lexer.get_formula(),
1148                            expecting: vec![ExpectedTokens::Other],
1149                            position: 0,
1150                            message: format!("sheet not found: {}", context.sheet),
1151                        };
1152                    }
1153                };
1154                // table-name => table
1155                let table = match self.tables.get(&table_name) {
1156                    Some(t) => t,
1157                    None => {
1158                        let message = format!(
1159                            "Table not found: '{table_name}' at '{}!{}{}'",
1160                            context.sheet,
1161                            number_to_column(context.column)
1162                                .unwrap_or(format!("{}", context.column)),
1163                            context.row
1164                        );
1165                        return Node::ParseErrorKind {
1166                            formula: self.lexer.get_formula(),
1167                            expecting: vec![ExpectedTokens::Other],
1168                            position: 0,
1169                            message,
1170                        };
1171                    }
1172                };
1173                let table_sheet_index = match self.get_sheet_index_by_name(&table.sheet_name) {
1174                    Some(i) => i,
1175                    None => {
1176                        return Node::ParseErrorKind {
1177                            formula: self.lexer.get_formula(),
1178                            expecting: vec![ExpectedTokens::Other],
1179                            position: 0,
1180                            message: format!("table sheet not found: {}", table.sheet_name),
1181                        };
1182                    }
1183                };
1184
1185                let sheet_name = if table_sheet_index == context_sheet_index {
1186                    None
1187                } else {
1188                    Some(table.sheet_name.clone())
1189                };
1190
1191                // context must be with tables.reference
1192                #[allow(clippy::expect_used)]
1193                let (column_start, mut row_start, column_end, mut row_end) =
1194                    parse_range(&table.reference).expect("Failed parsing range");
1195
1196                let totals_row_count = table.totals_row_count as i32;
1197                let header_row_count = table.header_row_count as i32;
1198                row_end -= totals_row_count;
1199
1200                match specifier {
1201                    Some(token::TableSpecifier::ThisRow) => {
1202                        row_start = context.row;
1203                        row_end = context.row;
1204                    }
1205                    Some(token::TableSpecifier::Totals) => {
1206                        if totals_row_count != 0 {
1207                            row_start = row_end + 1;
1208                            row_end = row_start;
1209                        } else {
1210                            // Table1[#Totals] is #REF! if Table1 does not have totals
1211                            return Node::ErrorKind(token::Error::REF);
1212                        }
1213                    }
1214                    Some(token::TableSpecifier::Headers) => {
1215                        row_end = row_start;
1216                    }
1217                    Some(token::TableSpecifier::Data) => {
1218                        row_start += header_row_count;
1219                    }
1220                    Some(token::TableSpecifier::All) => {
1221                        if totals_row_count != 0 {
1222                            row_end += 1;
1223                        }
1224                    }
1225                    None => {
1226                        // skip the headers
1227                        row_start += header_row_count;
1228                    }
1229                }
1230                match table_reference {
1231                    None => Node::RangeKind {
1232                        sheet_name,
1233                        sheet_index: table_sheet_index,
1234                        absolute_row1: true,
1235                        absolute_column1: true,
1236                        row1: row_start,
1237                        column1: column_start,
1238                        absolute_row2: true,
1239                        absolute_column2: true,
1240                        row2: row_end,
1241                        column2: column_end,
1242                    },
1243                    Some(TableReference::ColumnReference(s)) => {
1244                        let column_index = match get_table_column_by_name(&s, table) {
1245                            Some(s) => s + column_start,
1246                            None => {
1247                                return Node::ParseErrorKind {
1248                                    formula: self.lexer.get_formula(),
1249                                    expecting: vec![ExpectedTokens::Other],
1250                                    position: self.lexer.get_position() as usize,
1251                                    message: format!("Expecting column: {s} in table {table_name}"),
1252                                };
1253                            }
1254                        };
1255                        if row_start == row_end {
1256                            return Node::ReferenceKind {
1257                                sheet_name,
1258                                sheet_index: table_sheet_index,
1259                                absolute_row: true,
1260                                absolute_column: true,
1261                                row: row_start,
1262                                column: column_index,
1263                            };
1264                        }
1265                        Node::RangeKind {
1266                            sheet_name,
1267                            sheet_index: table_sheet_index,
1268                            absolute_row1: true,
1269                            absolute_column1: true,
1270                            row1: row_start,
1271                            column1: column_index,
1272                            absolute_row2: true,
1273                            absolute_column2: true,
1274                            row2: row_end,
1275                            column2: column_index,
1276                        }
1277                    }
1278                    Some(TableReference::RangeReference((left, right))) => {
1279                        let left_column_index = match get_table_column_by_name(&left, table) {
1280                            Some(f) => f + column_start,
1281                            None => {
1282                                return Node::ParseErrorKind {
1283                                    formula: self.lexer.get_formula(),
1284                                    expecting: vec![ExpectedTokens::Other],
1285                                    position: self.lexer.get_position() as usize,
1286                                    message: format!(
1287                                        "Expecting column: {left} in table {table_name}"
1288                                    ),
1289                                };
1290                            }
1291                        };
1292
1293                        let right_column_index = match get_table_column_by_name(&right, table) {
1294                            Some(f) => f + column_start,
1295                            None => {
1296                                return Node::ParseErrorKind {
1297                                    formula: self.lexer.get_formula(),
1298                                    expecting: vec![ExpectedTokens::Other],
1299                                    position: self.lexer.get_position() as usize,
1300                                    message: format!(
1301                                        "Expecting column: {right} in table {table_name}"
1302                                    ),
1303                                };
1304                            }
1305                        };
1306                        Node::RangeKind {
1307                            sheet_name,
1308                            sheet_index: table_sheet_index,
1309                            absolute_row1: true,
1310                            absolute_column1: true,
1311                            row1: row_start,
1312                            column1: left_column_index,
1313                            absolute_row2: true,
1314                            absolute_column2: true,
1315                            row2: row_end,
1316                            column2: right_column_index,
1317                        }
1318                    }
1319                }
1320            }
1321        }
1322    }
1323
1324    fn parse_function_args(&mut self, fn_name: &str) -> Result<Vec<Node>, Node> {
1325        let arg_separator_token = &self.get_argument_separator_token();
1326        let mut args: Vec<Node> = Vec::new();
1327        let mut next_token = self.lexer.peek_token();
1328        if next_token == TokenType::RightParenthesis {
1329            return Ok(args);
1330        }
1331        // The cursor is currently in the first argument of `fn_name`.
1332        self.set_argument_hint(fn_name, 1);
1333        if &self.lexer.peek_token() == arg_separator_token {
1334            args.push(Node::EmptyArgKind);
1335        } else {
1336            let t = self.parse_expr();
1337            if let Node::ParseErrorKind { .. } = t {
1338                return Err(t);
1339            }
1340            args.push(t);
1341        }
1342        next_token = self.lexer.peek_token();
1343        let mut arg_index = 1;
1344        while &next_token == arg_separator_token {
1345            self.lexer.advance_token();
1346            arg_index += 1;
1347            self.set_argument_hint(fn_name, arg_index);
1348            if &self.lexer.peek_token() == arg_separator_token {
1349                args.push(Node::EmptyArgKind);
1350                next_token = arg_separator_token.clone();
1351            } else if self.lexer.peek_token() == TokenType::RightParenthesis {
1352                args.push(Node::EmptyArgKind);
1353                return Ok(args);
1354            } else {
1355                let p = self.parse_expr();
1356                if let Node::ParseErrorKind { .. } = p {
1357                    return Err(p);
1358                }
1359                next_token = self.lexer.peek_token();
1360                args.push(p);
1361            }
1362        }
1363        Ok(args)
1364    }
1365
1366    /// Records that the position currently being parsed *starts* argument
1367    /// `index` (1-based) of `fn_name`: a fresh operand goes here, so a `Range`
1368    /// is a valid completion. Reported if an EOF lands on this empty slot (e.g.
1369    /// `SUM(` or `SUM(A1,`). Once the argument is complete the unclosed-call
1370    /// path in `parse_primary` reports the argument context without `Range`.
1371    fn set_argument_hint(&mut self, fn_name: &str, index: u32) {
1372        self.expecting_here = vec![
1373            ExpectedTokens::Argument(fn_name.to_string(), index),
1374            ExpectedTokens::Range,
1375        ];
1376    }
1377}