view src/kryshen/tema/FunctionDataParser.java @ 33:b637a4491862

Function data separator could be omitted if the data is empty.
author Mikhail Kryshen <mikhail@kryshen.net>
date Sat, 17 Oct 2009 03:39:07 +0400
parents bdd1c8d6b560
children
line source
1 /*
2 * Copyright 2006-2009 Mikhail Kryshen
3 *
4 * This file is part of Tema.
5 *
6 * Tema is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU Lesser General Public License as
8 * published by the Free Software Foundation, either version 3 of the
9 * License, or (at your option) any later version.
10 *
11 * Tema is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
15 *
16 * You should have received a copy of the
17 * GNU Lesser General Public License along with Tema.
18 * If not, see <http://www.gnu.org/licenses/>.
19 */
21 package kryshen.tema;
23 import java.io.File;
24 import java.io.IOException;
25 import java.io.StringWriter;
26 import java.io.Writer;
27 import java.util.ArrayList;
28 import java.util.List;
29 import kryshen.tema.TemplateParser.DataFormat;
30 import static kryshen.tema.TemplateParser.Terminator;
31 import kryshen.tema.io.CopyWriter;
32 import kryshen.tema.io.NullWriter;
33 import kryshen.tema.io.TemplateReader;
35 /**
36 * Parser for a function data.
37 *
38 * @author Mikhail Kryshen
39 */
40 public class FunctionDataParser {
41 static final char[] ARG_SEPARATORS = TemplateParser.LIST_SEPARATORS;
43 private final TemplateParser tp;
44 private final DataFormat fd;
45 private final TemplateReader in;
46 private final String name;
48 private boolean available = true;
50 private int lastReturnCode = 0;
52 FunctionDataParser(TemplateParser tp, DataFormat fd, TemplateReader in,
53 String name) throws IOException, TemplateException {
54 this.tp = tp;
55 this.fd = fd;
56 this.in = in;
57 this.name = name;
59 // Check for empty function data.
60 checkAvailable();
61 }
63 private void checkAvailable() throws IOException, TemplateException {
64 if (tp.checkCloseBracket(in)) {
65 // Complete parsing the instruction.
66 skipData();
67 }
68 }
70 private int parseData(Writer out, boolean argument, boolean skip)
71 throws IOException, TemplateException {
73 if (!available)
74 throw new TemplateException
75 ("Unexpected end of instruction data.", in);
77 if (fd == DataFormat.EMPTY) {
78 available = false;
79 lastReturnCode = 0;
80 return 0;
81 }
83 DataFormat fd = skip ? this.fd.noInvoke() : this.fd;
85 TemplateParser.Result r;
87 if (fd.subfunction) {
88 r = tp.parse(in, out, fd);
89 } else if (argument) {
90 // Skip duplicate separators before argument.
91 tp.skip(in, ARG_SEPARATORS);
93 r = tp.parse(in, out, fd, ARG_SEPARATORS);
95 // Skip duplicate separators after argument.
96 if (r.terminator == Terminator.SEPARATOR) {
97 tp.skip(in, ARG_SEPARATORS);
98 checkAvailable();
99 }
100 } else {
101 r = tp.parse(in, out, fd, null);
102 }
104 if (r.terminator == Terminator.EOF) {
105 throw new TemplateException
106 ("Unexpected end of instruction data", in);
107 }
109 if (r.terminator != Terminator.SEPARATOR)
110 available = false; // No more function data available.
112 lastReturnCode = r.retCode;
113 return r.retCode;
114 }
116 /**
117 * Parse function data.
118 */
119 public int parseData(Writer out) throws IOException, TemplateException {
120 return parseData(out, false, false);
121 }
123 /**
124 * Skip function data (do not call any functions).
125 */
126 public void skipData() throws IOException, TemplateException {
127 parseData(NullWriter.INSTANCE, false, true);
128 }
130 /**
131 * Get function data as string.
132 */
133 public String getData() throws IOException, TemplateException {
134 StringWriter sw = new StringWriter();
135 parseData(sw);
136 sw.close();
137 return sw.toString();
138 }
140 /**
141 * Parse function data into specified <code>Writer</code>.
142 * Returns copy of the parsed data as string.
143 */
144 public String getData(Writer out) throws IOException, TemplateException {
145 StringWriter sw = new StringWriter();
146 parseData(new CopyWriter(sw, out));
147 sw.close();
148 return sw.toString();
149 }
151 public int parseNextArg(Writer out) throws IOException, TemplateException {
152 return parseData(out, true, false);
153 }
155 public void skipNextArg() throws IOException, TemplateException {
156 parseData(NullWriter.INSTANCE, true, true);
157 }
159 public String getNextArg() throws IOException, TemplateException {
160 StringWriter sw = new StringWriter();
161 parseNextArg(sw);
162 sw.close();
163 return sw.toString();
164 }
166 public List<String> getArgs() throws IOException, TemplateException {
167 List<String> l = new ArrayList<String>();
169 while (available) {
170 l.add(getNextArg());
171 }
173 return l;
174 }
176 public boolean hasMoreData() {
177 return available;
178 }
180 public int getLastReturnCode() {
181 return lastReturnCode;
182 }
184 public TemplateParser getTemplateParser() {
185 return tp;
186 }
188 public Context getContext() {
189 return tp.getContext();
190 }
192 public TemplateReader getTemplateReader() {
193 return in;
194 }
196 public String getName() {
197 return name;
198 }
200 public void warning(String message) {
201 System.err.println(in.getSource() + ":" + (in.getLineNumber() + 1) +
202 ": " + name + ": " + message);
203 }
205 public File createFile(String path) {
206 File file = new File(path);
208 if (file.isAbsolute())
209 return file;
211 File base = tp.getContext().getBaseDirectory();
213 return base.getPath().isEmpty()
214 ? new File(path)
215 : new File(base, path);
216 }
217 }