首页 > 解决方案 > 我的 PetitParser 映射函数中缺少空格

问题描述

我试图解析带有函数调用的普通文本。

class EmmaGrammarDefinition extends GrammarDefinition {
  const EmmaGrammarDefinition();

  Parser start() => ref(value).plus().end();

  Parser token(Object source, [String name]) {
    if (source is String) {
      return source.toParser(message: 'Expected ${name ?? source}').trim();
    } else if (source is Parser) {
      ArgumentError.checkNotNull(name, 'name');
      return source.flatten('Expected $name').trim();
    } else {
      throw ArgumentError('Unknown token type: $source.');
    }
  }

  Parser word() =>
      ref(wordToken) &
      (whitespace().plus() | ref(token, '.') | whitespace()).optional();

  Parser call() =>
      ref(wordToken) & ref(token, '(') & ref(value) & ref(token, ')');

  Parser array() =>
      ref(token, '[') & ref(elements).optional() & ref(token, ']');

  Parser elements() =>
      ref(value).separatedBy(ref(token, ','), includeSeparators: false);

  Parser members() =>
      ref(pair).separatedBy(ref(token, ','), includeSeparators: false);

  Parser object() =>
      ref(token, '{') & ref(members).optional() & ref(token, '}');

  Parser pair() => (ref(wordToken)| ref(stringToken)) & ref(token, ':') & ref(value);

  Parser value() =>
      ref(call) |
      ref(word) |
      ref(stringToken) |
      ref(numberToken) |
      ref(object) |
      ref(array) |
      ref(trueToken) |
      ref(falseToken) |
      ref(nullToken);

  Parser trueToken() => ref(token, 'true');

  Parser falseToken() => ref(token, 'false');

  Parser nullToken() => ref(token, 'null');

  Parser stringToken() => ref(token, ref(stringPrimitive), 'string');

  Parser numberToken() => ref(token, ref(numberPrimitive), 'number');

  Parser wordToken() => ref(token, ref(wordPrimitive), 'word');

  Parser characterPrimitive() =>
      ref(characterNormal) | ref(characterEscape) | ref(characterUnicode);

  Parser characterNormal() => pattern('^"\\');

  Parser characterEscape() => char('\\') & pattern(jsonEscapeChars.keys.join());

  Parser characterUnicode() => string('\\u') & pattern('0-9A-Fa-f').times(4);

  Parser numberPrimitive() =>
      char('-').optional() &
      char('0').or(digit().plus()) &
      char('.').seq(digit().plus()).optional() &
      pattern('eE')
          .seq(pattern('-+').optional())
          .seq(digit().plus())
          .optional();

  Parser wordPrimitive() => letter().plus() & digit().plus().optional();

  Parser stringPrimitive() =>
      char('"') & ref(characterPrimitive).star() & char('"');
}

它很接近,但我对普通文本部分有一些问题。当我想映射这些点时,点就在那里,但缺少空白。

Parser word() => super.word().map((each) => WordValueWidget(each));

当我解析“Hello World”时。每个是第一个 ["Hello", null] 然后是 ["World", "."] 我希望它是第一个 ["Hello", " "] 然后是 ["World", "."]。

感谢您的帮助,对不起我的英语不好:)

标签: flutterdartpetitparser

解决方案


我怀疑wordToken在单词字符之后已经消耗了所有空格(由于.trim()您的令牌定义中的操作)。然后没有任何选择whitespace().plus() | ref(token, '.') | whitespace()匹配,并.optional()返回null

也就是说,从您发布的那种庞大而复杂的语法中很难分辨出来。理想情况下,您会尝试将问题分解为更小且更易于管理的部分,然后可以独立测试和修复。一个最低限度可重现的示例将使我更容易提供直接适用的解决方案。


推荐阅读