如何在C中使我的BASIC解释器知道输入了什么

时间:2011-05-20 09:17:39

标签: c interpreter basic

我正在尝试在C中创建一个BASIC解释器。我开始使用解释器进行数学计算(就像计算器一样,除了这里我可以给变量X赋值2,例如)。我的问题是我不知道如何让我的翻译找到一些输入之间的差异。例如: 10 LET x = 10,这应该存储在一个数组中供以后使用。 LET x = 10,应该立即执行 10 + 1,这应该立即执行。

我如何修改我的翻译,以便它知道这些事情?我不知道在哪里进行更改,但我认为它应该在解析器中进行,所以我在这里发布它。如果您想查看其他代码,请询问。

//diddi

    /*
     * File: parser.c
     * --------------
     * This file implements a version of ReadExp that uses
     * conventional precedence rules.  Thus, the expression
     *
     *        x = 2 * x + y
     *
     * is interpreted as if it had been written
     *
     *        x = ((2 * x) + y))
     *
     * This language can be parsed using the following ambiguous
     * grammar:
     *
     *       E  ->  T
     *       E  ->  E op E
     *
     *       T  ->  integer
     *       T  ->  identifier
     *       T  ->  ( E )
     *
     * Unfortunately, this grammar is not sufficient by itself.  The
     * parser must also provide some way to determine what operators
     * take precedence over others.  Moreover, it must avoid the
     * problem of going into an infinite recursion of trying to read
     * an expression by reading an expression, and so on forever.
     *
     * To solve these problems, this implementation passes a numeric
     * value to the ReadE function that specifies the precedence
     * level for the current subexpression.  As long as ReadE finds
     * operators with a higher precedence, it will read in those
     * operators along with the following subexpression.  If the
     *

 precedence of the new operator is the same or lower than
 * the prevailing precedence, ReadE returns to the next higher
 * level in the recursive-descent parsing and reads the operator
 * there.
 */

#include <stdio.h>
#include <ctype.h>
#include "genlib.h"
#include "strlib.h"
#include "simpio.h"
#include "scanadt.h"
#include "parsering.h"
#include "exp.h"
#include "cmddisp.c"

/*
 * Implementation notes: ParseExp
 * ------------------------------
 * This function just calls ReadE to read an expression and then
 * checks to make sure no tokens are left over.
 */

expressionADT ParseExp(scannerADT scanner)
{
    expressionADT exp;

    exp = ReadE(scanner, 0);
    if (MoreTokensExist(scanner)) {
        Error("ParseExp: %s unexpected", ReadToken(scanner));
    }
    return (exp);
}

/*
 * Implementation notes: ReadE
 * Usage: exp = ReadE(scanner, prec);
 * ----------------------------------
 * This function reads an expression from the scanner stream,
 * stopping when it encounters an operator whose precedence is
 * less that or equal to prec.
 */

expressionADT ReadE(scannerADT scanner, int prec)
{
    expressionADT exp, rhs;
    string token;
    int newPrec;

    exp = ReadT(scanner, 0);
    while (TRUE) {
        token = ReadToken(scanner);
        newPrec = Precedence(token);
        if (newPrec <= prec) break;
        rhs = ReadE(scanner, newPrec);
        exp = NewCompoundExp(token[0], exp, rhs);
    }
    SaveToken(scanner, token);
    return (exp);
}

/*
 * Function: ReadT
 * Usage: exp = ReadT(scanner);
 * ----------------------------
 * This function reads a single term from the scanner by matching
 * the input to one of the following grammatical rules:
 *
 *       T  ->  integer
 *       T  ->  identifier
 *       T  ->  ( E )
 *
 * In each case, the first token identifies the appropriate rule.
 */

expressionADT ReadT(scannerADT scanner, int prec)
{
    expressionADT exp, rhs;
    string token;
    int newPrec;

    exp = ReadF(scanner);
    while (TRUE) {
        token = ReadToken(scanner);
        newPrec = Precedence(token);
        if (newPrec <= prec) break;
        rhs = ReadT(scanner, newPrec);
        exp = NewCompoundExp(token[0], exp, rhs);
    }
    SaveToken(scanner, token);
    return (exp);
}

int Precedence(string token)
{
    if (StringLength(token) > 1) return (0);
    switch (token[0]) {
      case '=': return (1);
      case '+': case '-': return (2);
      case '*': case '/': return (3);
      default:  return (0);
    }
}

expressionADT ReadF(scannerADT scanner)
{
    expressionADT exp;
    string token;

    token = ReadToken(scanner);
    if (StringEqual(token, "(")) {
        exp = ReadE(scanner, 0);
        if (!StringEqual(ReadToken(scanner), ")")) {
            Error("Unbalanced parentheses");
        }
    } else if (isdigit(token[0])) {
        exp = NewIntegerExp(StringToInteger(token));
    } else if (isalpha(token[0])) {
        exp = NewIdentifierExp(token);
    } else {
        Error("Illegal term in expression");
    }
    return (exp);

}

1 个答案:

答案 0 :(得分:0)

最简单的方法是在使用语法进行解析之前执行一步,该语法查看是否存在行号(即整数后跟空格)然后删除(记住它是什么,以便将其存储在您的它将该行的其余部分交给解析器。在大多数解释器中,有不止一个解析器工作。