Mercurial > hg > tema
view src/kryshen/tema/TemplateParser.java @ 0:1d2fe61a3a62 release_0_1
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 wrap: on
line source
/* * Copyright (C) 2005, 2006 Mikhail A. Kryshen * * $Id: TemplateParser.java,v 1.1.1.1 2006/05/16 14:04:09 mikhail Exp $ */ package kryshen.tema; import java.io.*; import java.util.*; /** * Parser for DbReader templates. * * @author Mikhail A. Kryshen */ public class TemplateParser { static final String SUPER = "SUPER."; /* Brackets. */ static final char[] BR_LEFT = {'<', '['}; static final char[] BR_RIGHT = {'>', ']'}; static final char BR_IN = '%'; /* Separators. */ static final char[] REC_DATA_SEPARATORS = {':'}; static final char[] NONREC_DATA_SEPARATORS = {'\\', '`'}; static final char[] LIST_SEPARATORS = {' ', '\t', '\r', '\n'}; static enum FunctionData { SUBFUNCTION, RECURSIVE, NONRECURSIVE; }; static enum Terminator { EOF, BRACKET, SEPARATOR; }; static class Result { Terminator terminator; int substitutions; /** No text had been parsed. */ boolean empty; Result(Terminator terminator, int substitutions, boolean empty) { this.terminator = terminator; this.substitutions = substitutions; this.empty = empty; } Result() { this(null, 0, true); } }; private Map<String, Function> functions = new HashMap<String, Function>(); private Map<String, Object> variables = new HashMap<String, Object>(); private TemplateParser superParser; private int termBracket = -1; public TemplateParser() { this(null); } public TemplateParser(TemplateParser superParser) { this.superParser = superParser; Functions.registerAllFunctions(this); } public void registerFunction(Function f) { functions.put(f.name, f); } public int parse(Reader in, Writer out) throws IOException, TemplateException { return parse(in, out, true, null, null).substitutions; } /** * Parse template. * * @param in Reader to read template data. * @param out Writer to write processed data. * @param recursive enables recursive processing. * @param separators characters which terminate parsing block. * @param leading characters to ignore at the beginning of the block. */ Result parse(Reader in, Writer out, boolean recursive, char[] separators, char[] leading) throws IOException, TemplateException { Result result = new Result(); int lc = -1; while (true) { int c = in.read(); if (leading != null && isSeparator(c, leading)) continue; else leading = null; boolean leftBracket = false; int index; for (index = 0; index < BR_LEFT.length; index++) { if (lc == BR_LEFT[index]) { leftBracket = true; break; } } if (recursive && leftBracket && c == BR_IN) { lc = -1; int tb = termBracket; termBracket = BR_RIGHT[index]; result.substitutions += parseFunction(in, out); termBracket = tb; } else if (lc == BR_IN && c == termBracket) { lc = -1; result.terminator = Terminator.BRACKET; break; } else { if (lc >= 0) out.write(lc); lc = c; } if (c < 0) { result.terminator = Terminator.EOF; break; } else if (separators != null && isSeparator(c, separators)) { result.terminator = Terminator.SEPARATOR; break; } result.empty = false; } return result; } int parseVariable(String name, Writer out) throws IOException, TemplateException { Object ovalue = getValue(name); if (ovalue == null) return 0; String svalue = ovalue.toString(); if (svalue == null || svalue.length() == 0) return 0; out.write(svalue); return 1; } boolean isSeparator(int c, char[] separators) { for (char p : separators) { if (c == p) return true; } return false; } int parseFunction(Reader in, Writer out) throws IOException, TemplateException { StringBuffer sb = new StringBuffer(); while (true) { int c = in.read(); if (isSeparator(c, LIST_SEPARATORS)) { return invokeFunction(sb.toString(), FunctionData.SUBFUNCTION, in, out); } else if (isSeparator(c, REC_DATA_SEPARATORS)) { return invokeFunction(sb.toString(), FunctionData.RECURSIVE, in, out); } else if (isSeparator(c, NONREC_DATA_SEPARATORS)) { return invokeFunction(sb.toString(), FunctionData.NONRECURSIVE, in, out); } else if (c < 0) { System.err.println("Error: unexpected end of file."); return 0; } else { sb.append((char)c); } } } private int invokeFunction(String name, FunctionData fd, Reader in, Writer out) throws IOException, TemplateException { FunctionDataParser fdp = new FunctionDataParser(this, fd, in); if ("".equals(name)) { return fdp.parseData(out); } Function f = getFunction(name); if (f == null) { throw new TemplateException("Unknown function: " + name); } int r = f.invoke(fdp, out); if (fdp.hasMoreData()) { /* Skip remaining function data. */ fdp.parseData(new Writer() { public void close() {} public void flush() {} public void write(char[] cbuf, int off, int len) {} }); } return r; } Function getFunction(String name) throws TemplateException { Function function = functions.get(name); if (function != null) return function; if (superParser != null) { if (name.startsWith(SUPER)) return superParser.getFunction(name.substring(SUPER.length())); else return superParser.getFunction(name); } return null; } Object getValue(String name) throws TemplateException { Object value = variables.get(name); if (value != null) return value; if (superParser != null) { if (name.startsWith(SUPER)) return superParser.getValue(name.substring(SUPER.length())); else return superParser.getValue(name); } return null; } void setValue(String name, Object value) { variables.put(name, value); } void clearValues() { variables.clear(); } // TEST public static void main(String[] args) throws IOException, TemplateException { TemplateParser p = new TemplateParser(); FileReader in = new FileReader("parser.in"); FileWriter out = new FileWriter("parser.out"); p.parse(in, out); in.close(); out.close(); } }