]> matita.cs.unibo.it Git - helm.git/blob - helm/DEVEL/mathml_editor/src/TPushLexer.cc
New version 0.0.2:
[helm.git] / helm / DEVEL / mathml_editor / src / TPushLexer.cc
1 /* This file is part of EdiTeX, an editor of mathematical
2  * expressions based on TeX syntax.
3  * 
4  * Copyright (C) 2002-2003 Luca Padovani <lpadovan@cs.unibo.it>,
5  *                    2003 Paolo Marinelli <pmarinel@cs.unibo.it>.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  *
21  * For more information, please visit the project's home page
22  * http://helm.cs.unibo.it/editex/
23  * or send an email to <lpadovan@cs.unibo.it>
24  */
25
26 #include <string>
27 #include <cctype>
28
29 #include "TToken.hh"
30 #include "TPushLexer.hh"
31 #include "APushParser.hh"
32
33 TPushLexer::TPushLexer(ALogger& l, APushParser& p) : APushLexer(l, p)
34 {
35   state = ACCEPT;
36 }
37
38 void
39 TPushLexer::reset()
40 {
41   buffer.erase();
42   state = ACCEPT;
43
44   displayCursor();
45 }
46
47 void
48 TPushLexer::flush()
49 {
50   push(-1);
51 }
52
53 void
54 TPushLexer::transaction(char ch, State newState)
55 {
56   switch (ch)
57     {
58     case '{': parser.push(TToken(TToken::BEGIN)); break;
59     case '}': parser.push(TToken(TToken::END)); break;
60     case '$': parser.push(TToken(TToken::SHIFT)); break;
61     case '&': parser.push(TToken(TToken::ALIGN)); break;
62     case '\n':
63     case '\r': parser.push(TToken(TToken::EOL, ch)); break;
64     case '^': parser.push(TToken(TToken::SUPERSCRIPT)); break;
65     case '_': parser.push(TToken(TToken::SUBSCRIPT)); break;
66     case '\t':
67     case ' ': parser.push(TToken(TToken::IGNORABLE_SPACE, ch)); break;
68     case '~': parser.push(TToken(TToken::ACTIVE, ch)); break;
69     case '%': parser.push(TToken(TToken::COMMENT)); break;     
70     default:
71       if (isalpha(ch)) parser.push(TToken(TToken::LETTER, ch));
72       else if (isdigit(ch)) parser.push(TToken(TToken::DIGIT, ch));
73       else parser.push(TToken(TToken::OTHER, ch));
74       break;
75     }
76   state = newState;
77 }
78
79 void
80 TPushLexer::push(char ch)
81 {
82   switch (state)
83     {
84     case ACCEPT:
85       if (ch == '\\') state = ESCAPE;
86       else if (ch == '#') state = PARAMETER;
87       else if (ch == -1) ;
88       else transaction(ch, ACCEPT);
89       break;
90     case ESCAPE:
91       if (isalpha(ch))
92         {
93           buffer.push_back(ch);
94           state = MACRO;
95         }
96       else if (ch == -1) error();
97       else
98         {
99           parser.push(TToken(TToken::CONTROL, ch));
100           state = ACCEPT;
101         }
102       break;
103     case MACRO:
104       if (ch == '\\')
105         {
106           parser.push(TToken(TToken::CONTROL, buffer));
107           buffer.erase();
108           state = ESCAPE;
109         }
110       else if (ch == '#')
111         {
112           parser.push(TToken(TToken::CONTROL, buffer));
113           buffer.erase();
114           state = PARAMETER;
115         }
116       else if (isalpha(ch))
117         buffer.push_back(ch);
118       else if (ch == -1)
119         {
120           parser.push(TToken(TToken::CONTROL, buffer));
121           buffer.erase();
122           state = ACCEPT;
123         }
124       else
125         {
126           parser.push(TToken(TToken::CONTROL, buffer));
127           buffer.erase();
128           if (isspace(ch)) state = IGNORE_SPACE;
129           else transaction(ch, ACCEPT);
130         }
131       break;
132     case IGNORE_SPACE:
133       if (ch == '\\') state = ESCAPE;
134       else if (ch == '#') state = PARAMETER;
135       else if (isspace(ch)) ;
136       else if (ch == -1) state = ACCEPT;
137       else transaction(ch, ACCEPT);
138       break;
139     case PARAMETER:
140       if (ch == -1) error();
141       else
142         {
143           parser.push(TToken(TToken::PARAMETER, ch));
144           state = ACCEPT;
145         }
146       break;
147     default:
148       assert(0);
149       break;
150     }
151
152   displayCursor();
153
154 }
155
156 void
157 TPushLexer::drop(bool alt)
158 {
159   std::string restore = "";
160
161   switch (state)
162     {
163     case ACCEPT:
164     case IGNORE_SPACE:
165       restore = parser.drop(alt);
166       if (restore.length() > 0 && restore[0] == '\\')
167         {
168           buffer = std::string(restore, 1, restore.length() - 1);
169           state = (buffer.length() > 0) ? MACRO : ESCAPE;
170         }
171       break;
172     case ESCAPE:
173       state = ACCEPT;
174       break;
175     case MACRO:
176       if (alt) buffer.erase();
177       else buffer.erase(buffer.length() - 1, 1);
178       if (buffer.length() == 0) state = ESCAPE;
179       break;
180     case PARAMETER:
181     default:
182       assert(0);
183       break;
184     }
185
186   displayCursor();
187
188 }
189
190 void
191 TPushLexer::displayCursor()
192 {
193   switch (state)
194     {
195     case ESCAPE: parser.setCursorHint("\\"); break;
196     case MACRO: parser.setCursorHint("\\" + buffer); break;
197     case PARAMETER: parser.setCursorHint("#"); break;
198     default: parser.setCursorHint(""); break;
199     }
200 }
201
202 bool
203 TPushLexer::error() const
204 {
205   return false;
206 }