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