1
0
mirror of https://github.com/DanilaFe/abacus synced 2024-12-22 07:20:09 -08:00

Write about the architecture of Abacus

Danila Fedorin 2017-08-18 17:46:20 -07:00
parent bf3593faf6
commit 011695ca26

29
Architecture.md Normal file

@ -0,0 +1,29 @@
The goal in designing Abacus was to separate core math logic from UI, and maintain a high degree of separation in the core itself. This would allow for parts of Abacus to be interchanged, while not affecting unrelated code. Contributors are strongly encouraged to maintain this separation of components, especially between modules.
## Abacus Core
The "core" math code, contained in the `core` Gradle module, is the main part of Abacus - the calculating part. It defines parsing, tokenizing, and the `NumberInterface`. It is essentially responsible for converting input text into a tree and reducing that tree into a single number. However, the core itself consists of several pieces.
### Tokenizer
The `Tokenizer` interface defines a class that converts a single string into a list of tokens. As a theoretical example, given the string "Hello, world!", it would produce the tokens `Hello`, `,`, ` `, `world` and `!`. By doing so, it groups important letters and characters together, and separates them from unrelated text. This makes it much easier to parse.
### Parser
The `Parser` interface defines a class that can convert some list of tokens, of some type, into a tree. This deduces the grammatical structure of the text. This step is independent of the input string, and only depends on the tokens given to it. The tokens given to the parser tend to be produced by a Tokenizer.
### TreeBuilder
There's a third class inside of the `parsing` package, called `TreeBuilder`. The tree builder serves as a kind of glue between the Tokenizer and Parser, and mostly serves to avoid generics. Let's take a look at an example:
```Java
// A tokenizer instance that produces a list of tokens of some type from a string.
SomeTokenizer<SomeToken> tokenizer = ...;
// A parser instance that produces a tree out of a list of tokens of the same type.
SomeParser<SomeToken> parser = ...;
String inputString = ...;
TreeNode producedTree = parser.constructTree(tokenizer.tokenizeString(inputString));
```
Note that the type of SomeToken is never actually used outside the Tokenizer and Parser. Once we have created a Tokenizer and Parser, there's no need to keep their type information around, as long as they match. For this purpose, a TreeBuilder takes a Tokenizer and Parser of the same type, and combines them. TreeBuilder itself doesn't provide any generic methods, and can be used without any generic arguments once it's been created. This way, although the tokenizer and parser are separate entities, they are combined together to perform a single task, and don't complicate matters in surrounding code.
### Reducer
The reducer is the last step in evaluating a mathematical expression. A reducer walks a tree recursively, simplifying each child into a value, then simplifying a parent and its already simplified children into a value, etc, until it reaches the of the tree. This is used by the NumberReducer, which reduces TreeNodes into a single NumberInterface, the result of the expression. This is also separate from tokenizing and parsing, but depends on the Abacus main class for creating instances of NumberInterface.
## FX
The `fx` module is a UI built around the Abacus core. It provides little functionality beyond interacting with the user and saving / loading configuration from disk.