Skip to content

RyazMax/mlang

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

13 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MLANG

Cодержание

Установка

Для дальнейшего запуска репозиторий необходимо клонировать в папку GOPATH/src
Папку с GOPATH можно узнать с помощью

go env GOPATH

Использование

Для запуска интерактивного выполните:

go run main.go

Чтобы выполнить заготовленный файл с кодом укажите путь до нужного файла:

go run main.go program.mlang resultfile

Тогда в resultfile будут записаны результаты верхнеуровневых выражений.

go run main.go program.mlang

В этом случае будет выполнена программа, в stdout попадут ошибки и результаты вызова print

Для запуска тестов запустите tests.sh

Cами тесты располагаются в папках: lexer, parser, evaluator в файлах с суффиксами _test

Грамматика языка

На выходе из лексера получаем следующий набор токенов(полный список можно посмотреть в файле token.go), с которыми и работает парсер:

  • Identifier - имя идентификатора начинающееся с буквы или символа _ и не являющееся ключевым словом
  • Спец символ из (){};,+=-*/<>!= - знаки операторов
  • IntegerLiteral - целое неотрицательное 64 битное число
  • BooleanLiteral - true или false
  • Ключевые слова - { return, if, else}
$$Program -> Statement;Program|e Statement -> ReturnStatement|AssignStatement|ExpressionStatement|BlockStatement ReturnStatement -> return Expression AssignStatement -> Identifier = Expression BlockStatement -> {Program} ExpressionStatement -> Expression Expression -> Expression1 +- Expression | Expression1 Expression1 -> Expression2 */ Expression1 | Expression2 Expression2 -> PrefixExpression (ExpressionList) | PrefixExpression PrefixExpression -> (Expression)|-PrefixExpression|!PrefixExpression|CallExpression CallExpression -> ZeroOpExpression(ExpressionList) | ZeroOpExpression ZeroOpExpression -> IntegerLiteral|BooleanLiteral|Identifier|FuncExpression|IfExpression|Null IfExpression -> if (Expression) BlockStatement Alternative Alternative -> else BlockStatement|e FuncExpression -> fn (ArgList) BlockStatement ArgList -> Identifier ArgList' | e ArgList' -> ,Identifier ArgList'| e ExpressionList -> Expression ExpressionList' | e ExpressionList' -> ,Expression ExpressionList' | e$$

К процессу парсинга выражений

Видно что правила грамматики, относящиеся к выражениям(Expression) имеют похожую структуру:
ExpressionN-> Expression(N+1) InfixOperator ExpressionN | Expression(N+1).
Т.е правило с оператором меньшего приоритета сводится к аналогичному с большим. Для того, чтобы обеспечить расширяемость набора операторов будем спускаться на следующий уровень приоритета, если приоритет последнего связанного оператора строго меньше приоритета нового оператора. Использование строгого сравнения приоритетов также решает проблему правой асоциативности, т.к в таком случае левая часть выражения с одинаковыми приоритетами становится левым подвыражением следующего блока выражения. Понятнее написано в parser.go/parseExpression, там же находится полный список возможных операторов и их приоритетов(таблица precedence). Вызов функции может быть интерпретирован как инфиксный оператор ( c наивысшим приоритетом.

Основные правила языка

MLang поддерживает 3 типа данных с которыми может работать пользователь:

  • integer - целые 64битные числа
  • boolean - логический тип, в программе обозначается литералами true и false
  • function - функции
  • null - специальный тип null

Язык содержит 2 основные конструкции:

Условные выражения:

if (10 + 5) {
    5 + 1;
} else {
    6 + 2;
}

Результатом которых является последнее выполненное выражение вополненной ветки условия(6).

Функции:

func(x, y) {
    x + y;
}

или

func(x,y) {
    return x + y;
    x - y;
}

В обоих случаях результатом вызова функции от 2 аргументов будет сумма этих аргументов.

Примеры

В папке examples расположены примеры программ для их запуска необходимо выполнить следующую команду

go run main.go ./examples/<filename>

В данных примерах используются стандартные функции print - выводит значения переменных на экран и read - считывает целое число с клавиатуры, возвращает null иначе.

Пример программы находящей сумму всех вводимых чисел до первого нуля

f = func(acc) {
    a = read()
    if (a) {
        f(acc + a)
    } else {
        acc
    }
}

print(f(0))

Cтруктура проекта

Интерпретатор языка состоит из 7 основных пакетов:

  • token - Описание разрешенных токенов в языке
  • lexer - Производит преобразование исходного кода на mlang в последовательность токенов для последующей обработки парсером
  • ast - Описание абстрактного синтаксического дерева, задающего структуру выполнения программы
  • parser - Преобразует последовательность токенов полученных из модуля лексера в абстрактное синтаксическое дерево
  • evaluator - Производит разбор аст, выполняя описаннные в нем вычисления
  • object - Описание внутренних объектов и типов языка
  • repl - Собственно интерпретатор

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published