TextParser.java
// $ANTLR 2.7.7 (20060906): "text.g" -> "TextParser.java"$
/*
** Module : TextLexer.java
** TextParser.java
** PreprocTokenTypes.java
** Abstract : This grammar is the top level recognizer of the Progress
** language preprocessor input. It recognizes tabs, nested
** comments, single and double quoted multiline strings and
** the code.
**
** Copyright (c) 2004-2019, Golden Code Development Corporation.
**
** -#- -I- --Date-- -T- --JPRM-- ----------------Description-----------------
** 001 GES 20041116 ADD @18832 WARNING, THIS IS A GENERATED FILE!!!
** DO NOT EDIT THIS FILE. The original source
** file is text.g!
*/
package com.goldencode.p2j.preproc;
import java.io.*;
import java.util.*;
import java.util.logging.*;
import antlr.collections.AST;
import antlr.collections.impl.*;
import antlr.debug.misc.*;
import antlr.*;
import com.goldencode.util.*;
import com.goldencode.p2j.convert.*;
import com.goldencode.p2j.util.*;
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;
/**
* Declares the entry point class of this grammar.
* This grammar takes a Progress source file and starts parsing it
* to a degree necessary for performing the preprocessing only.
* The preprocessing is done on the go without creating an AST tree
* first. This is possible due to a limited amount of transformations
* that has to be done to the input.
* <p>
* The parsing starts when a driving code calls the
* <code>{@link #text()}</code>
* method of this class. The processed output is written to an output
* stream as the parsing progresses. As soon as the parser reaches
* the end of file, the preprocessor is done.
* <p>
* The parser calls the lexer's <code>nextToken</code> method and works
* with the stream of <code>Token</code> objects. So, all the details
* of tokenizations are hidden in the lexer. The lexer, in turn, reads
* its input character by character from an input stream. The input
* stream is an instance of the <code>{@link ClearStream}</code> class
* that hides from the lexer some essential complexity of the preprocessing
* like handling the alternative codings, escape sequences and substitutions
* for braces.
* <p>
* The parser recognizes and properly handles the following constructs:
* <ul>
* <li>regular Progress code on input is copied to output according
* to the conditional generation currently in effect;
* <li>tabs are expanded on output;
* <li>other white spaces are preserved on output;
* <li>Progress language strings and comments are recognized because
* they affect the workings of the preprocessor;
* <li>preprocessor statements are recognized and processed;
* </ul>
* @see TextLexer
* @see BracesParser
* @see BracesLexer
*/
public class TextParser extends antlr.LLkParser implements PreprocTokenTypes
{
/** Logger. */
private static final ConversionStatus LOG = ConversionStatus.get(TextParser.class);
/** Keeps a reference to the shared environment. */
private Environment env = null;
/** Nesting level for text block processing. */
private int nested = 0;
/** Tracks nesting level for conditional preproc directives. */
private int condNesting = 0;
/**
* Constructor. Creates a parser attached to the token stream
* selector taken from the environment. Saves the environment
* for future needs.
*
* @param lexer
* The lexer for this instance.
* @param env
* The shared preprocessor environment.
*/
public TextParser(TokenStream lexer, Environment env)
{
this(lexer);
this.env = env;
this.env.setPsi(this.getInputState());
}
/**
* 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);
}
protected TextParser(TokenBuffer tokenBuf, int k) {
super(tokenBuf,k);
tokenNames = _tokenNames;
}
public TextParser(TokenBuffer tokenBuf) {
this(tokenBuf,2);
}
protected TextParser(TokenStream lexer, int k) {
super(lexer,k);
tokenNames = _tokenNames;
}
public TextParser(TokenStream lexer) {
this(lexer,2);
}
public TextParser(ParserSharedInputState state) {
super(state,2);
tokenNames = _tokenNames;
}
/**
* Matches any interpretable block of text from the Progress source
* file. This can be either the top level source text or any block
* of text following <code>&THEN</code> or <code>&ELSE</code>
* statements when their appropriate preprocessor expressions evaluate
* to those clauses.
*
* @throws antlr.RecognitionException
* @throws antlr.TokenStreamException
* @throws IOException
*/
public final void text() throws RecognitionException, TokenStreamException, IOException {
try { // for error handling
textBlock();
match(Token.EOF_TYPE);
}
catch (RecognitionException ex) {
reportError(ex);
recover(ex,_tokenSet_0);
}
}
/**
* Matches any interpretable block of text from the Progress source
* file. This can be either the top level source text or any block
* of text following <code>&THEN</code> or <code>&ELSE</code>
* statements when their appropriate preprocessor expressions evaluate
* to those clauses.
*
* @throws antlr.RecognitionException
* @throws antlr.TokenStreamException
* @throws IOException
*/
public final void textBlock() throws RecognitionException, TokenStreamException, IOException {
Token t = null;
try { // for error handling
// track our nesting level
nested++;
// cache off the in stmt flag
boolean inStmt = env.isInStatement();
// are we nested? (this can only happen due to an &IF)
if (nested > 1 && inStmt)
{
// disable while here
env.setInStatement(false);
env.clearDeferred();
}
{
_loop5:
do {
if ((_tokenSet_1.member(LA(1))) && (_tokenSet_2.member(LA(2)))) {
ppstatement();
}
else if ((_tokenSet_3.member(LA(1))) && (_tokenSet_2.member(LA(2)))) {
// cache off the in stmt flag (again, at this nested level)
boolean stillInStmt = env.isInStatement();
// are we nested? (this can only happen due to an &IF)
if (nested > 1 && stillInStmt)
{
// disable while here
env.setInStatement(false);
env.clearDeferred();
}
{
t = LT(1);
match(_tokenSet_3);
}
env.print(t.getText());
// need to reset inStatement at bottom of alternative if we
// turned it off at top
if (nested > 1 && stillInStmt)
{
env.setInStatement(true);
}
}
else {
break _loop5;
}
} while (true);
}
// if we are in a nested block
if (nested > 1)
{
// restore our saved state
env.setInStatement(inStmt);
}
// clear our nesting level
nested--;
}
catch (RecognitionException ex) {
reportError(ex);
recover(ex,_tokenSet_2);
}
}
/**
* Matches any Progress preprocessor statement, even mistyped one.
*
* @throws antlr.RecognitionException
* @throws antlr.TokenStreamException
* @throws IOException
*/
public final void ppstatement() throws RecognitionException, TokenStreamException, IOException {
try { // for error handling
// the lexer should already have setInStatement(true) during
// lookahead processing, but this is here as safety code
if (!env.isInStatement())
{
// should never trigger
env.setInStatement(true);
}
{
switch ( LA(1)) {
case AGLOBAL:
{
globdef();
break;
}
case ASCOPED:
{
scopdef();
break;
}
case AUNDEFINE:
{
undefine();
break;
}
case AMESSAGE:
{
message();
break;
}
case ASUSPEND:
case ARESUME:
{
noop();
break;
}
case AIF:
{
aif();
break;
}
case ASTMT:
{
astmt();
break;
}
default:
{
throw new NoViableAltException(LT(1), getFilename());
}
}
}
env.setInStatement(false);
env.clearDeferred();
}
catch (RecognitionException ex) {
reportError(ex);
recover(ex,_tokenSet_2);
}
}
/**
* Matches the <code>&GLOBAL-DEFINE</code> Progress preprocessor statement.
*/
public final void globdef() throws RecognitionException, TokenStreamException, IOException {
try { // for error handling
match(AGLOBAL);
define(true);
}
catch (RecognitionException ex) {
reportError(ex);
recover(ex,_tokenSet_2);
}
}
/**
* Matches the <code>&SCOPED-DEFINE</code> Progress preprocessor statement.
*/
public final void scopdef() throws RecognitionException, TokenStreamException, IOException {
try { // for error handling
match(ASCOPED);
define(false);
}
catch (RecognitionException ex) {
reportError(ex);
recover(ex,_tokenSet_2);
}
}
/**
* Matches <code>&UNDEFINE</code> preprocessor statement and removes
* the first found definition of the preprocessor variable in the nearest
* scope. Contrary to the parsing of {@link #define} which consumes all
* text up to the end of the line, this directive only consumes whitespace
* followed by a single preprocessor name.
*/
public final void undefine() throws RecognitionException, TokenStreamException, IOException {
Token c = null;
String name = null;
int line = 0;
int column = 0;
// after the ppname rule is called, the ClearStream may have already
// popped our scope, so we cache the possible names here so that we can
// check if the name was already removed because the scope was popped;
// this occurs when the UNDEFINE directive is the very last text in
// an include file, which causes the popping to occur before the name
// is parsed here
ScopedSymbolDictionary ssd = env.getSym();
Set<String> poppedNames = ssd.keySet(0);
try { // for error handling
match(AUNDEFINE);
{
int _cnt18=0;
_loop18:
do {
if ((LA(1)==WS)) {
match(WS);
}
else if ((LA(1)==STAR_COMMENT) && (_tokenSet_4.member(LA(2)))) {
c = LT(1);
match(STAR_COMMENT);
env.print(c.getText());
}
else {
if ( _cnt18>=1 ) { break _loop18; } else {throw new NoViableAltException(LT(1), getFilename());}
}
_cnt18++;
} while (true);
}
line = env.getLex().getLine();
column = env.getLex().getColumn();
name=ppname();
// undefine the nearest definition of the symbol, if not defined,
// issue an error message
if (!ssd.deleteSymbol(name) && !poppedNames.contains(name))
{
env.eprint("symbol '" + name + "' not defined.", line, column);
}
}
catch (RecognitionException ex) {
reportError(ex);
recover(ex,_tokenSet_2);
}
}
/**
* Matches <code>&MESSAGE</code> preprocessor statement and prints
* the message text into the error stream without incrementing the errors
* count.
*/
public final void message() throws RecognitionException, TokenStreamException, IOException {
Token c2 = null;
Token rst = null;
Token nl = null;
StringBuffer rest = new StringBuffer();
try { // for error handling
match(AMESSAGE);
{
_loop21:
do {
switch ( LA(1)) {
case STAR_COMMENT:
{
c2 = LT(1);
match(STAR_COMMENT);
env.print(c2.getText());
break;
}
case TAB:
case WS:
case COMMENT:
case COMM_OPEN:
case CODE:
case COMM_CLOSE:
case LBRACE:
case RBRACE:
case APOST:
case QUOTE:
case XAPOST:
case XQUOTE:
case AGLOBAL:
case ASCOPED:
case AMESSAGE:
case AUNDEFINE:
case AIF:
case ATHEN:
case AELSEIF:
case AELSE:
case AENDIF:
case ASUSPEND:
case ARESUME:
case ASTMT:
case STAR:
case AMPER:
case PPNAME:
case ALPHA:
case SPECIAL:
case DIGIT:
case EQUALS:
case ASTRING:
case QSTRING:
case STRING:
case SLASH_SLASH:
case BREAK_CODE_CHUNKS:
{
rst = LT(1);
matchNot(NL);
String content = rst.getText();
if (rst.getType() == STRING)
{
// Progress has a weird behavior here where it drops comments out of the
// message output even when the comments are inside a string!
// WARNING: This suggests they ignore strings in this mode so we probably
// have a future bug here where there are unmatched quotes in a
// compile-time message and it hoses up the preprocessing for us.
content = StringHelper.stripMatchedComments(content);
}
rest.append(content);
break;
}
default:
{
break _loop21;
}
}
} while (true);
}
nl = LT(1);
match(NL);
env.mprint(StringHelper.safeTrimLeading(rest.toString()), nl.getLine());
}
catch (RecognitionException ex) {
reportError(ex);
recover(ex,_tokenSet_2);
}
}
/**
* Matches the <code>&ANALYZE-SUSPEND</code> and <code>&ANALYZE-RESUME</code>
* preprocessor statements. Everything is parsed to the end of the line
* and is dropped. The newline is preserved in the output.
*/
public final void noop() throws RecognitionException, TokenStreamException, IOException {
Token c = null;
Token junk = null;
try { // for error handling
{
switch ( LA(1)) {
case ASUSPEND:
{
match(ASUSPEND);
break;
}
case ARESUME:
{
match(ARESUME);
break;
}
default:
{
throw new NoViableAltException(LT(1), getFilename());
}
}
}
{
_loop25:
do {
if ((LA(1)==STAR_COMMENT) && (_tokenSet_2.member(LA(2)))) {
c = LT(1);
match(STAR_COMMENT);
env.print(c.getText());
}
else if (((_tokenSet_5.member(LA(1))) && (_tokenSet_2.member(LA(2))))&&( LA(1) != EOF )) {
junk = LT(1);
matchNot(NL);
StringBuffer sb = new StringBuffer(junk.getText());
// if we are placed at the end of an include file, then the closing
// include marker sequence will be placed here in front of EOF so
// we need to process the markers
env.filter(sb, false);
}
else {
break _loop25;
}
} while (true);
}
{
if ((LA(1)==NL) && (_tokenSet_2.member(LA(2)))) {
match(NL);
env.print("\n");
}
else if (((_tokenSet_2.member(LA(1))) && (_tokenSet_2.member(LA(2))))&&( LA(1) == EOF )) {
}
else {
throw new NoViableAltException(LT(1), getFilename());
}
}
}
catch (RecognitionException ex) {
reportError(ex);
recover(ex,_tokenSet_2);
}
}
/**
* Matches the <code>&IF</code> Progress preprocessor statement.
*
* @throws antlr.RecognitionException
* @throws antlr.TokenStreamException
* @throws IOException
*/
public final void aif() throws RecognitionException, TokenStreamException, IOException {
Token tmp = null;
try { // for error handling
tmp = LT(1);
match(AIF);
condNesting++;
// String filename = ((FileScope)(env.getSym().getScope())).getFileName();
// System.out.printf("&IF level %d, filename %s, line %d, col %d\n", condNesting, filename, tmp.getLine(), tmp.getColumn());
condtext();
}
catch (RecognitionException ex) {
reportError(ex);
recover(ex,_tokenSet_2);
}
}
/**
* Matches any mistyped or unrecognized Progress preprocessor statement.
*
* @throws antlr.RecognitionException
* @throws antlr.TokenStreamException
*/
public final void astmt() throws RecognitionException, TokenStreamException {
Token s = null;
try { // for error handling
s = LT(1);
match(ASTMT);
env.eprint("unrecognized statement '" + s.getText() + "'", s.getLine(), s.getColumn());
}
catch (RecognitionException ex) {
reportError(ex);
recover(ex,_tokenSet_2);
}
}
/**
* Matches <code>&GLOBAL-DEFINE</code> and <code>&SCOPED-DEFINE</code>
* preprocessor directives and creates newly defined preprocessor variable
* in the corresponding scope. This consumes everything up to the end of
* the line and uses the text (trimmed of spaces at the front and back) as
* the value of the preprocessor variable.
*
* @param global
* <code>true</code> if this is a <code>&GLOBAL-DEFINE</code> and
* <code>false</code> for <code>&SCOPED-DEFINE</code>.
*/
public final void define(
boolean global
) throws RecognitionException, TokenStreamException, IOException {
Token c = null;
Token def = null;
String name = null;
StringBuilder definition = new StringBuilder();
int line = 0;
int column = 0;
env.setInDefine(true);
try { // for error handling
{
int _cnt12=0;
_loop12:
do {
if ((LA(1)==WS)) {
match(WS);
}
else {
if ( _cnt12>=1 ) { break _loop12; } else {throw new NoViableAltException(LT(1), getFilename());}
}
_cnt12++;
} while (true);
}
line = env.getLex().getLine();
column = env.getLex().getColumn();
name=ppname();
{
_loop15:
do {
if ((LA(1)==STAR_COMMENT) && ((LA(2) >= TAB && LA(2) <= BREAK_CODE_CHUNKS))) {
c = LT(1);
match(STAR_COMMENT);
env.print(c.getText());
}
else if ((_tokenSet_4.member(LA(1))) && ((LA(2) >= TAB && LA(2) <= BREAK_CODE_CHUNKS))) {
{
def = LT(1);
match(_tokenSet_4);
}
definition.append(def.getText());
}
else {
break _loop15;
}
} while (true);
}
match(NL);
env.setInDefine(false);
// the definition may have pending markers, process them
StringBuffer unclean = new StringBuffer(definition);
definition = new StringBuilder(env.filter(unclean, false));
// remove any leading blanks
while (definition.length() > 0 && definition.charAt(0) == ' ')
{
definition.deleteCharAt(0);
}
// remove any trailing blanks
while (definition.length() > 0 && definition.charAt(definition.length() - 1) == ' ')
{
definition.setLength(definition.length() - 1);
}
// remove any tildes that may have been left in '~{' pairs
// while(definition.length() > 0 && definition.indexOf("~{") >= 0)
// definition.deleteCharAt(definition.indexOf("~{"));
// as far as we know, there are no real syntax rules for the name
// so there is no known checks that need to be applied here
// lookup the name to see if it already exists
ScopedSymbolDictionary sym = env.getSym();
Symbol cur = (Symbol) sym.lookupSymbol(name);
// check to see if the name is for a builtin variable
if (cur != null && cur.getOrigin() == Symbol.BUILTIN)
{
env.eprint("cannot redefine builtin variable " + name,
line,
column);
return;
}
if (global)
{
// global definitions can be added if they don't already exist
// and they can be overridden if they only exist as global defs
// (but the override will fail if the name already exists as
// a scoped definition or as an argument); builtins can't be
// overridden either but they are handled above
if (cur == null || cur.getOrigin() == Symbol.GLOBAL)
{
sym.addSymbol(true,
name,
new Symbol(Symbol.GLOBAL, definition));
}
else
{
// TODO: Check if this "silent bypass if the values are the
// same" logic is actually how the 4GL preproc works.
// This behavior was found in a customer app and this is
// just a theory.
if (!cur.getValue().equals(definition.toString()))
{
String spec =
"Invalid global redefinition of preprocessor name '%s'." +
" (2967)";
env.eprint(String.format(spec, name), line, column);
}
}
}
else
{
// put the symbol definition into the locally scoped dictionary
sym.addSymbol(false,
name,
new Symbol(Symbol.SCOPED, definition));
}
}
catch (RecognitionException ex) {
reportError(ex);
recover(ex,_tokenSet_2);
}
}
/**
* Matches sequence of tokens that make a preprocessor variable name.
*
* @return the gathered variable name as a string
*
* @throws antlr.RecognitionException
* @throws antlr.TokenStreamException
* @throws IOException
*/
public final String ppname() throws RecognitionException, TokenStreamException, IOException {
String s;
Token c = null;
Token t = null;
StringBuilder buf = new StringBuilder();
s = null;
try { // for error handling
{
int _cnt30=0;
_loop30:
do {
if ((LA(1)==STAR_COMMENT) && (_tokenSet_2.member(LA(2)))) {
c = LT(1);
match(STAR_COMMENT);
env.print(c.getText());
}
else if ((_tokenSet_6.member(LA(1))) && (_tokenSet_2.member(LA(2)))) {
{
t = LT(1);
match(_tokenSet_6);
}
buf.append(t.getText());
}
else {
if ( _cnt30>=1 ) { break _loop30; } else {throw new NoViableAltException(LT(1), getFilename());}
}
_cnt30++;
} while (true);
}
s = buf.toString();
// in some extreme cases of stupid pp tricks, ppname references can have their own meta-references
// inside them; these can happen before we set the inStatement flag which means they can appear
// in our name; we must remove them now
if (s.indexOf(env.getOpt().getMarker()) != -1)
{
// LOG.log(Level.WARNING, String.format("PPNAME contains marker sequence '%s'\n", s));
s = env.filter(new StringBuffer(s), false);
}
}
catch (RecognitionException ex) {
reportError(ex);
recover(ex,_tokenSet_2);
}
return s;
}
/**
* Concludes the conditional input parsing for <code>&IF &ENDIF</code>
* preprocessor statements. Due to the nested nature of conditional
* statements, this method may be called recursively.
* <p>
* The preprocessor expression evaluation is done in two steps.
* Firstly, the entire expression is gathered from multiple lexer tokens
* into a string by calling the <code>expression</code> method.
* Secondly, if the expression has to be evaluated, the
* <code>{@link Preprocessor#evaluate(Environment,String)}</code> method
* is called to do the job.
*
* @throws antlr.RecognitionException
* @throws antlr.TokenStreamException
* @throws IOException
*/
public final void condtext() throws RecognitionException, TokenStreamException, IOException {
Token tmp0 = null;
Token tmp1 = null;
Token tmp4 = null;
Token tmp2 = null;
Token tmp3 = null;
int emit = 0;
String x = null;
String filename = null;
boolean lastIfCondValue = env.isIfCondValue();
try { // for error handling
x=expression(emit);
// evaluate the expression
if (Preprocessor.evaluate(env, x))
{
// force the following block to emit
emit = 1;
env.setIfCondValue(true);
}
else
{
// disable include expansion; must be done here BEFORE any
// matching may inadvertantly access lookahead and trigger
// an expansion; this is OK as long as it is above the &THEN
env.setExpandBraces(false);
env.setIfCondValue(false);
}
tmp0 = LT(1);
match(ATHEN);
// filename = ((FileScope)(env.getSym().getScope())).getFileName();
// System.out.printf("&THEN1 level %d, filename %s, line %d, col %d\n", condNesting, filename, tmp0.getLine(), tmp0.getColumn());
{
if (((_tokenSet_2.member(LA(1))) && (_tokenSet_2.member(LA(2))))&&( emit == 1 )) {
textBlock();
}
else if ((_tokenSet_2.member(LA(1))) && (_tokenSet_2.member(LA(2)))) {
skipBlock();
}
else {
throw new NoViableAltException(LT(1), getFilename());
}
}
{
_loop36:
do {
if ((LA(1)==AELSEIF) && (_tokenSet_7.member(LA(2)))) {
tmp1 = LT(1);
match(AELSEIF);
// filename = ((FileScope)(env.getSym().getScope())).getFileName();
// System.out.printf("&ELSEIF level %d, filename %s, line %d, col %d\n", condNesting, filename, tmp1.getLine(), tmp1.getColumn());
if (emit == 1)
emit = 2;
x=expression(emit);
// did the IF portion emit?
if (emit == 0)
{
// no emit yet, so evaluate the expression
if (Preprocessor.evaluate(env, x))
{
// force the following block to emit
emit = 1;
env.setIfCondValue(true);
}
else
{
// disable include expansion; must be done here BEFORE any
// matching may inadvertantly access lookahead and trigger
// an expansion; this is OK as long as it is above the
// &THEN
env.setExpandBraces(false);
env.setIfCondValue(false);
}
}
else
{
// disable include expansion; must be done here BEFORE any
// matching may inadvertantly access lookahead and trigger
// an expansion; this is OK as long as it is above the
// &THEN
env.setExpandBraces(false);
env.setIfCondValue(false);
}
tmp4 = LT(1);
match(ATHEN);
// filename = ((FileScope)(env.getSym().getScope())).getFileName();
// System.out.printf("&THEN2 level %d, filename %s, line %d, col %d\n", condNesting, filename, tmp4.getLine(), tmp4.getColumn());
{
if (((_tokenSet_2.member(LA(1))) && (_tokenSet_2.member(LA(2))))&&( emit == 1 )) {
textBlock();
}
else if ((_tokenSet_2.member(LA(1))) && (_tokenSet_2.member(LA(2)))) {
skipBlock();
}
else {
throw new NoViableAltException(LT(1), getFilename());
}
}
}
else {
break _loop36;
}
} while (true);
}
{
if ((LA(1)==AELSE) && (_tokenSet_2.member(LA(2)))) {
// will we be dropping the block?
if (emit != 0)
{
// disable include expansion; must be done here BEFORE any
// matching may inadvertantly access lookahead and trigger
// an expansion; this is OK as long as it is above the
// &ELSE
env.setExpandBraces(false);
}
tmp2 = LT(1);
match(AELSE);
// filename = ((FileScope)(env.getSym().getScope())).getFileName();
// System.out.printf("&ELSE level %d, filename %s, line %d, col %d\n", condNesting, filename, tmp2.getLine(), tmp2.getColumn());
{
if (((_tokenSet_2.member(LA(1))) && (_tokenSet_2.member(LA(2))))&&( emit == 0 )) {
textBlock();
}
else if ((_tokenSet_2.member(LA(1))) && (_tokenSet_2.member(LA(2)))) {
skipBlock();
}
else {
throw new NoViableAltException(LT(1), getFilename());
}
}
}
else if ((_tokenSet_2.member(LA(1))) && (_tokenSet_2.member(LA(2)))) {
}
else {
throw new NoViableAltException(LT(1), getFilename());
}
}
{
if ((LA(1)==AENDIF) && (_tokenSet_2.member(LA(2)))) {
tmp3 = LT(1);
match(AENDIF);
}
else if (((_tokenSet_2.member(LA(1))) && (_tokenSet_2.member(LA(2))))&&( LA(1) == EOF )) {
}
else {
throw new NoViableAltException(LT(1), getFilename());
}
}
// filename = ((FileScope)(env.getSym().getScope())).getFileName();
// System.out.printf("&ENDIF level %d, filename %s, line %d, col %d\n", condNesting, filename, tmp3.getLine(), tmp3.getColumn());
condNesting--;
env.setIfCondValue(lastIfCondValue);
}
catch (RecognitionException ex) {
reportError(ex);
recover(ex,_tokenSet_2);
}
}
/**
* Gathers the preprocessor expression into a string
* or ignores it.
*
* @param emit
* if 0, instructs the method to gather expression tokens
* into a string, otherwise the expression is ignored.
* @return the whole expression as a string if <code>emit</code>
* is 0, or "".
*
* @throws IOException
*/
public final String expression(
int emit
) throws RecognitionException, TokenStreamException, IOException {
String x;
Token t = null;
StringBuilder buf = new StringBuilder();
x = null;
try { // for error handling
{
int _cnt42=0;
_loop42:
do {
if ((_tokenSet_7.member(LA(1)))) {
t = LT(1);
matchNot(ATHEN);
if (emit == 0)
{
buf.append(t.getText());
}
}
else {
if ( _cnt42>=1 ) { break _loop42; } else {throw new NoViableAltException(LT(1), getFilename());}
}
_cnt42++;
} while (true);
}
x = buf.toString();
if (env.isInStatement())
{
// we need to process any nested include files now
env.clearDeferred();
x = env.filter(new StringBuffer(x), false);
}
// if (emit == 0)
// System.out.printf("EXPRESSION: %s\n", x);
}
catch (RecognitionException ex) {
reportError(ex);
recover(ex,_tokenSet_8);
}
return x;
}
/**
* Matches any non-interpretable block of text from the Progress source
* file, including those containing nested <code>&IF &ENDIF</code>
* statements. Non-interpretable blocks are the result of the preprocessor
* expressions evaluated so they cause bypassing of corresponding
* clauses of <code>&IF...&ENDIF</code> statements.
* <p>
* It is not possible to take the simple approach of matching everything
* until the next <code>&ELSEIF, &ELSE or &ENDIF</code> because there may be
* a nested <code>&IF</code> inside this block. In such a case, the
* <code>&IF</code> block will definitely have its own <code>&ENDIF</code>
* (and may also have its own <code>&ELSEIF or &ELSE</code>) which should
* not cause the termination of this loop since the entire
* <code>&IF...&ENDIF</code> is dead code. The matching loop can only
* terminate when it reaches an <code>&ELSEIF, &ELSE or &ENDIF</code> that
* is at the same level (no nesting) as the current block being skipped. The
* {@link #skipIf} rule handles matching any nested <code>&IF</code>
* constructs and uses recursion to handle any nested blocks that are
* nested inside of the nested block and so on.
* <p>
* Note that braces expansion must be disabled before entering this rule
* since the lookahead processing may trigger expansion of includes or
* argument references before this rule can be executed. Since braces are
* not expanded inside skipped conditional blocks in Progress, this is
* valid. This behavior also enables include files to include themselves
* recursively (so long as the <code>&IF</code>) blocks are VERY carefully
* crafted. This rule will always re-enable braces expansions before it
* returns.
*
* @throws antlr.RecognitionException
* @throws antlr.TokenStreamException
*/
public final void skipBlock() throws RecognitionException, TokenStreamException {
try { // for error handling
env.setInSkipBlock(true);
// cache off the in stmt flag
boolean inStmt = env.isInStatement();
// this should always be true
if (inStmt)
{
// disable while here
env.setInStatement(false);
env.clearDeferred();
}
{
_loop51:
do {
if ((LA(1)==AIF) && (_tokenSet_2.member(LA(2)))) {
skipIf();
}
else if ((_tokenSet_9.member(LA(1))) && (_tokenSet_2.member(LA(2)))) {
{
match(_tokenSet_9);
}
}
else {
break _loop51;
}
} while (true);
}
// re-enable include expansions
env.setExpandBraces(true);
env.setInSkipBlock(false);
// restore state if needed
if (inStmt)
{
env.setInStatement(true);
}
}
catch (RecognitionException ex) {
reportError(ex);
recover(ex,_tokenSet_2);
}
}
/**
* Matches non-interpretable block of text from the Progress source
* file which is a fully coded <code>&IF &ENDIF</code> statement, possibly
* recursive. Non-interpretable blocks are the result of the preprocessor
* expressions evaluated so they cause bypassing of corresponding
* clauses of <code>&IF...&ENDIF</code> statements.
* <p>
* This is a simple replacement for the {@link #aif} rule which discards
* any content and uses recursion to drop any nested conditional blocks.
* See {@link #skipBlock} which is the only user of this rule.
*
* @throws antlr.RecognitionException
* @throws antlr.TokenStreamException
*/
public final void skipIf() throws RecognitionException, TokenStreamException {
Token tmp = null;
Token tmp2 = null;
try { // for error handling
tmp = LT(1);
match(AIF);
condNesting++;
// String filename = ((FileScope)(env.getSym().getScope())).getFileName();
// System.out.printf("&IF (SKIPPING) level %d, filename %s, line %d, col %d\n", condNesting, filename, tmp.getLine(), tmp.getColumn());
{
_loop46:
do {
if ((LA(1)==AIF) && (_tokenSet_2.member(LA(2)))) {
skipIf();
}
else if ((_tokenSet_10.member(LA(1))) && (_tokenSet_2.member(LA(2)))) {
{
match(_tokenSet_10);
}
}
else {
break _loop46;
}
} while (true);
}
{
if ((LA(1)==AENDIF) && (_tokenSet_2.member(LA(2)))) {
tmp2 = LT(1);
match(AENDIF);
}
else if (((_tokenSet_2.member(LA(1))) && (_tokenSet_2.member(LA(2))))&&( LA(1) == EOF )) {
}
else {
throw new NoViableAltException(LT(1), getFilename());
}
}
// filename = ((FileScope)(env.getSym().getScope())).getFileName();
// System.out.printf("&ENDIF (SKIPPING) level %d, filename %s, line %d, col %d\n", condNesting, filename, tmp2.getLine(), tmp2.getColumn());
condNesting--;
}
catch (RecognitionException ex) {
reportError(ex);
recover(ex,_tokenSet_2);
}
}
public static final String[] _tokenNames = {
"<0>",
"EOF",
"<2>",
"NULL_TREE_LOOKAHEAD",
"TAB",
"WS",
"COMMENT",
"COMM_OPEN",
"CODE",
"COMM_CLOSE",
"LBRACE",
"RBRACE",
"APOST",
"QUOTE",
"XAPOST",
"XQUOTE",
"AGLOBAL",
"ASCOPED",
"AMESSAGE",
"AUNDEFINE",
"AIF",
"ATHEN",
"AELSEIF",
"AELSE",
"AENDIF",
"ASUSPEND",
"ARESUME",
"ASTMT",
"NL",
"STAR",
"AMPER",
"PPNAME",
"ALPHA",
"SPECIAL",
"DIGIT",
"EQUALS",
"ASTRING",
"QSTRING",
"STRING",
"STAR_COMMENT",
"SLASH_SLASH",
"BREAK_CODE_CHUNKS"
};
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 = { 236912640L, 0L};
return data;
}
public static final BitSet _tokenSet_1 = new BitSet(mk_tokenSet_1());
private static final long[] mk_tokenSet_2() {
long[] data = { 4398046511090L, 0L, 0L, 0L};
return data;
}
public static final BitSet _tokenSet_2 = new BitSet(mk_tokenSet_2());
private static final long[] mk_tokenSet_3() {
long[] data = { 4398017150960L, 0L, 0L, 0L};
return data;
}
public static final BitSet _tokenSet_3 = new BitSet(mk_tokenSet_3());
private static final long[] mk_tokenSet_4() {
long[] data = { 4397778075632L, 0L, 0L, 0L};
return data;
}
public static final BitSet _tokenSet_4 = new BitSet(mk_tokenSet_4());
private static final long[] mk_tokenSet_5() {
long[] data = { 3848022261744L, 0L, 0L, 0L};
return data;
}
public static final BitSet _tokenSet_5 = new BitSet(mk_tokenSet_5());
private static final long[] mk_tokenSet_6() {
long[] data = { 4397778075600L, 0L, 0L, 0L};
return data;
}
public static final BitSet _tokenSet_6 = new BitSet(mk_tokenSet_6());
private static final long[] mk_tokenSet_7() {
long[] data = { 4398044413936L, 0L, 0L, 0L};
return data;
}
public static final BitSet _tokenSet_7 = new BitSet(mk_tokenSet_7());
private static final long[] mk_tokenSet_8() {
long[] data = { 2097152L, 0L};
return data;
}
public static final BitSet _tokenSet_8 = new BitSet(mk_tokenSet_8());
private static final long[] mk_tokenSet_9() {
long[] data = { 4398016102386L, 0L, 0L, 0L};
return data;
}
public static final BitSet _tokenSet_9 = new BitSet(mk_tokenSet_9());
private static final long[] mk_tokenSet_10() {
long[] data = { 4398029733874L, 0L, 0L, 0L};
return data;
}
public static final BitSet _tokenSet_10 = new BitSet(mk_tokenSet_10());
}