1583 posts
Location
Germany
Posted 30 May 2013 - 12:06 PM
Hello all,
I've started developing my
Interpreter today.
Now I need a little bit of help:
How do I detect a while/for loop?
1522 posts
Location
The Netherlands
Posted 30 May 2013 - 02:49 PM
Please give us more information. But why do you need to detect it anyway? I mean really, you are not interpreting native code, at all. Otherwise, string.find("while") is a good help.
1583 posts
Location
Germany
Posted 30 May 2013 - 05:23 PM
Please give us more information. But why do you need to detect it anyway? I mean really, you are not interpreting native code, at all. Otherwise, string.find("while") is a good help.
Ok, I understand the string.find() thing.
But how does my interpreter understands the condition for it?
And how I say the interpreter where the loop stops?
I think I will post the code in a few days in the thread of it …
1190 posts
Location
RHIT
Posted 30 May 2013 - 06:23 PM
You'll want to use regex to do this.
For example, this would detect a basic while loop in Lua (you'll have to figure out yourself how you want to do this in whatever language you're interpreting):
local theCode = [[
--this is non relevant stuff
local x = 1
local hi = "hello"
while true do
print("This is looping")
end
--More non relevant stuff
]]
--#Now let's perform some regex
local match = theCode:match("while.-end")
print(match)
This would get the code that is inside a simple while loop and print it out. Of course, things can get pretty complicated if you're attempting to actually interpret a language, but regex is how you would go about it.
Find out more about regex
here.
7083 posts
Location
Tasmania (AU)
Posted 30 May 2013 - 07:13 PM
I would have the interpreter recognise the loop's start and mark that in a table, then place nested loops (and "if" statements and so on) inside tables WITHIN that table. I'd then carry on execution without worrying where the end point was. Whenever I did hit an "end" statement I'd simply delete the most deeply nested table.
This'd allow you to place variables local to each loop in their respective tables, allowing easy cleanup when you're done with them.
If I reached the end of the program and still had nested tables, I'd throw an error complaining that the loop relating to the final most deeply nested table had no "end" statement. If I hit "end" statements and didn't have any tables at all, I'd throw an "expected <eof>" error.
1583 posts
Location
Germany
Posted 30 May 2013 - 08:11 PM
o_O
I don't thought that it's so complex!
1522 posts
Location
The Netherlands
Posted 31 May 2013 - 02:17 AM
I would rather use plus instead of a minus:
string:gmatch('while.+end')
Since the plus is greedy, it needs the end.
Please correct me if Im wrong, Im still learning regex :P/>
871 posts
Posted 31 May 2013 - 09:51 AM
Neither of those will work in all cases; consider…
function foo()
...
while true do
...
if cond1 then
break
end
end
end
For this while loop, the first, with -, would go to the if's end, the + would go to the function's end. You'd have to stop at the "do", and match with "end"s in another way, like what bomb bloke described.
And there hasn't yet been any mention of how to parse the conditions themselves.
Basically, yes, this gets complicated. Why you would think otherwise, I have no idea.
500 posts
Posted 31 May 2013 - 03:12 PM
You would also need to detect these:
""
''
[[]]
[=[]=]
[==[]==]
[===[]===]
(etc.)
to make sure that it is not inside a string.
500 posts
Posted 31 May 2013 - 03:17 PM
I would rather use plus instead of a minus:
string:gmatch('while.+end')
Since the plus is greedy, it needs the end.
Please correct me if Im wrong, Im still learning regex :P/>
I think it's the opposite way around (not entirely sure though),
.+
matches anything except for a string with no characters at all,
.-
matches only the smallest amount required to go on with the pattern.
Oops, I wanted to edit my above post instead of add a new one in my head, but with my hands I accidentally click the reply button :P/>.
375 posts
Location
USA
Posted 31 May 2013 - 03:30 PM
If you want to do this the most "correct" way, you might want to do some research on how grammar parsing works. Here's a good Wikipedia article that helped me understand:
http://en.wikipedia...._descent_parserIf you want to do this the "easy" way, you could first make a pass over all the text, using a lookup table to run functions on certain tokens. A token would be something like
WHILE,
END,
TXTCOLOR,
SHUTDOWN, etc. On each token, check for its matching argument. If you are looking at
WHILE, then you'd check if the condition is true. This poses a problem for this kind of simple text interpreter. The condition can't be an expression because you'd have to implement a parser like what is mentioned in the article. You could, alternatively, have a register-based system where you can set and get register values and use them in arguments.The second solution is not very elegant, but it's probably closest to what you're looking for. I definitely recommend doing some research on how recursive parsers are made. It's a very interesting subject.