为什么我的C ++递归下降解析器只适用于几台计算机?

时间:2013-03-25 05:45:13

标签: c++ windows-xp codeblocks

出于某种原因,我的程序似乎不适用于使用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;
}

3 个答案:

答案 0 :(得分:2)

您的测试功能有副作用,您继续操作全局字符串s。您可以将数组索引用于字符串而不检查它的长度。你几乎肯定会得到未定义的行为。这可能是平台之间变化的来源。

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

更新

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

答案 1 :(得分:1)

您编写的程序将接受此无效声明并将其命名为有效:

a=(a7-62)^2

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

一旦你弄明白为什么会这样做并解决问题,你的程序可能会在不同的平台上有更多可预测的行为。

答案 2 :(得分:-2)

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);

没有