E4GLParser.java
// $ANTLR 2.7.7 (20060906): "e4gl.g" -> "E4GLParser.java"$
/*
** Module : E4GLParser.java
** E4GLTokenTypes.java
** E4GLLexer.java
** Abstract : lex and parse E4GL source code (html files)
**
** Copyright (c) 2007-2025, Golden Code Development Corporation.
**
** -#- -I- --Date-- -T- --JPRM-- ----------------Description-----------------
** 001 GES 20070820 NEW @348xx WARNING, THIS IS A GENERATED FILE!!!
** DO NOT EDIT THIS FILE. The original source
** file is e4gl.g!
*/
/*
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU Affero General Public License as
** published by the Free Software Foundation, either version 3 of the
** License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU Affero General Public License for more details.
**
** You may find a copy of the GNU Affero GPL version 3 at the following
** location: https://www.gnu.org/licenses/agpl-3.0.en.html
**
** Additional terms under GNU Affero GPL version 3 section 7:
**
** Under Section 7 of the GNU Affero GPL version 3, the following additional
** terms apply to the works covered under the License. These additional terms
** are non-permissive additional terms allowed under Section 7 of the GNU
** Affero GPL version 3 and may not be removed by you.
**
** 0. Attribution Requirement.
**
** You must preserve all legal notices or author attributions in the covered
** work or Appropriate Legal Notices displayed by works containing the covered
** work. You may not remove from the covered work any author or developer
** credit already included within the covered work.
**
** 1. No License To Use Trademarks.
**
** This license does not grant any license or rights to use the trademarks
** Golden Code, FWD, any Golden Code or FWD logo, or any other trademarks
** of Golden Code Development Corporation. You are not authorized to use the
** name Golden Code, FWD, or the names of any author or contributor, for
** publicity purposes without written authorization.
**
** 2. No Misrepresentation of Affiliation.
**
** You may not represent yourself as Golden Code Development Corporation or FWD.
**
** You may not represent yourself for publicity purposes as associated with
** Golden Code Development Corporation, FWD, or any author or contributor to
** the covered work, without written authorization.
**
** 3. No Misrepresentation of Source or Origin.
**
** You may not represent the covered work as solely your work. All modified
** versions of the covered work must be marked in a reasonable way to make it
** clear that the modified work is not originating from Golden Code Development
** Corporation or FWD. All modified versions must contain the notices of
** attribution required in this license.
*/
package com.goldencode.p2j.e4gl;
import java.io.*;
import java.util.logging.*;
import com.goldencode.ast.*;
import com.goldencode.p2j.convert.*;
import antlr.*;
import antlr.TokenBuffer;
import antlr.TokenStreamException;
import antlr.TokenStreamIOException;
import antlr.ANTLRException;
import antlr.LLkParser;
import antlr.Token;
import antlr.TokenStream;
import antlr.RecognitionException;
import antlr.NoViableAltException;
import antlr.MismatchedTokenException;
import antlr.SemanticException;
import antlr.ParserSharedInputState;
import antlr.collections.impl.BitSet;
/**
* Parses an HTML file that has embedded 4GL (E4GL) source code and acts like
* a filter in writing the result out as a Progress 4GL program. Any pure
* HTML is output as 4GL source code that duplicates this HTML via writes
* to a stream.
* <p>
* This is NOT a general purpose HTML parser. In fact, it is "dumbed down"
* from the pure HTML specification to a subset that is supported by the
* very limited parsing that WebSpeed supports. That parsing ignores certain
* features of HTML encoding that are valid, thus this parser can similarly
* ignore those features.
* <p>
* The WebSpeed product supports 4 types of program:
* <p>
* <ol>
* <li> Static HTML - pure, valid HTML that has no embedded 4GL source
* code
* <li> E4GL - HTML with embedded 4GL source code in sections delineated
* by statement (multi-line arbitrary 4GL code) start/end escapes or
* by expression (a single 4GL expression) start/end escapes
* <li> CGI Wrapper - hand-coded Progress source code that emits HTML
* <li> HTML Mapping - static HTML combined with a separate hard coded 4GL
* procedure that uses a configuration file containing field offsets
* to map data to/from the static HTML (this merging and enhancement
* of the static HTML is done at runtime by the WebSpeed code in
* cooperation with the coded 4GL procedure)
* </ol>
* <p>
* This preprocessor handles cases 1 and 2 above. Cases 3 and 4 do not have
* any embedded 4GL to preprocess so they do not need to run through this
* parser. On first glance, case 1 (static HTML with no E4GL) seems like it
* can be ignored since turning it into 4GL is costly from a runtime
* efficiency perspective. When run through this preprocessor, the output of
* such files is still a 4GL procedure (or include file). Since this procedure
* or include file can be itself included in other E4GL programs, it is
* necessary to convert all static HTML and E4GL code into 4GL source code.
* <p>
* Interestingly, the 4GL source code result of this preprocessor is the same
* as if one had coded a CGI Wrapper (case 3 above) instead of using static
* HTML or E4GL. There is no difference between the 3 cases at runtime, it is
* only a difference in whether this WebSpeed preprocessor is used first.
* <p>
* HTML Mapping (case 4) is not addressed by this preprocessor since the HTML
* involved in that solution is processed at runtime.
* <p>
* The filtering that happens can be customized to match the output of a
* specific E4GL implementation. At this time both WebSpeed and Blue Diamond
* implementations are supported.
* <p>
* This parser is heavily dependent upon the following code:
* <p>
* <ul>
* <li> {@link Options} - stores configuration that can be shared from
* multiple modules
* <li> {@link CompatibilityHelper} - this hides the difference in modes
* between WebSpeed and Blue Diamond
* <li> {@link E4GLPreprocessor} - this provides the external interface
* for the parser
* </ul>
* <p>
* There are 2 external entry points for the parser: {@link #preprocess} and
* {@link #scan_options}.
* <p>
* Parser features:
* <p>
* <ul>
* <li> statement escapes (the "...4GL..." indicates where the embedded
* 4GL code will be found)
* <ul>
* <li> <SCRIPT LANGUAGE="SpeedScript"> ...4GL... </SCRIPT>
* <li> <SCRIPT LANGUAGE="WebSpeed4GL"> ...4GL... </SCRIPT>
* <li> <SCRIPT LANGUAGE="Progress"> ...4GL... </SCRIPT>
* <li> <!--WSS ...4GL... -->
* <li> <!--WS4GL ...4GL... -->
* <li> <?WS> ...4GL... </?WS>
* <li> <SERVER> ...4GL... </SERVER>
* <li> <% ...4GL... %>
* </ul>
* <li> expression escapes (the "...4GL..." indicates where the embedded
* 4GL expression will be found)
* <ul>
* <li> <!--WSE ...4GL... -->
* <li> ` ...4GL... `
* <li> {= ...4GL... =}
* <li> <%= ...4GL... %>
* </ul>
* <li> parsing of a <code>META</code> or <code>WSMETA</code> elements
* with attributes of <code>NAME="wsoptions"</code> or
* <code>HTTP-EQUIV="content-type"</code>; in both cases the
* <code>CONTENT</code> attribute is read with the following options
* being honored
* <ul>
* <li> include
* <li> web-object
* <li> keep-meta-content-type
* <li> content-type
* </ul>
* <li> everything other than the above contructs is treated as raw HTML
* and is output with a line prefix (effectively the same as)
* <code>PUT Stream WebStream UNFORMATTED '</code>) and a line suffix
* <code>~n'.</code> (there are many variations on these depending on
* what is being output and in which order; in additions the actual
* text used is different depending on the compatibility helper that
* is in use, WebSpeed or BlueDiamond)
* <li> raw HTML is converted into 4GL strings and any characters that
* cannot be safely represented in 4GL source code is escaped
* <li> 4GL expressions and statements which have HTML entities encoded
* are decoded into the matching character
* <li> 4GL expressions used in HTML URLs that have the %XX character
* encoding for spaces and other special characters are decoded into
* the matching character (using the 2 hexidecimal digits that follow
* the percent sign)
* </ul>
* <p>
* <b>TODO:</b> before this output can be optimally converted, it is likely
* that the expansions, replacements and other state of the preprocessing
* will need to be recorded by the parser into a hints file. Much of the
* data to be stored will be in the form of a "section definition" which
* stores the start line/column and end line/column of a section of either
* the original source file or of the target file. The following will be
* needed:
* <p>
* <ul>
* <li> original HTML source file name
* <li> any specified wsoptions
* <li> any specified content-type
* <li> include flag
* <li> keep content type flag
* <li> compatibility mode
* <li> for each raw HTML section that was converted to "PUT" statements
* there will be a section definition for both the source and target
* files (this will allow the 4GL source code to be removed and
* replaced by the original raw HTML from the source file should
* the conversion need it)
* <li> a section definition in the target file for the generated header
* <li> a section definition in the target file for the generated footer
* </ul>
*/
public class E4GLParser extends antlr.LLkParser implements E4GLParserTokenTypes
{
/** Logger. */
private static final ConversionStatus LOG = ConversionStatus.get(E4GLParser.class);
/** Newline character to search for for line operations. */
private static char NL = '\n';
/** Configuration values to honor during preprocessing. */
private Options cfg = null;
/** Source for raw input. */
private InputStream in = null;
/** Destination for preprocessed output. */
private PrintStream out = null;
/** Helper to emit headers, footers, comments and other text. */
private CompatibilityHelper hlp = null;
/** Flag to denote that the output is starting a new line. */
private boolean lineBegin = true;
/** Flag to denote that the last output was HTML. */
private boolean wasHtml = true;
/** Flag to denote that the last output was an expression escape close. */
private boolean wasExprClose = false;
/** Flag to denote that the last output was an statement escape close. */
private boolean wasStmtClose = false;
static
{
// by default we search for '\n' which handles both "\n" and "\r\n"
// cases, but if the platform newline is "\r" then we must search for
// '\r' instead
if ("\r".equals(CompatibilityHelper.NEWLINE))
{
NL = '\r';
}
}
/**
* Get the input stream. This is not used internally but is stored here
* to allow the stream to be easily obtained by the user of this class.
*
* @return Source stream.
*/
public InputStream getInput()
{
return in;
}
/**
* Set the input stream. This is not used internally but is stored here
* to allow the stream to be easily obtained by the user of this class.
*
* @param in
* Source stream.
*/
public void setInput(InputStream in)
{
this.in = in;
}
/**
* Close the input stream.
*/
public void closeInput()
{
try
{
if (in != null)
in.close();
}
catch (IOException ioe)
{
// ignore
}
}
/**
* Writes error data to logger, including a full stack trace.
*
* @param re
* The error on which to report.
*/
public void reportError(RecognitionException re)
{
LOG.log(Level.SEVERE, "", re);
}
/**
* Output the given text to the stream while maintaining the new line
* state. If requested, this method will also convert HTML entities into
* the valid characters as they would appear in 4GL source code. This
* occurs based on the <code>cvt</code> parameter. If the type of output
* is <code>html</code>, then any unsafe characters are escaped before
* being output as 4GL code.
* <p>
* This method is highly sensitive to the member state variables that
* are maintained in cooperation with <code>outputOpenComment()</code> and
* <code>outputCloseComment()</code>. Together these 3 methods handle all
* output for the preprocessor.
* <p>
* Based on the current state variables, the parameters and the
* {@link CompatibilityHelper} instance, this method handles all output
* that isn't a start or end element of a statement or expression escape.
* This means that all raw HTML and all (embedded 4GL source) content of
* expression/statement escapes is handled here.
* <p>
* Of great importance is that each line of output is started and ended
* with the proper text (in HTML mode). Likewise, when shifting into and
* out of expression and statement escapes, any raw HTML must be properly
* terminated and resumed as needed. Some deferred suffix processing of
* end elements for statement and expression escapes is handled here where
* the following content is known such that the variance in results
* can be determined.
*
* @param txt
* Contents to write to the stream. Must be non-empty and
* not <code>null</code>.
* @param cvt
* <code>true</code> to force HTML entity conversion before the
* text is output.
* @param html
* <code>true</code> to add end of line and beginning of line
* output around new line characters in HTML. Since this
* preprocessor is converting this HTML into strings that are
* output via streams in the 4GL source, these strings need to
* be augmented at the beginning and end of each line.
*/
private void output(String txt, boolean cvt, boolean html)
{
int last = txt.length() - 1;
if (last == -1)
return;
txt = cvt ? hlp.entityConvert(txt) : txt;
// txt = html ? hlp.escapeHTML(txt) : txt;
if (lineBegin)
{
// if we are at the beginning of a line and in HTML mode, then we
// need to output the line prefix
if (html)
{
out.print(hlp.openHTML(true));
}
// clear the counter, since we are doing output
lineBegin = false;
}
else
{
// check if we just exited an expression escape
if (wasExprClose)
{
if (html && txt.indexOf(NL) != 0)
{
// re-open our string for raw HTML output
out.print(hlp.closeExprEscape());
}
else
{
// no more HTML so we need to close the last HTML output
out.print(hlp.closeHTML(false, false));
}
}
else if (wasStmtClose)
{
// HTML text that follows a statement escape needs to be opened
// if there is no newline char as the first character of our text
if (html && txt.indexOf(NL) != 0)
{
out.print(hlp.openHTML(true));
}
}
}
if (html)
{
StringBuilder sb = new StringBuilder();
boolean found = false;
int prev = 0;
int next = txt.indexOf(NL);
while (next >= 0)
{
if (found)
{
// subsequent time through, act like the lineBegin flag is
// true and output the line prefix
sb.append(hlp.openHTML(true));
}
// if the text to be output ends in a newline, then we need to
// reset the lineBegin flag to ensure that subsequent output will
// honor the fact (if needed by context) that we haven't yet output
// any line prefix; if this newline is in the middle of the text
// there is no need to update the state of this flag since we are
// about to reset its state again before this method returns...
if (next == last)
{
lineBegin = true;
}
// it is possible that there are blank lines and lines with only
// whitespace that are output here, but these can't be dropped
// in case we are inside a PRE block and the whitespace is
// important; put the text and the line suffix and the new line
sb.append(hlp.escapeHTML(txt.substring(prev, next)));
// on the first pass, even though we are outputting HTML now, if
// the newline is the first character and the previous mode was
// not HTML, then we don't output the close HTML text
boolean avoid = (!found && !wasHtml && next == 0);
if (!avoid || found)
sb.append(hlp.closeHTML(true, true));
sb.append(hlp.NEWLINE);
prev = next + 1;
next = txt.indexOf(NL, prev);
// not the first time through
found = true;
}
if (found)
{
// output the rest of the string if there is any
if (prev < txt.length())
{
sb.append(hlp.openHTML(true));
sb.append(hlp.escapeHTML(txt.substring(prev)));
}
// reset our output text to the modified version
txt = sb.toString();
}
else
{
txt = hlp.escapeHTML(txt);
}
}
else
{
// see the above comment regarding why we set this flag and why it
// is only if the last character is a newline
if (txt.lastIndexOf(NL) == last)
{
lineBegin = true;
}
}
out.print(txt);
// clear our indicators, any deferred output is complete
wasExprClose = false;
wasStmtClose = false;
// save state
wasHtml = html;
}
/**
* Comment out the given text of an expression or statement open element
* and output it to the stream.
* <p>
* This method is highly sensitive to the member state variables that
* are maintained in cooperation with <code>output()</code> and
* <code>outputCloseComment()</code>. Together these 3 methods handle all
* output for the preprocessor.
* <p>
* Based on the current state variables, the parameters and the
* {@link CompatibilityHelper} instance, this method handles all output
* that is a start element of a statement of expression escape.
* <p>
* Of great importance is that, when shifting into expression and
* statement escapes, any raw HTML must be properly terminated or
* started as needed. Some deferred suffix processing of end elements
* for statement and expression escapes is handled here where the
* following content is known such that the variance in results
* can be determined.
*
* @param escape
* The token with the text to comment.
* @param expr
* <code>true</code> if this is an expression escape,
* <code>false</code> for a statement escape.
*/
private void outputOpenComment(Token escape, boolean expr)
{
outputOpenComment(escape.getText(), expr);
}
/**
* Comment out the given text of an expression or statement open element
* and output it to the stream.
* <p>
* This method is highly sensitive to the member state variables that
* are maintained in cooperation with <code>output()</code> and
* <code>outputCloseComment()</code>. Together these 3 methods handle all
* output for the preprocessor.
* <p>
* Based on the current state variables, the parameters and the
* {@link CompatibilityHelper} instance, this method handles all output
* that is a start element of a statement of expression escape.
* <p>
* Of great importance is that, when shifting into expression and
* statement escapes, any raw HTML must be properly terminated or
* started as needed. Some deferred suffix processing of end elements
* for statement and expression escapes is handled here where the
* following content is known such that the variance in results
* can be determined.
*
* @param escape
* The text to comment.
* @param expr
* <code>true</code> if this is an expression escape,
* <code>false</code> for a statement escape.
*/
private void outputOpenComment(String escape, boolean expr)
{
String result = generateOpenComment(escape, expr);
if (result != null)
{
out.print(result);
}
}
/**
* Comment out the given text of an expression or statement open element
* and output it to the stream.
* <p>
* This method is highly sensitive to the member state variables that
* are maintained in cooperation with <code>output()</code> and
* <code>outputCloseComment()</code>. Together these 3 methods handle all
* output for the preprocessor.
* <p>
* Based on the current state variables, the parameters and the
* {@link CompatibilityHelper} instance, this method handles all output
* that is a start element of a statement of expression escape.
* <p>
* Of great importance is that, when shifting into expression and
* statement escapes, any raw HTML must be properly terminated or
* started as needed. Some deferred suffix processing of end elements
* for statement and expression escapes is handled here where the
* following content is known such that the variance in results
* can be determined.
*
* @param escape
* The text to comment.
* @param expr
* <code>true</code> if this is an expression escape,
* <code>false</code> for a statement escape.
*
* @return The generated open comment or {@code null} if there is nothing generated.
*/
private String generateOpenComment(String escape, boolean expr)
{
String result = null;
String prefix = "";
if (expr)
{
if (lineBegin)
{
// no content to terminate, but we do need to start the line
prefix = hlp.openHTML(false);
}
else
{
if (wasHtml)
{
// content to terminate before the comment emits
prefix = hlp.openExprEscape();
}
}
}
else
{
// this is a statement escape (nothing to do unless this is in the middle of a line)
if (!lineBegin)
{
if (wasHtml)
{
// there is unterminated content on the line, terminate it properly, but note that it is
// not the end of the line
prefix = hlp.closeHTML(true, false);
}
else
{
if (wasExprClose)
{
// close off the HTML mode BUT there is no content to terminate
prefix = hlp.closeHTML(false, false);
}
}
}
}
if (prefix.length() > 0)
{
result = prefix;
}
// reset our state vars
lineBegin = false;
wasHtml = false;
wasExprClose = false;
wasStmtClose = false;
String cmt = generateComment(escape, expr);
if (cmt != null)
{
result = (result == null) ? cmt : result + cmt;
}
return result;
}
/**
* Comment out the given text of an expression or statement close element
* and output it to the stream.
* <p>
* This method is highly sensitive to the member state variables that
* are maintained in cooperation with <code>output()</code> and
* <code>outputOpenComment()</code>. Together these 3 methods handle all
* output for the preprocessor.
* <p>
* Based on the current state variables, the parameters and the
* {@link CompatibilityHelper} instance, this method handles all output
* that is an end element of a statement of expression escape.
* <p>
* Of great importance is that, when shifting into and out of expression
* and statement escapes, any raw HTML must be properly
* resumed and terminated as needed. Some suffix processing of end elements
* for statement and expression escapes is also deferred to the
* <code>output()</code> and <code>outputOpenComment()</code> methods
* where the following content is known such that the variance in results
* can be determined.
*
* @param escape
* The token with the text to comment.
* @param expr
* <code>true</code> if this is an expression escape,
* <code>false</code> for a statement escape.
*/
private void outputCloseComment(Token escape, boolean expr)
{
outputCloseComment(escape.getText(), expr);
}
/**
* Comment out the given text of an expression or statement close element
* and output it to the stream.
* <p>
* This method is highly sensitive to the member state variables that
* are maintained in cooperation with <code>output()</code> and
* <code>outputOpenComment()</code>. Together these 3 methods handle all
* output for the preprocessor.
* <p>
* Based on the current state variables, the parameters and the
* {@link CompatibilityHelper} instance, this method handles all output
* that is an end element of a statement of expression escape.
* <p>
* Of great importance is that, when shifting into and out of expression
* and statement escapes, any raw HTML must be properly
* resumed and terminated as needed. Some suffix processing of end elements
* for statement and expression escapes is also deferred to the
* <code>output()</code> and <code>outputOpenComment()</code> methods
* where the following content is known such that the variance in results
* can be determined.
*
* @param escape
* The text to comment.
* @param expr
* <code>true</code> if this is an expression escape,
* <code>false</code> for a statement escape.
*/
private void outputCloseComment(String escape, boolean expr)
{
String cmt = generateCloseComment(escape, expr);
if (cmt != null)
{
out.print(cmt);
}
}
/**
* Comment out the given text of an expression or statement close element
* and return it.
* <p>
* This method is highly sensitive to the member state variables that
* are maintained in cooperation with <code>output()</code> and
* <code>generateOpenComment()</code>. Together these 3 methods handle all
* state management for the preprocessor.
* <p>
* Based on the current state variables, the parameters and the
* {@link CompatibilityHelper} instance, this method generates all text
* that is an end element of a statement of expression escape.
* <p>
* Of great importance is that, when shifting into and out of expression
* and statement escapes, any raw HTML must be properly
* resumed and terminated as needed. Some suffix processing of end elements
* for statement and expression escapes is also deferred to the
* <code>output()</code> and <code>generateOpenComment()</code> methods
* where the following content is known such that the variance in results
* can be determined.
*
* @param escape
* The text to comment.
* @param expr
* <code>true</code> if this is an expression escape,
* <code>false</code> for a statement escape.
*/
private String generateCloseComment(String escape, boolean expr)
{
// reset our state vars
lineBegin = false;
wasHtml = false;
// remember that we just exited an expression or statement escape so
// that following output can terminate the stream output or start
// another string of raw HTML, depending on the context
wasExprClose = expr;
wasStmtClose = !expr;
return generateComment(escape, expr);
}
/**
* Generate a comment out the given text of an escape and return it. The compatibility helper will be used
* to create the open and close comment text. The compatibility helper may also specify that the escape is
* to be silently dropped, in which case no text will be generated.
*
* @param escape
* The text to comment.
* @param expr
* <code>true</code> if this is an expression escape,
* <code>false</code> for a statement escape.
*
* @return The generated comment text or {@code null} if no text was generated.
*/
private String generateComment(String escape, boolean expr)
{
String open = hlp.openComment(expr);
// only output if the comment text is non-null, otherwise silently eat the escape
return (open != null) ? String.format("%s%s%s", open, escape, hlp.closeComment(expr)) : null;
}
/**
* Get the text of the token unless it is of type <code>ENCODED_CHAR</code>
* in which case the contents will be converted from the '%XX' form into
* the hexidecimal character that is being encoded.
*
* @param next
* The token to potentially decode.
*
* @return The text of the token or its encoded character as text.
*/
private String getTokenText(Token next)
{
String txt = next.getText();
if (next.getType() == ENCODED_CHAR)
{
char encoded = (char) Integer.parseInt(txt.substring(1, 3), 16);
txt = Character.toString(encoded);
}
return txt;
}
protected E4GLParser(TokenBuffer tokenBuf, int k) {
super(tokenBuf,k);
tokenNames = _tokenNames;
}
public E4GLParser(TokenBuffer tokenBuf) {
this(tokenBuf,2);
}
protected E4GLParser(TokenStream lexer, int k) {
super(lexer,k);
tokenNames = _tokenNames;
}
public E4GLParser(TokenStream lexer) {
this(lexer,2);
}
public E4GLParser(ParserSharedInputState state) {
super(state,2);
tokenNames = _tokenNames;
}
/**
* Top-level entry point that parses the input stream and preprocesses the
* HTML and embedded 4GL into a valid 4GL program. All statement and
* expression escapes are supported by calling a sub-rule for each type.
* This sub-rule will not return until the entire escape has been parsed
* and output. State is maintained such that transitions into and out of
* escapes are prefixed or suffixed with the proper text. In some cases,
* the suffix cannot be determined until following output is parsed, in which
* case that suffix processing is deferred via member state variables.
* <p>
* Uses the following expression escape rules:
* <p>
* <ul>
* <li> {@link #backtick_escape}
* <li> {@link #percent_eq_escape}
* <li> {@link #curly_escape}
* <li> {@link #wse_escape}
* </ul>
* <p>
* Uses the following statement escape rules:
* <p>
* <ul>
* <li> {@link #script_escape}
* <li> {@link #question_escape}
* <li> {@link #percent_escape}
* <li> {@link #server_escape}
* <li> {@link #wss_escape}
* </ul>
* <p>
* This rule also processes the {@link #meta_tag} rule in the case where
* <code>keep-meta-content-type</code> is not set as an option. In this
* case, a <code>META</code> or <code>WSMETA</code> element with an attribute
* of <code>HTTP-EQUIV</code> set to <code>CONTENT-TYPE</code> will be
* removed from the output stream using comments. Anything else will be
* passed through a raw HTML.
* <p>
* Anything that is not handled by one of the above listed rules is considered
* raw HTML and is output with little regard to the content. The exceptions to
* this include newline processing (since the beginning and end of each line
* must have text added) and the proper escaping of certain valid HTML
* characters that cannot be directly included in 4GL programs.
* <p>
* Internally, all of the state management and output processing is
* centralized in the following methods: <code>output()</code>,
* <code>outputOpenComment()</code> and <code>outputCloseComment()</code>.
* <p>
* All rules are peers at this level to ensure that they do not cause
* parser ambiguity.
*
* @param cfg
* Storage container for the options that are found.
*/
public final void preprocess(
Options cfg, PrintStream out
) throws RecognitionException, TokenStreamException {
Token txt = null;
this.cfg = cfg;
this.out = out;
hlp = cfg.getCompatibilityHelper();
boolean httpEquiv = false;
boolean keep = cfg.isKeepContentType();
StringBuilder sb = new StringBuilder();
// print the file header
output(hlp.header(), false, false);
wasHtml = true;
lineBegin = true;
try { // for error handling
{
_loop3:
do {
if ((LA(1)==BACK_TICK) && ((LA(2) >= OPEN_END_TAG && LA(2) <= JUNK))) {
backtick_escape();
}
else if ((LA(1)==OPEN_PCT_EQ) && ((LA(2) >= OPEN_END_TAG && LA(2) <= JUNK))) {
percent_eq_escape();
}
else if ((LA(1)==OPEN_CURLY_EQ) && ((LA(2) >= OPEN_END_TAG && LA(2) <= JUNK))) {
curly_escape();
}
else if ((LA(1)==OPEN_COMMENT) && (LA(2)==WSE)) {
wse_escape();
}
else if ((LA(1)==OPEN_START_TAG) && (LA(2)==SCRIPT)) {
script_escape();
}
else if ((LA(1)==OPEN_QUESTION) && (LA(2)==WSPEED)) {
question_escape();
}
else if ((LA(1)==OPEN_PCT) && ((LA(2) >= OPEN_END_TAG && LA(2) <= JUNK))) {
percent_escape();
}
else if ((LA(1)==OPEN_START_TAG) && (LA(2)==SERVER)) {
server_escape();
}
else if ((LA(1)==OPEN_COMMENT) && (LA(2)==WSS||LA(2)==WS4GL)) {
wss_escape();
}
else if (((LA(1)==OPEN_START_TAG||LA(1)==OPEN_COMMENT) && (LA(2)==META||LA(2)==WSMETA))&&( !keep )) {
httpEquiv=meta_tag(null, sb);
String open = httpEquiv ? hlp.openContentTypeComment() : "";
String close = httpEquiv ? hlp.closeContentTypeComment() : "";
String core = sb.toString();
// are we supposed to remove the entry
if (open.length() > 0)
{
// remove the start and end character from the core buffer,
// which should correspond to the '<' and '>' that must
// always be present
core = core.substring(1, core.length() - 1);
}
output(String.format("%s%s%s", open, core, close), false, true);
}
else if ((((LA(1) >= OPEN_END_TAG && LA(1) <= JUNK)) && (LA(2)==EOF||LA(2)==OPEN_END_TAG||LA(2)==SCRIPT||LA(2)==CLOSE_TAG||LA(2)==OPEN_START_TAG||LA(2)==LANGUAGE||LA(2)==OPEN_QUESTION||LA(2)==WSPEED||LA(2)==CLOSE_QUESTION||LA(2)==OPEN_PCT||LA(2)==CLOSE_PCT||LA(2)==SERVER||LA(2)==OPEN_COMMENT||LA(2)==WSS||LA(2)==WS4GL||LA(2)==CLOSE_COMMENT||LA(2)==BACK_TICK||LA(2)==OPEN_PCT_EQ||LA(2)==OPEN_CURLY_EQ||LA(2)==CLOSE_CURLY_EQ||LA(2)==WSE||LA(2)==META||LA(2)==WSMETA||LA(2)==WS||LA(2)==NAME||LA(2)==HTTP_EQUIV||LA(2)==CONTENT||LA(2)==SYMBOL||LA(2)==EQUALS||LA(2)==DQUOTE||LA(2)==SQUOTE||LA(2)==ENCODED_CHAR||LA(2)==UNKNOWN||LA(2)==CLOSE_TAG_NO_CONTENT||LA(2)==GT||LA(2)==LT||LA(2)==SLASH||LA(2)==PERCENT||LA(2)==EXCLAIM||LA(2)==HYPHEN||LA(2)==UNDERSCORE||LA(2)==DOT||LA(2)==COLON||LA(2)==QUESTION||LA(2)==LEFT_CURLY||LA(2)==RIGHT_CURLY||LA(2)==LETTER||LA(2)==DIGIT||LA(2)==HEX_DIGIT||LA(2)==OTHER||LA(2)==JUNK))&&( LA(1) != EOF )) {
txt = LT(1);
matchNot(EOF);
output(txt.getText(), false, true);
}
else {
break _loop3;
}
} while (true);
}
match(Token.EOF_TYPE);
// print the file footer
output(hlp.footer(), false, false);
}
catch (RecognitionException ex) {
reportError(ex);
recover(ex,_tokenSet_0);
}
}
/**
* Match a starting <code>BACK_TICK</code>, arbitrary 4GL expression text and
* a closing <code>BACK_TICK</code>.
*/
public final void backtick_escape() throws RecognitionException, TokenStreamException {
Token bt1 = null;
Token txt = null;
Token bt2 = null;
StringBuilder sb = new StringBuilder();
try { // for error handling
bt1 = LT(1);
match(BACK_TICK);
// comment out the open text
String open = generateOpenComment(bt1.getText(), true);
if (open != null)
{
out.print(open);
}
{
_loop25:
do {
if ((LA(1)==OPEN_END_TAG||LA(1)==SCRIPT||LA(1)==CLOSE_TAG||LA(1)==OPEN_START_TAG||LA(1)==LANGUAGE||LA(1)==OPEN_QUESTION||LA(1)==WSPEED||LA(1)==CLOSE_QUESTION||LA(1)==OPEN_PCT||LA(1)==CLOSE_PCT||LA(1)==SERVER||LA(1)==OPEN_COMMENT||LA(1)==WSS||LA(1)==WS4GL||LA(1)==CLOSE_COMMENT||LA(1)==OPEN_PCT_EQ||LA(1)==OPEN_CURLY_EQ||LA(1)==CLOSE_CURLY_EQ||LA(1)==WSE||LA(1)==META||LA(1)==WSMETA||LA(1)==WS||LA(1)==NAME||LA(1)==HTTP_EQUIV||LA(1)==CONTENT||LA(1)==SYMBOL||LA(1)==EQUALS||LA(1)==DQUOTE||LA(1)==SQUOTE||LA(1)==ENCODED_CHAR||LA(1)==UNKNOWN||LA(1)==CLOSE_TAG_NO_CONTENT||LA(1)==GT||LA(1)==LT||LA(1)==SLASH||LA(1)==PERCENT||LA(1)==EXCLAIM||LA(1)==HYPHEN||LA(1)==UNDERSCORE||LA(1)==DOT||LA(1)==COLON||LA(1)==QUESTION||LA(1)==LEFT_CURLY||LA(1)==RIGHT_CURLY||LA(1)==LETTER||LA(1)==DIGIT||LA(1)==HEX_DIGIT||LA(1)==OTHER||LA(1)==JUNK)) {
txt = LT(1);
matchNot(BACK_TICK);
sb.append(getTokenText(txt));
}
else {
break _loop25;
}
} while (true);
}
output(sb.toString(), true, false);
bt2 = LT(1);
match(BACK_TICK);
// comment out the close text
String close = generateCloseComment(bt2.getText(), true);
if (close != null)
{
out.print(close);
}
}
catch (RecognitionException ex) {
reportError(ex);
recover(ex,_tokenSet_1);
}
}
/**
* Match a starting <code>OPEN_PCT_EQ</code>, arbitrary 4GL expression text
* and a closing <code>CLOSE_PCT</code>.
*/
public final void percent_eq_escape() throws RecognitionException, TokenStreamException {
Token op = null;
Token txt = null;
Token cp = null;
StringBuilder sb = new StringBuilder();
try { // for error handling
op = LT(1);
match(OPEN_PCT_EQ);
// comment out the open text
outputOpenComment(op, true);
{
_loop28:
do {
if ((LA(1)==OPEN_END_TAG||LA(1)==SCRIPT||LA(1)==CLOSE_TAG||LA(1)==OPEN_START_TAG||LA(1)==LANGUAGE||LA(1)==OPEN_QUESTION||LA(1)==WSPEED||LA(1)==CLOSE_QUESTION||LA(1)==OPEN_PCT||LA(1)==SERVER||LA(1)==OPEN_COMMENT||LA(1)==WSS||LA(1)==WS4GL||LA(1)==CLOSE_COMMENT||LA(1)==BACK_TICK||LA(1)==OPEN_PCT_EQ||LA(1)==OPEN_CURLY_EQ||LA(1)==CLOSE_CURLY_EQ||LA(1)==WSE||LA(1)==META||LA(1)==WSMETA||LA(1)==WS||LA(1)==NAME||LA(1)==HTTP_EQUIV||LA(1)==CONTENT||LA(1)==SYMBOL||LA(1)==EQUALS||LA(1)==DQUOTE||LA(1)==SQUOTE||LA(1)==ENCODED_CHAR||LA(1)==UNKNOWN||LA(1)==CLOSE_TAG_NO_CONTENT||LA(1)==GT||LA(1)==LT||LA(1)==SLASH||LA(1)==PERCENT||LA(1)==EXCLAIM||LA(1)==HYPHEN||LA(1)==UNDERSCORE||LA(1)==DOT||LA(1)==COLON||LA(1)==QUESTION||LA(1)==LEFT_CURLY||LA(1)==RIGHT_CURLY||LA(1)==LETTER||LA(1)==DIGIT||LA(1)==HEX_DIGIT||LA(1)==OTHER||LA(1)==JUNK)) {
txt = LT(1);
matchNot(CLOSE_PCT);
sb.append(getTokenText(txt));
}
else {
break _loop28;
}
} while (true);
}
output(sb.toString(), true, false);
cp = LT(1);
match(CLOSE_PCT);
// comment out the close text
outputCloseComment(cp, true);
}
catch (RecognitionException ex) {
reportError(ex);
recover(ex,_tokenSet_1);
}
}
/**
* Match a starting <code>OPEN_CURLY_EQ</code>, arbitrary 4GL expression text
* and a closing <code>CLOSE_CURLY_EQ</code>.
*/
public final void curly_escape() throws RecognitionException, TokenStreamException {
Token oc = null;
Token txt = null;
Token cc = null;
StringBuilder sb = new StringBuilder();
try { // for error handling
oc = LT(1);
match(OPEN_CURLY_EQ);
// comment out the open text
outputOpenComment(oc, true);
{
_loop31:
do {
if ((LA(1)==OPEN_END_TAG||LA(1)==SCRIPT||LA(1)==CLOSE_TAG||LA(1)==OPEN_START_TAG||LA(1)==LANGUAGE||LA(1)==OPEN_QUESTION||LA(1)==WSPEED||LA(1)==CLOSE_QUESTION||LA(1)==OPEN_PCT||LA(1)==CLOSE_PCT||LA(1)==SERVER||LA(1)==OPEN_COMMENT||LA(1)==WSS||LA(1)==WS4GL||LA(1)==CLOSE_COMMENT||LA(1)==BACK_TICK||LA(1)==OPEN_PCT_EQ||LA(1)==OPEN_CURLY_EQ||LA(1)==WSE||LA(1)==META||LA(1)==WSMETA||LA(1)==WS||LA(1)==NAME||LA(1)==HTTP_EQUIV||LA(1)==CONTENT||LA(1)==SYMBOL||LA(1)==EQUALS||LA(1)==DQUOTE||LA(1)==SQUOTE||LA(1)==ENCODED_CHAR||LA(1)==UNKNOWN||LA(1)==CLOSE_TAG_NO_CONTENT||LA(1)==GT||LA(1)==LT||LA(1)==SLASH||LA(1)==PERCENT||LA(1)==EXCLAIM||LA(1)==HYPHEN||LA(1)==UNDERSCORE||LA(1)==DOT||LA(1)==COLON||LA(1)==QUESTION||LA(1)==LEFT_CURLY||LA(1)==RIGHT_CURLY||LA(1)==LETTER||LA(1)==DIGIT||LA(1)==HEX_DIGIT||LA(1)==OTHER||LA(1)==JUNK)) {
txt = LT(1);
matchNot(CLOSE_CURLY_EQ);
sb.append(getTokenText(txt));
}
else {
break _loop31;
}
} while (true);
}
output(sb.toString(), true, false);
cc = LT(1);
match(CLOSE_CURLY_EQ);
// comment out the close text
outputCloseComment(cc, true);
}
catch (RecognitionException ex) {
reportError(ex);
recover(ex,_tokenSet_1);
}
}
/**
* Match a starting <code>OPEN_COMMENT WSE</code>, arbitrary 4GL expression
* text and a closing <code>CLOSE_COMMENT</code>.
*/
public final void wse_escape() throws RecognitionException, TokenStreamException {
Token ow = null;
Token w = null;
Token txt = null;
Token cc = null;
StringBuilder sb = new StringBuilder();
try { // for error handling
{
ow = LT(1);
match(OPEN_COMMENT);
w = LT(1);
match(WSE);
}
// put the text back together as if it was a single token
ow.setText(String.format("%s%s", ow.getText(), w.getText()));
// comment out the open text
outputOpenComment(ow, true);
{
_loop35:
do {
if ((LA(1)==OPEN_END_TAG||LA(1)==SCRIPT||LA(1)==CLOSE_TAG||LA(1)==OPEN_START_TAG||LA(1)==LANGUAGE||LA(1)==OPEN_QUESTION||LA(1)==WSPEED||LA(1)==CLOSE_QUESTION||LA(1)==OPEN_PCT||LA(1)==CLOSE_PCT||LA(1)==SERVER||LA(1)==OPEN_COMMENT||LA(1)==WSS||LA(1)==WS4GL||LA(1)==BACK_TICK||LA(1)==OPEN_PCT_EQ||LA(1)==OPEN_CURLY_EQ||LA(1)==CLOSE_CURLY_EQ||LA(1)==WSE||LA(1)==META||LA(1)==WSMETA||LA(1)==WS||LA(1)==NAME||LA(1)==HTTP_EQUIV||LA(1)==CONTENT||LA(1)==SYMBOL||LA(1)==EQUALS||LA(1)==DQUOTE||LA(1)==SQUOTE||LA(1)==ENCODED_CHAR||LA(1)==UNKNOWN||LA(1)==CLOSE_TAG_NO_CONTENT||LA(1)==GT||LA(1)==LT||LA(1)==SLASH||LA(1)==PERCENT||LA(1)==EXCLAIM||LA(1)==HYPHEN||LA(1)==UNDERSCORE||LA(1)==DOT||LA(1)==COLON||LA(1)==QUESTION||LA(1)==LEFT_CURLY||LA(1)==RIGHT_CURLY||LA(1)==LETTER||LA(1)==DIGIT||LA(1)==HEX_DIGIT||LA(1)==OTHER||LA(1)==JUNK)) {
txt = LT(1);
matchNot(CLOSE_COMMENT);
sb.append(getTokenText(txt));
}
else {
break _loop35;
}
} while (true);
}
output(sb.toString(), true, false);
cc = LT(1);
match(CLOSE_COMMENT);
// comment out the close text
outputCloseComment(cc, true);
}
catch (RecognitionException ex) {
reportError(ex);
recover(ex,_tokenSet_1);
}
}
/**
* Match a starting <code>OPEN_START_TAG SCRIPT</code>, arbitrary
* 4GL statement text and then <code>CLOSE_QUESTION WSPEED CLOSE_TAG</code>.
*/
public final void script_escape() throws RecognitionException, TokenStreamException {
Token txt = null;
Token oe = null;
Token s = null;
Token ct = null;
StringBuilder sb = new StringBuilder();
boolean e4gl = false;
try { // for error handling
e4gl=script_tag(sb);
if (e4gl)
{
outputOpenComment(sb.toString(), false);
}
else
{
output(sb.toString(), false, true);
}
{
_loop6:
do {
if (((LA(1)==BACK_TICK) && ((LA(2) >= OPEN_END_TAG && LA(2) <= JUNK)))&&( !e4gl )) {
backtick_escape();
}
else if ((((LA(1) >= OPEN_END_TAG && LA(1) <= JUNK)) && ((LA(2) >= OPEN_END_TAG && LA(2) <= JUNK)))&&( !(LA(1) == OPEN_END_TAG && LA(2) == SCRIPT) )) {
txt = LT(1);
matchNot(EOF);
output(getTokenText(txt), e4gl, !e4gl);
}
else {
break _loop6;
}
} while (true);
}
oe = LT(1);
match(OPEN_END_TAG);
s = LT(1);
match(SCRIPT);
ct = LT(1);
match(CLOSE_TAG);
String combined = String.format("%s%s%s", oe.getText(), s.getText(), ct.getText());
if (e4gl)
{
// comment out the close text
outputCloseComment(combined, false);
}
else
{
// emit as raw HTML
output(combined, false, true);
}
}
catch (RecognitionException ex) {
reportError(ex);
recover(ex,_tokenSet_1);
}
}
/**
* Match a starting <code>OPEN_QUESTION WSPEED CLOSE_TAG</code>, arbitrary
* 4GL statement text and then <code>CLOSE_QUESTION WSPEED CLOSE_TAG</code>.
*/
public final void question_escape() throws RecognitionException, TokenStreamException {
Token oq = null;
Token ws1 = null;
Token ct1 = null;
Token txt = null;
Token cq = null;
Token ws2 = null;
Token ct2 = null;
StringBuilder sb = new StringBuilder();
try { // for error handling
oq = LT(1);
match(OPEN_QUESTION);
ws1 = LT(1);
match(WSPEED);
ct1 = LT(1);
match(CLOSE_TAG);
oq.setText(String.format("%s%s%s",
oq.getText(),
ws1.getText(),
ct1.getText()));
// comment out the open text
outputOpenComment(oq, false);
{
_loop12:
do {
if ((LA(1)==OPEN_END_TAG||LA(1)==SCRIPT||LA(1)==CLOSE_TAG||LA(1)==OPEN_START_TAG||LA(1)==LANGUAGE||LA(1)==OPEN_QUESTION||LA(1)==WSPEED||LA(1)==OPEN_PCT||LA(1)==CLOSE_PCT||LA(1)==SERVER||LA(1)==OPEN_COMMENT||LA(1)==WSS||LA(1)==WS4GL||LA(1)==CLOSE_COMMENT||LA(1)==BACK_TICK||LA(1)==OPEN_PCT_EQ||LA(1)==OPEN_CURLY_EQ||LA(1)==CLOSE_CURLY_EQ||LA(1)==WSE||LA(1)==META||LA(1)==WSMETA||LA(1)==WS||LA(1)==NAME||LA(1)==HTTP_EQUIV||LA(1)==CONTENT||LA(1)==SYMBOL||LA(1)==EQUALS||LA(1)==DQUOTE||LA(1)==SQUOTE||LA(1)==ENCODED_CHAR||LA(1)==UNKNOWN||LA(1)==CLOSE_TAG_NO_CONTENT||LA(1)==GT||LA(1)==LT||LA(1)==SLASH||LA(1)==PERCENT||LA(1)==EXCLAIM||LA(1)==HYPHEN||LA(1)==UNDERSCORE||LA(1)==DOT||LA(1)==COLON||LA(1)==QUESTION||LA(1)==LEFT_CURLY||LA(1)==RIGHT_CURLY||LA(1)==LETTER||LA(1)==DIGIT||LA(1)==HEX_DIGIT||LA(1)==OTHER||LA(1)==JUNK)) {
txt = LT(1);
matchNot(CLOSE_QUESTION);
sb.append(getTokenText(txt));
}
else {
break _loop12;
}
} while (true);
}
output(sb.toString(), true, false);
cq = LT(1);
match(CLOSE_QUESTION);
ws2 = LT(1);
match(WSPEED);
ct2 = LT(1);
match(CLOSE_TAG);
cq.setText(String.format("%s%s%s",
cq.getText(),
ws2.getText(),
ct2.getText()));
// comment out the close text
outputCloseComment(cq, false);
}
catch (RecognitionException ex) {
reportError(ex);
recover(ex,_tokenSet_1);
}
}
/**
* Match a starting <code>OPEN_PCT</code>, arbitrary 4GL statement text
* and then <code>CLOSE_PCT</code>.
*/
public final void percent_escape() throws RecognitionException, TokenStreamException {
Token op = null;
Token txt = null;
Token cp = null;
StringBuilder sb = new StringBuilder();
try { // for error handling
op = LT(1);
match(OPEN_PCT);
// comment out the open text
outputOpenComment(op, false);
{
_loop15:
do {
if ((LA(1)==OPEN_END_TAG||LA(1)==SCRIPT||LA(1)==CLOSE_TAG||LA(1)==OPEN_START_TAG||LA(1)==LANGUAGE||LA(1)==OPEN_QUESTION||LA(1)==WSPEED||LA(1)==CLOSE_QUESTION||LA(1)==OPEN_PCT||LA(1)==SERVER||LA(1)==OPEN_COMMENT||LA(1)==WSS||LA(1)==WS4GL||LA(1)==CLOSE_COMMENT||LA(1)==BACK_TICK||LA(1)==OPEN_PCT_EQ||LA(1)==OPEN_CURLY_EQ||LA(1)==CLOSE_CURLY_EQ||LA(1)==WSE||LA(1)==META||LA(1)==WSMETA||LA(1)==WS||LA(1)==NAME||LA(1)==HTTP_EQUIV||LA(1)==CONTENT||LA(1)==SYMBOL||LA(1)==EQUALS||LA(1)==DQUOTE||LA(1)==SQUOTE||LA(1)==ENCODED_CHAR||LA(1)==UNKNOWN||LA(1)==CLOSE_TAG_NO_CONTENT||LA(1)==GT||LA(1)==LT||LA(1)==SLASH||LA(1)==PERCENT||LA(1)==EXCLAIM||LA(1)==HYPHEN||LA(1)==UNDERSCORE||LA(1)==DOT||LA(1)==COLON||LA(1)==QUESTION||LA(1)==LEFT_CURLY||LA(1)==RIGHT_CURLY||LA(1)==LETTER||LA(1)==DIGIT||LA(1)==HEX_DIGIT||LA(1)==OTHER||LA(1)==JUNK)) {
txt = LT(1);
matchNot(CLOSE_PCT);
sb.append(getTokenText(txt));
}
else {
break _loop15;
}
} while (true);
}
output(sb.toString(), true, false);
cp = LT(1);
match(CLOSE_PCT);
// comment out the close text
outputCloseComment(cp, false);
}
catch (RecognitionException ex) {
reportError(ex);
recover(ex,_tokenSet_1);
}
}
/**
* Match a starting <code>OPEN_START_TAG SERVER CLOSE_TAG</code>, arbitrary
* 4GL statement text and then <code>CLOSE_QUESTION WSPEED CLOSE_TAG</code>.
*/
public final void server_escape() throws RecognitionException, TokenStreamException {
Token ot = null;
Token s1 = null;
Token ct1 = null;
Token txt = null;
Token oe = null;
Token s2 = null;
Token ct2 = null;
StringBuilder sb = new StringBuilder();
try { // for error handling
ot = LT(1);
match(OPEN_START_TAG);
s1 = LT(1);
match(SERVER);
ct1 = LT(1);
match(CLOSE_TAG);
ot.setText(String.format("%s%s%s",
ot.getText(),
s1.getText(),
ct1.getText()));
// comment out the open text
outputOpenComment(ot, false);
{
_loop18:
do {
if (((LA(1) >= SCRIPT && LA(1) <= JUNK))) {
txt = LT(1);
matchNot(OPEN_END_TAG);
sb.append(getTokenText(txt));
}
else {
break _loop18;
}
} while (true);
}
output(sb.toString(), true, false);
oe = LT(1);
match(OPEN_END_TAG);
s2 = LT(1);
match(SERVER);
ct2 = LT(1);
match(CLOSE_TAG);
oe.setText(String.format("%s%s%s",
oe.getText(),
s2.getText(),
ct2.getText()));
// comment out the close text
outputCloseComment(oe, false);
}
catch (RecognitionException ex) {
reportError(ex);
recover(ex,_tokenSet_1);
}
}
/**
* Match a starting <code>OPEN_COMMENT</code> followed by a <code>WSS</code>
* or <code>WS4GL</code>, arbitrary 4GL statement text and then
* <code>CLOSE_COMMENT</code>.
*/
public final void wss_escape() throws RecognitionException, TokenStreamException {
Token oc = null;
Token wss = null;
Token ws4gl = null;
Token txt = null;
Token cc = null;
StringBuilder sb = new StringBuilder();
try { // for error handling
oc = LT(1);
match(OPEN_COMMENT);
{
switch ( LA(1)) {
case WSS:
{
wss = LT(1);
match(WSS);
break;
}
case WS4GL:
{
ws4gl = LT(1);
match(WS4GL);
break;
}
default:
{
throw new NoViableAltException(LT(1), getFilename());
}
}
}
Token word = (wss == null) ? ws4gl : wss;
oc.setText(String.format("%s%s", oc.getText(), word.getText()));
// comment out the open text
outputOpenComment(oc, false);
{
_loop22:
do {
if ((LA(1)==OPEN_END_TAG||LA(1)==SCRIPT||LA(1)==CLOSE_TAG||LA(1)==OPEN_START_TAG||LA(1)==LANGUAGE||LA(1)==OPEN_QUESTION||LA(1)==WSPEED||LA(1)==CLOSE_QUESTION||LA(1)==OPEN_PCT||LA(1)==CLOSE_PCT||LA(1)==SERVER||LA(1)==OPEN_COMMENT||LA(1)==WSS||LA(1)==WS4GL||LA(1)==BACK_TICK||LA(1)==OPEN_PCT_EQ||LA(1)==OPEN_CURLY_EQ||LA(1)==CLOSE_CURLY_EQ||LA(1)==WSE||LA(1)==META||LA(1)==WSMETA||LA(1)==WS||LA(1)==NAME||LA(1)==HTTP_EQUIV||LA(1)==CONTENT||LA(1)==SYMBOL||LA(1)==EQUALS||LA(1)==DQUOTE||LA(1)==SQUOTE||LA(1)==ENCODED_CHAR||LA(1)==UNKNOWN||LA(1)==CLOSE_TAG_NO_CONTENT||LA(1)==GT||LA(1)==LT||LA(1)==SLASH||LA(1)==PERCENT||LA(1)==EXCLAIM||LA(1)==HYPHEN||LA(1)==UNDERSCORE||LA(1)==DOT||LA(1)==COLON||LA(1)==QUESTION||LA(1)==LEFT_CURLY||LA(1)==RIGHT_CURLY||LA(1)==LETTER||LA(1)==DIGIT||LA(1)==HEX_DIGIT||LA(1)==OTHER||LA(1)==JUNK)) {
txt = LT(1);
matchNot(CLOSE_COMMENT);
sb.append(getTokenText(txt));
}
else {
break _loop22;
}
} while (true);
}
output(sb.toString(), true, false);
cc = LT(1);
match(CLOSE_COMMENT);
// comment out the close text
outputCloseComment(cc, false);
}
catch (RecognitionException ex) {
reportError(ex);
recover(ex,_tokenSet_1);
}
}
/**
* Match <code>OPEN_START_TAG META</code> or <code>OPEN_COMMENT WSMETA</code>,
* the following <code>NAME</code> or <code>HTTP_EQUIV</code> and then the
* <code>CONTENT</code> and a closing <code>CLOSE_TAG</code> or
* <code>CLOSE_COMMENT</code>. This parses the meta tag processing and
* may set option values that are embedded in the attributes. This is
* called from {@link #scan_options} and {@link #preprocess}.
*
* @param opts
* The options to update with the found values. If <code>null</code>
* then this rule matches the given text but does not update any
* options even if those attributes are present.
* @param sb
* The buffer in which to accumulate the parsed text. May be
* <code>null</code> to bypass text accumulation.
*
* @return <code>true</code> if the parsed meta tag has an
* <code>HTTP-EQUIV</code> attribute with a value of
* "content-type".
*/
public final boolean meta_tag(
Options opts, StringBuilder sb
) throws RecognitionException, TokenStreamException {
boolean contype;
Token os = null;
Token m = null;
Token oc = null;
Token wm = null;
Token ws = null;
Token n = null;
Token he = null;
Token c = null;
Token s = null;
Token ct = null;
Token cc = null;
boolean wsmeta = false;
boolean wsoptions = false;
String prop = null;
String content = null;
contype = false;
try { // for error handling
{
switch ( LA(1)) {
case OPEN_START_TAG:
{
os = LT(1);
match(OPEN_START_TAG);
m = LT(1);
match(META);
break;
}
case OPEN_COMMENT:
{
oc = LT(1);
match(OPEN_COMMENT);
wm = LT(1);
match(WSMETA);
wsmeta = true;
break;
}
default:
{
throw new NoViableAltException(LT(1), getFilename());
}
}
}
if (sb != null)
{
if (os != null)
{
sb.append(os.getText()).append(m.getText());
}
else
{
sb.append(oc.getText()).append(wm.getText());
}
}
{
_loop42:
do {
switch ( LA(1)) {
case WS:
{
ws = LT(1);
match(WS);
if (sb != null)
{
sb.append(ws.getText());
}
break;
}
case NAME:
{
n = LT(1);
match(NAME);
if (sb != null)
{
sb.append(n.getText());
}
prop=attribute_value(sb);
if ("wsoptions".equalsIgnoreCase(prop))
{
wsoptions = true;
}
break;
}
case HTTP_EQUIV:
{
he = LT(1);
match(HTTP_EQUIV);
if (sb != null)
{
sb.append(he.getText());
}
prop=attribute_value(sb);
if ("content-type".equalsIgnoreCase(prop))
{
contype = true;
}
break;
}
case CONTENT:
{
c = LT(1);
match(CONTENT);
if (sb != null)
{
sb.append(c.getText());
}
content=attribute_value(sb);
break;
}
case SYMBOL:
{
s = LT(1);
match(SYMBOL);
if (sb != null)
{
sb.append(s.getText());
}
prop=attribute_value(sb);
break;
}
default:
{
break _loop42;
}
}
} while (true);
}
{
if (((LA(1)==CLOSE_TAG))&&( !wsmeta )) {
ct = LT(1);
match(CLOSE_TAG);
}
else if ((LA(1)==CLOSE_COMMENT)) {
cc = LT(1);
match(CLOSE_COMMENT);
}
else {
throw new NoViableAltException(LT(1), getFilename());
}
}
if (sb != null)
{
sb.append((ct != null) ? ct.getText() : cc.getText());
}
// only process if there is some content and we are in options
// processing mode
if (content != null && opts != null)
{
// only process specific matches to NAME = WSOPTIONS and
// to HTTP-EQUIV = CONTENT-TYPE, otherwise ignore
if (wsoptions)
{
opts.processWSOptions(content, true);
}
else if (contype)
{
opts.setContentType(content);
}
}
}
catch (RecognitionException ex) {
reportError(ex);
recover(ex,_tokenSet_1);
}
return contype;
}
/**
* Match a starting <code>OPEN_START_TAG SCRIPT</code>, arbitrary
* attributes and then <code>CLOSE_TAG</code>. The attributes will be
* scanned and if a <code>LANGUAGE</code> attribute with a value of
* <code>SpeedScript</code>, <code>WebSpeed4GL</code> or <code>Progress</code>
* is found then this rule will return <code>true</code>. Either way the text
* of all matched tokens will be returned in the given buffer so that the
* calling rule may handle the output however is needed.
*
* @param sb
* Buffer which will contain all text associated with the parsed
* tokens.
*
* @return <code>true</code> if this script element includes a language
* attribute that identifies the content as embedded 4GL.
*/
public final boolean script_tag(
StringBuilder sb
) throws RecognitionException, TokenStreamException {
boolean e4gl;
Token ot = null;
Token s = null;
Token l = null;
Token other = null;
Token ct = null;
String prop = null;
e4gl = false;
try { // for error handling
ot = LT(1);
match(OPEN_START_TAG);
s = LT(1);
match(SCRIPT);
sb.append(ot.getText()).append(s.getText());
{
_loop9:
do {
switch ( LA(1)) {
case LANGUAGE:
{
l = LT(1);
match(LANGUAGE);
sb.append(l.getText());
prop=attribute_value(sb);
if ("speedscript".equalsIgnoreCase(prop) ||
"webspeed4gl".equalsIgnoreCase(prop) ||
"progress".equalsIgnoreCase(prop))
{
e4gl = true;
}
break;
}
case OPEN_END_TAG:
case SCRIPT:
case OPEN_START_TAG:
case OPEN_QUESTION:
case WSPEED:
case CLOSE_QUESTION:
case OPEN_PCT:
case CLOSE_PCT:
case SERVER:
case OPEN_COMMENT:
case WSS:
case WS4GL:
case CLOSE_COMMENT:
case BACK_TICK:
case OPEN_PCT_EQ:
case OPEN_CURLY_EQ:
case CLOSE_CURLY_EQ:
case WSE:
case META:
case WSMETA:
case WS:
case NAME:
case HTTP_EQUIV:
case CONTENT:
case SYMBOL:
case EQUALS:
case DQUOTE:
case SQUOTE:
case ENCODED_CHAR:
case UNKNOWN:
case CLOSE_TAG_NO_CONTENT:
case GT:
case LT:
case SLASH:
case PERCENT:
case EXCLAIM:
case HYPHEN:
case UNDERSCORE:
case DOT:
case COLON:
case QUESTION:
case LEFT_CURLY:
case RIGHT_CURLY:
case LETTER:
case DIGIT:
case HEX_DIGIT:
case OTHER:
case JUNK:
{
other = LT(1);
matchNot(CLOSE_TAG);
sb.append(other.getText());
break;
}
default:
{
break _loop9;
}
}
} while (true);
}
ct = LT(1);
match(CLOSE_TAG);
sb.append(ct.getText());
}
catch (RecognitionException ex) {
reportError(ex);
recover(ex,_tokenSet_2);
}
return e4gl;
}
/**
* Parse the <code>=</code> followed by a <code>SYMBOL</code> or
* <code>STRING</code>. Whitespace on either side of the <code>EQUALS</code>
* is tolerated.
*
* @param sb
* Buffer in which to store all matched text if not
* <code>null</code>.
*
* @return The text of the <code>SYMBOL</code> or <code>STRING</code>.
*/
public final String attribute_value(
StringBuilder sb
) throws RecognitionException, TokenStreamException {
String txt;
Token ws1 = null;
Token eq = null;
Token ws2 = null;
Token s1 = null;
txt = null;
try { // for error handling
{
switch ( LA(1)) {
case WS:
{
ws1 = LT(1);
match(WS);
break;
}
case EQUALS:
{
break;
}
default:
{
throw new NoViableAltException(LT(1), getFilename());
}
}
}
eq = LT(1);
match(EQUALS);
{
switch ( LA(1)) {
case WS:
{
ws2 = LT(1);
match(WS);
break;
}
case SYMBOL:
case DQUOTE:
case SQUOTE:
{
break;
}
default:
{
throw new NoViableAltException(LT(1), getFilename());
}
}
}
{
switch ( LA(1)) {
case SYMBOL:
{
s1 = LT(1);
match(SYMBOL);
break;
}
case DQUOTE:
case SQUOTE:
{
txt=string();
break;
}
default:
{
throw new NoViableAltException(LT(1), getFilename());
}
}
}
if (s1 != null)
txt = s1.getText();
// capture all the text if needed
if (sb != null)
{
if (ws1 != null)
sb.append(ws1.getText());
sb.append(eq.getText());
if (ws2 != null)
sb.append(ws2.getText());
sb.append(txt);
}
if (s1 == null)
{
// remove the enclosing quotes
txt = txt.substring(1, txt.length() - 1);
}
// no need for leading or trailing whitespace
txt = txt.trim();
}
catch (RecognitionException ex) {
reportError(ex);
recover(ex,_tokenSet_2);
}
return txt;
}
/**
* Top-level entry point that parses the input stream to read the E4GL
* options embedded in any <code>META</code> or <code>WSMETA</code> elements.
* <p>
* Uses {@link #meta_tag} to parse the options themselves. Anything else
* is simply ignored until <code>EOF</code>.
*
* @param opts
* Storage container for the options that are found.
*/
public final void scan_options(
Options opts
) throws RecognitionException, TokenStreamException {
try { // for error handling
boolean bogus;
{
_loop38:
do {
if ((LA(1)==OPEN_START_TAG||LA(1)==OPEN_COMMENT) && (LA(2)==META||LA(2)==WSMETA)) {
bogus=meta_tag(opts, null);
}
else if (((LA(1) >= OPEN_END_TAG && LA(1) <= JUNK)) && (LA(2)==EOF||LA(2)==OPEN_END_TAG||LA(2)==SCRIPT||LA(2)==CLOSE_TAG||LA(2)==OPEN_START_TAG||LA(2)==LANGUAGE||LA(2)==OPEN_QUESTION||LA(2)==WSPEED||LA(2)==CLOSE_QUESTION||LA(2)==OPEN_PCT||LA(2)==CLOSE_PCT||LA(2)==SERVER||LA(2)==OPEN_COMMENT||LA(2)==WSS||LA(2)==WS4GL||LA(2)==CLOSE_COMMENT||LA(2)==BACK_TICK||LA(2)==OPEN_PCT_EQ||LA(2)==OPEN_CURLY_EQ||LA(2)==CLOSE_CURLY_EQ||LA(2)==WSE||LA(2)==META||LA(2)==WSMETA||LA(2)==WS||LA(2)==NAME||LA(2)==HTTP_EQUIV||LA(2)==CONTENT||LA(2)==SYMBOL||LA(2)==EQUALS||LA(2)==DQUOTE||LA(2)==SQUOTE||LA(2)==ENCODED_CHAR||LA(2)==UNKNOWN||LA(2)==CLOSE_TAG_NO_CONTENT||LA(2)==GT||LA(2)==LT||LA(2)==SLASH||LA(2)==PERCENT||LA(2)==EXCLAIM||LA(2)==HYPHEN||LA(2)==UNDERSCORE||LA(2)==DOT||LA(2)==COLON||LA(2)==QUESTION||LA(2)==LEFT_CURLY||LA(2)==RIGHT_CURLY||LA(2)==LETTER||LA(2)==DIGIT||LA(2)==HEX_DIGIT||LA(2)==OTHER||LA(2)==JUNK)) {
matchNot(EOF);
}
else {
break _loop38;
}
} while (true);
}
match(Token.EOF_TYPE);
}
catch (RecognitionException ex) {
reportError(ex);
recover(ex,_tokenSet_0);
}
}
/**
* Matches various string types (data delimited by two matching single or
* double quote characters). This is not implemented in the lexer since
* there is no lookahead that can inform the lexer when it needs to match
* paired quotes versus when it is acceptable for the quote characters to
* stand alone. Since both are possible depending on parser context AND
* since there is no reliable way to share state between the parser and
* lexer, it was necessary to move the matching here.
* <p>
* Uses {@link #sstring} and {@link #dstring}.
*
* @return The parsed string text.
*/
public final String string() throws RecognitionException, TokenStreamException {
String txt;
txt = null;
try { // for error handling
switch ( LA(1)) {
case DQUOTE:
{
txt=dstring();
break;
}
case SQUOTE:
{
txt=sstring();
break;
}
default:
{
throw new NoViableAltException(LT(1), getFilename());
}
}
}
catch (RecognitionException ex) {
reportError(ex);
recover(ex,_tokenSet_2);
}
return txt;
}
/**
* Matches any data delimited by two matching double quote characters.
* <p>
* See {@link #string}.
*
* @return The parsed string text.
*/
public final String dstring() throws RecognitionException, TokenStreamException {
String retstr;
Token start = null;
Token txt = null;
Token end = null;
StringBuilder sb = new StringBuilder();
retstr = null;
try { // for error handling
start = LT(1);
match(DQUOTE);
sb.append(start.getText());
{
_loop51:
do {
if ((LA(1)==OPEN_END_TAG||LA(1)==SCRIPT||LA(1)==CLOSE_TAG||LA(1)==OPEN_START_TAG||LA(1)==LANGUAGE||LA(1)==OPEN_QUESTION||LA(1)==WSPEED||LA(1)==CLOSE_QUESTION||LA(1)==OPEN_PCT||LA(1)==CLOSE_PCT||LA(1)==SERVER||LA(1)==OPEN_COMMENT||LA(1)==WSS||LA(1)==WS4GL||LA(1)==CLOSE_COMMENT||LA(1)==BACK_TICK||LA(1)==OPEN_PCT_EQ||LA(1)==OPEN_CURLY_EQ||LA(1)==CLOSE_CURLY_EQ||LA(1)==WSE||LA(1)==META||LA(1)==WSMETA||LA(1)==WS||LA(1)==NAME||LA(1)==HTTP_EQUIV||LA(1)==CONTENT||LA(1)==SYMBOL||LA(1)==EQUALS||LA(1)==SQUOTE||LA(1)==ENCODED_CHAR||LA(1)==UNKNOWN||LA(1)==CLOSE_TAG_NO_CONTENT||LA(1)==GT||LA(1)==LT||LA(1)==SLASH||LA(1)==PERCENT||LA(1)==EXCLAIM||LA(1)==HYPHEN||LA(1)==UNDERSCORE||LA(1)==DOT||LA(1)==COLON||LA(1)==QUESTION||LA(1)==LEFT_CURLY||LA(1)==RIGHT_CURLY||LA(1)==LETTER||LA(1)==DIGIT||LA(1)==HEX_DIGIT||LA(1)==OTHER||LA(1)==JUNK)) {
txt = LT(1);
matchNot(DQUOTE);
sb.append(txt.getText());
}
else {
break _loop51;
}
} while (true);
}
end = LT(1);
match(DQUOTE);
sb.append(start.getText());
retstr = sb.toString();
}
catch (RecognitionException ex) {
reportError(ex);
recover(ex,_tokenSet_2);
}
return retstr;
}
/**
* Matches any data delimited by two matching single quote characters.
* <p>
* See {@link #string}.
*
* @return The parsed string text.
*/
public final String sstring() throws RecognitionException, TokenStreamException {
String retstr;
Token start = null;
Token txt = null;
Token end = null;
StringBuilder sb = new StringBuilder();
retstr = null;
try { // for error handling
start = LT(1);
match(SQUOTE);
sb.append(start.getText());
{
_loop54:
do {
if ((LA(1)==OPEN_END_TAG||LA(1)==SCRIPT||LA(1)==CLOSE_TAG||LA(1)==OPEN_START_TAG||LA(1)==LANGUAGE||LA(1)==OPEN_QUESTION||LA(1)==WSPEED||LA(1)==CLOSE_QUESTION||LA(1)==OPEN_PCT||LA(1)==CLOSE_PCT||LA(1)==SERVER||LA(1)==OPEN_COMMENT||LA(1)==WSS||LA(1)==WS4GL||LA(1)==CLOSE_COMMENT||LA(1)==BACK_TICK||LA(1)==OPEN_PCT_EQ||LA(1)==OPEN_CURLY_EQ||LA(1)==CLOSE_CURLY_EQ||LA(1)==WSE||LA(1)==META||LA(1)==WSMETA||LA(1)==WS||LA(1)==NAME||LA(1)==HTTP_EQUIV||LA(1)==CONTENT||LA(1)==SYMBOL||LA(1)==EQUALS||LA(1)==DQUOTE||LA(1)==ENCODED_CHAR||LA(1)==UNKNOWN||LA(1)==CLOSE_TAG_NO_CONTENT||LA(1)==GT||LA(1)==LT||LA(1)==SLASH||LA(1)==PERCENT||LA(1)==EXCLAIM||LA(1)==HYPHEN||LA(1)==UNDERSCORE||LA(1)==DOT||LA(1)==COLON||LA(1)==QUESTION||LA(1)==LEFT_CURLY||LA(1)==RIGHT_CURLY||LA(1)==LETTER||LA(1)==DIGIT||LA(1)==HEX_DIGIT||LA(1)==OTHER||LA(1)==JUNK)) {
txt = LT(1);
matchNot(SQUOTE);
sb.append(txt.getText());
}
else {
break _loop54;
}
} while (true);
}
end = LT(1);
match(SQUOTE);
sb.append(start.getText());
retstr = sb.toString();
}
catch (RecognitionException ex) {
reportError(ex);
recover(ex,_tokenSet_2);
}
return retstr;
}
public static final String[] _tokenNames = {
"<0>",
"EOF",
"<2>",
"NULL_TREE_LOOKAHEAD",
"OPEN_END_TAG",
"\"script\"",
"CLOSE_TAG",
"OPEN_START_TAG",
"\"language\"",
"OPEN_QUESTION",
"\"ws\"",
"CLOSE_QUESTION",
"OPEN_PCT",
"CLOSE_PCT",
"\"server\"",
"OPEN_COMMENT",
"\"wss\"",
"\"ws4gl\"",
"CLOSE_COMMENT",
"BACK_TICK",
"OPEN_PCT_EQ",
"OPEN_CURLY_EQ",
"CLOSE_CURLY_EQ",
"\"wse\"",
"\"meta\"",
"\"wsmeta\"",
"WS",
"\"name\"",
"\"http-equiv\"",
"\"content\"",
"SYMBOL",
"EQUALS",
"DQUOTE",
"SQUOTE",
"ENCODED_CHAR",
"UNKNOWN",
"CLOSE_TAG_NO_CONTENT",
"GT",
"LT",
"SLASH",
"PERCENT",
"EXCLAIM",
"HYPHEN",
"UNDERSCORE",
"DOT",
"COLON",
"QUESTION",
"LEFT_CURLY",
"RIGHT_CURLY",
"LETTER",
"DIGIT",
"HEX_DIGIT",
"OTHER",
"JUNK"
};
private static final long[] mk_tokenSet_0() {
long[] data = { 2L, 0L};
return data;
}
public static final BitSet _tokenSet_0 = new BitSet(mk_tokenSet_0());
private static final long[] mk_tokenSet_1() {
long[] data = { 18014398509481970L, 0L, 0L, 0L};
return data;
}
public static final BitSet _tokenSet_1 = new BitSet(mk_tokenSet_1());
private static final long[] mk_tokenSet_2() {
long[] data = { 18014398509481968L, 0L, 0L, 0L};
return data;
}
public static final BitSet _tokenSet_2 = new BitSet(mk_tokenSet_2());
}