Синтаксический анализ отрицательных чисел с помощью jparsec

#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