Итак, я задал кучу меньших вопросов об этом проекте, но у меня все еще нет большой уверенности в конструкциях, которые я придумываю, поэтому я собираюсь задать вопрос в более широких масштабах ,Как лучше всего разобрать простую грамматику?
Я анализирую предварительные описания каталога курсов. Описания почти всегда следуют определенной форме, что заставляет меня думать, что я могу разобрать большинство из них.
Из текста, я хотел бы сгенерировать график, конечно, необходимых отношений. (Эта часть будет легко, после того как я разобраны данные.)
Некоторые примеры входов и выходов:
"CS 2110" => ("CS", 2110) # 0
"CS 2110 and INFO 3300" => [("CS", 2110), ("INFO", 3300)] # 1
"CS 2110, INFO 3300" => [("CS", 2110), ("INFO", 3300)] # 1
"CS 2110, 3300, 3140" => [("CS", 2110), ("CS", 3300), ("CS", 3140)] # 1
"CS 2110 or INFO 3300" => [[("CS", 2110)], [("INFO", 3300)]] # 2
"MATH 2210, 2230, 2310, or 2940" => [[("MATH", 2210), ("MATH", 2230), ("MATH", 2310)], [("MATH", 2940)]] # 3
Если вся описание только, конечно, выводится напрямую.
Если курсы соединяются («и»), все они выводятся в том же список
Если курс является разобщенными («или»), они находятся в отдельных списках
Здесь мы имеем и «и», и «или».
Одно предостережение, что делает его проще: оказывается, что вложенность фраз «и»/«или» никогда не бывает больше, чем показано в примере 3.
Что такое лучший способ сделать это ? Я начал с PLY, но я не мог понять, как разрешить конфликты уменьшения/уменьшения. Преимущество СЛОЯ в том, что это легко манипулировать, что формирует каждое правило синтаксического анализа:
def p_course(p):
'course : DEPT_CODE COURSE_NUMBER'
p[0] = (p[1], int(p[2]))
С PyParse, это менее понятно, как изменить вывод parseString()
. Я подумывал о том, чтобы основать идею @Alex Martelli о сохранении состояния в объекте и выработать выход из этого, но я не уверен точно, как это лучше всего сделать.
def addCourse(self, str, location, tokens):
self.result.append((tokens[0][0], tokens[0][1]))
def makeCourseList(self, str, location, tokens):
dept = tokens[0][0]
new_tokens = [(dept, tokens[0][1])]
new_tokens.extend((dept, tok) for tok in tokens[1:])
self.result.append(new_tokens)
Например, для обработки "или" случаи:
def __init__(self):
self.result = []
# ...
self.statement = (course_data + Optional(OR_CONJ + course_data)).setParseAction(self.disjunctionCourses)
def disjunctionCourses(self, str, location, tokens):
if len(tokens) == 1:
return tokens
print "disjunction tokens: %s" % tokens
disjunctionCourses()
Как узнать, какие меньше фраз разъединить? Все, что он получает, это токены, но то, что было проанализировано до сих пор, хранится в result
, поэтому как функция может определить, какие данные в result
соответствуют элементам token
? Я предполагаю, что я мог бы найти через лексему, а затем найти элемент result
с теми же данными, но чувствуют себя запутанными ...
Кроме того, есть много описаний, которые включают MISC текст, например:
"CS 2110 or permission of instructor"
"INFO 3140 or equivalent experience"
"PYSCH 2210 and sophomore standing"
Но не критично, что я разбираю этот текст.
Что является лучшим способом подойти к этой проблеме?
Нумерация в ваших входов и выходов образцов не соответствует нумерации при их обсуждении. –