It really depends.
It really depends on what you think of when you speak of a DSL. More specifically, is it essential for you to define new syntax? I think this is quite crucial, because if syntax is not essential, then why not use the syntax of the hosting language (Python in your case, I presume)?!
Is it essential to be able to type
rotate circle 45°
or is it just fine to say
rotate(circle, degree=45)
or even
circle.rotateByDegree(45)
IIRC, it was Paul Graham who said any kind of decent programming is actually inventing a language (the term DSL wasn't popular at that times). You define basic functions (the "verbs") and data structures (the "nouns"), and then try to express your solution in terms of these basic functions and data structures (maybe you have layers of these functions and data structures, with each layer closer to your "domain language"). If it is fine for you to express your solution in something like circle = Circle(); circle.rotate(degree=45)
, you're all done. I think Python has a nice, convenient syntax so I would probably always choose to stay away from inventing new syntax. Several functional languages like Haskell have a parentheses-less, comma-less way of applying functions to parameters so working code really looks like rotate circle 45
.
If that isn't quite good enough for you, and you really depend on new syntax, then you might want to consider Lisp macros or Rebol's dialects, before resorting to general grammar and parsing work. Also, several other languages allow you to specify infix operators on the fly.
The crucial question is: How much syntax do you need?
EDIT: I guess the basic distinction I was trying to make was that between an internal and an external DSL; wasn't aware of the terminology at that time.