# Logical Expression Pest Parser Documentation
This crate parses strings of logical expression using `pest` crate, such as:
> (A AND B) OR (NOT (A XOR C))
> (A | C) & !B
> (X XOR Y) | A
It returns a truth table showing all input combinations with corresponding output results.
---
It can handle those logic operators:
| NOT | NOT, not, ! |
| AND | AND, and, & |
| NAND | NAND, nand, !& |
| OR | OR, or, \| |
| NOR | NOR, nor, !\| |
| XOR | XOR, xor, ^ |
| XNOR | XNOR, xnor, !^ |
After parsing, the resulting three is analyzed and converted into an Abstract Syntax Tree.
The next step is to evaluate the logical expression for all possible combinations of input values, allowing the
generation of a complete truth table.
For example, we have an expression:
> (A & B) | C
The resulting truth table is going to be
| 0 | 0 | 0 | 0 |
| 1 | 0 | 0 | 0 |
| 0 | 1 | 0 | 0 |
| 1 | 1 | 0 | 1 |
| 0 | 0 | 1 | 1 |
| 1 | 0 | 1 | 1 |
| 0 | 1 | 1 | 1 |
| 1 | 1 | 1 | 1 |
## Usage
```shell
cargo install logical-expression-parser
logical-expression-pest-parser.exe parse -f .\input.txt --ast
```
---
#### input.txt
In order to analyze multiple expressions, they must be defined in different lines and there must be an empty line at the end.
```text
A and !B or C
```
---
#### Output
```text
Processing file: .\input.txt
Expression 1
Input: "A and !B or C"
AST: Or(And(Identifier('A'), Not(Identifier('B'))), Identifier('C'))
| 0 | 0 | 0 | 0 |
| 1 | 0 | 0 | 1 |
| 0 | 1 | 0 | 0 |
| 1 | 1 | 0 | 0 |
| 0 | 0 | 1 | 1 |
| 1 | 0 | 1 | 1 |
| 0 | 1 | 1 | 1 |
| 1 | 1 | 1 | 1 |
Expression 2
AST: Nor(Identifier('X'), Identifier('Y'))
| 0 | 0 | 1 |
| 1 | 0 | 0 |
| 0 | 1 | 0 |
| 1 | 1 | 0 |
Expression 3
Input: "(K XOR L) AND M"
AST: And(Xor(Identifier('K'), Identifier('L')), Identifier('M'))
| 0 | 0 | 0 | 0 |
| 1 | 0 | 0 | 0 |
| 0 | 1 | 0 | 0 |
| 1 | 1 | 0 | 0 |
| 0 | 0 | 1 | 0 |
| 1 | 0 | 1 | 1 |
| 0 | 1 | 1 | 1 |
| 1 | 1 | 1 | 0 |
```
---
#### Use this command for help
```shell
logical-expression-pest-parser.exe help
```
## grammar.pest
The grammar is structured in such a way that the parser can determine priorities for boolean operators.
```text
WHITESPACE = _{ " " | "\t" }
not_operator = { "NOT" | "not" | "!" }
and_operator = { "AND" | "and" | "&" }
nand_operator = { "NAND" | "nand" | "!&" }
or_operator = { "OR" | "or" | "|" }
nor_operator = { "NOR" | "nor" | "!|" }
xor_operator = { "XOR" | "xor" | "^" }
xnor_operator = { "XNOR" | "xnor" | "!^" }
left_parenthesis = { "(" }
right_parenthesis = { ")" }
identifier = @{ ASCII_ALPHA_UPPER ~ !(ASCII_ALPHA_UPPER) }
term = { not_operator* ~ (identifier | left_parenthesis ~ expression ~ right_parenthesis) }
expression = { and_clause ~ ((or_operator | nor_operator) ~ and_clause)* }
NEWLINE = _{ "\n" | "\r\n" }
file = { SOI ~ expression ~ NEWLINE ~ (expression ~ NEWLINE)* ~ EOI }
```