为啥我的 C++ 递归下降解析器只适用于几台计算机? [关闭]

Posted

技术标签:

【中文标题】为啥我的 C++ 递归下降解析器只适用于几台计算机? [关闭]【英文标题】:Why does my C++ recursive descent parser only work for a few computers? [closed]为什么我的 C++ 递归下降解析器只适用于几台计算机? [关闭] 【发布时间】:2013-03-14 13:22:45 【问题描述】:

由于某种原因,我的程序似乎无法在使用 Code Blocks 12.11 的计算机或使用 VMware 的教授的计算机上运行,​​但它在两个使用 Visual C++ 2012 的同学计算机上运行良好。因为我的计算机在 Windows XP 上运行,我不能使用 Visual C++ 2012 甚至 2010,所以我必须使用代码块。我的程序旨在从文件中读取字符串列表并检查这些字符串是否符合 BNF 语法。

从未打印过任何错误。该程序编译得很好,但在我或我教授的计算机上运行时没有输出。

编辑:预期的输出应该是它询问要读取的文本文件的名称。然后,对于文件中的每个字符串,程序应该输出该字符串是否使用该语言。如果文件不存在,则程序输出“操作失败”。而不是这个,程序直接进入“按任意键终止”,这只是假设程序已经完成运行时显示。

/* This is a recursive descent parser that uses the following productions. The
   '||' operator stands for concatenation. The '|' operator for alternatives.

P_statement -> P_Identifier = P_Expression | P_Expression
P_Expression -> P_Term + P_Expression | P_Term - P_Expression | P_Term
P_Term -> P_Factor * P_Term | P_Factor / P_Term | P_Factor
P_Factor -> P_Exponential ^ P_Factor | P_Exponential
P_Exponential -> P_Identifier | L | UI | UL | (P_statement)
P_Unary -> + | - | !
P_Identifier -> P_Character | P_Character||P_Identifier
P_Character -> a | b | ... | y | z
P_Number -> P_Digit | P_Digid||P_Number
P_Digit -> 0 | 1 | ... | 8 | 9
*/

#include <iostream>
#include <string>
#include <fstream>

using std::cout;
using std::cin;
using std::endl;
using std::ifstream;
using std::ios;
using std::ofstream;
using std::string;

// The functions that test whether the current string matches a particular
// production, hence the 'P_' prefix.
bool P_statement(void);
bool P_Expression(void);
bool P_Term(void);
bool P_Factor(void);
bool P_Exponential(void);
bool P_Unary(void);
bool P_Identifier(void);
bool P_Character(void);
bool P_Number(void);
bool P_Digit(void);

string s;

int main()
   string mystr;
   cout << "What is your text file? ";
   cin >> mystr;
   ifstream input(mystr.c_str());

   if(input.is_open())
      while(input.good())
         getline(input, s);
         string C = s;
         if (P_statement() && s == "")
            cout << "The string \"" << C << "\" is in the language." <<endl;
         
         else 
            cout << "The string \"" << C << "\" is not in the language." <<endl;
         
      
      input.close();
   
   else cout << "Operation failed" << endl;

   return 0;


bool P_statement(void) 

   if (P_Identifier()) 
      if (s[0] == '=') 
         s = s.substr(1);
         if (P_Expression()) 
            return true;
         
      
      s = s.substr(1);
   
   if(P_Expression())
      return true;
   
   return false;


bool P_Expression(void) 

  if (P_Term()) 
     if (s[0] == '+' || s[0] == '-') 
         s = s.substr(1);
         if (P_Expression()) 
            return true;
         
     
     return true;
  
  return false;


bool P_Term(void) 

   if(P_Factor())
      if (s[0]=='*' || s[0]=='/')
         s = s.substr(1);
         if (P_Term()) 
            return true;
         
      
      return true;
   
   return false;


bool P_Factor(void)
   if (P_Exponential()) 
      if (s[0] == '^') 
         s = s.substr(1);
         if (P_Factor()) 
            return true;
         
      
      return true;
   
   return false;


bool P_Exponential(void)
   if(P_Identifier())
      return true;
   
   else if(P_Number())
      return true;
   
   else if(P_Unary())
      if (P_Identifier())
         return true;
      
      else if(P_Number())
         return true;
      
   
   else if (s[0] == '(') 
      s = s.substr(1);
      if (P_statement()) 
         if (s[0] == ')') 
            s = s.substr(1);
            return true;
         
      
   
   return false;


bool P_Unary(void)
   if (s[0] =='+' || s[0]=='-' || s[0]=='!')
      s = s.substr(1);
      return true;
   
   return false;


bool P_Identifier(void) 
   if(P_Character()) 
      if(P_Identifier())
         return true;
      
      return true;
   
   return false;


bool P_Character(void)
   if ('a' <= s[0] && s[0] <= 'z') 
      s = s.substr(1);
      return true;
   
   return false;


bool P_Number(void) 
   if(P_Digit())
      if(P_Number())
         return true;
      
      return true;
   
   return false;


bool P_Digit(void)
   if ('0' <= s[0] && s[0] <= '9') 
      s = s.substr(1);
      return true;
   
   return false;

【问题讨论】:

预期的输出是什么,你会得到什么?此外,您还粘贴了大量代码。程序中是否有一个子部分显示出与您不符合预期的相同行为? Visual Studio 2012 有一个 XP 编译器,您可以免费下载。它可能是更新 1 的一部分。 那些函数名和变量名太可怕了。 您可以从更改while(input.good()) 开始。不要循环.good()。相反,它应该是while(getline(input, s))。这可能会改变行为。就像其他人所说的那样,您粘贴了很多代码,您在混淆方面做得很好,这使得它更难提供帮助。 您必须遵循良好的命名约定 【参考方案1】:

您的测试函数有副作用,并且您继续对全局字符串s 进行操作。您使用数组索引到字符串中而不检查它有多长。你几乎肯定会得到未定义的行为。这可能是您在平台之间出现差异的根源。

然而,真正的问题是您的代码不清楚,不值得弄清楚它的真正作用。

更新:

您说“没有打印错误”和“它没有输出”。由于代码块上的标准库行为不同,这可能就像不刷新 std::cout 一样简单。就像&lt;&lt; endl 到您的第一条消息的末尾一样,看看您是否获得了刷新的缓冲区。我关于您代码中未定义行为的其他 cmets 仍然适用,但如果您根本没有收到任何消息,这可能是第一个问题。

【讨论】:

【参考方案2】:

您编写的程序将接受此无效语句并将其称为有效:

a=(a7-62)^2

您不允许在标识符中使用数字,因此根据您的语法,该程序不是一个有效的程序。但是你的程序会接受它。

一旦您弄清楚它为什么会这样并解决了问题,您的程序可能会在不同平台上具有更可预测的行为。

【讨论】:

【参考方案3】:
bool A(void);
bool E(void);
bool T(void);
bool F(void);
bool P(void);
bool U(void);
bool I(void);
bool C(void);
bool L(void);
bool D(void);

没有。

【讨论】:

好吧,尽管我很想对此投赞成票,但我不能让自己这么做,因为这并不是问题的真正答案。这是非常正确的。 :-) 很遗憾“低质量帖子”审核任务没有“建议回答者改进答案”按钮。

以上是关于为啥我的 C++ 递归下降解析器只适用于几台计算机? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

递归下降解析器

当我们可以解析地解决线性回归时,为啥梯度下降

为啥 jQuery 选择器只选择特定网站上的第一个层次结构元素?

线性回归有解析解为啥还要用梯度下降

Atitit 表达式原理 语法分析 原理与实践 解析java的dsl  递归下降是现阶段主流的语法分析方法

为啥有些编译器更喜欢手工制作的解析器而不是解析器生成器?