Hành vi mặc định khi trình phân tích cú pháp không biết phải làm gì là in các thông báo tới thiết bị đầu cuối như:
dòng 1:23 thiếu DECIMAL tại '}'
Đây là một thông điệp tốt, nhưng không đúng chỗ. Tôi muốn nhận điều này như một ngoại lệ.
Tôi đã thử sử dụng BailErrorStrategy
, nhưng điều này ném ra một ParseCancellationException
mà không có thông báo (gây ra bởi a InputMismatchException
, cũng không có thông báo).
Có cách nào để tôi có thể báo cáo lỗi thông qua các ngoại lệ trong khi vẫn giữ lại thông tin hữu ích trong tin nhắn không?
Đây là những gì tôi thực sự theo đuổi - Tôi thường sử dụng các hành động trong quy tắc để xây dựng một đối tượng:
dataspec returns [DataExtractor extractor]
@init {
DataExtractorBuilder builder = new DataExtractorBuilder(layout);
}
@after {
$extractor = builder.create();
}
: first=expr { builder.addAll($first.values); } (COMMA next=expr { builder.addAll($next.values); })* EOF
;
expr returns [List<ValueExtractor> values]
: a=atom { $values = Arrays.asList($a.val); }
| fields=fieldrange { $values = values($fields.fields); }
| '%' { $values = null; }
| ASTERISK { $values = values(layout); }
;
Sau đó, khi tôi gọi trình phân tích cú pháp, tôi làm như sau:
public static DataExtractor create(String dataspec) {
CharStream stream = new ANTLRInputStream(dataspec);
DataSpecificationLexer lexer = new DataSpecificationLexer(stream);
CommonTokenStream tokens = new CommonTokenStream(lexer);
DataSpecificationParser parser = new DataSpecificationParser(tokens);
return parser.dataspec().extractor;
}
Tất cả những gì tôi thực sự muốn là
- để
dataspec()
cuộc gọi ném ra một ngoại lệ (lý tưởng là một ngoại lệ đã được chọn) khi đầu vào không thể phân tích cú pháp - ngoại lệ đó để có một thông báo hữu ích và cung cấp quyền truy cập vào số dòng và vị trí nơi phát hiện ra sự cố
Sau đó, tôi sẽ để ngoại lệ đó làm bong bóng ngăn gọi đến bất kỳ nơi nào phù hợp nhất để trình bày một thông báo hữu ích cho người dùng - giống như cách tôi xử lý kết nối mạng bị ngắt, đọc tệp bị hỏng, v.v.
Tôi đã thấy rằng các hành động hiện được coi là "nâng cao" trong ANTLR4, vì vậy có thể tôi đang xem xét mọi thứ theo một cách kỳ lạ, nhưng tôi chưa xem xét cách "không nâng cao" để làm điều này là gì kể từ đó đã hoạt động tốt cho nhu cầu của chúng tôi.