001: /**
002: * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE, version 2.1, dated February 1999.
003: *
004: * This program is free software; you can redistribute it and/or modify
005: * it under the terms of the latest version of the GNU Lesser General
006: * Public License as published by the Free Software Foundation;
007: *
008: * This program is distributed in the hope that it will be useful,
009: * but WITHOUT ANY WARRANTY; without even the implied warranty of
010: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
011: * GNU Lesser General Public License for more details.
012: *
013: * You should have received a copy of the GNU Lesser General Public License
014: * along with this program (LICENSE.txt); if not, write to the Free Software
015: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
016: */package org.jamwiki.parser.jflex;
017:
018: import java.util.Stack;
019: import org.jamwiki.parser.ParserOutput;
020: import org.jamwiki.parser.ParserInput;
021: import org.jamwiki.parser.ParserTag;
022: import org.jamwiki.utils.WikiLogger;
023:
024: /**
025: * Abstract class that is extended by the JFlex lexers. This class primarily
026: * contains utility methods useful during parsing.
027: */
028: public abstract class JFlexLexer {
029:
030: private static final WikiLogger logger = WikiLogger
031: .getLogger(JFlexLexer.class.getName());
032:
033: /** Member variable used to keep track of the state history for the lexer. */
034: protected Stack states = new Stack();
035: /** Parser configuration information. */
036: protected ParserInput parserInput = null;
037: /** Parser parsing results. */
038: protected ParserOutput parserOutput = null;
039: /** Parser mode, which provides input to the parser about what steps to take. */
040: protected int mode = JFlexParser.MODE_LAYOUT;
041: /** Stack of currently parsed tag content. */
042: protected Stack tagStack = new Stack();
043:
044: /**
045: * Append content to the current tag in the tag stack.
046: */
047: protected void append(String content) {
048: JFlexTagItem currentTag = (JFlexTagItem) this .tagStack.peek();
049: currentTag.getTagContent().append(content);
050: }
051:
052: /**
053: * Begin a new parser state and store the old state onto the stack.
054: *
055: * @param state The new parsing state that is being entered.
056: */
057: protected void beginState(int state) {
058: // store current state
059: Integer current = new Integer(yystate());
060: states.push(current);
061: // switch to new state
062: yybegin(state);
063: }
064:
065: /**
066: * End processing of a parser state and switch to the previous parser state.
067: */
068: protected void endState() {
069: // revert to previous state
070: if (states.empty()) {
071: logger
072: .warning("Attempt to call endState for an empty stack with text: "
073: + yytext());
074: return;
075: }
076: int next = ((Integer) states.pop()).intValue();
077: yybegin(next);
078: }
079:
080: /**
081: * This method is used to set the ParserOutput field, which is used to retrieve
082: * parsed information from the parser.
083: *
084: * @return Parsed information generated by the parser
085: */
086: public ParserOutput getParserOutput() {
087: return this .parserOutput;
088: }
089:
090: /**
091: * Initialize the parser settings. This functionality should be done
092: * from the constructor, but since JFlex generates code it is not possible
093: * to modify the constructor parameters.
094: *
095: * @param parserInput The ParserInput object containing parser parameters
096: * required for successful parsing.
097: * @param parserOutput The current parsed document. When parsing is done
098: * in multiple stages that output values are also built in stages.
099: * @param mode The parser mode to use when parsing. Mode affects what
100: * type of parsing actions are taken when processing raw text.
101: */
102: public final void init(ParserInput parserInput,
103: ParserOutput parserOutput, int mode) {
104: this .parserInput = parserInput;
105: this .parserOutput = parserOutput;
106: this .mode = mode;
107: }
108:
109: /**
110: * Parse a token using the specified parser tag handler. If an error
111: * occurs during processing then this method will return the raw text
112: * that was passed to it.
113: *
114: * @param raw The raw token text that is to be parsed.
115: * @param parserTag The parser tag handler to use when parsing the token.
116: * @return Returns the parsed text, or if an error occurs returns the raw
117: * text that was passed to this method.
118: */
119: protected String parseToken(String raw, ParserTag parserTag) {
120: try {
121: return parserTag.parse(this .parserInput, this .parserOutput,
122: this .mode, raw);
123: } catch (Throwable t) {
124: logger.info("Unable to parse " + raw, t);
125: return raw;
126: }
127: }
128:
129: /**
130: * Pop a the most recent HTML tag from the lexer stack.
131: */
132: protected JFlexTagItem popTag(String tagClose, boolean trimContent) {
133: if (this .tagStack.size() <= 1) {
134: logger.warning("Attempting to pop the tag stack when size "
135: + this .tagStack.size());
136: this .append(tagClose);
137: return (JFlexTagItem) this .tagStack.peek();
138: }
139: JFlexTagItem currentTag = (JFlexTagItem) this .tagStack.pop();
140: currentTag.setTagClose(tagClose);
141: JFlexTagItem previousTag = (JFlexTagItem) this .tagStack.peek();
142: previousTag.getTagContent().append(
143: currentTag.toString(trimContent));
144: return currentTag;
145: }
146:
147: /**
148: * Pop all tags off of the stack and return a string representation.
149: */
150: protected String popAllTags() {
151: StringBuffer result = new StringBuffer();
152: while (!this .tagStack.empty()) {
153: JFlexTagItem currentTag = (JFlexTagItem) this .tagStack
154: .pop();
155: result.insert(0, currentTag.toString(false));
156: }
157: return result.toString();
158: }
159:
160: /**
161: * Push a new HTML tag onto the lexer stack.
162: */
163: protected void pushTag(String tagOpen) {
164: JFlexTagItem tag = new JFlexTagItem();
165: tag.setTagOpen(tagOpen);
166: this .tagStack.push(tag);
167: }
168:
169: /**
170: * JFlex internal method used to change the lexer state values.
171: */
172: public abstract void yybegin(int newState);
173:
174: /**
175: * JFlex internal method used to parse the next token.
176: */
177: public abstract String yylex() throws Exception;
178:
179: /**
180: * JFlex internal method used to retrieve the current lexer state value.
181: */
182: public abstract int yystate();
183:
184: /**
185: * JFlex internal method used to retrieve the current text matched by the
186: * yylex() method.
187: */
188: public abstract String yytext();
189: }
|