001: /*
002: * Parser.java February 2006
003: *
004: * Copyright (C) 2006, Niall Gallagher <niallg@users.sf.net>
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation.
009: *
010: * This library is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
013: * GNU Lesser General Public License for more details.
014: *
015: * You should have received a copy of the GNU Lesser General
016: * Public License along with this library; if not, write to the
017: * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
018: * Boston, MA 02111-1307 USA
019: */
020:
021: package simple.page.translate;
022:
023: import simple.util.parse.ParseBuffer;
024:
025: /**
026: * The <code>Parser</code> object is used to digest the tokens emitted
027: * from the lexer. This will delegate the token parsing to objects
028: * implementing the <code>Token</code> class. Each token emitted from
029: * the lexical analysis phase is classified using a classification
030: * object. Once classified a specific token type processes the text.
031: *
032: * @author Niall Gallagher
033: */
034: final class Parser extends ParseBuffer {
035:
036: /**
037: * This is the document definition that is populated via parsing.
038: */
039: private Definition source;
040:
041: /**
042: * This is used to classify the tokens emitted from the lexer.
043: */
044: private Classifier factory;
045:
046: /**
047: * This is used if recursive processing of a token is required.
048: */
049: private Builder builder;
050:
051: /**
052: * Constructor for the <code>Parser</code> object. This requires
053: * the document definition to be constructed as well as the builder
054: * driving the process, the builder is required for the recursive
055: * evaluation of included JSP sources via the include directive.
056: *
057: * @param source this is the document definition to populate
058: * @param builder this is the object that builds the definition
059: */
060: public Parser(Definition source, Builder builder) {
061: this .factory = new Classifier();
062: this .builder = builder;
063: this .source = source;
064: }
065:
066: /**
067: * Each parser implementation must specify the boundaries of the
068: * tokens it is prepared to classify and digest. This implementation
069: * uses the standard JSP tags "<%" and "%>", however it can
070: * just as easily use the PHP tag "<?" and "?>".
071: *
072: * @param lexer this is the lexer that emits the required tokens
073: */
074: public void begin(Lexer lexer) {
075: lexer.match("<%", "%>");
076: }
077:
078: /**
079: * This method is invoked by the lexer and is used to process an
080: * array of characters, which signifies the full text for a token.
081: * The text provided to this method is guaranteed to contain either
082: * a complete token, or plain text which is not a parsable token.
083: *
084: * @param text this contains only a single token or plain text
085: */
086: public void parse(char[] text) {
087: parse(text, 0, text.length);
088: }
089:
090: /**
091: * This method is invoked by the lexer and is used to process an
092: * array of characters, which signifies the full text for a token.
093: * The text provided to this method is guaranteed to contain either
094: * a complete token, or plain text which is not a parsable token.
095: *
096: * @param text this contains only a single token or plain text
097: * @param off this is the offset within the buffer to read from
098: * @param len the number of characters in the buffer to evaluate
099: */
100: public void parse(char[] text, int off, int len) {
101: if (len > 2) {
102: if (text[off] == '<' && text[off + 1] == '%') {
103: if (count > 0) {
104: process(buf, 0, count);
105: clear();
106: }
107: process(text, off, len);
108: len = 0;
109: }
110: }
111: if (len > 0) {
112: append(text, off, len);
113: }
114: }
115:
116: /**
117: * Once a full token has been passed to the parser this method is
118: * invoked to classify and process the token. This requires that
119: * a full token is provided, this unlike the </code>parse</code>
120: * method does not buffer the plain text tokens.
121: *
122: * @param text this contains only a single token or plain text
123: * @param off this is the offset within the buffer to read from
124: * @param len the number of characters in the buffer to evaluate
125: */
126: private void process(char[] text, int off, int len) {
127: String data = new String(text, off, len);
128: Token token = factory.getToken(data);
129:
130: try {
131: token.process(source, builder);
132: } catch (Exception e) {
133: e.printStackTrace();
134: }
135: }
136:
137: /**
138: * Once lexical analysis has finished this method is invoked. This
139: * will force any buffered plain text to be processed so that the
140: * full JSP source is processed and used in the document definition.
141: */
142: public void finish() {
143: if (count > 0) {
144: process(buf, 0, count);
145: }
146: }
147: }
|