Идентификатор eps
, как и многие другие используемые вами идентификаторы, определены в пространстве имен qi
.Остальные переносятся в глобальное пространство имен с помощью операторов using
в верхней части вашего конструктора.Сделайте то же самое для eps
:
using qi::eps;
Как только вы решите это, у вас возникнет более серьезная проблема: правильно ли вы представляете синтаксис и грамматику XML.Похоже, вы не правы.У вас есть это:
xml %=
start_tag[_a = _1]
> attribute
> ( "/>" > eps
| ">" > *node > end_tag(_a)
)
;
Хотя это не может быть правдой.Атрибуты являются частью тега, а не вещами, которые следуют за тегом.Похоже, вы хотели сломать start_tag
приложение, чтобы вы могли обрабатывать пустые теги.Если бы я делал это, я бы, вероятно, вместо этого создал бы правило empty_tag
, а затем изменил бы xml
на empty_tag | (start_tag > *node > end_tag)
.Вот как рекомендация по языку W3C делает это:
[39] element ::= EmptyElemTag
| STag content ETag
Но пока не беспокойтесь об этом.Помните, что ваша заявленная задача - добавить атрибутов в анализатор.Не отвлекайтесь на другие недостающие функции.Позже есть над чем поработать.
Я упомянул документ W3C.Вы должны обращаться к этому часто;он определяет язык и даже показывает грамматику.Одна из целей разработки Spirit заключалась в том, чтобы он выглядел как грамматическое определение.Используйте это в своих интересах, пытаясь имитировать грамматику W3C в своем собственном коде.W3C определяет начальный тег следующим образом:
[40] STag ::= '<' Name (S Attribute)* S? '>'
[41] Attribute ::= Name Eq AttValue
Итак, напишите ваш код следующим образом:
start_tag %=
// Can't use operator> for "expect" because empty_tag
// will be the same up to the final line.
'<'
>> !lit('/')
>> name
>> *attribute
>> '>'
;
name %= ...; // see below
attribute %=
name
> '='
> attribute_value
;
Спецификация определяет синтаксис значения атрибутов:
[10] AttValue ::= '"' ([^<&"] | Reference)* '"'
| "'" ([^<&'] | Reference)* "'"
Я бы пока не беспокоился о ссылках на сущности.Как и пустые теги, ваш текущий код уже не поддерживает их, поэтому не важно добавлять их сейчас как часть атрибутов.Это позволяет легко определить attribute_value
:
attribute_value %=
'"' > *(char_ - char_("<&\"")) > '"'
| '\'' > *(char_ - char_("<&'")) > '\''
;
Определение name
еще не должно быть чем-то фантастическим.Это сложно в спецификации, потому что он обрабатывает весь диапазон символов Unicode, но вы можете начать с чего-то более простого и вернуться к нему позже, когда вы поймете, как обрабатывать символы Unicode в вашем парсере.
name %=
lexeme[char_("a-zA-Z:_") >> *char_("-a-zA-Z0-9:_")]
;
Эти изменения должны позволить вам проанализировать атрибуты XML. Однако , это другой вопрос - извлекать результаты как атрибуты Spirit (чтобы вы могли знать имена и значения атрибутов для данного тега в остальной части вашей программы), и я 'Я не готов обсуждать это прямо сейчас.