算符優先分析過程 編譯原理

算符優先分析過程只考慮算符(終結符)之間的優先關係,分析掃描每個規約式的算符間優先關係。

根據龍書闡述,算符優先分析逐漸淘汰了。orz

但仍然實現之。

示例語法如下:

D->#E#
E->E+T|T
T->T*F|F
F->P$F|P
P->(E)|i

 

main.cpp

#include <iostream>

#include <vector>

#include "grammerin.h"
#include "calculatepriortable.h"
#include "analy.h"
using namespace std;

int main()
{
    vector<vector<char> > sign;
    cout<<"讀入語法規則:"<<endl;
    sign=readGrammer();
    /*
    for(int i=0;i<2;++i)
    {
        for(int j=0;j<sign[i].size();++j)
            cout<<sign[i][j]<<" ";
        cout<<endl;
    }
    */
    vector<vector<vector<char> > > vvvc;
    vvvc = createfirstandfollow(sign);
    vector<vector<char> > priortable;
    priortable=createtable(vvvc);

    while(true)
    {
        cout<<endl<<"input: ";
        string s;
        cin>>s;
        inStringAnalyze(s,priortable);
    }
    return 0;
}

 

grammerin.cpp:

#ifndef GRMMERIN_H
#define GRMMERIN_H
#include <vector>
using namespace std;
vector< vector<char> > readGrammer();
vector< vector<char> > readGrammerWithNoPrint();
vector<string> getgrammer();
#endif

grammerin.h:

#include <iostream>
#include <sstream>
#include <string>
#include <fstream>
#include <cstdlib>
#include <vector>
#include <cctype>
#include <algorithm>
#include <map>
#include <set>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstdlib>
#include <ctime>

using namespace std;

vector< vector<char> > readGrammer()
{


    vector<char> terminatesign,unterminatesign;
    string s,grammer;

    ifstream in("C:\\Users\\lsy\\Desktop\\grammer1.txt");
    if (! in.is_open())
    { cout << "Error opening file"; exit (1); }
    while (!in.eof() )
    {
        char lin[100];
        //in.getline(buffer);
        in.getline(lin,100);
        s+=lin;
        grammer+=s+"\n";

        //cout <<s<< endl;
        int k=s.find_first_of("->");
        for(int i=0;i<k;++i)
        {
            //cout<<s[i]<<endl;
            vector<char>::iterator result = find(unterminatesign.begin(),unterminatesign.end(),s[i]);
            if(result==unterminatesign.end())
                unterminatesign.push_back(s[i]);
        }
        for(int i=k+2;i<s.size();++i)
        {
            //cout<<s[i]<<endl;
            if((s[i]>='A'&&s[i]<='Z')||s[i]==' '||s[i]=='|')
                ;
            else
            {
                vector<char>::iterator result = find(terminatesign.begin(),terminatesign.end(),s[i]);
                if(result==terminatesign.end())
                    terminatesign.push_back(s[i]);
            }
        }

        s="";
    }
    cout<<grammer;
    cout<<endl<<"·ÇÖÕ½á·û£º"<<endl;
    for(int i=0;i<unterminatesign.size();++i)
        cout<<unterminatesign[i]<<" ";
    cout<<endl;
    cout<<"ÖÕ½á·û£º"<<endl;
    for(int i=0;i<terminatesign.size();++i)
        cout<<terminatesign[i]<<" ";
    cout<<endl;
    vector<vector<char> > returnvector;
    returnvector.push_back(unterminatesign);
    returnvector.push_back(terminatesign);
    return returnvector;
}

vector< vector<char> > readGrammerWithNoPrint()
{
    //system("chcp 65001");

    vector<char> terminatesign,unterminatesign;
    string s,grammer;

    ifstream in("C:\\Users\\lsy\\Desktop\\grammer1.txt");
    if (! in.is_open())
    { cout << "Error opening file"; exit (1); }
    while (!in.eof() )
    {
        char lin[100];
        //in.getline(buffer);
        in.getline(lin,100);
        s+=lin;
        grammer+=s+"\n";

        //cout <<s<< endl;
        int k=s.find_first_of("->");
        for(int i=0;i<k;++i)
        {
            //cout<<s[i]<<endl;
            vector<char>::iterator result = find(unterminatesign.begin(),unterminatesign.end(),s[i]);
            if(result==unterminatesign.end())
                unterminatesign.push_back(s[i]);
        }
        for(int i=k+2;i<s.size();++i)
        {
            //cout<<s[i]<<endl;
            if((s[i]>='A'&&s[i]<='Z')||s[i]==' '||s[i]=='|')
                ;
            else
            {
                vector<char>::iterator result = find(terminatesign.begin(),terminatesign.end(),s[i]);
                if(result==terminatesign.end())
                    terminatesign.push_back(s[i]);
            }
        }

        s="";
    }
    vector<vector<char> > returnvector;
    returnvector.push_back(unterminatesign);
    returnvector.push_back(terminatesign);
    return returnvector;
}


vector<string> getgrammer()
{
    string s;
    vector<string> vv;
    ifstream in("C:\\Users\\lsy\\Desktop\\grammer1.txt");
    if (! in.is_open())
    { cout << "Error opening file"; exit (1); }
    while (!in.eof() )
    {
        char lin[100];
        //in.getline(buffer);
        in.getline(lin,100);
        s+=lin;
        //cout<<s.find_first_of("|")<<"  "<<s.size()<<endl;

        while(s.find_first_of("|")<=s.size()&&s.find_first_of("|")>=0)
        {
            //cout<<s.find_first_of("|")<<"  "<<s.size()<<"  "<<s<<endl;
            int a=s.find_first_of("->");
            int b=s.find_first_of("|");
            //cout<<a<<"  "<<b<<" "<<s<<endl;
            string ss="";
            ss+=s[0];
            ss+="->";
            ss+=s.substr(a+2,b-a-2);
            //cout<<ss<<"  "<<s<<endl;
            s.erase(a+2,b-a-1);
            //cout<<ss<<"  "<<s<<endl;
            vv.push_back(ss);
        }
        vv.push_back(s);
        s="";
    }
    /*
    cout<<endl;
    for(int i=0;i<vv.size();++i)
    {
        cout<<vv[i]<<endl;
    }
    */
    return vv;
}

calculatepriortable.h

#ifndef CALCULATEPRIORTABLE_H
#define CALCULATEPRIORTABLE_H
#include <vector>
using namespace std;
vector<vector<vector<char> > > createfirstandfollow(vector< vector<char> > sign);
vector<vector<char> > createtable(vector<vector<vector<char> > > vvvc);
#endif

calculatepriortable.cpp

#include <iostream>
#include <sstream>
#include <string>
#include <fstream>
#include <cstdlib>
#include <vector>
#include <cctype>
#include <algorithm>
#include <map>
#include <set>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <set>
#include <map>
#include "grammerin.h"
using namespace std;

vector<char> findUnterminateSignsFirstav(char c,vector<string> grammer,vector<char>& result)
{
    for(int i=0;i<grammer.size();++i)
    {
        if(grammer[i][0]==c)
        {
            int a=grammer[i].find_first_of("->");
            a+=2;
            if(grammer[i][a]>='A'&&grammer[i][a]<='Z')
                findUnterminateSignsFirstav(c,grammer,result);
            else
            {
                vector<char>::iterator res = find(result.begin(),result.end(),grammer[i][a]);
                if(res==result.end())
                    result.push_back(grammer[i][a]);
                else
                    ;
            }
        }
    }
}

vector<vector<vector<char> > > createfirstandfollow(vector< vector<char> > sign)
{
    /*
    cout<<sign.size()<<endl;
    for(int i=0;i<2;++i)
    {
        for(int j=0;j<sign[i].size();++j)
            cout<<sign[i][j]<<" ";
        cout<<endl;
    }
    */
    vector<vector<char> > signtable;
    vector<char> v;
    for(int i=0;i<20;++i)
        v.push_back(' ');
    for(int i=0;i<20;++i)
        signtable.push_back(v);
    vector<string> grammer;
    grammer=getgrammer();

    cout<<endl<<"讀入語法:"<<endl;
    for(int i=0;i<grammer.size();++i)
        cout<<grammer[i]<<endl;
    cout<<endl;
    vector<vector<char> > firstav,followav;
    map<char,set<char> > ufirstav,ufollowav;

//構造firstav數組
    for(int i=0;i<grammer.size();++i)
    {
        char c=grammer[i][0];
        int a=grammer[i].find_first_of("->");
        a+=2;
        //cout<<grammer[i]<<" "<<grammer[i][a]<<endl;
        if(grammer[i][a]>='A'&&grammer[i][a]<='Z')
        {
            int flag3=0;
            for(int j=0;j<firstav.size();++j)
            {
                if(firstav[j][0]==c)
                {
                    flag3=1;
                    break;
                }
            }
            if(flag3==0)
            {
                vector<char> v;
                v.push_back(c);
                if((a+1)<grammer[i].size())
                {
                    if(grammer[i][a+1]>='A'&&grammer[i][a+1]<='Z')
                        ;
                    else
                        v.push_back(grammer[i][a+1]);
                }
                //v.push_back(grammer[i][a]);
                firstav.push_back(v);
            }
            /*
            vector<char> result;
            findUnterminateSignsFirstav(c,grammer,result);
            cout<<"---"<<endl;
            for(int i=0;i<result.size();++i)
                cout<<result[i]<<" ";
            cout<<"---"<<endl;
            */

            map<char,set<char> >::iterator iter = ufirstav.find(c);
            if(iter!=ufirstav.end())
            {
                ufirstav[c].insert(grammer[i][a]);
            }
            else
            {
                set<char> sc;
                sc.insert(grammer[i][a]);
                ufirstav[c]=sc;
            }

        }
        else
        {

            int k=1;
            for(int j=0;j<firstav.size();++j)
            {
                //cout<<"---"<<endl;
                if(firstav[j][0]==c)
                {
                    firstav[j].push_back(grammer[i][a]);
                    --k;
                    break;
                }
            }
            if(k)
            {
                vector<char> v;
                v.push_back(c);
                v.push_back(grammer[i][a]);
                firstav.push_back(v);
            }
        }
    }
        int flag;
        L1:
        flag=1;
        //從非終結符集合向終結符集合加入元素
        for(map<char,set<char> >::iterator iter=ufirstav.begin();iter!=ufirstav.end();++iter)
        {
            char c=iter->first;
            //cout<<endl<<c<<endl;
            int csite;
            int ssite;
            //找到目的位置
            for(int i=0;i<firstav.size();++i)
            {
                if(c==firstav[i][0])
                {
                    csite=i;
                    break;
                }
            }
            for(set<char>::iterator itera=(iter->second).begin();itera!=(iter->second).end();++itera)
            {

                //找到源位置
                for(int i=0;i<firstav.size();++i)
                {
                    if((*itera)==firstav[i][0])
                    {
                        ssite=i;
                        break;
                    }
                }//cout<<"------------"<<endl;
                //源數組掃描
                for(int i=1;i<firstav[ssite].size();++i)
                {
                    int flag2=1;
                    //比較源數組某一位和目的數組各位是否有相同元素
                    for(int j=1;j<firstav[csite].size();++j)
                    {
                        if(firstav[ssite][i]==firstav[csite][j])
                        {
                            flag2=0;
                            break;
                        }
                    }
                    if(flag2)
                    {
                        firstav[csite].push_back(firstav[ssite][i]);
                        flag=0;
                    }
                }
            }
        }
        if(flag==0)
            goto L1;
        /*
        cout<<endl;
        for(int i=0;i<firstav.size();++i)
        {
            cout<<firstav[i][0]<<" : ";
            for(int j=1;j<firstav[i].size();++j)
            {
                cout<<firstav[i][j]<<" ";
            }
            cout<<endl;
        }
        */

    cout<<"firstav: "<<endl;
    for(int i=0;i<firstav.size();++i)
    {
        cout<<firstav[i][0]<<" : ";
        for(int j=1;j<firstav[i].size();++j)
        {
            cout<<firstav[i][j]<<" ";
        }
        cout<<endl;
    }
    /*
    cout<<endl<<"U:"<<endl;
    //map<char,set<char> >::iterator iter;
    for(map<char,set<char> >::iterator iter=ufirstav.begin();iter!=ufirstav.end();++iter)
    {
        cout<<(iter->first)<<" : ";
        for(set<char>::iterator itera=(iter->second).begin();itera!=(iter->second).end();++itera)
        {
            cout<<*itera<<" ";
        }
        cout<<endl;
    }
    */
//構造followav數組
    for(int i=0;i<grammer.size();++i)
    {
        char c=grammer[i][0];
        //cout<<c<<"  "<<grammer[i][grammer[i].size()-1]<<endl;
        if(grammer[i][grammer[i].size()-1]>='A'&&grammer[i][grammer[i].size()-1]<='Z')
        {
            int flag3=0;
            for(int j=0;j<followav.size();++j)
            {
                if(followav[j][0]==c)
                {
                    flag3=1;
                    break;
                }
            }
            if(flag3==0)
            {
                vector<char> v;
                v.push_back(c);
                if(grammer[i][grammer[i].size()-2]>='A'&&grammer[i][grammer[i].size()-2]<='Z')
                        ;
                else
                {
                    int y=grammer[i].find_first_of("->");
                    y+=2;
                    if((grammer[i].size()-2)>=y)
                        v.push_back(grammer[i][grammer[i].size()-2]);
                }
            followav.push_back(v);
            }
            /*
            for(int o=0;o<v.size();++o)
                    cout<<"---"<<v[o];
                cout<<endl;
                */
            map<char,set<char> >::iterator iter = ufollowav.find(c);
            //cout<<endl<<grammer[i];
            if(iter!=ufollowav.end())
            {
                //cout<<c<<" - - "<<grammer[i][grammer[i].size()-1]<<endl;
                ufollowav[c].insert(grammer[i][grammer[i].size()-1]);
            }
            else
            {
                //cout<<c<<" -- -- "<<grammer[i][grammer[i].size()-1]<<endl;
                set<char> sc;
                sc.insert(grammer[i][grammer[i].size()-1]);
                ufollowav[c]=sc;
            }

        }
        else
        {
            int k=1;
            for(int j=0;j<followav.size();++j)
            {
                //cout<<"---"<<endl;
                if(followav[j][0]==c)
                {
                    followav[j].push_back(grammer[i][grammer[i].size()-1]);
                    --k;
                    break;
                }
            }
            if(k)
            {
                vector<char> v;
                v.push_back(c);
                v.push_back(grammer[i][grammer[i].size()-1]);
                followav.push_back(v);

            }
        }
    }



        L2:
        flag=1;
        //從非終結符集合向終結符集合加入元素
        for(map<char,set<char> >::iterator iter=ufollowav.begin();iter!=ufollowav.end();++iter)
        {
            char c=iter->first;
            //cout<<endl<<c<<endl;
            int csite;
            int ssite;
            //找到目的位置
            for(int i=0;i<followav.size();++i)
            {
                if(c==followav[i][0])
                {
                    csite=i;
                    break;
                }
            }
            for(set<char>::iterator itera=(iter->second).begin();itera!=(iter->second).end();++itera)
            {

                //找到源位置
                for(int i=0;i<followav.size();++i)
                {
                    if((*itera)==followav[i][0])
                    {
                        ssite=i;
                        break;
                    }
                }
                //源數組掃描
                for(int i=1;i<followav[ssite].size();++i)
                {
                    int flag2=1;
                    //比較源數組某一位和目的數組各位是否有相同元素
                    for(int j=1;j<followav[csite].size();++j)
                    {
                        if(followav[ssite][i]==followav[csite][j])
                        {
                            flag2=0;
                            break;
                        }
                    }
                    if(flag2)
                    {
                        followav[csite].push_back(followav[ssite][i]);
                        flag=0;
                    }
                }
            }
        }
        if(flag==0)
            goto L2;



    cout<<endl<<"followav: "<<endl;
    for(int i=0;i<followav.size();++i)
    {
        cout<<followav[i][0]<<" : ";
        for(int j=1;j<followav[i].size();++j)
        {
            cout<<followav[i][j]<<" ";
        }
        cout<<endl;
    }
    /*
    cout<<endl<<"U:"<<endl;
    //map<char,set<char> >::iterator iter;
    for(map<char,set<char> >::iterator iter=ufollowav.begin();iter!=ufollowav.end();++iter)
    {
        cout<<(iter->first)<<" : ";
        for(set<char>::iterator itera=(iter->second).begin();itera!=(iter->second).end();++itera)
        {
            cout<<*itera<<" ";
        }
        cout<<endl;
    }
    */
    vector<vector<vector<char> > > ret;
    ret.push_back(firstav);
    ret.push_back(followav);
    return ret;
}



vector<vector<char> > createtable(vector<vector<vector<char> > > vvvc)
{
    vector<vector<char> > firstav,followav;
    firstav=vvvc[0];
    followav=vvvc[1];
    /*
    cout<<"firstav: "<<endl;
    for(int i=0;i<firstav.size();++i)
    {
        cout<<firstav[i][0]<<" : ";
        for(int j=1;j<firstav[i].size();++j)
        {
            cout<<firstav[i][j]<<" ";
        }
        cout<<endl;
    }

    cout<<endl<<"followav: "<<endl;
    for(int i=0;i<followav.size();++i)
    {
        cout<<followav[i][0]<<" : ";
        for(int j=1;j<followav[i].size();++j)
        {
            cout<<followav[i][j]<<" ";
        }
        cout<<endl;
    }
    */
    vector<char> terminatesign= readGrammerWithNoPrint()[1];
    /*
    for(int i=0;i<terminatesign.size();++i)
        cout<<terminatesign[i]<<"  ";
    cout<<endl;
    */
    map<char,int> mapTerminateSignCharToInt;
    for(int i=0;i<terminatesign.size();++i)
        mapTerminateSignCharToInt[terminatesign[i]]=i;
    /*
    map<char,int>::iterator iter;
    for(iter=mapTerminateSignCharToInt.begin();iter!=mapTerminateSignCharToInt.end();++iter)
    {
        cout<<iter->first<<" "<<iter->second<<endl;
    }
    */
    vector<vector<char> > priortable;
    vector<char> vc;
    for(int i=0;i<terminatesign.size();++i)
        vc.push_back(' ');
    for(int i=0;i<terminatesign.size();++i)
        priortable.push_back(vc);
    /*
    for(int i=0;i<priortable.size();++i)
    {
        for(int j=0;j<priortable[i].size();++j)
        {
            cout<<priortable[i][j];
        }
        cout<<endl;
    }
    */
    vector<string> grammer;
    grammer=getgrammer();

    for(int i=0;i<grammer.size();++i)
    {
        int arrowcite=grammer[i].find_first_of("->");
        arrowcite+=2;
        //cout<<grammer[i].substr(arrowcite)<<endl;
        for(int j=arrowcite;j<grammer[i].size()-1;++j)
        {
            for(int k=j+1;k<grammer[i].size();++k)
            {
                if( (!(isupper(grammer[i][j]))) && (!(isupper(grammer[i][k]))) )
                {
                    //cout<<j<<"  "<<k<<"  "<<grammer[i]<<endl;
                    priortable[mapTerminateSignCharToInt[grammer[i][j]]][mapTerminateSignCharToInt[grammer[i][k]]] = '=';
                    //priortable[mapTerminateSignCharToInt[grammer[i][k]]][mapTerminateSignCharToInt[grammer[i][j]]] = '=';

                }

                else if( (!(isupper(grammer[i][j]))) && ((isupper(grammer[i][k]))) )
                {//cout<<"here----------"<<endl;
                    for(int l=0;l<firstav.size();++l)
                    {
                        if(firstav[l][0]==grammer[i][k])
                        {
                            for(int m=1;m<firstav[l].size();++m)
                            {
                                priortable[mapTerminateSignCharToInt[grammer[i][j]]][mapTerminateSignCharToInt[firstav[l][m]]] = '<';
                            }
                            break;
                        }

                    }

                }
                else if( ((isupper(grammer[i][j]))) && (!(isupper(grammer[i][k]))) )
                {
                    for(int l=0;l<followav.size();++l)
                    {
                        if(followav[l][0]==grammer[i][j])
                        {
                            for(int m=1;m<followav[l].size();++m)
                            {
                                priortable[mapTerminateSignCharToInt[followav[l][m]]][mapTerminateSignCharToInt[grammer[i][k]]] = '>';
                                //cout<<i<<"  "<<j<<"  "<<k<<"  "<<followav[l][m]<<"  "<<grammer[i][k]<<endl;
                            }
                            break;
                        }

                    }

                }
            }
        }
    }
    cout<<endl<<"優先關係表:"<<endl<<' ';
    for(int i=0;i<terminatesign.size();++i)
        cout<<terminatesign[i];
    cout<<endl;
    for(int i=0;i<priortable.size();++i)
    {
        cout<<terminatesign[i];
        for(int j=0;j<priortable[i].size();++j)
        {
            cout<<priortable[i][j];
        }
        cout<<endl;
    }
    return priortable;
}

analy.h


#ifndef ANALY_H
#define ANALY_H
#include <vector>
using namespace std;

void inStringAnalyze(string s,vector<vector<char> > priortable);
#endif

analy.cpp

#include <iostream>
#include <sstream>
#include <string>
#include <fstream>
#include <cstdlib>
#include <vector>
#include <cctype>
#include <algorithm>
#include <map>
#include <set>
#include <cmath>
#include <queue>
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <set>
#include <map>
#include "grammerin.h"
using namespace std;

void createRightToLeftMapping()
{
    vector<string> grammer=getgrammer();
    for(int i=0;i<grammer.size();++i)
        cout<<grammer[i]<<endl;
    map<string,char> leftToRight;

    for(int i=0;i<grammer.size();++i)
    {
        int c=grammer[i].find_first_of("->");
        c+=2;
        string left=grammer[i].substr(c);
        //out<<left<<endl;
        leftToRight[left]=grammer[i][0];         //此處假設產生式右部無重複
    }
}

//#i+i#


void inStringAnalyze(string s,vector<vector<char> > priortable)
{
    vector<char> terminatesign= readGrammerWithNoPrint()[1];
    /*
    for(int i=0;i<terminatesign.size();++i)
        cout<<terminatesign[i]<<"  ";
    cout<<endl;
    */
    map<char,int> mapTerminateSignCharToInt;
    for(int i=0;i<terminatesign.size();++i)
        mapTerminateSignCharToInt[terminatesign[i]]=i;
    createRightToLeftMapping();
    string analystack="";
    analystack+=s[0];
    cout<<analystack<<endl;
    cout<<s[0]<<endl;
    int analystackpoint=0;
    string inputstring=s.substr(1);
    //cout<<s<<endl;
    cout<<"  "<<"分析棧  "<<"優先關係    "<<"輸入串"<<endl;
    int num=0;
    int sign=0;
    int presign=-1;
    int numg=0;
    while(true)
    {
        cout<<(num++)<<"   "<<analystack<<"     ";
        //cout<<endl<<analystack[analystackpoint]<<"  "<<s[0]<<endl;
        cout<<analystack[analystackpoint];
        cout<<priortable[mapTerminateSignCharToInt[analystack[analystackpoint]]][mapTerminateSignCharToInt[inputstring[0]]];
        cout<<inputstring[0]<<"          "<<inputstring<<endl;
        //cout<<(num++)<<"  "<<analystack[analystackpoint]<<"  ";
        //cout<<priortable[analystack[analystackpoint]][s[0]]<<"  "<<s[0]<<"  "<<s<<endl;
        if(priortable[mapTerminateSignCharToInt[analystack[analystackpoint]]][mapTerminateSignCharToInt[inputstring[0]]]=='=')
            sign=0;
        else if(priortable[mapTerminateSignCharToInt[analystack[analystackpoint]]][mapTerminateSignCharToInt[inputstring[0]]]=='<')
            sign=1;
        else if(priortable[mapTerminateSignCharToInt[analystack[analystackpoint]]][mapTerminateSignCharToInt[inputstring[0]]]=='>')
            sign=2;
        else
        {
            cout<<"grammer error!"<<endl;
            break;
        }
        if(presign==1&&sign==2)
        {
            cout<<numg<<endl;;//規約
            string dis;
            dis=analystack.substr(analystackpoint,analystackpoint+numg);
            cout<<dis<<endl;
        }
        else
        {
            numg++;
            analystack+=inputstring[0];
            ++analystackpoint;
            //cout<<endl<<analystack<<endl;
            inputstring=inputstring.substr(1);
            presign=1;
        }
    //cout<<endl<<analystackpoint<<endl;
    if(num>5)
        break;
    }
}

 

發佈了75 篇原創文章 · 獲贊 20 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章