/*
 * 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.
 */

/**
 * This grammar is used to process parameters passed from
 * command line or config file
 */

options {
    // Generate non-static functions
    STATIC = false;
    JAVA_UNICODE_ESCAPE = true;
}
PARSER_BEGIN(ParamLoader)
package org.apache.pig.tools.parameters;

import java.io.IOException;
import java.util.Hashtable;

//warnings in by code generated by javacc cannot be fixed here, 
// so suppressing all warnings for this class. But this does not help in 
//supressing Warnings in other classes generated by this .jj file
@SuppressWarnings("all")

public class ParamLoader {

    private PreprocessorContext pc;
    public void setContext(PreprocessorContext pc) {
        this.pc = pc;
    }
}

PARSER_END(ParamLoader)

SKIP : 
{
    "\n"
|   "\r"
|   " "
|   "\t"
}

TOKEN:
{
    <#LETTER : ["a"-"z", "A"-"Z"] >
    |
    <#DIGIT : ["0"-"9"] >
    |
    <#SPECIALCHAR : ["_"] >
}

TOKEN :
{
//    <IDENTIFIER: (<LETTER> | <SPECIALCHAR>) (<DIGIT> | <LETTER> | <SPECIALCHAR>)*>
    <IDENTIFIER: (<SPECIALCHAR>)*<LETTER>(<DIGIT> | <LETTER> | <SPECIALCHAR>)*>
    |
    <OTHER: ~["\"" , "'" , "`" , "a"-"z" , "A"-"Z" , "_" , "#" , "=" , " " , "\n" , "\t" , "\r"] (~["\n","\r"])* >
    |
    <SHELLCMD: "`" (~["`"])* "`" >
    |
    <EQUALS: "="  >
    |
    <COMMENT: "#" (~["\n"])* ("\n"|"\r")  >
}

MORE :
{
    <DOUBLE_QUOTE_START: ("\"") > : DOUBLE_QUOTE
    |
    <SINGLE_QUOTE_START: ("'") > : SINGLE_QUOTE
}

<DOUBLE_QUOTE> TOKEN :
{
    <DOUBLE_QUOTE_LITERAL: ("\"") > {
        image.deleteCharAt(image.length()-1);
        image.deleteCharAt(0);
        matchedToken.image = image.toString();
    } : DEFAULT
} 

<SINGLE_QUOTE> TOKEN :
{
    <SINGLE_QUOTE_LITERAL: ("'") > {
        image.deleteCharAt(image.length()-1);
        image.deleteCharAt(0);
        matchedToken.image = image.toString();
    } : DEFAULT 
}

<DOUBLE_QUOTE > MORE :
{
    <ESCAPED_DOUBLE_QUOTE: ("\\\"")> { image.replace(image.length()-2, image.length(), "\""); }
}

<SINGLE_QUOTE > MORE :
{
    <ESCAPED_SINGLE_QUOTE: ("\\'")> { image.replace(image.length()-2, image.length(), "'"); }
}

<DOUBLE_QUOTE,SINGLE_QUOTE> MORE:
{
    < (~[]) >
}


boolean Parse() throws IOException  :
{
    Token id, val;
    boolean more=true;
    String s;
}
{
    (
        (
            id=<IDENTIFIER>
            <EQUALS>
            (
                val=<OTHER> { pc.processOrdLine(id.image , val.image);}
                |
                val=<IDENTIFIER> 
                {s = val.image;}
                (
                    val =<OTHER>
                    {s += val.image;}
                )?
                {pc.processOrdLine(id.image , s);}
                |
                val=<SHELLCMD>  { pc.processShellCmd(id.image , val.image);}
                |
                val=<SINGLE_QUOTE_LITERAL> { pc.processOrdLine(id.image , val.image); }
                |
                val=<DOUBLE_QUOTE_LITERAL> { pc.processOrdLine(id.image , val.image); }
            
            )
        )
        |
        <COMMENT> { }
        |
        <EOF> { more=false; }
    ) { return more; }


}


