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
20 * Didier 'Ptitjes Villevalois <ptitjes@free.fr>
24 public class Valadoc
.WikiScanner
: Object
, Scanner
{
26 public WikiScanner (Settings settings
) {
30 private Settings _settings
;
31 private Parser _parser
;
33 private string _content
;
34 private unowned
string _index
;
36 private int _last_line
;
37 private int _last_column
;
40 private bool _url_escape_mode
;
41 private bool _code_escape_mode
;
42 private unichar _last_char
;
44 private StringBuilder _current_string
= new
StringBuilder ();
46 public void set_parser (Parser parser
) {
50 public virtual void reset () {
56 _url_escape_mode
= false;
57 _code_escape_mode
= false;
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 ();
72 public void end () throws ParserError
{
73 emit_token (TokenType
.EOF
);
76 public virtual void stop () {
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 () {
92 public virtual string get_line_content () {
93 StringBuilder builder
= new
StringBuilder ();
94 weak string line_start
= _index
;
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') {
103 builder
.append_c (' ');
105 builder
.append_unichar (c
);
107 line_start
= line_start
.next_char ();
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
{
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
);
129 } else if (_url_escape_mode
) {
131 // Reserved characters
140 // Special characters
161 emit_token (TokenType
.AROBASE
);
166 TokenType
.OPEN_BRACE
,
167 TokenType
.DOUBLE_OPEN_BRACE
,
168 TokenType
.TRIPLE_OPEN_BRACE
);
173 TokenType
.CLOSED_BRACE
,
174 TokenType
.DOUBLE_CLOSED_BRACE
,
175 TokenType
.TRIPLE_CLOSED_BRACE
);
179 look_for_two_or_append (c
, TokenType
.DOUBLE_OPEN_BRACKET
);
183 look_for_two_or_append (c
, TokenType
.DOUBLE_CLOSED_BRACKET
);
189 TokenType
.DOUBLE_PIPE
);
193 if (get_next_char () == ')') {
194 emit_token (TokenType
.ALIGN_RIGHT
);
196 } else if (get_next_char () == '(') {
197 emit_token (TokenType
.ALIGN_CENTER
);
205 emit_token (TokenType
.MINUS
);
218 if (!look_for ("<<BR>>", TokenType
.BREAK
)) {
219 emit_token (TokenType
.LESS_THAN
);
224 emit_token (TokenType
.GREATER_THAN
);
228 emit_token (TokenType
.ALIGN_TOP
);
232 unichar next_char
= get_next_char ();
233 if (_last_char
.isalnum () || _last_char
== ' '
234 || next_char
.isalnum () || next_char
== ' ') {
237 emit_token (TokenType
.ALIGN_BOTTOM
);
242 look_for_two_or_append (c
, TokenType
.SINGLE_QUOTE_2
);
246 look_for_two_or_append (c
, TokenType
.SLASH_2
);
250 look_for_two_or_append (c
, TokenType
.UNDERSCORE_2
);
254 if (get_next_char () == '`') {
255 emit_token (TokenType
.BACK_QUOTE_2
);
263 emit_token (TokenType
.TAB
);
267 emit_token (TokenType
.SPACE
);
274 emit_token (TokenType
.EOL
);
290 private void append_char (unichar c
) {
291 _current_string
.append_unichar (c
);
294 public virtual int get_line_start_column () {
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);
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
)));
322 _last_column
= _column
;
325 private void look_for_two_or_append (unichar c
, TokenType type
) throws ParserError
{
326 if (get_next_char () == c
) {
334 private void look_for_two (unichar c
, TokenType one
, TokenType two
) throws ParserError
{
335 if (get_next_char (1) == c
) {
343 private void look_for_three (unichar c
, TokenType one
, TokenType two
, TokenType three
)
346 if (get_next_char (1) == c
) {
347 if (get_next_char (2) == c
) {
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
) {
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
]) {
393 _skip
= (int) (str
.length
- 1);