zypo_parser/
lib.rs

1//! # About
2//!
3//! `zypo-parser` is the primary parser implementation for the `zypo-rs`
4//! reference compiler. This package uses the [LALRPOP](https://github.com/lalrpop/lalrpop)
5//! library, a yacc-like `LR(1)` parser combiner for Rust. This crate also
6//! contains the AST (*abstract-syntax-tree*) for Zypo and all public AST structures,
7//! enums and associated functions are avalible at the base-level of this crate.
8//!
9//! *Please beware as this package is heavily work-in-progress and is developed
10//! alongside the main Zypo compiler as a sub-package. If you are looking for
11//! the base `zypo-rs` compiler, you may find it
12//! [here](https://gitlab.com/zypo/zypo-rs)*.
13//!
14//! # Examples
15//!
16//! Shortcut for parsing an AST or panicing if there is an error in any of the
17//! given input:
18//!
19//! ```rust
20//! use zypo_parser::{
21//!     Function,
22//!     VarType,
23//!     Parameter,
24//!     ast_result
25//! }; // All but ast_result are from the AST. ast_result is the shortcut func
26//!
27//! fn main() {
28//!     let input = "fun shortcut_test_func(my_param: int) {}";
29//!     let expected = vec![
30//!         Function {
31//!             ident: "shortcut_test_func".to_string(),
32//!             params: vec![
33//!                 Parameter { ident: "my_param".to_string(), ty: VarType::Int }
34//!             ],
35//!             body: vec![],
36//!             return_type: VarType::Void
37//!         }
38//!     ];
39//!
40//!     assert_eq!(ast_result(input), expected);
41//! }
42//! ```
43//!
44//! More controllable but lower-level `LALRPOP` bind for manually handling the
45//! generated parsing errors:
46//!
47//! ```rust
48//! use zypo_parser::{
49//!     Function,
50//!     VarType,
51//!     parser
52//! }; // Function and VarType are from the AST, parser is generated by LALRPOP
53//!
54//! fn main() {
55//!     let input = "fun test_func() {}";
56//!     let expected = vec![
57//!         Function {
58//!             ident: "test_func".to_string(),
59//!             params: vec![],
60//!             body: vec![],
61//!             return_type: VarType::Void
62//!         }
63//!     ];
64//!
65//!     assert_eq!(parser::GrammarParser::new().parse(input).unwrap(), expected);
66//! }
67//! ```
68
69#[macro_use]
70extern crate lalrpop_util;
71
72mod ast;
73
74lalrpop_mod!(pub parser, "/grammar.rs");
75
76pub use ast::*;
77
78/// Gets the abstract syntax tree generated from the parser of `zypo-rs`. This
79/// function will panic is parsing fails and is intended for developers aiming
80/// to implament the parser into code generation.
81///
82/// Please see [Function] for more infomation of what this will immidiatly
83/// return.
84///
85/// # Examples
86///
87/// Basic function with 2 defined parameters:
88///
89/// ```rust
90/// use zypo_parser::{
91///     VarType,
92///     Function,
93///     Parameter,
94///     ast_result
95/// };
96///
97/// fn main() {
98///     let input = "fun test_function(my_int: int, some_string: str) {}";
99///     let expected = vec![
100///         Function {
101///             ident: "test_function".to_string(),
102///             params: vec![
103///                 Parameter { ident: "my_int".to_string(), ty: VarType::Int },
104///                 Parameter { ident: "some_string".to_string(), ty: VarType::Str }
105///             ],
106///             body: vec![],
107///             return_type: VarType::Void
108///         }
109///     ];
110///
111///     assert_eq!(ast_result(input), expected);
112/// }
113/// ```
114pub fn ast_result(input: &str) -> Vec<Function> {
115    parser::GrammarParser::new().parse(input).unwrap()
116}
117
118#[cfg(test)]
119mod tests {
120    use super::*;
121
122    /// Tests for the correct output of a basic function decleration with no
123    /// defined body.
124    #[test]
125    fn basic_function_ast() {
126        let input_str = "fun hello_there(hi: str) {}";
127        let expected = vec![Function {
128            ident: "hello_there".to_string(),
129            params: vec![Parameter {
130                ident: "hi".to_string(),
131                ty: VarType::Str,
132            }],
133            body: vec![],
134            return_type: VarType::Void,
135        }];
136
137        assert_eq!(ast_result(input_str), expected);
138    }
139
140    /// Tests a simple variable statement inside of the function
141    #[test]
142    fn while_loop_ast() {
143        let input_str = "fun test_while() { var x: int = 54; }";
144        let expected = vec![Function {
145            ident: "test_while".to_string(),
146            params: vec![],
147            body: vec![StatementNode::Variable(Variable {
148                ident: "x".to_string(),
149                ty: VarType::Int,
150                body: Box::new(ExpressionNode::Constant(Constant::Int(54))),
151            })],
152            return_type: VarType::Void,
153        }];
154
155        assert_eq!(ast_result(input_str), expected);
156    }
157}