Skip to main content

office_rs/xlsx/formulas/
mod.rs

1//! Excel公式模块
2//! 提供公式解析、计算和函数库功能
3
4use crate::error::{ OfficeError, Result, XlsxError };
5use crate::xlsx::cell::{ CellReference, CellValue };
6use std::collections::{ HashMap, HashSet };
7use std::fmt;
8
9// 导入子模块
10mod formula_calculator;
11mod formula_manager;
12
13// pub use formula_calculator::*;
14pub use formula_manager::*;
15
16/// 公式值类型
17#[derive(Debug, Clone, PartialEq)]
18pub enum FormulaValue {
19    /// 数字值
20    Number(f64),
21    /// 文本值
22    Text(String),
23    /// 布尔值
24    Boolean(bool),
25    /// 错误值
26    Error(FormulaError),
27    /// 数组值
28    Array(Vec<Vec<FormulaValue>>),
29}
30
31/// 公式错误类型
32#[derive(Debug, Clone, PartialEq)]
33pub enum FormulaError {
34    /// 除零错误 #DIV/0!
35    DivisionByZero,
36    /// 值错误 #VALUE!
37    ValueError,
38    /// 引用错误 #REF!
39    ReferenceError,
40    /// 名称错误 #NAME?
41    NameError,
42    /// 数字错误 #NUM!
43    NumError,
44    /// 不可用 #N/A
45    NotAvailable,
46    /// 空值错误 #NULL!
47    NullError,
48    /// 数组溢出 #SPILL!
49    SpillError,
50}
51
52/// 公式表达式节点
53#[derive(Debug, Clone, PartialEq)]
54pub enum FormulaExpression {
55    /// 常量值
56    Constant(FormulaValue),
57    /// 单元格引用
58    CellRef(CellReference),
59    /// 范围引用
60    RangeRef(CellReference, CellReference),
61    /// 函数调用
62    Function {
63        name: String,
64        args: Vec<FormulaExpression>,
65    },
66    /// 二元操作
67    BinaryOp {
68        op: BinaryOperator,
69        left: Box<FormulaExpression>,
70        right: Box<FormulaExpression>,
71    },
72    /// 一元操作
73    UnaryOp {
74        op: UnaryOperator,
75        operand: Box<FormulaExpression>,
76    },
77}
78
79/// 二元操作符
80#[derive(Debug, Clone, PartialEq)]
81pub enum BinaryOperator {
82    /// 加法
83    Add,
84    /// 减法
85    Subtract,
86    /// 乘法
87    Multiply,
88    /// 除法
89    Divide,
90    /// 幂运算
91    Power,
92    /// 等于
93    Equal,
94    /// 不等于
95    NotEqual,
96    /// 小于
97    LessThan,
98    /// 小于等于
99    LessThanOrEqual,
100    /// 大于
101    GreaterThan,
102    /// 大于等于
103    GreaterThanOrEqual,
104    /// 字符串连接
105    Concatenate,
106    /// 逻辑或
107    LogicalOr,
108    /// 逻辑与
109    LogicalAnd,
110}
111
112/// 一元操作符
113#[derive(Debug, Clone, PartialEq)]
114pub enum UnaryOperator {
115    /// 正号
116    Plus,
117    /// 负号
118    Minus,
119    /// 百分号
120    Percent,
121    /// 阶乘
122    Factorial,
123}
124
125/// 公式词法单元
126#[derive(Debug, Clone, PartialEq)]
127pub enum Token {
128    /// 数字
129    Number(f64),
130    /// 字符串
131    String(String),
132    /// 标识符(函数名或命名范围)
133    Identifier(String),
134    /// 单元格引用
135    CellReference(String),
136    /// 操作符
137    Operator(String),
138    /// 左括号
139    LeftParen,
140    /// 右括号
141    RightParen,
142    /// 逗号
143    Comma,
144    /// 冒号(范围分隔符)
145    Colon,
146    /// 分号
147    Semicolon,
148    /// 文件结束
149    Eof,
150}
151
152/// 公式解析器
153pub struct FormulaParser {
154    tokens: Vec<Token>,
155    current: usize,
156}
157
158/// 公式计算器
159pub struct FormulaCalculator {
160    /// 单元格数据提供者
161    cell_provider: Box<dyn CellProvider>,
162    /// 函数库
163    function_library: FunctionLibrary,
164    /// 计算缓存
165    cache: HashMap<String, FormulaValue>,
166}
167
168/// 单元格数据提供者接口
169pub trait CellProvider {
170    /// 获取单元格值
171    fn get_cell_value(&self, reference: &CellReference) -> Result<CellValue>;
172
173    /// 获取范围内的所有单元格值
174    fn get_range_values(
175        &self,
176        start: &CellReference,
177        end: &CellReference
178    ) -> Result<Vec<Vec<CellValue>>>;
179}
180
181/// 函数库
182pub struct FunctionLibrary {
183    functions: HashMap<String, Box<dyn FormulaFunction>>,
184}
185
186/// 公式函数接口
187pub trait FormulaFunction {
188    /// 函数名称
189    fn name(&self) -> &str;
190
191    /// 最小参数数量
192    fn min_args(&self) -> usize;
193
194    /// 最大参数数量(None表示无限制)
195    fn max_args(&self) -> Option<usize>;
196
197    /// 执行函数
198    fn execute(&self, args: &[FormulaValue]) -> Result<FormulaValue>;
199}
200
201/// 公式依赖关系
202#[derive(Debug, Clone)]
203pub struct FormulaDependency {
204    /// 公式所在单元格
205    pub formula_cell: CellReference,
206    /// 依赖的单元格
207    pub dependent_cells: HashSet<CellReference>,
208}
209
210/// 公式管理器
211pub struct FormulaManager {
212    /// 公式表达式缓存
213    formulas: HashMap<CellReference, FormulaExpression>,
214    /// 依赖关系图
215    dependencies: HashMap<CellReference, FormulaDependency>,
216    /// 计算器
217    calculator: FormulaCalculator,
218}
219
220impl fmt::Display for FormulaError {
221    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
222        match self {
223            FormulaError::DivisionByZero => write!(f, "#DIV/0!"),
224            FormulaError::ValueError => write!(f, "#VALUE!"),
225            FormulaError::ReferenceError => write!(f, "#REF!"),
226            FormulaError::NameError => write!(f, "#NAME?"),
227            FormulaError::NumError => write!(f, "#NUM!"),
228            FormulaError::NotAvailable => write!(f, "#N/A"),
229            FormulaError::NullError => write!(f, "#NULL!"),
230            FormulaError::SpillError => write!(f, "#SPILL!"),
231        }
232    }
233}
234
235impl FormulaValue {
236    /// 转换为数字
237    pub fn as_number(&self) -> Result<f64> {
238        match self {
239            FormulaValue::Number(n) => Ok(*n),
240            FormulaValue::Boolean(b) => Ok(if *b { 1.0 } else { 0.0 }),
241            FormulaValue::Text(s) =>
242                s.parse::<f64>().map_err(|_| {
243                    OfficeError::Xlsx(XlsxError::InvalidFormula {
244                        formula: format!("Cannot convert '{}' to number", s),
245                    })
246                }),
247            FormulaValue::Error(e) =>
248                Err(
249                    OfficeError::Xlsx(XlsxError::InvalidFormula {
250                        formula: format!("Formula error: {:?}", e),
251                    })
252                ),
253            FormulaValue::Array(_) =>
254                Err(
255                    OfficeError::Xlsx(XlsxError::InvalidFormula {
256                        formula: "Cannot convert array to number".to_string(),
257                    })
258                ),
259        }
260    }
261
262    /// 转换为文本
263    pub fn as_text(&self) -> String {
264        match self {
265            FormulaValue::Number(n) => n.to_string(),
266            FormulaValue::Text(s) => s.clone(),
267            FormulaValue::Boolean(b) => b.to_string().to_uppercase(),
268            FormulaValue::Error(e) => e.to_string(),
269            FormulaValue::Array(_) => "#VALUE!".to_string(),
270        }
271    }
272
273    /// 转换为布尔值
274    pub fn as_boolean(&self) -> Result<bool> {
275        match self {
276            FormulaValue::Boolean(b) => Ok(*b),
277            FormulaValue::Number(n) => Ok(*n != 0.0),
278            FormulaValue::Text(s) =>
279                match s.to_uppercase().as_str() {
280                    "TRUE" => Ok(true),
281                    "FALSE" => Ok(false),
282                    _ =>
283                        Err(
284                            OfficeError::Xlsx(XlsxError::InvalidFormula {
285                                formula: format!("Cannot convert '{}' to boolean", s),
286                            })
287                        ),
288                }
289            FormulaValue::Error(e) =>
290                Err(
291                    OfficeError::Xlsx(XlsxError::InvalidFormula {
292                        formula: format!("Formula error: {:?}", e),
293                    })
294                ),
295            FormulaValue::Array(_) =>
296                Err(
297                    OfficeError::Xlsx(XlsxError::InvalidFormula {
298                        formula: "Cannot convert array to boolean".to_string(),
299                    })
300                ),
301        }
302    }
303
304    /// 判断是否为错误值
305    pub fn is_error(&self) -> bool {
306        matches!(self, FormulaValue::Error(_))
307    }
308
309    /// 判断是否为数字
310    pub fn is_number(&self) -> bool {
311        matches!(self, FormulaValue::Number(_))
312    }
313
314    /// 判断是否为文本
315    pub fn is_text(&self) -> bool {
316        matches!(self, FormulaValue::Text(_))
317    }
318
319    /// 判断是否为布尔值
320    pub fn is_boolean(&self) -> bool {
321        matches!(self, FormulaValue::Boolean(_))
322    }
323}
324
325impl FormulaParser {
326    /// 创建新的公式解析器
327    pub fn new(formula: &str) -> Result<Self> {
328        let tokens = Self::tokenize(formula)?;
329        Ok(Self { tokens, current: 0 })
330    }
331
332    /// 解析公式
333    pub fn parse(&mut self) -> Result<FormulaExpression> {
334        self.parse_expression()
335    }
336
337    /// 词法分析
338    fn tokenize(formula: &str) -> Result<Vec<Token>> {
339        let mut tokens = Vec::new();
340        let mut chars = formula.chars().peekable();
341
342        while let Some(&ch) = chars.peek() {
343            match ch {
344                ' ' | '\t' | '\n' | '\r' => {
345                    chars.next();
346                }
347                '(' => {
348                    tokens.push(Token::LeftParen);
349                    chars.next();
350                }
351                ')' => {
352                    tokens.push(Token::RightParen);
353                    chars.next();
354                }
355                ',' => {
356                    tokens.push(Token::Comma);
357                    chars.next();
358                }
359                ':' => {
360                    tokens.push(Token::Colon);
361                    chars.next();
362                }
363                ';' => {
364                    tokens.push(Token::Semicolon);
365                    chars.next();
366                }
367                '+' | '-' | '*' | '/' | '^' | '=' | '<' | '>' | '&' | '|' | '%' => {
368                    let mut op = String::new();
369                    op.push(chars.next().unwrap());
370
371                    // 处理复合操作符
372                    // if let Some(&next_ch) = chars.peek() {
373                    //     if
374                    //         (ch == '<' && next_ch == '=') ||
375                    //         (ch == '>' && next_ch == '=') ||
376                    //         (ch == '<' && next_ch == '>')
377                    //     {
378                    //         op.push(chars.next().unwrap());
379                    //     } else {
380                    //         return Err(
381                    //             OfficeError::Xlsx(XlsxError::InvalidFormula {
382                    //                 formula: format!("Unexpected character after operator: {}", next_ch),
383                    //             })
384                    //         );
385                    //     }
386                    // }
387
388                    // 预先定义有效的双字符操作符
389                    let valid_double_ops = [
390                        "<=", // 小于等于
391                        ">=", // 大于等于
392                        "<>", // 比较
393                    ];
394
395                    if let Some(&next_ch) = chars.peek() {
396                        let potential_op = format!("{}{}", ch, next_ch);
397                        if valid_double_ops.contains(&potential_op.as_str()) {
398                            op.push(chars.next().unwrap()); // 消费下一个字符
399                        }
400                    }
401
402                    tokens.push(Token::Operator(op));
403                }
404                '"' => {
405                    chars.next(); // 跳过开始引号
406                    let mut string_val = String::new();
407
408                    while let Some(ch) = chars.next() {
409                        if ch == '"' {
410                            // 检查是否是转义的引号
411                            if chars.peek() == Some(&'"') {
412                                string_val.push('"');
413                                chars.next();
414                            } else {
415                                break;
416                            }
417                        } else {
418                            string_val.push(ch);
419                        }
420                    }
421
422                    tokens.push(Token::String(string_val));
423                }
424                '0'..='9' | '.' => {
425                    let mut number = String::new();
426
427                    while let Some(&ch) = chars.peek() {
428                        if ch.is_ascii_digit() || ch == '.' {
429                            number.push(chars.next().unwrap());
430                        } else {
431                            break;
432                        }
433                    }
434
435                    let num_val = number
436                        .parse::<f64>()
437                        .map_err(|_| {
438                            OfficeError::Xlsx(XlsxError::InvalidFormula { formula: number })
439                        })?;
440
441                    tokens.push(Token::Number(num_val));
442                }
443                'A'..='Z' | 'a'..='z' | '$' => {
444                    let mut identifier = String::new();
445
446                    // 处理可能的单元格引用或标识符
447                    while let Some(&ch) = chars.peek() {
448                        if ch.is_ascii_alphanumeric() || ch == '$' || ch == '_' {
449                            identifier.push(chars.next().unwrap());
450                        } else {
451                            break;
452                        }
453                    }
454
455                    // 判断是单元格引用还是标识符
456                    if Self::is_cell_reference(&identifier) {
457                        tokens.push(Token::CellReference(identifier));
458                    } else if
459                        identifier.to_uppercase() == "TRUE" ||
460                        identifier.to_uppercase() == "FALSE"
461                    {
462                        tokens.push(Token::Identifier(identifier));
463                    } else {
464                        tokens.push(Token::Identifier(identifier));
465                    }
466                }
467                _ => {
468                    return Err(
469                        OfficeError::Xlsx(XlsxError::InvalidFormula {
470                            formula: format!("Unexpected character: {}", ch),
471                        })
472                    );
473                }
474            }
475        }
476
477        tokens.push(Token::Eof);
478        Ok(tokens)
479    }
480
481    /// 判断是否为单元格引用
482    fn is_cell_reference(text: &str) -> bool {
483        let text = text.trim();
484
485        // 检查是否为空
486        if text.is_empty() {
487            return false;
488        }
489
490        // 检查是否以$结尾
491        if text.ends_with("$") {
492            return false;
493        }
494
495        let mut chars = text.chars().peekable();
496        let mut dollar_count = 0;
497
498        // 处理可能的列绝对引用符号$
499        if chars.peek() == Some(&'$') {
500            chars.next();
501            dollar_count += 1;
502        }
503
504        // 处理列字母部分
505        let mut has_col_letter = false;
506        while let Some(ch) = chars.peek() {
507            if ch.is_ascii_uppercase() {
508                chars.next();
509                has_col_letter = true;
510            } else {
511                break;
512            }
513        }
514
515        // 如果没有列字母,则不是有效的单元格引用
516        if !has_col_letter {
517            return false;
518        }
519
520        // 处理可能的列绝对引用符号$
521        if chars.peek() == Some(&'$') {
522            chars.next();
523            dollar_count += 1;
524        }
525
526        // 处理行数字部分
527        let mut has_row_number = false;
528        while let Some(ch) = chars.peek() {
529            if ch.is_ascii_digit() {
530                chars.next();
531                has_row_number = true;
532            } else {
533                break;
534            }
535        }
536
537        // 如果没有行数字,则不是有效的单元格引用
538        if !has_row_number {
539            return false;
540        }
541
542        // 处理可能的行绝对引用符号$
543        if chars.peek() == Some(&'$') {
544            chars.next();
545            dollar_count += 1;
546            // 如果$符号后面还有字符,则不是有效的单元格引用
547            if chars.peek().is_some() {
548                return false;
549            }
550        }
551
552        // 确保所有字符都已处理完,有字母和数字,且$符号不超过2个
553        chars.next().is_none() && dollar_count <= 2
554    }
555
556    /// 解析表达式
557    fn parse_expression(&mut self) -> Result<FormulaExpression> {
558        self.parse_logical_or()
559    }
560
561    /// 解析逻辑或表达式
562    fn parse_logical_or(&mut self) -> Result<FormulaExpression> {
563        let mut expr = self.parse_logical_and()?;
564
565        while self.match_operator("|") {
566            let right = self.parse_logical_and()?;
567            expr = FormulaExpression::BinaryOp {
568                op: BinaryOperator::LogicalOr,
569                left: Box::new(expr),
570                right: Box::new(right),
571            };
572        }
573
574        Ok(expr)
575    }
576
577    /// 解析逻辑与表达式
578    fn parse_logical_and(&mut self) -> Result<FormulaExpression> {
579        let mut expr = self.parse_equality()?;
580
581        while self.match_operator("&") {
582            let right = self.parse_equality()?;
583            expr = FormulaExpression::BinaryOp {
584                op: BinaryOperator::LogicalAnd,
585                left: Box::new(expr),
586                right: Box::new(right),
587            };
588        }
589
590        Ok(expr)
591    }
592
593    /// 解析相等性表达式
594    fn parse_equality(&mut self) -> Result<FormulaExpression> {
595        let mut expr = self.parse_comparison()?;
596
597        while let Some(op) = self.match_equality_operator() {
598            let right = self.parse_comparison()?;
599            expr = FormulaExpression::BinaryOp {
600                op,
601                left: Box::new(expr),
602                right: Box::new(right),
603            };
604        }
605
606        Ok(expr)
607    }
608
609    /// 解析比较表达式
610    fn parse_comparison(&mut self) -> Result<FormulaExpression> {
611        let mut expr = self.parse_addition()?;
612
613        while let Some(op) = self.match_comparison_operator() {
614            let right = self.parse_addition()?;
615            expr = FormulaExpression::BinaryOp {
616                op,
617                left: Box::new(expr),
618                right: Box::new(right),
619            };
620        }
621
622        Ok(expr)
623    }
624
625    /// 解析加减表达式
626    fn parse_addition(&mut self) -> Result<FormulaExpression> {
627        let mut expr = self.parse_multiplication()?;
628
629        while let Some(op) = self.match_addition_operator() {
630            let right = self.parse_multiplication()?;
631            expr = FormulaExpression::BinaryOp {
632                op,
633                left: Box::new(expr),
634                right: Box::new(right),
635            };
636        }
637
638        Ok(expr)
639    }
640
641    /// 解析乘除表达式
642    fn parse_multiplication(&mut self) -> Result<FormulaExpression> {
643        let mut expr = self.parse_power()?;
644
645        while let Some(op) = self.match_multiplication_operator() {
646            let right = self.parse_power()?;
647            expr = FormulaExpression::BinaryOp {
648                op,
649                left: Box::new(expr),
650                right: Box::new(right),
651            };
652        }
653
654        Ok(expr)
655    }
656
657    /// 解析幂运算表达式
658    fn parse_power(&mut self) -> Result<FormulaExpression> {
659        let mut expr = self.parse_unary()?;
660
661        // 检查后缀一元操作符(百分号)
662        if self.match_operator("%") {
663            expr = FormulaExpression::UnaryOp {
664                op: UnaryOperator::Percent,
665                operand: Box::new(expr),
666            };
667        }
668
669        if self.match_operator("^") {
670            let right = self.parse_power()?; // 右结合
671            expr = FormulaExpression::BinaryOp {
672                op: BinaryOperator::Power,
673                left: Box::new(expr),
674                right: Box::new(right),
675            };
676        }
677
678        Ok(expr)
679    }
680
681    /// 解析一元表达式
682    fn parse_unary(&mut self) -> Result<FormulaExpression> {
683        // 处理前缀一元操作符(+、-)
684        if let Some(op) = self.match_unary_operator() {
685            // 只有加号和减号是前缀操作符
686            if matches!(op, UnaryOperator::Plus | UnaryOperator::Minus) {
687                let operand = self.parse_unary()?;
688                return Ok(FormulaExpression::UnaryOp {
689                    op,
690                    operand: Box::new(operand),
691                });
692            } else {
693                // 如果是百分号,回退并按后缀操作符处理
694                self.current -= 1;
695            }
696        }
697
698        self.parse_primary()
699    }
700
701    /// 解析基本表达式
702    fn parse_primary(&mut self) -> Result<FormulaExpression> {
703        match &self.current_token()? {
704            Token::Number(n) => {
705                let value = *n;
706                self.advance();
707                Ok(FormulaExpression::Constant(FormulaValue::Number(value)))
708            }
709            Token::String(s) => {
710                let value = s.clone();
711                self.advance();
712                Ok(FormulaExpression::Constant(FormulaValue::Text(value)))
713            }
714            Token::CellReference(ref_str) => {
715                let cell_ref = CellReference::from_a1(ref_str)?;
716                self.advance();
717
718                // 检查是否是范围引用
719                if self.match_token(&Token::Colon) {
720                    if let Token::CellReference(end_ref_str) = &self.current_token()? {
721                        let end_ref = CellReference::from_a1(end_ref_str)?;
722                        self.advance();
723                        Ok(FormulaExpression::RangeRef(cell_ref, end_ref))
724                    } else {
725                        Err(
726                            OfficeError::Xlsx(XlsxError::InvalidFormula {
727                                formula: "Expected cell reference after colon".to_string(),
728                            })
729                        )
730                    }
731                } else {
732                    Ok(FormulaExpression::CellRef(cell_ref))
733                }
734            }
735            Token::Identifier(name) => {
736                let func_name = name.clone();
737                self.advance();
738
739                // 检查是否是布尔常量
740                if func_name.to_uppercase() == "TRUE" {
741                    return Ok(FormulaExpression::Constant(FormulaValue::Boolean(true)));
742                } else if func_name.to_uppercase() == "FALSE" {
743                    return Ok(FormulaExpression::Constant(FormulaValue::Boolean(false)));
744                }
745
746                if self.match_token(&Token::LeftParen) {
747                    // 函数调用
748                    let mut args = Vec::new();
749
750                    if !self.check_token(&Token::RightParen) {
751                        loop {
752                            args.push(self.parse_expression()?);
753
754                            if !self.match_token(&Token::Comma) {
755                                break;
756                            }
757                        }
758                    }
759
760                    if !self.match_token(&Token::RightParen) {
761                        return Err(
762                            OfficeError::Xlsx(XlsxError::InvalidFormula {
763                                formula: "Expected ')' after function arguments".to_string(),
764                            })
765                        );
766                    }
767
768                    Ok(FormulaExpression::Function {
769                        name: func_name,
770                        args,
771                    })
772                } else {
773                    // 命名范围或其他标识符
774                    Err(
775                        OfficeError::Xlsx(XlsxError::InvalidFormula {
776                            formula: format!("Unknown identifier: {}", func_name),
777                        })
778                    )
779                }
780            }
781            Token::LeftParen => {
782                self.advance();
783                let expr = self.parse_expression()?;
784
785                if !self.match_token(&Token::RightParen) {
786                    return Err(
787                        OfficeError::Xlsx(XlsxError::InvalidFormula {
788                            formula: "Expected ')'".to_string(),
789                        })
790                    );
791                }
792
793                Ok(expr)
794            }
795            _ =>
796                Err(
797                    OfficeError::Xlsx(XlsxError::InvalidFormula {
798                        formula: "Unexpected token".to_string(),
799                    })
800                ),
801        }
802    }
803
804    /// 获取当前token
805    fn current_token(&self) -> Result<&Token> {
806        self.tokens.get(self.current).ok_or_else(|| {
807            OfficeError::Xlsx(XlsxError::InvalidFormula {
808                formula: "Unexpected end of formula".to_string(),
809            })
810        })
811    }
812
813    /// 前进到下一个token
814    fn advance(&mut self) {
815        if self.current < self.tokens.len() {
816            self.current += 1;
817        }
818    }
819
820    /// 检查当前token是否匹配
821    fn check_token(&self, token: &Token) -> bool {
822        if let Ok(current) = self.current_token() {
823            std::mem::discriminant(current) == std::mem::discriminant(token)
824        } else {
825            false
826        }
827    }
828
829    /// 匹配并消费token
830    fn match_token(&mut self, token: &Token) -> bool {
831        if self.check_token(token) {
832            self.advance();
833            true
834        } else {
835            false
836        }
837    }
838
839    /// 匹配操作符
840    fn match_operator(&mut self, op: &str) -> bool {
841        if let Ok(Token::Operator(current_op)) = self.current_token() {
842            if current_op == op {
843                self.advance();
844                return true;
845            }
846        }
847        false
848    }
849
850    /// 匹配相等性操作符
851    fn match_equality_operator(&mut self) -> Option<BinaryOperator> {
852        if let Ok(Token::Operator(op)) = self.current_token() {
853            let result = match op.as_str() {
854                "=" => Some(BinaryOperator::Equal),
855                "<>" => Some(BinaryOperator::NotEqual),
856                _ => None,
857            };
858
859            if result.is_some() {
860                self.advance();
861            }
862
863            result
864        } else {
865            None
866        }
867    }
868
869    /// 匹配比较操作符
870    fn match_comparison_operator(&mut self) -> Option<BinaryOperator> {
871        if let Ok(Token::Operator(op)) = self.current_token() {
872            let result = match op.as_str() {
873                "<" => Some(BinaryOperator::LessThan),
874                "<=" => Some(BinaryOperator::LessThanOrEqual),
875                ">" => Some(BinaryOperator::GreaterThan),
876                ">=" => Some(BinaryOperator::GreaterThanOrEqual),
877                "<>" => Some(BinaryOperator::NotEqual),
878                _ => None,
879            };
880
881            if result.is_some() {
882                self.advance();
883            }
884
885            result
886        } else {
887            None
888        }
889    }
890
891    /// 匹配加减操作符
892    fn match_addition_operator(&mut self) -> Option<BinaryOperator> {
893        if let Ok(Token::Operator(op)) = self.current_token() {
894            let result = match op.as_str() {
895                "+" => Some(BinaryOperator::Add),
896                "-" => Some(BinaryOperator::Subtract),
897                _ => None,
898            };
899
900            if result.is_some() {
901                self.advance();
902            }
903
904            result
905        } else {
906            None
907        }
908    }
909
910    /// 匹配乘除操作符
911    fn match_multiplication_operator(&mut self) -> Option<BinaryOperator> {
912        if let Ok(Token::Operator(op)) = self.current_token() {
913            let result = match op.as_str() {
914                "*" => Some(BinaryOperator::Multiply),
915                "/" => Some(BinaryOperator::Divide),
916                _ => None,
917            };
918
919            if result.is_some() {
920                self.advance();
921            }
922
923            result
924        } else {
925            None
926        }
927    }
928
929    /// 匹配一元操作符
930    fn match_unary_operator(&mut self) -> Option<UnaryOperator> {
931        if let Ok(Token::Operator(op)) = self.current_token() {
932            let result = match op.as_str() {
933                "+" => Some(UnaryOperator::Plus),
934                "-" => Some(UnaryOperator::Minus),
935                "%" => Some(UnaryOperator::Percent),
936                "!" => Some(UnaryOperator::Factorial),
937                _ => None,
938            };
939
940            if result.is_some() {
941                self.advance();
942            }
943
944            result
945        } else {
946            None
947        }
948    }
949}
950
951/// 解析公式字符串
952pub fn parse_formula(formula: &str) -> Result<FormulaExpression> {
953    // 如果公式以'='开头,跳过它
954    let formula_content = if formula.starts_with('=') { &formula[1..] } else { formula };
955
956    let mut parser = FormulaParser::new(formula_content)?;
957    parser.parse()
958}
959
960#[cfg(test)]
961mod tests {
962    use super::*;
963
964    #[test]
965    fn test_tokenize_simple() {
966        let tokens = FormulaParser::tokenize("1+2").unwrap();
967        assert_eq!(tokens.len(), 4); // 1, +, 2, EOF
968    }
969
970    #[test]
971    fn test_parse_simple_addition() {
972        let expr = parse_formula("1+2").unwrap();
973        match expr {
974            FormulaExpression::BinaryOp { op: BinaryOperator::Add, .. } => {}
975            _ => panic!("Expected addition expression"),
976        }
977    }
978
979    #[test]
980    fn test_parse_cell_reference() {
981        let expr = parse_formula("A1").unwrap();
982        match expr {
983            FormulaExpression::CellRef(_) => {}
984            _ => panic!("Expected cell reference"),
985        }
986    }
987
988    #[test]
989    fn test_parse_function_call() {
990        let expr = parse_formula("SUM(A1:A10)").unwrap();
991        match expr {
992            FormulaExpression::Function { name, args } => {
993                assert_eq!(name, "SUM");
994                assert_eq!(args.len(), 1);
995            }
996            _ => panic!("Expected function call"),
997        }
998    }
999
1000    #[test]
1001    fn test_formula_value_conversions() {
1002        let num_val = FormulaValue::Number(42.0);
1003        assert_eq!(num_val.as_number().unwrap(), 42.0);
1004        assert_eq!(num_val.as_text(), "42");
1005
1006        let bool_val = FormulaValue::Boolean(true);
1007        assert_eq!(bool_val.as_boolean().unwrap(), true);
1008        assert_eq!(bool_val.as_number().unwrap(), 1.0);
1009    }
1010
1011    #[test]
1012    fn test_logical_or_operator() {
1013        let expr = parse_formula("TRUE|FALSE").unwrap();
1014        match expr {
1015            FormulaExpression::BinaryOp { op: BinaryOperator::LogicalOr, .. } => {}
1016            _ => panic!("Expected logical OR expression"),
1017        }
1018    }
1019
1020    #[test]
1021    fn test_logical_and_operator() {
1022        let expr = parse_formula("TRUE&FALSE").unwrap();
1023        match expr {
1024            FormulaExpression::BinaryOp { op: BinaryOperator::LogicalAnd, .. } => {}
1025            _ => panic!("Expected logical AND expression"),
1026        }
1027    }
1028
1029    #[test]
1030    fn test_boolean_constants() {
1031        let expr = parse_formula("TRUE").unwrap();
1032        match expr {
1033            FormulaExpression::Constant(FormulaValue::Boolean(true)) => {}
1034            _ => panic!("Expected TRUE constant"),
1035        }
1036
1037        let expr = parse_formula("FALSE").unwrap();
1038        match expr {
1039            FormulaExpression::Constant(FormulaValue::Boolean(false)) => {}
1040            _ => panic!("Expected FALSE constant"),
1041        }
1042    }
1043
1044    #[test]
1045    fn test_mixed_logical_operations() {
1046        let expr = parse_formula("TRUE|FALSE&TRUE").unwrap();
1047        // 应该解析为 TRUE|(FALSE&TRUE),因为 & 的优先级高于 |
1048        match expr {
1049            FormulaExpression::BinaryOp { op: BinaryOperator::LogicalOr, left, right } => {
1050                match *left {
1051                    FormulaExpression::Constant(FormulaValue::Boolean(true)) => {}
1052                    _ => panic!("Expected TRUE constant"),
1053                }
1054                match *right {
1055                    FormulaExpression::BinaryOp { op: BinaryOperator::LogicalAnd, .. } => {}
1056                    _ => panic!("Expected logical AND expression"),
1057                }
1058            }
1059            _ => panic!("Expected logical OR expression"),
1060        }
1061    }
1062
1063    #[test]
1064    fn test_case_insensitive_boolean_constants() {
1065        let expr = parse_formula("true").unwrap();
1066        match expr {
1067            FormulaExpression::Constant(FormulaValue::Boolean(true)) => {}
1068            _ => panic!("Expected TRUE constant"),
1069        }
1070
1071        let expr = parse_formula("False").unwrap();
1072        match expr {
1073            FormulaExpression::Constant(FormulaValue::Boolean(false)) => {}
1074            _ => panic!("Expected FALSE constant"),
1075        }
1076    }
1077
1078    #[test]
1079    fn test_is_cell_reference() {
1080        // 有效的单元格引用
1081        assert!(FormulaParser::is_cell_reference("A1"));
1082        assert!(FormulaParser::is_cell_reference("Z999"));
1083        assert!(FormulaParser::is_cell_reference("AA1"));
1084        assert!(FormulaParser::is_cell_reference("AZ999"));
1085        assert!(FormulaParser::is_cell_reference("$A$1"));
1086        assert!(FormulaParser::is_cell_reference("$Z$999"));
1087        assert!(FormulaParser::is_cell_reference("A$1"));
1088        assert!(FormulaParser::is_cell_reference("$A1"));
1089        assert!(FormulaParser::is_cell_reference("AA$1"));
1090        assert!(FormulaParser::is_cell_reference("$AA1"));
1091
1092        // 无效的单元格引用
1093        assert!(!FormulaParser::is_cell_reference("A"));
1094        assert!(!FormulaParser::is_cell_reference("1"));
1095        assert!(!FormulaParser::is_cell_reference("$A"));
1096        assert!(!FormulaParser::is_cell_reference("A$"));
1097        assert!(!FormulaParser::is_cell_reference("$$A1"));
1098        assert!(!FormulaParser::is_cell_reference("A1$"));
1099        assert!(!FormulaParser::is_cell_reference("A1$1"));
1100        assert!(!FormulaParser::is_cell_reference("A$$1"));
1101        assert!(!FormulaParser::is_cell_reference("$A$1$"));
1102        assert!(!FormulaParser::is_cell_reference(""));
1103        assert!(!FormulaParser::is_cell_reference("AB CD"));
1104    }
1105
1106    #[test]
1107    fn test_compound_operators() {
1108        // 比较操作符
1109        let expr = parse_formula("A1<=B1").unwrap();
1110        match expr {
1111            FormulaExpression::BinaryOp { op: BinaryOperator::LessThanOrEqual, .. } => {}
1112            _ => panic!("Expected less than or equal expression"),
1113        }
1114
1115        let expr = parse_formula("A1>=B1").unwrap();
1116        match expr {
1117            FormulaExpression::BinaryOp { op: BinaryOperator::GreaterThanOrEqual, .. } => {}
1118            _ => panic!("Expected greater than or equal expression"),
1119        }
1120
1121        let expr = parse_formula("A1<>B1").unwrap();
1122        match expr {
1123            FormulaExpression::BinaryOp { op: BinaryOperator::NotEqual, .. } => {}
1124            _ => panic!("Expected not equal expression"),
1125        }
1126    }
1127
1128    #[test]
1129    fn test_invalid_operator_combinations() {
1130        // 测试无效的操作符组合
1131        // assert!(parse_formula("1++2").is_err());
1132        // assert!(parse_formula("1+-2").is_err());
1133        assert!(parse_formula("1<=<2").is_err());
1134        assert!(parse_formula("1>=>2").is_err());
1135        assert!(parse_formula("1&&>2").is_err());
1136        assert!(parse_formula("1||<2").is_err());
1137        assert!(parse_formula("TRUE||FALSE").is_err());
1138        assert!(parse_formula("TRUE&&TRUE").is_err());
1139        assert!(parse_formula("TRUE && TRUE").is_err());
1140    }
1141
1142    #[test]
1143    fn test_operator_spacing() {
1144        // 测试操作符周围的空格处理
1145        let expr = parse_formula("A1 <= B1").unwrap();
1146        match expr {
1147            FormulaExpression::BinaryOp { op: BinaryOperator::LessThanOrEqual, .. } => {}
1148            _ => panic!("Expected less than or equal expression"),
1149        }
1150    }
1151}