Есть ли хороший, многоразовый парсер, который преобразует строку в иерархию списков? - PullRequest
0 голосов
/ 19 января 2009

Я бы хотел взять такую ​​строку:

[One, Two[A, B[i, ii, iii, iv], C], Three]

И преобразовать его в иерархию списков, чтобы при выполнении кода, такого как следующий:

Console.Write(myList[1][1][2]);

Вывод будет:

iii

Я надеюсь, что это достаточно распространенное требование, чтобы на C # был написан простой код синтаксического анализа.

Дайте мне знать, если мой вопрос будет сформулирован более четко.

Ответы [ 5 ]

4 голосов
/ 19 января 2009

XML или JSON - превосходные методы для хранения подобных вещей.

Как сказал Спенс - это сложная проблема - я не рекомендую кататься самостоятельно.

Прокрутите вниз до этой ссылки JSON для реализации на большинстве языков.

2 голосов
/ 19 января 2009

Я должен был бы пойти с регулярным выражением. Соответствия подстрок и подвыражения могут дать вам рекурсию для получения уровней sub-sub -... в.

Используйте что-то вроде /^\[(.+)\]$/ в preg, чтобы собрать один уровень предметов. Обрабатывайте его до тех пор, пока вы больше не получите уровень, взорвитесь на ',' после того, как вы получите смелость одной серии.

Результат разделения на ','.

должно получиться как

  • [Один, Два [A, B [i, ii, iii, iv], C], Три]
    • Один
    • Два
    • [A, B [i, ii, iii, iv], C]
      • A
      • B
      • [i, ii, iii, iv]
        • я
        • II
        • III
        • IV
      • C
    • Три

Наконец обрежьте левый / правый пробел, чтобы получить отточенный результат.

0 голосов
/ 19 января 2009

Мой голос также за XML, JSON или другой формат, если у вас есть возможность контролировать формат. Но без этого, вот реализация Python парсера, потому что мне было скучно.

class ExprParser(object):
current = []
list_stack = []

def __init__(self):
    pass

def parse(self,input):
    for atom in [s.strip() for s in input.split(',')]:
        self.parse_atom(atom)
    return self.current

def do_pushes(self,atom):
    """ Strip off the '[' and push new lists """
    i = 0
    while i < len(atom) and atom[i] == '[':
        self.push()
        i += 1
    return atom[i:]

def do_pops(self,atom):
    """ Pop the lists """
    i = 0
    while i < len(atom) and atom[i] == ']':
        self.pop()
        i += 1

def parse_atom(self,atom):
    push_start = atom.find('[')

    rest = self.do_pushes(atom[push_start:]) if push_start >= 0 else atom

    pop_start = rest.find(']')

    val = rest[:pop_start] if pop_start >= 0 else rest

    self.add(val)

    if pop_start >= 0:
        self.do_pops(rest[pop_start:])

def push(self):
    self.current = []
    self.list_stack.append(self.current)

def pop(self):
    done = self.list_stack.pop()
    self.current = self.list_stack[-1] if self.list_stack else done
    if self.current is not done:
        self.add(done)

def add(self,val):
    self.current.append(val)

Используйте как:

parser = ExprParser()
parser.parse('[One, Two[A, B[i, ii, iii, iv], C], Three]')

Нет обработки ошибок, хотя для некорректного ввода.

0 голосов
/ 19 января 2009

Это не практичный ответ, но если вы можете использовать бета-версию .NET 4.0, вы можете изучить Oslo (и последующие инструменты), которые Microsoft разрабатывает для текстовых DSL, которые, кажется, именно то, что вам нужно. 1001 *

0 голосов
/ 19 января 2009

Вы после массивов или списков?

Это было бы чрезвычайно трудно сделать со строками, так как вам приходится иметь дело с пробелами или использованием запятой в элементе и т. Д.

Если у вас есть контроль над тем, что в этом списке, я предлагаю вам изучить XML или двоичную сериализацию, в которой есть библиотеки, которые помогут вам сделать это.

...