view src/kryshen/tema/TemplateParser.java @ 0:1d2fe61a3a62

Tema 0.1 (imported from CVS).
author Mikhail Kryshen <mikhail@kryshen.net>
date Tue, 16 May 2006 18:04:09 +0400
parents
children 548a93c24e55
line source
1 /*
2 * Copyright (C) 2005, 2006 Mikhail A. Kryshen
3 *
4 * $Id: TemplateParser.java,v 1.1.1.1 2006/05/16 14:04:09 mikhail Exp $
5 */
7 package kryshen.tema;
9 import java.io.*;
10 import java.util.*;
12 /**
13 * Parser for DbReader templates.
14 *
15 * @author Mikhail A. Kryshen
16 */
17 public class TemplateParser {
18 static final String SUPER = "SUPER.";
20 /* Brackets. */
21 static final char[] BR_LEFT = {'<', '['};
22 static final char[] BR_RIGHT = {'>', ']'};
24 static final char BR_IN = '%';
26 /* Separators. */
27 static final char[] REC_DATA_SEPARATORS = {':'};
28 static final char[] NONREC_DATA_SEPARATORS = {'\\', '`'};
29 static final char[] LIST_SEPARATORS = {' ', '\t', '\r', '\n'};
31 static enum FunctionData {
32 SUBFUNCTION, RECURSIVE, NONRECURSIVE;
33 };
35 static enum Terminator {
36 EOF, BRACKET, SEPARATOR;
37 };
39 static class Result {
40 Terminator terminator;
41 int substitutions;
43 /** No text had been parsed. */
44 boolean empty;
46 Result(Terminator terminator, int substitutions, boolean empty) {
47 this.terminator = terminator;
48 this.substitutions = substitutions;
49 this.empty = empty;
50 }
52 Result() {
53 this(null, 0, true);
54 }
55 };
57 private Map<String, Function> functions = new HashMap<String, Function>();
59 private Map<String, Object> variables = new HashMap<String, Object>();
60 private TemplateParser superParser;
62 private int termBracket = -1;
64 public TemplateParser() {
65 this(null);
66 }
68 public TemplateParser(TemplateParser superParser) {
69 this.superParser = superParser;
71 Functions.registerAllFunctions(this);
72 }
74 public void registerFunction(Function f) {
75 functions.put(f.name, f);
76 }
78 public int parse(Reader in, Writer out)
79 throws IOException, TemplateException {
81 return parse(in, out, true, null, null).substitutions;
82 }
84 /**
85 * Parse template.
86 *
87 * @param in Reader to read template data.
88 * @param out Writer to write processed data.
89 * @param recursive enables recursive processing.
90 * @param separators characters which terminate parsing block.
91 * @param leading characters to ignore at the beginning of the block.
92 */
93 Result parse(Reader in, Writer out, boolean recursive,
94 char[] separators, char[] leading)
95 throws IOException, TemplateException {
97 Result result = new Result();
98 int lc = -1;
100 while (true) {
101 int c = in.read();
103 if (leading != null && isSeparator(c, leading))
104 continue;
105 else
106 leading = null;
108 boolean leftBracket = false;
109 int index;
111 for (index = 0; index < BR_LEFT.length; index++) {
112 if (lc == BR_LEFT[index]) {
113 leftBracket = true;
114 break;
115 }
116 }
118 if (recursive && leftBracket && c == BR_IN) {
120 lc = -1;
121 int tb = termBracket;
122 termBracket = BR_RIGHT[index];
123 result.substitutions += parseFunction(in, out);
124 termBracket = tb;
126 } else if (lc == BR_IN && c == termBracket) {
128 lc = -1;
129 result.terminator = Terminator.BRACKET;
130 break;
132 } else {
134 if (lc >= 0)
135 out.write(lc);
137 lc = c;
138 }
140 if (c < 0) {
141 result.terminator = Terminator.EOF;
142 break;
143 } else if (separators != null && isSeparator(c, separators)) {
144 result.terminator = Terminator.SEPARATOR;
145 break;
146 }
148 result.empty = false;
149 }
151 return result;
152 }
154 int parseVariable(String name, Writer out)
155 throws IOException, TemplateException {
157 Object ovalue = getValue(name);
158 if (ovalue == null)
159 return 0;
161 String svalue = ovalue.toString();
163 if (svalue == null || svalue.length() == 0)
164 return 0;
166 out.write(svalue);
167 return 1;
168 }
170 boolean isSeparator(int c, char[] separators) {
171 for (char p : separators) {
172 if (c == p) return true;
173 }
175 return false;
176 }
178 int parseFunction(Reader in, Writer out)
179 throws IOException, TemplateException {
181 StringBuffer sb = new StringBuffer();
183 while (true) {
184 int c = in.read();
186 if (isSeparator(c, LIST_SEPARATORS)) {
187 return invokeFunction(sb.toString(),
188 FunctionData.SUBFUNCTION,
189 in, out);
190 } else if (isSeparator(c, REC_DATA_SEPARATORS)) {
191 return invokeFunction(sb.toString(),
192 FunctionData.RECURSIVE,
193 in, out);
194 } else if (isSeparator(c, NONREC_DATA_SEPARATORS)) {
195 return invokeFunction(sb.toString(),
196 FunctionData.NONRECURSIVE,
197 in, out);
198 } else if (c < 0) {
199 System.err.println("Error: unexpected end of file.");
200 return 0;
201 } else {
202 sb.append((char)c);
203 }
204 }
205 }
207 private int invokeFunction(String name, FunctionData fd,
208 Reader in, Writer out)
209 throws IOException, TemplateException {
211 FunctionDataParser fdp = new FunctionDataParser(this, fd, in);
213 if ("".equals(name)) {
214 return fdp.parseData(out);
215 }
217 Function f = getFunction(name);
219 if (f == null) {
220 throw new TemplateException("Unknown function: " + name);
221 }
223 int r = f.invoke(fdp, out);
225 if (fdp.hasMoreData()) {
226 /* Skip remaining function data. */
227 fdp.parseData(new Writer() {
228 public void close() {}
229 public void flush() {}
230 public void write(char[] cbuf, int off, int len) {}
231 });
232 }
234 return r;
235 }
237 Function getFunction(String name) throws TemplateException {
238 Function function = functions.get(name);
239 if (function != null) return function;
241 if (superParser != null) {
242 if (name.startsWith(SUPER))
243 return superParser.getFunction(name.substring(SUPER.length()));
244 else
245 return superParser.getFunction(name);
246 }
248 return null;
249 }
251 Object getValue(String name) throws TemplateException {
252 Object value = variables.get(name);
253 if (value != null) return value;
255 if (superParser != null) {
256 if (name.startsWith(SUPER))
257 return superParser.getValue(name.substring(SUPER.length()));
258 else
259 return superParser.getValue(name);
260 }
262 return null;
263 }
265 void setValue(String name, Object value) {
266 variables.put(name, value);
267 }
269 void clearValues() {
270 variables.clear();
271 }
273 // TEST
274 public static void main(String[] args)
275 throws IOException, TemplateException {
277 TemplateParser p = new TemplateParser();
279 FileReader in = new FileReader("parser.in");
280 FileWriter out = new FileWriter("parser.out");
282 p.parse(in, out);
284 in.close();
285 out.close();
286 }
287 }