← Back to context

Comment by librasteve

8 hours ago

I have been playing with DSLs a little, here is the kind of syntax that I would choose:

  invoice "INV-001" for "ACME Corp"
    item "Hosting" 100 x 3
    item "Support" 50 x 2
    tax 20%
  invoice "INV-002" for "Globex"
    item "Consulting" 200 x 5
    discount 10%
    tax 21%

In contrast to XML (even with authoring tools), my feeling is that XML (or any angle-bracket language tbh) is just too hard to write correctly (ie XML syntax and XMl schema parsing is very unforgiving) and has a lot of noise when you read it that obscures the main intent of the DSL code.

I have a preference for command/argument DSLs for certain things, such as the example given, over XML etc, for the reasons given.

As an occasional Tcl coder, the example would actually be a valid Tcl script - after adding invoice, item, tax and discount procedures, the example could be run as a script. The procedures would perform actions as needed for the arguments.

It's a shame that there isn't a common library that can be used for these types of tasks. Tcl evolved into something quite complex - compiling to bytecode, object oriented features, etc, etc. Although Tcl was originally intended to be embedded in apps, that boat sailed a long time ago (except for FPGA tools, which is where I use it).

Here's how the built-in Raku Grammar can be used to parse this. I can see Raku generating the XML as the Actions from this Grammar so allow ease of DSL authoring with XML as a interchange and strict scheme validation format.

  grammar InvoiceDSL {

    token TOP {
        ^ <invoice>+ % \n* $
    }

    token invoice {
        <header>
        \n
        <line>+
    }

    token header {
        'invoice' \h+ <id=string> \h+ 'for' \h+ <client=string>
    }

    token line {
        \h**4 <entry> \n?
    }

    token entry {
        | <item>
        | <tax>
        | <discount>
    }

    token item {
        'item' \h+ <desc=string> \h+ <price=num> \h+ 'x' \h+ <qty=int>
    }

    token tax {
        'tax' \h+ <percent=num> '%'
    }

    token discount {
        'discount' \h+ <percent=num> '%'
    }

    token string { \" <( <-["]>* )> \" }
    token num    { \d+ [ '.' \d+ ]? }
    token int    { \d+ }
  }