/*************************************************************************** expression.cpp - Expression parser ------------------- copyright : (C) 2004 Michal Rudolf ***************************************************************************/ /*************************************************************************** * * * 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. * * * ***************************************************************************/ #include "expression.h" #include Expression::Expression() : m_start(0), m_error(false) { } Expression::Expression(const TQString& expr) { *this = expr; } Expression& Expression::operator=(const TQString& s) { m_start = 0; m_error = false; m_parts.clear(); const TQString single = "()<>!+-/*%"; int start = 0; int len = s.length(); int i = 0; while (i < len) { if (((s[i] == '>' || s[i] == '<' || s[i] == '=' || s[i] == '!') && s[i + 1] == '=') || (s[i] == '<' && s[i + 1] == '>')) { m_parts.append(TQVariant(s.mid(i, 2))); i += 2; } else if (s[i].isDigit()) { i++; bool decimal = false; while (i < len && (s[i].isDigit() || (!decimal && s[i] == TQChar('.')))) { if (s[i] == '.') decimal = true; i++; } if (decimal) m_parts.append(TQVariant(s.mid(start, i - start).toDouble())); else m_parts.append(TQVariant(s.mid(start, i - start).toInt())); } else if (single.contains(s[i])) m_parts.append(TQVariant(TQString(s[i++]))); else if (s[i] == '\"') { i++; while (i < len && s[i] != '\"') i++; m_parts.append(TQVariant(s.mid(start + 1, i - start - 1))); i++; } else if (s[i].isSpace()) while (i < len && s[i].isSpace()) i++; else { while (i < len && !s[i].isSpace()) i++; TQString keyword = s.mid(start, i - start); if (keyword == "true") m_parts.append(TQVariant(true)); else if (keyword == "false") m_parts.append(TQVariant(false)); else /* will be deprecated soon */ m_parts.append(TQVariant(keyword)); } start = i; } return *this; } TQString Expression::next() const { if (m_start < m_parts.count()) return m_parts[m_start].toString(); else return TQString(); } bool Expression::validate() { if (m_start >= m_parts.count()) setError(); return !m_error; } Expression::Type Expression::commonType(const TQVariant v1, const TQVariant v2) const { if (v1.type() == TQVariant::String || v2.type() == TQVariant::String) return TypeString; else if (v1.type() == TQVariant::Double || v2.type() == TQVariant::Double) return TypeDouble; return TypeInt; } static int expression_compareDouble(const double A, const double B) { return A=" || cmp == ">" || cmp == "<>" || cmp == "!=") { m_start++; TQVariant value2 = parseAdd(); if (cmp == "<") return compare(value, value2) < 0; else if (cmp == "<=") return compare(value, value2) <= 0; else if (cmp == "==") return compare(value, value2) == 0; else if (cmp == ">=") return compare(value, value2) >= 0; else if (cmp == "<>" || cmp == "!=") return compare(value, value2) != 0; else return compare(value, value2) > 0; } return value; } TQVariant Expression::parseNot() { if (next() == "!" || next() == "not") { m_start++; return !parseComparison().asBool(); } else return parseComparison(); } TQVariant Expression::parseAnd() { if (!validate()) return -1; TQVariant value = parseNot(); while (next() == "&&" || next() == "and") { m_start++; value = parseNot().toBool() && value.toBool(); } return value; } TQVariant Expression::parseOr() { if (!validate()) return -1; TQVariant value = parseAnd(); while (next() == "||" || next() == "or") { m_start++; value = parseAnd().toBool() || value.toBool(); } return value; } TQVariant Expression::parse() { return parseOr(); } TQVariant Expression::value(bool* valid) { m_start = 0; m_error = false; TQVariant val = parse(); if (valid) *valid = !m_error && m_start == m_parts.count(); return val; } TQVariant Expression::value(const TQString& s, bool* valid) { *this = s; return value(valid); } bool Expression::isTrue(const TQString& s, bool* valid) { TQVariant v = value(s, valid); return (v.type() == TQVariant::String && !v.toString().isNull()) || (v.type() != TQVariant::String && v.toInt() != 0); }