Mercurial Hosting > luan
annotate src/luan/modules/parsers/BBCode.java @ 1111:88b5b81cad4a
move Parser to luan.lib.parser
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Wed, 02 Aug 2017 15:19:47 -0600 |
parents | 1460d297e960 |
children | 728d8e75f476 |
rev | line source |
---|---|
585 | 1 package luan.modules.parsers; |
2 | |
637
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
3 import java.util.List; |
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
4 import java.util.ArrayList; |
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
5 import luan.Luan; |
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
6 import luan.LuanState; |
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
7 import luan.LuanFunction; |
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
8 import luan.LuanException; |
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
9 import luan.modules.Utils; |
1111
88b5b81cad4a
move Parser to luan.lib.parser
Franklin Schmidt <fschmidt@gmail.com>
parents:
777
diff
changeset
|
10 import luan.lib.parser.Parser; |
637
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
11 |
585 | 12 |
13 public final class BBCode { | |
14 | |
637
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
15 public static String toHtml(LuanState luan,String bbcode,LuanFunction quoter) throws LuanException { |
638 | 16 return new BBCode(luan,bbcode,quoter,true).parse(); |
585 | 17 } |
18 | |
637
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
19 public static String toText(LuanState luan,String bbcode,LuanFunction quoter) throws LuanException { |
638 | 20 return new BBCode(luan,bbcode,quoter,false).parse(); |
585 | 21 } |
22 | |
637
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
23 private final LuanState luan; |
585 | 24 private final Parser parser; |
638 | 25 private final LuanFunction quoter; |
585 | 26 private final boolean toHtml; |
27 | |
638 | 28 private BBCode(LuanState luan,String text,LuanFunction quoter,boolean toHtml) throws LuanException { |
646
cdc70de628b5
simplify LuanException
Franklin Schmidt <fschmidt@gmail.com>
parents:
638
diff
changeset
|
29 Utils.checkNotNull(text,1); |
777
1460d297e960
add bbcode to blog example
Franklin Schmidt <fschmidt@gmail.com>
parents:
775
diff
changeset
|
30 // Utils.checkNotNull(quoter,2); |
637
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
31 this.luan = luan; |
585 | 32 this.parser = new Parser(text); |
638 | 33 this.quoter = quoter; |
585 | 34 this.toHtml = toHtml; |
35 } | |
36 | |
637
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
37 private String parse() throws LuanException { |
585 | 38 StringBuilder sb = new StringBuilder(); |
39 while( !parser.endOfInput() ) { | |
40 String block = parseBlock(); | |
41 if( block != null ) | |
42 sb.append(block); | |
43 else { | |
44 sb.append( parser.currentChar() ); | |
45 parser.anyChar(); | |
46 } | |
47 } | |
48 return sb.toString(); | |
49 } | |
50 | |
637
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
51 private String parseWellFormed() throws LuanException { |
585 | 52 StringBuilder sb = new StringBuilder(); |
53 while( !parser.endOfInput() ) { | |
54 String block = parseBlock(); | |
55 if( block != null ) { | |
56 sb.append(block); | |
57 continue; | |
58 } | |
59 if( couldBeTag() ) | |
60 break; | |
61 sb.append( parser.currentChar() ); | |
62 parser.anyChar(); | |
63 } | |
64 return sb.toString(); | |
65 } | |
66 | |
67 private boolean couldBeTag() { | |
68 if( parser.currentChar() != '[' ) | |
69 return false; | |
70 return parser.testIgnoreCase("[b]") | |
71 || parser.testIgnoreCase("[/b]") | |
72 || parser.testIgnoreCase("[i]") | |
73 || parser.testIgnoreCase("[/i]") | |
74 || parser.testIgnoreCase("[u]") | |
75 || parser.testIgnoreCase("[/u]") | |
76 || parser.testIgnoreCase("[url]") | |
77 || parser.testIgnoreCase("[url=") | |
78 || parser.testIgnoreCase("[/url]") | |
79 || parser.testIgnoreCase("[code]") | |
80 || parser.testIgnoreCase("[/code]") | |
81 || parser.testIgnoreCase("[img]") | |
82 || parser.testIgnoreCase("[/img]") | |
83 || parser.testIgnoreCase("[color=") | |
84 || parser.testIgnoreCase("[/color]") | |
85 || parser.testIgnoreCase("[size=") | |
86 || parser.testIgnoreCase("[/size]") | |
87 || parser.testIgnoreCase("[youtube]") | |
88 || parser.testIgnoreCase("[/youtube]") | |
89 || parser.testIgnoreCase("[quote]") | |
90 || parser.testIgnoreCase("[quote=") | |
91 || parser.testIgnoreCase("[/quote]") | |
92 ; | |
93 } | |
94 | |
637
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
95 private String parseBlock() throws LuanException { |
585 | 96 if( parser.currentChar() != '[' ) |
97 return null; | |
98 String s; | |
99 s = parseB(); if(s!=null) return s; | |
100 s = parseI(); if(s!=null) return s; | |
101 s = parseU(); if(s!=null) return s; | |
102 s = parseUrl1(); if(s!=null) return s; | |
103 s = parseUrl2(); if(s!=null) return s; | |
104 s = parseCode(); if(s!=null) return s; | |
105 s = parseImg(); if(s!=null) return s; | |
106 s = parseColor(); if(s!=null) return s; | |
107 s = parseSize(); if(s!=null) return s; | |
108 s = parseYouTube(); if(s!=null) return s; | |
109 s = parseQuote1(); if(s!=null) return s; | |
110 s = parseQuote2(); if(s!=null) return s; | |
111 return null; | |
112 } | |
113 | |
637
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
114 private String parseB() throws LuanException { |
585 | 115 parser.begin(); |
116 if( !parser.matchIgnoreCase("[b]") ) | |
117 return parser.failure(null); | |
118 String content = parseWellFormed(); | |
119 if( !parser.matchIgnoreCase("[/b]") ) | |
120 return parser.failure(null); | |
121 String rtn = toHtml ? "<b>"+content+"</b>" : content; | |
122 return parser.success(rtn); | |
123 } | |
124 | |
637
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
125 private String parseI() throws LuanException { |
585 | 126 parser.begin(); |
127 if( !parser.matchIgnoreCase("[i]") ) | |
128 return parser.failure(null); | |
129 String content = parseWellFormed(); | |
130 if( !parser.matchIgnoreCase("[/i]") ) | |
131 return parser.failure(null); | |
132 String rtn = toHtml ? "<i>"+content+"</i>" : content; | |
133 return parser.success(rtn); | |
134 } | |
135 | |
637
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
136 private String parseU() throws LuanException { |
585 | 137 parser.begin(); |
138 if( !parser.matchIgnoreCase("[u]") ) | |
139 return parser.failure(null); | |
140 String content = parseWellFormed(); | |
141 if( !parser.matchIgnoreCase("[/u]") ) | |
142 return parser.failure(null); | |
143 String rtn = toHtml ? "<u>"+content+"</u>" : content; | |
144 return parser.success(rtn); | |
145 } | |
146 | |
147 private String parseUrl1() { | |
148 parser.begin(); | |
149 if( !parser.matchIgnoreCase("[url]") ) | |
150 return parser.failure(null); | |
151 String url = parseRealUrl(); | |
152 if( !parser.matchIgnoreCase("[/url]") ) | |
153 return parser.failure(null); | |
154 String rtn = toHtml ? "<a href='"+url+"'>"+url+"</u>" : url; | |
155 return parser.success(rtn); | |
156 } | |
157 | |
637
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
158 private String parseUrl2() throws LuanException { |
585 | 159 parser.begin(); |
160 if( !parser.matchIgnoreCase("[url=") ) | |
161 return parser.failure(null); | |
162 String url = parseRealUrl(); | |
163 if( !parser.match(']') ) | |
164 return parser.failure(null); | |
165 String content = parseWellFormed(); | |
166 if( !parser.matchIgnoreCase("[/url]") ) | |
167 return parser.failure(null); | |
168 String rtn = toHtml ? "<a href='"+url+"'>"+content+"</u>" : content; | |
169 return parser.success(rtn); | |
170 } | |
171 | |
172 private String parseRealUrl() { | |
173 parser.begin(); | |
174 while( parser.match(' ') ); | |
175 int start = parser.currentIndex(); | |
176 if( !parser.matchIgnoreCase("http") ) | |
177 return parser.failure(null); | |
178 parser.matchIgnoreCase("s"); | |
179 if( !parser.matchIgnoreCase("://") ) | |
180 return parser.failure(null); | |
181 while( parser.noneOf(" []'") ); | |
182 String url = parser.textFrom(start); | |
183 while( parser.match(' ') ); | |
184 return parser.success(url); | |
185 } | |
186 | |
187 private String parseCode() { | |
188 parser.begin(); | |
189 if( !parser.matchIgnoreCase("[code]") ) | |
190 return parser.failure(null); | |
191 int start = parser.currentIndex(); | |
192 while( !parser.testIgnoreCase("[/code]") ) { | |
193 if( !parser.anyChar() ) | |
194 return parser.failure(null); | |
195 } | |
196 String content = parser.textFrom(start); | |
197 if( !parser.matchIgnoreCase("[/code]") ) throw new RuntimeException(); | |
198 String rtn = toHtml ? "<code>"+content+"</code>" : content; | |
199 return parser.success(rtn); | |
200 } | |
201 | |
202 private String parseImg() { | |
203 parser.begin(); | |
204 if( !parser.matchIgnoreCase("[img]") ) | |
205 return parser.failure(null); | |
206 String url = parseRealUrl(); | |
207 if( !parser.matchIgnoreCase("[/img]") ) | |
208 return parser.failure(null); | |
209 String rtn = toHtml ? "<img src='"+url+"'>" : ""; | |
210 return parser.success(rtn); | |
211 } | |
212 | |
637
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
213 private String parseColor() throws LuanException { |
585 | 214 parser.begin(); |
215 if( !parser.matchIgnoreCase("[color=") ) | |
216 return parser.failure(null); | |
217 int start = parser.currentIndex(); | |
218 parser.match('#'); | |
219 while( parser.inCharRange('0','9') | |
220 || parser.inCharRange('a','z') | |
221 || parser.inCharRange('A','Z') | |
222 ); | |
223 String color = parser.textFrom(start); | |
224 if( !parser.match(']') ) | |
225 return parser.failure(null); | |
226 String content = parseWellFormed(); | |
227 if( !parser.matchIgnoreCase("[/color]") ) | |
228 return parser.failure(null); | |
229 String rtn = toHtml ? "<span style='color: "+color+"'>"+content+"</span>" : content; | |
230 return parser.success(rtn); | |
231 } | |
232 | |
637
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
233 private String parseSize() throws LuanException { |
585 | 234 parser.begin(); |
235 if( !parser.matchIgnoreCase("[size=") ) | |
236 return parser.failure(null); | |
237 int start = parser.currentIndex(); | |
238 while( parser.match('.') || parser.inCharRange('0','9') ); | |
239 String size = parser.textFrom(start); | |
240 if( !parser.match(']') ) | |
241 return parser.failure(null); | |
242 String content = parseWellFormed(); | |
243 if( !parser.matchIgnoreCase("[/size]") ) | |
244 return parser.failure(null); | |
245 String rtn = toHtml ? "<span style='font-size: "+size+"em'>"+content+"</span>" : content; | |
246 return parser.success(rtn); | |
247 } | |
248 | |
249 private String parseYouTube() { | |
250 parser.begin(); | |
251 if( !parser.matchIgnoreCase("[youtube]") ) | |
252 return parser.failure(null); | |
253 int start = parser.currentIndex(); | |
254 while( parser.inCharRange('0','9') | |
255 || parser.inCharRange('a','z') | |
256 || parser.inCharRange('A','Z') | |
257 || parser.match('-') | |
258 || parser.match('_') | |
259 ); | |
260 String id = parser.textFrom(start); | |
261 if( id.length()==0 || !parser.matchIgnoreCase("[/youtube]") ) | |
262 return parser.failure(null); | |
263 String rtn = toHtml ? "<iframe width='420' height='315' src='https://www.youtube.com/embed/"+id+"' frameborder='0' allowfullscreen></iframe>" : ""; | |
264 return parser.success(rtn); | |
265 } | |
266 | |
637
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
267 private String quote(Object... args) throws LuanException { |
777
1460d297e960
add bbcode to blog example
Franklin Schmidt <fschmidt@gmail.com>
parents:
775
diff
changeset
|
268 if( quoter==null ) |
1460d297e960
add bbcode to blog example
Franklin Schmidt <fschmidt@gmail.com>
parents:
775
diff
changeset
|
269 throw new LuanException("BBCode quoter function not defined"); |
637
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
270 Object obj = quoter.call(luan,args); |
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
271 if( !(obj instanceof String) ) |
646
cdc70de628b5
simplify LuanException
Franklin Schmidt <fschmidt@gmail.com>
parents:
638
diff
changeset
|
272 throw new LuanException("BBCode quoter function returned "+Luan.type(obj)+" but string required"); |
637
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
273 return (String)obj; |
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
274 } |
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
275 |
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
276 private String parseQuote1() throws LuanException { |
585 | 277 parser.begin(); |
278 if( !parser.matchIgnoreCase("[quote]") ) | |
279 return parser.failure(null); | |
280 String content = parseWellFormed(); | |
281 if( !parser.matchIgnoreCase("[/quote]") ) | |
282 return parser.failure(null); | |
637
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
283 String rtn = quote(content); |
585 | 284 return parser.success(rtn); |
285 } | |
286 | |
637
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
287 private String parseQuote2() throws LuanException { |
585 | 288 parser.begin(); |
289 if( !parser.matchIgnoreCase("[quote=") ) | |
290 return parser.failure(null); | |
637
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
291 List args = new ArrayList(); |
585 | 292 int start = parser.currentIndex(); |
293 while( parser.noneOf("[];") ); | |
294 String name = parser.textFrom(start).trim(); | |
295 if( name.length() == 0 ) | |
296 return parser.failure(null); | |
637
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
297 args.add(name); |
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
298 while( parser.match(';') ) { |
585 | 299 start = parser.currentIndex(); |
637
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
300 while( parser.noneOf("[];'") ); |
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
301 String src = parser.textFrom(start).trim(); |
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
302 args.add(src); |
585 | 303 } |
304 if( !parser.match(']') ) | |
305 return parser.failure(null); | |
306 String content = parseWellFormed(); | |
637
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
307 args.add(0,content); |
585 | 308 if( !parser.matchIgnoreCase("[/quote]") ) |
309 return parser.failure(null); | |
637
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
310 String rtn = quote(args.toArray()); |
6ea90dc10375
bbcode parser now takes a quoter function
Franklin Schmidt <fschmidt@gmail.com>
parents:
588
diff
changeset
|
311 return parser.success(rtn); |
585 | 312 } |
313 | |
314 } |