递归下降解析

发布于 2024-10-26 02:31:46 字数 4437 浏览 1 评论 0原文

我正在寻找有关我的作业的一些建议/帮助。由于这是一门课程,我并不要求任何人从字面上为我写出答案,但我确实需要帮助进行实际编码。

问题:

考虑以下 BNF 语法:

<前><代码>A -> I=EE->时间 + 时间 | T - E | TT-> F * T |时间/时间 | FF-> P ^ F | PP->我|左 | (五) 我->一个 |乙| ... | y | z L-> 0 | 1 | ... | 8 | 9

使用课堂上描述的技术实现递归下降 识别该语言中的字符串的解析器。输入应该来自 一个名为 input.dat 的文件,输出应该到控制台。一个 示例会话可能如下所示:

从文件中读取的字符串:a=a+bc*d 字符串“a=a+bc*d”位于 语言。从文件读取的字符串:a=a**b++c 字符串 “a=a**b++c”不在该语言中。

您必须使用 Java 和 C++ 实现该项目!实施 不包含两种语言的解决方案充其量, 获得一半学分。为了简化你不必处理的事情 解析字符串时的空格,即“”和类似的 该语言中的非法字符。

具有不同语法的正确相关示例:

// * <分配> =>  = <表达式>;
// * ; =>一个 |乙| c
// * <表达式>; => <点亮> + <点亮> | <点亮> - <点亮>
// * <点燃>; => 0 | ... | 9 | (<表达式>)

#include ;

使用 std::cout;
使用 std::endl;

布尔分配(无效);
布尔 ID(无效);
布尔表达式(无效);
布尔点亮(无效);

字符*c;

int main(int argc, char *argv[]) {

    c = argc == 2 ? argv[1] : (char *)"";

    if (分配() && *c == '\0') {
        计算<< “字符串 \”“ << argv[1] << “\” 位于该语言中。” <<结束;
    }
    别的 {
        计算<< “字符串 \”” << argv[1] << “\” 不在该语言中。” <<结束;
    }

    返回0;
}

布尔分配(无效){

    如果(id()){
        如果(*c == '='){
            ++c;
            如果 (expr()) {
                返回真;
            }
        }
    }

    返回假;
}

布尔 ID(无效){

    if (*c >= 'a' && *c <= 'c') {
        ++c;
        返回真;
    }

    返回假;
}

布尔表达式(无效){

    如果(点燃()){
        if (*c == '+' || *c == '-') {
            ++c;
            如果(点燃()){
                返回真;
            }
        }
    }

    返回假;
}

布尔点燃(无效){

    if (*c >= '0' && *c <= '9') {
        ++c;
        返回真;
    }
    别的 {
        如果 (*c == '(') {
            ++c;
            如果 (expr()) {
                如果 (*c == ')') {
                    ++c;
                    返回真;
                }
            }
        }
    }

    返回假;
}

到目前为止我的实际工作:(我暂时省略了 txt 文件的阅读,希望首先让语法工作) edit1:问题是没有一个字符串显示为该语言中的有效字符串。不幸的是,即使像 a=b 这样的简单字符串也必须遍历几乎所有的生产规则,所以我无法指出哪里出错了

//A -> I = E 
//E -> T + E | T - E | T 
//T -> F * T | F / T | F 
//F -> P ^ F | P 
//P -> I | L | (E) 
//I -> a | b | ... | y | z 
//L -> 0 | 1 | ... | 8 | 9 

#include <iostream>

using namespace std;

bool A(void);
bool E(void);
bool T(void);
bool F(void);
bool P(void);
bool I(void);
bool L(void);

char *c;

int main(int argc, char *argv[]){

     c = argc == 2 ? argv[1] : (char *)"";

    if (A() && *c == '\0') {
        cout << "The string \"" << argv[1] << "\" is in the language." << endl;
    }
    else {
        cout << "The string \"" << argv[1] << "\" is not in the language." << endl;
    }

    return 0;
}

bool A(void){

    if( I() )
    {
        if ( *c == '=' ){
            ++c;
            if ( E() )
            return true;
        }
    }

    return false;
}

bool E(void){

    if( T() ){
        if ( *c == '+' || *c == '-' ){
                ++c;
                if ( E() )
                return true;
        }
    }
    else
    if ( T() ){
        ++c;
        return true;
    }

    return false;
}

bool F(void){

    if( P() ){
        if( *c == '^')
        ++c;
        if( F() )
        return true;
    }
    else
    if ( P() ){
        ++c;
        return true;
    }

    return false;

}

bool I(void){

    if ( *c >= 'a' && *c <= 'z'){
        ++c;
        return true;
    }

    return false;

}

bool L(void){

    if ( *c >= '0' && *c <= '9' ){
    ++c;
    return true;
    }

    return false;
}

bool P(void){

    if ( I() ){
        ++c;
        return true;
    }
    else
    if ( L() ){
        ++c;
        return true;
    }
    else
    if ( *c == '(' ){
            ++c;
            if ( E() ){
                    if ( *c == ')' ){
                        ++c;
                        return true;
                    }
            }
    }

    return false;
}

bool T(void){

    if( F() ){
        if ( *c == '*' || *c == '/' ){
                ++c;
                if ( T() )
                return true;
        }
    }
    else
    if ( F() ){
        ++c;
        return true;
    }

    return false;
}

I was looking for some advice / help on my assignment. Since it is for a class I am not asking for anyone to literally write out the answers for me, but I do need help with my actual coding.

The Question:

Consider the following BNF grammar:

A -> I = E  
E -> T + E | T - E | T  
T -> F * T | F / T | F  
F -> P ^ F | P  
P -> I | L | (E)  
I -> a | b | ... | y | z  
L -> 0 | 1 | ... | 8 | 9  

Using the technique described in class implement a recursive descent
parser that recognizes strings in this language. Input should be from
a file called input.dat and output should be to the console. An
example session might look like this:

String read from file: a=a+b-c*d The string "a=a+b-c*d" is in
the language. String read from file: a=a**b++c The string
"a=a**b++c" is not in the language.

You must implement the project in BOTH Java and C++! Implementations
that do not include a solution in both languages will, at best,
receive half credit. To simplify things you will not have to handle
whitespace when parsing the string, i.e. "" and similiar are
illegal characters in this language.

A correct related example with a different grammar:

// * <assign> => <id> = <expr>
// *     <id> => a | b | c
// *   <expr> => <lit> + <lit> | <lit> - <lit>
// *    <lit> => 0 | ... | 9 | (<expr>)

#include <iostream>

using std::cout;
using std::endl;

bool assign(void);
bool id(void);
bool expr(void);
bool lit(void);

char *c;

int main(int argc, char *argv[]) {

    c = argc == 2 ? argv[1] : (char *)"";

    if (assign() && *c == '\0') {
        cout << "The string \"" << argv[1] << "\" is in the language." << endl;
    }
    else {
        cout << "The string \"" << argv[1] << "\" is not in the language." << endl;
    }

    return 0;
}

bool assign(void) {

    if (id()) {
        if (*c == '=') {
            ++c;
            if (expr()) {
                return true;
            }
        }
    }

    return false;
}

bool id(void) {

    if (*c >= 'a' && *c <= 'c') {
        ++c;
        return true;
    }

    return false;
}

bool expr(void) {

    if (lit()) {
        if (*c == '+' || *c == '-') {
            ++c;
            if (lit()) {
                return true;
            }
        }
    }

    return false;
}

bool lit(void) {

    if (*c >= '0' && *c <= '9') {
        ++c;
        return true;
    }
    else {
        if (*c == '(') {
            ++c;
            if (expr()) {
                if (*c == ')') {
                    ++c;
                    return true;
                }
            }
        }
    }

    return false;
}

My actual work so far: (I am leaving out the reading from the txt file for the moment, want to get the grammar working first)
edit1: The problem is that none of the strings are showing up as valid strings that are in the language. Unfortunately even a simple string like a=b has to run through almost all the production rules so I can't pintpoint where I am going wrong

//A -> I = E 
//E -> T + E | T - E | T 
//T -> F * T | F / T | F 
//F -> P ^ F | P 
//P -> I | L | (E) 
//I -> a | b | ... | y | z 
//L -> 0 | 1 | ... | 8 | 9 

#include <iostream>

using namespace std;

bool A(void);
bool E(void);
bool T(void);
bool F(void);
bool P(void);
bool I(void);
bool L(void);

char *c;

int main(int argc, char *argv[]){

     c = argc == 2 ? argv[1] : (char *)"";

    if (A() && *c == '\0') {
        cout << "The string \"" << argv[1] << "\" is in the language." << endl;
    }
    else {
        cout << "The string \"" << argv[1] << "\" is not in the language." << endl;
    }

    return 0;
}

bool A(void){

    if( I() )
    {
        if ( *c == '=' ){
            ++c;
            if ( E() )
            return true;
        }
    }

    return false;
}

bool E(void){

    if( T() ){
        if ( *c == '+' || *c == '-' ){
                ++c;
                if ( E() )
                return true;
        }
    }
    else
    if ( T() ){
        ++c;
        return true;
    }

    return false;
}

bool F(void){

    if( P() ){
        if( *c == '^')
        ++c;
        if( F() )
        return true;
    }
    else
    if ( P() ){
        ++c;
        return true;
    }

    return false;

}

bool I(void){

    if ( *c >= 'a' && *c <= 'z'){
        ++c;
        return true;
    }

    return false;

}

bool L(void){

    if ( *c >= '0' && *c <= '9' ){
    ++c;
    return true;
    }

    return false;
}

bool P(void){

    if ( I() ){
        ++c;
        return true;
    }
    else
    if ( L() ){
        ++c;
        return true;
    }
    else
    if ( *c == '(' ){
            ++c;
            if ( E() ){
                    if ( *c == ')' ){
                        ++c;
                        return true;
                    }
            }
    }

    return false;
}

bool T(void){

    if( F() ){
        if ( *c == '*' || *c == '/' ){
                ++c;
                if ( T() )
                return true;
        }
    }
    else
    if ( F() ){
        ++c;
        return true;
    }

    return false;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

雨落星ぅ辰 2024-11-02 02:31:46

遇到的普遍问题

E = T + E | T - E | T

我认为您在检测诸如当您查找 T() 时 ,但您尝试再次查找 T() 失败。
您在大多数其他函数中也犯过这个错误。

E() 的正确实现是(在 Chris 评论后更新):

if (T())
{
   if (c == '+' || c == '-')
   {  
      ++c;
      return E();
   }
   return true;
}
return false;

让我们练习一个示例:“a=(3)”

A()-> I() 返回 true -> c == '=' -> E() ->在调用 P() 后解析 3 时,T() 返回 true,最终调用 E()再次->现在 c == ')' 所以我们需要在 E() 中返回 true,否则如果我们在这里返回 false,解析将在 P() 中停止code>

我希望它不会太混乱,但这里很难表达。最好的方法是在一张纸上写下解析树以使其可视化。

再次更新:您在T()F()中也有类似的情况

I think you have a generic problem with detecting things like

E = T + E | T - E | T

When you look for T() and it fails you try to look for T() again.
You have made this mistake in most of the other functions as well.

The correct implementation for E() would be (updated after Chris comment):

if (T())
{
   if (c == '+' || c == '-')
   {  
      ++c;
      return E();
   }
   return true;
}
return false;

Lets exercise an example: "a=(3)"

A() -> I() returns true -> c == '=' -> E() -> T() returns true upon parsing 3 after calling into P() which ends up calling into E() again -> now c == ')' so we need to return true in E() otherwise if we return false here, parsing will stop in P()

I hope it's not too confusing but it's hard to express here. The best is if you write down the parse tree on a sheet of paper to visualize it.

Update again: You have a similar situation in T() and F()

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文