]> matita.cs.unibo.it Git - helm.git/blob - helm/DEVEL/mathml_editor/src/LPushLexer.cc
Added the special deletion. Pressing backspace, the user has a normal deletion
[helm.git] / helm / DEVEL / mathml_editor / src / LPushLexer.cc
1
2 #include "TToken.hh"
3 #include "LPushLexer.hh"
4 #include "APushParser.hh"
5
6 LPushLexer::LPushLexer(ALogger& l, APushParser& p) : APushLexer(l, p)
7 {
8   state = ACCEPT;
9 }
10
11 void
12 LPushLexer::reset()
13 {
14   buffer.erase();
15   state = ACCEPT;
16 }
17
18 void
19 LPushLexer::flush()
20 {
21   push(-1);
22 }
23
24 void
25 LPushLexer::transaction(char ch, State newState)
26 {
27   switch (ch)
28     {
29     case '{': parser.push(TToken(TToken::BEGIN)); break;
30     case '}': parser.push(TToken(TToken::END)); break;
31     case '$': parser.push(TToken(TToken::SHIFT)); break;
32     case '&': parser.push(TToken(TToken::ALIGN)); break;
33     case '\n':
34     case '\r': parser.push(TToken(TToken::EOL, ch)); break;
35     case '^': parser.push(TToken(TToken::SUPERSCRIPT)); break;
36     case '_': parser.push(TToken(TToken::SUBSCRIPT)); break;
37     case '\t':
38     case ' ': parser.push(TToken(TToken::SPACE, ch)); break;
39     case '~': parser.push(TToken(TToken::ACTIVE, ch)); break;
40     case '%': parser.push(TToken(TToken::COMMENT)); break;     
41     default: parser.push(TToken(TToken::OTHER, ch)); break;
42     }
43   state = newState;
44 }
45
46 void
47 LPushLexer::push(char ch)
48 {
49   switch (state)
50     {
51     case ACCEPT:
52       if (ch == '\\') state = ESCAPE;
53       else if (ch == '#') state = PARAMETER;
54       else if (ch == -1) ;
55       else if (isalpha(ch))
56         {
57           buffer.push_back(ch);
58           state = IDENTIFIER;
59         }
60       else if (isspace(ch))
61         {
62           // we translate this space in a macro.
63           parser.push(TToken(TToken::CONTROL, "space"));
64         }
65       else if (isdigit(ch))
66         {
67           buffer.push_back(ch);
68           state = NUMBER;
69         }
70       else transaction(ch, ACCEPT);
71       break;
72     case ESCAPE:
73       if (isalpha(ch))
74         {
75           buffer.push_back(ch);
76           state = MACRO;
77         }
78       else if (ch == -1) error();
79       else if (isdigit(ch))
80         {
81           // in this case, the previous '\' is ignored
82           buffer.push_back(ch);
83           state = NUMBER;
84         }
85       else
86         {
87           parser.push(TToken(TToken::CONTROL, ch));
88           state = ACCEPT;
89         }
90       break;
91     case MACRO:
92       if (ch == '\\')
93         {
94           parser.push(TToken(TToken::CONTROL, buffer));
95           buffer.erase();
96           state = ESCAPE;
97         }
98       else if (ch == '#')
99         {
100           parser.push(TToken(TToken::CONTROL, buffer));
101           buffer.erase();
102           state = PARAMETER;
103         }
104       else if (isalpha(ch))
105         buffer.push_back(ch);
106       else if (ch == -1)
107         {
108           parser.push(TToken(TToken::CONTROL, buffer));
109           buffer.erase();
110           state = ACCEPT;
111         }
112       else if (isspace(ch))
113         {
114           parser.push(TToken(TToken::CONTROL, buffer));
115           buffer.erase();
116           /*
117            * we comment this line, because a space after a macro 
118            * is useful to exit from a macro
119           //parser.push(TToken(TToken::CONTROL, ";"));
120           */
121           state = ACCEPT;
122         }
123       else if (isdigit(ch))
124         {
125           parser.push(TToken(TToken::CONTROL, buffer));
126           buffer.erase();
127           buffer.push_back(ch);
128           state = NUMBER;
129         }
130       else
131         {
132           parser.push(TToken(TToken::CONTROL, buffer));
133           buffer.erase();
134           transaction(ch, ACCEPT);
135         }
136       break;
137     case PARAMETER:
138       if (ch == -1) error();
139       else
140         {
141           parser.push(TToken(TToken::PARAMETER, ch));
142           state = ACCEPT;
143         }
144       break;
145     case IDENTIFIER:
146       if (ch == -1)
147         {
148           parser.push(TToken(TToken::LETTER, buffer));
149           buffer.erase();
150           state = ACCEPT;
151         }
152       else if (isalpha(ch) || isdigit(ch))
153         {
154           buffer.push_back(ch);
155         }
156       else if (isspace(ch))
157         {
158           parser.push(TToken(TToken::LETTER, buffer));
159           buffer.erase();
160           parser.push(TToken(TToken::CONTROL, "space"));
161           state = ACCEPT;
162         }
163       else if (ch == '\\')
164         {
165           parser.push(TToken(TToken::LETTER, buffer));
166           buffer.erase();
167           state = ESCAPE;
168         }
169       else if (ch == '#')
170         {
171           parser.push(TToken(TToken::LETTER, buffer));
172           buffer.erase();
173           state = PARAMETER;
174         }
175       else
176         {
177           parser.push(TToken(TToken::LETTER, buffer));
178           buffer.erase();
179           transaction(ch, ACCEPT);
180         }
181       break;
182     case NUMBER:
183       if (isdigit(ch)) buffer.push_back(ch);
184       else if (isspace(ch))
185         {
186           parser.push(TToken(TToken::DIGIT, buffer));
187           buffer.erase();
188           parser.push(TToken(TToken::CONTROL, "space"));
189           state = ACCEPT;
190         }
191       else if (isalpha(ch))
192         {
193           parser.push(TToken(TToken::DIGIT, buffer));
194           buffer.erase();
195           buffer.push_back(ch);
196           state = IDENTIFIER;
197         }
198       else if (ch == -1)
199         {
200           parser.push(TToken(TToken::DIGIT, buffer));
201           buffer.erase();
202           state = ACCEPT;
203         }
204       else if (ch == '\\')
205         {
206           parser.push(TToken(TToken::DIGIT, buffer));
207           buffer.erase();
208           state = ESCAPE;
209         }
210       else if (ch == '#')
211         {
212           parser.push(TToken(TToken::DIGIT, buffer));
213           buffer.erase();
214           state = PARAMETER;
215         }
216       else
217         {
218           parser.push(TToken(TToken::DIGIT, buffer));
219           buffer.erase();
220           transaction(ch, ACCEPT);
221         }
222       break;
223     default:
224       assert(0);
225       break;
226     }
227
228   switch (state)
229     {
230     case ESCAPE: parser.setCursorHint("\\"); break;
231     case MACRO: parser.setCursorHint("\\" + buffer); break;
232     case PARAMETER: parser.setCursorHint("#"); break;
233     case IDENTIFIER: parser.setCursorHint(buffer); break;
234     case NUMBER: parser.setCursorHint(buffer); break;
235     default: parser.setCursorHint(""); break;
236     }
237 }
238
239 void
240 LPushLexer::drop(bool alt)
241 {
242   std::string restore = "";
243
244   switch (state)
245     {
246     case ACCEPT:
247       restore = parser.drop(alt);
248       if (restore.length() > 0 && restore[0] == '\\')
249         {
250           cout << restore << endl;
251           buffer = std::string(restore, 1, restore.length() - 1);
252           state = (buffer.length() > 0) ? MACRO : ESCAPE;
253         }
254       else if (restore.length() > 0 && isdigit(restore[0]))
255         {
256           buffer = restore;
257           state = NUMBER;
258         }
259       else if (restore.length() > 0 && isalpha(restore[0]))
260         {
261           buffer = restore;
262           state = IDENTIFIER;
263         }
264       break;
265     case ESCAPE:
266       state = ACCEPT;
267       break;
268     case MACRO:
269       if (alt) buffer.erase();
270       else buffer.erase(buffer.length() - 1, 1);
271       if (buffer.length() == 0) state = ESCAPE;
272       break;
273     case IDENTIFIER:
274       if (alt) buffer.erase(); 
275       else buffer.erase(buffer.length() - 1, 1);
276       if (buffer.length() == 0) state = ACCEPT;
277       break;
278     case NUMBER:
279       if (alt) buffer.erase();
280       else buffer.erase(buffer.length() - 1, 1);
281       if (buffer.length() == 0) state = ACCEPT;
282       break;
283     case PARAMETER:
284     default:
285       //assert(0);
286       error();
287       break;
288     }
289
290   switch (state)
291     {
292     case ESCAPE: parser.setCursorHint("\\"); break;
293     case MACRO: parser.setCursorHint("\\" + buffer); break;
294     case PARAMETER: parser.setCursorHint("#"); break;
295     case IDENTIFIER: parser.setCursorHint(buffer); break;
296     case NUMBER: parser.setCursorHint(buffer); break;
297     default: parser.setCursorHint(""); break;
298     }
299 }
300
301 bool
302 LPushLexer::error() const
303 {
304   return false;
305 }