Jump to content




Interpreter [I have made it but I get an error]


11 replies to this topic

#1 CCTech

  • Members
  • 40 posts
  • LocationGermany

Posted 09 May 2018 - 06:46 PM

Hello dear Community,

I know making an Interpreter is hard but I tried it using fs.read etc.

So everything works fine but when I run the interpreter it works as it should. There is a text and it asks for my input, When I enter the file I made in that "language" i get this error:

boios.lua:14: [string "test"]:3 '=' excepted

Here is the "interpreter":

term.setBackgroundColor(colors.black)
term.setTextColor(colors.white)
term.clear()
term.setCursorPos(1,1)

print("-- SDK Interpreter --")
print(" ")
print("Please type in the file/directory and file")
print(" ")
print(" ")
write(">> ")

local input = read()

fs.makeDir("/temp")
fs.copy(input, "/temp/main.sdk")

local write = fs.open("/temp/main.sdk","w")
local read = fs.open(input, "r")
local Code = read.readLine()

if Code == "sdk.File" then
  write.writeLine('os.loadAPI("/sdk")')
end

if Code == "func" then
  write.writeLine(code, "function()")
end

if Code == "}" then
  write.writeLine("end")
end

if Code == "loop {" then
  write.writeLine("while true do")
end

if Code == "?" then
  write.writeLine("if", code)
end

if Code == "sdk.off" then
  io.close(input)
  io.close("/temp/main.sdk")
  fs.delete("/temp")
end

shell.run(input)

and here is the Test file:

sdk.file

i = false

? I = false then
  print("I is false")
  os.pullEvent("key")
  i = true
}

? i == true then
  print("I is true")
  os.pullEvent("key")
}

sdk.end

If it seems like I couldn't make it like that.. I could make an API of this.. like the user types:
sdk.func


#2 Luca_S

  • Members
  • 399 posts
  • LocationGermany

Posted 09 May 2018 - 06:58 PM

The first thing I notice is that you are only interpreting the first line, try adding a while loops or something similar.
The next thing is that when everything is done you are executing the file which is in input, but that file is just what you already have and not the modified one.
The third thing is that, once your code reaches a line like
? i == false then
It will replace that whole line by just "if", because writeLine(a, b ) only writes a and not a and b to the file.
Even if it would write both it would replace it with:
if ? i == true then
which is still not valid.
In Line 5 of your test file you are also checking for the variable I, which is not the same as the variable i and you are not checking if they are equal, but you are assigning a new value to I.

Edited by Luca_S, 09 May 2018 - 07:56 PM.


#3 CCTech

  • Members
  • 40 posts
  • LocationGermany

Posted 09 May 2018 - 08:22 PM

Thanks for the fast answer..

I see... I first tried changing the normal file but then I gave up and copied it.. so I forgot to change
shell.run(input)
to
shell.run("/temp/main.sdk")

So now I changed the code.. but now when I type in the Interpreter the file name I don't get any error. My computer freezes and I can't do anything. I can't reboot, terminate or shutdown.. after sometime it gets black and.. I can't do anything either..


Code:
running = true

term.setBackgroundColor(colors.black)
term.setTextColor(colors.white)
term.clear()
term.setCursorPos(1,1)

print("-- SDK Interpreter --")
print(" ")
print("Please type in the file/directory and file")
print(" ")
print(" ")
write(">> ")

local input = read()

Modify = function()
  fs.makeDir("/temp")
  fs.copy(input, "/temp/main.sdk")
end

if fs.exists("/temp/main.sdk") then
  fs.delete("/temp")
  Modify()
else
  Modify()
end

local write = fs.open("/temp/main.sdk","w")
local read = fs.open(input, "r")
local Code = read.readAll()
local String = io.input()

while running do
if Code == "sdk.File" then
  write.writeLine('os.loadAPI("/sdk")')
end

if Code == String and Code == "func {" then
  write.writeLine(String, "= function()")
end

if Code == "}" then
  write.writeLine("end")
end

if Code == "loop {" then
  write.writeLine("while true do")
end

if Code == "?" and Code == String and Code == "{" then
  write.writeLine("if", String, "then")
end

if Code == "sdk.off" then
  write.writeLine('io.close("/temp/main.sdk")')
  write.writeLine('fs.delete("/temp")')
  running = false
  shell.run("/temp/main.sdk")
end
end

Edited by OneTech, 09 May 2018 - 08:23 PM.


#4 CCTech

  • Members
  • 40 posts
  • LocationGermany

Posted 09 May 2018 - 08:35 PM

Small update.. I changed the code to:

term.setBackgroundColor(colors.black)
term.setTextColor(colors.white)
term.clear()
term.setCursorPos(1,1)

print("-- SDK Interpreter --")
print(" ")
print("Please type in the file/directory and file")
print(" ")
print(" ")
write(">> ")

local input = read()

Modify = function()
  fs.makeDir("/temp")
  fs.open("/temp/main.sdk")
end

if fs.exists("/temp/main.sdk") then
  fs.delete("/temp")
  Modify()
else
  Modify()
end

local write = fs.open("/temp/main.sdk","w")
local read = fs.open(input, "r")
local Code = read.readAll()
local String = io.input() 

  if Code == "sdk.File" then
    write.writeLine('os.loadAPI("/sdk")')
  end

  if Code == String and Code == "func {" then
    write.writeLine(String, "= function()")
  end

  if Code == "}" then
    write.writeLine("end")
  end

  if Code == "loop {" then
    write.writeLine("while true do")
  end

  if Code == String and Code == "{" then
    write.writeLine("if", String, "then")
  end

  if Code == "sdk.off" then
    write.writeLine('io.close("/temp/main.sdk")')
    write.writeLine('fs.delete("/temp")')
    write.writeLine("shell.exit()")
    shell.run("/temp/main.sdk")
  end

But now when I enter the file at the sdk I get a random red number.. even if I type a file name which doesn't exists

#5 Bomb Bloke

    Hobbyist Coder

  • Moderators
  • 7,099 posts
  • LocationTasmania (AU)

Posted 10 May 2018 - 07:55 AM

Your Modify() function makes an incorrect fs.open() call - you probably don't want to be attempting to open a file there at all.

Off the top of my head, I'm fairly certain ComputerCraft doesn't implement io.input(), and I'm not entirely certain what you'd expect it to return in this instance even if it did. I guess what you're wanting to do is read through the specified file line by line - a "for" loop incorporating io.lines() is one of the easier ways to do this:

for line in io.lines(input) do
  if line == "sdk.File" then
    --# etc .........
  end
end

Edited by Bomb Bloke, 10 May 2018 - 07:55 AM.


#6 CCTech

  • Members
  • 40 posts
  • LocationGermany

Posted 10 May 2018 - 10:20 AM

View PostBomb Bloke, on 10 May 2018 - 07:55 AM, said:

Your Modify() function makes an incorrect fs.open() call - you probably don't want to be attempting to open a file there at all.

Off the top of my head, I'm fairly certain ComputerCraft doesn't implement io.input(), and I'm not entirely certain what you'd expect it to return in this instance even if it did. I guess what you're wanting to do is read through the specified file line by line - a "for" loop incorporating io.lines() is one of the easier ways to do this:

for line in io.lines(input) do
  if line == "sdk.File" then
	--# etc .........
  end
end

I don't really understand.. I tried making it how I understood:

for line in io.lines(input) do
  if line == "clearScreen" then
	write.writeLine("term.clear()")
  end
end

Now when I enter at the interpreter the file name it just exists the interpreter.. and when I open the file (I had some trouble with the new and modify file) there is nothing inside

Edited by OneTech, 10 May 2018 - 10:21 AM.


#7 CCTech

  • Members
  • 40 posts
  • LocationGermany

Posted 10 May 2018 - 10:31 AM

Another.. New.. I've got it to work to clear the screen :lol:

Here is the modify function (I will rename it):

for line in îo.lines(input) do
  if line == "clearScreen" do
    term.clear()
    term.setCursorPos(1,1)
  end
end

Now I'm working on changing the cursorPos and changing Backgound color.. and need help with the statements.. (I know how I can replace the if (i think) but executing the if and the rest of the line......)

#8 Windows10User

  • Members
  • 62 posts
  • LocationC:\Minecraft\saves\stuff\computer

Posted 10 May 2018 - 12:26 PM

I feel like making my own interpreter now!

#9 CCTech

  • Members
  • 40 posts
  • LocationGermany

Posted 11 May 2018 - 09:26 AM

..One.. more question ^_^ how can I make it if the user types print("Hello, World!") that the script I run with the interpreter prints something..?

#10 SquidDev

    Frickin' laser beams

  • Members
  • 1,417 posts
  • LocationDoes anyone put something serious here?

Posted 11 May 2018 - 09:35 AM

Well, following on from your above implementation:
if line == 'print("Hello, World!")' then
  print("Hello, World!")
end

Ideally though, you'd be tokenising the input, so the above gets converted into print, (, "Hello, World!", ). Then you can convert it into some AST and codegen from that. It might be worth checking out Urn's lexer (or Howl's, which is substantially more complex but parses Lua).

#11 CCTech

  • Members
  • 40 posts
  • LocationGermany

Posted 11 May 2018 - 09:46 AM

View PostSquidDev, on 11 May 2018 - 09:35 AM, said:

Well, following on from your above implementation:
if line == 'print("Hello, World!")' then
  print("Hello, World!")
end

I didn't ment like that.

If the user types

print("SOmething")

that the if function in the interpreter scans what it prints.... Idk like:

if(line == "print(" string ")" then
  print(string)
end

But I don't know how to make it.. (Above is just an example so you understand what I mean..)

#12 Bomb Bloke

    Hobbyist Coder

  • Moderators
  • 7,099 posts
  • LocationTasmania (AU)

Posted 11 May 2018 - 11:13 AM

Frankly, if you had the experience needed to understand the answer, then you wouldn't need to ask that question in the first place.

But to try to give you a picture: this is what SquidDev is talking about when he refers to tokenisation. In a nutshell, you need to break that line down into parts so that you can identify that it starts with a request to display something, and that it then moves on to establish what that "something" is.

Consider the items in the line print("Hello, World!") - first it provides a name ("print"). Then it throws in some brackets, an indication that the preceding name is that of a variable containing a function pointer, and that function is to be called. Within those brackets, quotes then appear, which are used to define a single string of text, "Hello, World!", which is the argument to be passed to the called function.

You need to code your own way of breaking the line down into those elements. The way I would personally do this is to switch from inspecting your file line by line to instead going character by character - start by adding characters to a string until you have a complete word (terminated by a space, or a bracket, or an equals sign, or any of the other characters that signify a break), and then use the following symbol to determine what to do with it. Following the above example of printing something, the first word is ended with a bracket, indicating you should be preparing to call a function - so within your interpreter, define a function for the purpose of interpreting function calls. Pass that the name of the function you read in, along with the remainder of the text, and have it keep parsing character by character until it's gathered all the information contained within the brackets.

You'll soon want to define additional functions for the purpose of translating other data types. A string-identifier would be next, in order to recognise "Hello, World!". Soon you'll want to be able to recognise numbers, and then perhaps booleans, too.

The basic structure of your script would start to look a bit like this very-rough-and-loose bit of psuedo-code:

Spoiler

As you start to add support for more actions, data types, and so on, this'll start to get a lot longer. Take another look at Howl - this is the sort of thing that's doing.

So, um... yeah.

What I suggest is that you switch projects and start work on a text adventure game - these sorts of "simple interpreters" would help you step up to the more complex source code interpreters.





1 user(s) are reading this topic

0 members, 1 guests, 0 anonymous users