Writing an interpreter isn't necessarily a big job, but it does require a structured approach and strong coding skills in general.
First tokenization, make a list of all the components of the code, sting, keywords, operators etc. all take one slot each, like:
- print
- (
- "Hello \"world\""
- )
This shouldn't be too hard.
Now do identifier classification, depending on their position in code etc. you should be able to figure if they are function calls, operators, variables or whatever.
Now do bracket matching, run through the list while updating a stack of unmatched opening brackets, whenever a bracket is matched remove it from the stack and link the matching brackets giving each a pointer to the other.
Your list have to be made into a tree, now you can start blocking stuff, every pair of brackets make a block, and depending on language other constructs may constitute a bracket-like block. (begin-end statements and similar can simply be treated like brackets). Such a block you simply make into a single element on the list containing a list of all it's sub-elements. Hereafter you traverse the tree once for each operator precedence level and do blocking for those operators.
Now you can make lists of all variables and functions, one for each scope, and check that there are no collisions.
For each scope you make an ordered list of variables so that you can erect a block of memory and know exactly where each goes.
Replace variable and function names with links to memory block location and function declarations respectively.
Now you could go on to compile the program completely, or run it in an interpreter.
To run it, make a call stack list, and a matching list of scopes. Whenever a function is called note the return position in the call stack and erect a matching scope, when it is finished destroy the scope and return to the return position.
Normal language constructs should be pretty easy to handle, whenever there is an if
you know that it is followed by two blocks, if the first block evaluate to false, skip the second. Similarly loops and other constructs are trivial to handle once you consider them as consisting of a fixed number of blocks with some trivial rules dictating when to execute each one of them.
I have now given you the structured approach, the skill to implement it I can't guarantee. There are countless possible performance tweaks, and a lot that I haven't explicitly told how to implement, you'll have to figure.