Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/theiskaa/mate
A simple and lightweight arithmetic expression interpreter
https://github.com/theiskaa/mate
interpreter math parser
Last synced: about 2 months ago
JSON representation
A simple and lightweight arithmetic expression interpreter
- Host: GitHub
- URL: https://github.com/theiskaa/mate
- Owner: theiskaa
- License: apache-2.0
- Created: 2021-10-25T15:12:44.000Z (about 3 years ago)
- Default Branch: main
- Last Pushed: 2024-01-11T19:27:12.000Z (almost 1 year ago)
- Last Synced: 2024-10-28T14:18:27.205Z (2 months ago)
- Topics: interpreter, math, parser
- Language: Rust
- Homepage: https://crates.io/crates/mate-rs
- Size: 220 KB
- Stars: 21
- Watchers: 2
- Forks: 1
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
Mate is a library designed for parsing and calculating arithmetic expressions inputted as strings. It utilizes a Lexer structure, similar to those found in interpreted programming languages, to parse string input into a token list. The Calculator structure is then used to compute the final result from this token list. A general wrapper structure is also implemented that encapsulates both the Lexer and Calculator, simplifying the process of calculating arithmetic expression results without the need for manual parsing and calculation.
**Note**: This project serves as a demonstration and is not intended for production use. It represents my initial steps in learning to create a programming language.
# Usage
This crate is available on [crates.io](http://crates.io/crates/mate-rs) and can be added to your project's dependencies in your `Cargo.toml` file.
```toml
[dependencies]
mate-rs = "0.1.4"
```## Example: Using `Mate`
`Mate` is a general wrapper structure for `Lexer` and `Calculator`. It provides a single method for calculating results from string input.
```rust
use mate_rs::mate::Mate;let result = Mate::calculate("6 * 7");
match result {
Ok(v) => assert_eq!(v, 42.0),
Err(_) => {
// Handle error ...
}
};
```## Example: Using `Lexer` and `Calculator`
`Lexer` is the primary structure that parses string input into a token list. `Calculator` is used to compute the final result from the `Lexer`'s output.
```rust
use mate_rs::{calculator::Calculator, lexer::Lexer};let input = "[ (2 + 5) * (5 - 9 + (8 - 5)) ] + 35";
let tokens = Lexer::lex(input.clone()).unwrap(); // Error handling should also be implemented
```View the generated token tree
// The generated tokens will resemble the following:
//
// Token(
// type: SUBEXP,
// tokens: [
// Token(
// type: SUBEXP,
// tokens: [
// Token(type: NUMBER, literal: "2")
// Token(type: PLUS, literal: "+")
// Token(type: NUMBER, literal: "5")
// ],
// ),
// Token(type: PRODUCT, literal: "*"),
// Token(
// type: SUBEXP,
// tokens: [
// Token(type: NUMBER, literal: "5")
// Token(type: MINUS, literal: "-")
// Token(type: NUMBER, literal: "9")
// Token(type: PLUS, literal: "+")
// Token(
// type: SUBEXP,
// tokens: [
// Token(type: NUMBER, literal: "8")
// Token(type: PLUS, literal: "-")
// Token(type: NUMBER, literal: "5")
// ],
// ),
// ],
// ),
// ],
// ),
// Token(type: PLUS, literal: "+")
// Token(type: NUMBER, literal: "35")```rust
// The result is calculated from the tokens using the X/O/Y algorithm.
//
// ╭────────╮ ╭───────────╮ ╭────────╮
// │ NUMBER │ │ OPERATION │ │ NUMBER │
// ╰────────╯ ╰───────────╯ ╰────────╯
// ╰───╮ │ ╭───╯
// ▼ ▼ ▼
// X [+, -, *, /] Y
//
let result = Calculator::calculate(tokens, input.clone());
```---
# How it Works
Mate primarily consists of two main structures: [Lexer] and [Calculator]. The [Lexer] structure is responsible for parsing and interpreting the given string expression, while the [Calculator] structure calculates the final result from the parsed tokens.## Lexer
The Lexer iterates through the given input string, reading and converting each character into a [Token] structure. The main types of tokens include:
- `ILLEGAL` - Represents an illegal character.
- `NUMBER` - Represents a number.
- `MINUS`, `PLUS`, `PRODUCT`, `DIVIDE`, `PERCENTAGE`, `POWER` - Represents operations.
- `LPAREN`, `RPAREN` - Represents parentheses.
- `LABS`, `RABS` - Represents absolute values.
- `SUBEXP` - Represents sub-expressions, which are expressions inside parentheses, absolute values, or combinations of division and multiplication.The Lexer's `lex` function converts each character into one of these tokens. It groups tokens related to multiplication or division operations into a single sub-expression to maintain the correct operation priority. It also nests parentheses, absolute values, and powers using a custom level-to-expression algorithm.
The level-to-expression algorithm is a mapping algorithm that maps a specific expression to its nesting level.
For example, given the token list `(2 + 5) : (5 - 9 / (8 - 5))`, the generated result will be:
This approach ensures the correct operation priority is maintained.
## Calculator
The Calculator takes the parsed token list and calculates the final result. It uses a custom `X/O/Y` algorithm, also known as `X/OPERATION/Y`, where `X` and `Y` are numbers, and `O` is an operation. If `X` or `Y` cannot be obtained, they are taken as zero.
```
╭────────╮ ╭───────────╮ ╭────────╮
│ NUMBER │ │ OPERATION │ │ NUMBER │
╰────────╯ ╰───────────╯ ╰────────╯
╰───╮ │ ╭───╯
▼ ▼ ▼
X [+, -, *, /] Y
```---
# Syntax
The syntax of `Mate` is designed to be as simple and basic as possible. It follows the plain-text mathematics syntax with a few customizations. Here are some examples:
### Addition and Subtraction
`2 + 5` and `2 - 5` are valid syntaxes. (in `x y` where x and y could be `NUMBER` or `SUBEXP`).### Multiplication, Division, and Percentage
`4 * 2`, `4 / 2`, and `4 % 2` are valid syntaxes. (in `x y` where x and y could be `NUMBER` or `SUBEXP`). Also, `4(10 / 2)` or `4(2)` are valid syntaxes for multiplication.### Power
`4 ^ 2` is a valid syntax. (in `x y` where x and y could be `NUMBER` or `SUBEXP`). Continuous powers are also accepted: `4 ^ 2 ^ 3`, which will be automatically converted to `4 ^ (2 ^ 3)`.### Parentheses
`(2 * 5)` is a valid syntax. (in `x y` where x and y could be `NUMBER` or `SUBEXP`). Nested parentheses expressions are also accepted: `(2 * ((5 * 2) / (9 - 5)))`.### Absolute Values
`[2 - 12]` is a valid syntax. (in `x y` where x and y could be `NUMBER` or `SUBEXP`). Nested absolute-value expressions are also accepted: `[7 - 14] * [5 - 9 / [5 - 3]]`.