1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
//! # About
//!
//! `zypo-rs` is the official refrence compiler for the Zypo programming language.
//! This compiler was built in [Rust](https://www.rust-lang.org/) and targets
//! Python bytecode primarily.
//!
//! # Objectives
//!
//! Below are some of the core sentients and objectives that Zypo aims towards.
//!
//! - Python inter-compatibility
//! - Compiler portability (lightweight)
//! - Fast compile speeds + optimizations
//! - Standard library only
//!
//! # Disclaimers
//!
//! - There is currently no *formal* standard for Zypo so please stick to a
//! documented compiler version and stick with it
//! - This project is heavily **work-in-progress** so please do not use this
//! compiler in production.
//!
//! # Installing `zypo-rs`
//!
//! ## Building from source
//!
//! You can easily build `zypo-rs` from source using the in-built crates
//! builder. Below are some simple steps on how to do so.
//!
//! 1. Clone the `zypo-rs` repository with `git clone https://gitlab.com/zypo/zypo-rs/`
//! 2. Make sure you have Rust [installed](https://www.rust-lang.org/tools/install).
//! 3. Enter the repository and type `cargo build` to build the compiler.
//! 4. That's it! You have successfully built the compiler from source code.
//! Please view the relevant [documentation](#for-users) for further
//! information.
//!
//! # Language syntax
//!
//! Basic blocks and class example:
//!
//! ```zypo
//! get requests;
//!
//! --- This is a docstring, it is 3x `-` and they should be parsed in
//! --- ***MARKDOWN*** (similar to what Rust does).
//! fun send_url(url: string) -> string {
//!     if (url == null) {
//!         return "No URL provided";
//!     }
//!     else {
//!         return requests.post(url).json();
//!     }
//! }
//!
//! --- CoolClass is a simple testing class that you can easily add your full name
//! --- to and edit if you so wish.
//! ---
//! --- # Examples
//! ---
//! --- ```zypo
//! --- var new_class: CoolClass = CoolClass("Owen", "[last_name]");
//! --- new_class.print_name();
//! ---
//! --- new_class.change_name("John", "Matthews");
//! --- new_class.print_name();
//! --- ```
//! class CoolClass {
//!     fun __init__(self, first_name: string, last_name: string) {
//!         change_name(first_name, last_name);
//!     }
//!
//!     fun print_name(self) {
//!         print(self.name);
//!     }
//!
//!     fun change_name(self, first_name: string, last_name: string) {
//!         var self.name: string = self._swap_name_full(
//!             concat(" ", first_name, last_name)
//!         );
//!     }
//! }
//!
//! fun main() {
//!     -- Testing send_url
//!
//!     var url: string = "https://duck.com";
//!     var return_msg: string = "";
//!
//!     try {
//!         return_msg = send_url(url);
//!     }
//!     catch {
//!         return_msg = "Unsuccessful";
//!     }
//!     else {
//!         print("Sent successfully!");
//!     }
//!
//!     if (return_msg) {
//!         print(return_msg);
//!     }
//!
//!     -- Testing CoolClass
//!
//!     var new_class: CoolClass = CoolClass("Owen", "[last_name]");
//!     new_class.print_name();
//!
//!     new_class.change_name("John", "Matthews");
//!     new_class.print_name();
//! }
//! ```
//!
//! # Other infomation
//!
//! ## Credits
//!
//! - Owez ([GitLab](https://gitlab.com/owez), [Portfolio](https://ogriffiths.com)): Core developer
//!
//! ## Licensing
//!
//! As you may find in `LICENSE` inside of this compiler's source code (found
//! [here](https://gitlab.com/zypo/zypo-rs/)), this repository is licensed
//! under the [MIT](https://opensource.org/licenses/MIT) license.

#[macro_use]
extern crate lalrpop_util;

mod parser;

pub use parser::ast::*;

/// Gets the abstract syntax tree generated from the parser of `zypo-rs`. This
/// function will panic is parsing fails and is intended for developers aiming
/// to implament the parser into code generation.
///
/// Please see [Function] for more infomation of what this will immidiatly
/// return.
///
/// # Examples
///
/// Basic function with 1 defined parameter:
///
/// ```rust
/// use zypo_rs::{
///     VarType,
///     Function,
///     Parameter,
///     ast_result
/// };
///
/// fn main() {
///     let input = "fun test_function(my_int: int, some_string: str) {}";
///     let expected = vec![
///         Function {
///             ident: "test_function".to_string(),
///             params: vec![
///                 Parameter { ident: "my_int".to_string(), ty: VarType::Int },
///                 Parameter { ident: "some_string".to_string(), ty: VarType::Str }
///             ],
///             body: vec![]
///         }
///     ];
///
///     assert_eq!(ast_result(input), expected);
/// }
/// ```
pub fn ast_result(input: &str) -> Vec<Function> {
    parser::parser::GrammarParser::new().parse(input).unwrap()
}

#[cfg(test)]
mod tests {
    use super::*;

    /// Tests for the correct output of a basic function decleration with no
    /// defined body.
    #[test]
    fn basic_function_ast() {
        let input_str = "fun hello_there(hi: str) {}";
        let expected = vec![Function {
            ident: "hello_there".to_string(),
            params: vec![Parameter {
                ident: "hi".to_string(),
                ty: VarType::Str,
            }],
            body: vec![],
        }];

        assert_eq!(ast_result(input_str), expected);
    }
}