--- /dev/null
+
+#include <sstream>
+
+#include "dom.hh"
+#include "TDictionary.hh"
+#include "TTokenizer.hh"
+
+static TDictionary::Entry undefinedEntry;
+
+void
+TDictionary::load(const char* uri)
+{
+ DOM::DOMImplementation di;
+
+ DOM::Document doc = di.createDocumentFromURI(uri);
+ assert(doc);
+
+ DOM::Element root = doc.get_documentElement();
+ assert(root);
+
+ TTokenizer tokenizer;
+
+ for (DOM::Node p = root.get_firstChild(); p; p = p.get_nextSibling())
+ 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())
+ cerr << "WARNING: entry `" << name << "' is being redefined" << endl;
+
+ 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)
+ cerr << "WARNING: `" << name << "' has a specified value, but is classified as macro" << endl;
+ }
+
+ if (el.hasAttribute("pattern"))
+ {
+ if (entry.cls != MACRO)
+ cerr << "WARNING: `" << name << "' has a specified pattern, but is not classified as macro" << endl;
+
+ 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 (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;
+ }
+ }
+
+ 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)
+ cerr << "WARNING: `" << name << "' delimiter ignored for non-operator" << endl;
+
+ std::istringstream is(el.getAttribute("delimiter"));
+ unsigned delimiter;
+ is >> delimiter;
+ entry.delimiter = delimiter;
+ }
+
+ if (el.hasAttribute("table"))
+ {
+ if (entry.cls != MACRO)
+ cerr << "WARNING: `" << name << "' table ignored for non-macro" << endl;
+
+ 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
+ {
+ cerr << "ERROR: unknown entry `" << name << "'" << endl;
+ return undefinedEntry;
+ }
+}
+
+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;
+}