Having problem with exiting copied code

closed account (jwC5fSEw)
As I wrote the post below, it occurred to me that running a program from the command line is different from running it in an IDE. Is there a way to run a program from the command line and exit it if the program itself doesn't supply a way to exit while still retaining the return value of main()? If so, please tell me and disregard the rest of this message.

One of the exercises in TC++PL is to copy a desk calculator program in the book that demonstrates basic parsing. I copied it by hand, obviously, and when I compiled it it works well except I can't get it to exit. (I made extra sure I copied it exactly, and I found the exact exercise online and compared it and found no difference.) Here's the code in question:

1
2
3
4
5
6
7
8
Token_value get_token() {
    char ch = 0;
    cin >> ch;
    switch(ch) {
        case 0:
            return curr_tok = END;
    /* ... */ 
}


curr_tok being of enum type Token_value. Here's the bulk of main():

1
2
3
4
5
6
while (cin) {
        get_token();
        if (curr_tok == END) break;
        if (curr_tok == PRINT) continue;
        cout << expr(false) << '\n';
    }


I'm assuming I'm just misunderstanding something. Entering 0 obviously doesn't work because it's used as the character 0, so I guess nothing will exit the program? (Nothing in the rest of the code has any favility for exiting the program. I at least made sure of that.)
From TC++PL:
By default, operator >> skips whitespace (that is, spaces, tabs, newlines, etc.) and leaves the value
of ch unchanged if the input operation failed. Consequently, ch==0 indicates end of input.

To give eof to cin, enter Ctrl+D or Ctrl+Z ( depending on the system )
closed account (jwC5fSEw)
Thanks, Bazzy! Ctrl-Z does it for me.
closed account (jwC5fSEw)
I have a related question that I don't want to make a new topic for:

I'm using GDB to follow the flow of the parser and get a better understanding for it. I have a decent grasp of it, except for entering an identifier. In get_token(), it takes a char ch and uses that to determine the token. When I say var = 10, it takes var in with this:

1
2
3
4
5
if (isalpha(ch)) {
                cin.putback(ch);
                cin >> string_value;
                return curr_tok = NAME;
            }


string_value being a string. I don't understand how ch can hold a multi-letter identifier like var to put into string_value. If chars can only hold one character, then how does this code work?
ch holds only a single character, if that is a letter, you read the whole word into the string:

Input: var = 10
1
2
3
4
5
6
// CODE:
cin >> ch;
...
if (isalpha(ch)) {
    cin.putback(ch);
    cin >> string_value;
Value of the variables:
ch: 'v'  cin: "ar = 10" (removed 'v')      string_value: ""

ch: 'v' ( so this is true )
ch: 'v'  cin: "var = 10" (re-inserted 'v') string_value: ""
ch: 'v'  cin: "= 10" (removed "var")       string_value: "var"           

closed account (jwC5fSEw)
EDIT: One more question!

Okay that taught me a LOT. I wasn't aware that cin would hold everything entered like that. So if the first thing entered is a letter, it'll read everything up until the next whitespace as an identifier. I understand it much better now, thanks!

While still on the topic of this, I'm a little confused about this part of the code:

1
2
3
4
5
6
7
8
9
double prim(bool get) {
    if (get) get_token();

    switch (curr_tok) {
        case NUMBER:
        {   double v = number_value;
            get_token();
            return v;
        }


The beginning of prim(). If I put in var = 10; , it goes through parsing the identifier, = operator, and number as I expect it to. Then it enters prim() and goes to that section of the switch. When it gets to get_token(), it then gets the token as the = operator again. Why does this happen?
Last edited on
The purpose of that get_token call, is visible in the previous function:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
double term(bool get )
{
        double left = prim(get); // calls prim to get a number, which calls get_token again
        for (;;)
                switch (curr_tok) { // here is switching the result of the second get_token call
                case MUL:
                        left *= prim(true);
                        break;
                case DIV:
                        if (double d = prim(true)) {
                                 left /= d;
                                 break;
                        }
                        return error("divide by 0");
                default:
                        return left;
                }
}
So, the first get_token says that there's a NUMBER, then you get that number, and the last get_token is to provide the operation


closed account (jwC5fSEw)
Okay, I'm pretty sure I understand now. One more:

Why separate expr() and term()? I understand why prim() is its own function, but the other two seem like they would all be one function (i.e. one function for all arithmetic operators).
To give precedence to * / over + - operations
Topic archived. No new replies allowed.