--- a
+++ b/src/query/wasaparseaux.cpp
@@ -0,0 +1,236 @@
+/* Copyright (C) 2006 J.F.Dockes
+ * 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.
+ */
+#include "autoconfig.h"
+
+#include <iostream>
+
+#include "wasatorcl.h"
+#include "wasaparserdriver.h"
+#include "searchdata.h"
+#include "debuglog.h"
+
+#define YYDEBUG 1
+
+// bison-generated file
+#include "wasaparse.h"
+
+using namespace std;
+using namespace Rcl;
+
+
+void
+yy::parser::error (const location_type& l, const std::string& m)
+{
+ d->setreason(m);
+}
+
+
+SearchData *wasaStringToRcl(const RclConfig *config,
+ const std::string& stemlang,
+ const std::string& query, string &reason,
+ const std::string& autosuffs)
+{
+ WasaParserDriver d(config, stemlang, autosuffs);
+ SearchData *sd = d.parse(query);
+ if (!sd)
+ reason = d.getreason();
+ return sd;
+}
+
+SearchData *WasaParserDriver::parse(const std::string& in)
+{
+ m_input = in;
+ m_index = 0;
+ delete m_result;
+ m_result = 0;
+ m_returns = stack<int>();
+
+ yy::parser parser(this);
+ parser.set_debug_level(0);
+
+ if (parser.parse() != 0) {
+ delete m_result;
+ m_result = 0;
+ }
+
+ return m_result;
+}
+
+int WasaParserDriver::GETCHAR()
+{
+ if (!m_returns.empty()) {
+ int c = m_returns.top();
+ m_returns.pop();
+ return c;
+ }
+ if (m_index < m_input.size())
+ return m_input[m_index++];
+ return 0;
+}
+void WasaParserDriver::UNGETCHAR(int c)
+{
+ m_returns.push(c);
+}
+
+// Add clause to query, handling special pseudo-clauses for size/date
+// etc. (mostly determined on field name).
+bool WasaParserDriver::addClause(SearchData *sd,
+ SearchDataClauseSimple* cl)
+{
+ if (cl->getfield().empty()) {
+ // Simple clause with empty field spec.
+ // Possibly change terms found in the "autosuffs" list into "ext"
+ // field queries
+ if (!m_autosuffs.empty()) {
+ vector<string> asfv;
+ if (stringToStrings(m_autosuffs, asfv)) {
+ if (find_if(asfv.begin(), asfv.end(),
+ StringIcmpPred(cl->gettext())) != asfv.end()) {
+ cl->setfield("ext");
+ cl->addModifier(SearchDataClause::SDCM_NOSTEMMING);
+ }
+ }
+ }
+ return sd->addClause(cl);
+ }
+
+
+ const string& fld = cl->getfield();
+
+ // MIME types and categories
+ if (!stringicmp("mime", fld) ||!stringicmp("format", fld)) {
+ if (cl->getexclude()) {
+ sd->remFiletype(cl->gettext());
+ } else {
+ sd->addFiletype(cl->gettext());
+ }
+ delete cl;
+ return true;
+ }
+
+ if (!stringicmp("rclcat", fld) || !stringicmp("type", fld)) {
+ vector<string> mtypes;
+ if (m_config && m_config->getMimeCatTypes(cl->gettext(), mtypes)) {
+ for (vector<string>::iterator mit = mtypes.begin();
+ mit != mtypes.end(); mit++) {
+ if (cl->getexclude()) {
+ sd->remFiletype(*mit);
+ } else {
+ sd->addFiletype(*mit);
+ }
+ }
+ }
+ delete cl;
+ return true;
+ }
+
+ // Handle "date" spec
+ if (!stringicmp("date", fld)) {
+ DateInterval di;
+ if (!parsedateinterval(cl->gettext(), &di)) {
+ LOGERR(("Bad date interval format: %s\n",
+ cl->gettext().c_str()));
+ m_reason = "Bad date interval format";
+ delete cl;
+ return false;
+ }
+ LOGDEB(("addClause:: date span: %d-%d-%d/%d-%d-%d\n",
+ di.y1,di.m1,di.d1, di.y2,di.m2,di.d2));
+ sd->setDateSpan(&di);
+ delete cl;
+ return true;
+ }
+
+ // Handle "size" spec
+ if (!stringicmp("size", fld)) {
+ char *cp;
+ size_t size = strtoll(cl->gettext().c_str(), &cp, 10);
+ if (*cp != 0) {
+ switch (*cp) {
+ case 'k': case 'K': size *= 1E3;break;
+ case 'm': case 'M': size *= 1E6;break;
+ case 'g': case 'G': size *= 1E9;break;
+ case 't': case 'T': size *= 1E12;break;
+ default:
+ m_reason = string("Bad multiplier suffix: ") + *cp;
+ delete cl;
+ return false;
+ }
+ }
+
+ SearchDataClause::Relation rel = cl->getrel();
+
+ delete cl;
+
+ switch (rel) {
+ case SearchDataClause::REL_EQUALS:
+ sd->setMaxSize(size);
+ sd->setMinSize(size);
+ break;
+ case SearchDataClause::REL_LT:
+ case SearchDataClause::REL_LTE:
+ sd->setMaxSize(size);
+ break;
+ case SearchDataClause::REL_GT:
+ case SearchDataClause::REL_GTE:
+ sd->setMinSize(size);
+ break;
+ default:
+ m_reason = "Bad relation operator with size query. Use > < or =";
+ return false;
+ }
+ return true;
+ }
+
+ if (!stringicmp("dir", fld)) {
+ // dir filtering special case
+ SearchDataClausePath *nclause =
+ new SearchDataClausePath(cl->gettext(), cl->getexclude());
+ delete cl;
+ return sd->addClause(nclause);
+ }
+
+ if (cl->getTp() == SCLT_OR || cl->getTp() == SCLT_AND) {
+ // If this is a normal clause and the term has commas or
+ // slashes inside, take it as a list, turn the slashes/commas
+ // to spaces, leave unquoted. Otherwise, this would end up as
+ // a phrase query. This is a handy way to enter multiple terms
+ // to be searched inside a field. We interpret ',' as AND, and
+ // '/' as OR. No mixes allowed and ',' wins.
+ SClType tp = SCLT_FILENAME;// impossible value
+ string ns = neutchars(cl->gettext(), ",");
+ if (ns.compare(cl->gettext())) {
+ // had ','
+ tp = SCLT_AND;
+ } else {
+ ns = neutchars(cl->gettext(), "/");
+ if (ns.compare(cl->gettext())) {
+ // had not ',' but has '/'
+ tp = SCLT_OR;
+ }
+ }
+
+ if (tp != SCLT_FILENAME) {
+ SearchDataClauseSimple *ncl =
+ new SearchDataClauseSimple(tp, ns, fld);
+ delete cl;
+ return sd->addClause(ncl);
+ }
+ }
+ return sd->addClause(cl);
+}
+