词法分析主程序

/**词法分析主程序**/

TkWord * tk_hashtable[MAXKEY];  //单词哈希表
DynArray tktable;               //单词动态数组,单词表中放置标识符,包括变量名,函数名,结构定义名
DynString tkstr;                //单词字符串
DynString sourcestr;            //单词源码字符串
int tkvalue;                    //单词值(单词为整型变量)
char ch;                        //当前取到的源码字符
int token;                      //单词编码
int line_num;                   //行号

/**从源文件中读取一个字符**/
void getch()
{
    ch=getc(fin);       /**文件尾返回EOF,其他返回实际字节值**/
}
/**
空白字符处理
忽略空格,Tab和回车
**/
void skip_white_space()
{
    while(ch==' '||ch=='\t'||ch=='\r')
    {
        if(ch=='\r')            /**windows下.c文件就是文本文件,而windows下文件行末结束符是\r\n,是俩个字符**/
        {
            getch();
            if(ch!='\n')
                return;
            line_num++;
        }
        printf("%c",ch);
        getch();
    }
}
/**
解析注释
**/
void parse_comment()
{
    getch();
    do
    {
        do
        {
            if(ch=='\n'||ch=='*'||ch==CH_EOF)
                break;
            else
                getch();
        }while(1);
        if(ch=='\n')        /**读到换行符,行数加一**/
        {
            line_num++;
            getch();
        }
        else if(ch=='*')    /**可能出现注释结束符,先往前读一个字符**/
        {
            getch();
            if(ch=='/')      /**跳出循环**/
            {
                getch();
                return;
            }
        }
        else
        {
            error("一直到文件尾未看到配对的注释结束符");
            return ;
        }
    }while(1);
}
/**预处理,忽略空白字符及注释**/
void preprocess()
{
    while(1)
    {
        if(ch==' '||ch=='\t'||ch=='\r')/**忽略空白字符**/
            skip_white_space();
        else if(ch=='/')
        {
            getch();                   /**向前多看一个字符**/
            if(ch=='*')                /**是注释就忽略**/
                parse_comment();
            else
            {
                ungetc(ch,fin);        /**不是注释就把字符回退到输入流**/
                ch='/';
                break;                 /**并结束循环**/
            }
        }
        else
            break;
    }
}
/**解析标识符**/
/**判断c是否为字母或下划线**/
int is_nodigit(char c)
{
    return (c>='a'&&c<='z')||(c>='A'&&c<='Z')||c=='_';
}
/**判断c是否是数字**/
int is_digit(char c)
{
    return c>='0'&&c<='9';
}
/**解析标识符**/
void parse_identifier()
{
    dynstring_reset(&tkstr);
    dynstring_chcat(&tkstr,ch);
    getch();
    while(is_nodigit(ch)||is_digit(ch))
    {
        dynstring_chcat(&tkstr,ch);
        getch();
    }
    dynstring_chcat(&tkstr,'\0');
}
/**解析整数**/
/**解析整型常量**/
void parse_num()
{
    dynstring_reset(&tkstr);
    dynstring_reset(&sourcestr);
    do{
        dynstring_chcat(&tkstr,ch);
        dynstring_chcat(&sourcestr,ch);
        getch();
    }while(is_digit(ch));
    if(ch=='.')
    {
        do{
        dynstring_chcat(&tkstr,ch);
        dynstring_chcat(&sourcestr,ch);
        getch();
        }while(is_digit(ch));
    }
    dynstring_chcat(&tkstr,'\0');
    dynstring_chcat(&sourcestr,'\0');
    tkvalue=atoi(tkstr.data);               /**把字符型转换为整型**/
}
/**解析字符串**/
/**
解析字符常量,字符串常量
sep:字符常量界符标识为单引号
    字符串常量界符标识为双引号
**/
void parse_string(char sep)
{
    char c;
    dynstring_reset(&tkstr);
    dynstring_reset(&sourcestr);
    dynstring_chcat(&sourcestr,sep);
    getch();
    for(;;)
    {
        if(ch==sep)
            break;                    /**界符匹配**/
        else if(ch=='\\')
        {
            dynstring_chcat(&sourcestr,ch);
            getch();
            switch(ch)                /**解析转义字符**/
            {
            case '0':
                c='\0';
                break;
            case 'a':
                c='\a';
                break;
            case 'b':                 /**退格**/
                c='\b';
                break;
            case 't':
                c='\t';
                break;
            case 'n':
                c='\n';
                break;
            case 'v':               /**垂直制表**/
                c='\v';
                break;
            case 'f':               /**换页**/
                c='\f';
                break;
            case 'r':
                c='\r';
                break;
            case '\"':
                c='\"';
                break;
            case '\'':
                c='\'';
                break;
            case '\\':
                c='\\';
                break;
            default:
                c=ch;
                if(c>='!'&&c<='~')
                    warning("非法转义字符:\'\\%c\'",c);
                else
                    warning("非法转义字符:\'\\0x%x\'",c);
                break;
            }
            dynstring_chcat(&tkstr,c);
            dynstring_chcat(&sourcestr,ch);
            getch();
        }
        else
        {
            dynstring_chcat(&tkstr,ch);
            dynstring_chcat(&sourcestr,ch);
            getch();
        }
    }
    dynstring_chcat(&tkstr,'\0');
    dynstring_chcat(&sourcestr,sep);
    dynstring_chcat(&sourcestr,'\0');
    getch();
}
/**取单词**/
void get_token()
{
    preprocess();
    switch(ch)
    {
        case 'a':case 'b':case 'c':case 'd':case 'e':case 'f':case'g':
        case 'h':case 'i':case 'j':case 'k':case 'l':case 'm':case'n':
        case 'o':case 'p':case 'q':case 'r':case 's':case 't':
        case 'u':case 'v':case 'w':case 'x':case 'y':case 'z':
        case 'A':case 'B':case 'C':case 'D':case 'E':case 'F':case'G':
        case 'H':case 'I':case 'J':case 'K':case 'L':case 'M':case'N':
        case 'O':case 'P':case 'Q':case 'R':case 'S':case 'T':
        case 'U':case 'V':case 'W':case 'X':case 'Y':case 'Z':
        case '_':
            {
                TkWord *tp;
                parse_identifier();
                tp=tkword_insert(tkstr.data);
                token=tp->tkcode;
                break;
            }
        case '0':case '1':case '2':case '3':
        case '4':case '5':case '6':case '7':
        case '8':case '9':
            parse_num();
            token=TK_CINT;
            break;
        case '+':
            getch();
            token=TK_PLUS;
            break;
        case '-':
            getch();
            if(ch=='>')
            {
                token=TK_POINTSO;
                getch();
            }
            else
                token=TK_MINUS;
            break;
        case '/':
            token=TK_DIVIDE;
            getch();
            break;
        case '%':
            token=TK_MOD;
            getch();
            break;
        case '=':
            getch();
            if(ch=='=')
            {
                token=TK_EQ;
                getch();
            }
            else
                token=TK_ASSIGN;
            break;
        case '!':
            getch();
            if(ch=='=')
            {
                token=TK_NEQ;
                getch();
            }
            else
                error("暂不支持'!'(非操作符)");
            break;
        case '<':
            getch();
            if(ch=='=')
            {
                token=TK_LEQ;
                getch();
            }
            else
                token=TK_LF;
            break;
        case '>':
            getch();
            if(ch=='=')
            {
                token=TK_GEQ;
                getch();
            }
            else
                token=TK_GT;
            break;
        case '.':
            getch();
            if(ch=='.')
            {
                getch();
                if(ch!='.')
                    error("省略号拼写错误");
                else
                    token=TK_ELLIPSIS;
                getch();
            }
            else
            {
                token=TK_DOT;
            }
            break;
        case '&':
            token=TK_AND;
            getch();
            break;
        case ';':
            token=TK_SEMICOLON;
            getch();
            break;
        case ']':
            token=TK_CLOSEBR;
            getch();
            break;
        case '}':
            token=TK_END;
            getch();
            break;
        case ')':
            token=TK_CLOSEPA;
            getch();
            break;
        case '[':
            token=TK_OPENBR;
            getch();
            break;
        case '{':
            token=TK_BEGIN;
            getch();
            break;
        case '(':
            token=TK_OPENPA;
            getch();
            break;
        case ',':
            token=TK_COMMA;
            getch();
            break;
        case '*':
            token=TK_STAR;
            getch();
            break;
        case '\'':
            parse_string(ch);
            token=TK_CCHAR;
            tkvalue=*(char *)tkstr.data;    /**强制转换成字符的ascll码**/
            break;
        case '\"':
            parse_string(ch);
            token=TK_CSTR;
            break;
        case EOF:
            token=TK_EOF;
            break;
        default:
            error("不认识的字符:0x%02x",ch);/**把ch的值用16进制表示,%02x表示不足2位,高位就用0补充**/
            getch();
            break;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值