Why is this regex acting greedy, when I've told it not to be?

Viewed 146

I've attempted to encode the following EBNF grammar for my system's macros into a regular expression (below), but despite my best efforts it appears to greedily match across multiple macros: it doesn't stop at the closing }}@.

    Expand ``@{{...}}@`` references which may appear in Step parameters.
    The syntax is described by the following EBNF grammar::

        depdata = "@{{", source identifier, ":", attribute, "}}@"
                | "@{{TAGS:", expression, "}}@" ;
        source identifier = ? printable 7-bit ASCII ? ;
        attribute = "DATADIR" | "TAGSFILE" | "RESULT_INT" ;
        expression = ? printable 7-bit ASCII ? ;

and the Python regular expression I've come up with

@{{(?:(?:(?P<id>.*?):(?P<attr>DATADIR|TAGSFILE|RESULT_INT))|TAGS:(?P<expr>.+?))}}@

Edit: Added missing + within expr group

Regular expression visualization

Debuggex Demo

When finding all the matches in the following test-case, I expect the result to be three matches, but I only get two:

@{{TAGS:sTagsJob << "job||ID||source"}}@ test  @{{job:DATADIR}}@ email body @{{job:DATADIR}}@ blah

The matches I expect are:

  1. @{{TAGS:sTagsJob << "job||ID||source"}}@ with the expr group set
  2. @{{job:DATADIR}}@ with id and attr groups set
  3. @{{job:DATADIR}}@ (again) with id and attr groups set

But instead, the matches are:

  1. @{{TAGS:sTagsJob << "job||ID||source"}}@ test @{{job:DATADIR}}@
  2. @{{job:DATADIR}}@

How come the non-greedy matches (.+?) seem to be acting greedy? What have I missed?

(And yes, I'm aware the EBNF grammar is silly and could be improved by always having the fixed strings appear on the right hand side. But that's not my question: I want to learn why my regex-fu has failed me)

2 Answers
Related