I have a C++ audio project that is a Score-Based Music System for offline computation. I have two parsers: in the first one I input a text that contains the node declaration and the graph structure of the audio chain. In the second one, I define the parameters that the nodes defined in the first text must use for the given audio section.
Historically, I wrote initially the parameters parser, that accepts a basic syntax like:
key = value;
plus some basic error checks like:
key = value key2 = value2; (note the missing semicolon in the between).
The output of this parser is a unordered map of two strings, like std::unorderderd_map<std::string, std::string>, from which I retrieve the value given a key.
However, I see some pitfalls in this parser, due to the fact that it was the first element of the project that I wrote and I considered only few aspects on it.
1. The parser lacks of formality. There is no Backus-Naur notation.
2. The parser accepts only “key = value;” format, without any kind of comments. I would introduce inline comments using //
3. Value is always interpreted as string and I have another class that transform it in a double number. However, the project evolved and now I am considering to accepts value that are strings or lists of strings or list of double.
4. Consider the following example:
key = 440;
key2 = 440;
I must repeat the value 440 explicitly, while it may be sound interesting the following options:
double value = 440;
key = value;
key2 = value;
or
double value = 440;
key = value;
key2 = key;
5. It may be of interest to introduce some keyword, like double or string to denote the expected type.
6. key is in the form: <ClassName>::<InstanceName> <VariableName>, like SinOsc::osc1 frequency to denote that an instance of type SinOsc called osc1 has a parameter named frequency. Actually the parser searches for this full path, and if it does not find it it throws an error, however I would split this information in the three components to improve the error checking and reporting.
7. The value can be in the following expression:
key = sin(2PIt);
where sin is interpreted and evaluated as sine function, PI stands for pi, and t is used as a unit variable between [0,1] that is the normalized time in the range of the computed audio section, such that if key is computed at half of the section t will have value 0.5. t is an hardcoded variable, while I can introduce a keyword like time or unit or tnorm like:
time u;
key = sin(2*PI*u);
This should make clear to the user the temporal dependency and allow to change the variable, while avoiding to hardcode t as keyword.
8. I have a namespace called ExpressionEvaluator that the main method is: double evaluateExpression(const std::string &expression, const double &t); that is responsible to evaluate and expression like sin(2 * PI *t). It may be an idea even if I introduce a keyword like time to provide to it an expression where as variable is used ‘t’, to do not change even this component.
9. Introduce a basic semantic analysis. Indeed,
string value = 440;
SinOsc::osc1 frequency = value;
is not possible because the SinOsc's frequency is of type double. 
10. Make the parser modular, for example having lexing, parsing, semantic analysis in three different modules. 
Stated these considerations, please provide feedback on them. Additionally, include any other relevant consideration to revise the parser to have a robust and well-defined parser and grammar.