Я не уверен, что понимаю вашу проблему на основе грамматики. Возможно, вы подразумеваете, что statement
и S
- это один и тот же символ. Если это так, я бы сказал, что ваша грамматика просто не подходит для языка, который вы намереваетесь описать. Если мы игнорируем ORDER
и LIMIT
, тогда ваша грамматика будет
S -> SW | "SELECT S" | foo
W -> "WHERE S"
Тогда да, вы можете получить ерунду, как
S -> SW -> SWW -> SWWW -> "SELECT foo WHERE foo WHERE foo WHERE foo"
Но это всего лишь ваша первая попытка грамматики, это не доказывает, что грамматика не работает. Учтите это:
<S> -> <A><B>
<A> -> SELECT <C>
<B> -> epsilon | WHERE <D>
<C> -> (rules for select lists)
<D> -> (rules for WHERE condition)
Правила для <C>
и <D>
могут ссылаться на S
и A
и B
, правильно, возможно, с использованием скобок, как требуется для создания строк, которые работают для вас. Вы больше не можете получить плохие строки.
Это на самом деле не проблема, которую CFG не может решить самостоятельно. Чтобы сделать что-то вроде принудительного использования только объявленных переменных, да, нужен контекстно-зависимый или более совершенный механизм, но мы просто говорим о повторении ключевых слов и фраз. Это вполне в рамках того, что могут делать CFG. Теперь, если вы хотите поддерживать псевдонимы и применять правильные ссылки на псевдонимы в запросе, это невозможно в контекстно-свободных языках. Но это не то, что мы обсуждаем здесь. Причина, по которой это невозможно, состоит в том, что язык L = {ww | w in E*}
не является контекстно-свободным языком, и это, по сути, то, что используется для принудительного применения имен переменных или псевдонимов таблиц.