2013-02-07 4 views
0

나는,어휘 분석기 사용하여 C++

나는 확신 파일을 구문 분석하고 그냥 토큰, 어휘를 표시하는 어휘 분석기를 코딩하고 가치/문자 평가자/경우 (INT, 부동 또는 문자) 한 분석기의 작동에 대한 코드 그러나 나는 그것은 다음과 같은 방법으로 출력을 표시합니다 displaytoken 아래로 쓸 수 없습니다 : 문자

토큰 어휘 값/평가자/

NUMT 1234 값

를 내가 이 공동있다. 드 샘플 다음 lexical.cpp에 대한

#include <cstdlib> 
#include <iostream> 
#include <fstream> 
#include <string> 
#include <cstring> 

#include "lexical.h" 


int value ; // integer 
float valuer ; // float 
char ch ; // character 
string lexeme ; // string 
SYMBOL Token ; // token of symbols 
string Literal ; // string literals 

string reswords[15] ; // reserved words 

using namespace std; 


//constructor 

Lexical::Lexical() 
{ 

} 

//destructor 

Lexical::~Lexical() 
{ 





} 

void Lexical::GetNextToken() 
{ 
      // getting the lexeme ******************* 
      // ************************************** 

      value = 0 ; 
      valuer = 0.0 ; 

      int i = 1 ; // line tracker 

      while(!(fin.eof())) 
      { 
       lexeme[i] = ch ; 
       fin.get(ch); 
      } 

      if(fin.peek() == '\n') 
      { 
       i++ ; // increment the line ! 
      } 
      if(!fin.eof()) 
      { 
       ProcessToken() ; 
      } 
      else 
      { 
       fin.close() ; 
       Token = eofilet ; // set to end of file 
      } 





    } 







//rules not implemented yet 
void Lexical::displayToken() 
{ 
    cout << "Token" << "   " << "Lexeme" << "   " << " value/valuer/Literal " << endl ; 

    cout << Token << "   " << lexeme << "   " << value ; 

} 



//initialize reserved words 
void Lexical::InitResWords() 
{ 
    reswords[begint].copy("BEGIN",5,0); 
    reswords[programt].copy("PROGRAM",7,0); 
    reswords[constt].copy("CONST",5,0); 
    reswords[vart].copy("VAR",3,0); 
    reswords[proceduret].copy("PROCEDURE",9,0); 
    reswords[ift].copy("IF",2,0); 
    reswords[whilet].copy("WHILE",5,0); 
    reswords[thent].copy("THEN",4,0); 
    reswords[elset].copy("ELSE",4,0); 
    reswords[realt].copy("REAL",4,0); 
    reswords[integert].copy("INTEGER",7,0); 
    reswords[booleant].copy("BOOLEAN",7,0); 
    reswords[chart].copy("CHAR",4,0); 
    reswords[arrayt].copy("ARRAY",5,0); 
    reswords[endt].copy("END",3,0); 
} 

void Lexical::ProcessToken() 
{ 
    lexeme.at(0) = ch ; // 1 character at a time 
    fin.get(ch) ; 

    if((lexeme.at(0) >= 'A' && lexeme.at(0) <= 'Z') || (lexeme.at(0) >= 'a' && lexeme.at(0) <= 'z')) // if alphabets 
    { 
     int counter = 0 ; 
     //match word token 
      if(!isdigit(lexeme.at(0)) && !isalpha(lexeme.at(0)) && lexeme.at(0) != '_') 
      { 
      //*********** Working with reserved words !!! ************************************************** 
         int j = 0 ; 
         bool flag = false ; 
         while(j < endt) 
          { 
           if(lexeme.compare(reswords[j]) == 0) 
           { 
            Token = (SYMBOL)j; 
            displayToken(); 
            flag = true ; 
           } 
          }  
      //********************************************************************************************** 

      // if not a token , then we are alrea 
         Token = idt ;// then an identifier token 
         displayToken(); 
         return ; 
      }// if ends 

      lexeme.at(counter) = ch ;// keep proceeding 
      fin.get(ch) ; 
    } 
    else if (lexeme.at(0) >= '0' && lexeme.at(0) <= '9') // if numbers 
    { 
     NumToken() ; 
    } 
    else if (lexeme.at(0) == '\"') // for string literal 
    { 
     ProcessLiteralToken(); 
    } 
    else if (lexeme.at(0) == '/') // entering comment section 
     { 
       if (ch == '/' || ch == '*') 
       { 
         // MatchComment(); 
         if (ch == '/') // start of a comment maybe ? 
          { 
          //Line comment 
           while(ch != '\n') 
           fin.get(ch); 
          } 
         else if(ch == '*') // end of a comment ? 
          { 
            while(true) 
           { 
            fin.get(ch); 
            if (ch == '*') 
            { 
             char peek_value = fin.peek(); 
             if (peek_value == '/') 
              { 
               fin.get(ch); 
              // fin.get(ch); 
               return; 
              } 
             else 
              continue; 
            } 
           } // while ends 
          } 
         else 
          { 
          cout << "ERROR !!!" ; 
          } 

         GetNextToken(); 
         } // comment analyzer then moves to next token ! 
       else 
       { 
        OpToken(); 
       } 
     } 
    else if ((lexeme.at(0) == '<') || (lexeme.at(0) == '>') || (lexeme.at(0) == '=')) 
     { 
     if (ch == '=') 
      { 
      lexeme.at(1) = ch; 
      Token = relop ; 
      fin.get(ch); 
      } 
     else 
      OpToken() ; // process the final token 
     } 
    else if ((lexeme.at(0)) == ':') 
     { 
      if (ch == '=') 
      { 
      lexeme.at(1) = ch; 
      Token = relop ; 
      fin.get(ch); 
      } 
    } 
    else 
    OpToken(); 
} 
void Lexical::OpToken() 
{ 
    //Need to detect +, -, ||, *, /, &&, =,(), {}, comma, semicolon, period, quotation("), and [] 
if(lexeme.at(0) == '+' || lexeme.at(0) == '-' || lexeme.at(0) == 'OR') 
     { 
      Token = addop ; 
      return; 
     } 
else if(lexeme.at(0) == '*' || lexeme.at(0) == '/' || lexeme.at(0) == 'DIV' || lexeme.at(0) == 'MOD' || lexeme.at(0) == 'AND') 
    { 
     Token = mulop ; 
     return; 
    } 
else if(lexeme.at(0) == '<' || lexeme.at(0) == '>' || lexeme.at(0) == '=') 
    { 
     Token = relop ; 
     return; 
    } 
else if(lexeme.at(0) == '(') 
    { 
     Token = lparen; 
     return; 
    } 
else if(lexeme.at(0) == ')') 
    { 
     Token = rparen; 
     return; 
    } 
else if(lexeme.at(0) == '{') 
    { 
     Token = clbrat; 
     return; 
    } 
else if(lexeme.at(0) == '}') 
    { 
     Token = crbrat; 
     return; 
    } 
else if(lexeme.at(0) == ',') 
    { 
     Token = comma; 
     return; 
    } 
else if(lexeme.at(0) == ';') 
    { 
     Token = semicolon ; 
     return; 
    } 
else if(lexeme.at(0) == '.') 
    { 
     Token = period ; 
     return; 
    } 
else if(lexeme.at(0) == '~') 
    { 
     Token = tildat; 
     return; 
    } 
else if(lexeme.at(0) == '[') 
    { 
     Token = lbrat; 
     return; 
    } 
else if(lexeme.at(0) == ']') 
    { 
     Token = rbrat; 
     return; 
    } 
else if(lexeme.at(0) == '#') 
    { 
     Token = nott ; 
     return; 
    } 

else 
    { 
    Token = unknownt ; 
    cout << "Error !!" ; 
    exit(0); 
    } 
} 

void Lexical::NumToken() 
{ 
int i = 0; 
    while (isdigit(ch)) 
    { 
    //Update Lexeme and keep going 
    lexeme.at(i++) = ch; 
    fin.get(ch); 
    } 

    if (ch == '.') // checking for float 
    { 
    //if ch is a period, then we might be dealing with a float. We need to ensure that the next character is a digit 
    lexeme.at(i++) = ch; 
    fin.get(ch); 
    if (isdigit(ch)) 
    { 
     //ch is a digit, so we are good to go. 
     while (isdigit(ch)) 
     { 
     lexeme.at(i++) = ch; 
     fin.get(ch); 
     } 
     //If we are here, then we have a float and we have just encountered a new token 
     Token = numt; 
     valuer = atof(lexeme.c_str()); 
     return; 
    } 
    //If we are here, then we have a period but no digit after it--an error 
    Token = unknownt ; 
    cout << "Error." << endl; 
    exit(0); 
    } 
    else { 
    //If we are here, then it means that the next char is not a period.... so we have a NUMT int token 
    Token = numt; 
    value = atoi(lexeme.c_str()); 
    return; 
    } 

} 

void Lexical::ProcessLiteralToken() 
{ 

    int i = 0; 
    while (ch != '\"') 
    { 
    if (ch == '\n') 
    { 
     Token = unknownt ; 
     cout << "Error!" << endl ; 
     exit(0); 
    } 
    Literal.at(i++) = ch ; // advance ! 
    fin.get(ch); 
    } 
    //Literal[i++] = ch; 
    Token = literalt; 
    fin.get(ch); 
    return; 




} 

내 lexical.h (헤더 파일)이 있습니다 파일 :

#ifndef _LEXICAL_H 
#define _LEXICAL_H 

#include <iostream> 
#include <fstream> 


using namespace std ; 


      // enumerated data type 
      enum SYMBOL 
      { 
       begint,programt, constt, vart, proceduret, ift, whilet, thent, elset, realt, integert, booleant, chart, arrayt, endt, divt, modt, andt, nott, ort, addop, mulop, assignop, lparen, rparen, comma, semicolon, period, numt, idt, literalt, unknownt, eofilet, relop, clbrat, crbrat, tildat, lbrat, rbrat ,colon 
      }; 

      //extern int size = 15 ; 
      extern int value ; // integer 
      extern float valuer ; // float 
      extern char ch ; // character 
      extern string lexeme ; // string 
      extern SYMBOL Token ; // token of symbols 
      extern string Literal ; // string literals 
      extern string reswords[15] ; // string array 

class Lexical { 

     public : 

      Lexical(); // constructor 

      ~Lexical() ; // destructor 

      //GetNextToken function 
      void GetNextToken() ; 

      //displayToken function 
      void displayToken() ; 




     private : 

      //initialize reserved words 
      void InitResWords() ; 

      //ProcessToken 
      void ProcessToken() ; 

      // operator tokens 
      void OpToken() ; 

      //NumToken 
      void NumToken() ; 

      //Process string literals 
      void ProcessLiteralToken() ; 

      ifstream fin ; // file 

} ; 


#endif // !_lexical_H 

코드는 사람이 어떤 기능을 위해, 그것을 통해 가고 싶은 경우에 제공합니다.

내 토큰을 올바르게 표시하는 방법을 알 수 없습니다. (displayToken) 어떤 사람이 함수를 도와 줄 수 있습니다. 따라서 모든 토큰에 대해 구문 분석하여 다음 형식으로 표시합니다. 토큰 ----- Lexeme ------- 값/가치/리터럴 numt ----- 1234 ------ 값

그냥 디스플레이 토큰 기능을 기록하고 싶습니다. 어휘, 토큰 및 각 토큰을 처리 한 후 값/값 또는 리터럴인지 여부를 어떻게 표시 할 것입니까?

이 내 드라이버 파일

#include "lexical.h" 

#include <iostream> 
#include <fstream> 

using namespace std; 

int main() 
{ 
    cout << "creating the constructor" << endl << endl ; 
    Lexical myLex ; 
    ifstream fin; 

    fin.open("test.txt") ; 

    while (Token != eofilet) 
    { 
     myLex.GetNextToken(); 
     myLex.displayToken(); 
    } 

    cout << endl << "success" << endl ; 
    fin.close(); 
    //system("pause"); 
    return 0; 

} 
+2

어떤 문제가 있습니까? 너 뭐 해봤 니? –

+0

디버깅을 시도 했습니까? – neagoegab

+0

원하는 출력을 얻기 위해 내 디스플레이 토큰 기능을 보낼 위치를 파악할 수 없습니다! @sftrabbit – thestralFeather7

답변

2

당신은 '\ n을'훔쳐, 당신은 그 문자를 소비 어디 볼 ​​수 없습니다입니다. 워스는 파스칼 예에서했던 방법

간단한 렉서/파서를 구현하는 가장 간단한 방법입니다 (여기서, 미안 기억하지 않는다) :

  • 당신은 항상 문자 내다가, 당신은 하나 개의 문자로 읽기 (귀하의 생성자에서) 처음에 미리보기
  • 토큰을 처리하기 시작할 때마다 미리보기 문자를보고 무엇에 따라 달라지는 지 결정하십시오 (예 : 숫자 -> 숫자, 문자 -> (임시) 식별자, ...). 공백을 건너 뛰려면 ''(또는 '\ t')가 아닐 때까지 다음 문자를 읽은 다음, '\ n'으로 계산 한 행을 세고 다음 문자를 읽습니다.
  • 문자가 필요할 때마다 미리보기를 사용하고 다음 문자를 가져옵니다.

파서 (재귀 적 디센트)는 lookahead 토큰에 대한 변수를 가지며 비슷한 선을 따라 작업했습니다.

이 방법을 사용하면 들여다 보거나 문자를 읽을 때 혼란스러워 할 필요가 없습니다.