Привет, Хабр! Меня зовут Владислав, мне 13 лет, и я создал язык программирования VladX. В этой статье расскажу, как устроен его интерпретатор, почему я выбрал русский синтаксис и как можно попробовать язык в действии.
Идея: почему русский синтаксис?
Когда я начал изучать программирование, английские ключевые слова if, else, function казались магическими заклинаниями. Логик�� алгоритмов была понятна, но синтаксис создавал лишний барьер. Я подумал: а что если сделать язык, где ключевые слова будут на русском? Так появился VladX.
VladX — это интерпретируемый язык с динамической типизацией, который работает поверх Node.js. Его особенность — полностью русский синтаксис, разработанный специально для обучения.
Архитектура: как устроен интерпретатор
VladX построен по классической схеме:
Исходный код → Лексер → Токены → Парсер → AST → Интерпретатор → Результат
Лексер: разбираем русские ключевые слова
Лексер преобразует исходный код в токены. Вот упрощённый пример обработки:
// Пример из src/lexer/tokenizer.js const keywords = { 'печать': 'PRINT', 'если': 'IF', 'иначе': 'ELSE', 'цикл': 'FOR', 'пока': 'WHILE', 'функция': 'FUNCTION', 'вернуть': 'RETURN', 'класс': 'CLASS', 'новый': 'NEW', 'пусть': 'LET' }; function tokenize(code) { const tokens = []; const lines = code.split('\n'); for (let i = 0; i < lines.length; i++) { const line = lines[i]; const words = line.split(/(\s+|\(|\)|\{|\}|\,|\;|\=|\+|\-|\*|\/)/) .filter(w => w.trim().length > 0); for (const word of words) { if (keywords[word]) { tokens.push({ type: keywords[word], value: word, line: i + 1 }); } else if (word.match(/^[0-9]+$/)) { tokens.push({ type: 'NUMBER', value: parseInt(word) }); } else if (word.match(/^"[^"]*"$/)) { tokens.push({ type: 'STRING', value: word.slice(1, -1) }); } else if (word.match(/^[а-яА-Я_][а-яА-Я0-9_]*$/)) { tokens.push({ type: 'IDENTIFIER', value: word }); } } } return tokens; }
Парсер: строим абстрактное синтаксическое дерево
Парсер преобразует последовательность токенов в AST. Вот как выглядит обработка условия:
// Пример из src/parser/parser.js class Parser { parseIf() { this.consume('IF'); // Потребляем токен 'если' const condition = this.parseExpression(); this.consume('LBRACE'); // { const thenBranch = this.parseBlock(); let elseBranch = null; if (this.match('ELSE')) { // Проверяем 'иначе' this.consume('LBRACE'); elseBranch = this.parseBlock(); } return { type: 'IfStatement', condition: condition, thenBranch: thenBranch, elseBranch: elseBranch }; } }
Интерпретатор: выполняем код
Интерпретатор обходит AST и выполняет инструкции:
// Пример из src/interpreter/interpreter.js class Interpreter { visitIf(node) { const condition = this.visit(node.condition); if (this.isTruthy(condition)) { return this.visit(node.thenBranch); } else if (node.elseBranch) { return this.visit(node.elseBranch); } return null; } visitPrint(node) { const value = this.visit(node.expression); console.log(value); return value; } visitFunction(node) { // Создаём объект функции const fn = (...args) => { const environment = new Environment(this.global); // Связываем параметры с аргументами for (let i = 0; i < node.params.length; i++) { environment.define(node.params[i], args[i]); } const previous = this.environment; this.environment = environment; try { this.visit(node.body); } finally { this.environment = previous; } }; return fn; } }
Примеры кода на VladX
Базовые конструкции
# Переменные и вывод пусть имя = "Мир" печать("Привет, " + имя + "!") # Условия пусть возраст = 15 если возраст >= 18 { печать("Ты взрослый!") } иначе { печать("Тебе " + возраст + " лет") } # Циклы цикл (пусть i = 1; i <= 5; i = i + 1) { печать("Шаг " + i) } # Функции функция приветствовать(имя) { вернуть "Привет, " + имя + "!" } печать(приветствовать("Вася"))
Объектно-ориентированное программирование
класс Животное { конструктор(имя) { это.имя = имя } говорить() { печать(это.имя + " издаёт звук") } } класс Собака расширяет Животное { говорить() { печать(это.имя + " говорит: Гав!") } лаять(раз) { цикл (пусть i = 0; i < раз; i = i + 1) { печать("Гав!") } } } пусть мой_пёс = новый Собака("Шарик") мой_пёс.говорить() # Шарик говорит: Гав! мой_пёс.лаять(3) # Три раза "Гав!"
Работа с массивами
пусть числа = [1, 2, 3, 4, 5] пусть сумма = 0 цикл (пусть i = 0; i < числа.длина; i = i + 1) { сумма = сумма + числа[i] } печать("Сумма: " + сумма) # Сумма: 15
Установка и использование
VladX можно установить несколькими способами:
Способ 1: через npm (рекомендуется)
npm install -g vladx-main
Способ 2: из исходников
git clone https://github.com/murfivladi/vladx-main.git cd vladx-main/vladx npm install npm link
Способ 3: через установочный скрипт
curl -sL https://raw.githubusercontent.com/murfivladi/vladx/main/install.sh | bash
Проверка установки
vlad --version
Запуск скрипта
vlad программа.vlad
REPL-режим
vlad > печать("Привет!") Привет! > пусть x = 10 > печать(x * 2) 20
Инфраструктура проекта
Структура репозитория
vladx-main/ ├── vladx/ # Основной пакет │ ├── src/ # Исходный код │ │ ├── lexer/ # Лексер │ │ ├── parser/ # Парсер │ │ ├── interpreter/ # Интерпретатор │ │ ├── runtime/ # Среда выполнения │ │ └── engine/ # Основной движок │ ├── bin/ # Исполняемые файлы │ │ ├── vlad.js # CLI интерпретатор │ │ └── vladpm.js # Менеджер пакетов │ ├── package.json # Конфигурация npm │ └── install.sh # Скрипт установки ├── examples/ # Примеры программ └── README.md # Документация
Менеджер пакетов VladPM
VladX включает собственный менеджер пакетов:
# Инициализировать проект vladpm init # Установить пакет vladpm install математика # Список установленных пакетов vladpm list
Трудности и решения
1. Обработка русского текста
Первоначально были проблемы с кодировкой, но переход на UTF-8 во всех компонентах решил вопрос.
2. Динамическая типизация
Реализация динамической типизации потребовала создания системы обёрток для значений, которая отслеживает типы во время выполнения.
3. Рекурсивный парсинг
Обработка вложенных конструкций (циклов в условиях, функций в функциях) требовала осторожного управления состоянием парсера.
4. Система модулей
Импорт/экспорт между файлами реализован через общую таблицу символов, что позволяет модулям взаимодействовать.
Почему Node.js?
Кроссплатформенность — работает на Windows, Linux, macOS
Богатая экосистема — можно использовать npm-пакеты
Простота распространения — один файл
.jsдля интерпретатораАсинхронность — в будущем можно добавить async/await
Планы по развитию
Ближайшие цели:
Онлайн-песочница — веб-редактор для быстрого тестирования
Дополнительные библиотеки — графика, игры, математика
Интеграция с IDE — плагины для VSCode
Образовательные материалы — учебник и видеоуроки
Долгосрочные планы:
JIT-компиляция для повышения производительности
Статическая типизация как опциональная возможность
Собственная виртуальная машина
Поддержка многопоточности
Для кого этот язык?
Школьники — первые шаги в программировании без языкового барьера
Учителя информатики — инструмент для обучения алгоритмам
Русскоязычные новички — возможность сосредоточиться на логике, а не на синтаксисе
Энтузиасты — интересный проект для изучения компиляторостроения
Попробовать VladX
Онлайн-демо: [скоро будет]
GitHub: https://github.com/murfivladi/vladx-main
npm: https://www.npmjs.com/package/vladx-main
Заключение
Создание VladX стало для меня увлекательным путешествием в мир компиляторостроения. Я узнал, как работают лексеры, парсеры, интерпретаторы, системы типов и среды выполнения.
Язык ещё развивается, но уже сейчас на нём можно писать полезные программы. Буду рад, если VladX поможет кому-то сделать первые шаги в программировании или вдохновит на создание собственного языка.
Вопросы и предложения приветствуются в комментариях! Особенно интересно услышать:
Какие функции добавить в первую очередь?
Где вы видите применение VladX?
Хотели бы вы использовать его для обучения?
P.S. Если вы учитель информатики и хотите попробовать VladX на уроках — напишите, подготовлю специальные материалы.
Спасибо за внимание! Код — на русском, логика — универсальна.
