mathhook_core/
parser.rs

1//! Multi-format mathematical expression parser for MathHook
2//!
3//! This crate provides parsing capabilities for various mathematical formats
4//! including LaTeX, Wolfram Language, and standard mathematical notation.
5pub mod cache;
6pub mod config;
7pub mod constants;
8pub mod error;
9pub mod grammar;
10pub mod lexer;
11use crate::core::Expression;
12pub use cache::*;
13use config::ParserConfig;
14pub use constants::*;
15use error::ParseError;
16/// Fully integrated mathematical expression parser
17pub struct Parser {
18    enable_implicit_multiplication: bool,
19}
20impl Parser {
21    /// Create parser with implicit multiplication enabled
22    pub fn new(config: &ParserConfig) -> Self {
23        Self {
24            enable_implicit_multiplication: config.enable_implicit_multiplication,
25        }
26    }
27    /// Parse mathematical expression with full integration
28    ///
29    /// # Examples
30    ///
31    /// ```rust
32    /// use mathhook_core::parser::Parser;
33    /// use mathhook_core::parser::config::ParserConfig;
34    ///
35    /// let parser = Parser::new(&ParserConfig::default());
36    ///
37    /// // These will work with implicit multiplication:
38    /// let expr = parser.parse("2x").unwrap();           // -> 2 * x
39    /// let expr = parser.parse("xy").unwrap();           // -> x * y
40    /// let expr = parser.parse("2(x+1)").unwrap();       // -> 2 * (x + 1)
41    ///
42    /// // These work normally:
43    /// let expr = parser.parse("x + y").unwrap();        // -> x + y
44    /// let expr = parser.parse("x^2").unwrap();          // -> x^2
45    /// ```
46    pub fn parse(&self, input: &str) -> Result<Expression, ParseError> {
47        if self.enable_implicit_multiplication {
48            self.parse_with_implicit_multiplication(input)
49        } else {
50            self.parse_explicit_only(input)
51        }
52    }
53    /// Parse with implicit multiplication enabled using comprehensive processor
54    fn parse_with_implicit_multiplication(&self, input: &str) -> Result<Expression, ParseError> {
55        let enhanced_input =
56            lexer::ImplicitMultiplicationProcessor::insert_implicit_multiplication(input);
57        let parser = grammar::ExpressionParser::new();
58        parser
59            .parse(&enhanced_input)
60            .map_err(|e| ParseError::SyntaxError(format!("LALRPOP parse error: {:?}", e)))
61    }
62    /// Parse with explicit operators only (no implicit multiplication)
63    fn parse_explicit_only(&self, input: &str) -> Result<Expression, ParseError> {
64        println!("Parsing with explicit operators only: {}", input);
65        let parser = grammar::ExpressionParser::new();
66        parser
67            .parse(input)
68            .map_err(|e| ParseError::SyntaxError(format!("LALRPOP parse error: {:?}", e)))
69    }
70}
71impl Default for Parser {
72    fn default() -> Self {
73        Self::new(&ParserConfig::default())
74    }
75}
76#[cfg(test)]
77mod tests {
78    use super::*;
79    #[test]
80    fn test_parser_modes() {
81        let config_implicit = ParserConfig {
82            enable_implicit_multiplication: true,
83        };
84        let parser_implicit = Parser::new(&config_implicit);
85        let config_explicit = ParserConfig {
86            enable_implicit_multiplication: false,
87        };
88        let parser_explicit = Parser::new(&config_explicit);
89        assert!(parser_implicit.parse("x + y").is_ok());
90        assert!(parser_explicit.parse("x + y").is_ok());
91    }
92    #[test]
93    fn test_implicit_multiplication_integration() {
94        let config = ParserConfig {
95            enable_implicit_multiplication: true,
96        };
97        let parser = Parser::new(&config);
98        println!("Testing: 2*x -> 2 * x");
99        assert!(parser.parse("2x").is_ok());
100        assert!(parser.parse("xy").is_ok());
101        assert!(parser.parse("2pi").is_ok());
102        assert!(parser.parse("2+3").is_ok());
103        assert!(parser.parse("x*y").is_ok());
104        assert!(parser.parse("a/b").is_ok());
105    }
106}