Simple Interpreter

Pages: 123
Yes, you can store there your functions as you store variables in map <string, double> table;
I was thinking of storing function names in one table, just a string then cross reference them to another table "parameters" which requires the name of the function?
I think a simple class would be a better approach but you can try whatever you like
Could you show me a small partly implemented example using the code?
I already have it looking for the function keyword then noting what the function name is, it's just storing this data and then looking for the body functions.
To get the arguments:
(assuming ftable to be the function table and param a std::list<string> )
1
2
3
4
5
6
7
8
9
10
string func_name = string_value; // temp. variable to hold the name
if ( get_token() != LP ) return error ( "( expected" ); // check for '('
while ( get_token() != RP )
{
   if ( curr_tok == NAME )
   {
        fmap[func_name].param.push_back(string_value); // add a parameter
        if ( curr_toc != COMMA ) return error(", expected"); // need to add the ',' token
   }
}

Try to see if this works, tomorrow I'll show you how to get the body
I've figured out how to read function declarations:
This is a simple function structure:
1
2
3
4
5
6
7
struct function
{
    list<string> parameters; // to know the sequence of the parameters
    map<string,double> arguments; // later would be used for argument assignment
    string body; // for the code to execute on function call
};
map <string,function> func_table; // to store the functions 
Then you need to add two tokens: the COMMA to divide the arguments and the BLOCK to get blocks enclosed by braces
To get the block (in get_token):
1
2
3
4
5
6
7
8
9
10
11
12
case '{':
            {
                unsigned nested = 0; // used to check that nested blocks are included properly
                string_value = "";
                while ( input->get(ch) )
                {
                    if ( ch == '{' ) nested++;
                    else if ( ch == '}' && nested-- == 0 ) break;
                    string_value += ch;
                }
                return curr_tok=BLOCK;
            }
For the comma, just do as with other operators
Now when reading the function:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
string name = string_value;
// get parameters
if ( get_token() != LP ) return error ( "( expected" );
do
{
    get_token();
    if ( curr_tok == NAME )
    {
        func_table[name].parameters.push_back(string_value);
        get_token();
        if ( curr_tok != COMMA && curr_tok != RP ) return error(", expected");
    }
    else return error("Parameter expected"); // you may want to modify this allowing functions taking no arguments
}while ( curr_tok != RP );

// get (if given) the function body
get_token();
if ( curr_tok == PRINT ) return 1;// just prototype, not body. NOTICE: both the newline character and the semicolon return PRINT as token
else if ( curr_tok != BLOCK ) return error ( "function body expected" );
func_table[name].body = string_value;
return 1; // you need to return a value 


Notes on the code you PMd me:
Line 28: ifstream* input; keep input as simply istream, it would be useful for later use

To execute functions, I repeat the pseudocode I gave you in page 2 (this time better explained)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// function call
if Your_token_is_a_NAME
    if is_a_keyword
        do_whatever_you_need
    if is_in_the_variable_table
        return variable_value
//===========================================
    if is_in_the_function_table
       check_for_LP
       save_current_input_pointer
       while function_needs_argument // Iterate the parameters list
            read_a_string_until_comma
            convert_that_string_into_a_stringstream
            change_input_to_that_stringstream // that is why you need to be able of reading all istream types
            get_the_result_from_the_new_input_source 
            set_the_parameter_to_the_argument_value// currentfunction.arguments[*iterator] = value
       restore_the_input_you_had
       check_for_RP
       for each argument
            execute "parameter name = argument value"
       execute_the_function_body_as_a_stringstream_and_return_the_value_you_got
Notice that variables haven't a scope, if you want scopes you may think of getting your interpreter in a class
Last edited on
Brilliant Bazzy!

I've been busy with college work so I will start attempting to implement the code in the weekend. Thanks again.
I've had no luck.

Is anyone able to take a stab please?
Topic archived. No new replies allowed.
Pages: 123