]> matita.cs.unibo.it Git - helm.git/blob - helm/DEVEL/mathml_editor/src/TDictionary.cc
* temporary fix for handling relative/absolute filenames in
[helm.git] / helm / DEVEL / mathml_editor / src / TDictionary.cc
1
2 #include <sstream>
3
4 #include "dom.hh"
5 #include "TDictionary.hh"
6 #include "TTokenizer.hh"
7 #include "CLoggerConsole.hh"
8
9 static TDictionary::Entry undefinedEntry;
10
11 static std::string
12 getURIBase(const std::string& uri)
13 {
14   std::string::size_type slash = uri.rfind('/');
15   if (slash != std::string::npos) return uri.substr(0, slash + 1);
16   else return "";
17 }
18
19 static std::string
20 getURIName(const std::string& uri)
21 {
22   std::string::size_type slash = uri.rfind('/');
23   if (slash != std::string::npos) return uri.substr(slash + 1, uri.size());
24   else return uri;
25 }
26
27 void
28 TDictionary::load(const std::string& uri)
29 {
30   load(getURIName(uri), getURIBase(uri));
31 }
32
33 void
34 TDictionary::load(const std::string& name, const std::string& base)
35 {
36   logger.debug("Dictionary: loading `" + base + name + "'");
37
38   DOM::DOMImplementation di;
39   DOM::Document doc = di.createDocumentFromURI((base + name).c_str());
40   assert(doc);
41   load(doc, base);
42 }
43
44 void
45 TDictionary::load(const DOM::Document& doc, const std::string& base)
46 {
47   assert(doc);
48
49   DOM::Element root = doc.get_documentElement();
50   assert(root);
51
52   CLoggerConsole logger;
53   TTokenizer tokenizer(logger);
54
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")
57       {
58         DOM::Element el = p;
59         assert(el);
60         if (el.hasAttribute("href"))
61           {
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);
68           }
69         else
70           logger.warning("Dictionary: include statement with no href attribute (ignored)");
71       }
72     else if (p.get_nodeType() == DOM::Node::ELEMENT_NODE && p.get_nodeName() == "entry")
73       {
74         DOM::Element el = p;
75         assert(el);
76         assert(el.hasAttribute("name"));
77
78         std::string name = el.getAttribute("name");
79         if (entries.find(name) != entries.end())
80           logger.info("Dictionary: `" + name + "' is being redefined");
81
82         Entry entry;
83
84         if (el.hasAttribute("class"))
85           {
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;
91           }
92         else
93           entry.cls = MACRO;
94
95         if (el.hasAttribute("val"))
96           {
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");
100           }
101
102         if (el.hasAttribute("pattern"))
103           {
104             if (entry.cls != MACRO)
105               logger.warning("Dictionary: `" + name + "' has a specified pattern, but is not classified as macro");
106
107             std::string pattern = el.getAttribute("pattern");
108             if (pattern == "{}")
109               entry.leftOpen = entry.rightOpen = 1;
110             else if (pattern == "{")
111               entry.leftOpen = 1;
112             else if (pattern == "}")
113               entry.rightOpen = 1;
114             else
115               entry.pattern = tokenizer.tokenize(pattern);
116           }
117
118 #if 0
119         if (el.hasAttribute("infix"))
120           {
121             std::istringstream is(el.getAttribute("infix"));
122             unsigned infix;
123             is >> infix;
124             entry.infix = infix;
125             if (!el.hasAttribute("prefix")) entry.prefix = infix;
126             if (!el.hasAttribute("postfix")) entry.postfix = infix;
127           }
128
129         if (el.hasAttribute("prefix"))
130           {
131             std::istringstream is(el.getAttribute("prefix"));
132             unsigned prefix;
133             is >> prefix;
134             entry.prefix = prefix;
135             if (!el.hasAttribute("infix"))
136               {
137                 entry.infix = prefix;
138                 if (!el.hasAttribute("postfix")) entry.postfix = prefix;
139               }
140           }
141
142         if (el.hasAttribute("postfix"))
143           {
144             std::istringstream is(el.getAttribute("postfix"));
145             unsigned postfix;
146             is >> postfix;
147             entry.postfix = postfix;
148             if (!el.hasAttribute("infix"))
149               {
150                 entry.infix = postfix;
151                 if (!el.hasAttribute("prefix")) entry.prefix = postfix;
152               }
153           }
154 #endif
155
156         if (el.hasAttribute("limits"))
157           {
158             std::istringstream is(el.getAttribute("limits"));
159             unsigned limits;
160             is >> limits;
161             entry.limits = limits;
162           }
163
164         if (el.hasAttribute("embellishment"))
165           {
166             std::istringstream is(el.getAttribute("embellishment"));
167             unsigned embellishment;
168             is >> embellishment;
169             entry.embellishment = embellishment;
170           }
171
172         if (el.hasAttribute("delimiter"))
173           {
174             if (entry.cls != OPERATOR && !entry.embellishment)
175               logger.warning("Dictionary: `" + name + "' delimiter ignored for non-operator");
176
177             std::istringstream is(el.getAttribute("delimiter"));
178             unsigned delimiter;
179             is >> delimiter;
180             entry.delimiter = delimiter;
181           }
182
183         if (el.hasAttribute("table"))
184           {
185             if (entry.cls != MACRO)
186               logger.warning("Dictionary: `" + name + "' table ignored for non-macro");
187
188             std::istringstream is(el.getAttribute("table"));
189             unsigned table;
190             is >> table;
191             entry.table = table;
192           }
193
194         entries[name] = entry;
195       }
196 }
197
198 const TDictionary::Entry&
199 TDictionary::find(const std::string& name) const
200 {
201   Dictionary::const_iterator p = entries.find(name);
202   if (p != entries.end()) return (*p).second;
203   else
204     {
205       cerr << "ERROR: unknown entry `" << name << "'" << endl;
206       return undefinedEntry;
207     }
208 }
209
210 bool
211 TDictionary::Entry::paramDelimited(unsigned i) const
212 {
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;
218 }
219
220 bool
221 TDictionary::Entry::lastDelimiter(unsigned i) const
222 {
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;
228 }
229
230 unsigned
231 TDictionary::Entry::previousParam(unsigned i) const
232 {
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
236   // pattern.size().
237   // To know the position of the last parameter, call this 
238   // method with i == pattern.size()
239   unsigned j = i - 1;
240
241   while (pattern[j].category != TToken::PARAMETER)
242     {
243       if (j) j--;
244       else return pattern.size();
245     }
246   return j;
247 }