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