/*
 * 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;
    }

    private static String unquote(String s)
    {
        if (s.charAt(0) == '\'' && s.charAt(s.length()-1) == '\'')
            return s.substring(1, s.length()-1);
        else if (s.charAt(0) == '"' && s.charAt(s.length()-1) == '"')
            return s.substring(1, s.length()-1);
        else
            return s;
    }
}

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"])* >
    |
    <LITERAL: ("\"" ((~["\""])*("\\\"")?)* "\"")|("'" ((~["'"])*("\\\'")?)* "'") >
    |
    <SHELLCMD: "`" (~["`"])* "`" >
    |
    <EQUALS: "="  >
    |
    <COMMENT: "#" (~["\n"])* ("\n"|"\r")  >

}



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=<LITERAL> { s = unquote(val.image); pc.processOrdLine(id.image , s); }
            )
        )
        |
        <COMMENT> { }
        |
        <EOF> { more=false; }
    ) { return more; }


}


