+++ /dev/null
-/* This file is part of EdiTeX, an editor of mathematical
- * expressions based on TeX syntax.
- *
- * Copyright (C) 2002-2003 Luca Padovani <lpadovan@cs.unibo.it>,
- * 2003 Paolo Marinelli <pmarinel@cs.unibo.it>.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- * For more information, please visit the project's home page
- * http://helm.cs.unibo.it/editex/
- * or send an email to <lpadovan@cs.unibo.it>
- */
-
-#include <sstream>
-#include <cassert>
-
-#include "dom.hh"
-#include "config.dirs"
-#include "TDictionary.hh"
-#include "TTokenizer.hh"
-#include "CLoggerConsole.hh"
-
-static TDictionary::Entry undefinedEntry;
-
-static std::string
-getURIBase(const std::string& uri)
-{
- std::string::size_type slash = uri.rfind('/');
- if (slash != std::string::npos) return uri.substr(0, slash + 1);
- else return "";
-}
-
-static std::string
-getURIName(const std::string& uri)
-{
- std::string::size_type slash = uri.rfind('/');
- if (slash != std::string::npos) return uri.substr(slash + 1, uri.size());
- else return uri;
-}
-
-std::string
-TDictionary::getDefaultDictionaryPath()
-{
- return PKGDATADIR"/dictionary-tex.xml";
-}
-
-void
-TDictionary::load(const std::string& uri)
-{
- load(getURIName(uri), getURIBase(uri));
-}
-
-void
-TDictionary::load(const std::string& name, const std::string& base)
-{
- logger.debug("Dictionary: loading `" + base + name + "'");
-
- DOM::DOMImplementation di;
- DOM::Document doc = di.createDocumentFromURI((base + name).c_str());
- assert(doc);
- load(doc, base);
-}
-
-void
-TDictionary::load(const DOM::Document& doc, const std::string& base)
-{
- assert(doc);
-
- DOM::Element root = doc.get_documentElement();
- assert(root);
-
- CLoggerConsole logger;
- TTokenizer tokenizer(logger);
-
- for (DOM::Node p = root.get_firstChild(); p; p = p.get_nextSibling())
- if (p.get_nodeType() == DOM::Node::ELEMENT_NODE && p.get_nodeName() == "include")
- {
- DOM::Element el = p;
- assert(el);
- if (el.hasAttribute("href"))
- {
- // WARNING: this may result into an infinite loop!
- std::string href = el.getAttribute("href");
- std::string newBase = getURIBase(href);
- std::string newName = getURIName(href);
- if (newBase != "") load(newName, newBase);
- else load(newName, base);
- }
- else
- logger.warning("Dictionary: include statement with no href attribute (ignored)");
- }
- else if (p.get_nodeType() == DOM::Node::ELEMENT_NODE && p.get_nodeName() == "entry")
- {
- DOM::Element el = p;
- assert(el);
- assert(el.hasAttribute("name"));
-
- std::string name = el.getAttribute("name");
- if (entries.find(name) != entries.end())
- logger.info("Dictionary: `" + name + "' is being redefined");
-
- Entry entry;
-
- if (el.hasAttribute("class"))
- {
- std::string cls = el.getAttribute("class");
- if (cls == "o") entry.cls = OPERATOR;
- else if (cls == "i") entry.cls = IDENTIFIER;
- else if (cls == "n") entry.cls == NUMBER;
- else entry.cls = MACRO;
- }
- else
- entry.cls = MACRO;
-
- if (el.hasAttribute("val"))
- {
- entry.value = el.getAttribute("val");
- if (entry.cls == MACRO)
- logger.warning("Dictionary: `" + name + "' has a specified value, but is classified as macro");
- }
-
- if (el.hasAttribute("pattern"))
- {
- if (entry.cls != MACRO)
- logger.warning("Dictionary: `" + name + "' has a specified pattern, but is not classified as macro");
-
- std::string pattern = el.getAttribute("pattern");
- if (pattern == "{}")
- entry.leftOpen = entry.rightOpen = 1;
- else if (pattern == "{")
- entry.leftOpen = 1;
- else if (pattern == "}")
- entry.rightOpen = 1;
- else
- entry.pattern = tokenizer.tokenize(pattern);
- }
-
-#if 0
- if (el.hasAttribute("infix"))
- {
- std::istringstream is(el.getAttribute("infix"));
- unsigned infix;
- is >> infix;
- entry.infix = infix;
- if (!el.hasAttribute("prefix")) entry.prefix = infix;
- if (!el.hasAttribute("postfix")) entry.postfix = infix;
- }
-
- if (el.hasAttribute("prefix"))
- {
- std::istringstream is(el.getAttribute("prefix"));
- unsigned prefix;
- is >> prefix;
- entry.prefix = prefix;
- if (!el.hasAttribute("infix"))
- {
- entry.infix = prefix;
- if (!el.hasAttribute("postfix")) entry.postfix = prefix;
- }
- }
-
- if (el.hasAttribute("postfix"))
- {
- std::istringstream is(el.getAttribute("postfix"));
- unsigned postfix;
- is >> postfix;
- entry.postfix = postfix;
- if (!el.hasAttribute("infix"))
- {
- entry.infix = postfix;
- if (!el.hasAttribute("prefix")) entry.prefix = postfix;
- }
- }
-#endif
-
- if (el.hasAttribute("limits"))
- {
- std::istringstream is(el.getAttribute("limits"));
- unsigned limits;
- is >> limits;
- entry.limits = limits;
- }
-
- if (el.hasAttribute("embellishment"))
- {
- std::istringstream is(el.getAttribute("embellishment"));
- unsigned embellishment;
- is >> embellishment;
- entry.embellishment = embellishment;
- }
-
- if (el.hasAttribute("delimiter"))
- {
- if (entry.cls != OPERATOR && !entry.embellishment)
- logger.warning("Dictionary: `" + name + "' delimiter ignored for non-operator");
-
- std::istringstream is(el.getAttribute("delimiter"));
- unsigned delimiter;
- is >> delimiter;
- entry.delimiter = delimiter;
- }
-
- if (el.hasAttribute("table"))
- {
- if (entry.cls != MACRO)
- logger.warning("Dictionary: `" + name + "' table ignored for non-macro");
-
- std::istringstream is(el.getAttribute("table"));
- unsigned table;
- is >> table;
- entry.table = table;
- }
-
- entries[name] = entry;
- }
-}
-
-const TDictionary::Entry&
-TDictionary::find(const std::string& name) const
-{
- Dictionary::const_iterator p = entries.find(name);
- if (p != entries.end()) return (*p).second;
- else
- {
- logger.warning("unknown entry `" + name + "'");
- return undefinedEntry;
- }
-}
-
-std::string
-TDictionary::complete(const std::string prefix, std::list<std::string>& complete_list) const
-{
- bool no_match = true;
- std::string new_prefix = "";
- for (Dictionary::const_iterator i = entries.begin(); i != entries.end(); i++)
- {
- if ((*i).first.find(prefix) == 0)
- {
- complete_list.push_front((*i).first);
- if (no_match)
- {
- // it's the first match
- no_match = false;
- new_prefix = (*i).first;
- }
- else
- {
- // in this case, new_prefix has been set yet.
- std::string s1 = (*i).first.substr(prefix.length()); // s1 is the high part of the matching string
- std::string s2 = new_prefix.substr(prefix.length()); // s2 is the high part of new_prefix
-#if 0
- long j = 0; // it's the number of common characters
- while (s1[j] == s2[j]) j++;
-#endif
- std::string::const_iterator i1 = s1.begin();
- std::string::const_iterator i2 = s2.begin();
- while (i1 != s1.end() && i2 != s2.end() && *i1 == *i2) i1++, i2++;
- new_prefix = prefix + s1.substr(0, i1 - s1.begin());
- //new_prefix = (j) ? prefix + s1.substr(0, i1 - s1.begin()) : prefix;
- }
- }
- }
-
- return new_prefix;
-}
-
-bool
-TDictionary::Entry::paramDelimited(unsigned i) const
-{
- assert(i < pattern.size());
- assert(pattern[i].category == TToken::PARAMETER);
- // a parameter is delimited if it is NOT the last one
- // AND the next argument is not a parameter
- return i + 1 < pattern.size() && pattern[i + 1].category != TToken::PARAMETER;
-}
-
-bool
-TDictionary::Entry::lastDelimiter(unsigned i) const
-{
- assert(i < pattern.size());
- assert(pattern[i].category != TToken::PARAMETER);
- // a token is the last delimiter if it is the last token
- // of the pattern or if the next token is a parameter)
- return i + 1 == pattern.size() || pattern[i + 1].category == TToken::PARAMETER;
-}
-
-unsigned
-TDictionary::Entry::previousParam(unsigned i) const
-{
- // this method return the position in the pattern of the
- // parameter placed in a position preceding i.
- // If no preceding i parameter present, the method return
- // pattern.size().
- // To know the position of the last parameter, call this
- // method with i == pattern.size()
- unsigned j = i - 1;
-
- while (pattern[j].category != TToken::PARAMETER)
- {
- if (j) j--;
- else return pattern.size();
- }
- return j;
-}