Developing a programming language (interpreter) in roblox

Recently, I completed a course on programming languages where I learned how programming languages are designed and how to implement them (specifically in this class, I built and implemented a subset of javascript). Closer to the end of the course I was thinking about potentially using those skills to build a simple language in Roblox, implementing some really basic things (basic variables, lists, loops, math, prints, if/elses) and potentially building a game to teach some of the basics of programming to newer users.

The game itself would proabably be a set of simple lessons, that teach users how to use each of the implemented functionalities and gives them a window with a console output and an area to type their code. I think this would be something nice to create for those who dont have any expereince in programming, as sometimes they can be intimidated by all the features packed into Roblox Studio and have no idea where to start (at least, that’s how it was for me when I was at that stage) and give them somewhere to learn the fundamentals of programming on roblox.

This was just an idea I had and I’m not sure if I’ll ever go through with it, so I wanted to put it out there for anyone who would be interested in developing it or sharing some ideas.

Edit: There also could be a lot of challenges making this comply with Roblox TOS and rules (e.g. text filtering on variable names and print statements)


Some more specific ideas on how I was going to implement this:
  • Stack/heap would be implemented as dicts [var name → value], as using a dict to represent these would make it easier to allow for dynamic typing (like Lua).
  • Only strings, numbers, and booleans would be implemented
  • Potentially implement functions? This was pretty hard to do in my javascript implementation but that was also because I had to use a language that was really difficult in the first place (OCaml sucks)
  • Lists/loops weren’t things we covered the implementation of in my class but I think if you wanted to build an educational tool these would be important to implement.

2 Likes

Actually really interested in this idea. I have tried multiple times but that was a while ago. I would like to ask if you would use a plugin or use a roblox studio mod to insert a new language into studio. The main issue with this would actually be running the scripts. How would you go about that?

I wouldn’t worry about this because of the filter function provided. And as long as the players don’t see the messages, you should be good.

2 Likes

While I think it’s a great idea as a personal project, on ROBLOX I don’t think it will have much practical use outside of it being a personal project. You mentioned that it can be used to teach others how to program but I’m not sure how many people want to learn programming through an unknown language you invented.

But that aside, it sounds like a great thing you can do for yourself I just don’t think you should expect it to have much use outside of being a learning experience for you.

2 Likes

Wouldn’t recommend Luau for making a language but you can still use it.

Then again, anything you’d like to do.


Would be extremely simple to make a lexer with a for loop and string.gmatch (could possibly use string patterns) instead of constantly subbing out each character.

The rest would also be simple, not sure if you did a course on bytecode or tree walk but :man_shrugging:

Bytecode might be more difficult in Luau. Why?

Bytecode might be more complex due to:

  • Having linear execution
  • Being stack-based
  • Registers
  • Jump Labels
  • Stack functions

And overall having NO access to memory or memory functions/methods.


I created a lexer in Luau, if I can find it I’ll drop the source code.

Anyways, I wish you the best of luck on this. If you’re stuck, please remember to do your research and at least take a break.

1 Like

How I implemented it for the course was basically designing functions that did all the basic steps individually (lexing, parsing, tokenizing, evaluating, ect.) and then fed a string of code to a program that called all the functions and evaluated the output. My idea was basically doing the same thing, except putting it in a module script that you basically just called module.runthiscode("your string of code here") and let the module call all the neccesary functions in order, and give you back your output. Haven’t put too much thought into it, so thats all I really had for now

2 Likes

Ideally I would be implementing a subset of Lua so it would be more applicable, but yeah there would probably be better ways to learn programming than this. Just thought it was a fun way to make a personal project more usable by other people

1 Like

Thats a valid concern, if I did this myself it would definitely be a lot of looking back on my javascript interpreter and my notes from the course (and a lot of debugging but I try not to think about that too much). I was thinking of using dicts to ‘represent’ memory to get around directly accessing it and use as many other shortcuts as Lua gives me, but it would dfinitely still be a challenge.

1 Like

Would be a nice idea honestly. You could even make your own “stack” or environment with push and pop functions and the internals just being an array (literally what a stack is).


Found the Lexer, here it is:

Luau Lexer
--Created by TheUnderratedDev
--Date: Unknown
--If you don't understand this, visit https://craftinginterpreters.com/ to learn more about lexers and programming languages

--This could have been optimized more with other things, but I'd rather do it how you would do it in C++/JS with little string patterns and a "switch statement" being a for loop

local Source = [[
    local a = "d"
    require(a)
]]

local Data = {}

--Util data for the lexer
local Specials = {
    Current = 0,
    Advance = 0
}

--Lexemes array containing lexemes and their token
local Lexemes = {
    ["("] = "LPAREN",
    [")"] = "RPAREN",
    ["="] = "EQUAL"
}

--Keywords array
local Keywords = {
    ["require"] = "REQUIRE",
    ["getfenv"] = "GETFUNCTIONENV",
    ["local"] = "LOCAL",
    ["tonumber"] = "TONUMBER",
}

--Adds a token to the array
function addToken(type, val)
	Data[#Data + 1] = {
		Token = type,
        Value = val
	}
end

--Just formats and prints out the tokens
function toString()
    local main = ""

    for i, v in pairs(Data) do
        local other = "   { TOKEN: %s, VALUE: %s }\n"
        main ..= string.format(other, v.Token, v.Value)
    end

    return string.format("{\n%s}", main)
end

--Checks if the identifier is a built in keyword, if it is then create a token of the keyword, if not make an identifier token
function keyword()
    local start = Specials.Current
    local str = string.sub(Source, start, -1)
    local collected = ""
    local count = 0

    for i in string.gmatch(str, ".") do
        if (not string.match(i, "%w")) then
            break
        end

        count += 1
        collected ..= i
    end

    local Find = Keywords[collected]

    if (Find) then
        addToken(Find, collected)
    else
		addToken("IDENTIFIER", collected)
    end

    return count - 1
end

--Checks if the current is a number, if so then continue checking if the preceding characters are also numbers. This supports decimals
function number()
    local start = Specials.Current
    local str = string.sub(Source, start, -1)
    local collected = ""
    local count = 0

    for i in string.gmatch(str, ".") do
        if (i == ".") then
			count += 1
            collected ..= "."
            continue
        end

        if (not string.match(i, "%d")) then
            break
        end

        count += 1
        collected ..= i
    end

    local num = tonumber(collected)

    if (num) then
        addToken("NUMBER", collected)
    end

    return count - 1
end

--WIP
function strng()
    local start = Specials.Current + 1
    local str = string.sub(Source, start, -1)
    local collected = ""
	local ended = false
    local count = 0

    for i in string.gmatch(str, ".") do
        if (i == "\"") then
		    count += 1
            ended = true
            break
        end

        count += 1
        collected ..= i
    end

	addToken("STRING", collected)
    return count
end

--MAIN
for i in string.gmatch(Source, ".") do
    Specials.Current += 1

    --Whitespace? Continue
    if (string.match(i, "%s")) then
        continue
    end

    --Checks if it should skip the current character and advance the for loop to a set number. If Specials.Advance is 2, skip 2 iterations
    if (Specials.Advance > 0) then
        Specials.Advance -= 1
        continue
    end

    --Finding out if the current is a special character like "(" and returning the token for it
    local Find = Lexemes[i]

    --If found then add the token and continue
	if (Find) then
		addToken(Find, i)
        continue
	end

    --If the current is an alphabetic character then call the keyword function
	if (string.match(i, "%a")) then
        Specials.Advance = keyword()
        continue
    end

    --If the current is a number, call the number function
    if (string.match(i, "%d")) then
		Specials.Advance = number()
		continue
    end
end

print(toString()) -- Prints all tokens

If you run this with Luau (or MAYBE Roblox), you’ll get this result:

image

Why the heck are there 14 problems?

2 Likes