Я бы предложил (и это более или менее прямо из учебников по компилятору), что вы подходите к проблеме поэтапно.Это ломает вещи так, что проблема становится намного более управляемой на каждой фазе.
Сосредоточьтесь сначала на фазе лексера.Ваша фаза лексизма должна взять необработанный текст и дать вам последовательность токенов, таких как слова и специальные символы.Фаза лексера может заботиться о продолжении строки и обрабатывать пробелы или комментарии в зависимости от ситуации.Обрабатывая пробелы, лексер может упростить задачу вашего синтаксического анализатора: вы можете написать лексер так, чтобы global{
, global {
и даже
global<br/>
{
приводили к двум токенам:один, представляющий global
, и другой, представляющий {
.
Также обратите внимание, что лексер может прикрепить номера строк и столбцов к токенам для использования позже, если вы нажмете ошибки.
После того, как вы получите хороший поток токенов, приступайте к фазе анализа.Анализатор должен взять эту последовательность токенов и построить абстрактное синтаксическое дерево, которое моделирует синтаксические структуры вашего документа.На этом этапе вам не следует беспокоиться о ifstream
и operator>>
, поскольку лексер должен был выполнить все это чтение за вас.
Вы указали на заинтересованность в рекурсивном вызове функции синтаксического анализа один разВы видите область.Это, безусловно, один из способов.Как вы увидите, дизайнерское решение, которое вы должны будете неоднократно принимать, заключается в том, хотите ли вы буквально вызывать одну и ту же функцию синтаксического анализа рекурсивно (с учетом конструкций типа global { global { ... } }
, которые вы, возможно, захотите запретить синтаксически), или хотите лиопределить немного (или даже значительно) другой набор синтаксических правил, которые применяются внутри области.
Как только вы обнаружите, что вам нужно изменить правила: ключ заключается в повторном использовании, путем рефакторинга в функции, столько вещей, сколькоВы можете повторно использовать различные варианты синтаксиса.Если вы продолжаете двигаться в этом направлении - используя отдельные функции, которые представляют различные фрагменты синтаксиса, с которыми вы хотите иметь дело, и заставляете их вызывать друг друга (возможно, рекурсивно) там, где это необходимо - в конечном итоге вы получите то, что мы называем парсер рекурсивного спуска .У записи Википедии есть хороший простой пример одного;см. http://en.wikipedia.org/wiki/Recursive_descent_parser.
Если вы действительно хотите углубиться в теорию и практику лексеров и синтаксических анализаторов, я рекомендую вам получить хороший твердый учебник по компилятору, который поможет вам.Тема переполнения стека, упомянутая в комментариях выше, поможет вам начать: Обучение написанию компилятора