Это переформулировка программ грамматики? предыдущий вопрос от Vag и множество предложений от комментаторов.
Каким образом грамматика может рассматриваться как спецификация модели вычислений? Если, например, мы берем простую контекстно-свободную грамматику, такую как
G ::= '1' -> '0' '+' '1'
'1' -> '1' '+' '0'
'2' -> '2' '+' '0'
'2' -> '1' '+' '1'
'2' -> '0' '+' '2'
'3' -> '3' '+' '0'
'3' -> '2' '+' '1'
'3' -> '1' '+' '2'
'3' -> '1' '+' '2'
Предполагая, что синтаксический анализатор не различает терминальные и нетерминальные символы, как я продемонстрировал здесь, можно выполнить простую арифметику для чисел до 3.
Например, взять строку
"2 + 0 + 1"
Запуск синтаксического анализатора LR (1) для этой строки должен дать нам следующее конкретное синтаксическое дерево, в котором результат вычисления сохраняется в корне дерева:
'3'
/ | \
/ | \
'2' '+' '1'
/ | \
/ | \
'2' '+' '0'
Таким образом, если мы возьмем грамматику в качестве программы и генератор синтаксического анализатора в качестве компилятора , можем ли мы рассматривать язык спецификации грамматики в качестве языка программирования ?
Кроме того, можем ли мы построить программы, полные по Тьюрингу, указав грамматику, аналогичную тому, как вы могли бы построить программы, полные по Тьюрингу, с помощью целлюлярных автоматов или лямбда-исчисления ?
Другими словами, известно, что в смысле распознавания языка обычные языки соответствуют автоматам конечного состояния , контекстно-свободные языки соответствуют автоматам с выталкиванием , а контекстно-зависимые языки соответствуют линейным ограниченным автоматам . Однако если мы посмотрим на грамматики как на вычислительные устройства (т.е. программы в смысле вышеприведенного примера), то как мы классифицируем вычислительную мощность каждого класса грамматик в иерархии Хомского?
- Регулярные грамматики
- Контекстно-свободные грамматики
- Контекстно-зависимые грамматики
- Неограниченные грамматики (для рекурсивно перечислимых языков )
Кроме того, как насчет менее известных подклассов грамматик, таких как
- Детерминированные контекстно-свободные грамматики (также LR (k) / LL (k) / SLR / LALR и т. Д.)
- Вложенные грамматики слова
- Примыкающие к дереву грамматики
- Индексированные грамматики
РЕДАКТИРОВАТЬ: Между прочим, это мой клеветник по моему собственному вопросу, но я не упомянул, что я не дал начальный символ для примера грамматики и помахал рукой при необходимости различать терминалы и нетерминалы. Технически или традиционно я думаю, что грамматика, вероятно, должна была бы быть написана в более сложной форме, такой как эта (где S - начальный символ, а $ - терминал конца потока):
G ::= S -> R0 '$'
S -> R1 '$'
S -> R2 '$'
R0 -> '0'
R0 -> R0 '+' '0'
R1 -> '1'
R1 -> R0 '+' '1'
R1 -> '1' '+' R0
R1 -> R0 '+' '1' '+' R0
R2 -> '2'
R2 -> R0 '+' '2'
R2 -> '2' '+' R0
R2 -> R0 '+' '2' '+' R0
R2 -> R1 '+' '1'
R2 -> R1 '+' '1' '+' R0
... не то чтобы это действительно что-то меняет, но я подумал, что должен это упомянуть.
РЕДАКТИРОВАТЬ: Что-то еще, что пришло в голову, когда я прочитал ответ Гаше, это то, что каждая ветвь в дереве в моем примере представляет подсчет. Если вы посмотрите на каждое производственное правило как на функцию, в которой LHS представляет результат, а RHS представляет его аргументы, то структура грамматики определяет, как составляются функции.
Другими словами, контекст синтаксического анализатора вместе с его механизмом предварительного просмотра помогает определить не только, какие функции применять (своего рода параметрический полиморфизм), но и то, как они должны быть скомпонованы вместе для формирования новых функций.
По крайней мере, я полагаю, что вы могли бы взглянуть на это таким образом для однозначных CFG, для других грамматик умственная гимнастика для меня сейчас слишком велика.
Ответы:
Между грамматиками Хомского типа 0 и машинами Тьюринга существует однозначное соответствие .
Это используется в языке программирования Thue, который позволяет вам писать программы, полные по Тьюрингу, заданные исходной строкой и набором правил перезаписи строк ( грамматика полу-Thue , которая эквивалентна грамматике типа 0).
ОБНОВИТЬ:
Помимо эзотерических языков «таржанки Тьюринга», таких как Thue, для выполнения полного по Тьюрингу вычисления на этапе компиляции синтаксического анализа могут использоваться различные языки общего назначения, которые позволяют программисту расширять свой собственный синтаксис.
Языки в семействе Lisp , в частности Common Lisp , являются, пожалуй, наиболее очевидными примерами, но в целом это также языки со статической проверкой типов, которые не всегда должны останавливаться, такие как C ++ с шаблонами , Scala и Qi .
источник
Мой ответ не предназначен быть формальным, точным и абсолютно тематическим. Я думаю, что ответ Марка Хаммана очень убедителен, но ваш вопрос заставил меня задуматься о смежной теме.
Грамматики можно рассматривать как особые случаи дедуктивных систем: входные данные являются суждением, а дерево разбора является производным суждения или доказательством того, что суждение является действительным в соответствии с (грамматическими) правилами.
В этом смысле ваш вопрос может быть связан с подходом какой-то части сообщества логического программирования / поиска доказательства (я думаю о Дейле Миллере, например), который заключается в том, что поиск доказательства имеет вычислительное содержание, в отличие от более классического точка зрения теории типа / доказательства, где вычисление - это нормализация доказательства .
Замечание: перечитывая мой ответ, я думаю, что идея о том, что «построение дерева разбора является поиском корректуры», здесь немного надумана. Поиск доказательства скорее идет в другом направлении: один начинается с данного, довольно сложного суждения и, благодаря многократному использованию правил вывода, работающих над структурой доказательства, мы надеемся получить более простые аксиомы, которые не нуждаются в дальнейшем доказательстве. Таким образом, было бы более естественно видеть в грамматических терминах сложные суждения как нетерминалы, атомы как терминалы, а поиск доказательства как проблему генерации слова или тест на пустоту.
источник
Я не уверен, правильно ли я понял ваш вопрос, но если вы ищете язык программирования, основанный на некой системе строкового переписывания, вы, вероятно, заинтересуетесь Refal , который основан на формализме алгоритма Маркова ( формализм, который также является грамматически-подобной системой переписывания строк).
источник
S -> A a; S -> B b; A -> 0; B -> 0
. Если мы запрограммируем это путем изменения правил, нам нужно будет выбрать другие правила для обработки0
во время выполнения, чтобы вычислить «0a» или «0b»S
.(Просто некоторые тривиальные соображения. Может быть комментарий, но слишком длинный.)
Фактически, то, что вы описываете, выглядит как очень естественное представление о том, что такое язык (в человеческом понимании «языка», его цели) и как грамматика определяет язык.
Язык содержит (бесконечно много) правильных синтаксических форм, которые интерпретируются, чтобы дать семантические значения .
Если интерпретация вычислима, то синтаксические формы языка могут рассматриваться как программы, которые вычисляют семантические значения.
Если мы предположим, что язык реализован как конечное устройство, мы можем назвать это конечное представление языка «грамматикой». Согласно этому пониманию, грамматика заботится не только о синтаксисе, но и о семантике, то есть о том, как вычислить семантическое значение целого выражения из значений его частей (атомарные части и их значения хранятся в «лексиконе»). ,
У некоторых теорий естественного языка есть такая форма (форма, которая согласуется с вышеупомянутыми соображениями; это уже упоминалось в ответе @ gasche здесь): дедуктивная система, которая ищет вывод ввода (в сочетании с вычислением семантического значение или построение проверочного термина; см. соответствие Карри-Хорварда). Итак, если мы посмотрим на подобные системы и рассмотрим их грамматики, то ваш вопрос тривиален : эти системы точно разработаны для выполнения вычислений описанным вами способом.
(Фактически, настоящие компиляторы для языков программирования больше похожи на систему с синтаксисом и семантикой: они преобразуют синтаксическую форму программы в исполняемый файл, который является семантическим смыслом программы, а не просто в начальный символ грамматики.)
источник
Просто добавить:
Грамматический взгляд на логическое программирование Пьера Дерансара и Яна Малушинского.
источник
Как насчет чего-то вроде чисел Пеано:
он распознает любую строку (число) этой формы:
и он должен возвращать вложенную структуру с глубиной, равной числу.
Но это становится все сложнее, когда кто-то хочет реализовать просто скажем сложение:
Это имеет смысл в том смысле, что он распознает только хорошо сформированные целые, как это:
Но эта грамматика вводит расщепление в дереве разбора всякий раз, когда есть сумма, поэтому вместо того, чтобы иметь хорошее одноразветвленное дерево, которое напрямую отображается на число, мы имеем структуру выражения, все еще на расстоянии нескольких вычислений от эффективного значение. Так что никаких вычислений не делается, только распознавание. Беда может быть не в грамматике, а в парсере. Вместо этого можно использовать что-то другое, idk ... Еще один момент, который приходит на ум, - это адекватность грамматического формализма для выражения вычислений. Когда вы смотрите аксиому Пеано (в хаскеллоподобной записи):
Третье правило явно указывает на преобразование. Может ли кто-нибудь представить, что в контекстно-свободном грамматическом правиле есть смысл. И если да, то как?
источник