Bjarne Stroustrup编程实践和原则第7章

时间:2013-10-21 17:02:24

标签: c++

我对逻辑流程有疑问:

I'm trying to create a calculator functionality that: 
1.lets you assign a declare a variable (eg, let x = 5;) 
2. that will also let you reassign a value (eg, x = 10;)
3. will let you use values in expressions (eg, x + 5; returns 15)

底部函数语句()应该决定Token Token_stream :: get()    返回声明,重新分配或表达式,然后运行相应的代码。

使它成为Token_stream :: get()将name返回给statement()    并调用重新分配。我失去了功能   有一个表达式()以一个名字开头。例如。如果我写

x + 5;

它将从赋值中抛出一个错误,因为它读取x并查找= 而不是呼叫表达。

如果Token Token_stream :: get()读取一个后跟'='的字符串,我想创建特殊的令牌以便在statement()中使用赋值,但是然后将该名称放回输入流中,这样我就可以抓取作业。有什么建议吗?

    //------------------------------------------------------------------------------
        Token Token_stream::get()
        {
            if (full) { full=false; return buffer; }
            char ch;
            cin >> ch;
            switch (ch) {
            case '(':
            case ')':
            case '+':
            case '-':
            case '*':
            case '/':
            case '%':
            case ';':
            case '=':
            case ',': 
                return Token(ch);
            case '.':
            case '0':
            case '1':
            case '2':
            case '3':
            case '4':
            case '5':
            case '6':
            case '7':
            case '8':
            case '9':
            {   cin.unget();
                double val;
                cin >> val;
                return Token(number,val);
            }
            default:
                if (isalpha(ch)) {
                    string s;
                    s += ch;
                      while(cin.get(ch) && (isalpha(ch) || isdigit(ch))||        ch    =='_' )   s+=ch;
                    cin.unget();
                    if (s ==   "let")   return Token(let);
                    if (s == "const")   return Token(constant);   
                    if (s ==     "q")   return Token(quit);
                    if (s ==  "sqrt")   return Token(square_root); 
                    if (s ==   "pow")   return Token(exponent);       
                    return Token(name,s);
                }
                error("Bad token");
            }
        }
        //------------------------------------------------------------------------------
        //------------------------------------------------------------------------------------------------
        double statement()
        {
            Token t = ts.get();
            switch(t.kind) 
                {
                case let: 
                    return declaration();

                case name:
                    ts.unget(t);
                    return assigment();

                case constant: 
                    return declare_constant();

                default:
                    ts.unget(t);
                    return expression();
                }
        }
        //----

1 个答案:

答案 0 :(得分:1)

我不会将错误处理逻辑放在tokenizer类中 - 它应该是一个非常愚蠢的文本muncher,它只是在空格上分割它并将标记返回给调用者。

因此,假设您开始解析语句,并且您的tokeninizer返回let。现在你知道接下来应该是一个宣言。下一个标记应该是尚不存在的变量的唯一名称。所以你再次致电Token_stream::get(),看看你得到了什么。成功后,您将获得下一个令牌,看看您是否获得了=。等

类似地 - 您将变量的名称作为语句的第一个标记。您检查它是否已被声明,如果没有,则报告错误。你检查另一个令牌。它应该是某种类型的运算符(可能包括=)。如果你得到它,你开始寻找一个有效的术语(一个值,另一个变量,一个表达式......)。等