5 #include "TDictionary.hh"
6 #include "TTokenizer.hh"
7 #include "CLoggerConsole.hh"
9 static TDictionary::Entry undefinedEntry;
12 TDictionary::load(const std::string& uri)
14 logger.debug("Dictionary: loading `" + uri + "'");
16 DOM::DOMImplementation di;
17 DOM::Document doc = di.createDocumentFromURI(uri.c_str());
23 TDictionary::load(const DOM::Document& doc)
27 DOM::Element root = doc.get_documentElement();
30 CLoggerConsole logger;
31 TTokenizer tokenizer(logger);
33 for (DOM::Node p = root.get_firstChild(); p; p = p.get_nextSibling())
34 if (p.get_nodeType() == DOM::Node::ELEMENT_NODE && p.get_nodeName() == "include")
38 if (el.hasAttribute("href"))
39 // WARNING: this may result into an infinite loop!
40 load(std::string(el.getAttribute("href")));
42 logger.warning("Dictionary: include statement with no href attribute (ignored)");
44 else if (p.get_nodeType() == DOM::Node::ELEMENT_NODE && p.get_nodeName() == "entry")
48 assert(el.hasAttribute("name"));
50 std::string name = el.getAttribute("name");
51 if (entries.find(name) != entries.end())
52 logger.info("Dictionary: `" + name + "' is being redefined");
56 if (el.hasAttribute("class"))
58 std::string cls = el.getAttribute("class");
59 if (cls == "o") entry.cls = OPERATOR;
60 else if (cls == "i") entry.cls = IDENTIFIER;
61 else if (cls == "n") entry.cls == NUMBER;
62 else entry.cls = MACRO;
67 if (el.hasAttribute("val"))
69 entry.value = el.getAttribute("val");
70 if (entry.cls == MACRO)
71 logger.warning("Dictionary: `" + name + "' has a specified value, but is classified as macro");
74 if (el.hasAttribute("pattern"))
76 if (entry.cls != MACRO)
77 logger.warning("Dictionary: `" + name + "' has a specified pattern, but is not classified as macro");
79 std::string pattern = el.getAttribute("pattern");
81 entry.leftOpen = entry.rightOpen = 1;
82 else if (pattern == "{")
84 else if (pattern == "}")
87 entry.pattern = tokenizer.tokenize(pattern);
91 if (el.hasAttribute("infix"))
93 std::istringstream is(el.getAttribute("infix"));
97 if (!el.hasAttribute("prefix")) entry.prefix = infix;
98 if (!el.hasAttribute("postfix")) entry.postfix = infix;
101 if (el.hasAttribute("prefix"))
103 std::istringstream is(el.getAttribute("prefix"));
106 entry.prefix = prefix;
107 if (!el.hasAttribute("infix"))
109 entry.infix = prefix;
110 if (!el.hasAttribute("postfix")) entry.postfix = prefix;
114 if (el.hasAttribute("postfix"))
116 std::istringstream is(el.getAttribute("postfix"));
119 entry.postfix = postfix;
120 if (!el.hasAttribute("infix"))
122 entry.infix = postfix;
123 if (!el.hasAttribute("prefix")) entry.prefix = postfix;
128 if (el.hasAttribute("limits"))
130 std::istringstream is(el.getAttribute("limits"));
133 entry.limits = limits;
136 if (el.hasAttribute("embellishment"))
138 std::istringstream is(el.getAttribute("embellishment"));
139 unsigned embellishment;
141 entry.embellishment = embellishment;
144 if (el.hasAttribute("delimiter"))
146 if (entry.cls != OPERATOR && !entry.embellishment)
147 logger.warning("Dictionary: `" + name + "' delimiter ignored for non-operator");
149 std::istringstream is(el.getAttribute("delimiter"));
152 entry.delimiter = delimiter;
155 if (el.hasAttribute("table"))
157 if (entry.cls != MACRO)
158 logger.warning("Dictionary: `" + name + "' table ignored for non-macro");
160 std::istringstream is(el.getAttribute("table"));
166 entries[name] = entry;
170 const TDictionary::Entry&
171 TDictionary::find(const std::string& name) const
173 Dictionary::const_iterator p = entries.find(name);
174 if (p != entries.end()) return (*p).second;
177 cerr << "ERROR: unknown entry `" << name << "'" << endl;
178 return undefinedEntry;
183 TDictionary::Entry::paramDelimited(unsigned i) const
185 assert(i < pattern.size());
186 assert(pattern[i].category == TToken::PARAMETER);
187 // a parameter is delimited if it is NOT the last one
188 // AND the next argument is not a parameter
189 return i + 1 < pattern.size() && pattern[i + 1].category != TToken::PARAMETER;
193 TDictionary::Entry::lastDelimiter(unsigned i) const
195 assert(i < pattern.size());
196 assert(pattern[i].category != TToken::PARAMETER);
197 // a token is the last delimiter if it is the last token
198 // of the pattern or if the next token is a parameter)
199 return i + 1 == pattern.size() || pattern[i + 1].category == TToken::PARAMETER;
203 TDictionary::Entry::previousParam(unsigned i) const
205 // this method return the position in the pattern of the
206 // parameter placed in a position preceding i.
207 // If no preceding i parameter present, the method return
209 // To know the position of the last parameter, call this
210 // method with i == pattern.size()
213 while (pattern[j].category != TToken::PARAMETER)
216 else return pattern.size();