/*************************************************************************** languagedefinition.cpp - description ------------------- begin : Wed Nov 28 2001 copyright : (C) 2001-2007 by Andre Simon email : andre.simon1@gmx.de ***************************************************************************/ /* This file is part of Highlight. Highlight 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 3 of the License, or (at your option) any later version. Highlight 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 Highlight. If not, see . */ #include #include "languagedefinition.h" #include "stringtools.h" using namespace std; namespace highlight { const string LanguageDefinition::REGEX_IDENTIFIER = "[a-zA-Z_]\\w*"; const string LanguageDefinition::REGEX_NUMBER = "(?:0x|0X)[0-9a-fA-F]+|\\d*[\\.]?\\d+(?:[eE][\\-\\+]\\d+)?[lLuU]*"; LanguageDefinition::LanguageDefinition() : ignoreCase ( false ), disableHighlighting ( false ), allowExtEscape ( false ), allowNestedComments ( true ), reformatCode ( false ) { reDefPattern=Pattern::compile ( "^regex\\((.+?)(,\\s*(\\d+))?\\)$" ); } LanguageDefinition::~LanguageDefinition() { for ( vector::iterator it=regex.begin(); it!=regex.end();it++ ) { delete *it; } delete reDefPattern; } int LanguageDefinition::isKeyword ( const string &s ) { return ( s.length() && keywords.count ( s ) ) ? keywords[s] : 0; } void LanguageDefinition::addSymbol ( stringstream& symbolStream, State stateBegin, State stateEnd, bool isDelimiter, const string& paramValue, unsigned int classID ) { RegexDef re = extractRegex ( paramValue ); if ( !re.reString.empty() ) { Pattern* p = Pattern::compile ( re.reString ); if ( p!=NULL ) { regex.push_back ( new RegexElement ( stateBegin,stateEnd, p, re.capturingGroup ) ); } else { failedRegex = re.reString; } return; } if ( isDelimiter ) { addDelimiterSymbol ( symbolStream, stateBegin, stateEnd, paramValue, classID ); } else { addSimpleSymbol ( symbolStream, stateBegin,paramValue ); } } RegexDef LanguageDefinition::extractRegex ( const string ¶mValue ) { RegexDef re_def; auto_ptr m ( reDefPattern->createMatcher ( paramValue ) ); if ( m.get() && m->matches() ) { re_def.reString = m->getGroup ( 1 ); if ( m->getStartingIndex ( 3 ) !=-1 ) { StringTools::str2num ( re_def.capturingGroup, m->getGroup ( 3 ), std::dec ); //std::cerr << "capturingGroup "<> value ) { symbolStream << " " << value; valExists = true; delimiterPair[value] = ++pairCount; } if ( valExists ) { symbolStream << " " << state; } } void LanguageDefinition::addDelimiterSymbol ( stringstream& symbolStream, State stateBegin, State stateEnd, const string& paramValue, unsigned int classID ) { istringstream valueStream ( paramValue ); string delimPrefix, delimSuffix; int pairCount =0; while ( valueStream>>delimPrefix ) { valueStream >> delimSuffix; symbolStream << " "<"<"<>delimStart; valueStream>>delimEnd; RegexDef reStart = extractRegex ( delimStart ); if ( !reStart.reString.empty() ) { Pattern* p = Pattern::compile ( reStart.reString ); if ( p!=NULL ) { regex.insert (regex.begin(),1, new RegexElement ( stateBegin,stateBegin, p, reStart.capturingGroup, -1, langName ) ); } } // end regex string needs to be saved to pass it back to host language when embedded section is over //host language definiton needs to know end delimiter to recognize single line embedded sections RegexDef reEnd = extractRegex ( delimEnd ); if ( !reEnd.reString.empty() ) { exitDelimiters[getNewPath(langName)]=reEnd.reString; } } void LanguageDefinition::restoreLangEndDelim(const string& langPath){ if ( !langPath.empty()&& exitDelimiters.count(langPath) ) { Pattern* p = Pattern::compile ( exitDelimiters[langPath]); if ( p!=NULL ) { regex.insert (regex.begin(),1, new RegexElement ( EMBEDDED_CODE_END,EMBEDDED_CODE_END, p ) ); } //else // cerr<<"Pattern::compile fehler\n"; } } void LanguageDefinition::getFlag ( string& paramValue, bool &flag) { if (paramValue.size()) flag= StringTools::change_case ( paramValue ) =="true"; } void LanguageDefinition::getSymbol ( const string& paramValue, unsigned char &symbol ) { if (paramValue.empty()) return; symbol=paramValue[0]; /* istringstream valueStream ( paramValue ); unsigned char symbol; valueStream >> symbol; return symbol; */ } void LanguageDefinition::addKeywords ( const string &kwList, State stateBegin, State stateEnd, int classID ) { RegexDef re = extractRegex ( kwList ); if ( !re.reString.empty() ) { Pattern* p = Pattern::compile ( re.reString ); if ( p!=NULL ) regex.push_back ( new RegexElement ( stateBegin,stateEnd, p, classID, re.capturingGroup ) ); else failedRegex = re.reString; return; } istringstream valueStream ( kwList ); string keyword; while ( valueStream >> keyword ) { keywords.insert ( make_pair ( keyword, classID ) ); } } unsigned int LanguageDefinition::generateNewKWClass ( const string& newClassName ) { unsigned int newClassID=0; bool found=false; while ( newClassID paramNames=langDef.getParameterNames(); for ( unsigned int i=0;i::iterator it=regex.begin(); it!=regex.end();it++ ) { delete *it; } regex.clear(); failedRegex.clear(); } string LanguageDefinition::getNewPath(const string& lang){ string::size_type Pos = currentPath.find_last_of ( Platform::pathSeparator ); return currentPath.substr ( 0, Pos+1 ) + lang + ".lang"; } }