Squashed 'third_party/pycrc/' content from commit cb91196b9
Change-Id: Iaed6f7d683e3c11395f10f0724f973363aad2cdb
git-subtree-dir: third_party/pycrc
git-subtree-split: cb91196b920d1f892c05941ed470c7a80cba7596
diff --git a/pycrc/expr.py b/pycrc/expr.py
new file mode 100644
index 0000000..a15742c
--- /dev/null
+++ b/pycrc/expr.py
@@ -0,0 +1,398 @@
+# pycrc -- parameterisable CRC calculation utility and C source code generator
+#
+# Copyright (c) 2017 Thomas Pircher <tehpeh-web@tty1.net>
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to
+# deal in the Software without restriction, including without limitation the
+# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+# sell copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+
+
+"""
+This modules simplifies an expression.
+
+ import pycrc.expr as exp
+
+ my_expr = exp.Xor('var', exp.Parenthesis(exp.And('0x700', 4)))
+ print('"{}" -> "{}"'.format(my_expr, my_expr.simplify()))
+"""
+
+
+def _classify(val):
+ """
+ Creates a Terminal object if the parameter is a string or an integer.
+ """
+ if type(val) is int:
+ return Terminal(val)
+ if type(val) is str:
+ if val.isdigit():
+ return Terminal(int(val), val)
+ if val[:2].lower() == '0x':
+ return Terminal(int(val, 16), val)
+ return Terminal(val)
+ return val
+
+
+class Expression(object):
+ """
+ Base class for all expressions.
+ """
+ def is_int(self, val = None):
+ return False
+
+
+class Terminal(Expression):
+ """
+ A terminal object.
+ """
+ def __init__(self, val, pretty = None):
+ """
+ Construct a Terminal.
+ The val variable is usually a string or an integer. Integers may also
+ be passed as strings. The pretty-printer will use the string when
+ formatting the expression.
+ """
+ self.val = val
+ self.pretty = pretty
+
+ def __str__(self):
+ """
+ Return the string expression of this object.
+ """
+ if self.pretty is None:
+ return str(self.val)
+ return self.pretty
+
+ def simplify(self):
+ """
+ Return a simplified version of this sub-expression.
+ """
+ return self
+
+ def is_int(self, val = None):
+ """
+ Return True if the value of this Terminal is an integer.
+ """
+ if type(self.val) is int:
+ return val is None or self.val == val
+ return False
+
+
+class FunctionCall(Expression):
+ """
+ Represent a function call
+ """
+ def __init__(self, name, args):
+ """
+ Construct a function call object.
+ """
+ self.name = _classify(name)
+ self.args = [_classify(arg) for arg in args]
+
+ def __str__(self):
+ """
+ Return the string expression of this object.
+ """
+ return str(self.name) + '(' + ', '.join([str(arg) for arg in self.args]) + ')'
+
+ def simplify(self):
+ """
+ Return a simplified version of this sub-expression.
+ """
+ args = [arg.simplify() for arg in self.args]
+ return FunctionCall(self.name, args)
+
+
+class Parenthesis(Expression):
+ """
+ Represent a pair of round brackets.
+ """
+ def __init__(self, val):
+ """
+ Construct a parenthesis object.
+ """
+ self.val = _classify(val)
+
+ def simplify(self):
+ """
+ Return a simplified version of this sub-expression.
+ """
+ val = self.val.simplify()
+ if type(val) is Terminal:
+ return val
+ return Parenthesis(val)
+
+ def __str__(self):
+ """
+ Return the string expression of this object.
+ """
+ return '(' + str(self.val) + ')'
+
+
+class Add(Expression):
+ """
+ Represent an addition of operands.
+ """
+ def __init__(self, lhs, rhs):
+ """
+ Construct an addition object.
+ """
+ self.lhs = _classify(lhs)
+ self.rhs = _classify(rhs)
+
+ def simplify(self):
+ """
+ Return a simplified version of this sub-expression.
+ """
+ lhs = self.lhs.simplify()
+ rhs = self.rhs.simplify()
+ if lhs.is_int() and rhs.is_int():
+ return Terminal(lhs.val + rhs.val)
+ if lhs.is_int(0):
+ return rhs
+ if rhs.is_int(0):
+ return lhs
+ return Add(lhs, rhs)
+
+ def __str__(self):
+ """
+ Return the string expression of this object.
+ """
+ return str(self.lhs) + ' + ' + str(self.rhs)
+
+
+class Sub(Expression):
+ """
+ Represent a subtraction of operands.
+ """
+ def __init__(self, lhs, rhs):
+ """
+ Construct subtraction object.
+ """
+ self.lhs = _classify(lhs)
+ self.rhs = _classify(rhs)
+
+ def simplify(self):
+ """
+ Return a simplified version of this sub-expression.
+ """
+ lhs = self.lhs.simplify()
+ rhs = self.rhs.simplify()
+ if lhs.is_int() and rhs.is_int():
+ return Terminal(lhs.val - rhs.val)
+ if lhs.is_int(0):
+ return rhs
+ if rhs.is_int(0):
+ return lhs
+ return Sub(lhs, rhs)
+
+ def __str__(self):
+ """
+ Return the string expression of this object.
+ """
+ return str(self.lhs) + ' - ' + str(self.rhs)
+
+
+class Mul(Expression):
+ """
+ Represent the multiplication of operands.
+ """
+ def __init__(self, lhs, rhs):
+ """
+ Construct a multiplication object.
+ """
+ self.lhs = _classify(lhs)
+ self.rhs = _classify(rhs)
+
+ def simplify(self):
+ """
+ Return a simplified version of this sub-expression.
+ """
+ lhs = self.lhs.simplify()
+ rhs = self.rhs.simplify()
+ if lhs.is_int() and rhs.is_int():
+ return Terminal(lhs.val * rhs.val)
+ if lhs.is_int(0) or rhs.is_int(0):
+ return Terminal(0)
+ if lhs.is_int(1):
+ return rhs
+ if rhs.is_int(1):
+ return lhs
+ return Mul(lhs, rhs)
+
+ def __str__(self):
+ """
+ Return the string expression of this object.
+ """
+ return str(self.lhs) + ' * ' + str(self.rhs)
+
+
+class Shl(Expression):
+ """
+ Shift left operation.
+ """
+ def __init__(self, lhs, rhs):
+ """
+ Construct a shift left object.
+ """
+ self.lhs = _classify(lhs)
+ self.rhs = _classify(rhs)
+
+ def simplify(self):
+ """
+ Return a simplified version of this sub-expression.
+ """
+ lhs = self.lhs.simplify()
+ rhs = self.rhs.simplify()
+ if lhs.is_int() and rhs.is_int():
+ return Terminal(lhs.val << rhs.val)
+ if lhs.is_int(0):
+ return Terminal(0)
+ if rhs.is_int(0):
+ return lhs
+ return Shl(lhs, rhs)
+
+ def __str__(self):
+ """
+ Return the string expression of this object.
+ """
+ return str(self.lhs) + ' << ' + str(self.rhs)
+
+
+class Shr(Expression):
+ """
+ Shift right operation.
+ """
+ def __init__(self, lhs, rhs):
+ """
+ Construct a shift right object.
+ """
+ self.lhs = _classify(lhs)
+ self.rhs = _classify(rhs)
+
+ def simplify(self):
+ """
+ Return a simplified version of this sub-expression.
+ """
+ lhs = self.lhs.simplify()
+ rhs = self.rhs.simplify()
+ if lhs.is_int() and rhs.is_int():
+ return Terminal(lhs.val >> rhs.val)
+ if lhs.is_int(0):
+ return Terminal(0)
+ if rhs.is_int(0):
+ return lhs
+ return Shr(lhs, rhs)
+
+ def __str__(self):
+ """
+ Return the string expression of this object.
+ """
+ return str(self.lhs) + ' >> ' + str(self.rhs)
+
+
+class Or(Expression):
+ """
+ Logical or operation.
+ """
+ def __init__(self, lhs, rhs):
+ """
+ Construct a logical and object.
+ """
+ self.lhs = _classify(lhs)
+ self.rhs = _classify(rhs)
+
+ def simplify(self):
+ """
+ Return a simplified version of this sub-expression.
+ """
+ lhs = self.lhs.simplify()
+ rhs = self.rhs.simplify()
+ if lhs.is_int() and rhs.is_int():
+ return Terminal(lhs.val | rhs.val)
+ if lhs.is_int(0):
+ return rhs
+ if rhs.is_int(0):
+ return lhs
+ return Or(lhs, rhs)
+
+ def __str__(self):
+ """
+ Return the string expression of this object.
+ """
+ return str(self.lhs) + ' | ' + str(self.rhs)
+
+
+class And(Expression):
+ """
+ Logical and operation.
+ """
+ def __init__(self, lhs, rhs):
+ """
+ Construct a logical and object.
+ """
+ self.lhs = _classify(lhs)
+ self.rhs = _classify(rhs)
+
+ def simplify(self):
+ """
+ Return a simplified version of this sub-expression.
+ """
+ lhs = self.lhs.simplify()
+ rhs = self.rhs.simplify()
+ if lhs.is_int() and rhs.is_int():
+ return Terminal(lhs.val & rhs.val)
+ if lhs.is_int(0) or rhs.is_int(0):
+ return Terminal(0)
+ return And(lhs, rhs)
+
+ def __str__(self):
+ """
+ Return the string expression of this object.
+ """
+ return str(self.lhs) + ' & ' + str(self.rhs)
+
+
+class Xor(Expression):
+ """
+ Logical xor operation.
+ """
+ def __init__(self, lhs, rhs):
+ """
+ Construct a logical xor object.
+ """
+ self.lhs = _classify(lhs)
+ self.rhs = _classify(rhs)
+
+ def simplify(self):
+ """
+ Return a simplified version of this sub-expression.
+ """
+ lhs = self.lhs.simplify()
+ rhs = self.rhs.simplify()
+ if lhs.is_int() and rhs.is_int():
+ return Terminal(lhs.val ^ rhs.val)
+ if lhs.is_int(0):
+ return rhs
+ if rhs.is_int(0):
+ return lhs
+ return Xor(lhs, rhs)
+
+ def __str__(self):
+ """
+ Return the string expression of this object.
+ """
+ return str(self.lhs) + ' ^ ' + str(self.rhs)