#java #parsing #jparsec
#java #синтаксический анализ #jparsec
Вопрос:
Используя jparsec, я пытаюсь проанализировать числа, которые могут быть или не быть отрицательными:
@Test
public void canParseIntegerValues() {
assertEquals(0, ValueParser.PARSER.parse("0"));
assertEquals(276, ValueParser.PARSER.parse("276"));
assertEquals(-3874, ValueParser.PARSER.parse("-3874"));
}
Я не смог понять, как объявить PARSER
. Я пробовал:
private static final Parser<Integer> INTEGER_VALUE_PARSER = Terminals.IntegerLiteral.TOKENIZER
.map(new Map<Fragment, Integer>() {
@Override
public Integer map(Fragment from) {
return Integer.valueOf(from.text());
}
});
Это не работает, потому Terminals.IntegerLiteral.TOKENIZER
что не содержит знака минус. Затем я попытался:
private static final Parser<Integer> INTEGER_VALUE_PARSER = Parsers.sequence(
Scanners.string("-").optional().token(),
Terminals.IntegerLiteral.TOKENIZER
.map(new Map<Fragment, Integer>() {
@Override
public Integer map(Fragment from) {
return Integer.valueOf(from.text());
}
}));
Это также не работает, потому что отрицательный знак отбрасывается, и моя функция map никогда его не видит.
Кто-нибудь может сказать мне, как правильно анализировать целые числа, которые могут быть или не быть положительными, используя jparsec?
РЕДАКТИРОВАТЬ: я нашел способ сделать это, но мне трудно поверить, что это лучший способ:
private static final Parser<Integer> INTEGER_VALUE_PARSER = Parsers.sequence(
Scanners.string("-").many(),
Terminals.IntegerLiteral.TOKENIZER,
new Map2<List<Void>, Fragment, Integer>() {
@Override
public Integer map(List<Void> from1, Fragment from2) {
boolean isNegative = (from1.size() % 2) == 1;
if (isNegative) {
return -1 * Integer.valueOf(from2.text());
} else {
return Integer.valueOf(from2.text());
}
}
});
Ответ №1:
Вы можете взглянуть на Calculator
класс в примерах jparsec: https://github.com/abailly/jparsec/blob/master/jparsec-examples/src/main/java/org/codehaus/jparsec/examples/calculator/Calculator.java Здесь отрицательные целые числа обрабатываются как целые числа, к которым был применен префиксный -
оператор.
В качестве альтернативы вы можете просто объявить шаблон, содержащий ваш знак минус:
public void test() {
Pattern regex = Patterns.regex("-?\d ");
Parser<Integer> integer = Scanners.pattern(regex, "Integer").source().map(new Map<String, Integer>() {
@Override
public Integer map(String s) {
return Integer.parseInt(s);
}
});
assertEquals(-42, (int) integer.parse("-42"));
}
HTH
Arnaud