1. 程式人生 > >PL/0詞法分析程式

PL/0詞法分析程式

  用C語言編寫一個PL/0詞法分析器,為語法語義分析提供單詞,使之能把輸入的字串形式的源程式分割成一個個單詞符號傳遞給語法語義分析,並把分析結果(基本字,運算子,識別符號,常數以及界符)輸出。

  PL/0的詞法分析程式GETSYM是一個獨立的過程,其功能是為語法語義分析提供單詞,把輸入的字串形式的源程式分割成一個個單詞符號傳遞給語法語義分析。其主要任務為:1、濾空格;2、識別基本字;3、識別識別符號;4、拼數;5、拼複合詞;6、輸出源程式。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

using namespace std;
char stayWord[13][15] = {"const","var","procedure","begin","end","odd","if","then","call","while","do","read","write"};
char enumStayWord[13][15] = {"constsym","varsym","proceduresym","beginsym","endsym","oddsym","ifsym","thensym",
                            "callsym","whilesym","dosym","readsym","writesym"};
bool isNumber(char ch);
bool isCase(char ch);
bool isCaculationSymbol(char ch);
bool isBandSymbol(char ch);
int isStayWord(char *str);
void getInputStreamFromFile(char *fileName,char *str);
void calulationString(char *str);
void bandString(char *str);
void Analysis(char *InputFileName,char *str);

int main()
{
    char strr[100000],input[100]="E:\\程式設計驗證\\input.txt";
    Analysis(input,strr);
    return 0;
}

bool isNumber(char ch){
    if(ch >='0' && ch <= '9') return true;
    return false;
}

bool isCase(char ch)
{
    if((ch >='a' && ch <='z') || (ch >= 'A'&& ch <='Z'))
        return true;
    return false;
}

bool isCaculationSymbol(char ch)
{
    if(ch == '+' || ch == '-' || ch == '/' || ch == '>' || ch == '<' || ch == '=' || ch == '#' || ch == ':')
        return true;
    return false;
}

bool isBandSymbol(char ch)
{
    if(ch == '(' || ch == ')'|| ch == ','|| ch ==';' || ch == '.')
        return true;
    return false;
}

int isStayWord(char *str)
{
     int i;
     for(i=0;i<13;++i){
            //printf("%s + !!\n",stayWord[i]);
        if(!strcmp(str,stayWord[i])) break;
     }
     return i;
}

void getInputStreamFromFile(char *fileName,char *str)
{
    char ch;
    int k=0;
    FILE *f;
    f = fopen(fileName,"r");
    while((ch=fgetc(f))!=EOF)
    {
        if(ch!='\n')
            str[k++] = ch;
        else
            str[k++]=' ';
    }
    str[k]='\0';
    fclose(f);
}

void calulationString(char *str)
{
    int len = strlen(str);
    int i;
    for(i=0;i<len;++i)
    {
        if(str[i] == '+') printf("  +  運算子/加號\n");
        else if(str[i] == '-') printf("  -  運算子/減號\n");
        else if(str[i] == '*') printf("  *  運算子/乘號\n");
        else if(str[i] == '/') printf("  /  運算子/除號\n");
        else if(str[i] == '=') printf("  =  運算子/等號\n");
        else if(str[i] == ':'){
            if(i+1<len && str[i+1] == '='){
                printf("  :=  運算子/賦值號\n");
                i++;
            }
            else
                printf("  %c  非法字元!\n",str[i]);
        }
        else if(str[i] == '#') printf("  #  運算子/不等於號\n");
        else if(str[i] == '>'){
            if(i+1<len && str[i+1] == '='){
                printf("  >=  邏輯運算子/大於等於號\n");
                i++;
            }
            else
                printf("  >  邏輯運算子/大於號\n");
        }
        else if(str[i] == '<'){
            if(i+1<len && str[i+1]=='='){
                printf("  <=  邏輯運算子/小於等於號\n");
                i++;
            }
            else
                printf("  <  邏輯運算子/小於號\n");;
        }
    }
}

void bandString(char *str)
{
    int len,i;
    len = strlen(str);
    for(i=0;i<len;++i)
    switch(str[i]){

       case '(': printf("  (  界符/左括號\n"); break;
       case ')': printf("  )  界符/右括號\n"); break;
       case ',': printf("  ,  界符/逗號\n"); break;
       case ';': printf("  ;  界符/分號\n"); break;
       case '.': printf("  .  界符/結束號\n"); break;
       default : break;
    }
}
void Analysis(char *InputFileName,char *str)
{
    getInputStreamFromFile(InputFileName,str);
    int len = strlen(str);
    int i,j,len1,len2,k,t,re;
    char str1[100],str2[100];
    i=0;
    while(i<len)
    {
        j=0;
        while(str[i] == ' '&& i<len) ++i;
        while(str[i] != ' '&& i<len) str1[j++] = str[i++];
        str1[j]='\0';
        len1 = strlen(str1);
        k=0;
        while(k<len1)
        {
            if(isCase(str1[k]))
            {
                t=0;
                while((!isCaculationSymbol(str1[k]))&&(!isBandSymbol(str1[k]))&&k<len1)
                    str2[t++] = str1[k++];
                str2[t]='\0';
                re = isStayWord(str2);
                if(re < 13)
                {
                    printf("  %s  基本字/%s\n",stayWord[re],enumStayWord[re]);
                    strcpy(str2,"");
                    t=0;
                }
                else
                {
                    printf("  %s  識別符號\n",str2);
                    strcpy(str2,"");
                    t=0;
                }
            }
            else if(isNumber(str1[k]))
            {
                while(isNumber(str1[k])&&k<len1)
                    str2[t++] = str1[k++];
                str2[t]='\0';
                printf("  %s  常數\n",str2);
                strcpy(str2,"");
                t=0;
            }
            else if(isCaculationSymbol(str1[k])){
                while(isCaculationSymbol(str1[k])&&k<len1)
                    str2[t++] = str1[k++];
                str2[t] = '\0';
                calulationString(str2);
                strcpy(str2,"");
                t=0;
            }
            else if(isBandSymbol(str1[k]))
            {
                while(isBandSymbol(str1[k]) && k<len1)
                    str2[t++] = str1[k++];;
                str2[t] = '\0';
                bandString(str2);
                strcpy(str2,"");
                t=0;
            }
            else{
                printf("  字串無法識別!\n"); k++;
            }
        }
        strcpy(str2,"");
    }
    fclose(stdout);
}
建立input.txt檔案,修改檔案路徑即可使用。