#!/bin/bash
## Licensed to the Apache Software Foundation (ASF) under one
## or more contributor license agreements.  See the NOTICE file
## distributed with this work for additional information
## regarding copyright ownership.  The ASF licenses this file
## to you 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.

# Parser builder

GRAMMAR="${GRAMMAR:-master.jj}"

# --------------------------------------------------------

function grammar
{
    FILE="$1"
    PKG="$2"
    CLASS="$3"

##     NAME="$(echo $N | tr '[:lower:]' '[:upper:]')"
##     DIR1="$(echo $N | tr '[:upper:]' '[:lower:]')"
    
    DIR="../src/main/java/org/apache/jena/sparql/lang/$PKG"

    (cd "$DIR" ; rm -f TokenMgrError.java ParseException.java Token.java JavaCharStream.java )

    echo "---- Process grammar -- $1"
    javacc -OUTPUT_DIRECTORY=$DIR  -JDK_VERSION=1.7 "${FILE}"
    RC=$?

    [ "$RC" = 0 ] || return

##     echo "---- Create HTML"
##     jjdoc -OUTPUT_FILE=${FILE%%.jj}.html "${FILE}"
    echo "---- Create text form"
    jjdoc -TEXT=true -OUTPUT_FILE=${FILE%%.jj}.txt "${FILE}"

  # Fix unnecessary imports
    echo "---- Fixing Java warnings in ${NAME}TokenManager ..."

    F="$DIR/${CLASS}TokenManager.java"

    sed -e 's/import .*//' -e 's/MatchLoop: do/do/' \
        -e 's/int hiByte = (int)(curChar/int hiByte = (curChar/' \
	< $F > F
    mv F $F

##     # Java5+ fixups
##     echo "---- Fixing Java warnings in JavaCharStream ..."
##     # Deprecated:
##     #   public int getColumn()
##     #   public int getLine()
##     F="$DIR/JavaCharStream.java"
##     if [ -e "$F" ]
## 	then
## 	sed -e 's/@Deprecated //' \
## 	    -e 's/public int getColumn/@Deprecated public int getColumn/' \
## 	    -e 's/public int getLine/@Deprecated public int getLine/' < $F > F
## 	mv F $F
##     fi
## 

##     echo "---- Fixing Java warnings in ParseException ..."
##     #Override:
##     #   public String getMessage()
##     F="$DIR/ParseException.java"
##     sed -e 's/@Override //' \
## 	-e 's/public String getMessage/@Override public String getMessage/' < $F > F
##     mv F $F

    echo "---- Fixing Java warnings in Token ..."
    F="$DIR/Token.java"
    sed -e 's/@Override //' \
	-e 's/public String toString/@Override public String toString/' < $F > F
    mv F $F


    echo "---- Fixing Java warnings in TokenMgrError ..."
    # Override:
    #   public String getMessage()
    F="$DIR/TokenMgrError.java"
    sed -e 's/@Override //' \
	-e 's/public String getMessage/@Override public String getMessage/' < $F > F
    mv F $F

    echo "---- Fixing Java warnings in ${CLASS} ..."
    F="$DIR/${CLASS}.java"
    sed -e 's/public class /\n@SuppressWarnings("all")\npublic class /' < $F > F 
##     sed -e 's/for (java.util.Iterator/for (java.util.Iterator<int[]>/' \
## 	-e 's/(int\[\])//' < $F > F
    mv F $F

    echo "---- Done"
}

# --------------------------------------------------------

if [ $# == 0 ]
then
    # Not sparql10
    set -- sparql11 arq
    ## echo "Usage: grammar [arq|sparql]" 1>&2
    ## exit 1
    fi

for G in "$@"
do
  case "$G" in
      sparql10|sparql_10.jj)
    
          # SPARQL 1.0 - use a static copy.
          # The parser that is exactly the working group grammar.
##           #### cat "$GRAMMAR" | cpp -P -DSPARQL -DSPARQL_10 > sparql_10.jj
##           grammar sparql_10.jj sparql_10 SPARQLParser10
##           ;;
         echo "SPARQL 1.0 - not rebuilt"
          ;;

      sparql11|sparql_11.jj)
	  # License header.  cpp is run to exclude comments from \$GRAMMAR
	  # because thay picks up unwanted material as well as the comments
	  # in $GRAMMAR
	  cp header.jj sparql_11.jj
          # The parser that is exactly the working group grammar.
          cat "$GRAMMAR" | cpp -P -DSPARQL -DSPARQL_11 >> sparql_11.jj
          grammar sparql_11.jj sparql_11 SPARQLParser11
          ;;

      arq|arq.jj)
	  cp header.jj arq.jj
          cat "$GRAMMAR" | cpp -P -DARQ - >> arq.jj
          grammar arq.jj arq ARQParser
          ;;

      all)  grammar sparql
            grammar arq
	    # rdqlGrammar
	    ;;
      *)    echo "**** Unknown grammar: $G" 1>&2
            ;;
    esac
done
