carbon_parser/lib.rs
1//! # Carbon Parser
2//!
3//! A high-performance parser for Google's [Carbon programming language](https://github.com/carbon-language/carbon-lang),
4//! built with Rust using the Pest parsing framework.
5//!
6//! ## Overview
7//!
8//! This library provides a complete parsing solution for Carbon source code, enabling developers
9//! to build tools, compilers, analyzers, and other applications that work with Carbon programs.
10//! The parser is built on top of Pest, a PEG (Parsing Expression Grammar) parser that provides
11//! excellent performance and clear error messages.
12//!
13//! ## Features
14//!
15//! - Fast and reliable parsing using Pest PEG parser
16//! - Complete support for Carbon language constructs
17//! - Type-safe AST manipulation through Rust's type system
18//! - Detailed error messages with line and column information
19//! - Zero-copy parsing for efficient memory usage
20//! - Command-line interface for file parsing
21//! - Comprehensive test coverage
22//!
23//! ## Installation
24//!
25//! Add this to your `Cargo.toml`:
26//!
27//! ```toml
28//! [dependencies]
29//! carbon-parser = "0.1.2"
30//! pest = "2.7"
31//! ```
32//!
33//! ## Quick Start
34//!
35//! ```rust
36//! use carbon_parser::parse_carbon;
37//!
38//! let code = r#"
39//! fn main() -> i32 {
40//! var x: i32 = 42;
41//! return x;
42//! }
43//! "#;
44//!
45//! match parse_carbon(code) {
46//! Ok(pairs) => {
47//! println!("Parsing successful");
48//! for pair in pairs {
49//! println!("Rule: {:?}", pair.as_rule());
50//! }
51//! }
52//! Err(e) => eprintln!("Parse error: {}", e),
53//! }
54//! ```
55//!
56//! ## Supported Language Constructs
57//!
58//! ### Functions
59//!
60//! The parser supports function declarations with parameters and return types:
61//!
62//! ```rust
63//! use carbon_parser::parse_function_decl;
64//!
65//! // Simple function without parameters
66//! let code = "fn test() -> i32 { return 42; }";
67//! assert!(parse_function_decl(code).is_ok());
68//!
69//! // Function with single parameter
70//! let code = "fn square(x: i32) -> i32 { return x; }";
71//! assert!(parse_function_decl(code).is_ok());
72//!
73//! // Function with multiple parameters
74//! let code = "fn add(x: i32, y: i32, z: i32) -> i32 { return x; }";
75//! assert!(parse_function_decl(code).is_ok());
76//!
77//! // Function without return type
78//! let code = "fn print_hello() { return 0; }";
79//! assert!(parse_function_decl(code).is_ok());
80//!
81//! // Function with different parameter types
82//! let code = "fn process(name: String, age: i32, active: bool) -> bool { return active; }";
83//! assert!(parse_function_decl(code).is_ok());
84//! ```
85//!
86//! ### Variables
87//!
88//! Variable declarations with type annotations and optional initialization:
89//!
90//! ```rust
91//! use carbon_parser::parse_var_decl;
92//!
93//! // Variable with initialization
94//! let code = "var x: i32 = 42;";
95//! assert!(parse_var_decl(code).is_ok());
96//!
97//! // Variable without initialization
98//! let code = "var y: bool;";
99//! assert!(parse_var_decl(code).is_ok());
100//!
101//! // String variable
102//! let code = r#"var name: String = "John";"#;
103//! assert!(parse_var_decl(code).is_ok());
104//!
105//! // Float variable
106//! let code = "var pi: f64 = 3.14;";
107//! assert!(parse_var_decl(code).is_ok());
108//!
109//! // Variable with expression
110//! let code = "var sum: i32 = 10 + 20;";
111//! assert!(parse_var_decl(code).is_ok());
112//! ```
113//!
114//! ### Expressions
115//!
116//! The parser handles various expression types including literals, identifiers, binary operations,
117//! and function calls:
118//!
119//! ```rust
120//! use carbon_parser::parse_expression;
121//!
122//! // Integer literal
123//! assert!(parse_expression("42").is_ok());
124//!
125//! // Float literal
126//! assert!(parse_expression("3.14").is_ok());
127//!
128//! // Boolean literals
129//! assert!(parse_expression("true").is_ok());
130//! assert!(parse_expression("false").is_ok());
131//!
132//! // String literal
133//! assert!(parse_expression(r#""Hello, World!""#).is_ok());
134//!
135//! // Identifier
136//! assert!(parse_expression("variable_name").is_ok());
137//!
138//! // Binary operations
139//! assert!(parse_expression("10 + 20").is_ok());
140//! assert!(parse_expression("10 + 20 * 30 - 5").is_ok());
141//!
142//! // Function call
143//! assert!(parse_expression("calculate(x, y)").is_ok());
144//!
145//! // Comparison operators
146//! assert!(parse_expression("x == y").is_ok());
147//! assert!(parse_expression("x != y").is_ok());
148//! assert!(parse_expression("x < y").is_ok());
149//! assert!(parse_expression("x > y").is_ok());
150//! ```
151//!
152//! ### Type System
153//!
154//! The parser supports both primitive and custom types:
155//!
156//! ```rust
157//! use carbon_parser::parse_type_name;
158//!
159//! // Integer types
160//! assert!(parse_type_name("i32").is_ok());
161//! assert!(parse_type_name("i64").is_ok());
162//!
163//! // Float types
164//! assert!(parse_type_name("f32").is_ok());
165//! assert!(parse_type_name("f64").is_ok());
166//!
167//! // Boolean type
168//! assert!(parse_type_name("bool").is_ok());
169//!
170//! // String type
171//! assert!(parse_type_name("String").is_ok());
172//!
173//! // Custom types
174//! assert!(parse_type_name("CustomType").is_ok());
175//! ```
176//!
177//! ## Complete Programs
178//!
179//! The main parsing function handles complete Carbon programs:
180//!
181//! ```rust
182//! use carbon_parser::parse_carbon;
183//!
184//! // Empty program
185//! let code = "";
186//! assert!(parse_carbon(code).is_ok());
187//!
188//! // Single function program
189//! let code = r#"
190//! fn main() -> i32 {
191//! return 0;
192//! }
193//! "#;
194//! assert!(parse_carbon(code).is_ok());
195//!
196//! // Multiple functions
197//! let code = r#"
198//! fn add(x: i32, y: i32) -> i32 {
199//! return x;
200//! }
201//!
202//! fn main() -> i32 {
203//! return 0;
204//! }
205//! "#;
206//! assert!(parse_carbon(code).is_ok());
207//!
208//! // Program with variables
209//! let code = r#"
210//! var global_x: i32 = 100;
211//!
212//! fn main() -> i32 {
213//! var local_y: i32 = 200;
214//! return 0;
215//! }
216//! "#;
217//! assert!(parse_carbon(code).is_ok());
218//!
219//! // Program with comments
220//! let code = r#"
221//! // This is a comment
222//! fn main() -> i32 {
223//! /* Multi-line
224//! comment */
225//! return 0;
226//! }
227//! "#;
228//! assert!(parse_carbon(code).is_ok());
229//! ```
230//!
231//! ## Working with Parse Trees
232//!
233//! After parsing, you can traverse and inspect the resulting parse tree:
234//!
235//! ```rust
236//! use carbon_parser::{parse_carbon, Rule};
237//!
238//! let code = r#"
239//! fn calculate(x: i32) -> i32 {
240//! var result: i32 = 42;
241//! return result;
242//! }
243//! "#;
244//!
245//! let pairs = parse_carbon(code).unwrap();
246//!
247//! for pair in pairs {
248//! println!("Top-level rule: {:?}", pair.as_rule());
249//! println!("Text: {}", pair.as_str());
250//!
251//! // Traverse nested pairs
252//! for inner_pair in pair.into_inner() {
253//! println!(" Nested rule: {:?}", inner_pair.as_rule());
254//! println!(" Nested text: {}", inner_pair.as_str());
255//! }
256//! }
257//! ```
258//!
259//! ## Error Handling
260//!
261//! The parser provides detailed error messages indicating the exact location and nature of syntax errors:
262//!
263//! ```rust
264//! use carbon_parser::parse_carbon;
265//!
266//! // Invalid syntax - missing closing parenthesis
267//! let code = "fn main( { }";
268//! assert!(parse_carbon(code).is_err());
269//!
270//! // Missing semicolon
271//! let code = "var x: i32 = 42";
272//! assert!(parse_carbon(code).is_err());
273//!
274//! // Invalid identifier starting with number
275//! let code = "var 123invalid: i32 = 0;";
276//! assert!(parse_carbon(code).is_err());
277//!
278//! // Proper error handling
279//! match parse_carbon("fn broken( { }") {
280//! Ok(_) => println!("Success"),
281//! Err(e) => {
282//! eprintln!("Parse error occurred:");
283//! eprintln!("{}", e);
284//! // The error will show the exact line and column where parsing failed
285//! }
286//! }
287//! ```
288//!
289//! ## Command Line Interface
290//!
291//! The parser includes a CLI tool for parsing Carbon files:
292//!
293//! ```bash
294//! # Parse a Carbon file
295//! cargo run -- parse example.carbon
296//!
297//! # Parse with verbose output showing the parse tree
298//! cargo run -- parse example.carbon --verbose
299//!
300//! # Show author information
301//! cargo run -- authors
302//! ```
303//!
304//! ## Advanced Usage
305//!
306//! ### Building a Syntax Highlighter
307//!
308//! ```rust
309//! use carbon_parser::{parse_carbon, Rule};
310//!
311//! fn highlight_code(code: &str) -> Result<String, Box<dyn std::error::Error>> {
312//! let pairs = parse_carbon(code)?;
313//! let mut highlighted = String::new();
314//!
315//! for pair in pairs {
316//! match pair.as_rule() {
317//! Rule::function_decl => {
318//! highlighted.push_str(&format!("<span class='function'>{}</span>",
319//! pair.as_str()));
320//! }
321//! Rule::var_decl => {
322//! highlighted.push_str(&format!("<span class='variable'>{}</span>",
323//! pair.as_str()));
324//! }
325//! _ => highlighted.push_str(pair.as_str()),
326//! }
327//! }
328//!
329//! Ok(highlighted)
330//! }
331//! ```
332//!
333//! ### Code Analysis
334//!
335//! ```rust
336//! use carbon_parser::{parse_carbon, Rule};
337//! use std::collections::HashMap;
338//!
339//! fn count_functions(code: &str) -> Result<usize, Box<dyn std::error::Error>> {
340//! let pairs = parse_carbon(code)?;
341//! let mut count = 0;
342//!
343//! for pair in pairs {
344//! if matches!(pair.as_rule(), Rule::function_decl) {
345//! count += 1;
346//! }
347//! }
348//!
349//! Ok(count)
350//! }
351//! ```
352//!
353//! ## Performance Considerations
354//!
355//! This parser is designed for optimal performance:
356//!
357//! - **Zero-copy parsing**: The parse tree references the original input string rather than
358//! copying data, minimizing memory allocations.
359//! - **Lazy evaluation**: Parse tree nodes are created on-demand as you traverse the tree.
360//! - **Efficient grammar**: The PEG grammar is optimized to minimize backtracking.
361//!
362//! For large files (>1MB), consider:
363//! - Using streaming or incremental parsing if available
364//! - Processing the parse tree in chunks
365//! - Using the `--verbose` flag judiciously in the CLI tool
366//!
367//! ## Error Recovery
368//!
369//! When parsing fails, the error type provides detailed information:
370//!
371//! ```rust
372//! use carbon_parser::{parse_carbon, ParseError};
373//!
374//! match parse_carbon("invalid code") {
375//! Err(ParseError::PestError(e)) => {
376//! // Pest error with line/column information
377//! eprintln!("Syntax error at: {}", e);
378//! }
379//! Err(ParseError::SyntaxError(msg)) => {
380//! // Custom syntax error
381//! eprintln!("Error: {}", msg);
382//! }
383//! Ok(_) => {}
384//! }
385//! ```
386//!
387//! ## Testing
388//!
389//! The library includes comprehensive integration tests covering:
390//! - Function declarations with various parameter combinations
391//! - Variable declarations with different types
392//! - Expression parsing including operators and precedence
393//! - Type system validation
394//! - Complete program parsing
395//! - Error detection and reporting
396//!
397//! Run tests with:
398//! ```bash
399//! cargo test
400//! ```
401//!
402//! ## Grammar Reference
403//!
404//! The parser is based on a formal grammar defined in `carbon.pest`. Key grammar rules include:
405//!
406//! - `program`: Top-level rule matching complete Carbon programs
407//! - `function_decl`: Function declarations
408//! - `var_decl`: Variable declarations
409//! - `expression`: All expression types
410//! - `type_name`: Type annotations
411//! - `statement`: Individual statements
412//!
413//! ## Contributing
414//!
415//! Contributions are welcome. Please ensure all tests pass and add tests for new features.
416//!
417//! ## Author
418//!
419//! Daniil Cherniavskyi
420//!
421//! ## License
422//!
423//! This project is available under standard open source licenses.
424
425use pest::Parser;
426use pest_derive::Parser;
427use thiserror::Error;
428
429/// Carbon parser implementation using Pest.
430///
431/// This struct is generated by the `pest_derive` macro and implements the parsing
432/// logic defined in `carbon.pest`. You typically will not need to use this struct
433/// directly; instead, use the provided parsing functions.
434///
435/// # Implementation Details
436///
437/// The parser uses a PEG (Parsing Expression Grammar) which provides:
438/// - Deterministic parsing without ambiguity
439/// - Clear error messages with position information
440/// - Efficient parsing with linear time complexity
441/// - Composable grammar rules
442#[derive(Parser)]
443#[grammar = "carbon.pest"]
444pub struct CarbonParser;
445
446/// Errors that can occur during parsing.
447///
448/// This enum encapsulates both syntax errors and internal parser errors,
449/// providing a unified error handling interface for all parsing operations.
450#[derive(Error, Debug)]
451pub enum ParseError {
452 /// A syntax error in the Carbon source code.
453 ///
454 /// This error is used for high-level syntax violations that are caught
455 /// during semantic analysis rather than during initial parsing.
456 #[error("Syntax error: {0}")]
457 SyntaxError(String),
458
459 /// An error from the Pest parser.
460 ///
461 /// This error includes detailed information about:
462 /// - The exact line and column where the error occurred
463 /// - What the parser expected at that position
464 /// - The actual input that was found
465 ///
466 /// # Example Error Message
467 ///
468 /// ```text
469 /// --> 1:8
470 /// |
471 /// 1 | fn test {
472 /// | ^---
473 /// |
474 /// = expected `(`
475 /// ```
476 #[error("Parser error: {0}")]
477 PestError(#[from] pest::error::Error<Rule>),
478}
479
480/// Result type for parsing operations.
481///
482/// This type alias provides a convenient way to work with parsing results
483/// throughout the library. All parsing functions return this type.
484pub type ParseResult<T> = Result<T, ParseError>;
485
486/// Parses a complete Carbon program.
487///
488/// This is the main entry point for parsing Carbon source code. It expects
489/// a complete, valid Carbon program which may contain multiple top-level
490/// declarations including functions, variables, and other constructs.
491///
492/// # Arguments
493///
494/// * `input` - The complete Carbon source code as a string slice
495///
496/// # Returns
497///
498/// Returns a `ParseResult` containing an iterator over the top-level parse tree
499/// nodes on success, or a detailed `ParseError` on failure.
500///
501/// # Grammar Rule
502///
503/// This function uses the `program` grammar rule from `carbon.pest`.
504///
505/// # Examples
506///
507/// ## Basic Usage
508///
509/// ```rust
510/// use carbon_parser::parse_carbon;
511///
512/// let code = r#"
513/// fn main() -> i32 {
514/// return 0;
515/// }
516/// "#;
517///
518/// let result = parse_carbon(code);
519/// assert!(result.is_ok());
520/// ```
521///
522/// ## Multiple Functions
523///
524/// ```rust
525/// use carbon_parser::parse_carbon;
526///
527/// let code = r#"
528/// fn add(x: i32, y: i32) -> i32 {
529/// return x;
530/// }
531///
532/// fn main() -> i32 {
533/// return 0;
534/// }
535/// "#;
536///
537/// let result = parse_carbon(code);
538/// assert!(result.is_ok());
539/// ```
540///
541/// ## With Variables
542///
543/// ```rust
544/// use carbon_parser::parse_carbon;
545///
546/// let code = r#"
547/// var counter: i32 = 0;
548///
549/// fn increment(x: i32) -> i32 {
550/// return x;
551/// }
552/// "#;
553///
554/// let result = parse_carbon(code);
555/// assert!(result.is_ok());
556/// ```
557///
558/// ## Error Handling
559///
560/// ```rust
561/// use carbon_parser::parse_carbon;
562///
563/// let invalid = "fn broken( { }";
564/// match parse_carbon(invalid) {
565/// Ok(_) => panic!("Should have failed"),
566/// Err(e) => println!("Expected error: {}", e),
567/// }
568/// ```
569pub fn parse_carbon(input: &str) -> ParseResult<pest::iterators::Pairs<Rule>> {
570 CarbonParser::parse(Rule::program, input).map_err(ParseError::from)
571}
572
573/// Parses a single function declaration.
574///
575/// Use this function when you need to parse an individual function definition
576/// in isolation, without requiring a complete program context. This is useful
577/// for testing, code generation, incremental parsing, or working with code fragments.
578///
579/// # Carbon Function Syntax
580///
581/// A function declaration in Carbon has the following structure:
582///
583/// ```text
584/// fn function_name(param1: Type1, param2: Type2) -> ReturnType {
585/// // function body statements
586/// return expression;
587/// }
588/// ```
589///
590/// Components:
591/// - `fn` keyword to start the declaration
592/// - Function name (identifier)
593/// - Parameter list in parentheses (may be empty)
594/// - Optional return type preceded by `->`
595/// - Function body in braces
596///
597/// # Arguments
598///
599/// * `input` - A string slice containing exactly one function declaration
600///
601/// # Returns
602///
603/// Returns a `ParseResult` containing the parsed function declaration tree.
604///
605/// # Grammar Rule
606///
607/// This function uses the `function_decl` grammar rule from `carbon.pest`.
608///
609/// # Examples
610///
611/// ## Function Without Parameters
612///
613/// ```rust
614/// use carbon_parser::parse_function_decl;
615///
616/// let code = "fn test() -> i32 { return 42; }";
617/// let result = parse_function_decl(code);
618/// assert!(result.is_ok());
619/// ```
620///
621/// ## Function With Single Parameter
622///
623/// ```rust
624/// use carbon_parser::parse_function_decl;
625///
626/// let code = "fn square(x: i32) -> i32 { return x; }";
627/// let result = parse_function_decl(code);
628/// assert!(result.is_ok());
629/// ```
630///
631/// ## Function With Multiple Parameters
632///
633/// ```rust
634/// use carbon_parser::parse_function_decl;
635///
636/// let code = "fn add(x: i32, y: i32, z: i32) -> i32 { return x; }";
637/// let result = parse_function_decl(code);
638/// assert!(result.is_ok());
639/// ```
640///
641/// ## Function Without Return Type
642///
643/// ```rust
644/// use carbon_parser::parse_function_decl;
645///
646/// let code = "fn print_hello() { return 0; }";
647/// let result = parse_function_decl(code);
648/// assert!(result.is_ok());
649/// ```
650///
651/// ## Function With Mixed Parameter Types
652///
653/// ```rust
654/// use carbon_parser::parse_function_decl;
655///
656/// let code = "fn process(name: String, age: i32, active: bool) -> bool { return active; }";
657/// let result = parse_function_decl(code);
658/// assert!(result.is_ok());
659/// ```
660pub fn parse_function_decl(input: &str) -> ParseResult<pest::iterators::Pairs<Rule>> {
661 CarbonParser::parse(Rule::function_decl, input).map_err(ParseError::from)
662}
663
664/// Parses a variable declaration statement.
665///
666/// Variable declarations in Carbon require explicit type annotations and may
667/// optionally include an initializer expression. Variables use the `var` keyword
668/// and must specify their type before use.
669///
670/// # Carbon Variable Syntax
671///
672/// A variable declaration has the following structure:
673///
674/// ```text
675/// var variable_name: Type = initial_value;
676/// ```
677///
678/// Components:
679/// - `var` keyword to start the declaration
680/// - Variable name (identifier)
681/// - Type annotation preceded by `:`
682/// - Optional initializer with `=` and expression
683/// - Terminating semicolon
684///
685/// # Arguments
686///
687/// * `input` - A string slice containing exactly one variable declaration
688///
689/// # Returns
690///
691/// Returns a `ParseResult` containing the parsed variable declaration tree.
692///
693/// # Grammar Rule
694///
695/// This function uses the `var_decl` grammar rule from `carbon.pest`.
696///
697/// # Examples
698///
699/// ## Variable With Initialization
700///
701/// ```rust
702/// use carbon_parser::parse_var_decl;
703///
704/// let code = "var x: i32 = 42;";
705/// let result = parse_var_decl(code);
706/// assert!(result.is_ok());
707/// ```
708///
709/// ## Variable Without Initialization
710///
711/// ```rust
712/// use carbon_parser::parse_var_decl;
713///
714/// let code = "var y: bool;";
715/// let result = parse_var_decl(code);
716/// assert!(result.is_ok());
717/// ```
718///
719/// ## String Variable
720///
721/// ```rust
722/// use carbon_parser::parse_var_decl;
723///
724/// let code = r#"var name: String = "John";"#;
725/// let result = parse_var_decl(code);
726/// assert!(result.is_ok());
727/// ```
728///
729/// ## Float Variable
730///
731/// ```rust
732/// use carbon_parser::parse_var_decl;
733///
734/// let code = "var pi: f64 = 3.14;";
735/// let result = parse_var_decl(code);
736/// assert!(result.is_ok());
737/// ```
738///
739/// ## Variable With Expression
740///
741/// ```rust
742/// use carbon_parser::parse_var_decl;
743///
744/// let code = "var sum: i32 = 10 + 20;";
745/// let result = parse_var_decl(code);
746/// assert!(result.is_ok());
747/// ```
748pub fn parse_var_decl(input: &str) -> ParseResult<pest::iterators::Pairs<Rule>> {
749 CarbonParser::parse(Rule::var_decl, input).map_err(ParseError::from)
750}
751
752/// Parses an expression.
753///
754/// Expressions are fundamental building blocks that compute or represent values.
755/// This parser handles a comprehensive range of expression types with proper
756/// operator precedence and associativity rules.
757///
758/// # Supported Expression Types
759///
760/// - **Literals**: Integer, float, boolean, and string constants
761/// - **Identifiers**: Variable and function names
762/// - **Binary Operations**: Arithmetic, comparison, and logical operators
763/// - **Function Calls**: Invocations with argument lists
764/// - **Parenthesized Expressions**: For grouping and precedence control
765///
766/// # Operator Precedence
767///
768/// Operators are evaluated in the following order (highest to lowest):
769///
770/// 1. Parentheses: `( )`
771/// 2. Unary operators
772/// 3. Multiplicative: `*`, `/`, `%`
773/// 4. Additive: `+`, `-`
774/// 5. Comparison: `<`, `>`, `<=`, `>=`
775/// 6. Equality: `==`, `!=`
776/// 7. Logical AND: `&&`
777/// 8. Logical OR: `||`
778///
779/// # Arguments
780///
781/// * `input` - A string slice containing exactly one expression
782///
783/// # Returns
784///
785/// Returns a `ParseResult` containing the parsed expression tree.
786///
787/// # Grammar Rule
788///
789/// This function uses the `expression` grammar rule from `carbon.pest`.
790///
791/// # Examples
792///
793/// ## Literals
794///
795/// ```rust
796/// use carbon_parser::parse_expression;
797///
798/// // Integer literal
799/// assert!(parse_expression("42").is_ok());
800///
801/// // Float literal
802/// assert!(parse_expression("3.14").is_ok());
803///
804/// // Boolean literals
805/// assert!(parse_expression("true").is_ok());
806/// assert!(parse_expression("false").is_ok());
807///
808/// // String literal
809/// assert!(parse_expression(r#""Hello, World!""#).is_ok());
810/// ```
811///
812/// ## Identifiers
813///
814/// ```rust
815/// use carbon_parser::parse_expression;
816///
817/// let code = "variable_name";
818/// let result = parse_expression(code);
819/// assert!(result.is_ok());
820/// ```
821///
822/// ## Binary Operations
823///
824/// ```rust
825/// use carbon_parser::parse_expression;
826///
827/// // Addition
828/// assert!(parse_expression("10 + 20").is_ok());
829///
830/// // Complex arithmetic with precedence
831/// assert!(parse_expression("10 + 20 * 30 - 5").is_ok());
832/// ```
833///
834/// ## Function Calls
835///
836/// ```rust
837/// use carbon_parser::parse_expression;
838///
839/// let code = "calculate(x, y)";
840/// let result = parse_expression(code);
841/// assert!(result.is_ok());
842/// ```
843///
844/// ## Comparison Operators
845///
846/// ```rust
847/// use carbon_parser::parse_expression;
848///
849/// assert!(parse_expression("x == y").is_ok());
850/// assert!(parse_expression("x != y").is_ok());
851/// assert!(parse_expression("x < y").is_ok());
852/// assert!(parse_expression("x > y").is_ok());
853/// ```
854pub fn parse_expression(input: &str) -> ParseResult<pest::iterators::Pairs<Rule>> {
855 CarbonParser::parse(Rule::expression, input).map_err(ParseError::from)
856}
857
858/// Parses a type name.
859///
860/// Carbon has a static type system that includes both built-in primitive types
861/// and support for user-defined custom types. This function validates and parses
862/// type names used in variable declarations, function parameters, and return types.
863///
864/// # Built-in Primitive Types
865///
866/// - **Signed Integers**: `i32`, `i64`
867/// - **Unsigned Integers**: `u32`, `u64` (if supported by grammar)
868/// - **Floating-Point**: `f32`, `f64`
869/// - **Boolean**: `bool`
870/// - **String**: `String`
871///
872/// # Custom Types
873///
874/// User-defined types follow standard identifier naming rules and can represent
875/// structs, classes, interfaces, or other custom type definitions.
876///
877/// # Arguments
878///
879/// * `input` - A string slice containing exactly one type name
880///
881/// # Returns
882///
883/// Returns a `ParseResult` containing the parsed type name.
884///
885/// # Grammar Rule
886///
887/// This function uses the `type_name` grammar rule from `carbon.pest`.
888///
889/// # Examples
890///
891/// ## Integer Types
892///
893/// ```rust
894/// use carbon_parser::parse_type_name;
895///
896/// assert!(parse_type_name("i32").is_ok());
897/// assert!(parse_type_name("i64").is_ok());
898/// ```
899///
900/// ## Float Types
901///
902/// ```rust
903/// use carbon_parser::parse_type_name;
904///
905/// assert!(parse_type_name("f32").is_ok());
906/// assert!(parse_type_name("f64").is_ok());
907/// ```
908///
909/// ## Boolean Type
910///
911/// ```rust
912/// use carbon_parser::parse_type_name;
913///
914/// let result = parse_type_name("bool");
915/// assert!(result.is_ok());
916/// ```
917///
918/// ## String Type
919///
920/// ```rust
921/// use carbon_parser::parse_type_name;
922///
923/// let result = parse_type_name("String");
924/// assert!(result.is_ok());
925/// ```
926///
927/// ## Custom Type
928///
929/// ```rust
930/// use carbon_parser::parse_type_name;
931///
932/// let result = parse_type_name("CustomType");
933/// assert!(result.is_ok());
934/// ```
935pub fn parse_type_name(input: &str) -> ParseResult<pest::iterators::Pairs<Rule>> {
936 CarbonParser::parse(Rule::type_name, input).map_err(ParseError::from)
937}
938
939#[cfg(test)]
940mod tests {
941 use super::*;
942
943 #[test]
944 fn test_simple_function() {
945 let code = r#"
946 fn main() -> i32 {
947 return 42;
948 }
949 "#;
950 assert!(parse_carbon(code).is_ok());
951 }
952
953 #[test]
954 fn test_function_with_params() {
955 let code = "fn add(x: i32, y: i32) -> i32 { return x; }";
956 assert!(parse_function_decl(code).is_ok());
957 }
958
959 #[test]
960 fn test_variable_declaration() {
961 let code = "var x: i32 = 42;";
962 assert!(parse_var_decl(code).is_ok());
963 }
964
965 #[test]
966 fn test_expression() {
967 let code = "42 + 10 * 2";
968 assert!(parse_expression(code).is_ok());
969 }
970
971 #[test]
972 fn test_type_names() {
973 assert!(parse_type_name("i32").is_ok());
974 assert!(parse_type_name("bool").is_ok());
975 assert!(parse_type_name("String").is_ok());
976 }
977
978 #[test]
979 fn test_complex_expression() {
980 let code = "(a + b) * c - d / e";
981 assert!(parse_expression(code).is_ok());
982 }
983
984 #[test]
985 fn test_function_with_complex_body() {
986 let code = r#"
987 fn fibonacci(n: i32) -> i32 {
988 var a: i32 = 0;
989 var b: i32 = 1;
990 var i: i32 = 0;
991 return a;
992 }
993 "#;
994 assert!(parse_function_decl(code).is_ok());
995 }
996
997 #[test]
998 fn test_multiple_functions() {
999 let code = r#"
1000 fn first() -> i32 { return 1; }
1001 fn second() -> i32 { return 2; }
1002 "#;
1003 assert!(parse_carbon(code).is_ok());
1004 }
1005
1006 #[test]
1007 fn test_error_handling() {
1008 let invalid = "fn broken() {";
1009 assert!(parse_carbon(invalid).is_err());
1010 }
1011
1012 #[test]
1013 fn test_empty_program() {
1014 let code = "";
1015 assert!(parse_carbon(code).is_ok());
1016 }
1017
1018 #[test]
1019 fn test_program_with_comments() {
1020 let code = r#"
1021 // This is a comment
1022 fn main() -> i32 {
1023 /* Multi-line
1024 comment */
1025 return 0;
1026 }
1027 "#;
1028 assert!(parse_carbon(code).is_ok());
1029 }
1030
1031 #[test]
1032 fn test_variable_without_initialization() {
1033 let code = "var y: bool;";
1034 assert!(parse_var_decl(code).is_ok());
1035 }
1036
1037 #[test]
1038 fn test_function_without_return_type() {
1039 let code = "fn print_hello() { return 0; }";
1040 assert!(parse_function_decl(code).is_ok());
1041 }
1042
1043 #[test]
1044 fn test_comparison_operators() {
1045 assert!(parse_expression("x == y").is_ok());
1046 assert!(parse_expression("x != y").is_ok());
1047 assert!(parse_expression("x < y").is_ok());
1048 assert!(parse_expression("x > y").is_ok());
1049 }
1050
1051 #[test]
1052 fn test_boolean_literals() {
1053 assert!(parse_expression("true").is_ok());
1054 assert!(parse_expression("false").is_ok());
1055 }
1056
1057 #[test]
1058 fn test_string_literal() {
1059 let code = r#""Hello, World!""#;
1060 assert!(parse_expression(code).is_ok());
1061 }
1062
1063 #[test]
1064 fn test_function_call() {
1065 let code = "calculate(x, y)";
1066 assert!(parse_expression(code).is_ok());
1067 }
1068
1069 #[test]
1070 fn test_invalid_syntax() {
1071 let code = "fn main( { }";
1072 assert!(parse_carbon(code).is_err());
1073 }
1074
1075 #[test]
1076 fn test_missing_semicolon() {
1077 let code = "var x: i32 = 42";
1078 assert!(parse_var_decl(code).is_err());
1079 }
1080
1081 #[test]
1082 fn test_custom_type() {
1083 assert!(parse_type_name("CustomType").is_ok());
1084 }
1085
1086 #[test]
1087 fn test_float_types() {
1088 assert!(parse_type_name("f32").is_ok());
1089 assert!(parse_type_name("f64").is_ok());
1090 }
1091
1092 #[test]
1093 fn test_program_with_variables() {
1094 let code = r#"
1095 var global_x: i32 = 100;
1096
1097 fn main() -> i32 {
1098 var local_y: i32 = 200;
1099 return 0;
1100 }
1101 "#;
1102 assert!(parse_carbon(code).is_ok());
1103 }
1104}