Расширяемый дизайн парсера - PullRequest
0 голосов
/ 01 декабря 2010

У меня есть класс Target с "fileType" enum, который содержит все виды файлов, о которых мой анализатор должен знать (в настоящее время SOURCE, HEADER, RESOURCE).Мне бы хотелось, чтобы моя функция синтаксического анализа могла делать что-то общее, например:

if( token == some_known_fileType )
    put_nextToken_in_the_list_for_that_fileType();
else
    return an_error();

Но есть одна загвоздка: я бы хотела иметь возможность просто расширять известные типы файлов с помощью подклассов Targetо том, как правильно расширить enum, см. Базовое наследование класса enum , как я это сделал.Я не хочу изменять вышеприведенный код, а лишь расширю целевую половину.C ++ 0X может потребоваться и очень приветствуется.

Спасибо!

ОБНОВЛЕНИЕ: После попытки объяснить это здесь и опубликования некоторых сокращенных объявлений класса я понял, что мойдизайн не работает, и я попытался слишком сильно углубить специализацию fileType в моей структуре классов.Мне нужно было только одно место для хранения полного списка всех известных типов, но, пытаясь это сделать, я случайно вынудил дизайн иметь доступ к этому списку в двух местах одновременно.Теперь я понимаю, что список всех типов файлов должен быть там, где читаются ключевые слова SOURCE, HEADER и т. Д., И обрабатываться * в общем случае с их помощью.Я буду хранить полный список в одном месте, и позже получу доступ к этому списку через «огромный» enum.std::map<fileType, std::set<std::string> > появляется в моей голове как логический выбор, вместо отдельного имени set для каждого конкретного fileType.Спасибо за умственные способности в ваших ответах, хотя!Любые мысли все еще приветствуются.

Ответы [ 3 ]

2 голосов
/ 01 декабря 2010

Я считаю, что это обычно не правильный подход, но это мое убеждение. Я бы сделал это по-другому. Сделайте шаг назад, и чего мы хотим достичь, мы хотим контролировать поведение на основе входящего (входного параметра) значения. Допустим, у нас есть классы: FileA FileB ... тип_файла содержит тип файла. Используйте фабрику для управления доступным списком файлов (который может меняться в зависимости от регистрации различных файлов).

class FileA {
    void register_type();  // register itself to the factory.
};

class FileB..
//main code
class FileFactoryDelegator {
    ...
    delegateControl (FileType file_type) {
        //validate file_type.
        file_types[file_type]->performFileOperation (..);
    }
};

Вместо цикла if-else.

file_factory.delegateControl (token);
0 голосов
/ 02 декабря 2010

не пишите свой парсер.используйте boost :: spirit

0 голосов
/ 01 декабря 2010

Сложно ответить, так как многое зависит от того, что именно вы делаете с токенами, значениями типов файлов и экземплярами Target.Тем не менее, я думаю, что основной темой здесь является то, что вам нужно заменить операторы if () вызовами виртуальных методов.Например, ваш фрагмент кода может в итоге получить

if (tokenLists.supportsFileType(token))
    tokenLists.getListForType(token).put_nextToken_into_this_list();
else
    return an_error();

Приведенный выше пример tokenLists можно обобщить в реестр экземпляров TargetSpecificLogic, который объединяет все виды методов, специфичных для типов файлов.класс может реализовать виртуальный метод retrieveAllKnownFileTypes(), который будет расширяться подклассами и который может оценить весь ваш код.

Класс Target может реализовать виртуальный метод bool isFileTypeKnown(filetype), возвращающий true или false.

... и т. Д.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...