5 #include "TDictionary.hh"
6 #include "TTokenizer.hh"
7 #include "CLoggerConsole.hh"
9 static TDictionary::Entry undefinedEntry;
12 getURIBase(const std::string& uri)
14 std::string::size_type slash = uri.rfind('/');
15 if (slash != std::string::npos) return uri.substr(0, slash + 1);
20 getURIName(const std::string& uri)
22 std::string::size_type slash = uri.rfind('/');
23 if (slash != std::string::npos) return uri.substr(slash + 1, uri.size());
28 TDictionary::load(const std::string& uri)
30 load(getURIName(uri), getURIBase(uri));
34 TDictionary::load(const std::string& name, const std::string& base)
36 logger.debug("Dictionary: loading `" + base + name + "'");
38 DOM::DOMImplementation di;
39 DOM::Document doc = di.createDocumentFromURI((base + name).c_str());
45 TDictionary::load(const DOM::Document& doc, const std::string& base)
49 DOM::Element root = doc.get_documentElement();
52 CLoggerConsole logger;
53 TTokenizer tokenizer(logger);
55 for (DOM::Node p = root.get_firstChild(); p; p = p.get_nextSibling())
56 if (p.get_nodeType() == DOM::Node::ELEMENT_NODE && p.get_nodeName() == "include")
60 if (el.hasAttribute("href"))
62 // WARNING: this may result into an infinite loop!
63 std::string href = el.getAttribute("href");
64 std::string newBase = getURIBase(href);
65 std::string newName = getURIName(href);
66 if (newBase != "") load(newName, newBase);
67 else load(newName, base);
70 logger.warning("Dictionary: include statement with no href attribute (ignored)");
72 else if (p.get_nodeType() == DOM::Node::ELEMENT_NODE && p.get_nodeName() == "entry")
76 assert(el.hasAttribute("name"));
78 std::string name = el.getAttribute("name");
79 if (entries.find(name) != entries.end())
80 logger.info("Dictionary: `" + name + "' is being redefined");
84 if (el.hasAttribute("class"))
86 std::string cls = el.getAttribute("class");
87 if (cls == "o") entry.cls = OPERATOR;
88 else if (cls == "i") entry.cls = IDENTIFIER;
89 else if (cls == "n") entry.cls == NUMBER;
90 else entry.cls = MACRO;
95 if (el.hasAttribute("val"))
97 entry.value = el.getAttribute("val");
98 if (entry.cls == MACRO)
99 logger.warning("Dictionary: `" + name + "' has a specified value, but is classified as macro");
102 if (el.hasAttribute("pattern"))
104 if (entry.cls != MACRO)
105 logger.warning("Dictionary: `" + name + "' has a specified pattern, but is not classified as macro");
107 std::string pattern = el.getAttribute("pattern");
109 entry.leftOpen = entry.rightOpen = 1;
110 else if (pattern == "{")
112 else if (pattern == "}")
115 entry.pattern = tokenizer.tokenize(pattern);
119 if (el.hasAttribute("infix"))
121 std::istringstream is(el.getAttribute("infix"));
125 if (!el.hasAttribute("prefix")) entry.prefix = infix;
126 if (!el.hasAttribute("postfix")) entry.postfix = infix;
129 if (el.hasAttribute("prefix"))
131 std::istringstream is(el.getAttribute("prefix"));
134 entry.prefix = prefix;
135 if (!el.hasAttribute("infix"))
137 entry.infix = prefix;
138 if (!el.hasAttribute("postfix")) entry.postfix = prefix;
142 if (el.hasAttribute("postfix"))
144 std::istringstream is(el.getAttribute("postfix"));
147 entry.postfix = postfix;
148 if (!el.hasAttribute("infix"))
150 entry.infix = postfix;
151 if (!el.hasAttribute("prefix")) entry.prefix = postfix;
156 if (el.hasAttribute("limits"))
158 std::istringstream is(el.getAttribute("limits"));
161 entry.limits = limits;
164 if (el.hasAttribute("embellishment"))
166 std::istringstream is(el.getAttribute("embellishment"));
167 unsigned embellishment;
169 entry.embellishment = embellishment;
172 if (el.hasAttribute("delimiter"))
174 if (entry.cls != OPERATOR && !entry.embellishment)
175 logger.warning("Dictionary: `" + name + "' delimiter ignored for non-operator");
177 std::istringstream is(el.getAttribute("delimiter"));
180 entry.delimiter = delimiter;
183 if (el.hasAttribute("table"))
185 if (entry.cls != MACRO)
186 logger.warning("Dictionary: `" + name + "' table ignored for non-macro");
188 std::istringstream is(el.getAttribute("table"));
194 entries[name] = entry;
198 const TDictionary::Entry&
199 TDictionary::find(const std::string& name) const
201 Dictionary::const_iterator p = entries.find(name);
202 if (p != entries.end()) return (*p).second;
205 cerr << "ERROR: unknown entry `" << name << "'" << endl;
206 return undefinedEntry;
211 TDictionary::Entry::paramDelimited(unsigned i) const
213 assert(i < pattern.size());
214 assert(pattern[i].category == TToken::PARAMETER);
215 // a parameter is delimited if it is NOT the last one
216 // AND the next argument is not a parameter
217 return i + 1 < pattern.size() && pattern[i + 1].category != TToken::PARAMETER;
221 TDictionary::Entry::lastDelimiter(unsigned i) const
223 assert(i < pattern.size());
224 assert(pattern[i].category != TToken::PARAMETER);
225 // a token is the last delimiter if it is the last token
226 // of the pattern or if the next token is a parameter)
227 return i + 1 == pattern.size() || pattern[i + 1].category == TToken::PARAMETER;
231 TDictionary::Entry::previousParam(unsigned i) const
233 // this method return the position in the pattern of the
234 // parameter placed in a position preceding i.
235 // If no preceding i parameter present, the method return
237 // To know the position of the last parameter, call this
238 // method with i == pattern.size()
241 while (pattern[j].category != TToken::PARAMETER)
244 else return pattern.size();