2013-09-14 8 views
3

Я пишу SQL-подобный язык. Предположим, что правильный синтаксис являетсяxtext как переносить ошибку синтаксического анализа?

USE foo; 
SELECT * FROM bar; 

но я набираю его

US foo; 
SELECT * FROM bar; 

По умолчанию поведение Antlr остановит синтаксический анализ, и я потерял синтаксис hightlighting и вид контура. Сообщение об ошибке: Missing EOF at 'US'. Я пересвязать IParser к моему пользовательского анализатора в RuntimeModule

@Override 
public Class<? extends org.eclipse.xtext.parser.IParser> bindIParser() { 
    return CustomCqlParser.class; 
} 

Override метод createParser в Parser

@Override 
protected InternalCqlParser createParser(XtextTokenStream stream) { 
    return new CustomInternalCqlParser(stream, getGrammarAccess()); 
} 

и переопределить метод обработки этой части recoverFromMismatchedToken потреблять все маркеры до запятой

@Override 
protected Object recoverFromMismatchedToken(IntStream input, int ttype, BitSet follow) throws RecognitionException { 
    Object out = super.recoverFromMismatchedToken(input, ttype, follow); 

    if (out == null) { 

     beginResync(); 
     consumeUntil(input, RULE_T_SEMICOLON); 
     input.consume(); 
     endResync(); 

     Object matchedSymbol = getCurrentInputSymbol(input); 
     System.out.println(matchedSymbol); 
     return matchedSymbol; 
    } 
    return out; 
} 

после этого matchedSymbol - SELECT, но подсветка синтаксиса по-прежнему остается e и antlr прекратить разбор. Как я мог достичь своей цели?

============ ==================================================================================================================================================== =

Я копирую super.recoverFromMismatchToken в свой пользовательский класс и добавляю это из исходного кода.

if (ttype != EOF) { 
    beginResync(); 
    consumeUntil(input, RULE_T_SEMICOLON); 
    input.consume(); 
    endResync(); 

    Object matchedSymbol = getCurrentInputSymbol(input); 
    input.consume(); // move past ttype token as if all were ok 
    return matchedSymbol; 
} 

Если маркер ошибка происходит не в начале и не no viable alternative исключения, это будет держать подсветку синтаксиса собирается. Но он все равно будет считать, что он по-прежнему использует одни и те же правила синтаксического анализа, а не запускает новый. Кроме того, если я набрал неправильный токен в начале, то ожидаемым токеном будет EOF. Который заставит мои «потреблять все токены до тех пор, пока точка с запятой» тоже не сработает.

===================== ========================================================================================================================================== ===============================

tracing InternalCqlParser.java, я узнал, произошла ли опечатка в первом ключевом слове операторов, она получит ID и вернется. После этого я добавляю фрагмент кода

if (LA1_0 == RULE_IDENT) { 
    beginResync(); 
    consumeUntil(input, RULE_T_SEMICOLON); 
    input.consume(); 
    endResync(); 
    continue; 
} 

Разбор продолжается и подсветка синтаксиса остается после утверждения ошибки. Однако в строке ошибки не будет никакого маркера ошибки, и я потерял контент, помог после этой строки. Класс для запуска поддержки контента - Statement, но он больше не будет работать.

+0

Я полагаю, вы говорите о Кассандре CQL - Вы пытаетесь сделать парсер на самом деле принять что-то вроде «США mykeyspace;» как действительный оператор USE или вы просто пытаетесь улучшить сообщение об ошибке, чтобы он не говорил об EOF и не хотел отклонять утверждение в конце? –

+0

Привет, я больше не работаю над этим проектом. В то время я хочу сохранить подсветку синтаксиса и другие возможности IDE, но с маркером ошибки в неправильном выражении. В исходной ситуации, если я сделал одиночную опечатку, область редактирования всего текста станет серой из-за неудачного разбора. –

ответ

0

Что вы просите, вообще не поддерживается в основном парсерами на основе lexer, такими как те, которые генерируются Antlr/Xtext, потому что лексер должен решить, какой токен должен вырабатываться, не зная о правилах парсера, маркеры могут быть сопоставлены ,

В любом случае, я бы не рекомендовал пытаться решить эту проблему на уровне Antlr, потому что вам придется выполнять большую настройку в инструментах Xtext.

Если возможно, я бы рекомендовал думать об альтернативных решениях, которые не связаны с грамматикой вообще:

  • Если вы хотите лучше сообщения об ошибках синтаксиса, вы можете customize их.

  • Если ваш вариант использования поддерживает пользователя при наборе текста, пользовательский номер Auto Edit Strategy Provider может быть прав.

  • Если вы хотите, чтобы пользователь исправлял ошибки в существующих запросах, возможно, это может быть Quick Fixes (что может быть объединено с сообщениями об ошибках синтаксиса, см. Ссылку выше).

Только если ни один из них является вариант, и вы действительно хотите, чтобы позволить этот вид неправильно набранного синтаксиса, вы должны попытаться исправить ее на уровне грамматики. Как я полагаю, вы говорите о грамматике CQL Cassandra, я думаю, что существует более одного типа операторов (например, select, insert и т. Д.), Поэтому хаки с идентификаторами, интерпретируемыми как ключевые слова, не могут быть квалифицированы из-за неоднозначности грамматики (кроме их уродства ;-)). Итак, я думаю, вы должны перечислить все слова, которые вы готовы принять в качестве замены. В этом случае я бы предложил создать Data Type Rule для ошибочных вариантов каждого ключевого слова и другого правила типа данных для идентификаторов, включая туманные варианты, потому что, я думаю, вы не хотите запрещать «US» в качестве идентификатора. т.д .:

Use: 
    ('USE' | MistypedUseKeyword) keyspaceName=Identifier ';'; 

CreateTable: 

MistypedUseKeyword: 
    'US' | 'USW' | 'USEE'; 

MistypedCreateKeyword: 
    'CREAT' | 'CREATW' | 'CERATE' | 'CRATE'; 

MistypedTableKeyword: 
    'TABL' | 'TALBE' | 'TBLE' | 'TBALE' | 'TABEL'; 

MistypedKeyword: 
    MistypedUseKeyword | MistypedCreateKeyword | MistypedTableKeyword; 

Identifier: 
    ID | MistypedKeyword; 
Смежные вопросы