/* $Id$ */ /* * Copyright (C) 2006 Richard Braun * * 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; either version 2 of the License, or * (at your option) any later version. * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #ifndef _MTXEXPRESSION_H #define _MTXEXPRESSION_H #include #include #include "mtx.h" #include "mtxvalue.h" #include "mtxsymbol.h" #include "mtxlanguage.h" #define MTXEXPRESSION_OPERATOR_NULL \ {NULL, MTXEXPRESSION_FUNCTION_NULL, MTXEXPRESSION_ASSOCIATIVITY_NULL} /** * \enum mtx_function_id * \brief ID of a function/operator. E.g. assignment, addition. */ enum mtx_function_id { MTXEXPRESSION_FUNCTION_NULL, MTXEXPRESSION_FUNCTION_ASSIGNMENT, MTXEXPRESSION_FUNCTION_ADDITION, MTXEXPRESSION_FUNCTION_ADD_ASSIGN, MTXEXPRESSION_FUNCTION_SUBTRACTION, MTXEXPRESSION_FUNCTION_SUBTRACT_ASSIGN, MTXEXPRESSION_FUNCTION_MULTIPLY, MTXEXPRESSION_FUNCTION_MULTIPLY_ASSIGN, MTXEXPRESSION_FUNCTION_DIVIDE, MTXEXPRESSION_FUNCTION_DIVIDE_ASSIGN, MTXEXPRESSION_FUNCTION_DETERMINANT, MTXEXPRESSION_FUNCTION_INVERSE, MTXEXPRESSION_FUNCTION_TRANSPOSE, MTXEXPRESSION_FUNCTION_AUGMENT, MTXEXPRESSION_FUNCTION_LUDECOMPOSITION }; /** * \enum mtx_operator_associativity * \brief Associativity of an operator. */ enum mtx_operator_associativity { MTXEXPRESSION_ASSOCIATIVITY_NULL, MTXEXPRESSION_RIGHT_TO_LEFT, MTXEXPRESSION_LEFT_TO_RIGHT }; /** * A function. */ struct mtx_function { /** * Function string as entered by the user. */ const char *str; /** * ID of the function. */ enum mtx_function_id id; /** * Number of arguments. */ size_t argc; }; /** * An operator. * * XXX Inheritence from struct mtx_function seems to cause trouble. Why ? */ struct mtx_operator { /** * Operator string as entered by the user. */ const char *str; /** * ID of the operator. */ enum mtx_function_id id; /** * Associativity of the operator. */ enum mtx_operator_associativity associativity; }; /** * An expression. * * All language expressions that are not atomic symbols (e.g. "a" or "2") * are expressions which consist of a function/operator and one or more * arguments. These arguments are in turn MtxExpression or MtxSymbol * objects. MtxExpression objects are always nodes in the tree of symbols, * whereas MtxSymbol objects are always leaves. */ class MtxExpression: public MtxSymbol { private: /** * Function/operator compiled in this expression. */ enum mtx_function_id function; /** * Vector of arguments. */ std::vector expressions; /** * True if silent. * * A silent expression is an expression ended with the ';' character. * Engine users should not display silent expressions. This property * is propagated to underlying expressions and symbols. * * @see isSilent() */ bool silent; /** * Find an operator in the vector of lexical elements. * * This method uses the \a operators array to look for operators by * order of precedence. * * @param lexical_elements vector of strings in which to look for an * operator * @param str operator string as entered by the user to look for * @see operators * @see rfindOperator() */ mtx_expression_t::iterator findOperator(mtx_expression_t &lexical_elements, const char *str); /** * Find an operator in the vector of lexical elements in reverse order. * * @see findOperator(). */ mtx_expression_t::reverse_iterator rfindOperator(mtx_expression_t &lexical_elements, const char *str); /** * Free the pointers stored in the given vector of symbols. * * Mainly used after parsing a matrix or function arguments is done or * failed. */ void freeSymbols(std::vector &symbols) const; /** * Parse the given lexical elements and extract symbols and expressions * from it to create the list of elements that will be used to create a * matrix. An exception is thrown if the syntax doesn't comply with * the matrix creation syntax. * * @param lexical_elements vector of strings to parse * @param symbols vector of symbols/expressions updated by this method * @param rows number of rows found * @param columns number of columns found */ void parseMatrix(const mtx_expression_t &lexical_elements, std::vector &symbols, size_t &rows, size_t &columns) const; /** * Parse the given lexical elements and extract symbols and expressions * from it to create the list of arguments of a function. An exception is * thrown if the syntax is invalid. * * @param lexical_elements vector of strings to parse * @param symbols vector of symbols/expressions updated by this method */ void parseArguments(const mtx_expression_t &lexical_elements, std::vector &symbols) const; /** * Array of builtin functions. */ static struct mtx_function functions[]; /** * Multidimensional array of supported operators. * * Each line of the array indicates a level of precedence. Lines must * be ordered in reverse order of precedence, e.g. = has low precedence, * so it is placed in first line. Operators of same precedence must have * the same associativity (this is never checked). * * XXX There are at most 5 operators for the same precedence (+ a null * entry to indicate end of list), so the second dimension is 6. * * @see isOperator() */ static struct mtx_operator operators[][6]; /** * Return true if the given string matches an operator. * * @see operators() */ static bool isOperator(const std::string &str); /** * Return true if the given string is a valid variable name. * * A valid variable name consist of [a-zA-Z0-9_] characters only, * and cannot begin with a digit. */ static bool isVariableName(const std::string &str); public: /** * Create an expression from a set of lexical elements. * * @param language address of the MtxLanguage object used to get/set * variables * @param lexical_elements vector of lexical elements * @param silent see silent * @see silent */ MtxExpression(MtxLanguage *language, mtx_expression_t &lexical_elements, bool silent = false); virtual ~MtxExpression(); virtual MtxSymbol getSymbol(bool create = false, bool fail_if_special = true) const; virtual std::string getName() const; virtual MtxValue * getValue() const; virtual std::string toString() const; /** * Return the silent member. * * As MtxExpression objects are always nodes, and there is always a node * on top of a leaf, it is not necessary to propagate the silent property * to underlying objects. When the engine calls isSilent(), it always get * a return value from the first node it is calling the function on. * That's why MtxSymbol objects don't have a silent property. */ virtual bool isSilent() const; }; #endif /* _MTXEXPRESSION_H */