rudy_parser/
expressions.rs

1//! Expression parsing for debugger evaluation
2//!
3//! This module provides parsing for Rust-like expressions for use in
4//! debugger evaluation. Supports field access, array indexing, dereferencing,
5//! and other common expression forms.
6
7use std::fmt;
8
9use anyhow::{Result, anyhow};
10use itertools::Itertools;
11
12/// Represents a parsed expression
13#[derive(Debug, Clone, PartialEq)]
14pub enum Expression {
15    /// Simple variable reference (e.g., `foo`)
16    Variable(String),
17
18    /// Path expression (e.g., `std::vec::Vec`, `lldb_demo::User`)
19    Path(Vec<String>),
20
21    /// Generic type (e.g., `Vec<String>`, `HashMap<String, u32>`)
22    Generic { base: String, args: Vec<String> },
23
24    /// Field access (e.g., `foo.bar`, `self.field`)
25    FieldAccess {
26        base: Box<Expression>,
27        field: String,
28    },
29
30    /// Array/slice indexing (e.g., `arr[5]`, `slice[idx]`)
31    Index {
32        base: Box<Expression>,
33        index: Box<Expression>,
34    },
35
36    /// Pointer dereferencing (e.g., `*ptr`, `**ptr_ptr`)
37    Deref(Box<Expression>),
38
39    /// Address-of operator (e.g., `&var`, `&mut var`)
40    AddressOf {
41        mutable: bool,
42        expr: Box<Expression>,
43    },
44
45    /// Literal number (e.g., `42`, `0xff`)
46    NumberLiteral(u64),
47
48    /// String literal (e.g., `"hello"`, `"created"`)
49    StringLiteral(String),
50
51    /// Parenthesized expression (e.g., `(foo)`)
52    Parenthesized(Box<Expression>),
53
54    /// Method call (e.g., `foo.bar()`, `vec.len()`)
55    MethodCall {
56        base: Box<Expression>,
57        method: String,
58        args: Vec<Expression>,
59    },
60
61    /// Function call (e.g., `foo()`, `bar(1, 2)`)
62    FunctionCall {
63        function: String,
64        args: Vec<Expression>,
65    },
66}
67
68impl fmt::Display for Expression {
69    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70        match self {
71            Expression::Variable(name) => write!(f, "{name}"),
72            Expression::Path(segments) => write!(f, "{}", segments.join("::")),
73            Expression::Generic { base, args } => write!(f, "{}<{}>", base, args.join(", ")),
74            Expression::FieldAccess { base, field } => write!(f, "{base}.{field}"),
75            Expression::Index { base, index } => write!(f, "{base}[{index}]"),
76            Expression::Deref(expr) => write!(f, "*{expr}"),
77            Expression::AddressOf { mutable, expr } => {
78                if *mutable {
79                    write!(f, "&mut {expr}")
80                } else {
81                    write!(f, "&{expr}")
82                }
83            }
84            Expression::NumberLiteral(value) => write!(f, "{value}"),
85            Expression::StringLiteral(value) => write!(f, "\"{value}\""),
86            Expression::Parenthesized(expr) => write!(f, "({expr})"),
87            Expression::MethodCall { base, method, args } => {
88                write!(f, "{base}.{method}({})", args.iter().join(", "))
89            }
90            Expression::FunctionCall { function, args } => {
91                write!(f, "{function}({})", args.iter().join(", "))
92            }
93        }
94    }
95}
96
97/// Simple tokenizer for expressions
98#[derive(Debug, Clone, PartialEq)]
99enum Token {
100    Identifier(String),
101    Number(u64),
102    String(String),
103    Dot,
104    Star,
105    Ampersand,
106    /// '['
107    LeftBracket,
108    /// ']'
109    RightBracket,
110    /// '('
111    LeftParen,
112    /// ')'
113    RightParen,
114    /// '<'
115    LeftAngle,
116    /// '>'
117    RightAngle,
118    /// '::'
119    PathSeparator,
120    /// ','
121    Comma,
122    Mut,
123    Eof,
124}
125
126struct Tokenizer<'a> {
127    input: &'a str,
128    position: usize,
129}
130
131impl<'a> Tokenizer<'a> {
132    fn new(input: &'a str) -> Self {
133        Self { input, position: 0 }
134    }
135
136    fn current_char(&self) -> Option<char> {
137        self.input.chars().nth(self.position)
138    }
139
140    fn advance(&mut self) {
141        if self.position < self.input.len() {
142            self.position += 1;
143        }
144    }
145
146    fn skip_whitespace(&mut self) {
147        while let Some(ch) = self.current_char() {
148            if ch.is_whitespace() {
149                self.advance();
150            } else {
151                break;
152            }
153        }
154    }
155
156    fn read_identifier(&mut self) -> String {
157        let start = self.position;
158        while let Some(ch) = self.current_char() {
159            if ch.is_ascii_alphanumeric() || ch == '_' {
160                self.advance();
161            } else {
162                break;
163            }
164        }
165        self.input[start..self.position].to_string()
166    }
167
168    fn read_number(&mut self) -> Result<u64> {
169        let start = self.position;
170
171        // Check for hex prefix
172        if self.input[self.position..].starts_with("0x")
173            || self.input[self.position..].starts_with("0X")
174        {
175            self.advance(); // skip '0'
176            self.advance(); // skip 'x'
177            while let Some(ch) = self.current_char() {
178                if ch.is_ascii_hexdigit() {
179                    self.advance();
180                } else {
181                    break;
182                }
183            }
184            let hex_str = &self.input[start + 2..self.position];
185            u64::from_str_radix(hex_str, 16).map_err(|e| anyhow!("Invalid hex number: {}", e))
186        } else {
187            // Regular decimal number
188            while let Some(ch) = self.current_char() {
189                if ch.is_ascii_digit() {
190                    self.advance();
191                } else {
192                    break;
193                }
194            }
195            self.input[start..self.position]
196                .parse()
197                .map_err(|e| anyhow!("Invalid number: {}", e))
198        }
199    }
200
201    fn read_string(&mut self) -> Result<String> {
202        // Skip opening quote
203        self.advance();
204        let start = self.position;
205
206        while let Some(ch) = self.current_char() {
207            if ch == '"' {
208                // Found closing quote
209                let content = self.input[start..self.position].to_string();
210                self.advance(); // Skip closing quote
211                return Ok(content);
212            } else if ch == '\\' {
213                // Handle escape sequences (basic support)
214                self.advance(); // Skip backslash
215                if self.current_char().is_some() {
216                    self.advance(); // Skip escaped character
217                }
218            } else {
219                self.advance();
220            }
221        }
222
223        Err(anyhow!("Unterminated string literal"))
224    }
225
226    fn next_token(&mut self) -> Result<Token> {
227        self.skip_whitespace();
228
229        match self.current_char() {
230            None => Ok(Token::Eof),
231            Some('.') => {
232                self.advance();
233                Ok(Token::Dot)
234            }
235            Some('*') => {
236                self.advance();
237                Ok(Token::Star)
238            }
239            Some('&') => {
240                self.advance();
241                Ok(Token::Ampersand)
242            }
243            Some('[') => {
244                self.advance();
245                Ok(Token::LeftBracket)
246            }
247            Some(']') => {
248                self.advance();
249                Ok(Token::RightBracket)
250            }
251            Some('(') => {
252                self.advance();
253                Ok(Token::LeftParen)
254            }
255            Some(')') => {
256                self.advance();
257                Ok(Token::RightParen)
258            }
259            Some('<') => {
260                self.advance();
261                Ok(Token::LeftAngle)
262            }
263            Some('>') => {
264                self.advance();
265                Ok(Token::RightAngle)
266            }
267            Some(':') => {
268                self.advance();
269                if self.current_char() == Some(':') {
270                    self.advance();
271                    Ok(Token::PathSeparator)
272                } else {
273                    Err(anyhow!("Expected '::' but found single ':'"))
274                }
275            }
276            Some(',') => {
277                self.advance();
278                Ok(Token::Comma)
279            }
280            Some(ch) if ch.is_ascii_alphabetic() || ch == '_' => {
281                let ident = self.read_identifier();
282                if ident == "mut" {
283                    Ok(Token::Mut)
284                } else {
285                    Ok(Token::Identifier(ident))
286                }
287            }
288            Some(ch) if ch.is_ascii_digit() => {
289                let number = self.read_number()?;
290                Ok(Token::Number(number))
291            }
292            Some('"') => {
293                let string = self.read_string()?;
294                Ok(Token::String(string))
295            }
296            Some(ch) => Err(anyhow!("Unexpected character: '{}'", ch)),
297        }
298    }
299}
300
301/// Simple recursive descent parser
302struct Parser {
303    tokens: Vec<Token>,
304    position: usize,
305}
306
307impl Parser {
308    fn new(input: &str) -> Result<Self> {
309        let mut tokenizer = Tokenizer::new(input);
310        let mut tokens = Vec::new();
311
312        loop {
313            let token = tokenizer.next_token()?;
314            let is_eof = token == Token::Eof;
315            tokens.push(token);
316            if is_eof {
317                break;
318            }
319        }
320
321        Ok(Self {
322            tokens,
323            position: 0,
324        })
325    }
326
327    fn current_token(&self) -> &Token {
328        self.tokens.get(self.position).unwrap_or(&Token::Eof)
329    }
330
331    fn advance(&mut self) {
332        if self.position < self.tokens.len() {
333            self.position += 1;
334        }
335    }
336
337    fn expect(&mut self, expected: Token) -> Result<()> {
338        if std::mem::discriminant(self.current_token()) == std::mem::discriminant(&expected) {
339            self.advance();
340            Ok(())
341        } else {
342            Err(anyhow!(
343                "Expected {:?}, found {:?}",
344                expected,
345                self.current_token()
346            ))
347        }
348    }
349
350    pub fn parse(&mut self) -> Result<Expression> {
351        self.parse_expression()
352    }
353
354    fn parse_expression(&mut self) -> Result<Expression> {
355        self.parse_unary()
356    }
357
358    fn parse_unary(&mut self) -> Result<Expression> {
359        match self.current_token() {
360            Token::Star => {
361                self.advance();
362                let expr = self.parse_unary()?;
363                Ok(Expression::Deref(Box::new(expr)))
364            }
365            Token::Ampersand => {
366                self.advance();
367                let mutable = matches!(self.current_token(), Token::Mut);
368                if mutable {
369                    self.advance();
370                }
371                let expr = self.parse_unary()?;
372                Ok(Expression::AddressOf {
373                    mutable,
374                    expr: Box::new(expr),
375                })
376            }
377            _ => self.parse_postfix(),
378        }
379    }
380
381    fn parse_postfix(&mut self) -> Result<Expression> {
382        let mut expr = self.parse_primary()?;
383
384        loop {
385            match self.current_token() {
386                Token::Dot => {
387                    self.advance();
388                    if let Token::Identifier(field) = self.current_token() {
389                        let field = field.clone();
390                        self.advance();
391
392                        // Check if this is a method call
393                        if matches!(self.current_token(), Token::LeftParen) {
394                            self.advance(); // consume '('
395                            let args = self.parse_arguments()?;
396                            self.expect(Token::RightParen)?;
397                            expr = Expression::MethodCall {
398                                base: Box::new(expr),
399                                method: field,
400                                args,
401                            };
402                        } else {
403                            expr = Expression::FieldAccess {
404                                base: Box::new(expr),
405                                field,
406                            };
407                        }
408                    } else {
409                        return Err(anyhow!("Expected field name after '.'"));
410                    }
411                }
412                Token::LeftBracket => {
413                    self.advance();
414                    let index = self.parse_expression()?;
415                    self.expect(Token::RightBracket)?;
416                    expr = Expression::Index {
417                        base: Box::new(expr),
418                        index: Box::new(index),
419                    };
420                }
421                _ => break,
422            }
423        }
424
425        Ok(expr)
426    }
427
428    fn parse_primary(&mut self) -> Result<Expression> {
429        match self.current_token() {
430            Token::Identifier(name) => {
431                let first_segment = name.clone();
432                self.advance();
433
434                // Check if this is a path (e.g., std::vec::Vec)
435                let mut segments = vec![first_segment.clone()];
436                while matches!(self.current_token(), Token::PathSeparator) {
437                    self.advance(); // consume '::'
438                    if let Token::Identifier(segment) = self.current_token() {
439                        segments.push(segment.clone());
440                        self.advance();
441                    } else {
442                        return Err(anyhow!("Expected identifier after '::'"));
443                    }
444                }
445
446                // Check if this is a generic type (e.g., Vec<String>)
447                if matches!(self.current_token(), Token::LeftAngle) {
448                    self.advance(); // consume '<'
449                    let type_args = self.parse_type_arguments()?;
450                    self.expect(Token::RightAngle)?;
451
452                    // For generics, we use the full path as the base
453                    let base = segments.join("::");
454                    return Ok(Expression::Generic {
455                        base,
456                        args: type_args,
457                    });
458                }
459
460                // Check if this is a function call
461                if matches!(self.current_token(), Token::LeftParen) {
462                    self.advance(); // consume '('
463                    let args = self.parse_arguments()?;
464                    self.expect(Token::RightParen)?;
465
466                    // For function calls, use the full path as the function name
467                    let function = segments.join("::");
468                    return Ok(Expression::FunctionCall { function, args });
469                }
470
471                // Return as path if multiple segments, otherwise as variable
472                if segments.len() > 1 {
473                    Ok(Expression::Path(segments))
474                } else {
475                    Ok(Expression::Variable(first_segment))
476                }
477            }
478            Token::Number(value) => {
479                let value = *value;
480                self.advance();
481                Ok(Expression::NumberLiteral(value))
482            }
483            Token::String(value) => {
484                let value = value.clone();
485                self.advance();
486                Ok(Expression::StringLiteral(value))
487            }
488            Token::LeftParen => {
489                self.advance();
490                let expr = self.parse_expression()?;
491                self.expect(Token::RightParen)?;
492                Ok(Expression::Parenthesized(Box::new(expr)))
493            }
494            _ => Err(anyhow!(
495                "Expected identifier, number, string, or '(', found {:?}",
496                self.current_token()
497            )),
498        }
499    }
500
501    fn parse_arguments(&mut self) -> Result<Vec<Expression>> {
502        let mut args = Vec::new();
503
504        // Handle empty argument list
505        if matches!(self.current_token(), Token::RightParen) {
506            return Ok(args);
507        }
508
509        // Parse first argument
510        args.push(self.parse_expression()?);
511
512        // Parse remaining arguments
513        while matches!(self.current_token(), Token::Comma) {
514            self.advance(); // consume ','
515            args.push(self.parse_expression()?);
516        }
517
518        Ok(args)
519    }
520
521    fn parse_type_arguments(&mut self) -> Result<Vec<String>> {
522        let mut args = Vec::new();
523
524        // Handle empty type argument list
525        if matches!(self.current_token(), Token::RightAngle) {
526            return Ok(args);
527        }
528
529        // Parse first type argument
530        args.push(self.parse_type_name()?);
531
532        // Parse remaining type arguments
533        while matches!(self.current_token(), Token::Comma) {
534            self.advance(); // consume ','
535            args.push(self.parse_type_name()?);
536        }
537
538        Ok(args)
539    }
540
541    fn parse_type_name(&mut self) -> Result<String> {
542        let mut segments = Vec::new();
543
544        // Parse first segment
545        if let Token::Identifier(name) = self.current_token() {
546            segments.push(name.clone());
547            self.advance();
548        } else {
549            return Err(anyhow!("Expected type name"));
550        }
551
552        // Parse additional path segments
553        while matches!(self.current_token(), Token::PathSeparator) {
554            self.advance(); // consume '::'
555            if let Token::Identifier(segment) = self.current_token() {
556                segments.push(segment.clone());
557                self.advance();
558            } else {
559                return Err(anyhow!("Expected identifier after '::'"));
560            }
561        }
562
563        let mut type_name = segments.join("::");
564
565        // Check for nested generics
566        if matches!(self.current_token(), Token::LeftAngle) {
567            self.advance(); // consume '<'
568            let nested_args = self.parse_type_arguments()?;
569            self.expect(Token::RightAngle)?;
570            type_name.push('<');
571            type_name.push_str(&nested_args.join(", "));
572            type_name.push('>');
573        }
574
575        Ok(type_name)
576    }
577}
578
579/// Parse a string into an Expression
580pub fn parse_expression(input: &str) -> Result<Expression> {
581    let mut parser = Parser::new(input)?;
582    parser.parse()
583}
584
585#[cfg(test)]
586mod tests {
587    use super::*;
588
589    #[track_caller]
590    fn parse(s: &str) -> Expression {
591        match parse_expression(s) {
592            Ok(expr) => expr,
593            Err(e) => panic!("Failed to parse expression '{s}': {e}"),
594        }
595    }
596
597    #[test]
598    fn test_variable() {
599        let expr = parse("foo");
600        assert_eq!(expr, Expression::Variable("foo".to_string()));
601    }
602
603    #[test]
604    fn test_number_literal() {
605        let expr = parse("42");
606        assert_eq!(expr, Expression::NumberLiteral(42));
607
608        let expr = parse("0xff");
609        assert_eq!(expr, Expression::NumberLiteral(0xff));
610    }
611
612    #[test]
613    fn test_string_literal() {
614        let expr = parse(r#""hello""#);
615        assert_eq!(expr, Expression::StringLiteral("hello".to_string()));
616
617        let expr = parse(r#""created""#);
618        assert_eq!(expr, Expression::StringLiteral("created".to_string()));
619    }
620
621    #[test]
622    fn test_field_access() {
623        let expr = parse("foo.bar");
624        assert_eq!(
625            expr,
626            Expression::FieldAccess {
627                base: Box::new(Expression::Variable("foo".to_string())),
628                field: "bar".to_string(),
629            }
630        );
631    }
632
633    #[test]
634    fn test_chained_field_access() {
635        let expr = parse("foo.bar.baz");
636        assert_eq!(
637            expr,
638            Expression::FieldAccess {
639                base: Box::new(Expression::FieldAccess {
640                    base: Box::new(Expression::Variable("foo".to_string())),
641                    field: "bar".to_string(),
642                }),
643                field: "baz".to_string(),
644            }
645        );
646    }
647
648    #[test]
649    fn test_index_access() {
650        let expr = parse("arr[0]");
651        assert_eq!(
652            expr,
653            Expression::Index {
654                base: Box::new(Expression::Variable("arr".to_string())),
655                index: Box::new(Expression::NumberLiteral(0)),
656            }
657        );
658
659        // Test string indexing
660        let expr = parse(r#"map["key"]"#);
661        assert_eq!(
662            expr,
663            Expression::Index {
664                base: Box::new(Expression::Variable("map".to_string())),
665                index: Box::new(Expression::StringLiteral("key".to_string())),
666            }
667        );
668    }
669
670    #[test]
671    fn test_deref() {
672        let expr = parse("*ptr");
673        assert_eq!(
674            expr,
675            Expression::Deref(Box::new(Expression::Variable("ptr".to_string())))
676        );
677    }
678
679    #[test]
680    fn test_address_of() {
681        let expr = parse("&var");
682        assert_eq!(
683            expr,
684            Expression::AddressOf {
685                mutable: false,
686                expr: Box::new(Expression::Variable("var".to_string())),
687            }
688        );
689
690        let expr = parse("&mut var");
691        assert_eq!(
692            expr,
693            Expression::AddressOf {
694                mutable: true,
695                expr: Box::new(Expression::Variable("var".to_string())),
696            }
697        );
698    }
699
700    #[test]
701    fn test_parenthesized() {
702        let expr = parse("(foo)");
703        assert_eq!(
704            expr,
705            Expression::Parenthesized(Box::new(Expression::Variable("foo".to_string())))
706        );
707    }
708
709    #[test]
710    fn test_complex_expressions() {
711        // Test field access with indexing: obj.field[0]
712        let expr = parse("obj.field[0]");
713        assert_eq!(
714            expr,
715            Expression::Index {
716                base: Box::new(Expression::FieldAccess {
717                    base: Box::new(Expression::Variable("obj".to_string())),
718                    field: "field".to_string(),
719                }),
720                index: Box::new(Expression::NumberLiteral(0)),
721            }
722        );
723
724        // Test dereferencing field access: *obj.ptr
725        let expr = parse("*obj.ptr");
726        assert_eq!(
727            expr,
728            Expression::Deref(Box::new(Expression::FieldAccess {
729                base: Box::new(Expression::Variable("obj".to_string())),
730                field: "ptr".to_string(),
731            }))
732        );
733    }
734
735    #[test]
736    fn test_display_formatting() {
737        assert_eq!(parse("foo").to_string(), "foo");
738        assert_eq!(parse("42").to_string(), "42");
739        assert_eq!(parse(r#""hello""#).to_string(), r#""hello""#);
740        assert_eq!(parse("foo.bar").to_string(), "foo.bar");
741        assert_eq!(parse("arr[0]").to_string(), "arr[0]");
742        assert_eq!(parse(r#"map["key"]"#).to_string(), r#"map["key"]"#);
743        assert_eq!(parse("*ptr").to_string(), "*ptr");
744        assert_eq!(parse("&var").to_string(), "&var");
745        assert_eq!(parse("&mut var").to_string(), "&mut var");
746        assert_eq!(parse("(foo)").to_string(), "(foo)");
747    }
748
749    #[test]
750    fn test_method_call() {
751        // No arguments
752        let expr = parse("vec.len()");
753        assert_eq!(
754            expr,
755            Expression::MethodCall {
756                base: Box::new(Expression::Variable("vec".to_string())),
757                method: "len".to_string(),
758                args: vec![],
759            }
760        );
761
762        // With arguments
763        let expr = parse("vec.push(42)");
764        assert_eq!(
765            expr,
766            Expression::MethodCall {
767                base: Box::new(Expression::Variable("vec".to_string())),
768                method: "push".to_string(),
769                args: vec![Expression::NumberLiteral(42)],
770            }
771        );
772
773        // Multiple arguments
774        let expr = parse(r#"map.insert("key", 42)"#);
775        assert_eq!(
776            expr,
777            Expression::MethodCall {
778                base: Box::new(Expression::Variable("map".to_string())),
779                method: "insert".to_string(),
780                args: vec![
781                    Expression::StringLiteral("key".to_string()),
782                    Expression::NumberLiteral(42)
783                ],
784            }
785        );
786
787        // Chained method calls
788        let expr = parse("vec.iter().count()");
789        assert_eq!(
790            expr,
791            Expression::MethodCall {
792                base: Box::new(Expression::MethodCall {
793                    base: Box::new(Expression::Variable("vec".to_string())),
794                    method: "iter".to_string(),
795                    args: vec![],
796                }),
797                method: "count".to_string(),
798                args: vec![],
799            }
800        );
801    }
802
803    #[test]
804    fn test_function_call() {
805        // No arguments
806        let expr = parse("foo()");
807        assert_eq!(
808            expr,
809            Expression::FunctionCall {
810                function: "foo".to_string(),
811                args: vec![],
812            }
813        );
814
815        // With arguments
816        let expr = parse("bar(1, 2)");
817        assert_eq!(
818            expr,
819            Expression::FunctionCall {
820                function: "bar".to_string(),
821                args: vec![Expression::NumberLiteral(1), Expression::NumberLiteral(2)],
822            }
823        );
824    }
825
826    #[test]
827    fn test_path_expressions() {
828        // Simple path
829        let expr = parse("std::vec::Vec");
830        assert_eq!(
831            expr,
832            Expression::Path(vec![
833                "std".to_string(),
834                "vec".to_string(),
835                "Vec".to_string()
836            ])
837        );
838
839        // Path function call
840        let expr = parse("lldb_demo::User::new(1, \"foo\", \"bar\")");
841        assert_eq!(
842            expr,
843            Expression::FunctionCall {
844                function: "lldb_demo::User::new".to_string(),
845                args: vec![
846                    Expression::NumberLiteral(1),
847                    Expression::StringLiteral("foo".to_string()),
848                    Expression::StringLiteral("bar".to_string())
849                ],
850            }
851        );
852    }
853
854    #[test]
855    fn test_generic_types() {
856        // Simple generic
857        let expr = parse("Vec<u64>");
858        assert_eq!(
859            expr,
860            Expression::Generic {
861                base: "Vec".to_string(),
862                args: vec!["u64".to_string()],
863            }
864        );
865
866        // Generic with multiple type arguments
867        let expr = parse("HashMap<String, u32>");
868        assert_eq!(
869            expr,
870            Expression::Generic {
871                base: "HashMap".to_string(),
872                args: vec!["String".to_string(), "u32".to_string()],
873            }
874        );
875
876        // Nested generics
877        let expr = parse("Vec<Option<String>>");
878        assert_eq!(
879            expr,
880            Expression::Generic {
881                base: "Vec".to_string(),
882                args: vec!["Option<String>".to_string()],
883            }
884        );
885
886        // Path with generics
887        let expr = parse("std::collections::HashMap<String, u32>");
888        assert_eq!(
889            expr,
890            Expression::Generic {
891                base: "std::collections::HashMap".to_string(),
892                args: vec!["String".to_string(), "u32".to_string()],
893            }
894        );
895    }
896
897    #[test]
898    fn test_method_call_display() {
899        assert_eq!(parse("vec.len()").to_string(), "vec.len()");
900        assert_eq!(parse("vec.push(42)").to_string(), "vec.push(42)");
901        assert_eq!(
902            parse(r#"map.insert("key", 42)"#).to_string(),
903            r#"map.insert("key", 42)"#
904        );
905        assert_eq!(parse("foo()").to_string(), "foo()");
906        assert_eq!(parse("bar(1, 2)").to_string(), "bar(1, 2)");
907    }
908
909    #[test]
910    fn test_path_and_generic_display() {
911        // Path expressions
912        assert_eq!(parse("std::vec::Vec").to_string(), "std::vec::Vec");
913        assert_eq!(
914            parse("lldb_demo::User::new(1, \"foo\", \"bar\")").to_string(),
915            r#"lldb_demo::User::new(1, "foo", "bar")"#
916        );
917
918        // Generic expressions
919        assert_eq!(parse("Vec<u64>").to_string(), "Vec<u64>");
920        assert_eq!(
921            parse("HashMap<String, u32>").to_string(),
922            "HashMap<String, u32>"
923        );
924        assert_eq!(
925            parse("Vec<Option<String>>").to_string(),
926            "Vec<Option<String>>"
927        );
928        assert_eq!(
929            parse("std::collections::HashMap<String, u32>").to_string(),
930            "std::collections::HashMap<String, u32>"
931        );
932    }
933}