Can you handle square brackets as atoms (i.e., '['and ']') along with everything else?
How about for an example :
label1(T) --> id(X), label2(Y), {T =.. [X, Y]}.
label2(Y) --> ['['], innerexp(Y), [']'].
id(X) --> [X].
innerexp(Y) --> [Y].
Execution:
?- phrase(label1(T), [foo, '[', bar, ']'], Rem).
T = foo(bar),
Rem = [].