Configuration scripts - part 1

This may sound weird in days where everything needs to have some kind of UI but the recent time I spend upgrading some of my configurations scripts. My current workflow is to define parsing rules and generate from them parser. To give you an idea what I talk about this is simple rules for the logging configuration file:
%name     = LogConfig 
%%
.input : /* empty */
       | LogAllow .input
       | LogBlock .input
       | AllLogBlock .input
       | AllLogAllow .input
;
LogAllow
       : 'LogAllow' '(' $(CStringID) ')' ';'
;
LogBlock
       : 'LogBlock' '(' $(CStringID) ')' ';'
;
AllLogBlock
       : 'AllLogBlock' '(' ')' ';'
;
AllLogAllow
       : 'AllLogAllow' '(' ')' ';'
;
%%
It allows me then to parse a file that looks like this:
LogAllow("Crash");
LogAllow("Assert");
LogBlock("Scripts");
LogBlock("Audio");
This may sound like a lot to parse simple format like this but in practice, I like it. If you interested why:
  • The generation of a parser is compile-time.
  • There is a validation of format while parsing script (I get a line where there is an error).
  • I can generate a more compact binary format for a script.
  • I get a lot of freedom in generating parsers.
Parsing of this file would be done then this way: 

            CScriptParserBase<CVmCodeLogConfig> parser;
            wrErrorRetCheck(parser.parse(script));

            CStringID filter;

            for (auto node : parser)
            {
                switch (node.h_name())
                {
                case "LogAllow"_Hash64:
                    node.arguments(filter);
                    allow(filter);
                    break;
                case "LogBlock"_Hash64:
                    node.arguments(filter);
                    allow(filter);
                    break;
                case "AllLogBlock"_Hash64:
                    m_defaultFilter = EBlock;
                    m_filters.clear();
                    break;
                case "AllLogAllow"_Hash64:
                    m_defaultFilter = EAllow;
                    m_filters.clear();
                    break;
                default:
                    break;
                }
            }

This introduction got a little bit longer than I planned. Yeah ... this is not really a topic that I wanted to discuss. At the same time, it is important to understand where I go with all of this. 

The real topic I wanted to discuss is: 

Designing intuitive API that makes sense. 

and because this post came out long already I will split the topic into multiple parts. The next one will describe in more detail why this topic.

To next time. 
Greg 

Comments

Popular posts from this blog

Query commands execution

W.U. 0x20

Lets play : Good code / Bad code