Я пишу программу, которая ищет файл и каждый раз сталкивается с<‘charachter, он копирует его и каждый следующий символ в строку, пока не будет достигнуто’> ‘. Пока это то, что я сделал:
while(!file.eof()){
char c;
string tag;
file.get(c);
if(c == '<'){
tag_num++;
tag += c;
}
}
Как я могу теперь продолжить file.get(c)
, добавив каждый символ tag
пока «>» не будет достигнуто?
Моя идея, которую я не могу заставить работать, заключалась в том, чтобы добавить while(file.get(c) != '>')
цикл внутри цикла, который будет состоять из другого file.get(c)
и каждый из этих символов будет скопирован в tag
,
Разбор файла вручную быстро становится хитрым.
Вы можете посмотреть на парсер рекурсивного спуска.
Это шаблон, который заключается в реализации грамматики файла с помощью функции, декодирующей каждый элемент рекурсивным способом.
Давайте рассмотрим простой пример с упрощенной грамматикой XML (в БНФ форма):
element ::= '<'<tag>'/>'|'<'<tag>'>'<content>'<'<tag>'/>'
content ::= <element>|<freetext>|<freetext><element>
freetext ::= [^<>]<freetext>
tag ::= <alpha>|<alpha><alphanum>
alpha ::= [a-zA-Z]
alphanum ::= [a-zA-Z0-9]
(Я думаю [...]
Синтаксис для регулярного выражения не является частью BNF, но для меня это проще, чем записывать все буквы 🙂 [^<]
обозначает любой символ, который не является < что будет конфликтовать с началом тега в XML)
Эта грамматика описывает элемент. Элемент состоит из самозакрывающегося тега (например: <br/>
) или начальный тег, за которым следует содержимое, а затем конечный тег.
Контентом может быть элемент (отсюда рекурсивное определение с использованием предыдущего элемента), некоторый свободный текст или некоторый свободный текст, за которым следует элемент. Так далее …
Разбор может быть реализован механически:
Element parse_element(char *c)
{
Element myElement; // Element contains the result of the parsing
// It's a type you have to define !
assert( *c == '<' ); // Handle the error in a more clever way :-)
c++;
Tag myTag = parse_tag(c);
if( *c == '/')
{
// Self-closing tag - add myTag to myElement
c++;
assert( *c == '>'); // Here again, better error handling
c++;
}
else
{
// Or a start tag
assert( *c == '>'); // Here again, better error handling
c++;
Content myContent = parse_content(c);
// Add myTag with myContent to myElement
assert( *c == '/'); // Here again, better error handling
c++;
assert( *c == '>'); // Here again, better error handling
c++;
}
return myElement;
}
Я надеюсь, что этой функции достаточно, чтобы получить представление о концепции. Главное, что нужно понять, это то, что сначала вам нужно иметь четкую грамматику формата для чтения, определенного. Затем вы можете механически реализовать синтаксический анализатор.
Обратите внимание, что этот пример слишком прост: вам нужно как минимум обрабатывать сущности, атрибуты и т. Д. Для анализа реального XML.
Некоторые инструменты, такие как GNU Bison упростите написание кода, как только у вас будет грамматика.
Наконец, как уже говорилось в комментариях, некоторые XML-парсеры, такие как LibXML существует, если вы хотите разобрать файлы XML. Это будет намного проще и полнее, чем реализация собственного парсера. XML очень сложный формат.
Других решений пока нет …