コンパイル原理PL0構文解析実験1

構文アナライザーと字句アナライザーの共通点

構文アナライザーはプッシュダウンオートマトンとも呼ばれ、字句アナライザーは有限オートマトンとも呼ばれます。

1.分析する単純言語の形態

同じ点:どちらも分析タイプコードです

違い:字句解析プログラムは、文字列内の単語のカテゴリコード(単語)を分析します

               パーサーは、文字列の文法が正しいかどうかを分析します(文)

分析する単純な言語の文法

BNF:(1)<プログラム> :: =begin<ステートメント文字列>end

          (2)<ステートメント文字列> ::=<ステートメント>{;<ステートメント>}

          (3)<ステートメント> ::=<割り当てステートメント>

          (4)<代入ステートメント> :: = ID:=<式>

          (5)<式> ::=<アイテム>{+<アイテム>|-<アイテム>}

         (6)<item> :: = <factor {* <factor> | / <factor>}

パーサーの機能

#記号で終わるC言語の文字列を入力します。文法的に正しい文の場合、プログラムは成功メッセージを出力します。文法的に正しくない文の場合、プログラムはエラーメッセージを出力し、エラーが発生した場所にプロンプ​​トを表示します。 。

正しい文法:BNF文法を開始しますend#

【例1】

文字列を指定して、構文が正しいかどうかを確認します。

入力:開始a:= 9; x:= 2 * 3; b:= a + x終了#

出力:成功!

入力:開始x:= a + b*c終了

出力:エラー!「終了」後のエラー

入力:開始x:= a + b * c

出力:エラー!「終わり」がありません

入力:x:= a + b * c end#

出力:エラー!行方不明の始まり

プログラム検証コード(パーサー)

#include <studio.h>
#include <string.h>
void scaner();
void sentence();
void statement();
void expression();
void term();
void factor();
char *key[0]={"begin","if","then","while","do","end"},ch[100];
int p=0,kk=0,q,syn;
int main()
{
    printf("输入:\n");
    gets(ch);
    sentence();
    return 0;
}

void scanner()
{
    char token[100] = {};
    q = 0;
    while(ch[p] == ' ') p++;
    if((ch[p] >= 'a' && ch[p] <= 'z')||(ch[p] >= 'A' && ch[p] <= 'Z')
    {
        token[q++] = ch[p];
        p++;
        while((ch[p] >= '0' && ch[p] <= '9')||(ch[p] >= 'a' && ch[p] <= 'z')
        ||(ch[p] >= 'A' && ch[p] <= 'Z')) token[q++] = ch[p++];
        syn = 10;
        token[q] = '\0';
        for(int n = 0;n < 6;n++)
        if(strcmp(token,key[n]) == 0)
        {
            syn = n + 1;
            break;
        }
    }
    else if(ch[p] >= '0' && ch[p] <= '9')
    {
        token[q++] = ch[p];
        p++;
        while(ch[p] >= '0' && ch[p] <= '9') token[q++] = ch[p++];
        syn = 11;
     }
    else switch(ch[p])
    {
        case '<':token[q++] = ch[p++];
        if(ch[p] == '>')
        {
            syn = 21;
            token[q++] = ch[p++];
        }
        else if(ch[p] == '=')
        {
            syn = 22;
            token[q++] = ch[p++];
        }
        else syn = 23;
        break;
        case '>':token[q++] = ch[p++];
        if(ch[p] == '>')
        {
            syn = 24;
            token[q++] = ch[p++];
        }
        else    syn = 20;
        break;
        case “:” :token[q++] = ch[p++];
        if(ch[p] == "="){
            syn = 18;
            token[q++] = ch[p++];
        }
        else syn = 17;
        token[q++] = ch[p++];
        break;    
        case '*':syn = 13;
        token[q++] = ch[p++];
        break;
        case '/':syn = 14;
        token[q++] = ch[p++];
        break;
        case '+':syn = 15;
        token[q++] = ch[p++];
        break;
        case '-':syn = 16;
        token[q++] = ch[p++];
        break;
        case '=':syn = 25;
        token[q++] = ch[p++];
        break;
        case ';':syn = 26;
        token[q++] = ch[p++];
        break;
        case '(':syn = 27;
        token[q++] = ch[p++];
        break;
        case ')':syn = 28;
        token[q++] = ch[p++];
        break;
        case '#':syn = 0;
        token[q++] = ch[p++];
        break;
        case '\n':syn = -2;
        break;
        default:syn = -1;
        break;
    }
}

void sentence()
{
    scaner();
    if(syn == 1)
    {
        statement();
        while(syn == 26) statement();
        if(syn == 6)
        {
           scaner();
           if(syn == 0) printf("成功!\n");
           else printf("错误!“end”后出错。\n");
        }
        else
        {
            printf("错误!缺少“end”。\n");
            kk = 1;
        }
    }
    else
    {
        printf("错误!缺少“begin”。\n");
        kk = 1;
    }
} 

void statement()
{
    scaner();
    if(syn == 10)
    {
        scaner();
        if(syn == 18)
        {
            scaner();
            expression();
        }
        else
        {
            printf("错误!“:=”出错。\n");
            kk = 1;
        }
    }
    else
    {
        printf("错误!句子出错。\n");
        kk = 1;
    }
    return;
}

void expression()
{
    term();
    while((syn == 13)||(syn == 14))
    {
        scaner();
        term();
    }
    return;
}

void term()
{
    factor();
    while((syn == 15)||(syn == 16))
    {
        scaner();
        factor();
    }
    return;
}


void factor()
{
    if((syn == 10)||(syn == 11)) scaner();
    else if(syn == 27)
    {
        scaner();
        expression();
        if(syn == 28) scaner();
        else
        {
            printf("错误!“(”出错。\n");
            kk = 1;
        }
    }
    else
    {
        printf("错误!\n");
        kk = 1;
    }
    return;
}

//begin a:=9;x:=2*3;b:=a+x end#
//begin x:a+b*c end

走る

文字列を入力してEnterキーを押すと、上記の例1の結果が出力されます。 

おすすめ

転載: blog.csdn.net/qq_44709970/article/details/121804295