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        let mut sign = 1;
555        while let TokenType::Addition(op) = next_token {
556            self.lexer.advance_token();
557            if op == token::OpSum::Minus {
558                sign = -sign;
559            }
560            next_token = self.lexer.peek_token();
561        }
562
563        let mut t = self.parse_range();
564        if let Node::ParseErrorKind { .. } = t {
565            return t;
566        }
567        if sign == -1 {
568            t = Node::UnaryKind {
569                kind: token::OpUnary::Minus,
570                right: Box::new(t),
571            }
572        }
573        next_token = self.lexer.peek_token();
574        while next_token == TokenType::Percent {
575            self.lexer.advance_token();
576            t = Node::UnaryKind {
577                kind: token::OpUnary::Percentage,
578                right: Box::new(t),
579            };
580            next_token = self.lexer.peek_token();
581        }
582        t
583    }
584
585    fn parse_range(&mut self) -> Node {
586        let t = self.parse_implicit();
587        if let Node::ParseErrorKind { .. } = t {
588            return t;
589        }
590        let next_token = self.lexer.peek_token();
591        if next_token == TokenType::Colon {
592            self.lexer.advance_token();
593            let p = self.parse_primary();
594            if let Node::ParseErrorKind { .. } = p {
595                return p;
596            }
597            return Node::OpRangeKind {
598                left: Box::new(t),
599                right: Box::new(p),
600            };
601        }
602        t
603    }
604
605    fn parse_implicit(&mut self) -> Node {
606        let next_token = self.lexer.peek_token();
607        if next_token == TokenType::At {
608            self.lexer.advance_token();
609            let t = self.parse_primary();
610            if let Node::ParseErrorKind { .. } = t {
611                return t;
612            }
613            return Node::ImplicitIntersection {
614                automatic: false,
615                child: Box::new(t),
616            };
617        }
618        let primary = self.parse_primary();
619        if let Node::ParseErrorKind { .. } = primary {
620            return primary;
621        }
622        let next_token = self.lexer.peek_token();
623        if next_token == TokenType::Spill {
624            self.lexer.advance_token();
625            return Node::SpillRangeOperator {
626                child: Box::new(primary),
627            };
628        }
629        primary
630    }
631
632    fn parse_array_row(&mut self) -> Result<Vec<ArrayNode>, Node> {
633        let mut row = Vec::new();
634        let column_separator_token = self.get_argument_separator_token();
635        // and array can only have numbers, string or booleans
636        // otherwise it is a syntax error
637        let first_element = match self.parse_expr() {
638            Node::BooleanKind(s) => ArrayNode::Boolean(s),
639            Node::NumberKind(s) => ArrayNode::Number(s),
640            Node::StringKind(s) => ArrayNode::String(s),
641            Node::ErrorKind(kind) => ArrayNode::Error(kind),
642            Node::UnaryKind {
643                kind: OpUnary::Minus,
644                right,
645            } => {
646                if let Node::NumberKind(n) = *right {
647                    ArrayNode::Number(-n)
648                } else {
649                    return Err(Node::ParseErrorKind {
650                        formula: self.lexer.get_formula(),
651                        expecting: vec![ExpectedTokens::Other],
652                        message: "Invalid value in array".to_string(),
653                        position: self.lexer.get_position() as usize,
654                    });
655                }
656            }
657            error @ Node::ParseErrorKind { .. } => return Err(error),
658            _ => {
659                return Err(Node::ParseErrorKind {
660                    formula: self.lexer.get_formula(),
661                    expecting: vec![ExpectedTokens::Other],
662                    message: "Invalid value in array".to_string(),
663                    position: self.lexer.get_position() as usize,
664                });
665            }
666        };
667        row.push(first_element);
668        let mut next_token = self.lexer.peek_token();
669        while next_token == column_separator_token {
670            self.lexer.advance_token();
671            let value = match self.parse_expr() {
672                Node::BooleanKind(s) => ArrayNode::Boolean(s),
673                Node::NumberKind(s) => ArrayNode::Number(s),
674                Node::StringKind(s) => ArrayNode::String(s),
675                Node::ErrorKind(kind) => ArrayNode::Error(kind),
676                Node::UnaryKind {
677                    kind: OpUnary::Minus,
678                    right,
679                } => {
680                    if let Node::NumberKind(n) = *right {
681                        ArrayNode::Number(-n)
682                    } else {
683                        return Err(Node::ParseErrorKind {
684                            formula: self.lexer.get_formula(),
685                            expecting: vec![ExpectedTokens::Other],
686                            message: "Invalid value in array".to_string(),
687                            position: self.lexer.get_position() as usize,
688                        });
689                    }
690                }
691                error @ Node::ParseErrorKind { .. } => return Err(error),
692                _ => {
693                    return Err(Node::ParseErrorKind {
694                        formula: self.lexer.get_formula(),
695                        expecting: vec![ExpectedTokens::Other],
696                        message: "Invalid value in array".to_string(),
697                        position: self.lexer.get_position() as usize,
698                    });
699                }
700            };
701            row.push(value);
702            next_token = self.lexer.peek_token();
703        }
704        Ok(row)
705    }
706
707    fn parse_primary(&mut self) -> Node {
708        let next_token = self.lexer.next_token();
709        match next_token {
710            TokenType::LeftParenthesis => {
711                let t = self.parse_expr();
712                if let Node::ParseErrorKind { .. } = t {
713                    return t;
714                }
715
716                if let Err(err) = self.lexer.expect(TokenType::RightParenthesis) {
717                    return Node::ParseErrorKind {
718                        formula: self.lexer.get_formula(),
719                        expecting: vec![ExpectedTokens::Other],
720                        position: err.position,
721                        message: err.message,
722                    };
723                }
724                t
725            }
726            TokenType::Number(s) => Node::NumberKind(s),
727            TokenType::String(s) => Node::StringKind(s),
728            TokenType::LeftBrace => {
729                // It's an array. It's a collection of rows all of the same dimension
730                let column_separator_token = self.get_column_separator_token();
731
732                let first_row = match self.parse_array_row() {
733                    Ok(s) => s,
734                    Err(error) => return error,
735                };
736                let length = first_row.len();
737
738                let mut matrix = Vec::new();
739                matrix.push(first_row);
740                let mut next_token = self.lexer.peek_token();
741                while next_token == column_separator_token {
742                    self.lexer.advance_token();
743                    let row = match self.parse_array_row() {
744                        Ok(s) => s,
745                        Err(error) => return error,
746                    };
747                    next_token = self.lexer.peek_token();
748                    if row.len() != length {
749                        return Node::ParseErrorKind {
750                            formula: self.lexer.get_formula(),
751                            expecting: vec![ExpectedTokens::Other],
752                            position: self.lexer.get_position() as usize,
753                            message: "All rows in an array should be the same length".to_string(),
754                        };
755                    }
756                    matrix.push(row);
757                }
758
759                if let Err(err) = self.lexer.expect(TokenType::RightBrace) {
760                    return Node::ParseErrorKind {
761                        formula: self.lexer.get_formula(),
762                        expecting: vec![ExpectedTokens::Other],
763                        position: err.position,
764                        message: err.message,
765                    };
766                }
767                Node::ArrayKind(matrix)
768            }
769            TokenType::Reference {
770                sheet,
771                row,
772                column,
773                absolute_column,
774                absolute_row,
775            } => {
776                let context = &self.context;
777                let sheet_index = match &sheet {
778                    Some(name) => self.get_sheet_index_by_name(name),
779                    None => self.get_sheet_index_by_name(&context.sheet),
780                };
781                let a1_mode = self.lexer.is_a1_mode();
782                let row = if absolute_row || !a1_mode {
783                    row
784                } else {
785                    row - context.row
786                };
787                let column = if absolute_column || !a1_mode {
788                    column
789                } else {
790                    column - context.column
791                };
792                match sheet_index {
793                    Some(index) => Node::ReferenceKind {
794                        sheet_name: sheet,
795                        sheet_index: index,
796                        row,
797                        column,
798                        absolute_row,
799                        absolute_column,
800                    },
801                    None => Node::WrongReferenceKind {
802                        sheet_name: sheet,
803                        row,
804                        column,
805                        absolute_row,
806                        absolute_column,
807                    },
808                }
809            }
810            TokenType::Range { sheet, left, right } => {
811                let context = &self.context;
812                let sheet_index = match &sheet {
813                    Some(name) => self.get_sheet_index_by_name(name),
814                    None => self.get_sheet_index_by_name(&context.sheet),
815                };
816                let mut row1 = left.row;
817                let mut column1 = left.column;
818                let mut row2 = right.row;
819                let mut column2 = right.column;
820
821                let mut absolute_column1 = left.absolute_column;
822                let mut absolute_column2 = right.absolute_column;
823                let mut absolute_row1 = left.absolute_row;
824                let mut absolute_row2 = right.absolute_row;
825
826                if self.lexer.is_a1_mode() {
827                    if row1 > row2 {
828                        (row2, row1) = (row1, row2);
829                        (absolute_row2, absolute_row1) = (absolute_row1, absolute_row2);
830                    }
831                    if column1 > column2 {
832                        (column2, column1) = (column1, column2);
833                        (absolute_column2, absolute_column1) = (absolute_column1, absolute_column2);
834                    }
835                }
836
837                if self.lexer.is_a1_mode() {
838                    if !absolute_row1 {
839                        row1 -= context.row
840                    };
841                    if !absolute_column1 {
842                        column1 -= context.column
843                    };
844                    if !absolute_row2 {
845                        row2 -= context.row
846                    };
847                    if !absolute_column2 {
848                        column2 -= context.column
849                    };
850                }
851
852                match sheet_index {
853                    Some(index) => Node::RangeKind {
854                        sheet_name: sheet,
855                        sheet_index: index,
856                        row1,
857                        column1,
858                        row2,
859                        column2,
860                        absolute_column1,
861                        absolute_column2,
862                        absolute_row1,
863                        absolute_row2,
864                    },
865                    None => Node::WrongRangeKind {
866                        sheet_name: sheet,
867                        row1,
868                        column1,
869                        row2,
870                        column2,
871                        absolute_column1,
872                        absolute_column2,
873                        absolute_row1,
874                        absolute_row2,
875                    },
876                }
877            }
878            TokenType::Ident(name) => {
879                let next_token = self.lexer.peek_token();
880                // If this identifier is the last token before the cursor (its
881                // peek is EOF), the user is mid-typing a name here. Record it so
882                // `parse_at_cursor` can offer function/name completion. We are in
883                // a name/operand position by construction, so this never fires
884                // for an identifier glued to a completed operand: the `m` in
885                // `1m` is leftover input, never reached as a primary.
886                if next_token == TokenType::EOF {
887                    let end = self.lexer.get_position() as usize;
888                    let start = end.saturating_sub(name.chars().count());
889                    self.trailing_name = Some((name.clone(), start));
890                }
891                if next_token == TokenType::LeftParenthesis {
892                    self.lexer.advance_token();
893                    // It's a function call "SUM(.."
894                    // _xlfn.LAMBDA(_xlpm.a,_xlpm.b, SQRT(_xlpm.a*_xlpm.a+_xlpm.b*_xlpm.b))(3,4)
895                    if &name == "_xlfn.LAMBDA" || &name.to_uppercase() == "LAMBDA" {
896                        return self.parse_lambda();
897                    }
898                    // The user-facing name, without the xlsx import prefixes.
899                    let display_name = name
900                        .trim_start_matches("_xlfn._xlws.")
901                        .trim_start_matches("_xlfn.")
902                        .trim_start_matches("_xlpm.")
903                        .to_string();
904                    let args = match self.parse_function_args(&display_name) {
905                        Ok(s) => s,
906                        Err(e) => return e,
907                    };
908                    if let Err(err) = self.lexer.expect(TokenType::RightParenthesis) {
909                        // `SUM(A1` parses a complete argument and then fails to
910                        // find the `)`. If we ran out of input we are still
911                        // inside the call, sitting right after a complete
912                        // argument: report the (correct) argument index so the
913                        // signature tooltip works, but NOT `Range` — a fresh
914                        // reference cannot begin after a complete operand. (A
915                        // separator or `)` is what is expected here.)
916                        let at_eof = err.position >= self.lexer.get_formula().chars().count();
917                        let expecting = if at_eof {
918                            let index = (args.len() as u32).max(1);
919                            vec![ExpectedTokens::Argument(display_name.clone(), index)]
920                        } else {
921                            vec![ExpectedTokens::Other]
922                        };
923                        return Node::ParseErrorKind {
924                            formula: self.lexer.get_formula(),
925                            expecting,
926                            position: err.position,
927                            message: err.message,
928                        };
929                    }
930                    // We should do this *only* importing functions from xlsx: Implicit Intersection
931                    if &name == "_xlfn.SINGLE" {
932                        if args.len() != 1 {
933                            return Node::ParseErrorKind {
934                                formula: self.lexer.get_formula(),
935                                expecting: vec![ExpectedTokens::Other],
936                                position: self.lexer.get_position() as usize,
937                                message: "Implicit Intersection requires just one argument"
938                                    .to_string(),
939                            };
940                        }
941                        return Node::ImplicitIntersection {
942                            automatic: false,
943                            child: Box::new(args[0].clone()),
944                        };
945                    }
946                    // We should do this *only* importing functions from xlsx: Spill Range Operator
947                    if &name == "_xlfn.ANCHORARRAY" {
948                        if args.len() != 1 {
949                            return Node::ParseErrorKind {
950                                formula: self.lexer.get_formula(),
951                                expecting: vec![ExpectedTokens::Other],
952                                position: self.lexer.get_position() as usize,
953                                message: "ANCHORARRAY requires one argument".to_string(),
954                            };
955                        }
956                        return Node::SpillRangeOperator {
957                            child: Box::new(args[0].clone()),
958                        };
959                    }
960                    // We should do this *only* importing functions from xlsx
961                    if let Some(function_kind) = self
962                        .language
963                        .functions
964                        .lookup(name.trim_start_matches("_xlfn._xlws."))
965                    {
966                        return Node::FunctionKind {
967                            kind: function_kind,
968                            args,
969                        };
970                    }
971
972                    if let Some(function_kind) = self
973                        .language
974                        .functions
975                        .lookup(name.trim_start_matches("_xlfn."))
976                    {
977                        return Node::FunctionKind {
978                            kind: function_kind,
979                            args,
980                        };
981                    }
982                    return Node::NamedFunctionKind {
983                        name: name.trim_start_matches("_xlpm.").to_string(),
984                        args,
985                        id: None,
986                    };
987                }
988                let context = &self.context;
989
990                let context_sheet_index = match self.get_sheet_index_by_name(&context.sheet) {
991                    Some(i) => i,
992                    None => {
993                        return Node::ParseErrorKind {
994                            formula: self.lexer.get_formula(),
995                            expecting: vec![ExpectedTokens::Other],
996                            position: 0,
997                            message: format!("sheet not found: {}", context.sheet),
998                        };
999                    }
1000                };
1001
1002                // Could be a defined name or a table
1003                if let Some((scope, formula)) = self.get_defined_name(&name, context_sheet_index) {
1004                    return Node::DefinedNameKind((name, scope, formula));
1005                }
1006                let name_lower = name.to_lowercase();
1007                for table_name in self.tables.keys() {
1008                    if table_name.to_lowercase() == name_lower {
1009                        return Node::TableNameKind(name);
1010                    }
1011                }
1012                // xlpm: Excel Lambda Parameter
1013                let name = name.trim_start_matches("_xlpm.").to_string();
1014                Node::NamedVariableKind { name, id: None }
1015            }
1016            TokenType::Error(kind) => Node::ErrorKind(kind),
1017            TokenType::Illegal(error) => Node::ParseErrorKind {
1018                formula: self.lexer.get_formula(),
1019                expecting: vec![ExpectedTokens::Other],
1020                position: error.position,
1021                message: error.message,
1022            },
1023            TokenType::EOF => Node::ParseErrorKind {
1024                formula: self.lexer.get_formula(),
1025                // The deepest frame to reach EOF knows what it was expecting.
1026                expecting: self.expecting_here.clone(),
1027                position: self.lexer.get_position() as usize,
1028                message: "Unexpected end of input.".to_string(),
1029            },
1030            TokenType::Boolean(value) => {
1031                // Could be a function call "TRUE()"
1032                let next_token = self.lexer.peek_token();
1033                if next_token == TokenType::LeftParenthesis {
1034                    self.lexer.advance_token();
1035                    // We parse all the arguments, although technically this is moot
1036                    // But is has the upside of transforming `=TRUE( 4 )` into `=TRUE(4)`
1037                    let fn_name = if value { "TRUE" } else { "FALSE" };
1038                    let args = match self.parse_function_args(fn_name) {
1039                        Ok(s) => s,
1040                        Err(e) => return e,
1041                    };
1042                    if let Err(err) = self.lexer.expect(TokenType::RightParenthesis) {
1043                        return Node::ParseErrorKind {
1044                            formula: self.lexer.get_formula(),
1045                            expecting: vec![ExpectedTokens::Other],
1046                            position: err.position,
1047                            message: err.message,
1048                        };
1049                    }
1050                    if value {
1051                        return Node::FunctionKind {
1052                            kind: Function::True,
1053                            args,
1054                        };
1055                    } else {
1056                        return Node::FunctionKind {
1057                            kind: Function::False,
1058                            args,
1059                        };
1060                    }
1061                }
1062                Node::BooleanKind(value)
1063            }
1064            TokenType::Compare(_) => {
1065                // A primary Node cannot start with an operator
1066                Node::ParseErrorKind {
1067                    formula: self.lexer.get_formula(),
1068                    expecting: vec![ExpectedTokens::Other],
1069                    position: 0,
1070                    message: "Unexpected token: 'COMPARE'".to_string(),
1071                }
1072            }
1073            TokenType::Addition(_) => {
1074                // A primary Node cannot start with an operator
1075                Node::ParseErrorKind {
1076                    formula: self.lexer.get_formula(),
1077                    expecting: vec![ExpectedTokens::Other],
1078                    position: 0,
1079                    message: "Unexpected token: 'SUM'".to_string(),
1080                }
1081            }
1082            TokenType::Product(_) => {
1083                // A primary Node cannot start with an operator
1084                Node::ParseErrorKind {
1085                    formula: self.lexer.get_formula(),
1086                    expecting: vec![ExpectedTokens::Other],
1087                    position: 0,
1088                    message: "Unexpected token: 'PRODUCT'".to_string(),
1089                }
1090            }
1091            TokenType::Power => {
1092                // A primary Node cannot start with an operator
1093                Node::ParseErrorKind {
1094                    formula: self.lexer.get_formula(),
1095                    expecting: vec![ExpectedTokens::Other],
1096                    position: 0,
1097                    message: "Unexpected token: 'POWER'".to_string(),
1098                }
1099            }
1100            TokenType::At => {
1101                // A primary Node cannot start with an operator
1102                Node::ParseErrorKind {
1103                    formula: self.lexer.get_formula(),
1104                    expecting: vec![ExpectedTokens::Other],
1105                    position: 0,
1106                    message: "Unexpected token: '@'".to_string(),
1107                }
1108            }
1109            TokenType::RightParenthesis
1110            | TokenType::RightBracket
1111            | TokenType::Colon
1112            | TokenType::Semicolon
1113            | TokenType::Backslash
1114            | TokenType::RightBrace
1115            | TokenType::Comma
1116            | TokenType::Bang
1117            | TokenType::And
1118            | TokenType::Spill
1119            | TokenType::Percent => Node::ParseErrorKind {
1120                formula: self.lexer.get_formula(),
1121                expecting: vec![ExpectedTokens::Other],
1122                position: 0,
1123                message: format!("Unexpected token: '{next_token:?}'"),
1124            },
1125            TokenType::LeftBracket => Node::ParseErrorKind {
1126                formula: self.lexer.get_formula(),
1127                expecting: vec![ExpectedTokens::Other],
1128                position: 0,
1129                message: "Unexpected token: '['".to_string(),
1130            },
1131            TokenType::StructuredReference {
1132                table_name,
1133                specifier,
1134                table_reference,
1135            } => {
1136                // We will try to convert to a normal reference
1137                // table_name[column_name] => cell1:cell2
1138                // table_name[[#This Row], [column_name]:[column_name]] => cell1:cell2
1139                let context = &self.context;
1140                let context_sheet_index = match self.get_sheet_index_by_name(&context.sheet) {
1141                    Some(i) => i,
1142                    None => {
1143                        return Node::ParseErrorKind {
1144                            formula: self.lexer.get_formula(),
1145                            expecting: vec![ExpectedTokens::Other],
1146                            position: 0,
1147                            message: format!("sheet not found: {}", context.sheet),
1148                        };
1149                    }
1150                };
1151                // table-name => table
1152                let table = match self.tables.get(&table_name) {
1153                    Some(t) => t,
1154                    None => {
1155                        let message = format!(
1156                            "Table not found: '{table_name}' at '{}!{}{}'",
1157                            context.sheet,
1158                            number_to_column(context.column)
1159                                .unwrap_or(format!("{}", context.column)),
1160                            context.row
1161                        );
1162                        return Node::ParseErrorKind {
1163                            formula: self.lexer.get_formula(),
1164                            expecting: vec![ExpectedTokens::Other],
1165                            position: 0,
1166                            message,
1167                        };
1168                    }
1169                };
1170                let table_sheet_index = match self.get_sheet_index_by_name(&table.sheet_name) {
1171                    Some(i) => i,
1172                    None => {
1173                        return Node::ParseErrorKind {
1174                            formula: self.lexer.get_formula(),
1175                            expecting: vec![ExpectedTokens::Other],
1176                            position: 0,
1177                            message: format!("table sheet not found: {}", table.sheet_name),
1178                        };
1179                    }
1180                };
1181
1182                let sheet_name = if table_sheet_index == context_sheet_index {
1183                    None
1184                } else {
1185                    Some(table.sheet_name.clone())
1186                };
1187
1188                // context must be with tables.reference
1189                #[allow(clippy::expect_used)]
1190                let (column_start, mut row_start, column_end, mut row_end) =
1191                    parse_range(&table.reference).expect("Failed parsing range");
1192
1193                let totals_row_count = table.totals_row_count as i32;
1194                let header_row_count = table.header_row_count as i32;
1195                row_end -= totals_row_count;
1196
1197                match specifier {
1198                    Some(token::TableSpecifier::ThisRow) => {
1199                        row_start = context.row;
1200                        row_end = context.row;
1201                    }
1202                    Some(token::TableSpecifier::Totals) => {
1203                        if totals_row_count != 0 {
1204                            row_start = row_end + 1;
1205                            row_end = row_start;
1206                        } else {
1207                            // Table1[#Totals] is #REF! if Table1 does not have totals
1208                            return Node::ErrorKind(token::Error::REF);
1209                        }
1210                    }
1211                    Some(token::TableSpecifier::Headers) => {
1212                        row_end = row_start;
1213                    }
1214                    Some(token::TableSpecifier::Data) => {
1215                        row_start += header_row_count;
1216                    }
1217                    Some(token::TableSpecifier::All) => {
1218                        if totals_row_count != 0 {
1219                            row_end += 1;
1220                        }
1221                    }
1222                    None => {
1223                        // skip the headers
1224                        row_start += header_row_count;
1225                    }
1226                }
1227                match table_reference {
1228                    None => Node::RangeKind {
1229                        sheet_name,
1230                        sheet_index: table_sheet_index,
1231                        absolute_row1: true,
1232                        absolute_column1: true,
1233                        row1: row_start,
1234                        column1: column_start,
1235                        absolute_row2: true,
1236                        absolute_column2: true,
1237                        row2: row_end,
1238                        column2: column_end,
1239                    },
1240                    Some(TableReference::ColumnReference(s)) => {
1241                        let column_index = match get_table_column_by_name(&s, table) {
1242                            Some(s) => s + column_start,
1243                            None => {
1244                                return Node::ParseErrorKind {
1245                                    formula: self.lexer.get_formula(),
1246                                    expecting: vec![ExpectedTokens::Other],
1247                                    position: self.lexer.get_position() as usize,
1248                                    message: format!("Expecting column: {s} in table {table_name}"),
1249                                };
1250                            }
1251                        };
1252                        if row_start == row_end {
1253                            return Node::ReferenceKind {
1254                                sheet_name,
1255                                sheet_index: table_sheet_index,
1256                                absolute_row: true,
1257                                absolute_column: true,
1258                                row: row_start,
1259                                column: column_index,
1260                            };
1261                        }
1262                        Node::RangeKind {
1263                            sheet_name,
1264                            sheet_index: table_sheet_index,
1265                            absolute_row1: true,
1266                            absolute_column1: true,
1267                            row1: row_start,
1268                            column1: column_index,
1269                            absolute_row2: true,
1270                            absolute_column2: true,
1271                            row2: row_end,
1272                            column2: column_index,
1273                        }
1274                    }
1275                    Some(TableReference::RangeReference((left, right))) => {
1276                        let left_column_index = match get_table_column_by_name(&left, table) {
1277                            Some(f) => f + column_start,
1278                            None => {
1279                                return Node::ParseErrorKind {
1280                                    formula: self.lexer.get_formula(),
1281                                    expecting: vec![ExpectedTokens::Other],
1282                                    position: self.lexer.get_position() as usize,
1283                                    message: format!(
1284                                        "Expecting column: {left} in table {table_name}"
1285                                    ),
1286                                };
1287                            }
1288                        };
1289
1290                        let right_column_index = match get_table_column_by_name(&right, table) {
1291                            Some(f) => f + column_start,
1292                            None => {
1293                                return Node::ParseErrorKind {
1294                                    formula: self.lexer.get_formula(),
1295                                    expecting: vec![ExpectedTokens::Other],
1296                                    position: self.lexer.get_position() as usize,
1297                                    message: format!(
1298                                        "Expecting column: {right} in table {table_name}"
1299                                    ),
1300                                };
1301                            }
1302                        };
1303                        Node::RangeKind {
1304                            sheet_name,
1305                            sheet_index: table_sheet_index,
1306                            absolute_row1: true,
1307                            absolute_column1: true,
1308                            row1: row_start,
1309                            column1: left_column_index,
1310                            absolute_row2: true,
1311                            absolute_column2: true,
1312                            row2: row_end,
1313                            column2: right_column_index,
1314                        }
1315                    }
1316                }
1317            }
1318        }
1319    }
1320
1321    fn parse_function_args(&mut self, fn_name: &str) -> Result<Vec<Node>, Node> {
1322        let arg_separator_token = &self.get_argument_separator_token();
1323        let mut args: Vec<Node> = Vec::new();
1324        let mut next_token = self.lexer.peek_token();
1325        if next_token == TokenType::RightParenthesis {
1326            return Ok(args);
1327        }
1328        // The cursor is currently in the first argument of `fn_name`.
1329        self.set_argument_hint(fn_name, 1);
1330        if &self.lexer.peek_token() == arg_separator_token {
1331            args.push(Node::EmptyArgKind);
1332        } else {
1333            let t = self.parse_expr();
1334            if let Node::ParseErrorKind { .. } = t {
1335                return Err(t);
1336            }
1337            args.push(t);
1338        }
1339        next_token = self.lexer.peek_token();
1340        let mut arg_index = 1;
1341        while &next_token == arg_separator_token {
1342            self.lexer.advance_token();
1343            arg_index += 1;
1344            self.set_argument_hint(fn_name, arg_index);
1345            if &self.lexer.peek_token() == arg_separator_token {
1346                args.push(Node::EmptyArgKind);
1347                next_token = arg_separator_token.clone();
1348            } else if self.lexer.peek_token() == TokenType::RightParenthesis {
1349                args.push(Node::EmptyArgKind);
1350                return Ok(args);
1351            } else {
1352                let p = self.parse_expr();
1353                if let Node::ParseErrorKind { .. } = p {
1354                    return Err(p);
1355                }
1356                next_token = self.lexer.peek_token();
1357                args.push(p);
1358            }
1359        }
1360        Ok(args)
1361    }
1362
1363    /// Records that the position currently being parsed *starts* argument
1364    /// `index` (1-based) of `fn_name`: a fresh operand goes here, so a `Range`
1365    /// is a valid completion. Reported if an EOF lands on this empty slot (e.g.
1366    /// `SUM(` or `SUM(A1,`). Once the argument is complete the unclosed-call
1367    /// path in `parse_primary` reports the argument context without `Range`.
1368    fn set_argument_hint(&mut self, fn_name: &str, index: u32) {
1369        self.expecting_here = vec![
1370            ExpectedTokens::Argument(fn_name.to_string(), index),
1371            ExpectedTokens::Range,
1372        ];
1373    }
1374}