Programming Language/C++2011. 9. 7. 00:54

 

  • Scanner.h

 

#pragma once

#include "global.h"

#include "Utility.h"

#include "TreeNode.h"

#define BUFLEN 500

 

class Scanner

{

        /*

 

        - 정규표현-> DFA 고안Scanner

        : -> 상태-(전이)-> 상태-(전이)-> 상태-(전이)-> 상태.....

 

        */

 

        // 식별자상태에대한Deterministic Finite Automation

        enum StateType {

               START,  // 시작상태

               INASSIGN, // 지정연산자: 시작상태에서; 입력에의해도착, 만약계속해서= 입력시지정연산 토큰이생성. (else 오류토큰)

               INCOMMENT, // 주석문: /*에의해서도착하여*/ 입력에의해서다시시작상태로반환됨

               INNUM,  // digit 측정

               INID,  // ID(영문자+ digit)scan. (식별자를찾음)

               DONE  // 모든인식상태는Done으로귀결

        } ;

public:

        Scanner(void);

        ~Scanner(void);

 

        int getNextChar(void);

 

        void ungetNextChar(void);

        TokenType getToken(void); // 입력문자를소비하여DFA에의해서인식되는다음토큰을반환.

 

 

        char lineBuf[BUFLEN]; /* holds the current line */

        int linepos; /* current position in LineBuf */

        int bufsize; /* current size of buffer string */

        bool EOF_flag; /* corrects ungetNextChar behavior on EOF */

 

};

 

 

 

  • Scanner.cpp

 

#include "Scanner.h"

 

Scanner::Scanner(void)

{

        linepos = 0;

        bufsize = 0;

        EOF_flag = false;

}

 

Scanner::~Scanner(void)

{

}

/******************************************************

getNextChar

- linebuf에서문자를읽어옴.

- getNextChar fetches the next non-blank character

from lineBuf, reading in a new line if lineBuf is

exhausted

*******************************************************/

int Scanner::getNextChar(void)

{

        if (!(linepos < bufsize))

        {

               lineno++;

               if (fgets(lineBuf,BUFLEN-1,fSource)) // fSource 파일에서읽어서버퍼를채움.

               {

                       if (EchoSource) fprintf(fListing,"%4d: %s",lineno,lineBuf);

                       bufsize = strlen(lineBuf);

                       linepos = 0;

                       return lineBuf[linepos++];

               }

               else

               {

                       EOF_flag = true;

                       return EOF;

               }

        }

        else return lineBuf[linepos++];

}

 

/******************************************************

ungetNextChar

- linebuf에서문자를읽어옴.

*******************************************************/

void Scanner::ungetNextChar(void) {

        if (!EOF_flag) linepos-- ;

}

 

/************* GetToken() *****************************

- 입력문자를소비하여DFA에의해서인식되는다음토큰을반환.

- case1 : DFA에따른automata 상태,

- case2 : 현재입력문자처리.

- START,  // 시작상태

INASSIGN, // 지정연산자: 시작상태에서; 입력에의해도착, 만약계속해서= 입력시지정연산 토큰이생성. (else 오류토큰)

INCOMMENT, // 주석문: /*에의해서도착하여* / 입력에의해서다시시작상태로반환됨

INNUM,  // digit 측정

INID,  // ID(영문자+ digit)scan. (식별자를찾음)

DONE  // 모든인식상태는Done으로귀결

*******************************************************/

TokenType Scanner::getToken(void) //

{

        /* index for storing into tokenString */

        int tokenStringIndex = 0;

        /* holds current token to be returned */

        TokenType currentToken;

        /* current state - always begins at START */

 

        StateType state = START;

        bool save; // 문자가tokenString에추가될지의여부를나타냄(빈칸, 주석문, \\등의비소비문자등이포함되지않도록하는데필요)

        while (state != DONE)

        { int c = getNextChar();

        save = true;

        switch (state)

        { case START:

        if (isdigit(c))

               state = INNUM;

        else if (isalpha(c))

               state = INID;

        else if (c == ':')

               state = INASSIGN;

        else if ((c == ' ') || (c == '\t') || (c == '\n'))

               save = false;

        else if (c == '{')

        { save = false;

        state = INCOMMENT;

        }

        else

        { state = DONE;

        switch (c)

        { case EOF:

        save = false;

        currentToken = END_FILE;

        break;

        case '=':

               currentToken = EQ;

               break;

        case '<':

               currentToken = LT;

               break;

        case '+':

               currentToken = PLUS;

               break;

        case '-':

               currentToken = MINUS;

               break;

        case '*':

               currentToken = TIMES;

               break;

        case '/':

               currentToken = OVER;

               break;

        case '(':

               currentToken = LPAREN;

               break;

        case ')':

               currentToken = RPAREN;

               break;

        case ';':

               currentToken = SEMI;

               break;

        default:

               currentToken = TYPE_ERROR;

               break;

        }

        }

        break;

        case INCOMMENT:

               save = false;

               if (c == EOF)

               { state = DONE;

               currentToken = END_FILE;

               }

               else if (c == '}') state = START;

               break;

        case INASSIGN:

               state = DONE;

               if (c == '=')

                       currentToken = ASSIGN;

               else

               { /* backup in the input */

                       ungetNextChar();

                       save = false;

                       currentToken = TYPE_ERROR;

               }

               break;

        case INNUM:

               if (!isdigit(c))

               { /* backup in the input */

                       ungetNextChar();

                       save = false;

                       state = DONE;

                       currentToken = NUM;

               }

               break;

        case INID:

               if (!isalpha(c))

               { /* backup in the input */

                       ungetNextChar();

                       save = false;

                       state = DONE;

                       currentToken = ID;

               }

               break;

        case DONE:

        default: /* should never happen */

               fprintf(fListing,"Scanner Bug: state= %d\n",state);

               state = DONE;

               currentToken = TYPE_ERROR;

               break;

        }

        if ((save) && (tokenStringIndex <= MAXTOKENLEN))

               tokenString[tokenStringIndex++] = (char) c;

        if (state == DONE)

        { tokenString[tokenStringIndex] = '\0';

        if (currentToken == ID)

               ;//   currentToken = reservedLookup(tokenString);

        }

        }

        if (TraceScan) {

               fprintf(fListing,"\t%d: ",lineno);

               // printToken(currentToken,tokenString);

        }

        return currentToken;

}

 

Posted by BLUE-NOTE