You're basically writing a very simple state machine - use functions to represent every state: (I'll use random pseudocode, since you didn't specify a language)
get_information():
return get_record()
ask_record():
record = read_line()
return () if !record
return ask_y(record)
ask_x(record):
x = read_line()
return ask_record() if !x
return ask_y(record, x)
ask_y(record, x):
y = read_line()
return ask_x(record) if !y
return ask_continue(record, x, y)
ask_continue(record, x, y)
continue = read_line()
return ask_y(record, x) if !continue
return (record, x, y)
this is a trivial approach. In some languages the call stack will grow, in others it won't. If you have a language which causes the stack to grow, you can use trampolines to prevent it, by rewriting get_information
to do:
x = get_information
while x is function:
x=x()
return x
ask_x(record):
x = read_line()
return (lambda: ask_record()) if !x
return (lambda: ask_y(record, x))
Or even abstracting the question and memory address of result in some question
structure:
struct question {
question *next, *prev;
char prompt[];
char **result;
}
and then running in a loop, calling question* run_question(question*)
, going to ->next, or ->prev depending on the answer, until the result is NULL (as a stop condition, when results are filled in and no questions are left).
The last solution is probably the most "normal one" if you use an imperative language with direct pointer access.