|
| 1 | +# Boolean Expression Parser <!-- omit in toc --> |
| 2 | + |
| 3 | +A simple boolean expression parser written in C#. It parses boolean expressions and prints out a truth table for each expression. |
| 4 | + |
| 5 | + |
| 6 | +## Contents <!-- omit in toc --> |
| 7 | + |
| 8 | +- [Building](#building) |
| 9 | +- [Usage](#usage) |
| 10 | +- [Expressions](#expressions) |
| 11 | +- [Variables](#variables) |
| 12 | +- [How it works](#how-it-works) |
| 13 | + - [1. Tokenisation](#1-tokenisation) |
| 14 | + - [2. Parsing](#2-parsing) |
| 15 | + - [3. AST](#3-ast) |
| 16 | + - [4. Evaluation](#4-evaluation) |
| 17 | +- [Example expressions](#example-expressions) |
| 18 | +- [Found an issue?](#found-an-issue) |
| 19 | + |
| 20 | + |
| 21 | +## Building |
| 22 | + |
| 23 | +To build the project, you'll need .NET 6 installed. You can then build the project with `dotnet build` or run it with `dotnet run`. Alternatively, you can open the project in Visual Studio or Visual Studio Code, the latter of which has config in the repo. |
| 24 | + |
| 25 | + |
| 26 | +## Usage |
| 27 | + |
| 28 | +Run `./BooleanExpressionParser <args>` from the command line. `args` is a list of boolean expressions to parse. If no arguments are given, the program will prompt you to enter them into the console. |
| 29 | + |
| 30 | + |
| 31 | +## Expressions |
| 32 | + |
| 33 | +Shown below is a list of supported operators. Each operator's aliases are listed in brackets. |
| 34 | + |
| 35 | + - AND (`&`, `.`) |
| 36 | + - OR (`|`, `+`) |
| 37 | + - NOT (`!`, `¬`) |
| 38 | + - XOR |
| 39 | + - NAND |
| 40 | + - NOR |
| 41 | + - XNOR |
| 42 | + |
| 43 | +Of course, you can also use brackets to group expressions. Every type of bracket can be used, which may help distinguish groupings: `()` `[]` `{}` `<>` |
| 44 | + |
| 45 | + |
| 46 | +## Variables |
| 47 | + |
| 48 | +Any characters in an expression which arent operators or brackets are considered variables. The parser will automatically generate a truth table for each variable. Variables can be several characters long, which allows for numbered variables (`A1`, `A_2`, etc.). |
| 49 | + |
| 50 | +The final truth table is ordered by the order in which the variables are encountered in the expression. For example, the expression `X | A & B` will have the variables ordered `X`, `A`, `B` in the truth table. |
| 51 | + |
| 52 | + |
| 53 | +## How it works |
| 54 | + |
| 55 | +### 1. Tokenisation |
| 56 | + - Input is split into tokens. These tokens are internal representations of the input. |
| 57 | + - Tokens are either operators, variables, or brackets. |
| 58 | + - For example, the input `A & ! B` would be tokenised into [`A`, `AND`, `NOT`, `B`]. |
| 59 | + |
| 60 | + |
| 61 | +### 2. Parsing |
| 62 | + - Tokens are parsed into prefix or Polish notation, using the (slightly modified) Shunting-yard algorithm. |
| 63 | + - Prefix notation removes the need for brackets, and makes it easier to evaluate the expression. In this notation, the operator is placed before the operands (rather than in between them). |
| 64 | + - Our tokenised list, [`A`, `AND`, `NOT`, `B`] would be parsed into [`A`, `B`, `NOT`, `AND`]. |
| 65 | + |
| 66 | + |
| 67 | +### 3. AST |
| 68 | + - The parsed tokens are then converted into an AST (Abstract Syntax Tree). This is so that the expression can be evaluated and easily traversed. |
| 69 | + - An AST consists of several nodes, each with children nodes (0, 1, or 2 depending on its type). Each node represents an operator or variable. |
| 70 | + - Our parsed list, [`A`, `B`, `NOT`, `AND`], would be converted into the following AST: |
| 71 | + - `AND` |
| 72 | + - `A` |
| 73 | + - `NOT` |
| 74 | + - `B` |
| 75 | + |
| 76 | + |
| 77 | +### 4. Evaluation |
| 78 | + - Finally, the AST is evaluated, and a truth table is printed out for the expression. |
| 79 | + - Evaluation simply traverses the AST and evaluates each node recursively, using the values of its children. |
| 80 | + - Each expression is evaluated using every possible set of inputs which is then collated into a truth table. |
| 81 | + |
| 82 | + |
| 83 | +## Example expressions |
| 84 | + |
| 85 | +- `A & B` |
| 86 | + - A simple AND gate |
| 87 | +- `A OR B` |
| 88 | + - A simple OR gate |
| 89 | +- `!S . D_0 + D_1 . S` |
| 90 | + - A 2-1 multiplexer |
| 91 | +- `(!S0 AND ¬S1 . D0) | (NOT<S0> . S1 . D1) + (S0 . {¬S1 & D2}) OR [S0 . S1 AND D3]` |
| 92 | + - A 4-1 multiplexer, using several aliases for operators and brackets |
| 93 | + |
| 94 | + |
| 95 | +## Found an issue? |
| 96 | + |
| 97 | +If you've found an issue, like an expression that casuses a crash or an incorrectly parsed expression, please open an issue on GitHub. Please include the expression that caused the issue, thank you! |
0 commit comments