Синтаксический анализ одного узла XML с помощью peg.js

Учитывая вход <outer> Content <inner> Inner <single/> </inner> </outer>,

Как бы я написал грамматику, которая разбирает <single> узел вместе с узлами, которые имеют соответствующий закрывающий узел?

Вот мой текущий грамматик, который был взят отсюда:

Content =
  (Element / Text)*

Element =
  startTag:StartTag content:Content endTag:EndTag {
    if (startTag != endTag) {
      throw new Error(
        "Expected </" + startTag + "> but </" + endTag + "> found."
      );
    }

    return {
      name:    startTag,
      content: content
    };
  }

StartTag =
  "<" name:TagName ">" { return name; }

EndTag =
  "</" name:TagName ">" { return name; }

TagName = chars:[a-z]+ { return chars.join(""); }
Text    = chars:[^<]+  { return chars.join(""); }

Это работает только с узлами, которые имеют закрывающий узел.

Я думаю, что проблема заключается в текстовом правиле. Поэтому я экспериментировал с его изменением, включив в него негативную перспективу, например:

Text    = chars:(!EndTag .)* EndTag { return chars.join(""); }

Но это еще ничего не дало.

Есть идеи?

1 ответ

Решение

Я сделал так, чтобы элемент соответствовал либо sTag, либо selfTag; если он соответствует "selfTag", то нет "Content" или "endTag":

Content =
  (Element / Text)*

Element =
  startTag:sTag content:Content endTag:eTag {
    if (startTag != endTag) {
      throw new Error(
        "Expected </" + startTag + "> but </" + endTag + "> found."
      );
    }

    return {
      name:    startTag,
      content: content
    };
  }
  / startTag:selfTag {
        return startTag;
    }

sTag =
  "<" name:TagName ">" { return name; }

selfTag =
  "<" name:TagName "/>" { return name; }

eTag =
  "</" name:TagName ">" { return name; }

TagName = chars:[a-z-]+ { return chars.join(""); }
Text    = chars:[^<]+  { return chars.join(""); }

Обратите внимание, что этот ответ требует использования <single/> вместо <single> (то есть / требуется); это самый простой способ сообщить анализатору PEG о разнице между висящим начальным тегом и "самозакрывающимся тегом".

Другие вопросы по тегам