Как я могу заставить эту грамматику JAVACC работать с [ ]?
Я пытаюсь изменить грамматику в проекте JSqlParser, который имеет дело с файлом грамматики javacc.jj, задающим стандартный синтаксис SQL. Мне было трудно заставить работать один раздел, я сузил его до следующей, очень упрощенной грамматики.
в основном у меня есть определение столбца: [таблица] . поле
но сама таблица также может содержать "." символ, который вызывает путаницу.
Я думаю, что следующая грамматика должна принять следующие предложения:
выберите mytable.myfield
выберите мое поле
выберите mydb.mytable.myfield
но на практике он принимает только 2 и 3 выше. всякий раз, когда он видит ".", он переходит к требованию двухточечной версии таблицы (т.е. первое правило деривации для таблицы)
как я могу заставить эту грамматику работать?
Большое спасибо Ян
options{
IGNORE_CASE=true ;
STATIC=false;
DEBUG_PARSER=true;
DEBUG_LOOKAHEAD=true;
DEBUG_TOKEN_MANAGER=false;
// FORCE_LA_CHECK=true;
UNICODE_INPUT=true;
}
PARSER_BEGIN(TT)
import java.util.*;
public class TT {
}
PARSER_END(TT)
///////////////////////////////////////////// main stuff concerned
void Statement() :
{ }
{
<K_SELECT> Column()
}
void Column():
{
}
{
[LOOKAHEAD(3) Table() "." ]
//[
//LOOKAHEAD(2) (
// LOOKAHEAD(5) <S_IDENTIFIER> "." <S_IDENTIFIER>
// |
// LOOKAHEAD(3) <S_IDENTIFIER>
//)
//
//
//
//]
Field()
}
void Field():
{}{
<S_IDENTIFIER>
}
void Table():
{}{
LOOKAHEAD(5) <S_IDENTIFIER> "." <S_IDENTIFIER>
|
LOOKAHEAD(3) <S_IDENTIFIER>
}
////////////////////////////////////////////////////////
SKIP:
{
" "
| "\t"
| "\r"
| "\n"
}
TOKEN: /* SQL Keywords. prefixed with K_ to avoid name clashes */
{
<K_CREATE: "CREATE">
|
<K_SELECT: "SELECT">
}
TOKEN : /* Numeric Constants */
{
< S_DOUBLE: ((<S_LONG>)? "." <S_LONG> ( ["e","E"] (["+", "-"])? <S_LONG>)?
|
<S_LONG> "." (["e","E"] (["+", "-"])? <S_LONG>)?
|
<S_LONG> ["e","E"] (["+", "-"])? <S_LONG>
)>
| < S_LONG: ( <DIGIT> )+ >
| < #DIGIT: ["0" - "9"] >
}
TOKEN:
{
< S_IDENTIFIER: ( <LETTER> | <ADDITIONAL_LETTERS> )+ ( <DIGIT> | <LETTER> | <ADDITIONAL_LETTERS> | <SPECIAL_CHARS>)* >
| < #LETTER: ["a"-"z", "A"-"Z", "_", "$"] >
| < #SPECIAL_CHARS: "$" | "_" | "#" | "@">
| < S_CHAR_LITERAL: "'" (~["'"])* "'" ("'" (~["'"])* "'")*>
| < S_QUOTED_IDENTIFIER: "\"" (~["\n","\r","\""])+ "\"" | ("`" (~["\n","\r","`"])+ "`") | ( "[" ~["0"-"9","]"] (~["\n","\r","]"])* "]" ) >
/*
To deal with database names (columns, tables) using not only latin base characters, one
can expand the following rule to accept additional letters. Here is the addition of german umlauts.
There seems to be no way to recognize letters by an external function to allow
a configurable addition. One must rebuild JSqlParser with this new "Letterset".
*/
| < #ADDITIONAL_LETTERS: ["ä","ö","ü","Ä","Ö","Ü","ß"] >
}
4 ответа
Вы можете переписать свою грамматику следующим образом
Statement --> "select" Column
Column --> Prefix <ID>
Prefix --> (<ID> ".")*
Теперь единственный выбор - повторять или нет. Предполагая "." не может следовать за колонкой, это легко сделать с помощью вида 2:
Statement --> "select" Column
Column --> Prefix <ID>
Prefix --> (LOOKAHEAD( <ID> ".") <ID> ".")*
Действительно, следующая грамматика в flex+bison (LR parser) работает нормально, распознавая все следующие предложения правильно:
создать mydb.mytable создать mytable выбрать mydb.mytable.myfield выбрать mytable.myfield выбрать myfield
так что это действительно из-за ограничения парсера LL
%%
statement:
create_sentence
|
select_sentence
;
create_sentence: CREATE table
;
select_sentence: SELECT table '.' ID
|
SELECT ID
;
table : table '.' ID
|
ID
;
%%
Если вам нужно, чтобы Table был ее собственным нетерминалом, вы можете сделать это, используя логический параметр, который сообщает, будет ли за таблицей следовать точка.
void Statement():{}{
"select" Column() | "create" "table" Table(false) }
void Column():{}{
[LOOKAHEAD(<ID> ".") Table(true) "."] <ID> }
void Table(boolean expectDot):{}{
<ID> MoreTable(expectDot) }
void MoreTable(boolean expectDot) {
LOOKAHEAD("." <ID> ".", {expectDot}) "." <ID> MoreTable(expectDot)
|
LOOKAHEAD(".", {!expectDot}) "." <ID> MoreTable(expectDot)
|
{}
}
Это делает невозможным прямое или косвенное использование Table в любых синтаксических предварительных спецификациях. Например, вы не должны иметь LOOKAHEAD( Table())
где-нибудь в вашей грамматике, потому что семантический просмотр не используется во время синтаксического просмотра. Смотрите FAQ для получения дополнительной информации об этом.
Ваши примеры отлично анализируются с использованием JSqlParser V0.9.x ( https://github.com/JSQLParser/JSqlParser)
CCJSqlParserUtil.parse("SELECT mycolumn");
CCJSqlParserUtil.parse("SELECT mytable.mycolumn");
CCJSqlParserUtil.parse("SELECT mydatabase.mytable.mycolumn");