В двух словах
Языки программирования состоят из синтаксиса, который представляет программу в виде строк символов, и семантики, которая является предполагаемым значением программы.
Формальные языки - это синтаксис без значения. Он предназначен для изучения структуры наборов строк, определенных формально, обычно без придания значения этим строкам.
Регулярные выражения и другие формализмы (такие как контекстно-свободные грамматики) используются для определения формальных языков, используемых в качестве синтаксического компонента программирования и естественных языков, то есть для представления предложений в структурированном виде. Другие механизмы используются для связи этой структуры с семантикой языков программирования.
Многое здесь значительно упрощено, особенно в отношении естественного языка.
С гораздо большим количеством деталей
Чтобы ответить на ваш вопрос, мы должны начать с самого начала. Язык в обычном смысле слова является неофициальным средством передачи информации или идей. На языке обычно различают синтаксис и семантику. Семантика - это то, о чем вы хотите поговорить / написать. информация, которую вы хотите передать. Синтаксис - это средство, которое вы используете для его передачи, то есть обычное представление, которым можно обмениваться между людьми, а теперь и между людьми и устройствами или между устройствами (компьютерами).
Как правило, вы будете использовать слово, dog
чтобы передать идею собаки. Слово dog
состоит из трех букв или эквивалентного звука и предназначено для обозначения какого-либо животного. Основная идея заключается в том, что общение осуществляется через представление того, что должно быть передано. Структуры представления обычно называют синтаксисом, в то время как то, что представлено, называется семантикой. Это более или менее подходит как для естественного языка, так и для языков программирования.
Слова - это синтаксические объекты, представляющие более или менее элементарные семантические понятия. Но эти элементарные понятия должны быть объединены различными способами, чтобы придать более сложный смысл. Мы пишем,
the dog
чтобы передать, что мы имеем в виду конкретную собаку, и the dog bites the cat
передать более сложную идею. Но то, как слова организованы, должно быть зафиксировано правилами, чтобы мы могли определить, какая из собак и кошек на самом деле кусает другую.
Таким образом, у нас есть такие правила sentence -> subject verb complement
, которые должны соответствовать предложениям и сообщать нам, как сформулированы идеи, связанные с каждой частью. Эти правила являются синтаксическими правилами, так как они говорят нам, как должно быть организовано представление нашего сообщения. Сам subject
может быть определен правилом subject -> article noun
и так далее.
2x+1=23x123
equation -> expression "=" expression
expression -> expression "+" expression
expression -> number
Структура языков программирования одинакова. Языки программирования семантически специализируются на выражении вычислений, которые необходимо выполнить, а не на выражении проблем, которые необходимо решить, доказательстве теорем или дружеских отношений между животными. Но это главное отличие.
Представления, используемые в синтаксисе, обычно представляют собой строки символов или звуков для разговорных языков. Семантика обычно принадлежит абстрактной области, или, возможно, реальности, но все еще абстрагируется в наших мыслительных процессах, или поведенческой области устройств. Коммуникация влечет за собой кодирование информации / идеи в синтаксис, который передается и декодируется получателем. Затем результат интерпретируется получателем любым способом.
То, что мы видим в языке, это в основном синтаксис и его структура. Приведенный выше пример является лишь одним из наиболее распространенных способов определения синтаксических строк и их структурной организации. Есть и другие. Для данного языка некоторым строкам можно присвоить структуру, и говорят, что они принадлежат этому языку, а другие - нет.
То же самое относится и к словам. Некоторые последовательности букв (или звука) являются допустимыми словами, а другие - нет.
Формальные языки - это просто синтаксис без семантики. Они определяют с помощью набора правил, какие последовательности могут быть построены, используя основные элементы алфавита. Какие правила могут быть очень переменными, иногда сложными. Но формальные языки используются для многих математических целей помимо лингвистического общения, будь то для естественных или для языков программирования. Набор правил, которые определяют строки в языке, называется грамматикой. Но есть много других способов определения языков.
На практике язык структурирован на двух уровнях. Лексический уровень определяет слова, построенные из алфавита символов. Синтаксический уровень определяет предложения или программы, составленные из алфавита слов (или, точнее, из семейств слов, чтобы он оставался конечным алфавитом). Это обязательно несколько упрощено.
Структура слов довольно проста в большинстве языков (программирования или естественных), так что они обычно определяются с помощью того, что обычно считается самым простым видом формального языка: обычными языками. Они могут быть определены с помощью регулярных выражений (regexp) и довольно легко идентифицируются с помощью запрограммированных устройств, называемых конечными автоматами. В случаях языков программирования примерами слова являются идентификатор, целое число, строка, действительное число, зарезервированное слово, такое как if
или repeat
, символ пунктуации или открытая скобка. Примерами семейств слов являются идентификатор, строка, целое число.
Синтаксический уровень обычно определяется немного более сложным типом формального языка: языками без контекста, использующими слова в качестве алфавита. Правила, которые мы видели выше, являются контекстно-свободными правилами для естественного языка. В случае языков программирования правила могут быть:
statement -> assignment
statement -> loop
loop -> "while" expression "do" statement
assignment -> "identifier" "=" expression
expression -> "identifier"
expression -> "integer"
expression -> expression "operator" expression
С такими правилами вы можете написать:
while aaa /= bbb do aaa = aaa + bbb / 6
что является заявлением.
И способ его создания может быть представлен древовидной структурой, называемой деревом разбора или синтаксическим деревом (здесь не полный):
statement
|
_______________ loop _______________
/ / \ \
"while" expression "do" statement
__________|_________ |
/ | \ assignment
expression "operator" expression _______|_______
| | | / | \
"identifier" "/=" "identifier" "identifier" "=" expression
| | | |
aaa bbb aaa ... ...
Имена, появляющиеся слева от правила, называются нетерминалами, в то время как слова называются также терминалами, поскольку они находятся в алфавите для языка (выше лексического уровня). Нетерминальные представляют различные синтаксические структуры, которые могут быть использованы для создания программы.
Такие правила называются свободными от контекста, потому что нетерминал может быть произвольно заменен с использованием любого из соответствующих правил, независимо от контекста, в котором он появляется. Набор правил, определяющих язык, называется грамматикой без контекста.
На самом деле существуют ограничения на это, когда идентификаторы должны быть впервые объявлены или когда выражение должно удовлетворять ограничениям типа. Но такое ограничение можно считать семантическим, а не синтаксическим. На самом деле некоторые профессионалы помещают их в то, что они называют
статической семантикой .
Для любого предложения, любой программы значение этого предложения извлекается путем анализа структуры, заданной деревом разбора для этого предложения. Следовательно, очень важно разработать алгоритмы, называемые синтаксическими анализаторами, которые могут восстанавливать древовидную структуру, соответствующую программе, при наличии данной программы.
Парсеру предшествует лексический анализатор, который распознает слова и определяет семью, к которой они принадлежат. Затем последовательность слов или лексических элементов передается парсеру, который извлекает базовую древовидную структуру. Из этой структуры компилятор может затем определить, как генерировать код, который его семантическая часть обрабатывает программой на стороне компилятора.
Парсер компилятора может на самом деле построить структуру данных, соответствующую дереву разбора, и передать ее на более поздние этапы процесса компиляции, но это не обязательно. Запуск алгоритма синтаксического анализа сводится к разработке вычислительной стратегии для изучения синтаксического дерева, которое неявно присутствует в тексте программы. Это дерево синтаксиса / синтаксического анализа может или не может быть объяснено в процессе, в зависимости от стратегии компиляции (количество этапов). Что необходимо, так это то, что в конечном счете, по крайней мере, одно восходящее исследование дерева синтаксического анализа, явное или неявное, присутствует в структуре вычислений.
Интуитивно это объясняется тем, что стандартный формальный способ определения семантики, связанной с синтаксической древовидной структурой, заключается в том, что называется гомоморфизмом. Не бойся большого слова. Идея состоит в том, чтобы просто рассмотреть значение целого, построенного из значения частей, на основе оператора, который их связывает.
Например, предложение the dog bites the cat
может быть проанализировано с помощью правила sentence -> subject verb complement
. Зная значение этих 3 поддеревьев subject
, verb
и complement
правило, которое их составляет, говорит нам, что субъект выполняет действие и что укушен кот.
Это только интуитивное объяснение, но оно может быть формализовано. Семантика построена вверх от составляющих. Но это скрывает много сложности.
Внутренняя работа компилятора может быть разбита на несколько этапов. Фактический компилятор может работать поэтапно, используя промежуточные представления. Это может также объединить некоторые этапы. Это зависит от используемой технологии и сложности компиляции языка под рукой.