# *************************************************************************** # * Copyright (c) 2020 Werner Mayer * # * * # * This file is part of the FreeCAD CAx development system. * # * * # * This program is free software; you can redistribute it and/or modify * # * it under the terms of the GNU Lesser General Public License (LGPL) * # * as published by the Free Software Foundation; either version 2 of * # * the License, or (at your option) any later version. * # * for detail see the LICENCE text file. * # * * # * 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 Library General Public License for more details. * # * * # * You should have received a copy of the GNU Library General Public * # * License along with this program; if not, write to the Free Software * # * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * # * USA * # * * # *************************************************************************** __title__ = "FEM Utilities" __author__ = "Werner Mayer" __url__ = "https://www.freecad.org" tokens = ( "NAME", "FLOAT", "INT", "PLUS", "MINUS", "TIMES", "DIVIDE", "EQUALS", "LPAREN", "RPAREN", "POWER", ) # Tokens t_PLUS = r"\+" t_MINUS = r"-" t_TIMES = r"\*" t_DIVIDE = r"/" t_EQUALS = r"=" t_LPAREN = r"\(" t_RPAREN = r"\)" t_POWER = r"\^" t_NAME = r"[a-zA-Z_][a-zA-Z0-9_]*" def t_FLOAT(t): r"\d+\.(\d+)?([eE][-+]?\d+)?" t.value = float(t.value) return t def t_INT(t): r"\d+" t.value = int(t.value) return t # Ignored characters t_ignore = " \t" def t_COMMENT(t): r"\#.*" pass def t_newline(t): r"\n+" t.lexer.lineno += t.value.count("\n") def t_error(t): print("Illegal character '%s'" % t.value[0]) t.lexer.skip(1) # Build the lexer import ply.lex as lex lex.lex() # Precedence rules for the arithmetic operators precedence = ( ("left", "PLUS", "MINUS"), ("left", "TIMES", "DIVIDE"), ("left", "POWER"), ("right", "UMINUS"), ) # dictionary of names (for storing variables) names = {} def p_statement_assign(p): "statement : NAME EQUALS expression" names[p[1]] = p[3] def p_statement_expr(p): "statement : expression" print(p[1]) def p_expression_binop(p): """expression : expression PLUS expression | expression MINUS expression | expression TIMES expression | expression DIVIDE expression | expression POWER expression""" if p[2] == "+": p[0] = p[1] + p[3] elif p[2] == "-": p[0] = p[1] - p[3] elif p[2] == "*": p[0] = p[1] * p[3] elif p[2] == "/": p[0] = p[1] / p[3] elif p[2] == "^": p[0] = p[1] ** p[3] def p_expression_uminus(p): "expression : MINUS expression %prec UMINUS" p[0] = -p[2] def p_expression_group(p): "expression : LPAREN expression RPAREN" p[0] = p[2] def p_expression_float(p): "expression : FLOAT" p[0] = p[1] def p_expression_int(p): "expression : INT" p[0] = p[1] def p_expression_name(p): "expression : NAME" try: p[0] = names[p[1]] except LookupError: print("Undefined name '%s'" % p[1]) p[0] = 0 def p_error(p): print("Syntax error at '%s'" % p.value) import ply.yacc as yacc yacc.yacc(debug=False, write_tables=False)