]> gitweb.fperrin.net Git - DictionaryPC.git/blob - src/com/hughes/android/dictionary/parser/WikiParser.java
8dd486439a9c993291bbcc1a929497769488f7d8
[DictionaryPC.git] / src / com / hughes / android / dictionary / parser / WikiParser.java
1 package com.hughes.android.dictionary.parser;
2
3 import java.util.ArrayList;
4 import java.util.LinkedHashMap;
5 import java.util.List;
6 import java.util.Map;
7 import java.util.regex.Matcher;
8 import java.util.regex.Pattern;
9
10 public class WikiParser {
11   
12   private static final Pattern markup = Pattern.compile("$|''|\\{\\{|\\[\\[|(==+)\\s*$|<!--|<pre>", Pattern.MULTILINE);
13   private static final Pattern listStart = Pattern.compile("^[*#;:]+");
14   private static final Pattern pipeSplit = Pattern.compile("\\s*\\|\\s*");
15   private static final Pattern whitespace = Pattern.compile("\\s+");
16   private static final Pattern headerStart = Pattern.compile("^==+");
17   
18   
19   static void parse(final String wikiText, final WikiCallback callback) {
20     
21     boolean boldOn = false;
22     boolean italicOn = false;
23     int insideHeaderDepth = -1;
24     String lastListItem = null;
25
26     final List<String> positionalArgs = new ArrayList<String>();
27     final Map<String, String> namedArgs = new LinkedHashMap<String, String>();
28
29     String rest = wikiText;
30     while (rest.length() > 0) {
31       final Matcher matcher = markup.matcher(rest);
32       if (matcher.find()) {
33         final int nextMarkupPos = matcher.start();
34         if (nextMarkupPos != 0) {
35           String text = rest.substring(0, nextMarkupPos);
36           whitespace.matcher(text).replaceAll(" ");
37           callback.onText(text);
38         }
39         rest = rest.substring(nextMarkupPos);
40         
41         if (rest.startsWith("\n")) {
42           rest = rest.substring(1);
43           
44           if (insideHeaderDepth != -1) {
45             throw new RuntimeException("barf");
46           }
47           if (lastListItem != null) {
48             callback.onListItemEnd(lastListItem, null);
49           }
50           
51           final Matcher headerMatcher = headerStart.matcher(rest);
52           if (headerMatcher.find()) {
53             insideHeaderDepth = headerMatcher.group().length();            
54             callback.onHeadingStart(insideHeaderDepth);
55             rest = rest.substring(headerMatcher.group().length());
56             continue;
57           }
58           
59           if (listStart.matcher(rest).find()) {
60             lastListItem = matcher.group();
61             callback.onListItemStart(lastListItem, null);
62             rest = rest.substring(lastListItem.length());
63             continue;
64           } else if (lastListItem != null) {
65             callback.onNewParagraph();
66             lastListItem = null;
67           }
68           
69           if (rest.startsWith("\n")) {
70             callback.onNewParagraph();
71             continue;
72           }
73           callback.onNewLine();
74         } else if (rest.startsWith("'''")) {
75           boldOn = !boldOn;
76           callback.onFormatBold(boldOn);
77           rest = rest.substring(3);
78         } else if (rest.startsWith("''")) {
79           italicOn = !italicOn;
80           callback.onFormatItalic(italicOn);
81           rest = rest.substring(2);
82         } else if (rest.startsWith("{{")) {
83           int end = rest.indexOf("}}");
84           if (end == -1) {
85             callback.onUnterminated("{{", rest);
86             return;
87           }
88           final String template = rest.substring(2, end).trim();
89           final String[] templateArray = pipeSplit.split(template);
90           positionalArgs.clear();
91           namedArgs.clear();
92           for (int i = 0; i < templateArray.length; ++i) {
93             int equalPos = templateArray[i].indexOf('=');
94             if (equalPos == -1) {
95               positionalArgs.add(templateArray[i]);
96             } else {
97               namedArgs.put(templateArray[i].substring(0, equalPos), templateArray[i].substring(equalPos + 1));
98             }
99           }
100           callback.onTemplate(positionalArgs, namedArgs);
101           rest = rest.substring(end + 2);
102         } else if (rest.startsWith("[[")) {
103           int end = rest.indexOf("]]");
104           if (end == -1) {
105             callback.onUnterminated("[[", rest);
106             return;
107           }
108           final String wikiLink = rest.substring(2, end);
109           final String[] args = pipeSplit.split(wikiLink);
110           callback.onWikiLink(args);
111           rest = rest.substring(end + 2);
112         } else if (rest.startsWith("=")) {
113           final String match = matcher.group(1) != null ? matcher.group(1) : matcher.group(2);
114           if (insideHeaderDepth == -1) {
115           } else {
116             if (match.length() != insideHeaderDepth) {
117               callback.onInvalidHeaderEnd(rest);
118               return;
119             }
120             callback.onHeadingEnd(insideHeaderDepth);
121             insideHeaderDepth = -1;
122           }
123           rest = rest.substring(match.length());
124         } else if (rest.startsWith("<!--")) {
125           int end = rest.indexOf("-->");
126           if (end == -1) {
127             callback.onUnterminated("<!--", rest);
128             return;
129           }
130           callback.onComment(rest.substring(4, end));
131           rest = rest.substring(end + 3);
132         } else if (rest.startsWith("<pre>")) {
133           int end = rest.indexOf("</pre>");
134           if (end == -1) {
135             callback.onUnterminated("<pre>", rest);
136             return;
137           }
138           callback.onText(rest.substring(5, end));
139           rest = rest.substring(end + 6);
140         } else {
141           throw new RuntimeException("barf!");
142         }
143       }  // matcher.find()
144     }
145   }
146
147 }