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}