/ojc-core/encodersl/encoder-coco/src/com/sun/encoder/coco/model/CocoParser.java
Java | 1334 lines | 874 code | 144 blank | 316 comment | 298 complexity | a6808b034c34480de3ded1a305a12c28 MD5 | raw file
- /*
- * BEGIN_HEADER - DO NOT EDIT
- *
- * The contents of this file are subject to the terms
- * of the Common Development and Distribution License
- * (the "License"). You may not use this file except
- * in compliance with the License.
- *
- * You can obtain a copy of the license at
- * https://open-jbi-components.dev.java.net/public/CDDLv1.0.html.
- * See the License for the specific language governing
- * permissions and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL
- * HEADER in each file and include the License file at
- * https://open-jbi-components.dev.java.net/public/CDDLv1.0.html.
- * If applicable add the following below this CDDL HEADER,
- * with the fields enclosed by brackets "[]" replaced with
- * your own identifying information: Portions Copyright
- * [year] [name of copyright owner]
- */
- /*
- * @(#)CocoParser.java
- *
- * Copyright 2004-2007 Sun Microsystems, Inc. All Rights Reserved.
- *
- * END_HEADER - DO NOT EDIT
- */
- package com.sun.encoder.coco.model;
- import java.io.IOException;
- import java.util.ArrayList;
- import java.util.Collections;
- import java.util.HashSet;
- import java.util.Iterator;
- import java.util.Set;
- import java.util.List;
- import java.util.ListIterator;
- import com.sun.encoder.coco.runtime.messages.ErrorManager;
- import com.sun.encoder.coco.runtime.messages.Message;
- import com.sun.encoder.coco.runtime.messages.MessageCatalog;
- /**
- * Reads Cobol Copybook files and creates a data model
- *
- * @author Noel Ang
- *
- */
- public class CocoParser {
- /**
- * Length of Cobol source lines
- */
- public static final int SOURCE_LINE_LENGTH = 82;
- private static Set cSourceAreas;
- private ArrayList mCols;
- private ArrayList mRows;
- private CocoLexer mLexer;
- private CocoDataModel mModel;
- private CocoDescriptionEntry mCurrentEntry;
- private CocoDescriptionEntry mLastEntry;
- private int mCol;
- private int mRow;
- private boolean mReservedWordCheck = true;
- private final ErrorManager mErrorMgr =
- ErrorManager.getManager("STC.eWay.converter.COBOLCopybook."
- + getClass().getName());
- static {
- String pkg = CocoParser.class.getPackage().getName();
- HashSet areas = new HashSet();
- areas.add(CobolSourceSequenceArea.getArea());
- areas.add(CobolSourceIndicatorArea.getArea());
- areas.add(CobolSourceAreaA.getArea());
- areas.add(CobolSourceAreaB.getArea());
- cSourceAreas = Collections.unmodifiableSet(areas);
- }
- /**
- * Create a parser.
- *
- * @param lexer CocoLexer object to use as the parser's input source
- */
- public CocoParser(CocoLexer lexer) {
- mLexer = lexer;
- mModel = new CocoDataModel();
- mCol = 1;
- mRow = 1;
- mCols = new ArrayList();
- mRows = new ArrayList();
- }
- /**
- * Parse Copybook data and create a data model.
- *
- * @throws CocoParseException
- * @throws java.io.IOException if an I/O error occurs
- */
- public CocoDataModel parse() throws CocoParseException, IOException {
- createModel();
- // resolve OCCURS with DEPENDING ON <data-name> etc
- mModel.validate();
- mModel.resolveOccurs();
- // Name mangling/resolution suspended.
- // First, this is not a parser concern, so it should be addressed elsewhere.
- // Second, COCOCO relaunch support requires the name mangling process to
- // modify its behaviour based on whether or not a relaunch is underway.
- // Name collision handling will be handled where and when it matters:
- // during OTD creation.
- //mModel.makeBaseNamesUnique();
- return mModel;
- }
- /**
- * Parse Copybook data and populate data model. If the supplied model is
- * null, a new model will be allocated instead.
- *
- * @param model Data model to fill with information
- * @throws CocoParseException
- * @throws java.io.IOException if an I/O error occurs
- */
- public CocoDataModel parse(CocoDataModel model)
- throws CocoParseException, IOException {
- if (model != null) {
- mModel = model;
- }
- return parse();
- }
- /**
- * Disable reserved word checking for item names. By default, reserved word
- * checking is enabled. The consequence of disabling it is that the parser
- * will not be able to parse item descriptions without names
- * (implied 'FILLER' items).
- *
- * @param disable <code>true</code> to disable reserved word checking.
- */
- public void disableItemNameReservedWordChecking(boolean disable) {
- mReservedWordCheck = !disable;
- }
- /**
- * Create the data model from parsed Cobol Copybook input.
- *
- * @throws CocoParseException
- * @throws java.io.IOException if an I/O error occurs
- * @see CocoDataModel
- */
- protected void createModel() throws CocoParseException, IOException {
- processEntries();
- }
- /**
- * Process parsed entries to make the data model.
- *
- * @see CocoDataModel
- * @see CocoDescriptionEntry
- */
- private void processEntries() throws CocoParseException, IOException {
- CocoDescriptionEntry entry = null;
- do {
- entry = getEntry();
- if (entry != null) {
- if (entry.getLevel() != -1) {
- mLastEntry = entry;
- /* special case: don't add 88 entries */
- if (entry.getLevel() == 88) {
- continue;
- }
- try {
- mModel.addEntry(entry);
- } catch (IllegalArgumentException iae) {
- logAndThrow("CCCB4201",
- new Object[]{iae.getLocalizedMessage()},
- ErrorManager.Severity.ERROR,
- iae,
- null);
- }
- }
- }
- } while (entry != null);
- }
- /**
- * Read one item description from the input source, and create a
- * CocoDescriptionEntry object for it.
- *
- * @return a CocoDescriptionEntry object, or null if there is no available
- * input. This method also has the side-effect of designating
- * the returned object as the "current" object for this parser
- * object.
- * @throws CocoParseException if the input cannot be parsed successfully
- * @throws java.io.IOException if an I/O error occurs
- */
- private CocoDescriptionEntry getEntry()
- throws CocoParseException,
- IOException {
- CocoDescriptionEntry entry = null;
- if (skipSequenceArea()) {
- entry = mCurrentEntry = new CocoDescriptionEntry();
- if (parseIndicatorArea(entry)) {
- // EOL
- consumeEOL();
- } else {
- // indicator already parsed
- boolean isEOLReached = parseAreaA(entry);
- if (isEOLReached) {
- consumeEOL();
- }
- if (!isEOLReached || entry.isContinuation()) {
- // either a blank but continue line or a line that has B area
- parseAreaB(entry);
- skipLine();
- }
- }
- } else {
- // no token following - but check EOL and EOF
- // an entry to be skipped
- CocoToken token = getNextToken();
- ungetToken(token);
- if (token != null) {
- if (token.isEOL()) {
- // return a dummy entry so getEntries() will continue
- entry = new CocoDescriptionEntry();
- // consume it
- consumeEOL();
- } else if (token.isEOF()) {
- // THE END
- entry = null;
- }
- } else {
- // unlikely
- }
- }
- return entry;
- }
- private void consumeEOL() throws IOException {
- CocoToken token = getNextToken();
- if (token != null && token.isEOL()) {
- // consume EOL
- updatePosition(token);
- } else {
- ungetToken(token);
- }
- }
- /**
- * Process the Indicator Area of the current Cobol source line.
- *
- * @param entry Description entry to initialize/populate with information
- * from Indicator Area.
- * @return true if EOL is reached, or false otherwise.
- * @throws CocoParseException if a parsing error occurs
- * @throws java.io.IOException if an I/O error occurs
- */
- private boolean parseIndicatorArea(CocoDescriptionEntry entry)
- throws CocoParseException, IOException {
- CocoToken token = getNextToken();
- if (!isInIndicatorArea(token)) {
- return false;
- } else {
- if (token.isEOL()) {
- ungetToken(token);
- return true;
- }
- /* Ignore entries with no indicators */
- if (isSpace(token)) {
- skipIndicatorArea();
- return false;
- }
- /* Ignore comments by consuming rest of area */
- if (isComment(token)) {
- entry.setComment(true);
- skipIndicatorArea();
- return false;
- }
- String value = token.getStringValue().toUpperCase();
- /* Ignore debugging lines */
- if (value.equals(CocoLanguage.DEBUGGING_INDICATOR)) {
- entry.setIndicatorValue(value);
- return false;
- }
- /* Process continuation entries */
- if (value.equals(CocoLanguage.HYPHEN)) {
- /*
- * This is not a conclusive indication; primary checking
- * is done during parsing of Area A
- */
- entry.setContinuation(true);
- return false;
- }
- /* Unrecognized indicator */
- logAndThrow("CCCB4202", new Object[]{token.getStringValue()},
- ErrorManager.Severity.ERROR, null, null);
- return false;
- }
- }
- /**
- * Process the Area A of the current Cobol source line.
- *
- * @param entry Description entry to initialize/populate with information
- * from Area A
- * @return true if EOL is reached, or false otherwise.
- * @throws CocoParseException if a parsing error occurs
- * @throws java.io.IOException if an I/O error occurs
- */
- private boolean parseAreaA(CocoDescriptionEntry entry)
- throws CocoParseException, IOException {
- boolean eodEncountered = false;
- if (entry.isComment()) {
- skipAreaA();
- return eodEncountered;
- }
- CocoToken token = null;
- while (true) {
- token = getNextToken();
- if (token == null || token.isEOF()) {
- ungetToken(token);
- break;
- }
- // scan until the first non blank char - break for level number parsing
- if (!CocoLanguage.SPACE.equals(token.getStringValue())) {
- ungetToken(token);
- break;
- } else {
- if (token.isEOL()) {
- ungetToken(token);
- return true;
- }
- if (!isInAreaA(token) && !isPartiallyInAreaA(token)) {
- ungetToken(token);
- break;
- }
- }
- }
- /* per 89392 a EOL is possible in area A, B, and indicator area
- */
- if (token == null || token.isEOF()) {
- ungetToken(token);
- return false;
- }
- /*
- * If Area A is blank, depending on what I find in Area B later,
- * it's either a blank line, a continuation line, or a free-standing
- * line whose level number is in Area B.
- *
- * Right now, assume this is a continuation line.
- *
- * If Area A is NOT blank, but the Indicator Area marked this as a
- * continuation line, it's an error.
- */
- if (!isInAreaA(token) && !isPartiallyInAreaA(token)) {
- entry.setContinuation(true);
- return false;
- } else if (entry.isContinuation()) {
- logAndThrow("CCCB4204", null, ErrorManager.Severity.ERROR, null, token);
- }
- parseLevelNumber(entry);
- skipSpacesOrPeriods(true);
- token = getNextToken();
- if (token != null && !token.isEOL()) {
- ungetToken(token);
- parseDataName(entry);
- }
- return false;
- }
- /**
- * Process the Area B of the current Cobol source line.
- *
- * @param entry Description entry to initialize/populate with information
- * from Area B
- * @throws CocoParseException if a parsing error occurs
- * @throws java.io.IOException if an I/O error occurs
- */
- private void parseAreaB(CocoDescriptionEntry entry)
- throws CocoParseException, IOException {
- if (entry.isComment()) {
- skipAreaB();
- return;
- }
- /* The entry being processed may be a blank line */
- skipOptionalSpaces(false);
- CocoToken token = getNextTokenAreaB(true, true);
- ungetToken(token);
- if (token == null || token.isEOF() || !isInAreaB(token)) {
- entry.setContinuation(false);
- return;
- }
- if ( entry.getLevel() == -1
- && ( entry.getName() == null || entry.getName().trim().length() == 0 )
- && token != null
- && token.isEOL() )
- return;
-
- /* I never found a level number while scanning Area A */
- if (entry.getLevel() == -1) {
- entry.setContinuation(false);
- parseLevelNumber(entry);
- }
- /* a level number and data name already been parsed before parseAreaB() */
- if (entry.getLevel() > 0
- && entry.getName() != null
- && entry.getName().length() > 0) {
- // already got a data name in A or A across B
- } else {
- parseDataName(entry);
- }
- parseRedefinesClause(entry);
- boolean gotBlankClause = false;
- boolean gotExternalClause = false;
- boolean gotGlobalClause = false;
- boolean gotJustifiedClause = false;
- boolean gotOccursClause = false;
- boolean gotPictureClause = false;
- boolean gotSignClause = false;
- boolean gotSynchronizedClause = false;
- boolean gotUsageClause = false;
- boolean gotValueClause = false;
- boolean gotDateFormatClause = false;
- boolean done = false;
- int prevCount = 0;
- while (!done) {
- int passCount = 0;
- if (!gotBlankClause) {
- gotBlankClause = parseBlankWhenZeroClause(entry);
- passCount += (gotBlankClause ? 1 : 0);
- }
- if (!gotExternalClause) {
- gotExternalClause = parseExternalClause(entry);
- passCount += (gotExternalClause ? 1 : 0);
- }
- if (!gotGlobalClause) {
- gotGlobalClause = parseGlobalClause(entry);
- passCount += (gotGlobalClause ? 1 : 0);
- }
- if (!gotJustifiedClause) {
- gotJustifiedClause = parseJustifiedClause(entry);
- passCount += (gotJustifiedClause ? 1 : 0);
- }
- if (!gotOccursClause) {
- gotOccursClause = parseOccursClause(entry); //also indexed by...
- passCount += (gotOccursClause ? 1 : 0);
- }
- if (!gotPictureClause) {
- gotPictureClause = parsePictureClause(entry);
- passCount += (gotPictureClause ? 1 : 0);
- }
- if (!gotSignClause) {
- gotSignClause = parseSignClause(entry);
- passCount += (gotSignClause ? 1 : 0);
- }
- if (!gotSynchronizedClause) {
- gotSynchronizedClause = parseSynchronizedClause(entry);
- passCount += (gotSynchronizedClause ? 1 : 0);
- }
- if (!gotUsageClause) {
- gotUsageClause = parseUsageClause(entry);
- passCount += (gotUsageClause ? 1 : 0);
- }
- if (!gotValueClause) {
- gotValueClause = parseValueClause(entry);
- passCount += (gotValueClause ? 1 : 0);
- }
- if (!gotDateFormatClause) {
- gotDateFormatClause = parseDateFormatClause(entry);
- passCount += (gotDateFormatClause ? 1 : 0);
- }
- skipOptionalSpaces(true);
- token = getNextTokenAreaB(false, true);
- ungetToken(token);
- if (token == null || token.isEOF()) {
- logAndThrow("CCCB4203", new Object[]{entry.getName()},
- ErrorManager.Severity.ERROR, null, null);
- }
- String value = token.getStringValue();
- done = (value.equals(CocoLanguage.PERIOD)
- || value.equals(CocoLanguage.PERIOD_S));
- if (!done) {
- if (passCount <= prevCount) {
- logAndThrow("CCCB4205", new Object[]{value},
- ErrorManager.Severity.ERROR, null, token, entry);
- }
- }
- prevCount = passCount;
- }
- skipLine();
- }
- /**
- * Read parser input for a level number and assign it to a description entry.
- *
- * @param entry CocoDescriptionEntry to initialize with the level number
- * @throws CocoParseException if a parsing error occurs
- * @throws java.io.IOException if an I/O error occurs
- */
- private void parseLevelNumber(CocoDescriptionEntry entry)
- throws CocoParseException, IOException {
- CobolSourceArea area = getCurrentArea();
- CocoToken token = null;
- skipOptionalSpaces(true);
- if (area instanceof CobolSourceAreaB) {
- token = getNextTokenAreaB(false, true);
- } else {
- token = getNextToken();
- }
- if (token != null && !token.isEOF()) {
- if (token.getType() == CocoTokenTypes.NUM_TOKEN) {
- int level = -1;
- try {
- level = Integer.parseInt(token.getStringValue());
- } catch (NumberFormatException nfe) {
- logAndThrow("CCCB4108", new Object[]{
- entry.getName(),
- String.valueOf(token.getStringValue())},
- ErrorManager.Severity.ERROR, nfe, token);
- }
- try {
- entry.setLevel(level);
- } catch (IllegalArgumentException e) {
- logAndThrow("CCCB4108", new Object[]{
- entry.getName(),
- String.valueOf(token.getStringValue())},
- ErrorManager.Severity.ERROR, e, token);
- }
- } else {
- logAndThrow("CCCB4108", new Object[]{
- entry.getName(),
- String.valueOf(token.getStringValue())},
- ErrorManager.Severity.ERROR, null, token);
- }
- } else {
- logAndThrow("CCCB4206", new Object[]{entry.getName()},
- ErrorManager.Severity.ERROR, null, null);
- }
- }
- /**
- * Attempt to read parser input for a data name, and make it the name of a
- * description entry. If no valid name can be obtained, the name of the
- * description entry is set to null (to nothing).
- *
- * @param entry CocoDescriptionEntry to initialize with the name
- * @throws CocoParseException if a parsing error occurs
- * @throws java.io.IOException if an I/O error occurs
- */
- private void parseDataName(CocoDescriptionEntry entry)
- throws CocoParseException, IOException {
- try {
- String name = parseCobolWord(mReservedWordCheck);
- entry.setName(name);
- entry.setOriginalName(name);
- skipClauseSeparator();
- } catch (ReservedWordEncounteredException rwe) {
- // since the data name could be FILLER or empty (blank)
- // we should let the parsing continue
- if (mReservedWordCheck) {
- entry.setReservedWordAfterLevel(rwe);
- //throw rwe;
- }
- // the following code is unlikely be reached
- // but put it here in case - fall back to old logic;
- String name = formWord("FILLER", false);
- if (name != null && !"".equals(name.trim())) {
- entry.setName(name);
- entry.setOriginalName(name);
- } else {
- entry.setName("BLANK");
- entry.setOriginalName("");
- }
- } catch (CocoParseException cpe) {
- String name = formWord("FILLER", false);
- if (name != null && !"".equals(name.trim())) {
- entry.setName(name);
- entry.setOriginalName(name);
- } else {
- entry.setName("BLANK");
- entry.setOriginalName("");
- }
- }
- }
- /**
- * Process 'Redefines' clause from the parser input, and initialize a
- * description entry with its information. If a Redefines clause is not
- * available, the entry is unchanged.
- *
- * @param entry CocoDescriptionEntry to initialize with the clause information
- * @throws CocoParseException if a parsing error occurs
- * @throws java.io.IOException if an I/O error occurs
- */
- private void parseRedefinesClause(CocoDescriptionEntry entry)
- throws CocoParseException, IOException {
- if (expectWord("REDEFINES")) {
- skipOptionalSpaces(true);
- // if EOL encountered - should continue to next B area
- // we must be in area B - so should call getNextTokenAreaB to jump to the
- // next point;
- CocoToken token = this.getNextTokenAreaB(false, true);
- if (token == null || token.isEOF()) {
- // error
- logAndThrow("CCCB4203",
- new Object[]{entry.getInfo()},
- ErrorManager.Severity.ERROR,
- null,
- null);
- }
- if (token.isEOL()) {
- // go to next line and scan for a word as redefined target
- token = this.getNextTokenAreaB(false, true);
- if (token == null || token.isEOF()) {
- logAndThrow("CCCB4203",
- new Object[]{entry.getInfo()},
- ErrorManager.Severity.ERROR,
- null,
- null);
- }
- }
- ungetToken(token);
- String name = parseCobolWord(mReservedWordCheck);
- CocoDescriptionEntry redefineTarget = mModel.findRedefineTarget(entry, name);
- if (redefineTarget == null) {
- logAndThrow("CCCB4207", new Object[]{
- name,
- entry.getName()},
- ErrorManager.Severity.ERROR, null, null);
- } else if (redefineTarget == entry) {
- logAndThrow("CCCB4114", new Object[]{entry.getName()},
- ErrorManager.Severity.ERROR, null, null);
- } else if (redefineTarget.getLevel() != entry.getLevel()) {
- logAndThrow("CCCB4116", new Object[]{
- entry.getName(),
- redefineTarget.getName(),
- String.valueOf(entry.getLevel()),
- String.valueOf(redefineTarget.getLevel())},
- ErrorManager.Severity.ERROR, null, null);
- } else {
- try {
- entry.setRedefinedTarget(redefineTarget);
- } catch (IllegalArgumentException e) {
- } catch (IllegalStateException e) {
- // TODO - implement
- }
- }
- skipClauseSeparator();
- }
- }
- /**
- * Process 'Blank When Zero' clause from the parser input, and initialize a
- * description entry with its information. If a Blank clause is not available,
- * the entry is also updated with that information.
- *
- * @param entry CocoDescriptionEntry to initialize with the clause information
- * @return true if a 'blank when zero' clause was consumed, false otherwise.
- * @throws CocoParseException if a parsing error occurs
- * @throws java.io.IOException if an I/O error occurs
- */
- private boolean parseBlankWhenZeroClause(CocoDescriptionEntry entry)
- throws CocoParseException, IOException {
- boolean gotClause = true;
- if (expectWord("BLANK")) {
- expectWord("WHEN");
- if (!expectWord("ZERO")) {
- if (!expectWord("ZEROS")) {
- if (!expectWord("ZEROES")) {
- logAndThrow("CCCB4208", null, ErrorManager.Severity.ERROR, null, null);
- } else {
- entry.setBlankWhenZero(true);
- skipClauseSeparator();
- }
- } else {
- entry.setBlankWhenZero(true);
- skipClauseSeparator();
- }
- } else {
- entry.setBlankWhenZero(true);
- skipClauseSeparator();
- }
- } else {
- entry.setBlankWhenZero(false);
- gotClause = false;
- }
- return gotClause;
- }
- /**
- * Process 'External' clause from the parser input, and initialize a
- * description entry with its information. If a External clause is not
- * available, the entry is unchanged.
- *
- * @param entry CocoDescriptionEntry to initialize with the clause information
- * @return true if a 'external' clause was consumed, false otherwise.
- * @throws CocoParseException if a parsing error occurs
- * @throws java.io.IOException if an I/O error occurs
- */
- private boolean parseExternalClause(CocoDescriptionEntry entry)
- throws CocoParseException, IOException {
- boolean gotClause = false;
- /* EXTERNAL clause not supported (ignored) */
- if (expectWord("EXTERNAL")) {
- skipClauseSeparator();
- gotClause = true;
- }
- return gotClause;
- }
- /**
- * Process 'Global' clause from the parser input, and initialize a
- * description entry with its information. If a Global clause is not
- * available, the entry is unchanged.
- *
- * @param entry CocoDescriptionEntry to initialize with the clause information
- * @return true if a 'global' clause was consumed, false otherwise.
- * @throws CocoParseException if a parsing error occurs
- * @throws java.io.IOException if an I/O error occurs
- */
- private boolean parseGlobalClause(CocoDescriptionEntry entry)
- throws CocoParseException, IOException {
- boolean gotClause = false;
- /* GLOBAL clause not supported (ignored) */
- if (expectWord("GLOBAL")) {
- skipClauseSeparator();
- gotClause = true;
- }
- return gotClause;
- }
- /**
- * Process 'Justified' clause from the parser input, and initialize a
- * description entry with its information.
- *
- * @param entry CocoDescriptionEntry to initialize with the clause information
- * @return true if a 'justified' clause was consumed, false otherwise.
- * @throws CocoParseException if a parsing error occurs
- * @throws java.io.IOException if an I/O error occurs
- */
- private boolean parseJustifiedClause(CocoDescriptionEntry entry)
- throws CocoParseException, IOException {
- boolean gotClause = false;
- if (expectWord("JUSTIFIED") || expectWord("JUST")) {
- expectWord("RIGHT");
- entry.setJustified(true);
- skipClauseSeparator();
- gotClause = true;
- } else {
- entry.setJustified(false);
- }
- return gotClause;
- }
- /**
- * Process 'Occurs' clause from the parser input, and initialize a
- * description entry with its information.
- *
- * @param entry CocoDescriptionEntry to initialize with the clause information
- * @return true if a 'occurs' clause was consumed, false otherwise.
- * @throws CocoParseException if a parsing error occurs
- * @throws java.io.IOException if an I/O error occurs
- */
- private boolean parseOccursClause(CocoDescriptionEntry entry)
- throws CocoParseException, IOException {
- boolean gotClause = false;
- if (expectWord("OCCURS")) {
- /* OCCURS cannot occur for level 01, 66, 77, or 88 entries */
- int level = entry.getLevel();
- if (level == 1 || level == 66 || level == 77 || level == 88) {
- logAndThrow("CCCB4209", new Object[]{
- entry.getName()
- }, ErrorManager.Severity.ERROR, null, null);
- }
- CocoToken token = null;
- if (skipOptionalSpaces(true)) {
- token = this.getNextToken();
- }
- int count1 = 0;
- int count2 = 0;
- /* "OCCURS n"... */
- token = getNextTokenAreaB(false, true);
- if (token == null || token.isEOF()) {
- logAndThrow("CCCB4203",
- new Object[]{entry.getInfo()},
- ErrorManager.Severity.ERROR,
- null,
- null);
- }
- if (token.isEOL()) {
- // next token after EOL
- token = getNextTokenAreaB(false, true);
- if (token == null || token.isEOF()) {
- logAndThrow("CCCB4203",
- new Object[]{entry.getInfo()},
- ErrorManager.Severity.ERROR,
- null,
- null);
- }
- }
- if (token.getType() == CocoTokenTypes.NUM_TOKEN) {
- try {
- count1 = Integer.parseInt(token.getStringValue());
- count2 = count1;
- } catch (NumberFormatException nfe) {
- logAndThrow("CCCB4210",
- new Object[]{token.getStringValue()},
- ErrorManager.Severity.ERROR, nfe, token);
- }
- }
- /* "OCCURS n to m..." */
- if (expectWord("TO")) { // OCCURS count1 TO...
- if (skipOptionalSpaces(true)) {
- token = this.getNextToken();
- }
- token = getNextTokenAreaB(false, true);
- if (token == null || token.isEOF()) {
- logAndThrow("CCCB4203",
- new Object[]{entry.getInfo()},
- ErrorManager.Severity.ERROR,
- null,
- null);
- }
- if (token.isEOL()) {
- token = getNextTokenAreaB(false, true);
- if (token == null || token.isEOF()) {
- logAndThrow("CCCB4203", new Object[]{entry.getName()},
- ErrorManager.Severity.ERROR, null, token);
- }
- }
- if (token.getType() == CocoTokenTypes.NUM_TOKEN) {
- try {
- int count = Integer.parseInt(token.getStringValue());
- count2 = count;
- } catch (NumberFormatException nfe) {
- logAndThrow("CCCB4210",
- new Object[]{token.getStringValue()},
- ErrorManager.Severity.ERROR, nfe, token);
- }
- }
- if (count1 < 0 || count2 <= count1) {
- logAndThrow("CCCB4118", new Object[]{
- String.valueOf(count1),
- String.valueOf(count2)},
- ErrorManager.Severity.ERROR, null, token);
- }
- } else if (count1 < 1) {
- logAndThrow("CCCB4117", new Object[]{String.valueOf(count1)},
- ErrorManager.Severity.ERROR, null, token);
- }
- expectWord("TIMES");
- /* "OCCURS" ... DEPENDING ON */
- if (expectWord("DEPENDING")) {
- // When the "DEPENDS ON" phrase is encountered
- // completing a "Foo OCCURS x TIMES" statement,
- // changes the semantic from "Foo occurs x times"
- // to "Foo can occur up to x times". In other words,
- // minimum recurrence count is no longer equal to the
- // maximum recurrence count; it becomes 0.
- count1 = 0;
- expectWord("ON");
- if (skipOptionalSpaces(true)) {
- token = this.getNextToken();
- }
- token = getNextTokenAreaB(false, true);
- if (token == null || token.isEOF()) {
- logAndThrow("CCCB4203", new Object[]{entry.getName()},
- ErrorManager.Severity.ERROR, null, token);
- }
- if (token.isEOL()) {
- // next token after EOL
- token = getNextTokenAreaB(false, true);
- if (token == null || token.isEOF()) {
- logAndThrow("CCCB4203", new Object[]{entry.getName()},
- ErrorManager.Severity.ERROR, null, token);
- }
- }
- ungetToken(token);
- String entryName = parseCobolWord(mReservedWordCheck);
- if (entryName == null || entryName.trim().length() == 0) {
- String item1 = entry.getLevel() + " " + entry.getName();
- // expecting a data name after DEPENDING ON
- token = getNextTokenAreaB(false, true);
- logAndThrow("CCCB4224", new Object[]{
- "data name",
- "DEPENDING ON",
- item1},
- ErrorManager.Severity.ERROR, null, token);
- }
- // the data-name for DEPENDING ON can be qualified
- // e.g., F1 OF L1 OF L2 OF R2 etc
- List qualifiers = null;
- while (expectWord("OF")) {
- if (skipOptionalSpaces(true)) {
- token = this.getNextToken();
- }
- token = getNextTokenAreaB(false, true);
- if (token == null || token.isEOF()) {
- logAndThrow("CCCB4203", new Object[]{entry.getName()},
- ErrorManager.Severity.ERROR, null, token);
- }
- if (token.isEOL()) {
- // next token after EOL
- token = getNextTokenAreaB(false, true);
- if (token == null || token.isEOF()) {
- logAndThrow("CCCB4203",
- new Object[]{entry.getName()},
- ErrorManager.Severity.ERROR, null, token);
- }
- }
- ungetToken(token);
- String qualifierName = parseCobolWord(mReservedWordCheck);
- if (qualifierName == null || qualifierName.trim().length() == 0) {
- token = getNextTokenAreaB(false, true);
- logAndThrow("CCCB4224", new Object[]{
- "data name",
- "OF",
- entry.getInfo()},
- ErrorManager.Severity.ERROR, null, token);
- }
- if (qualifiers == null) {
- qualifiers = new ArrayList(1);
- }
- qualifiers.add(qualifierName);
- }
- entry.setOccursResolveLater(count1, count2, qualifiers, entryName);
- mModel.addOccurs(entry);
- } else if (count1 == count2) {
- entry.setOccurs(count1);
- } else {
- token = getNextTokenAreaB(false, true);
- logAndThrow("CCCB4215", new Object[]{entry.getName()},
- ErrorManager.Severity.ERROR, null, token);
- }
- /* ignore rest of OCCURS clause (ASCENDING KEY, INDEX BY phrases et al) */
- if (expectWord("ASCENDING") || expectWord("DESCENDING")) {
- expectWord("KEY");
- expectWord("IS");
- skipOptionalSpaces(true);
- token = getNextTokenAreaB(false, true);
- if (token == null || token.isEOF()) {
- logAndThrow("CCCB4203", new Object[]{entry.getName()},
- ErrorManager.Severity.ERROR, null, token);
- }
- if (token.isEOL()) {
- // next token after EOL
- token = getNextTokenAreaB(false, true);
- if (token == null || token.isEOF()) {
- logAndThrow("CCCB4203", new Object[]{entry.getName()},
- ErrorManager.Severity.ERROR, null, token);
- }
- }
- ungetToken(token);
- String wd = parseCobolWord(mReservedWordCheck);
- if (wd == null || wd.trim().length() == 0) {
- token = getNextTokenAreaB(false, true);
- logAndThrow("CCCB4224", new Object[]{
- "data name",
- "ASCENDING or DESCENDINNG [KEY] [IS]",
- entry.getInfo()},
- ErrorManager.Severity.ERROR, null, token);
- }
- }
- if (expectWord("INDEXED")) {
- expectWord("BY");
- skipOptionalSpaces(true);
- token = getNextTokenAreaB(false, true);
- if (token == null || token.isEOF()) {
- logAndThrow("CCCB4203", new Object[]{entry.getName()},
- ErrorManager.Severity.ERROR, null, token);
- }
- if (token.isEOL()) {
- // get next token after EOL
- token = getNextTokenAreaB(false, true);
- if (token == null || token.isEOF()) {
- logAndThrow("CCCB4203", new Object[]{entry.getName()},
- ErrorManager.Severity.ERROR, null, token);
- }
- }
- ungetToken(token);
- while (true) {
- try {
- // try to parse 1 or more indexed variables
- // Open-ESB issue 2296
- String wd = parseCobolWord(mReservedWordCheck);
- if (wd == null || wd.trim().length() == 0) {
- token = getNextTokenAreaB(false, true);
- logAndThrow("CCCB4224", new Object[]{
- "data name",
- "INDEXED [BY]",
- entry.getInfo()},
- ErrorManager.Severity.ERROR, null, token);
- }
- } catch (CocoParseException e) {
- break;
- }
- }
- skipUntilNextClause();
- } else {
- skipClauseSeparator();
- }
- gotClause = true;
- }
- return gotClause;
- }
- /**
- * Consume tokens until a word is encountered that is the start of a
- * recognized clause. USE THIS METHOD ONLY WHEN CURRENT TOKEN POSITION
- * IS IN AREA B, OTHERWISE THE BEHAVIOUR IS UNDEFINED.
- *
- * @throws CocoParseException if EOD encountered
- * @throws IOException if any I/O error occurs
- */
- private void skipUntilNextClause() throws CocoParseException, IOException {
- final List tokenList = new ArrayList();
- final StringBuffer wordBuffer = new StringBuffer();
- String word;
- ListIterator it;
- CocoToken tok;
- try {
- // loop for skipping words
- while(true) {
- tokenList.clear();
- skipOptionalSpaces(true);
- // loop for skipping tokens
- while(true) {
- tok = getNextTokenAreaB(false, true);
- if (null == tok) {
- break;
- }
-
- if (tok.getType() == CocoTokenTypes.SEPARATOR_TOKEN) {
- ungetToken(tok);
- break;
- }
- wordBuffer.append(tok.getStringValue());
- tokenList.add(0, tok);
- }
- // no word formed
- if (wordBuffer.length() == 0) {
- break;
-
- // if word is the start of a clause, then stuff the
- // tokens that formed it, back into the token stream; I'm done
- } else {
- word = wordBuffer.toString();
- wordBuffer.delete(0, word.length());
- if (CocoLanguage.isClauseWord(word)) {
- it = tokenList.listIterator();
- while (it.hasNext()) {
- ungetToken((CocoToken) it.next());
- }
- break;
- }
- }
- }
- } finally {
- tokenList.clear();
- wordBuffer.delete(0, wordBuffer.length());
- }
- }
- /**
- * Process 'Picture'/'Pic' clause from the parser input, and initialize a
- * description entry with its information.
- *
- * @param entry CocoDescriptionEntry to initialize with the clause information
- * @return true if a 'picture' clause was consumed, false otherwise.
- * @throws CocoParseException if a parsing error occurs
- * @throws java.io.IOException if an I/O error occurs
- */
- private boolean parsePictureClause(CocoDescriptionEntry entry)
- throws CocoParseException, IOException {
- boolean gotClause = false;
- if (expectWord("PIC") || expectWord("PICTURE")) {
- expectWord("IS");
- skipOptionalSpaces(true);
- // make sure EOL is skipped
- CocoToken token = getNextTokenAreaB(false, true);
- if (token == null || token.isEOF()) {
- logAndThrow("CCCB4203", new Object[]{entry.getName()},
- ErrorManager.Severity.ERROR, null, token);
- }
- if (token.isEOL()) {
- // go to next line and scan for a word as redefined target
- token = this.getNextTokenAreaB(false, true);
- if (token == null || token.isEOF()) {
- // error
- if (token == null || token.isEOF()) {
- logAndThrow("CCCB4203", new Object[]{entry.getName()},
- ErrorManager.Severity.ERROR, null, token);
- }
- }
- }
- ungetToken(token);
- parsePictureLiteral(entry);
- skipClauseSeparator();
- gotClause = true;
- }
- return gotClause;
- }
- /**
- * Process a Picture clause's character string from the parser input, and
- * initialize a description entry with its information.
- *
- * @param entry CocoDescriptionEntry to initialize with the clause information
- * @throws CocoParseException if a parsing error occurs
- * @throws java.io.IOException if an I/O error occurs
- */
- private void parsePictureLiteral(CocoDescriptionEntry entry)
- throws CocoParseException, IOException {
- StringBuffer buffer = new StringBuffer();
- boolean foundPart = false;
- skipOptionalSpaces(true);
- do {
- CocoToken token = getNextTokenAreaB(true, true);
- if (token == null || token.isEOF()) {
- break;
- }
- String value = token.getStringValue();
- CocoTokenTypes type = token.getType();
- foundPart =
- (type == CocoTokenTypes.ALNUM_TOKEN
- || type == CocoTokenTypes.NUM_TOKEN
- || value.equals(CocoLanguage.SLANT)
- || value.equals(CocoLanguage.COMMA)
- || value.equals(CocoLanguage.PERIOD)
- || value.equals(CocoLanguage.PLUS)
- || value.equals(CocoLanguage.HYPHEN)
- || value.equals(CocoLanguage.ASTERISK)
- || value.equals(CocoLanguage.LPARENS)
- || value.equals(CocoLanguage.RPARENS)
- || CocoLanguage.isCurrencySymbol(value));
- /*
- * If I find a period or comma, in order to be part of the literal,
- * it must be followed immediately one of the following:
- * - a separator period
- * - a separator comma (not just a comma)
- * - a separator semicolon (not just a semicolon)
- */
- if (value.equals(CocoLanguage.PERIOD) || value.equals(CocoLanguage.COMMA)) {
- CocoToken nextToken = getNextTokenAreaB(true, true);
- if (nextToken == null) {
- foundPart = false;
- } else {
- String nextValue = nextToken.getStringValue();
- if (nextValue.equals(CocoLanguage.SPACE)
- || nextValue.charAt(0) == '\r'
- || nextValue.equals("EOF")) {
- // added check on "EOF" here, see open-esb issue 2273
- foundPart = false;
- ungetToken(nextToken);
- } else if (nextValue.equals(CocoLanguage.COMMA)
- || nextValue.equals(CocoLanguage.SEMICOLON)
- || nextValue.equals(CocoLanguage.PERIOD)) {
- CocoToken anotherToken = getNextTokenAreaB(true, true);
- ungetToken(nextToken);
- if (anotherToken != null) {
- String anotherValue = anotherToken.getStringValue();
- ungetToken(anotherToken);
- foundPart = anotherValue.equals(CocoLanguage.SPACE);
- }
- } else {
- ungetToken(nextToken);
- }
- }
- }
- if (foundPart) {
- buffer.append(value);
- } else {
- ungetToken(token);
- }
- } while (foundPart);
- String picstr = "";
- try {
- picstr = buffer.toString();
- CocoPicture picture = new CocoPicture(picstr);
- entry.setPicture(picture);
- } catch (IllegalArgumentException iae) {
- logAndThrow("CCCB4218", new Object[]{
- entry.getName(),
- picstr,
- iae.getLocalizedMessage()},
- ErrorManager.Severity.ERROR, iae, null);
- }
- }
- /**
- * Process 'Sign' clause from the parser input, and initialize a description
- * entry with its information.
- *
- * @param entry CocoDescriptionEntry to initialize with the clause information
- * @return true if a 'sign' clause was consumed, false otherwise.
- * @throws CocoParseException if a parsing error occurs
- * @throws java.io.IOException if an I/O error occurs
- */
- private boolean parseSignClause(CocoDescriptionEntry entry)
- throws CocoParseException, IOException {
- boolean gotClause = true;
- if (expectWord("SIGN")) {
- expectWord("IS");
- if (expectWord("LEADING")) {
- entry.setSign(CocoSign.LeadingSign);
- } else if (expectWord("TRAILING")) {
- entry.setSign(CocoSign.TrailingSign);
- } else {
- logAndThrow("CCCB4219", new Object[]{entry.getName()},
- ErrorManager.Severity.ERROR, null, null);
- }
- if (expectWord("SEPARATE")) {
- expectWord("CHARACTER");
- entry.setSeparateSign(true);
- }
- skipClauseSeparator();
- } else if (expectWord("LEADING")) {
- entry.setSign(CocoSign.LeadingSign);
- if (expectWord("SEPARATE")) {
- expectWord("CHARACTER");
- entry.setSeparateSign