One of my programs accepts commands (e.g. kill foo ) at runtime. Think of it as a small domain language. Here are some examples:
kill kill client exit
But chained teams are also allowed, and spaces are not significant before and after the teams, so the following examples are true:
kill ; say "that was fun" kill ; kill ; kill;
I have currently implemented this with lex / yacc (flex / bison) and this has caused a lot of headache. The lexer is very context sensitive (for example, tokens in the form of spaces usually do not return unless after the kill keyword) and has many different states. The grammar had conflicts, and I don't really like the format in which it should be specified (especially for $ 1, $ 2, $ 3, ... to use arguments for non-terminals). In addition, the error messages that the bison provides (during parsing) are sometimes accurate but often not used (the kill command with additional arguments leads to error messages, for example Unexpected $undefined, expected $end or ; for kill clont instead of kill client ). Finally, the C API for yacc is cruel (external defines around the place).
I do not ask you to solve all the above issues (I will open separate streams with more specific descriptions and code if there is no lex / yacc path). Instead, I'm interested in alternatives to lex / yacc.
My criteria are as follows:
- Input is a string (const char *), there is no output, but instead you need to call the code for every other keyword.
- I want to use this with C (C99).
- The software should already be included in major Linux distributions, or at least easy to bundle / package.
- It should be well documented.
- The syntax for describing my language should be easy.
- It should output meaningful error messages when analyzing errors.
- Performance is not so important (of course, it should be fast, but a typical use case is interactive use, rather than processing tons of MB instructions).
source share