#ifndef _KVI_KVS_PARSER_H_
#define _KVI_KVS_PARSER_H_
//=============================================================================
//
//   File : kvi_kvs_parser.h
//   Creation date : Thu 25 Sep 2003 05.12 CEST by Szymon Stefanek
//
//   This file is part of the KVirc irc client distribution
//   Copyright (C) 2003 Szymon Stefanek (pragma at kvirc dot net)
//
//   This program is FREE software. You can redistribute it and/or
//   modify it under the terms of the GNU General Public License
//   as published by the Free Software Foundation; either version 2
//   of the License, or (at your opinion) any later version.
//
//   This program is distributed in the HOPE that it will be USEFUL,
//   but WITHOUT ANY WARRANTY; without even the implied warranty of
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
//   See the GNU General Public License for more details.
//
//   You should have received a copy of the GNU General Public License
//   along with this program. If not, write to the Free Software Foundation,
//   Inc. ,59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
//=============================================================================

#include "kvi_settings.h"
#include "kvi_qstring.h"
#include "kvi_list.h"

#include "kvi_kvs_reporttarget.h"

#include <qdict.h>

class KviKvsTreeNode;

class KviKvsTreeNodeInstruction;
class KviKvsTreeNodeInstructionBlock;
class KviKvsTreeNodeCommand;
class KviKvsTreeNodeDataList;
class KviKvsTreeNodeData;
class KviKvsTreeNodeVariableReference;
class KviKvsTreeNodeConstantData;
class KviKvsTreeNodeSwitchList;
class KviKvsTreeNodeSpecialCommand;
class KviKvsTreeNodeExpression;
class KviKvsTreeNodeExpressionBinaryOperator;
class KviKvsTreeNodeFunctionCall;
class KviKvsTreeNodeOperation;
class KviKvsTreeNodeSpecialCommandDefpopupLabelPopup;

class KviKvsKernel;

// THIS IS INTENDED TO BE AN ONETIME PARSER

class KVIRC_API KviKvsParser : public KviKvsReportTarget
{
	friend class KviKvsKernel;
public:
	KviKvsParser();
	~KviKvsParser();
private:
	const QChar              * m_pBuffer;  // the local pointer to the beginning of the buffer
	const QChar              * m_ptr;      // the parsing pointer
	// parsing state
	QDict<QString>           * m_pGlobals; // the dict of the vars declared with global in this script
	int                        m_iFlags;   // the current parsing flags
public: // public interface
	enum Flags { AssumeGlobals = 1 };
	// parses the buffer pointed by pBuffer and returns
	// a syntax tree or 0 in case of failure
	// if the parsing fails, the error code can be retrieved by calling error()
	KviKvsTreeNodeInstruction * parse(const QChar * pBuffer,int iFlags = 0);
	KviKvsTreeNodeInstruction * parseAsExpression(const QChar * pBuffer,int iFlags = 0);
	KviKvsTreeNodeInstruction * parseAsParameter(const QChar * pBuffer,int iFlags = 0);
private: // parsing helpers
	// generic
	void skipSpaces(); // skips only spaces and tabs (eventually with \)
	void skipSpacesAndNewlines(); // skips space and newlines
	void skipToNextLine(); // skips up to a new line
	// dedicated
	void skipToEndOfCStyleComment();
	// dedicated to parseSpecialCommandFor() : in kvi_kvs_parser_specialcommands.cpp
	bool skipToEndOfForControlBlock();
protected:
	// this is called by KviKvsKernel to register the parsing routines
	static void init();
private:
	// returns 0 only in case of error
	// starts on the first char of a buffer
	// stops at the first null char encountered
	KviKvsTreeNodeInstruction                * parseInstructionList(); 
	// may return 0 (empty instruction), check error() for error conditions
	// starts on the first character of an instruction
	// if the first char is ';' '\n' or null it just returns 0 without error
	// stops after the ending char of the instruction
	KviKvsTreeNodeInstruction                * parseInstruction();
	// may return 0 (empty block), check error() for error conditions
	// starts at the leading '{' of the block
	// stops after the trailing '}' of the block
	KviKvsTreeNodeInstruction                * parseInstructionBlock();
	// returns 0 only in case of error
	// starts on the first character of the parameters
	// ends after the end of the command
	KviKvsTreeNodeDataList                   * parseCommandParameterList();
	// returns 0 only in case of error
	// starts on the leading '(' or a ',' in the middle of the list
	// ends after the trailing ')'
	// if started in the middle of the list returns only the remaining
	// parameters.
	KviKvsTreeNodeDataList                   * parseCommaSeparatedParameterList();
	KviPtrList<QString>                      * parseCommaSeparatedParameterListNoTree();
	// returns 0 only in case of error
	// start on the first character of the parameter
	// ends after the first character not included in the param (';','\n','\0',' ')
	KviKvsTreeNodeData                       * parseCommandParameter();
	// returns 0 only in case of error
	// start on the first character of the parameter
	// ends after the first character not included in the param (')','\n','\0',',')
	KviKvsTreeNodeData                       * parseCommaSeparatedParameter();
	// returns 0 only in case of error
	// start on the first character of the parameter
	// ends after the first character not included in the param (')','\n','\0')
	KviKvsTreeNodeData                       * parseSingleParameterInParenthesis();
	// never returns 0
	KviKvsTreeNodeConstantData               * parseCommandLiteralParameter();
	// never returns 0
	KviKvsTreeNodeConstantData               * parseCommaSeparatedLiteralParameter();
	// never returns 0
	KviKvsTreeNodeConstantData               * parseSingleLiteralParameterInParenthesis();
	// returns 0 only in case of error
	// starts at the leading '"'
	// ends after the trailing '"'
	KviKvsTreeNodeData                       * parseStringParameter();
	// never returns 0
	KviKvsTreeNodeConstantData               * parseStringLiteralParameter();
	// returns 0 only in case of error
	// starts at the leading '-' of the first switch
	// ends after the last switch
	KviKvsTreeNodeSwitchList                 * parseCommandSwitchList();
	// returns 0 only in case of error
	// starts at '%' or '$'
	// and ends after the end of the data reference
	// or just after the '%' or '$' if this was only a ConstandData (not a var or func)
	KviKvsTreeNodeData                       * parseParameterPercentOrDollar();
	// returns 0 only in case of error
	// starts at '%' or '$'
	// ends after the end of the complete data reference (including scope operators!)
	KviKvsTreeNodeData                       * parsePercentOrDollar(bool bInObjScope = false);
	// returns 0 only in case of error
	// starts at '%'
	// ends after the end of the structured data
	KviKvsTreeNodeData                       * parsePercent();
	// returns 0 only in case of error
	KviKvsTreeNodeData                       * parseHashKey();
	// never returns 0
	KviKvsTreeNodeConstantData               * parseHashKeyLiteralParameter();
	
	//
	// kvi_kvs_parser_specialcommands.cpp
	//
	
	// return 0 only in case of error
	// starts at the leading '(' of the if command (after the switches)
	// and stops after the end of the else block
	// if the first character is not '(' then this function fails with an error
	KviKvsTreeNodeSpecialCommand             * parseSpecialCommandIf();
	// always returns 0
	// check error() for error conditions
	// starts after the switches of the "global" keyword
	// and stops at the end of the command
	// if the first character is not '%' of a variable then this function fails with an error
	KviKvsTreeNodeSpecialCommand             * parseSpecialCommandGlobal();
	// returns 0 only in case of error
	// starts at the leading '(' of the while command (after the switches)
	// and stops after the end of the command block
	// if the first character is not '(' then this function fails with an error	
	KviKvsTreeNodeSpecialCommand             * parseSpecialCommandWhile();
	// returns 0 only in case of error
	// starts at the leading '(' of the while command (after the switches)
	// and stops after the end of the command block
	// if the first character is not '(' then this function fails with an error	
	KviKvsTreeNodeSpecialCommand             * parseSpecialCommandDo();
	// returns 0 only in case of error
	// and stops after the end of the break command
	KviKvsTreeNodeSpecialCommand             * parseSpecialCommandBreak();
	// returns 0 only in case of error
	// and stops after the end of the for command block
	KviKvsTreeNodeSpecialCommand             * parseSpecialCommandFor();
	// returns 0 only in case of error
	// and stops after the end of the foreach command block
	KviKvsTreeNodeSpecialCommand             * parseSpecialCommandForeach();
	// returns 0 only in case of error
	// and stops after the end of the switch command block
	KviKvsTreeNodeSpecialCommand             * parseSpecialCommandSwitch();
	// returns 0 only in case of error
	// and stops after the end of the defpopup command block
	KviKvsTreeNodeSpecialCommand             * parseSpecialCommandDefpopup();
	KviKvsTreeNodeSpecialCommandDefpopupLabelPopup * parseSpecialCommandDefpopupLabelPopup();

	//
	// kvi_kvs_parser_command.cpp
	//

	// may return 0 (empty command), check error() for error conditions
	// starts at the beginning of a command (can be non valid)
	// ends after the ending char of the command
	KviKvsTreeNodeCommand                    * parseCommand();


	//
	// kvi_kvs_parser_comment.cpp
	//

	// always returns 0, and it CAN be an error!
	// starts at the beginning of a comment (must be '#' or '/')
	// ends after the ending char of the comment
	KviKvsTreeNode                           * parseComment();


	//
	// kvi_kvs_parser_dollar.cpp
	//

	// returns 0 only in case of error
	// starts at '$'
	// ends after the end of the function call
	KviKvsTreeNodeData                       * parseDollar(bool bInObjScope = false);

	//
	// kvi_kvs_parser_lside.cpp
	//

	// returns 0 only in case of error
	// returns after the command terminator
	KviKvsTreeNodeInstruction                * parseVoidFunctionCallOrOperation();
	// returns 0 only in case of error
	// returns after the command terminator
	KviKvsTreeNodeOperation                  * parseOperation();
	// returns 0 only in case of error
	// returns after the command terminator
	KviKvsTreeNodeData                       * parseOperationRightSide();
	// return 0 only in case of error
	// returns after the command terminator
	KviKvsTreeNodeOperation                  * parseBindingOperation();

	//
	// kvi_kvs_parser_expression.cpp
	//
	
	// returns 0 only in case of error
	// starts AFTER the leading char of the expression
	// ends afer the first terminator found
	KviKvsTreeNodeExpression                * parseExpression(char terminator);
	KviKvsTreeNodeExpressionBinaryOperator  * parseExpressionBinaryOperator();
	KviKvsTreeNodeExpression                * parseExpressionOperand(char terminator);


};

#endif //!_KVI_KVS_PARSER_H_
