"Fossies" - the Fresh Open Source Software Archive

Member "highlight-3.57-x64/src/core/syntaxreader.cpp" (12 May 2020, 25379 Bytes) of package /windows/www/highlight-3.57-x64.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the last Fossies "Diffs" side-by-side code changes report for "syntaxreader.cpp": 3.56_vs_3.57.

    1 /***************************************************************************
    2                           syntaxreader.cpp  -  description
    3                              -------------------
    4     begin                : Wed Nov 28 2001
    5     copyright            : (C) 2001-2020 by Andre Simon
    6     email                : a.simon@mailbox.org
    7  ***************************************************************************/
    8 
    9 /*
   10 This file is part of Highlight.
   11 
   12 Highlight is free software: you can redistribute it and/or modify
   13 it under the terms of the GNU General Public License as published by
   14 the Free Software Foundation, either version 3 of the License, or
   15 (at your option) any later version.
   16 
   17 Highlight is distributed in the hope that it will be useful,
   18 but WITHOUT ANY WARRANTY; without even the implied warranty of
   19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
   20 GNU General Public License for more details.
   21 
   22 You should have received a copy of the GNU General Public License
   23 along with Highlight.  If not, see <http://www.gnu.org/licenses/>.
   24 */
   25 
   26 #include <memory>
   27 
   28 #include "syntaxreader.h"
   29 #include "stringtools.h"
   30 #include "enums.h"
   31 
   32 namespace highlight
   33 {
   34 
   35 //default expressions, can be overridden by syntax definition
   36 const string SyntaxReader::REGEX_IDENTIFIER =
   37     "[a-zA-Z_]\\w*";
   38 
   39 const string SyntaxReader::REGEX_NUMBER =
   40     "(?:0x|0X)[0-9a-fA-F]+|\\d*[\\.]?\\d+(?:[eE][\\-\\+]\\d+)?[lLuU]*";
   41 
   42 const string SyntaxReader::REGEX_ESCSEQ =
   43     "\\\\u[[:xdigit:]]{4}|\\\\\\d{3}|\\\\x[[:xdigit:]]{2}|\\\\[ntvbrfa\\\\\\?'\"]";
   44 
   45 DelimiterMap SyntaxReader::nestedStateEndDelimiters;
   46 
   47 DelimiterMap SyntaxReader::pluginConfigOverride;
   48 
   49 AllowInnerSectionsMap SyntaxReader::allowInnerSections;
   50 
   51 vector<Diluculum::LuaFunction*> SyntaxReader::pluginChunks;
   52 
   53 vector<string> SyntaxReader::persistentSnippets;
   54 
   55 set<string> SyntaxReader::persistentSyntaxDescriptions;
   56 
   57 
   58 int RegexElement::instanceCnt=0;
   59 
   60 
   61 SyntaxReader::SyntaxReader() :
   62     ignoreCase ( false ),
   63     disableHighlighting ( false ),
   64     allowNestedComments ( true ),
   65     reformatCode ( false ),
   66     assertEqualLength(false),
   67     paramsNeedUpdate(false),
   68     rawStringPrefix(0),
   69     continuationChar(0),
   70     validateStateChangeFct(NULL),
   71     decorateFct(NULL),
   72     decorateLineBeginFct(NULL),
   73     decorateLineEndFct(NULL),
   74     luaState(NULL)
   75 {
   76 
   77 }
   78 
   79 SyntaxReader::~SyntaxReader()
   80 {
   81     for ( vector<RegexElement*>::iterator it=regex.begin(); it!=regex.end(); it++ ) {
   82         delete *it;
   83     }
   84     if (validateStateChangeFct) delete validateStateChangeFct;
   85     if (decorateFct) delete decorateFct;
   86     if (decorateLineBeginFct) delete decorateLineBeginFct;
   87     if (decorateLineEndFct) delete decorateLineEndFct;
   88     if (luaState) delete luaState;
   89     for (unsigned int i=0; i<pluginChunks.size(); i++) {
   90         delete pluginChunks[i];
   91     }
   92     pluginChunks.clear();
   93 }
   94 
   95 //TODO add method to add format dependent variables (like CSS class name) for plug-in access
   96 //     needs to be called for each loaded syntax in CodeGenerator::loadLanguage
   97 void  SyntaxReader::initLuaState(Diluculum::LuaState& ls, const string& langDefPath, const string& pluginParameter, OutputType type )
   98 {
   99     // initialize Lua state with variables which can be used within scripts
  100     string::size_type Pos = langDefPath.find_last_of ( Platform::pathSeparator );
  101     ls["HL_LANG_DIR"] =langDefPath.substr ( 0, Pos+1 );
  102 
  103     ls["HL_INPUT_FILE"] = ls["HL_PLUGIN_PARAM"] = pluginParameter;
  104     ls["HL_OUTPUT"] = type;
  105 
  106     ls["Identifiers"]=REGEX_IDENTIFIER;
  107     ls["Digits"]=REGEX_NUMBER;
  108 
  109     //nitialize environment for hook functions
  110     ls["HL_STANDARD"]=STANDARD;
  111     ls["HL_STRING"]=STRING;
  112     ls["HL_NUMBER"]=NUMBER;
  113     ls["HL_LINE_COMMENT"]=SL_COMMENT;
  114     ls["HL_BLOCK_COMMENT"]=ML_COMMENT;
  115     ls["HL_ESC_SEQ"]=ESC_CHAR;
  116     ls["HL_PREPROC"]=DIRECTIVE;
  117     ls["HL_PREPROC_STRING"]=DIRECTIVE_STRING;
  118     ls["HL_OPERATOR"]=SYMBOL;
  119     ls["HL_LINENUMBER"]=LINENUMBER;
  120     ls["HL_INTERPOLATION"]=STRING_INTERPOLATION;
  121     ls["HL_KEYWORD"]=KEYWORD;
  122     ls["HL_STRING_END"]=STRING_END;
  123     ls["HL_LINE_COMMENT_END"]=SL_COMMENT_END;
  124     ls["HL_BLOCK_COMMENT_END"]=ML_COMMENT_END;
  125     ls["HL_ESC_SEQ_END"]=ESC_CHAR_END;
  126     ls["HL_PREPROC_END"]=DIRECTIVE_END;
  127     ls["HL_OPERATOR_END"]=SYMBOL_END;
  128     ls["HL_KEYWORD_END"]=KEYWORD_END;
  129     ls["HL_EMBEDDED_CODE_BEGIN"]=EMBEDDED_CODE_BEGIN;
  130     ls["HL_EMBEDDED_CODE_END"]=EMBEDDED_CODE_END;
  131     ls["HL_IDENTIFIER_BEGIN"]=IDENTIFIER_BEGIN;
  132     ls["HL_IDENTIFIER_END"]=IDENTIFIER_END;
  133     ls["HL_INTERPOLATION_END"]=STRING_INTERPOLATION_END;
  134     ls["HL_UNKNOWN"]=_UNKNOWN;
  135     ls["HL_REJECT"]=_REJECT;
  136     ls["HL_FORMAT_HTML"]=HTML;
  137     ls["HL_FORMAT_XHTML"]=XHTML;
  138     ls["HL_FORMAT_TEX"]=TEX;
  139     ls["HL_FORMAT_LATEX"]=LATEX;
  140     ls["HL_FORMAT_RTF"]=RTF;
  141     ls["HL_FORMAT_ANSI"]=ESC_ANSI;
  142     ls["HL_FORMAT_XTERM256"]=ESC_XTERM256;
  143     ls["HL_FORMAT_TRUECOLOR"]=ESC_TRUECOLOR;
  144     ls["HL_FORMAT_SVG"]=SVG;
  145     ls["HL_FORMAT_BBCODE"]=BBCODE;
  146     ls["HL_FORMAT_PANGO"]=PANGO;
  147     ls["HL_FORMAT_ODT"]=ODTFLAT;
  148 
  149     // default values for --verbose
  150     ls["IgnoreCase"]=false;
  151     ls["EnableIndentation"]=false;
  152     ls["DisableHighlighting"]=false;
  153 }
  154 
  155 LoadResult SyntaxReader::load ( const string& langDefPath, const string& pluginReadFilePath, OutputType outputType )
  156 {
  157     currentPath=langDefPath;
  158     disableHighlighting=false;
  159 
  160     if (!Platform::fileExists(langDefPath)) {
  161         return LOAD_FAILED;
  162     }
  163 
  164     try {
  165 
  166         if (luaState) delete luaState;
  167         luaState=new Diluculum::LuaState();
  168 
  169         Diluculum::LuaState& ls=*luaState;
  170         initLuaState(ls, langDefPath, pluginReadFilePath, outputType);
  171 
  172         lua_register (ls.getState(), "AddKeyword", luaAddKeyword);
  173         lua_register (ls.getState(), "RemoveKeyword", luaRemoveKeyword);
  174         lua_register (ls.getState(), "AddPersistentState", luaAddPersistentState);
  175         lua_register (ls.getState(), "OverrideParam", luaOverrideParam);
  176 
  177         SyntaxReader **s = (SyntaxReader **)lua_newuserdata(ls.getState(), sizeof(SyntaxReader *));
  178         *s=this;
  179         lua_setglobal(ls.getState(), GLOBAL_SR_INSTANCE_NAME);
  180 
  181         // ececute script and read values
  182         ls.doFile (langDefPath);
  183 
  184         langDesc = ls["Description"].value().asString();
  185         
  186         if (ls["Categories"].value() !=Diluculum::Nil){
  187 
  188             Diluculum::LuaValueMap categoryMap;
  189             categoryMap = ls["Categories"].value().asTable();
  190                 
  191             for(Diluculum::LuaValueMap::const_iterator it = categoryMap.begin(); it != categoryMap.end(); ++it)
  192             {
  193                 categories.append(it->second.asString());
  194                 if (std::next(it) != categoryMap.end()) {
  195                     categories.append(",");
  196                 }
  197             }
  198         }
  199 
  200         if (pluginChunks.size()) {
  201             Diluculum::LuaValueList params;
  202             params.push_back(langDesc);
  203             for (unsigned int i=0; i<pluginChunks.size(); i++) {
  204                 ls.call(*pluginChunks[i], params, "syntax user function");
  205             }
  206         }
  207 
  208         Diluculum::LuaValueMap globals = ls.globals();
  209 
  210         ignoreCase=readFlag(ls["IgnoreCase"]);
  211         reformatCode=readFlag(ls["EnableIndentation"]);
  212         disableHighlighting=readFlag(ls["DisableHighlighting"]);
  213 
  214         int idx=1;
  215         int kwId=0;
  216         while (ls["Keywords"][idx].value() !=Diluculum::Nil) {
  217             kwId= generateNewKWClass ( ls["Keywords"][idx]["Id"].value().asInteger() );
  218             
  219             if (ls["Keywords"][idx]["List"].value()!=Diluculum::Nil) {
  220                 int listIdx=1;
  221                 Diluculum::LuaVariable luaList=ls["Keywords"][idx]["List"];
  222                 while (luaList[listIdx].value()!=Diluculum::Nil) {
  223                     keywords.insert ( make_pair ( luaList[listIdx].value().asString(), kwId ) );
  224                     ++listIdx;
  225                 }
  226             } else if (ls["Keywords"][idx]["Regex"].value()!=Diluculum::Nil) {
  227                 string reString=StringTools::trim(ls["Keywords"][idx]["Regex"].value().asString());
  228                 int captGroup=-1;
  229                 if (ls["Keywords"][idx]["Group"].value()!=Diluculum::Nil) {
  230                     captGroup=ls["Keywords"][idx]["Group"].value().asInteger();
  231                 }
  232 
  233                 unsigned int priority=0;
  234                 if (ls["Keywords"][idx]["Priority"].value()!=Diluculum::Nil) {
  235                     priority=ls["Keywords"][idx]["Priority"].value().asInteger();
  236                 }
  237 
  238                 unsigned int constraintLineNum=0;
  239                 string constraintFilename, semanticDescription;
  240                 if (ls["Keywords"][idx]["Constraints"].value()!=Diluculum::Nil) {
  241 
  242                     if (ls["Keywords"][idx]["Constraints"]["Line"].value()!=Diluculum::Nil)
  243                         constraintLineNum=ls["Keywords"][idx]["Constraints"]["Line"].value().asInteger();
  244                     if (ls["Keywords"][idx]["Constraints"]["Filename"].value()!=Diluculum::Nil)
  245                         constraintFilename =ls["Keywords"][idx]["Constraints"]["Filename"].value().asString();
  246                 }
  247                 regex.push_back ( new RegexElement ( KEYWORD, KEYWORD_END, reString, kwId, captGroup, "", priority, constraintLineNum,  constraintFilename ) );
  248             }
  249             idx++;
  250         }
  251         
  252         /*
  253         if (globals.count("GeneratorOverride")) {
  254             idx=1;
  255             Diluculum::LuaValue lVal = ls["GeneratorOverride"][idx].value();
  256             while (lVal !=Diluculum::Nil) {
  257                 pluginConfigOverride[StringTools::change_case(lVal["Param"].asString())] = lVal["Value"].asString();
  258                 idx++;
  259                 lVal = ls["GeneratorOverride"][idx].value();
  260             }
  261         }*/
  262         
  263         if (globals.count("KeywordFormatHints")) {
  264             idx=1;
  265             Diluculum::LuaValue lVal = ls["KeywordFormatHints"][idx].value();
  266             while (lVal !=Diluculum::Nil) {
  267                 
  268                 int kwStyleOverride = lVal["Id"].asInteger();
  269 
  270                 if (lVal["Bold"]!=Diluculum::Nil){
  271                     kwStyleOverride += lVal["Bold"].asBoolean() ? 128 : 1024;
  272                 }
  273                 if (lVal["Italic"]!=Diluculum::Nil){
  274                      kwStyleOverride += lVal["Italic"].asBoolean() ? 256 : 2048;
  275                 }
  276                 if (lVal["Underline"]!=Diluculum::Nil){
  277                     kwStyleOverride += lVal["Underline"].asBoolean() ? 512 : 4096;
  278                 }
  279                  
  280                 overrideStyles.push_back(kwStyleOverride);
  281                 idx++;
  282                 lVal = ls["KeywordFormatHints"][idx].value();
  283             }
  284         }
  285         
  286         if (globals.count("Comments")) {
  287 
  288             int listIdx=1;
  289             int openDelimId=0;
  290             int closeDelimId=0;
  291             while (ls["Comments"][listIdx].value()!=Diluculum::Nil) {
  292                 if (ls["Comments"][listIdx]["Block"].value().asBoolean()) {
  293 
  294                     if (ls["Comments"][listIdx]["Nested"].value()!=Diluculum::Nil)
  295                         allowNestedComments = ls["Comments"][listIdx]["Nested"].value().asBoolean();
  296 
  297                     string openDelim=StringTools::trim(ls["Comments"][listIdx]["Delimiter"][1].value().asString());
  298                     RegexElement* elem=new RegexElement ( ML_COMMENT,ML_COMMENT_END, openDelim, 0, -1 );
  299                     openDelimId=elem->instanceId;
  300                     regex.push_back ( elem );
  301 
  302                     string closeDelim=StringTools::trim(ls["Comments"][listIdx]["Delimiter"][2].value().asString());
  303 
  304                     elem= new RegexElement ( ML_COMMENT_END,ML_COMMENT_END, closeDelim, 0, -1 );
  305                     closeDelimId=elem->instanceId;
  306                     regex.push_back ( elem);
  307 
  308                     delimiterDistinct[openDelimId]=openDelim!=closeDelim;
  309                     delimiterDistinct[closeDelimId]=openDelim!=closeDelim;
  310                     matchingDelimiters[closeDelimId]=openDelimId;
  311 
  312                 } else {
  313                     regex.push_back ( new RegexElement ( SL_COMMENT, SL_COMMENT_END,
  314                                                          StringTools::trim(ls["Comments"][listIdx]["Delimiter"][1].value().asString()), 0, -1 ) );
  315                 }
  316                 ++listIdx;
  317             }
  318         }
  319 
  320         //move behind comment section because of fortran comments (^cC.*$)
  321         string re_digit = StringTools::trim(ls["Digits"].value().asString());
  322         string re_identifier= StringTools::trim(ls["Identifiers"].value().asString());
  323 
  324         // insert identifier and number regex after keyword regexes
  325         regex.push_back ( new RegexElement ( IDENTIFIER_BEGIN, IDENTIFIER_END,
  326                                              re_identifier  ) );
  327         regex.push_back ( new RegexElement ( NUMBER, NUMBER_END,
  328                                              re_digit  ) );
  329 
  330         if (globals.count("Strings")) {
  331 
  332             if (ls["Strings"]["RawPrefix"].value()!=Diluculum::Nil) {
  333                 rawStringPrefix=ls["Strings"]["RawPrefix"].value().asString().at(0);
  334             }
  335 
  336             if (ls["Strings"]["Delimiter"].value()!=Diluculum::Nil) {
  337 
  338                 RegexElement* elem=new RegexElement ( STRING,STRING_END, StringTools::trim( ls["Strings"]["Delimiter"].value().asString()), 0, -1 );
  339                 delimiterDistinct[elem->instanceId]=true;
  340                 regex.push_back (elem );
  341             }
  342             if (ls["Strings"]["Interpolation"].value()!=Diluculum::Nil) {
  343                 RegexElement* elem=new RegexElement ( STRING_INTERPOLATION, STRING_INTERPOLATION_END,
  344                                                       StringTools::trim( ls["Strings"]["Interpolation"].value().asString()), 0, -1 );
  345                 regex.push_back (elem );
  346             }
  347 
  348             if (ls["Strings"]["DelimiterPairs"].value()!=Diluculum::Nil) {
  349 
  350                 int listIdx=1;
  351                 int openDelimId=0;
  352                 int closeDelimId=0;
  353                 while (ls["Strings"]["DelimiterPairs"][listIdx].value()!=Diluculum::Nil) {
  354 
  355                     string openDelim=StringTools::trim(ls["Strings"]["DelimiterPairs"][listIdx]["Open"].value().asString());
  356 
  357                     RegexElement* elem =new RegexElement(STRING, STRING_END, openDelim, 0, -1);
  358                     openDelimId=elem->instanceId;
  359                     regex.push_back( elem );
  360 
  361                     string closeDelim=StringTools::trim(ls["Strings"]["DelimiterPairs"][listIdx]["Close"].value().asString());
  362 
  363                     elem = new RegexElement(STRING_END, STRING_END, closeDelim, 0, -1);
  364                     closeDelimId=elem->instanceId;
  365                     regex.push_back( elem );
  366 
  367                     matchingDelimiters[closeDelimId]=openDelimId;
  368 
  369                     if (ls["Strings"]["DelimiterPairs"][listIdx]["Raw"].value()!=Diluculum::Nil) {
  370                         rawStringOpenDelims[openDelimId]=ls["Strings"]["DelimiterPairs"][listIdx]["Raw"].value().asBoolean();
  371                     }
  372                     ++listIdx;
  373                 }
  374             }
  375 
  376             assertEqualLength=readFlag(ls["Strings"]["AssertEqualLength"]);
  377 
  378             string escRegex;
  379             if (ls["Strings"]["Escape"].value()==Diluculum::Nil){
  380                 escRegex=REGEX_ESCSEQ;
  381             } else {
  382                 escRegex=ls["Strings"]["Escape"].value().asString();
  383             }
  384             regex.push_back ( new RegexElement ( ESC_CHAR,ESC_CHAR_END, StringTools::trim(escRegex), 0, -1 ) );
  385         }
  386 
  387         if (globals.count("PreProcessor")) {
  388 
  389             regex.push_back ( new RegexElement ( DIRECTIVE,DIRECTIVE_END, StringTools::trim(ls["PreProcessor"]["Prefix"].value().asString()), 0, -1 ) );
  390 
  391             if (ls["PreProcessor"]["Continuation"].value()!=Diluculum::Nil) {
  392                 continuationChar=ls["PreProcessor"]["Continuation"].value().asString().at(0);
  393             }
  394         }
  395 
  396         if (globals.count("Operators")) {
  397             regex.push_back ( new RegexElement ( SYMBOL,SYMBOL_END, StringTools::trim( ls["Operators"].value().asString()), 0, -1 ) );
  398         }
  399 
  400         if (globals.count("NestedSections")) {
  401 
  402             int listIdx=1;
  403             while (ls["NestedSections"][listIdx].value()!=Diluculum::Nil) {
  404 
  405                 string lang= ls["NestedSections"][listIdx]["Lang"].value().asString();
  406                 string openDelim=StringTools::trim(ls["NestedSections"][listIdx]["Delimiter"][1].value().asString());
  407                 regex.insert(regex.begin(), 1, new RegexElement(EMBEDDED_CODE_BEGIN, EMBEDDED_CODE_BEGIN, openDelim, 0, -1, lang));
  408                 
  409                 string closeDelim=StringTools::trim(ls["NestedSections"][listIdx]["Delimiter"][2].value().asString());
  410                 nestedStateEndDelimiters[getNewPath(lang)] = closeDelim;
  411                 
  412                 bool allowInnerSectionsFlag=true;
  413                 if (ls["NestedSections"][listIdx]["Sealed"].value()!=Diluculum::Nil){
  414                     allowInnerSectionsFlag = !ls["NestedSections"][listIdx]["Sealed"].value().asBoolean();
  415                 }
  416                 allowInnerSections[getNewPath(lang)] = allowInnerSectionsFlag;
  417                 
  418                 ++listIdx;
  419             }
  420             //allow host syntax
  421             allowInnerSections[getCurrentPath()] = true;               
  422         }
  423 
  424         if (globals.count("HeaderInjection")) {
  425             headerInjection+= ls["HeaderInjection"].value().asString();
  426         }
  427 
  428         if (globals.count("FooterInjection")) {
  429             footerInjection+= ls["FooterInjection"].value().asString();
  430         }
  431 
  432         if (globals.count("EncodingHint")) {
  433             encodingHint = ls["EncodingHint"].value().asString();
  434         }
  435         
  436         // load hook functions
  437         if (globals.count("OnStateChange")) {
  438             validateStateChangeFct=new Diluculum::LuaFunction(ls["OnStateChange"].value().asFunction());
  439         }
  440         if (globals.count("Decorate")) {
  441             decorateFct=new Diluculum::LuaFunction(ls["Decorate"].value().asFunction());
  442         }
  443         if (globals.count("DecorateLineBegin")) {
  444             decorateLineBeginFct=new Diluculum::LuaFunction(ls["DecorateLineBegin"].value().asFunction());
  445         }
  446         if (globals.count("DecorateLineEnd")) {
  447             decorateLineEndFct=new Diluculum::LuaFunction(ls["DecorateLineEnd"].value().asFunction());
  448         }
  449 
  450     } catch (Diluculum::LuaError &err) {
  451         luaErrorMsg = string(err.what());
  452         return LOAD_FAILED_LUA;
  453     }
  454     return LOAD_OK;
  455 }
  456 
  457 
  458 void SyntaxReader::addKeyword(unsigned int groupID, const string& kw)
  459 {
  460     if (!isKeyword ( kw )) {
  461         keywords.insert ( make_pair (kw, groupID ) );
  462     }
  463 }
  464 void SyntaxReader::removeKeyword(const string& kw)
  465 {
  466     keywords.erase(kw);
  467 }
  468 
  469 bool SyntaxReader::isKeyword ( const string &s )
  470 {
  471     return ( s.length() && keywords.count ( s ) ) ;
  472 }
  473 
  474 int SyntaxReader::getKeywordListGroup ( const string &s ) {
  475     if (isKeyword(s)) {
  476         return keywords[s];
  477     }
  478     return 0;
  479 }
  480     
  481 int SyntaxReader::luaAddKeyword (lua_State *L)
  482 {
  483     int retVal=0;
  484     if (lua_gettop(L)==2) {
  485         const char*keyword=lua_tostring(L, 1);
  486         unsigned int kwgroupID=lua_tonumber(L, 2);
  487         lua_getglobal(L, GLOBAL_SR_INSTANCE_NAME);
  488         SyntaxReader **a=reinterpret_cast<SyntaxReader **>(lua_touserdata(L, 3));
  489         if (*a) {
  490             (*a)->addKeyword(kwgroupID, keyword);
  491             retVal=1;
  492         }
  493     }
  494     lua_pushboolean(L, retVal);
  495     return 1;
  496 }
  497 
  498 int SyntaxReader::luaRemoveKeyword (lua_State *L)
  499 {
  500     int retVal=0;
  501     if (lua_gettop(L)==1) {
  502         const char*keyword=lua_tostring(L, 1);
  503         lua_getglobal(L, GLOBAL_SR_INSTANCE_NAME);
  504         SyntaxReader **a=reinterpret_cast<SyntaxReader **>(lua_touserdata(L, 2));
  505         if (*a) {
  506             (*a)->removeKeyword(keyword);
  507             retVal=1;
  508         }
  509     }
  510     lua_pushboolean(L, retVal);
  511     return 1;
  512 }
  513 
  514 
  515 void SyntaxReader::overrideParam(const string& name, const string& val)
  516 {
  517     pluginConfigOverride[name] = val;
  518     paramsNeedUpdate=true;
  519 }
  520 
  521 
  522 int SyntaxReader::luaOverrideParam (lua_State *L)
  523 {
  524     int retVal=0;
  525     if (lua_gettop(L)==2) {
  526         const char* name = lua_tostring(L, 1);
  527         const char* val = lua_tostring(L, 2);
  528         lua_getglobal(L, GLOBAL_SR_INSTANCE_NAME);
  529         SyntaxReader **a=reinterpret_cast<SyntaxReader **>(lua_touserdata(L, 3));
  530         if (*a) {
  531             (*a)->overrideParam(name, val);
  532             retVal=1;
  533         }
  534     }
  535     lua_pushboolean(L, retVal);
  536     return 1;
  537 }
  538 
  539 void SyntaxReader::restoreLangEndDelim(const string& langPath)
  540 {
  541     if ( !langPath.empty()&& nestedStateEndDelimiters.count(langPath) ) {
  542         regex.insert (regex.begin(),1, new RegexElement ( EMBEDDED_CODE_END,EMBEDDED_CODE_END, nestedStateEndDelimiters[langPath] ) );
  543     }
  544 }
  545 
  546 bool SyntaxReader::allowsInnerSection(const string& langPath)
  547 {
  548     return allowInnerSections[langPath];
  549 }
  550 
  551 unsigned int SyntaxReader::generateNewKWClass ( int classID )
  552 {
  553     char className[5]= {0};
  554     snprintf(className, sizeof(className), "kw%c", ('a'+classID-1));
  555 
  556     unsigned int newClassID=0;
  557     bool found=false;
  558     while (!keywordClasses.empty() && newClassID<keywordClasses.size() && !found ) {
  559         found = ( className==keywordClasses.at(newClassID++) );
  560     }
  561     if ( !found ) {
  562         newClassID++;
  563         keywordClasses.push_back ( className );
  564     }
  565     return newClassID;
  566 }
  567 
  568 
  569 bool SyntaxReader::readFlag(const Diluculum::LuaVariable& var)
  570 {
  571     if (var.value()==Diluculum::Nil) return false;
  572     return var.value().asBoolean();
  573 }
  574 
  575 
  576 string SyntaxReader::getNewPath(const string& lang)
  577 {
  578     string::size_type Pos = currentPath.find_last_of ( Platform::pathSeparator );
  579     return currentPath.substr ( 0, Pos+1 ) + lang + ".lang";
  580 }
  581 
  582 
  583 int SyntaxReader::getOpenDelimiterID ( const string& token, State s)
  584 {
  585     boost::xpressive::smatch what;
  586     for (unsigned int i=0; i<getRegexElements().size(); i++ )  {
  587         RegexElement *regexElem = getRegexElements() [i];
  588         if (regexElem->open==s ) {
  589 
  590             if( regex_match( token, what, regexElem->rex ) ) {
  591                 return regexElem->instanceId;
  592             }
  593         }
  594     }
  595     return 0;
  596 }
  597 
  598 bool SyntaxReader::matchesOpenDelimiter ( const string& token, State s, int openDelimId)
  599 {
  600     boost::xpressive::smatch what;
  601     for (unsigned int i=0; i<getRegexElements().size(); i++ )  {
  602         RegexElement *regexElem = getRegexElements() [i];
  603         if (regexElem->open==s ) {
  604 
  605             if( regex_match( token, what, regexElem->rex ) && matchingDelimiters[regexElem->instanceId]==openDelimId) {
  606                 return true;
  607             }
  608 
  609         }
  610     }
  611     return false;
  612 }
  613 
  614 void SyntaxReader::addPersistentKeyword(unsigned int groupID, const string& kw){
  615     ostringstream expr;
  616     expr <<"AddKeyword(\""<<kw<<"\", "<<groupID<<")";
  617              
  618     persistentSnippets.push_back(expr.str());
  619     persistentSyntaxDescriptions.insert(langDesc);
  620 }
  621     
  622 void SyntaxReader::addPersistentStateRange(unsigned int groupID, unsigned int column,unsigned int length, unsigned int lineNumber, const string& fileName){
  623     ostringstream expr;
  624     expr <<"table.insert(Keywords,\n"
  625          << "{ Id="<<groupID<<",\n"
  626          <<"  Regex=[[^.{"<<column<<"}(.{"<<length<<"})]],\n"
  627          <<"  Priority=1,\n"
  628          <<"  Constraints = {\n"
  629          <<"    Line = "<<lineNumber<<",\n"
  630          <<"    Filename = [=["<<fileName<<"]=],\n"
  631          <<" }\n"
  632          <<"})";
  633                 
  634     persistentSnippets.push_back(expr.str());
  635     persistentSyntaxDescriptions.insert(langDesc);
  636 }
  637 
  638 string SyntaxReader::getPersistentHookConditions() {
  639     ostringstream expr;
  640     expr << "ValidDesc = {";
  641     
  642     for (auto desc: persistentSyntaxDescriptions) {
  643         expr << "\"" << desc << "\",";
  644     }
  645     
  646     expr << "}\nif ValidDesc[desc] ~= nil then return end\n\n";
  647     
  648     return expr.str();
  649     
  650 }
  651  
  652 int SyntaxReader::luaAddPersistentState (lua_State *L)
  653 {
  654     int retVal=0;
  655     if (lua_gettop(L)==2) {
  656         const char*keyword=lua_tostring(L, 1);
  657         unsigned int kwgroupID=lua_tonumber(L, 2);
  658         lua_getglobal(L, GLOBAL_SR_INSTANCE_NAME);
  659         SyntaxReader **a=reinterpret_cast<SyntaxReader **>(lua_touserdata(L, 3));
  660         if (*a) {
  661             if (!(*a)->isKeyword(keyword)) {
  662                 (*a)->addKeyword(kwgroupID, keyword);
  663                 (*a)->addPersistentKeyword(kwgroupID, keyword);
  664             }
  665             
  666             retVal=1;
  667         }
  668     }
  669     if (lua_gettop(L)==4) {
  670         unsigned int lineNumber=lua_tonumber(L, 1);
  671         unsigned int kwgroupID=lua_tonumber(L, 2);
  672         unsigned int column=lua_tonumber(L, 3);
  673         unsigned int length=lua_tonumber(L, 4);
  674         lua_getglobal(L, GLOBAL_SR_INSTANCE_NAME);
  675         SyntaxReader **a=reinterpret_cast<SyntaxReader **>(lua_touserdata(L, 5));
  676         if (*a) {
  677             (*a)->addPersistentStateRange(kwgroupID, column, length, lineNumber, (*a)->getInputFileName() );
  678             retVal=1;
  679         }
  680     }
  681     lua_pushboolean(L, retVal);
  682     return 1;
  683 } 
  684 
  685 bool SyntaxReader::requiresTwoPassRun(){
  686     return persistentSyntaxDescriptions.count(langDesc)>0;
  687 }
  688 
  689 bool SyntaxReader::requiresParamUpdate(){
  690     bool ret = paramsNeedUpdate;
  691     paramsNeedUpdate = false;
  692     return ret;
  693 }
  694 
  695 void SyntaxReader::clearPersistentSnippets() {
  696     persistentSyntaxDescriptions.clear();
  697     persistentSnippets.clear();
  698 }
  699 
  700 
  701 }