Код состоит из различных символов. Например, следующий код:
static void Main (string [] args) {
Console.WriteLine ("Hello World!");
}
Сначала идёт ключевое слово static
, состоящее из шести символов, которое обозначает статичность. Затем идёт ключевое слово void
, состоящее из четырёх символов, которое представляет тип возвращаемого значения функции. Далее идут необязательные символы, такие как перенос строки и отступы табуляции.
Прежде всего, мы должны чётко понимать, что код на языке программирования — это строка, состоящая из разных символов.
Рассмотрим предыдущий код:
static void Main (string [] args) {
Console.WriteLine("Hello World!");
Console.WriteLine("Hello World!");
Console.WriteLine("Hello World!");
}
Это простой код, не так ли? Теперь давайте проанализируем его. Отличие этого кода от предыдущего заключается в том, что фраза «Hello World!» выводится три раза. На основе этого мы можем смело предположить, что в функции может быть от нуля до N строк кода (это очевидно).
Теперь определим структуру функции. Сначала идёт заголовок функции, который мы называем func_begin
. Затем идут операторы, которые мы называем stmt
. Наконец, идёт конец функции, который мы называем func_end
.
Мы можем описать эту структуру с помощью специальной грамматики:
func_stmt ::= func_begin stmt* func_end
Проще говоря, структура функции (func_stmt) состоит из трёх частей: заголовка функции (func_begin
), тела функции (состоит из операторов stmt
, звёздочка означает повторение от нуля до бесконечности раз) и конца функции (func_end
).
Эта грамматика позволяет нам сопоставить обе части кода, независимо от того, сколько выражений содержится в функции Main
.
Вкратце, терминальные символы — это символы или строки в коде. Нетерминальные символы — это определения структур.
Например, мы хотим разобрать следующее выражение:
1+2*3-4/5
Оно состоит из девяти частей, каждая из которых является символом. Мы можем представить его как:
expr ::= num op num op num op num op num
Упростим его:
expr ::= num (op num)+
Здесь op
и num
объединяются четыре раза, поэтому мы объединяем их и требуем, чтобы они повторялись хотя бы один раз.
Затем мы определяем num
и op
:
num ::= [0-9]+
op ::= '+' | '-' | '*' | '/'
Как видите, при определении грамматики языка мы используем символ ::=
для соединения двух частей. Левая часть определяет нетерминальный символ, а правая часть может быть терминальным символом или комбинацией нетерминальных символов.
Мы можем рассматривать строку кода как корень дерева, где нетерминальные символы являются узлами ствола, а терминальные символы — листьями. Определение грамматики — это определение того, какие типы дочерних узлов могут иметь узлы ствола. Когда мы определяем грамматику, мы берём строку кода и сопоставляем её с корнем дерева, пока не достигнем всех листьев. В результате получается дерево, называемое абстрактным синтаксическим деревом (AST).
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )