Я пытаюсь построить синтаксическое дерево для регулярного выражения. Я использую стратегию, аналогичную оценке арифметических выражений (я знаю, что существуют способы, подобные рекурсивному спуску), то есть для обработки используем два стека, стек OPND и стек OPTR.
Я использую различные виды узлов для представления различных типов RE. Например, SymbolExpression
, CatExpression
, OrExpression
и StarExpression
, все они являются производными от RegularExpression
.
Таким образом, в стеке OPND хранится RegularExpression*
.
while(c || optr.top()):
if(!isOp(c):
opnd.push(c)
c = getchar();
else:
switch(precede(optr.top(), c){
case Less:
optr.push(c)
c = getchar();
case Equal:
optr.pop()
c = getchar();
case Greater:
pop from opnd and optr then do operation,
then push the result back to opnd
}
Но мой основной вопрос, в типичном RE, оператор cat
неявный.
a|bc
представляет a|b.c
, (a|b)*abb
представляет (a|b)*.a.b.b
. Итак, при встрече с не оператором, как мне сделать, чтобы определить, есть ли оператор кошка или нет? И как мне поступить с оператором cat, чтобы правильно осуществить преобразование?
Обновление
Теперь я узнал, что есть своего рода грамматика, называемая «грамматика приоритета оператора», ее оценка аналогична арифметическому выражению. Это требует, чтобы образец грамматики не мог иметь форму S -> ... AB ... (A и B не являются терминальными). Так что я думаю, что я просто не могу напрямую использовать этот метод для анализа регулярного выражения.
Обновление II
Я пытаюсь разработать грамматику LL (1) для анализа основного регулярного выражения.
Вот грамматика происхождения. (\ | является escape-символом, так как | является специальным символом в шаблоне грамматики)
E -> E \| T | T
T -> TF | F
F -> P* | P
P -> (E) | i
Чтобы удалить левую рекурсию, импортируйте новую переменную
E -> TE'
E' -> \| TE' | ε
T -> FT'
T' -> FT' | ε
F -> P* | P
P -> (E) | i
сейчас, для шаблона F -> P * | P , import P '
P' -> * | ε
F -> PP'
Однако у шаблона T' -> FT' | ε
есть проблема. Рассмотрим случай (a | b):
E => TE'
=> FT' E'
=> PT' E'
=> (E)T' E'
=> (TE')T'E'
=> (FT'E')T'E'
=> (PT'E')T'E'
=> (iT'E')T'E'
=> (iFT'E')T'E'
Здесь наш человек знает, что мы должны заменить переменную T'
на T' -> ε
, но программа просто вызовет T' -> FT'
, что неверно.
Итак, что не так с этой грамматикой? И как я должен переписать это, чтобы сделать его пригодным для рекурсивного метода потомка.