// ===========================================================================
// This file has been generated by
// Rats! Parser Generator, version 1.14.2,
// (C) 2004-2008 Robert Grimm,
// on Tuesday, October 14, 2008 at 8:49:15 AM.
// Edit at your own risk.
// ===========================================================================

package xtc.lang.jeannie;

import java.io.Reader;
import java.io.IOException;

import xtc.util.Pair;

import xtc.tree.Node;
import xtc.tree.GNode;

import xtc.parser.ParserBase;
import xtc.parser.Column;
import xtc.parser.Result;
import xtc.parser.SemanticValue;
import xtc.parser.ParseError;

import xtc.lang.CParserState;

/**
 * Packrat parser for grammar <code>xtc.lang.jeannie.PreJeannie</code>.
 *
 * <p />This class has been generated by the <i>Rats!</i> parser
 * generator, version 1.14.2, (C) 2004-2008 Robert Grimm.
 */
public final class PreJeannieParser extends ParserBase {

  /** The RELOCATE flag. */
  public static final boolean RELOCATE = true;

  // =========================================================================

  /** Memoization table column. */
  static final class PreJeannieParserColumn extends Column {
    Result fQualifiedIdentifier;
    Result fQualifiedIdentifier$$Star1;
    Result fIdentifier;
    Result fSymbol;
  }

  // =========================================================================

  /** The global state object. */
  protected final xtc.lang.CParserState yyState;

  // =========================================================================

  /**
   * Create a new packrat parser.
   *
   * @param reader The reader.
   * @param file The file name.
   */
  public PreJeannieParser(final Reader reader, final String file) {
    super(reader, file);
    yyState = new xtc.lang.CParserState();
  }

  /**
   * Create a new packrat parser.
   *
   * @param reader The file reader.
   * @param file The file name.
   * @param size The file size.
   */
  public PreJeannieParser(final Reader reader, final String file, final int size) {
    super(reader, file, size);
    yyState = new xtc.lang.CParserState();
  }

  // =========================================================================

  protected Column newColumn() {
    return new PreJeannieParserColumn();
  }

  // =========================================================================

  /**
   * Parse nonterminal xtc.lang.jeannie.PreJeannie.File.
   *
   * @param yyStart The index.
   * @return The result.
   * @throws IOException Signals an I/O error.
   */
  public Result pFile(final int yyStart) throws IOException {
    Result     yyResult;
    Node       yyValue;
    ParseError yyError = ParseError.DUMMY;

    // Alternative 1.

    yyResult = pCPrelude(yyStart);
    yyError  = yyResult.select(yyError);
    if (yyResult.hasValue()) {
      final String p = yyResult.semanticValue();

      yyResult = pHead(yyResult.index);
      yyError  = yyResult.select(yyError);
      if (yyResult.hasValue()) {
        final String h = yyResult.semanticValue();

        yyResult = pTail(yyResult.index);
        yyError  = yyResult.select(yyError);
        if (yyResult.hasValue()) {
          final String t = yyResult.semanticValue();

          yyValue = GNode.create("File", p + h + t);

          setLocation(yyValue, yyStart);
          return yyResult.createValue(yyValue, yyError);
        }
      }
    }

    // Done.
    return yyError;
  }

  // =========================================================================

  /**
   * Parse nonterminal xtc.lang.jeannie.PreJeannie.CPrelude.
   *
   * @param yyStart The index.
   * @return The result.
   * @throws IOException Signals an I/O error.
   */
  private Result pCPrelude(final int yyStart) throws IOException {
    Result     yyResult;
    String     yyValue;
    ParseError yyError = ParseError.DUMMY;

    // Alternative 1.

    yyResult = pDirective(yyStart);
    yyError  = yyResult.select(yyError);
    if (yyResult.hasValue()) {

      yyResult = pSpacing(yyResult.index);
      yyError  = yyResult.select(yyError);
      if (yyResult.hasValue()) {

        yyValue = origString(yyStart, yyResult.index);

        return yyResult.createValue(yyValue, yyError);
      }
    }

    // Done.
    return yyError;
  }

  // =========================================================================

  /**
   * Parse nonterminal xtc.lang.jeannie.PreJeannie.Head.
   *
   * @param yyStart The index.
   * @return The result.
   * @throws IOException Signals an I/O error.
   */
  private Result pHead(final int yyStart) throws IOException {
    Result     yyResult;
    String     yyValue;
    ParseError yyError = ParseError.DUMMY;

    // Alternative 1.

    yyResult = pHead$$Choice1(yyStart);
    yyError  = yyResult.select(yyError);
    if (yyResult.hasValue()) {
      yyValue = yyResult.semanticValue();

      return yyResult.createValue(yyValue, yyError);
    }

    // Done.
    return yyError;
  }

  // =========================================================================

  /**
   * Parse synthetic nonterminal xtc.lang.jeannie.PreJeannie.Head$$Choice1.
   *
   * @param yyStart The index.
   * @return The result.
   * @throws IOException Signals an I/O error.
   */
  private Result pHead$$Choice1(final int yyStart) throws IOException {
    Result     yyResult;
    String     yyValue;
    ParseError yyError = ParseError.DUMMY;

    // Alternative 1.

    yyResult = pJavaHead(yyStart);
    yyError  = yyResult.select(yyError);
    if (yyResult.hasValue()) {
      yyValue = yyResult.semanticValue();

      return yyResult.createValue(yyValue, yyError);
    }

    // Alternative 2.

    yyResult = pCHead(yyStart);
    yyError  = yyResult.select(yyError);
    if (yyResult.hasValue()) {
      yyValue = yyResult.semanticValue();

      return yyResult.createValue(yyValue, yyError);
    }

    // Done.
    return yyError;
  }

  // =========================================================================

  /**
   * Parse nonterminal xtc.lang.jeannie.PreJeannie.JavaHead.
   *
   * @param yyStart The index.
   * @return The result.
   * @throws IOException Signals an I/O error.
   */
  private Result pJavaHead(final int yyStart) throws IOException {
    int        yyC;
    int        yyIndex;
    Result     yyResult;
    int        yyBase;
    int        yyOption1;
    String     yyValue;
    ParseError yyError = ParseError.DUMMY;

    // Alternative 1.

    yyOption1  = yyStart;

    yyResult = pPackageDeclaration(yyOption1);
    yyError  = yyResult.select(yyError, yyOption1);
    if (yyResult.hasValue()) {

      yyOption1  = yyResult.index;
    }

    yyResult = pJavaImports(yyOption1);
    yyError  = yyResult.select(yyError);
    if (yyResult.hasValue()) {

      yyBase   = yyResult.index;
      yyResult = pSymbol(yyBase);
      if (yyResult.hasValue("`")) {

        yyBase   = yyResult.index;
        yyResult = pSymbol(yyBase);
        if (yyResult.hasValue(".")) {

          yyBase = yyResult.index;
          yyC    = character(yyBase);
          if ('C' == yyC) {
            yyIndex = yyResult.index + 1;

            yyResult = pSpacing(yyIndex);
            yyError  = yyResult.select(yyError);
            if (yyResult.hasValue()) {

              yyBase   = yyResult.index;
              yyResult = pSymbol(yyBase);
              if (yyResult.hasValue("{")) {

                yyValue = origString(yyStart, yyResult.index);

                return yyResult.createValue(yyValue, yyError);
              } else {
                yyError = yyError.select("'{' expected", yyBase);
              }
            }
          } else {
            yyError = yyError.select("'C' expected", yyBase);
          }
        } else {
          yyError = yyError.select("'.' expected", yyBase);
        }
      } else {
        yyError = yyError.select("'`' expected", yyBase);
      }
    }

    // Done.
    return yyError;
  }

  // =========================================================================

  /**
   * Parse nonterminal xtc.lang.jeannie.PreJeannie.PackageDeclaration.
   *
   * @param yyStart The index.
   * @return The result.
   * @throws IOException Signals an I/O error.
   */
  private Result pPackageDeclaration(final int yyStart) throws IOException {
    int        yyC;
    int        yyIndex;
    Result     yyResult;
    int        yyBase;
    Void       yyValue;
    ParseError yyError = ParseError.DUMMY;

    // Alternative 1.

    yyC = character(yyStart);
    if ('p' == yyC) {
      yyIndex = yyStart + 1;

      yyC = character(yyIndex);
      if ('a' == yyC) {
        yyIndex = yyIndex + 1;

        yyC = character(yyIndex);
        if ('c' == yyC) {
          yyIndex = yyIndex + 1;

          yyC = character(yyIndex);
          if ('k' == yyC) {
            yyIndex = yyIndex + 1;

            yyC = character(yyIndex);
            if ('a' == yyC) {
              yyIndex = yyIndex + 1;

              yyC = character(yyIndex);
              if ('g' == yyC) {
                yyIndex = yyIndex + 1;

                yyC = character(yyIndex);
                if ('e' == yyC) {
                  yyIndex = yyIndex + 1;

                  yyResult = pSpacing(yyIndex);
                  yyError  = yyResult.select(yyError);
                  if (yyResult.hasValue()) {

                    yyResult = pQualifiedIdentifier(yyResult.index);
                    yyError  = yyResult.select(yyError);
                    if (yyResult.hasValue()) {

                      yyBase   = yyResult.index;
                      yyResult = pSymbol(yyBase);
                      if (yyResult.hasValue(";")) {

                        yyValue = null;

                        return yyResult.createValue(yyValue, yyError);
                      } else {
                        yyError = yyError.select("';' expected", yyBase);
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }

    // Done.
    yyError = yyError.select("package declaration expected", yyStart);
    return yyError;
  }

  // =========================================================================

  /**
   * Parse nonterminal xtc.lang.jeannie.PreJeannie.QualifiedIdentifier.
   *
   * @param yyStart The index.
   * @return The result.
   * @throws IOException Signals an I/O error.
   */
  private Result pQualifiedIdentifier(final int yyStart) throws IOException {
    PreJeannieParserColumn yyColumn = (PreJeannieParserColumn)column(yyStart);
    if (null == yyColumn.fQualifiedIdentifier) 
      yyColumn.fQualifiedIdentifier = pQualifiedIdentifier$1(yyStart);
    return yyColumn.fQualifiedIdentifier;
  }

  /** Actually parse xtc.lang.jeannie.PreJeannie.QualifiedIdentifier. */
  private Result pQualifiedIdentifier$1(final int yyStart) 
    throws IOException {

    Result     yyResult;
    Void       yyValue;
    ParseError yyError = ParseError.DUMMY;

    // Alternative 1.

    yyResult = pIdentifier(yyStart);
    yyError  = yyResult.select(yyError);
    if (yyResult.hasValue()) {

      yyResult = pQualifiedIdentifier$$Star1(yyResult.index);
      yyError  = yyResult.select(yyError);
      if (yyResult.hasValue()) {

        yyValue = null;

        return yyResult.createValue(yyValue, yyError);
      }
    }

    // Done.
    return yyError;
  }

  // =========================================================================

  /**
   * Parse synthetic nonterminal 
   * xtc.lang.jeannie.PreJeannie.QualifiedIdentifier$$Star1.
   *
   * @param yyStart The index.
   * @return The result.
   * @throws IOException Signals an I/O error.
   */
  private Result pQualifiedIdentifier$$Star1(final int yyStart) 
    throws IOException {

    PreJeannieParserColumn yyColumn = (PreJeannieParserColumn)column(yyStart);
    if (null == yyColumn.fQualifiedIdentifier$$Star1) 
      yyColumn.fQualifiedIdentifier$$Star1 = pQualifiedIdentifier$$Star1$1(yyStart);
    return yyColumn.fQualifiedIdentifier$$Star1;
  }

  /** Actually parse xtc.lang.jeannie.PreJeannie.QualifiedIdentifier$$Star1. */
  private Result pQualifiedIdentifier$$Star1$1(final int yyStart) 
    throws IOException {

    Result     yyResult;
    Void       yyValue;
    ParseError yyError = ParseError.DUMMY;

    // Alternative 1.

    yyResult = pSymbol(yyStart);
    if (yyResult.hasValue(".")) {

      yyResult = pIdentifier(yyResult.index);
      yyError  = yyResult.select(yyError);
      if (yyResult.hasValue()) {

        yyResult = pQualifiedIdentifier$$Star1(yyResult.index);
        yyError  = yyResult.select(yyError);
        if (yyResult.hasValue()) {

          yyValue = null;

          return yyResult.createValue(yyValue, yyError);
        }
      }
    }

    // Alternative 2.

    yyValue = null;

    return new SemanticValue(yyValue, yyStart, yyError);
  }

  // =========================================================================

  /**
   * Parse nonterminal xtc.lang.jeannie.PreJeannie.Identifier.
   *
   * @param yyStart The index.
   * @return The result.
   * @throws IOException Signals an I/O error.
   */
  private Result pIdentifier(final int yyStart) throws IOException {
    PreJeannieParserColumn yyColumn = (PreJeannieParserColumn)column(yyStart);
    if (null == yyColumn.fIdentifier) 
      yyColumn.fIdentifier = pIdentifier$1(yyStart);
    return yyColumn.fIdentifier;
  }

  /** Actually parse xtc.lang.jeannie.PreJeannie.Identifier. */
  private Result pIdentifier$1(final int yyStart) throws IOException {
    Result     yyResult;
    String     yyValue;
    ParseError yyError = ParseError.DUMMY;

    // Alternative 1.

    yyResult = pWordCharacters(yyStart);
    yyError  = yyResult.select(yyError);
    if (yyResult.hasValue()) {
      yyValue = yyResult.semanticValue();

      yyResult = pSpacing(yyResult.index);
      yyError  = yyResult.select(yyError);
      if (yyResult.hasValue()) {

        return yyResult.createValue(yyValue, yyError);
      }
    }

    // Done.
    return yyError;
  }

  // =========================================================================

  /**
   * Parse nonterminal xtc.lang.jeannie.PreJeannie.WordCharacters.
   *
   * @param yyStart The index.
   * @return The result.
   * @throws IOException Signals an I/O error.
   */
  private Result pWordCharacters(final int yyStart) throws IOException {
    int        yyC;
    int        yyIndex;
    int        yyRepetition1;
    String     yyValue;
    ParseError yyError = ParseError.DUMMY;

    // Alternative 1.

    yyC = character(yyStart);
    if (-1 != yyC) {
      yyIndex = yyStart + 1;
      final char start = (char)yyC;

      if (Character.isJavaIdentifierStart(start)) {

        yyRepetition1 = yyIndex;
        while (true) {

          yyC = character(yyRepetition1);
          if (-1 != yyC) {
            yyIndex = yyRepetition1 + 1;
            final char part = (char)yyC;

            if (Character.isJavaIdentifierPart(part)) {

              yyRepetition1 = yyIndex;
              continue;
            }
          }
          break;
        }

        yyValue = difference(yyStart, yyRepetition1);

        return new SemanticValue(yyValue, yyRepetition1, yyError);
      }
    }

    // Done.
    yyError = yyError.select("word characters expected", yyStart);
    return yyError;
  }

  // =========================================================================

  /**
   * Parse nonterminal xtc.lang.jeannie.PreJeannie.JavaImports.
   *
   * @param yyStart The index.
   * @return The result.
   * @throws IOException Signals an I/O error.
   */
  private Result pJavaImports(final int yyStart) throws IOException {
    Result     yyResult;
    int        yyRepetition1;
    Void       yyValue;
    ParseError yyError = ParseError.DUMMY;

    // Alternative 1.

    yyRepetition1 = yyStart;
    while (true) {

      yyResult = pImportDeclaration(yyRepetition1);
      yyError  = yyResult.select(yyError, yyRepetition1);
      if (yyResult.hasValue()) {

        yyRepetition1 = yyResult.index;
        continue;
      }
      break;
    }

    yyValue = null;

    return new SemanticValue(yyValue, yyRepetition1, yyError);
  }

  // =========================================================================

  /**
   * Parse nonterminal xtc.lang.jeannie.PreJeannie.ImportDeclaration.
   *
   * @param yyStart The index.
   * @return The result.
   * @throws IOException Signals an I/O error.
   */
  private Result pImportDeclaration(final int yyStart) throws IOException {
    int        yyC;
    int        yyIndex;
    Result     yyResult;
    int        yyBase;
    int        yyOption1;
    Void       yyValue;
    ParseError yyError = ParseError.DUMMY;

    // Alternative 1.

    yyC = character(yyStart);
    if ('i' == yyC) {
      yyIndex = yyStart + 1;

      yyC = character(yyIndex);
      if ('m' == yyC) {
        yyIndex = yyIndex + 1;

        yyC = character(yyIndex);
        if ('p' == yyC) {
          yyIndex = yyIndex + 1;

          yyC = character(yyIndex);
          if ('o' == yyC) {
            yyIndex = yyIndex + 1;

            yyC = character(yyIndex);
            if ('r' == yyC) {
              yyIndex = yyIndex + 1;

              yyC = character(yyIndex);
              if ('t' == yyC) {
                yyIndex = yyIndex + 1;

                yyResult = pSpacing(yyIndex);
                yyError  = yyResult.select(yyError);
                if (yyResult.hasValue()) {

                  yyResult = pQualifiedIdentifier(yyResult.index);
                  yyError  = yyResult.select(yyError);
                  if (yyResult.hasValue()) {

                    yyOption1  = yyResult.index;

                    yyResult = pDotStarTail(yyOption1);
                    yyError  = yyResult.select(yyError, yyOption1);
                    if (yyResult.hasValue()) {

                      yyOption1  = yyResult.index;
                    }

                    yyBase   = yyOption1;
                    yyResult = pSymbol(yyBase);
                    if (yyResult.hasValue(";")) {

                      yyValue = null;

                      return yyResult.createValue(yyValue, yyError);
                    } else {
                      yyError = yyError.select("';' expected", yyBase);
                    }
                  }
                }
              }
            }
          }
        }
      }
    }

    // Done.
    yyError = yyError.select("import declaration expected", yyStart);
    return yyError;
  }

  // =========================================================================

  /**
   * Parse nonterminal xtc.lang.jeannie.PreJeannie.DotStarTail.
   *
   * @param yyStart The index.
   * @return The result.
   * @throws IOException Signals an I/O error.
   */
  private Result pDotStarTail(final int yyStart) throws IOException {
    Result     yyResult;
    int        yyBase;
    Void       yyValue;
    ParseError yyError = ParseError.DUMMY;

    // Alternative 1.

    yyResult = pSymbol(yyStart);
    if (yyResult.hasValue(".")) {

      yyBase   = yyResult.index;
      yyResult = pSymbol(yyBase);
      if (yyResult.hasValue("*")) {

        yyValue = null;

        return yyResult.createValue(yyValue, yyError);
      } else {
        yyError = yyError.select("'*' expected", yyBase);
      }
    }

    // Done.
    yyError = yyError.select("dot star tail expected", yyStart);
    return yyError;
  }

  // =========================================================================

  /**
   * Parse nonterminal xtc.lang.jeannie.PreJeannie.CHead.
   *
   * @param yyStart The index.
   * @return The result.
   * @throws IOException Signals an I/O error.
   */
  private Result pCHead(final int yyStart) throws IOException {
    int        yyC;
    int        yyIndex;
    Result     yyResult;
    int        yyBase;
    int        yyRepetition1;
    boolean    yyRepeated1;
    String     yyValue;
    ParseError yyError = ParseError.DUMMY;

    // Alternative 1.

    yyResult = pSymbol(yyStart);
    if (yyResult.hasValue("`")) {

      yyBase   = yyResult.index;
      yyResult = pSymbol(yyBase);
      if (yyResult.hasValue(".")) {

        yyBase = yyResult.index;
        yyC    = character(yyBase);
        if ('J' == yyC) {
          yyIndex = yyResult.index + 1;

          yyC = character(yyIndex);
          if ('a' == yyC) {
            yyIndex = yyIndex + 1;

            yyC = character(yyIndex);
            if ('v' == yyC) {
              yyIndex = yyIndex + 1;

              yyC = character(yyIndex);
              if ('a' == yyC) {
                yyIndex = yyIndex + 1;

                yyResult = pSpacing(yyIndex);
                yyError  = yyResult.select(yyError);
                if (yyResult.hasValue()) {

                  yyBase   = yyResult.index;
                  yyResult = pSymbol(yyBase);
                  if (yyResult.hasValue("{")) {

                    yyRepetition1 = yyResult.index;
                    yyRepeated1   = false;
                    while (true) {

                      yyC = character(yyRepetition1);
                      if (-1 != yyC) {
                        yyIndex = yyRepetition1 + 1;

                        switch (yyC) {
                        case '^':
                        case '}':
                          {
                            yyRepetition1 = yyIndex;
                            yyRepeated1   = true;
                            continue;
                          }

                        default:
                          /* No match. */
                        }
                      }
                      break;
                    }

                    if (yyRepeated1) {

                      yyBase   = yyRepetition1;
                      yyResult = pSymbol(yyBase);
                      if (yyResult.hasValue("}")) {

                        yyValue = origString(yyStart, yyResult.index);

                        return yyResult.createValue(yyValue, yyError);
                      } else {
                        yyError = yyError.select("'}' expected", yyBase);
                      }
                    }
                  } else {
                    yyError = yyError.select("'{' expected", yyBase);
                  }
                }
              } else {
                yyError = yyError.select("'Java' expected", yyBase);
              }
            } else {
              yyError = yyError.select("'Java' expected", yyBase);
            }
          } else {
            yyError = yyError.select("'Java' expected", yyBase);
          }
        } else {
          yyError = yyError.select("'Java' expected", yyBase);
        }
      } else {
        yyError = yyError.select("'.' expected", yyBase);
      }
    }

    // Done.
    yyError = yyError.select("c head expected", yyStart);
    return yyError;
  }

  // =========================================================================

  /**
   * Parse nonterminal xtc.lang.jeannie.PreJeannie.Tail.
   *
   * @param yyStart The index.
   * @return The result.
   * @throws IOException Signals an I/O error.
   */
  private Result pTail(final int yyStart) throws IOException {
    int        yyC;
    int        yyIndex;
    Result     yyResult;
    int        yyRepetition1;
    boolean    yyRepeated1;
    String     yyValue;
    ParseError yyError = ParseError.DUMMY;

    // Alternative 1.

    yyRepetition1 = yyStart;
    yyRepeated1   = false;
    while (true) {

      yyC = character(yyRepetition1);
      if (-1 != yyC) {
        yyIndex = yyRepetition1 + 1;

        yyRepetition1 = yyIndex;
        yyRepeated1   = true;
        continue;
      }
      break;
    }

    if (yyRepeated1) {

      yyResult = pEndOfFile(yyRepetition1);
      yyError  = yyResult.select(yyError);
      if (yyResult.hasValue()) {

        yyValue = _tool.jeannieDefs() + origString(yyStart, yyResult.index);

        return yyResult.createValue(yyValue, yyError);
      }
    }

    // Done.
    yyError = yyError.select("tail expected", yyStart);
    return yyError;
  }

  // =========================================================================

  /**
   * Parse nonterminal xtc.lang.CSpacing.Spacing.
   *
   * @param yyStart The index.
   * @return The result.
   * @throws IOException Signals an I/O error.
   */
  private Result pSpacing(final int yyStart) throws IOException {
    int        yyC;
    int        yyIndex;
    Result     yyResult;
    Result     yyPredResult;
    boolean    yyPredMatched;
    int        yyBase;
    int        yyRepetition1;
    int        yyRepetition2;
    Void       yyValue;
    ParseError yyError = ParseError.DUMMY;

    // Alternative 1.

    yyRepetition1 = yyStart;
    while (true) {

      final int yyChoice1 = yyRepetition1;

      // Nested alternative 1.

      yyC = character(yyChoice1);
      if (-1 != yyC) {
        yyIndex = yyChoice1 + 1;

        switch (yyC) {
        case ' ':
          {
            yyRepetition1 = yyIndex;
            continue;
          }

        case '\t':
          {
            yyRepetition1 = yyIndex;
            continue;
          }

        case '\f':
          {
            yyRepetition1 = yyIndex;
            continue;
          }

        case '/':
          {
            yyC = character(yyIndex);
            if (-1 != yyC) {
              yyIndex = yyIndex + 1;

              switch (yyC) {
              case '*':
                {
                  yyRepetition2 = yyIndex;
                  while (true) {

                    final int yyChoice2 = yyRepetition2;

                    // Nested alternative 1.

                    yyC = character(yyChoice2);
                    if (-1 != yyC) {
                      yyIndex = yyChoice2 + 1;

                      switch (yyC) {
                      case '*':
                        {
                          yyPredMatched = false;

                          yyC = character(yyIndex);
                          if ('/' == yyC) {

                            yyPredMatched = true;
                          }

                          if (! yyPredMatched) {

                            yyRepetition2 = yyIndex;
                            continue;
                          } else {
                            yyError = yyError.select("spacing expected", yyStart);
                          }
                        }
                        break;

                      default:
                        {
                          yyRepetition2 = yyIndex;
                          continue;
                        }
                      }
                    }
                    break;
                  }

                  yyBase = yyRepetition2;
                  yyC    = character(yyBase);
                  if ('*' == yyC) {
                    yyIndex = yyRepetition2 + 1;

                    yyC = character(yyIndex);
                    if ('/' == yyC) {
                      yyIndex = yyIndex + 1;

                      yyRepetition1 = yyIndex;
                      continue;
                    } else {
                      yyError = yyError.select("'*/' expected", yyBase);
                    }
                  } else {
                    yyError = yyError.select("'*/' expected", yyBase);
                  }
                }
                break;

              case '/':
                {
                  yyRepetition2 = yyIndex;
                  while (true) {

                    yyC = character(yyRepetition2);
                    if (-1 != yyC) {
                      yyIndex = yyRepetition2 + 1;

                      switch (yyC) {
                      case '\n':
                      case '\r':
                        /* No match. */
                        break;

                      default:
                        {
                          yyRepetition2 = yyIndex;
                          continue;
                        }
                      }
                    }
                    break;
                  }

                  yyPredResult = pLineTerminator(yyRepetition2);
                  yyError      = yyPredResult.select(yyError);
                  if (yyPredResult.hasValue()) {

                    yyRepetition1 = yyRepetition2;
                    continue;
                  }
                }
                break;

              default:
                /* No match. */
              }
            }
          }
          break;

        case '\r':
          {
            final int yyChoice2 = yyIndex;

            // Nested alternative 1.

            yyC = character(yyChoice2);
            if ('\n' == yyC) {
              yyIndex = yyChoice2 + 1;

              yyResult = pDirective(yyIndex);
              yyError  = yyResult.select(yyError, yyRepetition1);
              if (yyResult.hasValue()) {

                yyRepetition1 = yyResult.index;
                continue;
              }
            }

            // Nested alternative 2.

            yyResult = pDirective(yyChoice2);
            yyError  = yyResult.select(yyError, yyRepetition1);
            if (yyResult.hasValue()) {

              yyRepetition1 = yyResult.index;
              continue;
            }
          }
          break;

        case '\n':
          {
            yyResult = pDirective(yyIndex);
            yyError  = yyResult.select(yyError, yyRepetition1);
            if (yyResult.hasValue()) {

              yyRepetition1 = yyResult.index;
              continue;
            }
          }
          break;

        default:
          /* No match. */
        }
      }
      break;
    }

    yyValue = null;

    return new SemanticValue(yyValue, yyRepetition1, yyError);
  }

  // =========================================================================

  /**
   * Parse nonterminal xtc.lang.CSpacing.Space.
   *
   * @param yyStart The index.
   * @return The result.
   * @throws IOException Signals an I/O error.
   */
  private Result pSpace(final int yyStart) throws IOException {
    int        yyC;
    int        yyIndex;
    Void       yyValue;
    ParseError yyError = ParseError.DUMMY;

    // Alternative 1.

    yyC = character(yyStart);
    if (-1 != yyC) {
      yyIndex = yyStart + 1;

      switch (yyC) {
      case ' ':
        {
          yyValue = null;

          return new SemanticValue(yyValue, yyIndex, yyError);
        }

      case '\t':
        {
          yyValue = null;

          return new SemanticValue(yyValue, yyIndex, yyError);
        }

      case '\f':
        {
          yyValue = null;

          return new SemanticValue(yyValue, yyIndex, yyError);
        }

      default:
        /* No match. */
      }
    }

    // Done.
    yyError = yyError.select("space expected", yyStart);
    return yyError;
  }

  // =========================================================================

  /**
   * Parse nonterminal xtc.lang.CSpacing.LineTerminator.
   *
   * @param yyStart The index.
   * @return The result.
   * @throws IOException Signals an I/O error.
   */
  private Result pLineTerminator(final int yyStart) throws IOException {
    int        yyC;
    int        yyIndex;
    Void       yyValue;
    ParseError yyError = ParseError.DUMMY;

    // Alternative 1.

    yyC = character(yyStart);
    if (-1 != yyC) {
      yyIndex = yyStart + 1;

      switch (yyC) {
      case '\r':
        {
          final int yyChoice1 = yyIndex;

          // Nested alternative 1.

          yyC = character(yyChoice1);
          if ('\n' == yyC) {
            yyIndex = yyChoice1 + 1;

            yyValue = null;

            return new SemanticValue(yyValue, yyIndex, yyError);
          }

          // Nested alternative 2.

          yyValue = null;

          return new SemanticValue(yyValue, yyChoice1, yyError);
        }

      case '\n':
        {
          yyValue = null;

          return new SemanticValue(yyValue, yyIndex, yyError);
        }

      default:
        /* No match. */
      }
    }

    // Done.
    yyError = yyError.select("line terminator expected", yyStart);
    return yyError;
  }

  // =========================================================================

  /**
   * Parse nonterminal xtc.lang.CSpacing.EndOfFile.
   *
   * @param yyStart The index.
   * @return The result.
   * @throws IOException Signals an I/O error.
   */
  private Result pEndOfFile(final int yyStart) throws IOException {
    int        yyC;
    boolean    yyPredMatched;
    Void       yyValue;
    ParseError yyError = ParseError.DUMMY;

    // Alternative 1.

    yyPredMatched = false;

    yyC = character(yyStart);
    if (-1 != yyC) {

      yyPredMatched = true;
    }

    if (! yyPredMatched) {

      yyValue = null;

      return new SemanticValue(yyValue, yyStart, yyError);
    } else {
      yyError = yyError.select("end of file expected", yyStart);
    }

    // Done.
    return yyError;
  }

  // =========================================================================

  /**
   * Parse nonterminal xtc.lang.CSpacing.Directive.
   *
   * @param yyStart The index.
   * @return The result.
   * @throws IOException Signals an I/O error.
   */
  private Result pDirective(final int yyStart) throws IOException {
    int        yyC;
    int        yyIndex;
    Result     yyResult;
    Result     yyPredResult;
    int        yyBase;
    int        yyRepetition1;
    boolean    yyRepeated1;
    int        yyOption1;
    String     yyOpValue1;
    Void       yyValue;
    ParseError yyError = ParseError.DUMMY;

    // Alternative 1.

    yyC = character(yyStart);
    if ('#' == yyC) {
      yyIndex = yyStart + 1;

      final int yyChoice1 = yyIndex;

      // Nested alternative 1.

      yyC = character(yyChoice1);
      if (' ' == yyC) {
        yyIndex = yyChoice1 + 1;

        yyResult = pLineNumber(yyIndex);
        yyError  = yyResult.select(yyError);
        if (yyResult.hasValue()) {
          final String line = yyResult.semanticValue();

          yyC = character(yyResult.index);
          if (' ' == yyC) {
            yyIndex = yyResult.index + 1;

            yyC = character(yyIndex);
            if ('\"' == yyC) {
              yyIndex = yyIndex + 1;

              yyResult = pFileName(yyIndex);
              yyError  = yyResult.select(yyError);
              if (yyResult.hasValue()) {
                final String file = yyResult.semanticValue();

                yyC = character(yyResult.index);
                if ('\"' == yyC) {
                  yyIndex = yyResult.index + 1;

                  yyOption1  = yyIndex;
                  yyOpValue1 = null;

                  yyBase = yyOption1;
                  yyC    = character(yyBase);
                  if (' ' == yyC) {
                    yyIndex = yyOption1 + 1;

                    yyC = character(yyIndex);
                    if ('1' == yyC) {
                      yyIndex = yyIndex + 1;
                      final String v$el$1 = " 1";

                      yyOption1  = yyIndex;
                      yyOpValue1 = v$el$1;
                    } else {
                      yyError = yyError.select("' 1' expected", yyBase);
                    }
                  } else {
                    yyError = yyError.select("' 1' expected", yyBase);
                  }
                  { // Start scope for f1.
                    final String f1 = yyOpValue1;

                    yyOpValue1 = null;

                    yyBase = yyOption1;
                    yyC    = character(yyBase);
                    if (' ' == yyC) {
                      yyIndex = yyOption1 + 1;

                      yyC = character(yyIndex);
                      if ('2' == yyC) {
                        yyIndex = yyIndex + 1;
                        final String v$el$2 = " 2";

                        yyOption1  = yyIndex;
                        yyOpValue1 = v$el$2;
                      } else {
                        yyError = yyError.select("' 2' expected", yyBase);
                      }
                    } else {
                      yyError = yyError.select("' 2' expected", yyBase);
                    }
                    { // Start scope for f2.
                      final String f2 = yyOpValue1;

                      yyOpValue1 = null;

                      yyBase = yyOption1;
                      yyC    = character(yyBase);
                      if (' ' == yyC) {
                        yyIndex = yyOption1 + 1;

                        yyC = character(yyIndex);
                        if ('3' == yyC) {
                          yyIndex = yyIndex + 1;
                          final String v$el$3 = " 3";

                          yyOption1  = yyIndex;
                          yyOpValue1 = v$el$3;
                        } else {
                          yyError = yyError.select("' 3' expected", yyBase);
                        }
                      } else {
                        yyError = yyError.select("' 3' expected", yyBase);
                      }
                      { // Start scope for f3.
                        final String f3 = yyOpValue1;

                        yyOpValue1 = null;

                        yyBase = yyOption1;
                        yyC    = character(yyBase);
                        if (' ' == yyC) {
                          yyIndex = yyOption1 + 1;

                          yyC = character(yyIndex);
                          if ('4' == yyC) {
                            yyIndex = yyIndex + 1;
                            final String v$el$4 = " 4";

                            yyOption1  = yyIndex;
                            yyOpValue1 = v$el$4;
                          } else {
                            yyError = yyError.select("' 4' expected", yyBase);
                          }
                        } else {
                          yyError = yyError.select("' 4' expected", yyBase);
                        }
                        { // Start scope for f4.
                          final String f4 = yyOpValue1;

                          yyPredResult = pLineTerminator(yyOption1);
                          yyError      = yyPredResult.select(yyError);
                          if (yyPredResult.hasValue()) {

                            final int lineNo = Integer.parseInt(line);
                            if (RELOCATE) setLocation(yyStart, file, lineNo-1, FIRST_COLUMN);
                            yyState.lineMarker(file, lineNo, f1, f2, f3, f4, location(yyStart));

                            yyValue = null;

                            return new SemanticValue(yyValue, yyOption1, yyError);
                          }
                        } // End scope for f4.
                      } // End scope for f3.
                    } // End scope for f2.
                  } // End scope for f1.
                }
              }
            }
          }
        }
      }

      // Nested alternative 2.

      yyRepetition1 = yyChoice1;
      while (true) {

        yyResult = pSpace(yyRepetition1);
        yyError  = yyResult.select(yyError, yyRepetition1);
        if (yyResult.hasValue()) {

          yyRepetition1 = yyResult.index;
          continue;
        }
        break;
      }
      { // Start scope for nested choice.

        final int yyChoice2 = yyRepetition1;

        // Nested alternative 1.

        yyC = character(yyChoice2);
        if (-1 != yyC) {
          yyIndex = yyChoice2 + 1;

          switch (yyC) {
          case 'p':
            {
              yyC = character(yyIndex);
              if (-1 != yyC) {
                yyIndex = yyIndex + 1;
                if ('r' == yyC) {

                  yyC = character(yyIndex);
                  if (-1 != yyC) {
                    yyIndex = yyIndex + 1;
                    if ('a' == yyC) {

                      yyC = character(yyIndex);
                      if (-1 != yyC) {
                        yyIndex = yyIndex + 1;
                        if ('g' == yyC) {

                          yyC = character(yyIndex);
                          if (-1 != yyC) {
                            yyIndex = yyIndex + 1;
                            if ('m' == yyC) {

                              yyC = character(yyIndex);
                              if (-1 != yyC) {
                                yyIndex = yyIndex + 1;
                                if ('a' == yyC) {

                                  yyC = character(yyIndex);
                                  if (-1 != yyC) {
                                    yyIndex = yyIndex + 1;
                                    if (' ' == yyC) {

                                      yyResult = pPragma(yyIndex);
                                      yyError  = yyResult.select(yyError);
                                      if (yyResult.hasValue()) {
                                        final String pragma = yyResult.semanticValue();

                                        yyPredResult = 
                                          pLineTerminator(yyResult.index);
                                        yyError      = 
                                          yyPredResult.select(yyError);
                                        if (yyPredResult.hasValue()) {

                                          yyState.pragma(pragma, location(yyStart));

                                          yyValue = null;

                                          return yyResult.createValue(yyValue, yyError);
                                        }
                                      }
                                    }
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
            break;

          case 'i':
            {
              yyC = character(yyIndex);
              if (-1 != yyC) {
                yyIndex = yyIndex + 1;
                if ('d' == yyC) {

                  yyC = character(yyIndex);
                  if (-1 != yyC) {
                    yyIndex = yyIndex + 1;
                    if ('e' == yyC) {

                      yyC = character(yyIndex);
                      if (-1 != yyC) {
                        yyIndex = yyIndex + 1;
                        if ('n' == yyC) {

                          yyC = character(yyIndex);
                          if (-1 != yyC) {
                            yyIndex = yyIndex + 1;
                            if ('t' == yyC) {

                              yyRepetition1 = yyIndex;
                              yyRepeated1   = false;
                              while (true) {

                                yyResult = pSpace(yyRepetition1);
                                yyError  = yyResult.select(yyError);
                                if (yyResult.hasValue()) {

                                  yyRepetition1 = yyResult.index;
                                  yyRepeated1   = true;
                                  continue;
                                }
                                break;
                              }

                              if (yyRepeated1) {

                                yyC = character(yyRepetition1);
                                if ('\"' == yyC) {
                                  yyIndex = yyRepetition1 + 1;

                                  yyResult = pFileName(yyIndex);
                                  yyError  = yyResult.select(yyError);
                                  if (yyResult.hasValue()) {
                                    final String s = yyResult.semanticValue();

                                    yyC = character(yyResult.index);
                                    if ('\"' == yyC) {
                                      yyIndex = yyResult.index + 1;

                                      yyPredResult = pLineTerminator(yyIndex);
                                      yyError      = 
                                        yyPredResult.select(yyError);
                                      if (yyPredResult.hasValue()) {

                                        yyState.ident(s, location(yyStart));

                                        yyValue = null;

                                        return new SemanticValue(yyValue, yyIndex, yyError);
                                      }
                                    }
                                  }
                                }
                              }
                            }
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
            break;

          default:
            /* No match. */
          }
        }
      } // End scope for nested choice.
    }

    // Alternative 2.

    yyValue = null;

    return new SemanticValue(yyValue, yyStart, yyError);
  }

  // =========================================================================

  /**
   * Parse nonterminal xtc.lang.CSpacing.LineNumber.
   *
   * @param yyStart The index.
   * @return The result.
   * @throws IOException Signals an I/O error.
   */
  private Result pLineNumber(final int yyStart) throws IOException {
    int        yyC;
    int        yyIndex;
    int        yyRepetition1;
    String     yyValue;
    ParseError yyError = ParseError.DUMMY;

    // Alternative 1.

    yyC = character(yyStart);
    if (-1 != yyC) {
      yyIndex = yyStart + 1;

      switch (yyC) {
      case '1':
      case '2':
      case '3':
      case '4':
      case '5':
      case '6':
      case '7':
      case '8':
      case '9':
        {
          yyRepetition1 = yyIndex;
          while (true) {

            yyC = character(yyRepetition1);
            if (-1 != yyC) {
              yyIndex = yyRepetition1 + 1;

              switch (yyC) {
              case '0':
              case '1':
              case '2':
              case '3':
              case '4':
              case '5':
              case '6':
              case '7':
              case '8':
              case '9':
                {
                  yyRepetition1 = yyIndex;
                  continue;
                }

              default:
                /* No match. */
              }
            }
            break;
          }

          yyValue = difference(yyStart, yyRepetition1);

          return new SemanticValue(yyValue, yyRepetition1, yyError);
        }

      default:
        /* No match. */
      }
    }

    // Done.
    yyError = yyError.select("line number expected", yyStart);
    return yyError;
  }

  // =========================================================================

  /**
   * Parse nonterminal xtc.lang.CSpacing.FileName.
   *
   * @param yyStart The index.
   * @return The result.
   * @throws IOException Signals an I/O error.
   */
  private Result pFileName(final int yyStart) throws IOException {
    int        yyC;
    int        yyIndex;
    int        yyRepetition1;
    String     yyValue;
    ParseError yyError = ParseError.DUMMY;

    // Alternative 1.

    yyRepetition1 = yyStart;
    while (true) {

      final int yyChoice1 = yyRepetition1;

      // Nested alternative 1.

      yyC = character(yyChoice1);
      if (-1 != yyC) {
        yyIndex = yyChoice1 + 1;

        switch (yyC) {
        case '\\':
          {
            yyC = character(yyIndex);
            if (-1 != yyC) {
              yyIndex = yyIndex + 1;

              yyRepetition1 = yyIndex;
              continue;
            }
          }
          break;

        default:
          /* No match. */
        }
      }

      // Nested alternative 2.

      yyC = character(yyChoice1);
      if (-1 != yyC) {
        yyIndex = yyChoice1 + 1;

        switch (yyC) {
        case '\"':
        case '\\':
          /* No match. */
          break;

        default:
          {
            yyRepetition1 = yyIndex;
            continue;
          }
        }
      }
      break;
    }

    yyValue = difference(yyStart, yyRepetition1);

    return new SemanticValue(yyValue, yyRepetition1, yyError);
  }

  // =========================================================================

  /**
   * Parse nonterminal xtc.lang.CSpacing.Pragma.
   *
   * @param yyStart The index.
   * @return The result.
   * @throws IOException Signals an I/O error.
   */
  private Result pPragma(final int yyStart) throws IOException {
    int        yyC;
    int        yyIndex;
    int        yyRepetition1;
    String     yyValue;
    ParseError yyError = ParseError.DUMMY;

    // Alternative 1.

    yyRepetition1 = yyStart;
    while (true) {

      yyC = character(yyRepetition1);
      if (-1 != yyC) {
        yyIndex = yyRepetition1 + 1;

        switch (yyC) {
        case '\n':
        case '\r':
          /* No match. */
          break;

        default:
          {
            yyRepetition1 = yyIndex;
            continue;
          }
        }
      }
      break;
    }

    yyValue = difference(yyStart, yyRepetition1);

    return new SemanticValue(yyValue, yyRepetition1, yyError);
  }

  // =========================================================================

  /**
   * Parse nonterminal xtc.lang.jeannie.JeannieSymbol.Symbol.
   *
   * @param yyStart The index.
   * @return The result.
   * @throws IOException Signals an I/O error.
   */
  private Result pSymbol(final int yyStart) throws IOException {
    PreJeannieParserColumn yyColumn = (PreJeannieParserColumn)column(yyStart);
    if (null == yyColumn.fSymbol) yyColumn.fSymbol = pSymbol$1(yyStart);
    return yyColumn.fSymbol;
  }

  /** Actually parse xtc.lang.jeannie.JeannieSymbol.Symbol. */
  private Result pSymbol$1(final int yyStart) throws IOException {
    Result     yyResult;
    String     yyValue;
    ParseError yyError = ParseError.DUMMY;

    // Alternative 1.

    yyResult = pSymbolCharacters(yyStart);
    yyError  = yyResult.select(yyError);
    if (yyResult.hasValue()) {
      yyValue = yyResult.semanticValue();

      yyResult = pSpacing(yyResult.index);
      yyError  = yyResult.select(yyError);
      if (yyResult.hasValue()) {

        return yyResult.createValue(yyValue, yyError);
      }
    }

    // Done.
    return yyError;
  }

  // =========================================================================

  /**
   * Parse nonterminal xtc.lang.jeannie.JeannieSymbol.SymbolCharacters.
   *
   * @param yyStart The index.
   * @return The result.
   * @throws IOException Signals an I/O error.
   */
  private Result pSymbolCharacters(final int yyStart) throws IOException {
    int        yyC;
    int        yyIndex;
    String     yyValue;
    ParseError yyError = ParseError.DUMMY;

    // Alternative 1.

    yyC = character(yyStart);
    if (-1 != yyC) {
      yyIndex = yyStart + 1;

      switch (yyC) {
      case '>':
        {
          final int yyChoice1 = yyIndex;

          // Nested alternative 1.

          yyC = character(yyChoice1);
          if (-1 != yyC) {
            yyIndex = yyChoice1 + 1;

            switch (yyC) {
            case '>':
              {
                final int yyChoice2 = yyIndex;

                // Nested alternative 1.

                yyC = character(yyChoice2);
                if (-1 != yyC) {
                  yyIndex = yyChoice2 + 1;

                  switch (yyC) {
                  case '>':
                    {
                      final int yyChoice3 = yyIndex;

                      // Nested alternative 1.

                      yyC = character(yyChoice3);
                      if (-1 != yyC) {
                        yyIndex = yyChoice3 + 1;
                        if ('=' == yyC) {

                          yyValue = ">>>=";

                          return new SemanticValue(yyValue, yyIndex, yyError);
                        }
                      }

                      // Nested alternative 2.

                      yyValue = ">>>";

                      return new SemanticValue(yyValue, yyChoice3, yyError);
                    }

                  case '=':
                    {
                      yyValue = ">>=";

                      return new SemanticValue(yyValue, yyIndex, yyError);
                    }

                  default:
                    /* No match. */
                  }
                }

                // Nested alternative 2.

                yyValue = ">>";

                return new SemanticValue(yyValue, yyChoice2, yyError);
              }

            case '=':
              {
                yyValue = ">=";

                return new SemanticValue(yyValue, yyIndex, yyError);
              }

            default:
              /* No match. */
            }
          }

          // Nested alternative 2.

          yyValue = ">";

          return new SemanticValue(yyValue, yyChoice1, yyError);
        }

      case '<':
        {
          final int yyChoice1 = yyIndex;

          // Nested alternative 1.

          yyC = character(yyChoice1);
          if (-1 != yyC) {
            yyIndex = yyChoice1 + 1;

            switch (yyC) {
            case '<':
              {
                final int yyChoice2 = yyIndex;

                // Nested alternative 1.

                yyC = character(yyChoice2);
                if (-1 != yyC) {
                  yyIndex = yyChoice2 + 1;
                  if ('=' == yyC) {

                    yyValue = "<<=";

                    return new SemanticValue(yyValue, yyIndex, yyError);
                  }
                }

                // Nested alternative 2.

                yyValue = "<<";

                return new SemanticValue(yyValue, yyChoice2, yyError);
              }

            case '=':
              {
                yyValue = "<=";

                return new SemanticValue(yyValue, yyIndex, yyError);
              }

            default:
              /* No match. */
            }
          }

          // Nested alternative 2.

          yyValue = "<";

          return new SemanticValue(yyValue, yyChoice1, yyError);
        }

      case '.':
        {
          final int yyChoice1 = yyIndex;

          // Nested alternative 1.

          yyC = character(yyChoice1);
          if (-1 != yyC) {
            yyIndex = yyChoice1 + 1;
            if ('.' == yyC) {

              yyC = character(yyIndex);
              if (-1 != yyC) {
                yyIndex = yyIndex + 1;
                if ('.' == yyC) {

                  yyValue = "...";

                  return new SemanticValue(yyValue, yyIndex, yyError);
                }
              }
            }
          }

          // Nested alternative 2.

          yyValue = ".";

          return new SemanticValue(yyValue, yyChoice1, yyError);
        }

      case '+':
        {
          final int yyChoice1 = yyIndex;

          // Nested alternative 1.

          yyC = character(yyChoice1);
          if (-1 != yyC) {
            yyIndex = yyChoice1 + 1;

            switch (yyC) {
            case '=':
              {
                yyValue = "+=";

                return new SemanticValue(yyValue, yyIndex, yyError);
              }

            case '+':
              {
                yyValue = "++";

                return new SemanticValue(yyValue, yyIndex, yyError);
              }

            default:
              /* No match. */
            }
          }

          // Nested alternative 2.

          yyValue = "+";

          return new SemanticValue(yyValue, yyChoice1, yyError);
        }

      case '-':
        {
          final int yyChoice1 = yyIndex;

          // Nested alternative 1.

          yyC = character(yyChoice1);
          if (-1 != yyC) {
            yyIndex = yyChoice1 + 1;

            switch (yyC) {
            case '=':
              {
                yyValue = "-=";

                return new SemanticValue(yyValue, yyIndex, yyError);
              }

            case '-':
              {
                yyValue = "--";

                return new SemanticValue(yyValue, yyIndex, yyError);
              }

            case '>':
              {
                yyValue = "->";

                return new SemanticValue(yyValue, yyIndex, yyError);
              }

            default:
              /* No match. */
            }
          }

          // Nested alternative 2.

          yyValue = "-";

          return new SemanticValue(yyValue, yyChoice1, yyError);
        }

      case '*':
        {
          final int yyChoice1 = yyIndex;

          // Nested alternative 1.

          yyC = character(yyChoice1);
          if (-1 != yyC) {
            yyIndex = yyChoice1 + 1;
            if ('=' == yyC) {

              yyValue = "*=";

              return new SemanticValue(yyValue, yyIndex, yyError);
            }
          }

          // Nested alternative 2.

          yyValue = "*";

          return new SemanticValue(yyValue, yyChoice1, yyError);
        }

      case '/':
        {
          final int yyChoice1 = yyIndex;

          // Nested alternative 1.

          yyC = character(yyChoice1);
          if (-1 != yyC) {
            yyIndex = yyChoice1 + 1;
            if ('=' == yyC) {

              yyValue = "/=";

              return new SemanticValue(yyValue, yyIndex, yyError);
            }
          }

          // Nested alternative 2.

          yyValue = "/";

          return new SemanticValue(yyValue, yyChoice1, yyError);
        }

      case '%':
        {
          final int yyChoice1 = yyIndex;

          // Nested alternative 1.

          yyC = character(yyChoice1);
          if (-1 != yyC) {
            yyIndex = yyChoice1 + 1;
            if ('=' == yyC) {

              yyValue = "%=";

              return new SemanticValue(yyValue, yyIndex, yyError);
            }
          }

          // Nested alternative 2.

          yyValue = "%";

          return new SemanticValue(yyValue, yyChoice1, yyError);
        }

      case '&':
        {
          final int yyChoice1 = yyIndex;

          // Nested alternative 1.

          yyC = character(yyChoice1);
          if (-1 != yyC) {
            yyIndex = yyChoice1 + 1;

            switch (yyC) {
            case '=':
              {
                yyValue = "&=";

                return new SemanticValue(yyValue, yyIndex, yyError);
              }

            case '&':
              {
                yyValue = "&&";

                return new SemanticValue(yyValue, yyIndex, yyError);
              }

            default:
              /* No match. */
            }
          }

          // Nested alternative 2.

          yyValue = "&";

          return new SemanticValue(yyValue, yyChoice1, yyError);
        }

      case '^':
        {
          final int yyChoice1 = yyIndex;

          // Nested alternative 1.

          yyC = character(yyChoice1);
          if (-1 != yyC) {
            yyIndex = yyChoice1 + 1;
            if ('=' == yyC) {

              yyValue = "^=";

              return new SemanticValue(yyValue, yyIndex, yyError);
            }
          }

          // Nested alternative 2.

          yyValue = "^";

          return new SemanticValue(yyValue, yyChoice1, yyError);
        }

      case '|':
        {
          final int yyChoice1 = yyIndex;

          // Nested alternative 1.

          yyC = character(yyChoice1);
          if (-1 != yyC) {
            yyIndex = yyChoice1 + 1;

            switch (yyC) {
            case '=':
              {
                yyValue = "|=";

                return new SemanticValue(yyValue, yyIndex, yyError);
              }

            case '|':
              {
                yyValue = "||";

                return new SemanticValue(yyValue, yyIndex, yyError);
              }

            default:
              /* No match. */
            }
          }

          // Nested alternative 2.

          yyValue = "|";

          return new SemanticValue(yyValue, yyChoice1, yyError);
        }

      case '=':
        {
          final int yyChoice1 = yyIndex;

          // Nested alternative 1.

          yyC = character(yyChoice1);
          if (-1 != yyC) {
            yyIndex = yyChoice1 + 1;
            if ('=' == yyC) {

              yyValue = "==";

              return new SemanticValue(yyValue, yyIndex, yyError);
            }
          }

          // Nested alternative 2.

          yyValue = "=";

          return new SemanticValue(yyValue, yyChoice1, yyError);
        }

      case '!':
        {
          final int yyChoice1 = yyIndex;

          // Nested alternative 1.

          yyC = character(yyChoice1);
          if (-1 != yyC) {
            yyIndex = yyChoice1 + 1;
            if ('=' == yyC) {

              yyValue = "!=";

              return new SemanticValue(yyValue, yyIndex, yyError);
            }
          }

          // Nested alternative 2.

          yyValue = "!";

          return new SemanticValue(yyValue, yyChoice1, yyError);
        }

      case ';':
        {
          yyValue = ";";

          return new SemanticValue(yyValue, yyIndex, yyError);
        }

      case ':':
        {
          yyValue = ":";

          return new SemanticValue(yyValue, yyIndex, yyError);
        }

      case ',':
        {
          yyValue = ",";

          return new SemanticValue(yyValue, yyIndex, yyError);
        }

      case '{':
        {
          yyValue = "{";

          return new SemanticValue(yyValue, yyIndex, yyError);
        }

      case '}':
        {
          yyValue = "}";

          return new SemanticValue(yyValue, yyIndex, yyError);
        }

      case '(':
        {
          yyValue = "(";

          return new SemanticValue(yyValue, yyIndex, yyError);
        }

      case ')':
        {
          yyValue = ")";

          return new SemanticValue(yyValue, yyIndex, yyError);
        }

      case '[':
        {
          yyValue = "[";

          return new SemanticValue(yyValue, yyIndex, yyError);
        }

      case ']':
        {
          yyValue = "]";

          return new SemanticValue(yyValue, yyIndex, yyError);
        }

      case '`':
        {
          yyValue = "`";

          return new SemanticValue(yyValue, yyIndex, yyError);
        }

      case '~':
        {
          yyValue = "~";

          return new SemanticValue(yyValue, yyIndex, yyError);
        }

      case '?':
        {
          yyValue = "?";

          return new SemanticValue(yyValue, yyIndex, yyError);
        }

      default:
        /* No match. */
      }
    }

    // Done.
    yyError = yyError.select("symbol characters expected", yyStart);
    return yyError;
  }

  // =========================================================================

  Preprocessor _tool;
  
  final String origString(final int start, final int end) throws IOException {
    final StringBuilder b = new StringBuilder(20 + end - start);
    b.append(_tool.lineMarker(column(start)));
    for (int i=start; i<end; i++) {
      final int c = character(i);
      if (c == -1)
      throw new Error();
      b.append((char)c);
    }
    return b.toString();
  }

  // =========================================================================

  /**
   * Get the specified text.
   *
   * @param s The text.
   * @return The text.
   */
  protected static final String toText(String s) {
    return s;
  }

}
