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
|
=================
Development Guide
=================
This document gives an overview of the code in `boolean.py`, explaining the
layout and design decisions and some difficult algorithms. All used definitions
and laws are stated in :doc:`concepts`.
.. contents::
:depth: 2
:backlinks: top
Testing
-------
Test `boolean.py` with your current Python environment:
.. code-block:: shell
python setup.py test
Test with all of the supported Python environments using `tox`:
.. code-block:: shell
pip install -r requirements-dev.txt
tox
If `tox` throws `InterpreterNotFound`, limit it to python interpreters that are actually installed on your machine:
.. code-block:: shell
tox -e py36
Classes Hierarchy
-----------------
..
boolean.boolean.BooleanAlgebra
boolean.boolean.Expression
boolean.boolean.BaseElement
boolean.boolean._TRUE
boolean.boolean._FALSE
boolean.boolean.Symbol
boolean.boolean.Function
boolean.boolean.NOT
boolean.boolean.DualBase
boolean.boolean.AND
boolean.boolean.OR
Expression
^^^^^^^^^^
..
.. autoclass:: boolean.boolean.Expression
Symbol
^^^^^^
..
.. autoclass:: boolean.boolean.Symbol
Function
^^^^^^^^
..
.. autoclass:: boolean.boolean.Function
NOT
^^^
..
.. autoclass:: boolean.boolean.NOT
AND
^^^
..
.. autoclass:: boolean.boolean.AND
OR
^^
..
.. autoclass:: boolean.boolean.OR
.. _class-creation:
Class creation
--------------
Except for BooleanAlgebra and Symbol, no other classes are is designed to be instantiated directly.
Instead you should create a BooleanAlgebra instance, then use BooleanAlgebra.symbol,
BooleanAlgebra.NOT, BooleanAlgebra.AND, BooleanAlgebra.OR BooleanAlgebra.TRUE and BooleanAlgebra.FALSE
to compose your expressions in the context of this algebra.
.. _class-initialization:
Class initialization
--------------------
In this section for all classes is stated which arguments they will accept
and how these arguments are processed before they are used.
Symbol
^^^^^^
& :obj:`obj` (Named Symbol)
Ordering
--------
As far as possible every expression should always be printed in exactly the
same way. Therefore a strict ordering between different boolean classes and
between instances of same classes is needed. This is defined primarily by the
sort_order attribute.
Class ordering
^^^^^^^^^^^^^^
:class:`BaseElement` < :class:`Symbol` < :class:`AND` < :class:`OR`
:class:`NOT` is an exception in this scheme. It will be sorted based on the sort order of its
argument.
Class ordering is implemented by an attribute :attr:`sort_order` in all
relevant classes. It holds an integer that will be used for comparison
if it is available in both compared objects.
For Symbols, the attached `obj` object is used instead.
+----------------------+-----------+
| :class:`Class` | sort_order|
+======================+===========+
| :class:`BaseElement` | 0 |
+----------------------+-----------+
| :class:`Symbol` | 5 |
+----------------------+-----------+
| :class:`AND` | 10 |
+----------------------+-----------+
| :class:`OR` | 25 |
+----------------------+-----------+
Instance ordering
^^^^^^^^^^^^^^^^^
:class:`BaseElement`
:obj:`FALSE` < :obj:`TRUE`
:class:`Symbol`
:obj:`Symbol.obj` o :obj:`Symbol.obj`
:class:`NOT`
if :obj:`NOT.args[0]` == :obj:`other` ---> :obj:`other` < :obj:`NOT`
:obj:`NOT` o :obj:`other` ---> :obj:`NOT.args[0]` o :obj:`other`
:class:`AND`
:obj:`AND` o :obj:`AND` ---> :obj:`AND.args[0]` o :obj:`AND.args[0]`
if undecided: repeat for all args
if undecided: len(:obj:`AND.args`) o len(:obj:`AND.args`)
if undecided: return :obj:`AND` < :obj:`AND`
:class:`OR`
:obj:`OR` o :obj:`OR` ---> :obj:`OR.args[0]` o :obj:`OR.args[0]`
if undecided: repeat for all args
if undecided: len(:obj:`OR.args`) o len(:obj:`OR.args`)
if undecided: return :obj:`OR` < :obj:`OR`
Parsing
-------
Parsing is done in two steps:
A tokenizer iterates over string characters assigning a TOKEN_TYPE to each token.
The parser receives this stream of token types and strings and creates
adequate boolean objects from a parse tree.
|