The following is the grammar of the MDL Transformation Language (MDLTL) in EBNF notation, as used in the CoCo compiler construction framework.
TOKENS IDENT = (LETTER | '_' | ':' ':') { LETTER | DIGIT | '_' | ':'} . INTEGER_LITERAL = (NONZERODIGIT { DIGIT }) | ( '0' ( ('x'|'X') HEXDIGIT { HEXDIGIT } | { OCTDIGIT } ) ). FLOATING_LITERAL = ( ( DIGIT { DIGIT } '.' | '.' DIGIT { DIGIT } | DIGIT { DIGIT } ['.' { DIGIT }] ('e'|'E') ['+'|'-'] DIGIT { DIGIT } | '.' DIGIT { DIGIT } ('e'|'E') ['+'|'-'] DIGIT { DIGIT } ) ['f'|'F'|'d'|'D'] ) | ( DIGIT { DIGIT } '.' DIGIT { DIGIT } ['f'|'F'|'d'|'D'] ) . STRING_LITERAL = '"' { CHARACTER | '\' ESCAPE | '\' CHARACTER } '"' . IMPORT = "import" . TRUE = "true" . FALSE = "false" . INC_OP = "++" . DEC_OP = "--" . MAPSTO = "-->" . AT_OP = "@" . ATTR_BEGIN = "[[" . ATTR_END = "]]" . BOTTOMUP = "bottomup" . TOPDOWN = "topdown" . REPEAT_RULES = "repeat_rules" . SKIP_RECURSION = "skip_recursion" . RULES = "rules" . DEADRULE = "deadrule" . POSTCOND = "postcond" . IF_KW = "if" . MAYBE = "maybe" . WHERE = "where" . OPTION = "option" . NONODE = "nonode" . MATCH = "match" . DEBUG_NAME = "debug_name" . DEBUG_PRINT = "debug_print" . COMMENTS FROM "/*" TO "*/" NESTED COMMENTS FROM "//" TO '\n' IGNORE '\r' + '\n' + '\t' PRODUCTIONS mdltl = { rules } . rules = RULES IDENT strategy<strat> '{' imports<ruleset> rule_sequence<ruleset> postconds_opt<ruleset> '}' . strategy<Ruleset::Strategy &strat> = BOTTOMUP | TOPDOWN . imports<Ruleset *&ruleset> = { import<ruleset> } . import<Ruleset *&ruleset> = IMPORT IDENT ';' . rule_sequence<Ruleset *&ruleset> = { rule<ruleset> } . rule<Ruleset *&ruleset> = node<expr_left> MAPSTO expression<expr_right> [ result_code<res_code> ] [ guard<expr_guard> ] [ where<bindings> ] [ DEBUG_NAME STRING_LITERAL ] { debug_print<deb_outs> } [ DEADRULE ] ';' . attribute_expr<Expr_attribute::Expr_attribute_vector &attrs, mi::mdl::string &node_name > = attr_entry<entry> { ',' attr_entry<entry> } . attr_entry<Expr_attribute::Expr_attribute_entry &pair > = IDENT [ ( '='| '~' ) expression<pair.expr> ] . postconds_opt<Ruleset *&ruleset> = [ POSTCOND postcond_or_expr<expr> ';' ]. result_code<Rule::Result_code &res_code> = REPEAT_RULES | SKIP_RECURSION . node<Expr *&expr> = IDENT ( AT_OP IDENT | '~' node<expr> | [ ternary_node_continuation<ref, expr> | call_node_continuation<ref, expr> ] ) [ ATTR_BEGIN attribute_expr<attrs, node_name> ATTR_END ] . ternary_node_continuation<Expr *expr_cond, Expr *&expr> = '?' node<expr_then> ':' node<expr_else> . call_node_continuation<Expr *expr_callee, Expr *&expr> = '(' [ paramlist<call_expr> ] ')' . paramlist<Expr_call *call_expr> = node<expr> { ',' node<expr> } . guard<Expr *&guard_expr> = IF_KW expression<expr> | MAYBE expression<expr> . debug_print<Debug_out_list &deb_outs> = DEBUG_PRINT '(' debug_variable_list<deb_outs> ')' . debug_variable_list<Debug_out_list &deb_outs> = [ identifier<sym> { ',' identifier<sym> } ] . where<Argument_list &bindings> = WHERE binding_list<bindings> . binding_list<Argument_list &bindings> = binding<expr> { binding<expr> } . binding<Expr *&expr> = IDENT '=' expression<expr_right> . reference_or_call<Expr *&expr> = IDENT [ '(' [ arglist<call_expr> ] ')' ] . arglist<Expr_call *call_expr> = expression<expr1> { ',' expression<exprn> } . primary_expr<Expr *&expr> = ( literal<expr> | reference_or_call<expr> | '(' expression<expr> ')' | OPTION '(' IDENT [ AT_OP IDENT ] ')' ) [ ATTR_BEGIN attribute_expr<attrs, node_name> ATTR_END ] . postfix_expr<Expr *&expr> = primary_expr<expr> { postfix<expr> } . postfix<Expr *&expr> = '[' expression<expr> ']' | '.' IDENT | INC_OP | DEC_OP | AT_OP IDENT . unary_expr<Expr *&expr> = INC_OP unary_expr<expr_sub> | DEC_OP unary_expr<expr_sub> | unary_operator<op> unary_expr<expr_sub> | postfix_expr<expr> . unary_operator<Expr_unary::Operator &op> = '+' | '-' | '~' | '!' . multiplicative_expr<Expr *&expr> = unary_expr<expr> { multiplicative_operator<op> unary_expr<expr_right> } . multiplicative_operator<Expr_binary::Operator &op> = '*' | '/' | '' . additive_expr<Expr *&expr> = multiplicative_expr<expr> { additive_operator<op> multiplicative_expr<expr_right> } . additive_operator<Expr_binary::Operator &op> = '+' | '-' . shift_expr<Expr *&expr> = additive_expr<expr> { shift_operator<op> additive_expr<expr_right> } . shift_operator<Expr_binary::Operator &op> = "<<" | ">>" | ">>>" . relational_expr<Expr *&expr> = shift_expr<expr> { relational_operator<op> shift_expr<expr_right> } . relational_operator<Expr_binary::Operator &op> = "<=" | ">=" | '<' | '>' . equality_expr<Expr *&expr> = relational_expr<expr> { equality_operator<op> relational_expr<expr_right> } . equality_operator<Expr_binary::Operator &op> = "==" | "!=" . and_expr<Expr *&expr> = equality_expr<expr> { '&' equality_expr<expr_right> } . exclusive_or_expr<Expr *&expr> = and_expr<expr> { '^' and_expr<expr_right> } . inclusive_or_expr<Expr *&expr> = exclusive_or_expr<expr> { '|' exclusive_or_expr<expr_right> } . logical_and_expr<Expr *&expr> = inclusive_or_expr<expr> { "&&" inclusive_or_expr<expr_right> } . logical_or_expr<Expr *&expr> = logical_and_expr<expr> { "||" logical_and_expr<expr_right> } . expression<Expr *&expr> = logical_or_expr<expr> [ '?' expression<expr_then> ':' expression<expr_else> ] . postcond_primary_expr<Expr *&expr> = NONODE '(' IDENT ')' | MATCH '(' node<expr> ')' | '(' postcond_or_expr<expr> ')' . postcond_and_expr<Expr *&expr> = postcond_primary_expr<expr> { "&&" postcond_primary_expr<expr_right> } . postcond_or_expr<Expr *&expr> = postcond_and_expr<expr> { "||" postcond_and_expr<expr_right> } . literal<Expr *&expr> = INTEGER_LITERAL | FLOATING_LITERAL | TRUE | FALSE | STRING_LITERAL .