PCRE has a feature called recursive pattern, which can be used to match nested subgroups. For example, consider the "grammar"
Q -> \\w | \'[\' A
The answer is (probably) Yes.
The technique is much more complex than the (?1) recursive call, but the result is almost 1-to-1 with the rules of the grammar - I worked in a such methodical way I can easily see it scripted. Basically, you match block-by-block, and use the stack to keep track of where you are. This is an almost working solution:
^(?:
(\w(?)) # Q1
|
(<(?)) #Q2 - start <
|
(\>(?<-Angle>)(?<-A>)?(?)) #Q2 - end >, match Q
|
(\[(?)) # Q3 start - [
|
(;(?)(?<-A>)?) #Q3 - ; after [
|
(\](?<-Semi>)(?<-Q>)*(?)) #Q3 ] after ;, match Q
|
((,|(?<-Q>))*(?)) #Match an A group
)*$
# Post Conditions
(?(Angle)(?!))
(?(Block)(?!))
(?(Semi)(?!))
It is missing the part of allowing commas in Q->[A;Q*,?Q*], and for some reason allows [A;A], so it matches [;,,] and [abc;d,e,f]. Rest of the strings match the same as the test cases.
Another minor point is an issue with pushing to the stack with an empty capture - it doesn't. A accepts Ø, so I had to use (?<-A>)? to check if it captured.
The whole regex should look like this, but again, it is useless with the bug there.
There is not way of synchronizing the stacks: if I push (?) and (?), I can pop them in any order. That is why this pattern cannot differentiate from ... we need one stack for all.
This can be solved for simple cases, but here we have something much more complicate - A whole Q or A, not just "<" or "[".