What I'm especially interested in is the ability to define the grammar in the code as ordinary code without any unnecessary cruft.
I'm aware I could use IronPython. I don't want to.
UPDATE:
To further explain what I'm looking for, I'm including some sample pyparsing code. This is an incomplete parser to convert emacs shortcut keys to more conventional notation. This example is, of course, small enough that string functions would suffice, but it's just to show the cleanness and conciseness of pyparsing.
from pyparsing import Literal, OneOrMore, Optional, Word, printables, replaceWith
CTRL_MODIFIER = Literal('C').setParseAction(replaceWith('Ctrl'))
META_MODIFIER = Literal('M').setParseAction(replaceWith('Alt'))
MODIFIER = CTRL_MODIFIER | META_MODIFIER # Note operator overloading
SEPARATOR = Literal('-').setParseAction(replaceWith('+'))
MODIFIER_LIST = OneOrMore(MODIFIER + SEPARATOR)
KEY = Word(printables) # This is a "word" composed of any number of printable characters.
# The lambda functions here just join the tokens with the literal string
# on which .join is called.
STROKE = (Optional(MODIFIER_LIST) + KEY).setParseAction(
lambda tokens: ' '.join([str(token) for token in tokens]))
BINDING = OneOrMore(STROKE).setParseAction(
lambda tokens: ', '.join([str(token) for token in tokens]))
# Example usage:
# >>> BINDING.transformString('M-/')
# Alt + /
# >>> BINDING.transformString('C-x C-f')
# Ctrl + x, Ctrl + f
# >>> BINDING.transformString('C-x f')
# Ctrl + x, f
# >>> BINDING.transformString('C-x M-c M-butterfly')
# Ctrl + x, Alt + c, Alt + butterfly
I would like to be able to write grammars in .NET with as much ease in as few lines.