Эта ошибка обычно возникает, когда вы пытаетесь прочитать файл, используя неправильную кодировку. Но, учитывая очень высокое смещение в вашем случае, также возможно, что у вас есть правильная кодировка, но какая-то ошибка в файле - нет смысла размышлять над спецификой.
Поскольку файл кажется в основном правильно, я могу просто попросить необработанные байты заменить специальным символом '�'
(Unicode "\ufffd"
). Затем вы можете найти контекст ошибки, просто выполнив поиск этого символа.
f = open('FY16_Query_Analysis1.txt', errors="replace")
raw = f.read()
lines = raw.splitlines()
for line in lines:
if '�' in line:
print(line)
В зависимости от того, что вы видите, вы можете решить, что делать дальше.
Альтернативно, вы мог прочитать файл в двоичном режиме и преобразовать строку вокруг рассматриваемого смещения; например:
f=open('FY16_Query_Analysis1.txt','rb')
raw = f.read()
errorpos = 16592600
fragment = raw[errorpos-20:errorpos+40]
print(repr(fragment))
Есть ли способ сделать ANTLR автоматически добавлять любые комментарии, которые он находит в AST?
blockquote>Нет, вам придется посыпать всю грамматику дополнительными правилами
comments
, чтобы учесть все допустимые места, которые могут возникнуть в комментариях:... if_stat : 'if' comments '(' comments expr comments ')' comments ... ; ... comments : (SingleLineComment | MultiLineComment)* ; SingleLineComment : '//' ~('\r' | '\n')* ; MultiLineComment : '/*' .* '*/' ;
Я сделал это на моей лексерской части:
WS : ( [ \t\r\n] | COMMENT) -> skip
;
fragment
COMMENT
: '/*'.*'*/' /*single comment*/
| '//'~('\r' | '\n')* /* multiple comment*/
;
Как будто он автоматически удалит их!
сначала: направить все комментарии на определенный канал (только комментарии)
COMMENT
: '/*' .*? '*/' -> channel(2)
;
LINE_COMMENT
: '//' ~[\r\n]* -> channel(2)
;
second: распечатать все комментарии
CommonTokenStream tokens = new CommonTokenStream(lexer);
tokens.fill();
for (int index = 0; index < tokens.size(); index++)
{
Token token = tokens.get(index);
// substitute whatever parser you have
if (token.getType() != Parser.WS)
{
String out = "";
// Comments will be printed as channel 2 (configured in .g4 grammar file)
out += "Channel: " + token.getChannel();
out += " Type: " + token.getType();
out += " Hidden: ";
List<Token> hiddenTokensToLeft = tokens.getHiddenTokensToLeft(index);
for (int i = 0; hiddenTokensToLeft != null && i < hiddenTokensToLeft.size(); i++)
{
if (hiddenTokensToLeft.get(i).getType() != IDLParser.WS)
{
out += "\n\t" + i + ":";
out += "\n\tChannel: " + hiddenTokensToLeft.get(i).getChannel() + " Type: " + hiddenTokensToLeft.get(i).getType();
out += hiddenTokensToLeft.get(i).getText().replaceAll("\\s", "");
}
}
out += token.getText().replaceAll("\\s", "");
System.out.println(out);
}
}
Для ANTLR v3:
Имена прожекторов обычно не обрабатываются парсером, но они все еще захватываются на канале HIDDEN.
Если вы используете BufferedTokenStream
, вы можете получить список всех токенов через него и выполнить постобработку, добавив их по мере необходимости.
В разделе 12.1 в «Определяющем описании Antlr 4» показано, как получить доступ к комментариям, не используя правила комментариев во всей грамматике. Короче говоря, вы добавляете это в файл грамматики:
grammar Java;
@lexer::members {
public static final int WHITESPACE = 1;
public static final int COMMENTS = 2;
}
. Тогда для ваших правил комментариев выполните следующее:
COMMENT
: '/*' .*? '*/' -> channel(COMMENTS)
;
LINE_COMMENT
: '//' ~[\r\n]* -> channel(COMMENTS)
;
Затем в коде запросите токены через getHiddenTokensToLeft / getHiddenTokensToRight и посмотрите раздел 12.1 в книге, и вы увидите, как это сделать.
Также можно использовать функцию «островные грамматики». См. Следующий раздел в книге ANTLR4:
Остроумные грамматики: обращение к разным форматам в одном файле
blockquote>
comments
не соответствует никаким или более комментариям, после него?
не требуется. – Bart Kiers 19 September 2012 в 15:06