Как создать язык программирования

в 12:47, , рубрики: python, Программирование, язык программирования

Как все началось

Дело было утром. Я захотел создать что-то на питоне, сложное, но посильное для меня. И тут я понял, что хочу создать язык программирования…

Как я создавал его...

Lexer

Куда же без него! Он требуется для «разделения» всего на токены. Если объяснить зачем он тогда представим: у нас есть код (CoffeScript).

a = true

if a
    console.log('Hello, lexer')

И лексер превращает этот код в это(сокращенная запись):

[IDENTIFIER:"a"]
[ASSIGN:"="]
[BOOLEAN:"true"]
[NEWLINE:"n"]
[NEWLINE:"n"]
[KEYWORD:"if"]
[IDENTIFIER:"a"]
[NEWLINE:"n"]
[INDENT:"    "]
[IDENTIFIER:"console"]
[DOT:"."]
[IDENTIFIER:"log"]
[ROUND_BRAKET_START:"("]
[STRING:"'Hello, lexer'"]
[ROUND_BRAKET_END:")"]
[NEWLINE:"n"]
[OUTDENT:""]
[EOF:"EOF"]

Но в моем случае я делаю все проще, т.к. это будет излишком трудности, а также язык программирования у меня простой. У меня все просто:

def lexer(code):
    code = code.split(";") # Токенезация
    code = code[0:-1] # Т.к. есть баг, что последний элемент пустой
    return parse(code, number=0) # "Отсылаем" это все парсеру

И код (моего «ЯП»):

printf Test; exit;

Он превратит в читабельное (!):

["printf Test", "exit"]

Парсер

Самое сложное только начинается… Сделать токенезацию легко, а обработать это сложно. В теории мы должны проверять команду, потом ее аргументы. Кажется это легко, но нет! По началу все было примерно так:

number = 0
if code[number].startswith("printf"):
    print(code[number][7:-0]
    number += 1

Но ничего не работало, точнее не печатало текст, потом я попробовал так:

number = 0
if code[number].startswith("printf"):
    print(code[number][7:-1]
    number += 1

Но приходилось писать в конце любой символ. Потом я понял, что, если узнать длину строки и обрезать с 7-го символа по последний все должно работать.

number = 0
if code[number].startswith("printf"):
    l = len(code[number])
    print(code[number][7:l]
    number += 1

Вроде работает, но если выводить текст боле два и более раз то в начале идет лишний пробел… Но даже с помощью переменной проверяющей печатался ли раньше текст, ничего не работало правильно. После нескольких десятков минут и кружки кофе я придумал, что и как.

if code[number][7] == " ":
    l = len(code[number])
    print(code[number][8:l]
else:
    l = len(code[number])
    print(code[number][7:l]

Но все равно ничего не работало :| и с таким лицом я пытался что-то сделать… Целый час. И спустя около полутора часа я сделал это!


l = len(code[number]) # Получаем длину
if code[number][6] == " ": # Если 6-ой символ это пробел
    print(code[number][7:l]) # Печатаем все с 7-го символа
else: # Иначе
    print(code[number][8:l]) #

Потом полчаса шаманства и… Все работает на ура!

P.S.

  1. Не весь код с комментариями, т.к. он ориентирован на продвинутых программистов.
  2. Код в спойлере, т.к. он длинный и в «главный» текст статьи не входит.
  3. Прошу не ругаться насчет кода, мне 11 лет.
  4. Это моя первая статья на Хабре и вообще.
  5. Код в начале был взят из одной статьи на Хабре.

Код

def parse(code, number=0):
    try:
        # Print function #
        if code[number].startswith("printf") or code[number].startswith(" printf"):
            # Get len
            l = len(code[number])
            # If text starts with space
            if code[number][6] == " ":
                print(code[number][7:l])
            # Else
            else:
                print(code[number][8:l])
            number += 1
            parse(code, number)

        # Input function #
        if code[number].startswith("input") or code[number].startswith(" input"):
            # Get len
            l = len(code[number])
            # If text starts with space
            if code[number][6] == " ":
                input(code[number][7:l])
            # Else
            else:
                input(code[number][8:l])
            number += 1
            parse(code, number)

        # Exit function #
        elif code[number].startswith("exit") or code[number].startswith(" exit"):
            input("nPress "Enter" to exit.")
            exit()
        else:
            cl = len(code[number])
            command = code[number]
            command = command[1:cl]
            print("n", "=" * 10)
            print("Error!")
            print("Undefined command " + '"' + command + '"' + ".")
            print("=" * 10)
            input("Press "Enter" to exit...")
            exit()
    except IndexError:
        input("n[!] Press "Enter" to exit.")
        exit()


def lexer(code):
    code = code.split(";")
    code = code[0:-1]
    return parse(code, number=0)


code = input()
lexer(code)

Автор: isisTance

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js