Well, one thing I can tell you is that in my compilers class we don't work with a parser or lexical analyzer. We used generators for those. So, you use regular expressions to define the tokens, and then grammars to define the semantics.
You can see the lexer generator I made here: https://github.com/Radnen/radlib/blob/master/scripts/radscript/radlexer.js
To define a language, such as a language of expressions, we can use regex's as so:
RadLexer.register(/^[0-9]+$/, NUM);
RadLexer.register(/^print$/, PRINT); // quick way of grabbing 'print', not ideal though.
RadLexer.register(/^#[^\n\r]*$/, COMMENT); // my comments start with a single #
RadLexer.register(/^+$/, '+');
RadLexer.register(/^-$/, '-');
RadLexer.register(/^*$/, '*');
RadLexer.register(/^\/$/, '/');
RadLexer.register(/^;$/, ';');
RadLexer.register(/^[\s]+$/, WHITESPACE);
RadLexer.register(/^[^ \n\r]+$/, ERROR); // all other characters not caught by previous regex steps are errors
And in RadLexer.tokens, there is an array of the tokens with what will be debug data soon enough.
I have not yet made the parser generator, but once that is done, creating a new language would be fairly easy. I won't go as far as a compiler, but it's not hard to build one once the parser created the abstract syntax tree.