Задача ниже требует, чтобы вы были знакомы с формальной теорией синтаксического анализа. Если вы не знаете, что задает вопрос, потому что не знаете, что означают эти термины, грамматики без контекста и наборы «первый / следующий» рассматриваются во многих университетских курсах.
Я могу порекомендовать этот Стэнфордский курс , в частности раздаточные материалы 08 и 09 (со страницы 7). Из этих раздаточных материалов я также извлек шпаргалку - всем, кто пытается выполнить эту задачу, я рекомендую прочитать ее .
Напишите программу или функцию, которая с учетом контекстно-свободной грамматики найдет следующий набор всех нетерминалов. Неформально, следующий набор нетерминала - это набор терминалов и $
(имеется в виду конец ввода), который вы можете найти после этого терминала в действительном предложении.
Входные данные задаются в виде одной печатаемой строки ASCII или массива печатаемых строк ASCII. Вы можете выводить наборы в любом приемлемом формате, используя $
(либо в качестве литерального вывода, либо в строке внутри набора и т. Д.), Чтобы указать конец ввода. Вы можете предположить, что ввод всегда действителен в соответствии с форматом ниже.
Контекстно-свободная грамматика дана в очень упрощенной форме. Каждая линия содержит одну продукцию. Каждое производство представляет собой список символов, разделенных пробелами. Терминал - это строка символов, окруженная апострофами (например '**'
). Для простоты вы можете предположить, что терминалы не содержат пробелов, но было бы неплохо, если ваша программа это позволяет. Нетерминал может быть любой строкой, не содержащей пробелов или $
. Пустое произведение (обычно обозначаемое ε) - это просто строка, содержащая только нетерминал с левой стороны. Первая строка - это производство, определяющее начальный символ.
В качестве примера приведем следующую грамматику:
S → aSa | bSb | ε
Будет дано как:
S 'a' S 'a'
S 'b' S 'b'
S
Пример ввода / вывода:
In:
S 'a' S 'a'
S 'b' S 'b'
S
Out:
S {'a', 'b', $}
In:
S A B C
A 'a'
A C 'b'
A
B C
B 'd' A
B
C 'e'
C 'f'
Out:
S {$}
A {'d', 'e', 'f'}
B {'e', 'f'}
C {'b', 'e', 'f', $}
In:
Start Alice Bob
Alice Charlie 'a'
Alice
Bob Bob 'a' Alice Charlie
Bob '!!!'
Charlie 'b'
Charlie
Out:
Start {$}
Alice {'a', '!!!', 'b', $}
Bob {'a', $}
Charlie {'a', $}
Самый короткий код в байтах побеждает.
Ответы:
Perl, 257 байт
Включает +4 для
-0p
Дайте грамматику на STDIN (без конечных пробелов. Обязательно удалите лишний пробел во втором примере). Предполагается, что нетерминальные имена содержат только буквы, цифры и
_
. Используется#
вместо того,$
чтобы указывать конец ввода. Может обрабатывать литералы, содержащие пробелыВыводит следующие наборы в виде списка
non-terminal literal
в произвольном порядке. Для приведенного выше примера это выводит:follow.pl
:Работает, как показано, но заменяет их
\xd8
и\n
их буквальными версиями, чтобы получить заявленную оценку.Это должно быть возможно улучшить, поскольку преобразование
first
наборов вfollow
наборы в настоящее время очень неудобно.источник