//============================================================================= // // File : kvi_kvs_parser.cpp // 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. ,51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // //============================================================================= #define __KVIRC__ #include "kvi_kvs_parser.h" #include "kvi_kvs_treenode.h" #include "kvi_kvs_report.h" #include "kvi_kvs_kernel.h" #include "kvi_kvs_script.h" #include "kvi_kvs_parser_macros.h" #include "kvi_locale.h" #include "kvi_options.h" //FIXME: @ == $$-> == $this-> KviKvsParser::KviKvsParser(KviKvsScript * pScript,KviWindow * pOutputWindow) { // no need to initialize m_pBuffer // no need to initialize m_ptr // no need to initialize m_bError m_pGlobals = 0; m_pScript = pScript; m_pWindow = pOutputWindow; } KviKvsParser::~KviKvsParser() { if(m_pGlobals)delete m_pGlobals; } void KviKvsParser::init() { KviKvsKernel * pKern = KviKvsKernel::instance(); #define _REG_CNTRL_CMD(__cntrlCmdName,__parsingRoutine) \ { \ KviKvsSpecialCommandParsingRoutine * r = new KviKvsSpecialCommandParsingRoutine; \ r->proc = KVI_PTR2MEMBER(KviKvsParser::__parsingRoutine); \ pKern->registerSpecialCommandParsingRoutine(TQString(__cntrlCmdName),r); \ } _REG_CNTRL_CMD("if",parseSpecialCommandIf); _REG_CNTRL_CMD("global",parseSpecialCommandGlobal); _REG_CNTRL_CMD("while",parseSpecialCommandWhile); _REG_CNTRL_CMD("break",parseSpecialCommandBreak); _REG_CNTRL_CMD("do",parseSpecialCommandDo); _REG_CNTRL_CMD("for",parseSpecialCommandFor); _REG_CNTRL_CMD("foreach",parseSpecialCommandForeach); _REG_CNTRL_CMD("switch",parseSpecialCommandSwitch); _REG_CNTRL_CMD("defpopup",parseSpecialCommandDefpopup); _REG_CNTRL_CMD("unset",parseSpecialCommandUnset); _REG_CNTRL_CMD("class",parseSpecialCommandClass); _REG_CNTRL_CMD("help",parseSpecialCommandHelp); #undef _REG_CNTRL_CMD } void KviKvsParser::report(bool bError,const TQChar * pLocation,const TQString &szMsgFmt,kvi_va_list va) { TQString szMsg; KviTQString::vsprintf(szMsg,szMsgFmt,va); KviPointerList * pCodeListing = 0; TQString szLocation; if(pLocation) { pCodeListing = new KviPointerList; pCodeListing->setAutoDelete(true); int iLine,iCol; KviKvsReport::findLineColAndListing(m_pBuffer,pLocation,iLine,iCol,pCodeListing); KviTQString::sprintf(szLocation,__tr2qs("line %d, near character %d"),iLine,iCol); } else { szLocation = __tr2qs("beginning of input"); } KviKvsReport rep(bError ? KviKvsReport::ParserError : KviKvsReport::ParserWarning,m_pScript->name(),szMsg,szLocation,m_pWindow); if(pCodeListing)rep.setCodeListing(pCodeListing); KviKvsReport::report(&rep,m_pWindow); } void KviKvsParser::errorBadChar(const TQChar * pLocation,char cExpected,const char * szCommandName) { if(pLocation->tqunicode()) error(pLocation,__tr2qs("Found character '%q' (tqunicode 0x%x) where '%c' was expected: see \"/help %s\" for the command syntax"), pLocation,pLocation->tqunicode(),cExpected,szCommandName); else error(pLocation,__tr2qs("Found end of input where character '%c' was expected: see \"/help %s\" for the command syntax"), cExpected,szCommandName); } void KviKvsParser::error(const TQChar * pLocation,const TQString &szMsgFmt,...) { m_bError = true; kvi_va_list va; kvi_va_start_by_reference(va,szMsgFmt); report(true,pLocation,szMsgFmt,va); kvi_va_end(va); } void KviKvsParser::warning(const TQChar * pLocation,const TQString &szMsgFmt,...) { kvi_va_list va; kvi_va_start_by_reference(va,szMsgFmt); report(false,pLocation,szMsgFmt,va); kvi_va_end(va); } KviKvsTreeNodeInstruction * KviKvsParser::parse(const TQChar * pBuffer,int iFlags) { m_iFlags = iFlags; m_bError = false; if(m_pGlobals)m_pGlobals->clear(); // this shouldn't be needed since this is a one time parser m_pBuffer = pBuffer; m_ptr = pBuffer; if(!pBuffer) { error(0,__tr2qs("Empty script")); return 0; } return parseInstructionList(); } KviKvsTreeNodeInstruction * KviKvsParser::parseAsExpression(const TQChar * pBuffer,int iFlags) { m_iFlags = iFlags; m_bError = false; if(m_pGlobals)m_pGlobals->clear(); // this shouldn't be needed since this is a one time parser m_pBuffer = pBuffer; m_ptr = pBuffer; if(!pBuffer) { error(0,__tr2qs("Empty script")); return 0; } KviKvsTreeNodeExpression * expr = parseExpression(0); if(!expr)return 0; return new KviKvsTreeNodeExpressionReturn(pBuffer,expr); } KviKvsTreeNodeInstruction * KviKvsParser::parseAsParameter(const TQChar * pBuffer,int iFlags) { m_iFlags = iFlags; m_bError = false; if(m_pGlobals)m_pGlobals->clear(); // this shouldn't be needed since this is a one time parser m_pBuffer = pBuffer; m_ptr = pBuffer; if(!pBuffer) { error(0,__tr2qs("Empty script")); return 0; } KviKvsTreeNodeDataList * l = parseCommandParameterList(); if(!l)return 0; return new KviKvsTreeNodeParameterReturn(pBuffer,l); } /////////////////////////////////////////////////////////////////////////////////////////////////// // THE REAL KVS // //