1 package com.hughes.android.dictionary.parser;
3 import java.util.regex.Matcher;
4 import java.util.regex.Pattern;
6 public class WikiParser {
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+");
13 static void parse(final String wikiText, final WikiCallback callback) {
15 boolean boldOn = false;
16 boolean italicOn = false;
17 int insideHeaderDepth = -1;
18 String lastListItem = null;
20 String rest = wikiText;
21 while (rest.length() > 0) {
22 final Matcher matcher = markup.matcher(rest);
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);
30 rest = rest.substring(nextMarkupPos);
32 if (rest.startsWith("\n")) {
33 if (insideHeaderDepth != -1) {
34 throw new RuntimeException("barf");
36 if (lastListItem != null) {
37 callback.onListItemEnd(lastListItem, null);
39 if (!listStart.matcher(rest.substring(1)).matches()) {
42 if (rest.startsWith("\n\n")) {
43 // TODO(thadh): eat all the newlines.
44 callback.onNewParagraph();
45 rest = rest.substring(2);
48 rest = rest.substring(1);
50 } else if (rest.startsWith("'''")) {
52 callback.onFormatBold(boldOn);
53 rest = rest.substring(3);
54 } else if (rest.startsWith("''")) {
56 callback.onFormatItalic(italicOn);
57 rest = rest.substring(2);
58 } else if (rest.startsWith("{{")) {
59 int end = rest.indexOf("}}");
61 callback.onUnterminated("{{", rest);
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('=');
70 templateArgs[i] = new String[] { null, templateArray[i] };
72 templateArgs[i] = new String[] { templateArray[i].substring(0, equalPos), templateArray[i].substring(equalPos + 1) };
75 callback.onTemplate(templateArgs);
76 rest = rest.substring(end + 2);
77 } else if (rest.startsWith("[[")) {
78 int end = rest.indexOf("]]");
80 callback.onUnterminated("[[", rest);
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);
93 if (match.length() != insideHeaderDepth) {
94 callback.onInvalidHeaderEnd(rest);
97 callback.onHeadingEnd(insideHeaderDepth);
98 insideHeaderDepth = -1;
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("-->");
108 callback.onUnterminated("<!--", rest);
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>");
116 callback.onUnterminated("<pre>", rest);
119 callback.onText(rest.substring(5, end));
120 rest = rest.substring(end + 6);
122 throw new RuntimeException("barf!");