--- /dev/null
+__pycache__
+/element.py
+/lex_yy.py
+/t_def.py
+/y_tab.py
--- /dev/null
+all: element.py lex_yy.py t_def.py y_tab.py
+
+element.py:
+ pitree --install-element
+
+lex_yy.py: cal_py.l
+ pilex --element --groups --python $<
+
+t_def.py: cal_py.t
+ pitree --python $<
+
+y_tab.py: cal_py.y
+ piyacc --element --python $<
+
+clean:
+ rm -f element.py lex_yy.py t_def.py y_tab.py
--- /dev/null
+#!/usr/bin/env python3
+
+# Copyright (C) 2018 Nick Downing <nick@ndcode.org>
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# This program is free software; you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation; version 2.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 51
+# Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+
+import t_def
+import element
+import sys
+import y_tab
+
+sys.stdout.write('Enter the expression: ')
+sys.stdout.flush()
+_ast = y_tab.yyparse(t_def.AST)
+element.serialize(_ast, sys.stdout)
+#element.serialize(_ast, 'a.xml', 'utf-8')
+#_ast = element.deserialize('a.xml', t_def.factory, 'utf-8')
+for i in _ast.children:
+ sys.stdout.write('{0:g}\n'.format(i.eval()))
--- /dev/null
+/*
+ * Copyright (C) 2018 Nick Downing <nick@ndcode.org>
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; version 2.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+%{
+ import t_def
+ import element
+ import y_tab
+%}
+
+DIGIT (?E{t_def.AST.Num.Mantissa}[0-9]+)\.?|(?E{t_def.AST.Num.Mantissa}[0-9]*)\.(?E{t_def.AST.Num.Fraction}[0-9]+)
+
+%%
+
+[ ]
+(?E{t_def.AST.Num}{DIGIT}) {
+ y_tab.yylval = float(yytext)
+ return y_tab.NUM
+}
+\n|. {
+ return ord(yytext[0])
+}
--- /dev/null
+/*
+ * Copyright (C) 2019 Nick Downing <nick@ndcode.org>
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; version 2.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+%{
+ import element
+%}
+
+%%
+
+class Text;
+class AST {
+ class Expr;
+ class Num: Expr {
+ class Mantissa: Text;
+ class Fraction: Text;
+ };
+ class Add;
+ class Sub;
+ class Mul;
+ class Div;
+ class Neg;
+};
+
+%%
+
+# Copyright (C) 2018 Nick Downing <nick@ndcode.org>
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# This program is free software; you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation; version 2.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+# details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 51
+# Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+
+def factory(tag, *args, **kwargs):
+ return tag_to_class[tag](*args, **kwargs)
+
+@method(Text)
+def get_text(self):
+ return self.text[0]
+del get_text
+
+@method(AST.Expr)
+def eval(self):
+ raise NotImplementedException()
+@method(AST.Num)
+def eval(self):
+ mantissa = self.children[0].get_text()
+ fraction = self.children[1].get_text() if len(self.children) >= 2 else ''
+ return int(mantissa + fraction) * 10 ** -len(fraction)
+@method(AST.Add)
+def eval(self):
+ return self.children[0].eval() + self.children[1].eval()
+@method(AST.Sub)
+def eval(self):
+ return self.children[0].eval() - self.children[1].eval()
+@method(AST.Mul)
+def eval(self):
+ return self.children[0].eval() * self.children[1].eval()
+@method(AST.Div)
+def eval(self):
+ return self.children[0].eval() / self.children[1].eval()
+@method(AST.Neg)
+def eval(self):
+ return -self.children[0].eval()
+del eval
--- /dev/null
+/*
+ * Copyright (C) 2018 Nick Downing <nick@ndcode.org>
+ * SPDX-License-Identifier: GPL-2.0-only
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; version 2.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+%{
+ import t_def
+ import sys
+%}
+
+%locations
+
+%token NUM
+
+%left '+' '-'
+%left '*' '/'
+%right UMINUS
+
+%%
+
+S : S E '\n' {
+ sys.stdout.write('Answer: {0:g}\nEnter:\n'.format($2))
+ }
+ | S '\n'
+ |
+ | error '\n' {
+ yyerror('Error: Enter once more...\n')
+ yyerrok()
+}
+ ;
+E : %space (?E{t_def.AST.Add}E '+' E) {
+ $$ = $1 + $3
+ }
+ | %space (?E{t_def.AST.Sub}E '-' E) {
+ $$ = $1 - $3
+ }
+ | %space (?E{t_def.AST.Mul}E '*' E) {
+ $$ = $1 * $3
+ }
+ | %space (?E{t_def.AST.Div}E '/' E) {
+ $$ = $1 / $3
+ }
+ | '(' E ')' {
+ $$ = $2
+ }
+ | %space (?E{t_def.AST.Neg}'-' E) %prec UMINUS {
+ $$ = -$2
+ }
+ | NUM
+ ;
+%%
+
+def yyerror(s):
+ sys.stdout.write('{0:s}\n'.format(s))
+ sys.exit(1)