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

Hierarchy - UI improvement

Resource Center - High CPU usage

Nvidia - unsigned integer issues