Yes, this is true.
It is a limitation I've thought a lot about how to fix, but have not actually implemented anything for.
The basic problem is that in both the generated parser and the generated meta-parser, which is used for matching patterns and output templates, it looks for the 1. a matching shape and 2. a matching initial keyword (if there is one).
In your example (abc se) and (abc arith) both fall into the same match rules.
Fortunately, the work around for this is pretty straightforward, if potentially a bit tortured. The conflicting productions can be turned into a single production, with a nonterminal that specifies the differences. From your example, you could do this as:
(define-language R2s
It is still also possible to match them separately, since (abc ,se) will only match abc forms with an se body and (abc ,arith) will only match those with an arith body. (Of course this is under the assumption that se and arith are always distinct.)
A more tortured example is a language from the very first assignment of the compiler course I TAed at IU. The natural definition of it would be:
(define-language L1
(terminals
(variable (x))
(binary-operator (binop))
(integer-64 (int64))
(integer-32 (int32)))
(Program (p)
(begin stmt* ...))
(Statement (stmt)
(set! x0 int64)
(set! x0 x1)
(set! x0 (binop x1 int32))
(set! x0 (binop x1 x2))))
However all of the set! productions conflict, since they all have the same top-level shape (list of three items, where set! is the first item). The somewhat more tortured version of this is:
(define-language L1
(terminals
(variable (x))
(binary-operator (b))
(int64 (w))
(int32 (hw)))
(Program (p)
(begin s* ...))
(Statement (s)
(set! x rhs))
(Rhs (rhs)
w
x
(b x rand))
(Operand (rand)
hw
x))
(Note that int64 and int32 are not legal metavariables, because the nanopass framework is not very smart about how it identifies the base of the metavariable, and it simply strips the trailing digits, resulting in them both being int---another bug on my list to fix.)
-andy:)