gdk-3.0: Atom is an IntegerType
[vala-gnome.git] / libvaladoc / documentation / wikiscanner.vala
blobf0c32d22422dc1d1beb9e91300d41f99922446fb
1 /* wikiscanner.vala
3 * Copyright (C) 2008-2009 Florian Brosch, Didier Villevalois
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 * Author:
20 * Didier 'Ptitjes Villevalois <ptitjes@free.fr>
24 public class Valadoc.WikiScanner : Object, Scanner {
26 public WikiScanner (Settings settings) {
27 _settings = settings;
30 private Settings _settings;
31 private Parser _parser;
33 private string _content;
34 private unowned string _index;
35 private bool _stop;
36 private int _last_line;
37 private int _last_column;
38 private int _line;
39 private int _column;
40 private bool _url_escape_mode;
41 private bool _code_escape_mode;
42 private unichar _last_char;
43 private int _skip;
44 private StringBuilder _current_string = new StringBuilder ();
46 public void set_parser (Parser parser) {
47 _parser = parser;
50 public virtual void reset () {
51 _stop = false;
52 _last_line = 0;
53 _last_column = 0;
54 _line = 0;
55 _column = 0;
56 _url_escape_mode = false;
57 _code_escape_mode = false;
58 _last_char = 0;
59 _skip = 0;
60 _current_string.erase (0, -1);
63 public void scan (string content) throws ParserError {
64 this._content = content;
66 for (_index = _content; !_stop && _index.get_char () != 0; _index = _index.next_char ()) {
67 unichar c = _index.get_char ();
68 accept (c);
72 public void end () throws ParserError {
73 emit_token (TokenType.EOF);
76 public virtual void stop () {
77 _stop = true;
80 public void set_url_escape_mode (bool escape_mode) {
81 _url_escape_mode = escape_mode;
84 public void set_code_escape_mode (bool escape_mode) {
85 _code_escape_mode = escape_mode;
88 public int get_line () {
89 return _line;
92 public virtual string get_line_content () {
93 StringBuilder builder = new StringBuilder ();
94 weak string line_start = _index;
95 unichar c;
97 while ((char*) line_start > (char*) _content && line_start.prev_char ().get_char () != '\n') {
98 line_start = line_start.prev_char ();
101 while ((c = line_start.get_char ()) != '\n' && c != '\0') {
102 if (c == '\t') {
103 builder.append_c (' ');
104 } else {
105 builder.append_unichar (c);
107 line_start = line_start.next_char ();
110 return builder.str;
113 protected unichar get_next_char (int offset = 1) {
114 return _index.get_char (_index.index_of_nth_char (offset));
117 protected virtual void accept (unichar c) throws ParserError {
118 _column++;
119 if (_skip == 0) {
120 if (_code_escape_mode) {
121 if (c == '}' && get_next_char (1) == '}' && get_next_char (2) == '}') {
122 _code_escape_mode = false; // This is a temporary hack
123 emit_token (TokenType.TRIPLE_CLOSED_BRACE);
124 _skip = 2;
125 } else {
126 append_char (c);
128 return;
129 } else if (_url_escape_mode) {
130 switch (c) {
131 // Reserved characters
132 case ';':
133 case '/':
134 case '?':
135 case ':':
136 case '@':
137 case '#':
138 case '=':
139 case '&':
140 // Special characters
141 case '$':
142 case '-':
143 case '_':
144 case '.':
145 case '+':
146 case '!':
147 case '*':
148 case '\'':
149 case '(':
150 case ')':
151 case ',':
152 append_char (c);
153 return;
154 default:
155 break;
159 switch (c) {
160 case '@':
161 emit_token (TokenType.AROBASE);
162 break;
164 case '{':
165 look_for_three (c,
166 TokenType.OPEN_BRACE,
167 TokenType.DOUBLE_OPEN_BRACE,
168 TokenType.TRIPLE_OPEN_BRACE);
169 break;
171 case '}':
172 look_for_three (c,
173 TokenType.CLOSED_BRACE,
174 TokenType.DOUBLE_CLOSED_BRACE,
175 TokenType.TRIPLE_CLOSED_BRACE);
176 break;
178 case '[':
179 look_for_two_or_append (c, TokenType.DOUBLE_OPEN_BRACKET);
180 break;
182 case ']':
183 look_for_two_or_append (c, TokenType.DOUBLE_CLOSED_BRACKET);
184 break;
186 case '|':
187 look_for_two (c,
188 TokenType.PIPE,
189 TokenType.DOUBLE_PIPE);
190 break;
192 case ')':
193 if (get_next_char () == ')') {
194 emit_token (TokenType.ALIGN_RIGHT);
195 _skip = 1;
196 } else if (get_next_char () == '(') {
197 emit_token (TokenType.ALIGN_CENTER);
198 _skip = 1;
199 } else {
200 append_char (c);
202 break;
204 case '-':
205 emit_token (TokenType.MINUS);
206 break;
208 case '=':
209 look_for_five (c,
210 TokenType.EQUAL_1,
211 TokenType.EQUAL_2,
212 TokenType.EQUAL_3,
213 TokenType.EQUAL_4,
214 TokenType.EQUAL_5);
215 break;
217 case '<':
218 if (!look_for ("<<BR>>", TokenType.BREAK)) {
219 emit_token (TokenType.LESS_THAN);
221 break;
223 case '>':
224 emit_token (TokenType.GREATER_THAN);
225 break;
227 case '^':
228 emit_token (TokenType.ALIGN_TOP);
229 break;
231 case 'v':
232 unichar next_char = get_next_char ();
233 if (_last_char.isalnum () || _last_char == ' '
234 || next_char.isalnum () || next_char == ' ') {
235 append_char (c);
236 } else {
237 emit_token (TokenType.ALIGN_BOTTOM);
239 break;
241 case '\'':
242 look_for_two_or_append (c, TokenType.SINGLE_QUOTE_2);
243 break;
245 case '/':
246 look_for_two_or_append (c, TokenType.SLASH_2);
247 break;
249 case '_':
250 look_for_two_or_append (c, TokenType.UNDERSCORE_2);
251 break;
253 case '`':
254 if (get_next_char () == '`') {
255 emit_token (TokenType.BACK_QUOTE_2);
256 _skip = 1;
257 } else {
258 append_char (c);
260 break;
262 case '\t':
263 emit_token (TokenType.TAB);
264 break;
266 case ' ':
267 emit_token (TokenType.SPACE);
268 break;
270 case '\r':
271 break;
273 case '\n':
274 emit_token (TokenType.EOL);
275 _line++;
276 _column = 0;
277 _last_column = 0;
278 break;
280 default:
281 append_char (c);
282 break;
284 } else {
285 _skip--;
287 _last_char = c;
290 private void append_char (unichar c) {
291 _current_string.append_unichar (c);
294 public virtual int get_line_start_column () {
295 return 0;
298 private Vala.SourceLocation get_begin () {
299 return Vala.SourceLocation (_index, _last_line, get_line_start_column () + _last_column);
302 private Vala.SourceLocation get_end (int offset = 0) {
303 return Vala.SourceLocation (_index, _line, get_line_start_column () + _column + offset);
306 private void emit_current_word () throws ParserError {
307 if (_current_string.len > 0) {
308 _parser.accept_token (new Token.from_word (_current_string.str, get_begin (), get_end (-1)));
309 _current_string.erase (0, -1);
311 _last_line = _line;
312 _last_column = _column - 1;
316 private void emit_token (TokenType type) throws ParserError {
317 emit_current_word ();
319 _parser.accept_token (new Token.from_type (type, get_begin (), get_end (_skip)));
321 _last_line = _line;
322 _last_column = _column;
325 private void look_for_two_or_append (unichar c, TokenType type) throws ParserError {
326 if (get_next_char () == c) {
327 emit_token (type);
328 _skip = 1;
329 } else {
330 append_char (c);
334 private void look_for_two (unichar c, TokenType one, TokenType two) throws ParserError {
335 if (get_next_char (1) == c) {
336 emit_token (two);
337 _skip = 1;
338 } else {
339 emit_token (one);
343 private void look_for_three (unichar c, TokenType one, TokenType two, TokenType three)
344 throws ParserError
346 if (get_next_char (1) == c) {
347 if (get_next_char (2) == c) {
348 emit_token (three);
349 _skip = 2;
350 } else {
351 emit_token (two);
352 _skip = 1;
354 } else {
355 emit_token (one);
359 private void look_for_five (unichar c, TokenType one, TokenType two, TokenType three,
360 TokenType four, TokenType five) throws ParserError
362 if (get_next_char (1) == c) {
363 if (get_next_char (2) == c) {
364 if (get_next_char (3) == c) {
365 if (get_next_char (4) == c) {
366 emit_token (five);
367 _skip = 4;
368 } else {
369 emit_token (four);
370 _skip = 3;
372 } else {
373 emit_token (three);
374 _skip = 2;
376 } else {
377 emit_token (two);
378 _skip = 1;
380 } else {
381 emit_token (one);
385 private bool look_for (string str, TokenType type) throws ParserError {
386 for (int i = 1; i < str.length; i++) {
387 if (get_next_char (i) != str[i]) {
388 return false;
392 emit_token (type);
393 _skip = (int) (str.length - 1);
394 return true;