All Downloads are FREE. Search and download functionalities are using the official Maven repository.

za.co.absa.cobrix.cobol.parser.antlr.ANTLRParser.scala Maven / Gradle / Ivy

/*
 * Copyright 2018 ABSA Group Limited
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package za.co.absa.cobrix.cobol.parser.antlr

import org.antlr.v4.runtime._
import za.co.absa.cobrix.cobol.internal.Logging
import za.co.absa.cobrix.cobol.parser.CopybookParser.CopybookAST
import za.co.absa.cobrix.cobol.parser.decoders.FloatingPointFormat.FloatingPointFormat
import za.co.absa.cobrix.cobol.parser.encoding.Encoding
import za.co.absa.cobrix.cobol.parser.encoding.codepage.CodePage
import za.co.absa.cobrix.cobol.parser.exceptions.SyntaxErrorException
import za.co.absa.cobrix.cobol.parser.policies.CommentPolicy
import za.co.absa.cobrix.cobol.parser.policies.StringTrimmingPolicy.StringTrimmingPolicy

import java.nio.charset.Charset


class ThrowErrorStrategy() extends DefaultErrorStrategy {
  override def recover(recognizer: Parser, e: RecognitionException): Unit = {
    throw new SyntaxErrorException(
      e.getOffendingToken.getLine,
      "",
      "Invalid input " + getTokenErrorDisplay(e.getOffendingToken) + " at position " + e.getOffendingToken.getLine
      + ":" + (e.getOffendingToken.getCharPositionInLine + 6)
    )
  }

  @throws[RecognitionException]
  override def recoverInline(recognizer: Parser): Token = {
    throw new InputMismatchException(recognizer)
  }

  override def sync(recognizer: Parser) = {}

}


object ANTLRParser extends Logging {

  def parse(copyBookContents: String,
            enc: Encoding,
            stringTrimmingPolicy: StringTrimmingPolicy,
            commentPolicy: CommentPolicy,
            strictSignOverpunch: Boolean,
            improvedNullDetection: Boolean,
            strictIntegralPrecision: Boolean,
            decodeBinaryAsHex: Boolean,
            ebcdicCodePage: CodePage,
            asciiCharset: Charset,
            isUtf16BigEndian: Boolean,
            floatingPointFormat: FloatingPointFormat,
            fieldCodePageMap: Map[String, String]): CopybookAST = {
    val visitor = new ParserVisitor(enc, stringTrimmingPolicy, ebcdicCodePage, asciiCharset, isUtf16BigEndian, floatingPointFormat, strictSignOverpunch, improvedNullDetection, strictIntegralPrecision, decodeBinaryAsHex, fieldCodePageMap)

    val strippedContents = filterSpecialCharacters(copyBookContents).split("\\r?\\n").map(
      line =>
        truncateComments(line, commentPolicy)
    ).mkString("\n")

    val charStream = CharStreams.fromString(strippedContents)
    val lexer = new copybookLexer(charStream)
    lexer.removeErrorListeners()
    lexer.addErrorListener(new LogErrorListener(logger))

    val tokens = new CommonTokenStream(lexer)
    val parser = new copybookParser(tokens)
    parser.removeErrorListeners()
    parser.addErrorListener(new LogErrorListener(logger))
    parser.setErrorHandler(new ThrowErrorStrategy())

    visitor.visitMain(parser.main())
    visitor.ast
  }

  /**
    * Replace special characters that have semantics of spaces.
    */
  private def filterSpecialCharacters(copybook: String): String = {
    copybook
      .replace('\u00a0', ' ') // Non-breakable spaces
      .replace('\u0009', ' ') // Tabs
  }

  /**
    * Truncate all columns after configured (72th by default) one and
    * first configured (6 by default) columns (historically for line numbers)
    */
  private def truncateComments(copybookLine: String, commentPolicy: CommentPolicy): String = {
    if (commentPolicy.truncateComments) {
      if (commentPolicy.commentsUpToChar >= 0 && commentPolicy.commentsAfterChar >= 0) {
        copybookLine.slice(commentPolicy.commentsUpToChar, commentPolicy.commentsAfterChar)
      } else {
        if (commentPolicy.commentsUpToChar >= 0) {
          copybookLine.drop(commentPolicy.commentsUpToChar)
        } else {
          copybookLine.dropRight(commentPolicy.commentsAfterChar)
        }
      }
    } else {
      copybookLine
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy