Сообщение [Nitra] Пример простого языка вычисляющего выражения от 02.12.2015 7:31
Изменено 02.12.2015 9:28 VladD2
В качестве примера опишу создание простого (но тем не менее не тривиального) языка.
Для начала пример кода на этом языке:
Данный язык состоит из объявлений переменных которые видны глобально. "Глобально" значит что из выражений можно обращаться как к переменным объявленным выше текущей, так и ниже (а возможно и в другом файле).
Переменные можно инициализировать произвольным выражением. Причем выражения вычисляются не в порядке их написания, а в порядке зависимостей. Зацикленным выражения не вычисляются.
Особенность данного примере в том, что он не порождает ничего. Он только демонстрирует расчеты на зависимых свойствах.
Для начала опишем синтаксис:
Скормив этот файл nitra и получив dll мы уже получим возможность забирать код на нашем языке, подсветку и претипринт.
Чтобы наш можно было использовать из IDE или из тестовой утилиты нужно написать еще один файл Sample-Language.nitra с описанием языка:
Здесь SampleSyntax — это имя описанного выше синтаксического модуля, а TopRule имя стартового правила. Еще в этом файле может быть множество информации: расширение файла, информация об авторе, информация о стилях подсветки и т.п. Как это выглядит для более серьезного языка можно посмотреть здесь. Описание языка для самой Nitra.
Теперь нам нужно писать AST нашего языка в которых будут располагаться вычисления необходимые нам. AST находится в файле Sample-Ast.nitra:
AST и расчеты на нем готовы, но AST не появится сам собой. Нам нужно проецировать дерево разбора на него, чтобы Nitra автоматически строила AST для кода на нашем языке.
Отображение (оно же проекция, оно же маппинг) находится в файле Sample-Mapping.nitra.
Последний штрих... Для того чтобы написанные нами вычисления работали нам нужно написать небольшой обвязочный код, который запустит их и проинициализирует ContainingTable у корневых элементов AST-а (т.е. у Top). Пока что в Nitra это делается так. Нужно создать паршал-класс корневого элемент AST и реализовать в нем интерфейс IProjectSupport. Вот как это сделано в данном примере (файл Main.n):
Заключение
Данный пример аналогичен свертке констант (constant folding) применяемому в большинстве языков программирования. Он изначально игрушечный и не предполагает компиляции в машинный код и т.п. Его цель показать как производятся расчеты на зависимых свойствах.
Интересно то, что данные вычисления не могут зациклиться. Если в выражениях двух или более переменных создать циклическую зависимость, то все переменные входящие в эту зависимость не будут вычислены. Это особенность вычислительной модели зависимых свойств. Если надо ее можно обойти. Но это уже отдельная тема.
Посмотреть на результат можно поместив полученную dll в нашу тестовую утилиту (Nitra.Visualizer.exe). Так же пример будет работать и в IDE, но там будет доступна только подсветка и навигация, а результат расчетов увидеть не удастся.
Для начала пример кода на этом языке:
var x = y + 2 * z;
var z = y + 3;
var y = 1;
Данный язык состоит из объявлений переменных которые видны глобально. "Глобально" значит что из выражений можно обращаться как к переменным объявленным выше текущей, так и ниже (а возможно и в другом файле).
Переменные можно инициализировать произвольным выражением. Причем выражения вычисляются не в порядке их написания, а в порядке зависимостей. Зацикленным выражения не вычисляются.
Особенность данного примере в том, что он не порождает ничего. Он только демонстрирует расчеты на зависимых свойствах.
Для начала опишем синтаксис:
Скрытый текст | |
| |
Скормив этот файл nitra и получив dll мы уже получим возможность забирать код на нашем языке, подсветку и претипринт.
Чтобы наш можно было использовать из IDE или из тестовой утилиты нужно написать еще один файл Sample-Language.nitra с описанием языка:
language Sample
{
syntax module SampleSyntax start rule TopRule;
}
Здесь SampleSyntax — это имя описанного выше синтаксического модуля, а TopRule имя стартового правила. Еще в этом файле может быть множество информации: расширение файла, информация об авторе, информация о стилях подсветки и т.п. Как это выглядит для более серьезного языка можно посмотреть здесь. Описание языка для самой Nitra.
Теперь нам нужно писать AST нашего языка в которых будут располагаться вычисления необходимые нам. AST находится в файле Sample-Ast.nitra:
Скрытый текст | |
| |
AST и расчеты на нем готовы, но AST не появится сам собой. Нам нужно проецировать дерево разбора на него, чтобы Nitra автоматически строила AST для кода на нашем языке.
Отображение (оно же проекция, оно же маппинг) находится в файле Sample-Mapping.nitra.
Скрытый текст | |
| |
Последний штрих... Для того чтобы написанные нами вычисления работали нам нужно написать небольшой обвязочный код, который запустит их и проинициализирует ContainingTable у корневых элементов AST-а (т.е. у Top). Пока что в Nitra это делается так. Нужно создать паршал-класс корневого элемент AST и реализовать в нем интерфейс IProjectSupport. Вот как это сделано в данном примере (файл Main.n):
Скрытый текст | |
| |
Заключение
Данный пример аналогичен свертке констант (constant folding) применяемому в большинстве языков программирования. Он изначально игрушечный и не предполагает компиляции в машинный код и т.п. Его цель показать как производятся расчеты на зависимых свойствах.
Интересно то, что данные вычисления не могут зациклиться. Если в выражениях двух или более переменных создать циклическую зависимость, то все переменные входящие в эту зависимость не будут вычислены. Это особенность вычислительной модели зависимых свойств. Если надо ее можно обойти. Но это уже отдельная тема.
Посмотреть на результат можно поместив полученную dll в нашу тестовую утилиту (Nitra.Visualizer.exe). Так же пример будет работать и в IDE, но там будет доступна только подсветка и навигация, а результат расчетов увидеть не удастся.
В качестве примера опишу создание простого (но тем не менее не тривиального) языка.
Для начала пример кода на этом языке:
Данный язык состоит из объявлений переменных которые видны глобально. "Глобально" значит что из выражений можно обращаться как к переменным объявленным выше текущей, так и ниже (а возможно и в другом файле).
Переменные можно инициализировать произвольным выражением. Причем выражения вычисляются не в порядке их написания, а в порядке зависимостей. Зацикленным выражения не вычисляются.
Особенность данного примере в том, что он не порождает ничего. Он только демонстрирует расчеты на зависимых свойствах.
Для начала опишем синтаксис:
Скормив этот файл nitra и получив dll мы уже получим возможность забирать код на нашем языке, подсветку и претипринт.
Чтобы наш можно было использовать из IDE или из тестовой утилиты нужно написать еще один файл Sample-Language.nitra с описанием языка:
Здесь SampleSyntax — это имя описанного выше синтаксического модуля, а TopRule имя стартового правила. Еще в этом файле может быть множество информации: расширение файла, информация об авторе, информация о стилях подсветки и т.п. Как это выглядит для более серьезного языка можно посмотреть здесь. Описание языка для самой Nitra.
Теперь нам нужно писать AST нашего языка в которых будут располагаться вычисления необходимые нам. AST находится в файле Sample-Ast.nitra:
AST и расчеты на нем готовы, но AST не появится сам собой. Нам нужно проецировать дерево разбора на него, чтобы Nitra автоматически строила AST для кода на нашем языке.
Отображение (оно же проекция, оно же маппинг) находится в файле Sample-Mapping.nitra.
Последний штрих... Для того чтобы написанные нами вычисления работали нам нужно написать небольшой обвязочный код, который запустит их и проинициализирует ContainingTable у корневых элементов AST-а (т.е. у Top). Пока что в Nitra это делается так. Нужно создать паршал-класс корневого элемент AST и реализовать в нем интерфейс IProjectSupport. Вот как это сделано в данном примере (файл Main.n):
Заключение
Данный пример аналогичен свертке констант (constant folding) применяемому в большинстве языков программирования. Он изначально игрушечный и не предполагает компиляции в машинный код и т.п. Его цель показать как производятся расчеты на зависимых свойствах.
Интересно то, что данные вычисления не могут зациклиться. Если в выражениях двух или более переменных создать циклическую зависимость, то все переменные входящие в эту зависимость не будут вычислены. Это особенность вычислительной модели зависимых свойств. Если надо ее можно обойти. Но это уже отдельная тема.
Посмотреть на результат можно поместив полученную dll в нашу тестовую утилиту (Nitra.Visualizer.exe). Так же пример будет работать и в IDE, но там будет доступна только подсветка и навигация, а результат расчетов увидеть не удастся.
Для начала пример кода на этом языке:
var x = y + 2 * z;
var z = y + 3;
var y = 1;
Данный язык состоит из объявлений переменных которые видны глобально. "Глобально" значит что из выражений можно обращаться как к переменным объявленным выше текущей, так и ниже (а возможно и в другом файле).
Переменные можно инициализировать произвольным выражением. Причем выражения вычисляются не в порядке их написания, а в порядке зависимостей. Зацикленным выражения не вычисляются.
Особенность данного примере в том, что он не порождает ничего. Он только демонстрирует расчеты на зависимых свойствах.
Для начала опишем синтаксис:
Скрытый текст | |
| |
Скормив этот файл nitra и получив dll мы уже получим возможность забирать код на нашем языке, подсветку и претипринт.
Чтобы наш можно было использовать из IDE или из тестовой утилиты нужно написать еще один файл Sample-Language.nitra с описанием языка:
language Sample
{
syntax module SampleSyntax start rule TopRule;
}
Здесь SampleSyntax — это имя описанного выше синтаксического модуля, а TopRule имя стартового правила. Еще в этом файле может быть множество информации: расширение файла, информация об авторе, информация о стилях подсветки и т.п. Как это выглядит для более серьезного языка можно посмотреть здесь. Описание языка для самой Nitra.
Теперь нам нужно писать AST нашего языка в которых будут располагаться вычисления необходимые нам. AST находится в файле Sample-Ast.nitra:
Скрытый текст | |
| |
AST и расчеты на нем готовы, но AST не появится сам собой. Нам нужно проецировать дерево разбора на него, чтобы Nitra автоматически строила AST для кода на нашем языке.
Отображение (оно же проекция, оно же маппинг) находится в файле Sample-Mapping.nitra.
Скрытый текст | |
| |
Последний штрих... Для того чтобы написанные нами вычисления работали нам нужно написать небольшой обвязочный код, который запустит их и проинициализирует ContainingTable у корневых элементов AST-а (т.е. у Top). Пока что в Nitra это делается так. Нужно создать паршал-класс корневого элемент AST и реализовать в нем интерфейс IProjectSupport. Вот как это сделано в данном примере (файл Main.n):
Скрытый текст | |
| |
Заключение
Данный пример аналогичен свертке констант (constant folding) применяемому в большинстве языков программирования. Он изначально игрушечный и не предполагает компиляции в машинный код и т.п. Его цель показать как производятся расчеты на зависимых свойствах.
Интересно то, что данные вычисления не могут зациклиться. Если в выражениях двух или более переменных создать циклическую зависимость, то все переменные входящие в эту зависимость не будут вычислены. Это особенность вычислительной модели зависимых свойств. Если надо ее можно обойти. Но это уже отдельная тема.
Посмотреть на результат можно поместив полученную dll в нашу тестовую утилиту (Nitra.Visualizer.exe). Так же пример будет работать и в IDE, но там будет доступна только подсветка и навигация, а результат расчетов увидеть не удастся.