]> matita.cs.unibo.it Git - helm.git/blob - helm/DEVEL/mathml_editor/src/TDictionary.cc
* this is a large commit
[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 void
12 TDictionary::load(const std::string& uri)
13 {
14   logger.debug("Dictionary: loading `" + uri + "'");
15
16   DOM::DOMImplementation di;
17   DOM::Document doc = di.createDocumentFromURI(uri.c_str());
18   assert(doc);
19   load(doc);
20 }
21
22 void
23 TDictionary::load(const DOM::Document& doc)
24 {
25   assert(doc);
26
27   DOM::Element root = doc.get_documentElement();
28   assert(root);
29
30   CLoggerConsole logger;
31   TTokenizer tokenizer(logger);
32
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")
35       {
36         DOM::Element el = p;
37         assert(el);
38         if (el.hasAttribute("href"))
39           // WARNING: this may result into an infinite loop!
40           load(std::string(el.getAttribute("href")));
41         else
42           logger.warning("Dictionary: include statement with no href attribute (ignored)");
43       }
44     else if (p.get_nodeType() == DOM::Node::ELEMENT_NODE && p.get_nodeName() == "entry")
45       {
46         DOM::Element el = p;
47         assert(el);
48         assert(el.hasAttribute("name"));
49
50         std::string name = el.getAttribute("name");
51         if (entries.find(name) != entries.end())
52           logger.info("Dictionary: `" + name + "' is being redefined");
53
54         Entry entry;
55
56         if (el.hasAttribute("class"))
57           {
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;
63           }
64         else
65           entry.cls = MACRO;
66
67         if (el.hasAttribute("val"))
68           {
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");
72           }
73
74         if (el.hasAttribute("pattern"))
75           {
76             if (entry.cls != MACRO)
77               logger.warning("Dictionary: `" + name + "' has a specified pattern, but is not classified as macro");
78
79             std::string pattern = el.getAttribute("pattern");
80             if (pattern == "{}")
81               entry.leftOpen = entry.rightOpen = 1;
82             else if (pattern == "{")
83               entry.leftOpen = 1;
84             else if (pattern == "}")
85               entry.rightOpen = 1;
86             else
87               entry.pattern = tokenizer.tokenize(pattern);
88           }
89
90 #if 0
91         if (el.hasAttribute("infix"))
92           {
93             std::istringstream is(el.getAttribute("infix"));
94             unsigned infix;
95             is >> infix;
96             entry.infix = infix;
97             if (!el.hasAttribute("prefix")) entry.prefix = infix;
98             if (!el.hasAttribute("postfix")) entry.postfix = infix;
99           }
100
101         if (el.hasAttribute("prefix"))
102           {
103             std::istringstream is(el.getAttribute("prefix"));
104             unsigned prefix;
105             is >> prefix;
106             entry.prefix = prefix;
107             if (!el.hasAttribute("infix"))
108               {
109                 entry.infix = prefix;
110                 if (!el.hasAttribute("postfix")) entry.postfix = prefix;
111               }
112           }
113
114         if (el.hasAttribute("postfix"))
115           {
116             std::istringstream is(el.getAttribute("postfix"));
117             unsigned postfix;
118             is >> postfix;
119             entry.postfix = postfix;
120             if (!el.hasAttribute("infix"))
121               {
122                 entry.infix = postfix;
123                 if (!el.hasAttribute("prefix")) entry.prefix = postfix;
124               }
125           }
126 #endif
127
128         if (el.hasAttribute("limits"))
129           {
130             std::istringstream is(el.getAttribute("limits"));
131             unsigned limits;
132             is >> limits;
133             entry.limits = limits;
134           }
135
136         if (el.hasAttribute("embellishment"))
137           {
138             std::istringstream is(el.getAttribute("embellishment"));
139             unsigned embellishment;
140             is >> embellishment;
141             entry.embellishment = embellishment;
142           }
143
144         if (el.hasAttribute("delimiter"))
145           {
146             if (entry.cls != OPERATOR && !entry.embellishment)
147               logger.warning("Dictionary: `" + name + "' delimiter ignored for non-operator");
148
149             std::istringstream is(el.getAttribute("delimiter"));
150             unsigned delimiter;
151             is >> delimiter;
152             entry.delimiter = delimiter;
153           }
154
155         if (el.hasAttribute("table"))
156           {
157             if (entry.cls != MACRO)
158               logger.warning("Dictionary: `" + name + "' table ignored for non-macro");
159
160             std::istringstream is(el.getAttribute("table"));
161             unsigned table;
162             is >> table;
163             entry.table = table;
164           }
165
166         entries[name] = entry;
167       }
168 }
169
170 const TDictionary::Entry&
171 TDictionary::find(const std::string& name) const
172 {
173   Dictionary::const_iterator p = entries.find(name);
174   if (p != entries.end()) return (*p).second;
175   else
176     {
177       cerr << "ERROR: unknown entry `" << name << "'" << endl;
178       return undefinedEntry;
179     }
180 }
181
182 bool
183 TDictionary::Entry::paramDelimited(unsigned i) const
184 {
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;
190 }
191
192 bool
193 TDictionary::Entry::lastDelimiter(unsigned i) const
194 {
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;
200 }
201
202 unsigned
203 TDictionary::Entry::previousParam(unsigned i) const
204 {
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
208   // pattern.size().
209   // To know the position of the last parameter, call this 
210   // method with i == pattern.size()
211   unsigned j = i - 1;
212
213   while (pattern[j].category != TToken::PARAMETER)
214     {
215       if (j) j--;
216       else return pattern.size();
217     }
218   return j;
219 }