认识到新的路线

时间:2009-06-29 20:58:58

标签: c++ parsing interpreter tokenize

我有一个相当复杂的计算器,当用户输入“;”时打印输出(并点击进入。)我现在要做的是允许用户在输入时打印输出,(不使用分号。)我需要知道如何实现它。

附注:计算器使用标记化来读取用户输入

这是计算器源代码的一部分,也是唯一需要更改的部分。它是Token_stream的成员函数,当计算器的各种其他函数调用以获取下一个标记时调用它。

const char let = '#';
const char quit = 'Q';
const char print = ';';
const char number = '8';
const char name = 'a';
const char sq_rt = '@';
const char power = '^';
const char constant = '~';

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 ',':
    case constant:
    case power:
    case sq_rt:
    case let:
    case quit:
    case name:
        return Token(ch);   // let each character represent itself
    case '.':
    case '0':
    case '1':
    case '2':
    case '3':
    case '4':
    case '5':
    case '6':
    case '7':
    case '8':
    case '9':
    {   cin.unget();       // equivalent of putback
        double val;
        cin >> val;
        return Token(number,val);
    }
    default:
        if (isalpha(ch)) {       // in order to create variable names
            string s;
            s += ch;
            while(cin.get(ch) && (isalpha(ch) || isdigit(ch) || ch == '_')) s += ch;
            cin.unget();
            if (s == "const") return Token(constant);
            if (s == "quit") return Token(quit);
            if (s == "pow") return Token(power);
            if (s == "sqrt") return Token(sq_rt);
            if (s == "let") return Token(let);  
            if (s == "name") return Token(name);
            return Token(name,s);
             }
       else if (isspace(ch)) {    // my attempt at allowing enter to produce output
            string s;
            cin.get(ch);
            s += ch;
            if(s == "\n") return Token(print);
            }

            }
        error("Bad token");
    }

到目前为止,如果用户输入5 * 5并点击空格,则输入..没有任何反应。但是如果它们占据了空间,那么输入一个随机字符(任何字符,而不仅仅是;)然后按回车键,输出答案。在此之后,用户可以使用enter来产生输出,但是它保存了用户在命中空间后输入的额外标记,因此操作顺序变得棘手。

简而言之,我需要知道如何让用户最初进入空间然后进入(或者甚至只是输入,但是使用空格并立即进入)以产生输出 - 没有任何其他字符。

如果您想查看更多来源或对计算器本身有任何疑问以解决问题,我很乐意发布更多信息。

P.S。原始程序来自我正在学习C ++的书。我刚刚做过改变它的练习并为它添加功能。

3 个答案:

答案 0 :(得分:2)

我会首先将该行读入字符串,并将其传递给您的'令牌'类。

类似的东西:

#include <iostream>
#include <string>

...

{
    std::string in;
    getline( std::cin, in );
    Token t( in );
    // Do whatever you need to with 't'
    std::cout << in << " = " << t.Result() << std::endl;
}

答案 1 :(得分:0)

在“厨房”上进行扩张

假设您像这样创建令牌流类:

int main()
{
     Token_stream    stream(std::cin);

     // Do Stuff.
};

您也可以更改此内容:

int main()
{
    MyApplicationState   stateInfo;
    std::string          line;

    while(std::getline(std::cin,line))
    {
        std::stringstream s(line);
        Token_stream      stream(stateInfo,s);

        // Do stuff
    }
}

现在每一行都是自己的流 这假定每行包含表达式所需的所有信息,并且您可以将状态信息存储在对象MyApplicationState中。

答案 2 :(得分:0)

扩展上述解决方案的另一个想法是:

如果一行不包含所有信息,即如果需要通过多行“空间”输入设置标准定界字符。 例如,两个换行符(连续两次输入)将标记流的结束。

然后只需将整个事物读入一个缓冲区(如之前的答案中建议的那样)并解析该缓冲区。

Windows上的行尾通常是十六进制0X0D 0X0A序列。

相关问题