001: /*
002: * Copyright 2007 Gerd Ziegler (www.gerdziegler.de)
003: * Licensed under the Apache License, Version 2.0 (the "License");
004: * you may not use this file except in compliance with the License.
005: * You may obtain a copy of the License at
006: * http://www.apache.org/licenses/LICENSE-2.0
007: * Unless required by applicable law or agreed to in writing,
008: * software distributed under the License is distributed on an
009: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
010: * either express or implied. See the License for the specific
011: * language governing permissions and limitations under the License.
012: * @author www.gerdziegler.de
013: */
014: package org.ztemplates.actions.expression;
015:
016: import java.util.ArrayList;
017: import java.util.List;
018:
019: import org.apache.log4j.Logger;
020: import org.ztemplates.actions.util.ZFormatUtil;
021:
022: public class ZExpression implements ZTerm {
023: private static Logger log = Logger.getLogger(ZExpression.class);
024:
025: private List<ZTerm> content = new ArrayList<ZTerm>();
026:
027: public ZExpression(String definition) throws ZParserException {
028: if (log.isDebugEnabled()) {
029: log.debug("parsing '" + definition + "'");
030: }
031: String rest = parse(definition);
032:
033: // paranoia
034: if (rest.length() > 0) {
035: throw new ZParserException(rest, "input too long");
036: }
037:
038: // selftest
039: // String definitionTest = toDefinition();
040: // if (!definition.equals(definitionTest))
041: // {
042: // throw new ParserException(definition, "internal error: not parsed
043: // correctly '" + definitionTest + "'");
044: // }
045: }
046:
047: public ZExpression() {
048: }
049:
050: public List<ZTerm> getContent() {
051: return content;
052: }
053:
054: public String parse(String s) throws ZParserException {
055: if (s.length() == 0) {
056: return "";
057: }
058:
059: char c = s.charAt(0);
060: switch (c) {
061: case '/': {
062: ZSlash v = new ZSlash();
063: content.add(v);
064: String rest = v.parse(s);
065: return parse(rest);
066: }
067: case '$': {
068: ZVariable v = new ZVariable();
069: checkLiteral(s, v);
070: content.add(v);
071: String rest = v.parse(s);
072: return parse(rest);
073: }
074: case '*': {
075: ZTail v = new ZTail();
076: checkLiteral(s, v);
077: content.add(v);
078: String rest = v.parse(s);
079: if (rest.length() > 0) {
080: throw new ZParserException(s,
081: "tail *{} must be last in expression");
082: }
083: return "";
084: }
085: case '#': {
086: ZNestedExpression v = new ZNestedExpression();
087: checkLiteral(s, v);
088: content.add(v);
089: String rest = v.parse(s);
090: return parse(rest);
091: }
092: case '[': {
093: ZOptionalExpression v = new ZOptionalExpression();
094: content.add(v);
095: String rest = v.parse(s);
096: return parse(rest);
097: }
098: case ']': {
099: return s;
100: }
101: default: {
102: ZLiteral v = new ZLiteral();
103: content.add(v);
104: String rest = v.parse(s);
105: return parse(rest);
106: }
107: }
108: }
109:
110: private void checkLiteral(String s, ZTerm crt)
111: throws ZParserException {
112: if (content.isEmpty()) {
113: return;
114: }
115: ZTerm last = content.get(content.size() - 1);
116: if (last != null && !(last instanceof ZLiteral)
117: && !(last instanceof ZSlash)) {
118: throw new ZParserException(s, crt
119: + " must be preceded by a literal or slash: "
120: + last);
121: }
122: }
123:
124: public String toString() {
125: return toXml();
126: }
127:
128: public String toXml() {
129: StringBuffer sb = new StringBuffer();
130: toXml(sb, 0);
131: return sb.toString();
132: }
133:
134: public void toXml(StringBuffer sb, int depth) {
135: ZFormatUtil.indent(sb, depth);
136: sb.append("<expression>");
137: for (ZTerm t : content) {
138: t.toXml(sb, depth + 1);
139: }
140: ZFormatUtil.indent(sb, depth);
141: sb.append("</expression>");
142: }
143:
144: public String toDefinition() {
145: StringBuffer sb = new StringBuffer();
146: for (ZTerm t : content) {
147: sb.append(t.toDefinition());
148: }
149: return sb.toString();
150: }
151:
152: }
|