UVA12421 (Jiandan) Mua (I) - Lexical Analyzer 题解

蒟蒻的第一篇紫题题解!

题目传送门

思路

一眼模拟,还是大模拟。不由得想起了我编了 \(4\) 个小时的猪国杀……

输入

首先处理输入,这里我们用一个字符串数组来存储所有的输入,然后再进行处理。

while(getline(cin,sr))str[++cnt]=sr+'\n';

处理时需要双重循环,注意如果遍历到空格要跳过!(字符串内除外)

换行符在第一层循环末尾输出即可。

NUMBER

我们从最难处理的数字开始。

首先判断有没有 .,再判断是不是十六进制,然后再逐个往后筛,看看能否加进这个数字中,用一个字符串 \(ans\) 来储存答案,记得在最后清零!

bool checknum(int x,int y){
    char ch=str[x][y];
    if(ch>='0'&&ch<='9'||ch=='e'||ch>='A'&&ch<='F'||ch>='a'&&ch<='f')return 1;
    if(ch=='-'||ch=='+')if(str[x][y-1]=='e')return 1;else return 0;
    if(ch=='.'&&!pd){pd=1;return 1;}
    return 0;
}

if(str[i][j]>='0'&&str[i][j]<='9'||str[i][j]=='.'&&str[i][j+1]>='0'&&str[i][j+1]<='9'){
    cout<<"[NUMBER] ";pd=0;
    if(str[i][j]=='.')ans+=str[i][j],j++,pd=1;
    if(str[i][j]=='0'&&(str[i][j+1]=='X'||str[i][j+1]=='x'))ans+=str[i][j],ans+=str[i][j+1],j+=2,pd=1;
    while(checknum(i,j))ans+=str[i][j],j++;j--;
    cout<<ans<<'\n';
    ans="";
}

STRING

接着我们再来看如何处理字符串。

如果碰到 '",就将从这个字符往后筛直到找到另一个 '",不过如果这个 '" 前一个字符是 \,则需跳过继续往后筛。

bool checkstring(int x,int y,char tmp){
    char ch1=str[x][y],ch2=str[x][y-1];
    if(tmp!=ch1)return 1;
    else{if(ch2=='\\')return 1;else return 0;}
    return 0;
}

if(str[i][j]=='\''||str[i][j]=='\"'){
    cout<<"[STRING] ";
    ans+=str[i][j];
    char tmp=str[i][j];j++;
    while(checkstring(i,j,tmp))ans+=str[i][j],j++;
    ans+=str[i][j];
    cout<<ans<<'\n';
    ans="";
}

SYMBOL

然后就是符号了。

直接用一个函数判断就行,但要注意先判断长度长的,避免重复。

int checksymbol(int x,int y){
    char ch1=str[x][y],ch2=str[x][y+1];
    if(ch1=='.'&&ch2=='.'&&str[x][y+2]=='.')return 3;
    if(ch1=='.'&&ch2=='.'||ch1=='='&&ch2=='='||ch1=='>'&&ch2=='='||ch1=='<'&&ch2=='='||ch1=='~'&&ch2=='=')return 2;
    /*+ - * / % ^ # == >= <= > < ~= ( ) { } [ ] ; : , . .. ... =*/
    if(ch1=='.'||ch1==','||ch1==':'||ch1==';'||ch1=='='||ch1=='+'||ch1=='-'||ch1=='*'||ch1=='/'||ch1=='%'||ch1=='^'||ch1=='#'||ch1=='<'||ch1=='>'||ch1=='('||ch1==')'||ch1=='{'||ch1=='}'||ch1=='['||ch1==']')return 1;
    return 0;
}

if(checksymbol(i,j)){
    int tmp=checksymbol(i,j);
    cout<<"[SYMBOL] ";
    for(int k=0;k<tmp;k++)ans+=str[i][j+k];
    j+=tmp,j--;
    cout<<ans<<'\n';
    ans="";
}

NAME&&RESERVED

保留字可以在名称里判断。

先找到一个字母,然后往后滤,只要后一个字符是字母、数字、下划线中的一个就压入 \(ans\) 中,最后整体判断 \(ans\) 属不属于保留字即可。

bool checkname(int x,int y){
    char ch=str[x][y];
    if(ch>='0'&&ch<='9'||ch>='a'&&ch<='z'||ch>='A'&&ch<='Z'||ch=='_')return 1;
    return 0;
}

bool checkreserved(string s){
    for(int i=0;i<21;i++)if(s==RESERVED[i])return 1;
    return 0;
}

if(str[i][j]>='a'&&str[i][j]<='z'||str[i][j]>='A'&&str[i][j]<='Z'){
    while(checkname(i,j))ans+=str[i][j],j++;j--;
    if(checkreserved(ans))cout<<"[RESERVED] "<<ans<<'\n';
    else cout<<"[NAME] "<<ans<<'\n';
    ans="";
}

COMMENT

只需要判断有没有两个连续的 _,然后把后面的全部刨去,注意要输出换行符!

if(str[i][j]=='-'&&str[i][j+1]=='-')j=len-1;

完整代码

#include<bits/stdc++.h>
using namespace std;
string RESERVED[25]={"and","break","do","else","elseif","end","false","for","function","if","in","local","nil","not","or","repeat","return","then","true","until","while"};
string sr,str[1005],ans;
int cnt,len,j;
bool pd;
bool checknum(int x,int y){
    char ch=str[x][y];
    if(ch>='0'&&ch<='9'||ch=='e'||ch>='A'&&ch<='F'||ch>='a'&&ch<='f')return 1;
    if(ch=='-'||ch=='+')if(str[x][y-1]=='e')return 1;else return 0;
    if(ch=='.'&&!pd){pd=1;return 1;}
    return 0;
}
bool checkstring(int x,int y,char tmp){
    char ch1=str[x][y],ch2=str[x][y-1];
    if(tmp!=ch1)return 1;
    else{if(ch2=='\\')return 1;else return 0;}
    return 0;
}
int checksymbol(int x,int y){
    char ch1=str[x][y],ch2=str[x][y+1];
    if(ch1=='.'&&ch2=='.'&&str[x][y+2]=='.')return 3;
    if(ch1=='.'&&ch2=='.'||ch1=='='&&ch2=='='||ch1=='>'&&ch2=='='||ch1=='<'&&ch2=='='||ch1=='~'&&ch2=='=')return 2;
    /*+ - * / % ^ # == >= <= > < ~= ( ) { } [ ] ; : , . .. ... =*/
    if(ch1=='.'||ch1==','||ch1==':'||ch1==';'||ch1=='='||ch1=='+'||ch1=='-'||ch1=='*'||ch1=='/'||ch1=='%'||ch1=='^'||ch1=='#'||ch1=='<'||ch1=='>'||ch1=='('||ch1==')'||ch1=='{'||ch1=='}'||ch1=='['||ch1==']')return 1;
    return 0;
}
bool checkname(int x,int y){
    char ch=str[x][y];
    if(ch>='0'&&ch<='9'||ch>='a'&&ch<='z'||ch>='A'&&ch<='Z'||ch=='_')return 1;
    return 0;
}
bool checkreserved(string s){
    for(int i=0;i<21;i++)if(s==RESERVED[i])return 1;
    return 0;
}
int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    while(getline(cin,sr))str[++cnt]=sr+'\n';
    for(int i=1;i<=cnt;i++){
        ans="";
        len=str[i].length();
        // cout<<str[i];
        for(int j=0;j<len;j++){
            if(str[i][j]==' ')continue;
            else if(str[i][j]=='-'&&str[i][j+1]=='-')j=len-1;
            else if(str[i][j]>='0'&&str[i][j]<='9'||str[i][j]=='.'&&str[i][j+1]>='0'&&str[i][j+1]<='9'){
                cout<<"[NUMBER] ";pd=0;
                if(str[i][j]=='.')ans+=str[i][j],j++,pd=1;
                if(str[i][j]=='0'&&(str[i][j+1]=='X'||str[i][j+1]=='x'))ans+=str[i][j],ans+=str[i][j+1],j+=2,pd=1;
                while(checknum(i,j))ans+=str[i][j],j++;j--;
                cout<<ans<<'\n';
                ans="";
            }else if(str[i][j]=='\''||str[i][j]=='\"'){
                cout<<"[STRING] ";
                ans+=str[i][j];
                char tmp=str[i][j];j++;
                while(checkstring(i,j,tmp))ans+=str[i][j],j++;
                ans+=str[i][j];
                cout<<ans<<'\n';
                ans="";
            }else if(checksymbol(i,j)){
                int tmp=checksymbol(i,j);
                cout<<"[SYMBOL] ";
                for(int k=0;k<tmp;k++)ans+=str[i][j+k];
                j+=tmp,j--;
                cout<<ans<<'\n';
                ans="";
            }else if(str[i][j]>='a'&&str[i][j]<='z'||str[i][j]>='A'&&str[i][j]<='Z'){
                while(checkname(i,j))ans+=str[i][j],j++;j--;
                if(checkreserved(ans))cout<<"[RESERVED] "<<ans<<'\n';
                else cout<<"[NAME] "<<ans<<'\n';
                ans="";
            }
        }
        cout<<"[EOL]\n";
    }
    return 0;
}
posted @ 2024-02-23 20:48  GyrthCurunír  阅读(6)  评论(0编辑  收藏  举报