Способ парсинга

Передо мной стоит задача написать программу для парсинга конфигурационного файла nginx. Я нашел решение этой задачи, но мне также необходимо определить, каким образом выполняется синтаксический разбор этого файла. Я считаю, что это абстрактное синтаксическое дерево, но я могу ошибаться. Вот код

import re
import json

FILENAME = 'testfile'

class Config(object):

    rex_start = re.compile(r"""^<(?P<name>[^/\s>]+)\s*(?P<value>[^>]+)?>$""")
    rex_end = re.compile(r"""^</(?P<name>[^\s>]+)\s*>$""")
    rex_comment = re.compile(r"""^#.*$""")

    def __init__(self, name, vals=[]):
        self.name = name
        self.vals = vals
        self.attribs = []
        self.children = []

    def find(self, path):
        pathPoint = path.strip("/").split("/")
        if pathPoints[0] == '':
            return self
        return self._find(pathPoints)


    def search(self, pathPoints):
        if pathPoints:
            next = pathPoints.pop(0)
            for child in self.children:
                if child.name == next:
                    result = child._find(pathPoints)
                    if result:
                        return result
            return None
        else:
            return self


    def findall(self, path):
        pathPoints = path.strip("/").split("/")
        if pathPoints[0] == '':
            return [self]
        return self._findall(pathPoints)


    def searchall(self, pathPoints):
        if pathPoints:
            result = []
            next = pathPoints.pop(0)
            for child in self.children:
                if child.name == next:
                    result.extend(child._findall(pathelements))
            return result
        else:
            return [self]

    def _attrib(self, name, vals ):
        setattr( self, name, vals )
        self.attribs.append( name )

    def childAppend(self, name, vals):
        child = Config(name, vals)
        self.children.append(child)
        child.parent = self
        self.attribs.append( child )

        attr = getattr( self, name, None )
        if attr != None:
            if type(attr) == list:
                attr.append( child )
            else:
                attr = [attr,child,]
            setattr( self, name, attr )
        else:
            setattr( self, name, child )

        return child

    def print_json(self, indt = 0):
        if indt == 0:
            print("{")
            indt += 1

        if self.vals != []:
            print ("    " * indt + '"атрибут": %s,'%json.dumps(self.vals))
        for attribute in self.attribs[:-1]:
            if type(attribute) != Config:
                print( "    " * indt + '"' + attribute + '":' + json.dumps(getattr(self, attribute, None)) + ",")
            else:
                print ("    " * indt + '"' + attribute.name + '":{')
                attribute.print_json(indt+1)
                print ("    " * indt + "},")
        else:
            if type(self.attribs[-1]) != Config:
                print( "    " * indt + '"' + self.attribs[-1] + '":' + json.dumps(getattr(self, self.attribs[-1], None)) )
            else:
                print ("    " * indt + '"' + self.attribs[-1].name + '":{')
                self.attribs[-1].print_json(indt+1)
                print ("    " * indt + "}")

        if indt == 1:
            print("}")


    @classmethod
    def pars_file(cls, file):
        f = open(file)
        root = cls._pars(f)
        f.close()
        return root

    @classmethod
    def _pars(cls, itobj):
        root = node = Config('root')
        for line in itobj:
            line = line.strip()


            # Если строка пустая или это комментарий, то пропускаем
            if (len(line) == 0) or cls.rex_comment.match(line):
                continue

            # Если найдено начало блока, добавляем его как дочерний элемент
            match = cls.rex_start.match(line)
            if match:
                vals = match.group("value").split()
                node = node.add_child(match.group("name"), vals)
                continue

            # Возвращаемся на родителя если найден конец блока
            match = cls.rex_end.match(line)
            if match:
                if node.name != match.group("name"):
                    raise Exception("Ошибка: '"+match.group("name")+"' должен быть '"+node.name+"'")
                node = node.parent
                continue

            """
             Если строка - не начало или конец,
             то это параметр, добавляем его в свойства узла
             и делаем его свойством класса
            """

            vals = line.split()
            name = vals.pop(0)
            if len(vals) == 1:
                vals = vals[0].strip('"')
            node._attrib(name, vals)
        return root

conf=Config.pars_file(FILENAME)

conf.print_json()

Ответы (0 шт):