устройство 组织 构造 制度 仪器

наврать 撒谎

соврать 骗

一个简单的C语言语法检查器的实现

  我自己的实现方法的核心过程:首先用一个非终结符代表所有要检查的程序代码,然后根据文法将这个整体的符号不断展开,以拼凑成按检查的程序的顺序排列的终结符序列,能成功说明语法正确,否则有错误。

关键词:分词;First集;Select集;

  目前还存在的问题:

    1.因为同一个非终结符->终结符的转化可能有多种解释,所以目前我的非终结符展开这里是用递归写的,因此不能定位具体错在哪里。

    2.int a={1,2};int a[2]={1,'b'};这种该出错的地方不会出错。这个比较致命,但目前还没想好怎么解决。

  代码部分借鉴了这里,我直接用了他的分词的scnner函数和宏定义的部分。他的程序总共2000+行,我改了一下,总共只用1000行就实现了他的功能,其中500行是抄的他的分词......并且修改了他的程序里的一些错误。

Grammar.txt:文法的定义

<程序闭包> -> <声明语句闭包> #
<程序闭包> -> <函数定义> #
<程序闭包> -> $ #
<函数定义> -> <修饰词闭包> <类型> <变量> ( <参数声明> ) { <函数块> } #
<修饰词闭包> -> <修饰词> <修饰词闭包> #
<修饰词闭包> -> $ #
<修饰词> -> describe #
<类型> -> type <取地址> #
<取地址> -> <星号闭包> #
<星号闭包> -> <星号> <星号闭包> #
<星号闭包> -> $ #
<星号> -> * #
<变量> -> <标志符> <数组下标> #
<标志符> -> id #
<数组下标> -> [ <因式> ] #
<数组下标> -> $ #
<因式> -> ( <表达式> ) #
<因式> -> <变量> #
<因式> -> <数字> #
<数字> -> digit #
<数字> -> string #
<表达式> -> <因子> <项> #
<因子> -> <因式> <因式递归> #
<因式递归> -> * <因式> <因式递归> #
<因式递归> -> / <因式> <因式递归> #
<因式递归> -> $ #
<项> -> + <因子> <项> #
<项> -> - <因子> <项> #
<项> -> $ #
<参数声明> -> <声明> <声明闭包> #
<参数声明> -> $ #
<声明> -> <修饰词闭包> <类型> <变量> <赋初值> #
<赋初值> -> = <右值> #
<赋初值> -> $ #
<右值> -> <表达式> #
<右值> -> { <多个数据> } #
<多个数据> -> <数字> <数字闭包> #
<数字闭包> -> , <数字> <数字闭包> #
<数字闭包> -> $ #
<声明闭包> -> , <声明> <声明闭包> #
<声明闭包> -> $ #
<函数块> -> <声明语句闭包> <函数块闭包> #
<声明语句闭包> -> <声明语句> <声明语句闭包> #
<声明语句闭包> -> $ #
<声明语句> -> <声明> ; #
<函数块闭包> -> <赋值函数> <函数块闭包> #
<函数块闭包> -> <for循环> <函数块闭包> #
<函数块闭包> -> <条件语句> <函数块闭包> #
<函数块闭包> -> <函数返回> <函数块闭包> #
<函数块闭包> -> $ #
<赋值函数> -> <变量> <赋值或函数调用> #
<赋值或函数调用> -> = <右值> ; #
<赋值或函数调用> -> ( <参数列表> ) ; # 
<参数列表> -> <参数> <参数闭包> #
<参数闭包> -> , <参数> <参数闭包> #
<参数闭包> -> $ #
<参数> -> <标志符> #
<参数> -> <数字> #
<参数> -> <字符串> #
<字符串> -> string #
<for循环> -> for ( <赋值函数> <逻辑表达式> ; <后缀表达式> ) { <函数块> } #
<逻辑表达式> -> <表达式> <逻辑运算符> <表达式> #
<逻辑运算符> -> < #
<逻辑运算符> -> > #
<逻辑运算符> -> == #
<逻辑运算符> -> != #
<后缀表达式> -> <变量> <后缀运算符> #
<后缀运算符> -> ++ #
<后缀运算符> -> -- #
<条件语句> -> if ( <逻辑表达式> ) { <函数块> } <否则语句> #
<否则语句> -> else { <函数块> } #
<否则语句> -> $ #
<函数返回> -> return <因式> ; #
View Code

Grammar.cpp:主程序

#include "initialize.h"
int main() {
    Init();
    Scan();
    Analyse();
    getchar();
    return 0;
}

initialize.h:初始化

#ifndef __INIT__
#define __INIT__
#include "WA.h"
#include "SA.h"
#include "Macro_Struct.h"
void InitKeyMap() {
    keyMap.clear();
    keyMap.push_back(make_pair("auto", AUTO));
    keyMap.push_back(make_pair("break", BREAK));
    keyMap.push_back(make_pair("case", CASE));
    keyMap.push_back(make_pair("char", CHAR));
    keyMap.push_back(make_pair("const", CONST));
    keyMap.push_back(make_pair("continue", CONTINUE));
    keyMap.push_back(make_pair("default", DEFAULT));
    keyMap.push_back(make_pair("do", DO));
    keyMap.push_back(make_pair("double", DOUBLE));
    keyMap.push_back(make_pair("else", ELSE));
    keyMap.push_back(make_pair("enum", ENUM));
    keyMap.push_back(make_pair("extern", EXTERN));
    keyMap.push_back(make_pair("float", FLOAT));
    keyMap.push_back(make_pair("for", FOR));
    keyMap.push_back(make_pair("goto", GOTO));
    keyMap.push_back(make_pair("if", IF));
    keyMap.push_back(make_pair("int", INT));
    keyMap.push_back(make_pair("long", LONG));
    keyMap.push_back(make_pair("register", REGISTER));
    keyMap.push_back(make_pair("return", RETURN));
    keyMap.push_back(make_pair("short", SHORT));
    keyMap.push_back(make_pair("signed", SIGNED));
    keyMap.push_back(make_pair("sizeof", SIZEOF));
    keyMap.push_back(make_pair("static", STATIC));
    keyMap.push_back(make_pair("struct", STRUCT));
    keyMap.push_back(make_pair("switch", SWITCH));
    keyMap.push_back(make_pair("typedef", TYPEDEF));
    keyMap.push_back(make_pair("union", UNION));
    keyMap.push_back(make_pair("unsigned", UNSIGNED));
    keyMap.push_back(make_pair("void", VOID));
    keyMap.push_back(make_pair("volatile", VOLATILE));
    keyMap.push_back(make_pair("while", WHILE));
    keyMap.push_back(make_pair("describe", DESCRIBE));
    keyMap.push_back(make_pair("type", TYPE));
    //keyMap.push_back(make_pair("string", STRING));
    keyMap.push_back(make_pair("digit", DIGIT));
}
void InitOperMap() {
    operMap.clear();
    operMap.push_back(make_pair("!", NOT));
    operMap.push_back(make_pair("&", BYTE_AND));
    operMap.push_back(make_pair("~", COMPLEMENT));
    operMap.push_back(make_pair("^", BYTE_XOR));
    operMap.push_back(make_pair("*", MUL));
    operMap.push_back(make_pair("/", DIV));
    operMap.push_back(make_pair("%", MOD));
    operMap.push_back(make_pair("+", ADD));
    operMap.push_back(make_pair("-", SUB));
    operMap.push_back(make_pair("<", LES_THAN));
    operMap.push_back(make_pair(">", GRT_THAN));
    operMap.push_back(make_pair("=", ASG));
    operMap.push_back(make_pair("->", ARROW));
    operMap.push_back(make_pair("++", SELF_ADD));
    operMap.push_back(make_pair("--", SELF_SUB));
    operMap.push_back(make_pair("<<", LEFT_MOVE));
    operMap.push_back(make_pair(">>", RIGHT_MOVE));
    operMap.push_back(make_pair("<=", LES_EQUAL));
    operMap.push_back(make_pair(">=", GRT_EQUAL));
    operMap.push_back(make_pair("==", EQUAL));
    operMap.push_back(make_pair("!=", NOT_EQUAL));
    operMap.push_back(make_pair("&&", AND));
    operMap.push_back(make_pair("||", OR));
    operMap.push_back(make_pair("+=", COMPLETE_ADD));
    operMap.push_back(make_pair("-=", COMPLETE_SUB));
    operMap.push_back(make_pair("*=", COMPLETE_MUL));
    operMap.push_back(make_pair("/=", COMPLETE_DIV));
    operMap.push_back(make_pair("^=", COMPLETE_BYTE_XOR));
    operMap.push_back(make_pair("&=", COMPLETE_BYTE_AND));
    operMap.push_back(make_pair("~=", COMPLETE_COMPLEMENT));
    operMap.push_back(make_pair("%=", COMPLETE_MOD));
    operMap.push_back(make_pair("|", BYTE_OR));
}
void InitLimitMap() {
    limitMap.clear();
    limitMap.push_back(make_pair("(", LEFT_BRA));
    limitMap.push_back(make_pair(")", RIGHT_BRA));
    limitMap.push_back(make_pair("[", LEFT_INDEX));
    limitMap.push_back(make_pair("]", RIGHT_INDEX));
    limitMap.push_back(make_pair("{", L_BOUNDER));
    limitMap.push_back(make_pair("}", R_BOUNDER));
    limitMap.push_back(make_pair(".", POINTER));
    limitMap.push_back(make_pair("#", JING));
    limitMap.push_back(make_pair("_", UNDER_LINE));
    limitMap.push_back(make_pair(",", COMMA));
    limitMap.push_back(make_pair(";", SEMI));
    limitMap.push_back(make_pair("'", SIN_QUE));
    limitMap.push_back(make_pair("\"", DOU_QUE));
}
void ShowExprList() {
    for (int i = 0; i < ExprNum; i++) {
        printf("%s -> ", Signature[Expr[i][0]].first);
        for (int j = 2; j <= Expr[i][1]; j++) {
            printf("%s ", Signature[Expr[i][j]].first);
        }
        printf("\n");
    }
}
void DFS_NullPossibility(int x) {
    //printf("%s\n",Signature[x].first);
    if (visited[x]) {
        return;
    }
    visited[x] = true;
    for (int i = 0; i < ExprNum; i++) {
        if (Expr[i][0] != x) {
            continue;
        }
        bool ret = true;
        for (int j = 2; j <= Expr[i][1]; j++) {
            DFS_NullPossibility(Expr[i][j]);
            ret &= canBeNull[Expr[i][j]];
        }
        if (ret) {
            visited[x] = true;
            canBeNull[x] = true;
            return;
        }
    }
}
void ReadExpr() {
    Signature.clear();
    ifstream fin("Grammar.txt");
    char str[50][50];
    int Length = 0;
    while (fin >> str[Length]) {
        if (strcmp(str[Length], "#") == 0) {
            for (int i = 0; i < Length; i++) {
                if (strcmp(str[i], "->") == 0) {
                    Expr[ExprNum][i] = Length - 1;
                    continue;
                }
                int signID = FindSignature(str[i]);
                if (signID == -1) {
                    int tempLen = strlen(str[i]);
                    if (str[i][0] == '<' && str[i][tempLen - 1] == '>') {
                        pair<char *, bool> tempPair;
                        tempPair.first = new char [tempLen + 1];
                        memcpy(tempPair.first, str[i], tempLen);
                        tempPair.first[tempLen] = '\0';
                        tempPair.second = Scalable;
                        Signature.push_back(tempPair);
                    } else {
                        pair<char *, bool> tempPair;
                        tempPair.first = new char [tempLen + 1];
                        memcpy(tempPair.first, str[i], tempLen);
                        tempPair.first[tempLen] = '\0';
                        tempPair.second = unScalsble;
                        Signature.push_back(tempPair);
                    }
                    signID = Signature.size() - 1;
                }
                Expr[ExprNum][i] = signID;
            }
            Length = 0;
            ExprNum++;
        } else {
            Length++;
        }
    }
    fin.close();
    memset(canBeNull, false, sizeof(canBeNull));
    for (int i = 0; i < Signature.size(); i++) {
        if (strcmp(Signature[i].first, "$") == 0) {
            canBeNull[i] = true;
        }
    }
    memset(visited, false, sizeof(visited));
    for (int i = 0; i < Signature.size(); i++) {
        if (Signature[i].second == Scalable) {
            DFS_NullPossibility(i);
        }
    }
    //ShowExprList();
}
void DFS_FirstSet(int x) {
    if (visited[x] || Signature[x].second == unScalsble) {
        return;
    }
    visited[x] = true;
    for (int i = 0; i < ExprNum; i++) {
        if (Expr[i][0] != x) {
            continue;
        }
        for (int j = 2; j <= Expr[i][1]; j++) {
            if (Signature[Expr[i][j]].second == unScalsble) {
                First[x][Expr[i][j]] = true;
            } else {
                DFS_FirstSet(Expr[i][j]);
                for (int k = 0; k < Signature.size(); k++) {
                    if (First[Expr[i][j]][k]) {
                        First[x][k] = true;
                    }
                }
            }
            if (!canBeNull[Expr[i][j]]) {
                break;
            }
        }
    }
}
void GetFirstSet() {
    memset(First, false, sizeof(First));
    memset(visited, false, sizeof(visited));
    for (int i = 0; i < Signature.size(); i++) {
        if (Signature[i].second == unScalsble) {
            continue;
        }
        DFS_FirstSet(i);
    }
}
void GetFollowSet() {}
void GetSelectSet() {
    memset(Select, false, sizeof(Select));
    for (int i = 0; i < ExprNum; i++) {
        for (int j = 2; j <= Expr[i][1]; j++) {
            if (Signature[Expr[i][j]].second == unScalsble) {
                Select[i][Expr[i][j]] = true;
            } else {
                for (int k = 0; k < Signature.size(); k++) {
                    if (First[Expr[i][j]][k]) {
                        Select[i][k] = true;
                    }
                }
            }
            if (!canBeNull[Expr[i][j]]) {
                break;
            }
        }
        if (!canBeNull[Expr[i][0]]) {
            Select[i][FindSignature("$")] = false;
        }
    }
}
void ShowShiftList() {
    for (int i = 0; i < Signature.size(); i++) {
        for (int j = 0; j < Signature.size(); j++) {
            if (ShiftList[i][j][0][0] <= 1 || i == j) {
                continue;
            }
            printf("%3d %30s -> %30s\n", ShiftList[i][j][0][0], Signature[i].first, Signature[j].first);
            for (int k = 1; k <= ShiftList[i][j][0][0]; k++) {
                printf("---------->");
                for (int h = 1; h <= ShiftList[i][j][k][0]; h++) {
                    printf("%s ", Signature[ShiftList[i][j][k][h]].first);
                }
                printf("\n");
            }
        }
    }
}
void GetShiftList() {
    memset(ShiftList, 0, sizeof(ShiftList));
    for (int i = 0; i < ExprNum; i++) {
        for (int j = 0; j < Signature.size(); j++) {
            if (!Select[i][j]) {
                continue;
            }
            /*if (Signature[j].second == Scalable) {
                printf("OMG\n");
            }*/
            ShiftList[Expr[i][0]][j][0][0]++;
            for (int k = 1; k <= Expr[i][1]; k++) {
                ShiftList[Expr[i][0]][j][ShiftList[Expr[i][0]][j][0][0]][k - 1] = Expr[i][k];
            }
            ShiftList[Expr[i][0]][j][ShiftList[Expr[i][0]][j][0][0]][0]--;
        }
    }
    //ShowShiftList();
}
void Init() {
    InitKeyMap();
    InitOperMap();
    InitLimitMap();
    tokenList.clear();
    errorList.clear();
    ReadExpr();
    GetFirstSet();
    GetFollowSet();
    GetSelectSet();
    GetShiftList();
}
#endif
View Code

WA.h:词法分析

#ifndef __WA__
#define __WA__
#include "stdafx.h"
#include "Macro_Struct.h"

vector<pair<const char *, int>> keyMap;
vector<pair<const char *, int>> operMap;
vector<pair<const char *, int>> limitMap;
vector<Token> tokenList;
vector<Error> errorList;

int SeekKey(char * word) {
    for (int i = 0; i < keyMap.size(); i++) {
        if (strcmp(word, keyMap[i].first) == 0) {
            return keyMap[i].second;
        }
    }
    return IDENTIFER;
}
void InsertToken(char * content, char * describe, int type, int line) {
    Token tempToken;
    strcpy_s(tempToken.content, content);
    strcpy_s(tempToken.describe, describe);
    tempToken.type = type;
    tempToken.line = line;
    tokenList.push_back(tempToken);
}
void InsertError(char * content, char * describe, int type, int line) {
    Error tempError;
    strcpy_s(tempError.content, content);
    strcpy_s(tempError.describe, describe);
    tempError.type = type;
    tempError.line = line;
    errorList.push_back(tempError);
    printf("Line %d:%s\n", line, describe);
}
void preProcess(char * word, int line) {
    regex INCLUDE_REGEX("#include\\s*<[\\w\\.]+>\\s*");
    regex DEFINE_REGEX("#define\\s+\\w+\\s+\\w+\\s*");
    if (regex_match(word, INCLUDE_REGEX)) {
        return;
    }
    if (regex_match(word, DEFINE_REGEX)) {
        return;
    }
    InsertError(word, PRE_PROCESS_ERROR, PRE_PROCESS_ERROR_NUM, line);
}

void Scan() {
    char ch;
    char array[30];//单词长度上限是30
    char * word;
    int i;
    int line = 1;//行数
    FILE * infile;
    errno_t err = fopen_s(&infile, "input.txt", "r");
    ch = fgetc(infile);
    while (ch != EOF) {
        i = 0;
        //以字母或者下划线开头,处理关键字或者标识符
        if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || ch == '_') {
            while ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9') || ch == '_') {
                array[i++] = ch;
                ch = fgetc(infile);
            }
            word = new char[i + 1];
            memcpy(word, array, i);
            word[i] = '\0';
            int seekTemp = SeekKey(word);
            if (seekTemp != IDENTIFER) {
                InsertToken(word, KEY_DESC, seekTemp, line);
            } else {
                InsertToken(word, IDENTIFER_DESC, seekTemp, line);
            }
            fseek(infile, -1L, SEEK_CUR); //向后回退一位
        }
        //以数字开头,处理数字
        else if (ch >= '0' && ch <= '9') {
            int flag = 0;
            int flag2 = 0;
            //处理整数
            while (ch >= '0' && ch <= '9') {
                array[i++] = ch;
                ch = fgetc(infile);
            }
            //处理float
            if (ch == '.') {
                flag2 = 1;
                array[i++] = ch;
                ch = fgetc(infile);
                if (ch >= '0' && ch <= '9') {
                    while (ch >= '0' && ch <= '9') {
                        array[i++] = ch;
                        ch = fgetc(infile);
                    }
                } else {
                    flag = 1;
                }
                //处理Double
                if (ch == 'E' || ch == 'e') {
                    array[i++] = ch;
                    ch = fgetc(infile);
                    if (ch == '+' || ch == '-') {
                        array[i++] = ch;
                        ch = fgetc(infile);
                    }
                    if (ch >= '0' && ch <= '9') {
                        array[i++] = ch;
                        ch = fgetc(infile);
                    } else {
                        flag = 2;
                    }
                }
            }
            word = new char[i + 1];
            memcpy(word, array, i);
            word[i] = '\0';
            if (flag == 1) {
                InsertError(word, FLOAT_ERROR, FLOAT_ERROR_NUM, line);
            } else if (flag == 2) {
                InsertError(word, DOUBLE_ERROR, DOUBLE_ERROR_NUM, line);
            } else {
                if (flag2 == 0) {
                    InsertToken(word, CONSTANT_DESC, INT_VAL, line);
                } else {
                    InsertToken(word, CONSTANT_DESC, FLOAT_VAL, line);
                }
            }
            fseek(infile, -1L, SEEK_CUR); //向后回退一位
        }
        //以"/"开头
        else if (ch == '/') {
            ch = fgetc(infile);
            //处理运算符"/="
            if (ch == '=') {
                InsertToken("/=", OPE_DESC, COMPLETE_DIV, line);
            }
            //处理"/**/"型注释
            else if (ch == '*') {
                ch =  fgetc(infile);
                while (1) {
                    while (ch != '*') {
                        if (ch == '\n') {
                            line++;
                        }
                        ch = fgetc(infile);
                        if (ch == EOF) {
                            InsertError(_NULL, NOTE_ERROR, NOTE_ERROR_NUM, line);
                            return;
                        }
                    }
                    ch = fgetc(infile);
                    if (ch == '/') {
                        break;
                    }
                    if (ch == EOF) {
                        InsertError(_NULL, NOTE_ERROR, NOTE_ERROR_NUM, line);
                        return;
                    }
                }
                InsertToken(_NULL, NOTE_DESC, NOTE1, line);
            }
            //处理"//"型注释
            else if (ch == '/') {
                while (ch != '\n') {
                    ch = fgetc(infile);
                    if (ch == EOF) {
                        InsertToken(_NULL, NOTE_DESC, NOTE2, line);
                        return;
                    }
                }
                line++;
                InsertToken(_NULL, NOTE_DESC, NOTE2, line);
                if (ch == EOF) {
                    return;
                }
            }
            //处理除号
            else {
                InsertToken("/", OPE_DESC, DIV, line);
            }
        }
        //处理常量字符串
        else if (ch == '"') {
            InsertToken("\"", CLE_OPE_DESC, DOU_QUE, line);
            ch = fgetc(infile);
            i = 0;
            while (ch != '"') {
                array[i++] = ch;
                if (ch == '\n') {
                    line++;
                }
                ch = fgetc(infile);
                if (ch == EOF) {
                    InsertError(_NULL, STRING_ERROR, STRING_ERROR_NUM, line);
                    return;
                }
            }
            word = new char[i + 1];
            memcpy(word, array, i);
            word[i] = '\0';
            InsertToken(word, CONSTANT_DESC, STRING_VAL, line);
            InsertToken("\"", CLE_OPE_DESC, DOU_QUE, line);
        }
        //处理常量字符
        else if (ch == '\'') {
            InsertToken("\'", CLE_OPE_DESC, SIN_QUE, line);
            ch = fgetc(infile);
            i = 0;
            while (ch != '\'') {
                array[i++] = ch;
                if (ch == '\n') {
                    line++;
                }
                ch = fgetc(infile);
                if (ch == EOF) {
                    InsertError(_NULL, CHARCONST_ERROR, CHARCONST_ERROR_NUM, line);
                    return;
                }
            }
            word = new char[i + 1];
            memcpy(word, array, i);
            word[i] = '\0';
            InsertToken(word, CONSTANT_DESC, CHAR_VAL, line);
            InsertToken("\'", CLE_OPE_DESC, SIN_QUE, line);
        } else if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n') {
            if (ch == '\n') {
                line++;
            }
        } else {
            if (ch == EOF) {
                return;
            }
            //处理头文件和宏常量(预处理)
            else if (ch == '#') {
                while (ch != '\n' && ch != EOF) {
                    array[i++] = ch;
                    ch = fgetc(infile);
                }
                word = new char[i + 1];
                memcpy(word, array, i);
                word[i] = '\0';
                preProcess(word, line);
                fseek(infile, -1L, SEEK_CUR); //向后回退一位
            }
            //处理-开头的运算符
            else if (ch == '-') {
                array[i++] = ch;
                ch = fgetc(infile);
                if (ch >= '0' && ch <= '9') {
                    int flag = 0;
                    int flag2 = 0;
                    //处理整数
                    while (ch >= '0' && ch <= '9') {
                        array[i++] = ch;
                        ch = fgetc(infile);
                    }
                    //处理float
                    if (ch == '.') {
                        flag2 = 1;
                        array[i++] = ch;
                        ch = fgetc(infile);
                        if (ch >= '0' && ch <= '9') {
                            while (ch >= '0' && ch <= '9') {
                                array[i++] = ch;
                                ch = fgetc(infile);
                            }
                        } else {
                            flag = 1;
                        }
                        //处理Double
                        if (ch == 'E' || ch == 'e') {
                            array[i++] = ch;
                            ch = fgetc(infile);
                            if (ch == '+' || ch == '-') {
                                array[i++] = ch;
                                ch = fgetc(infile);
                            }
                            if (ch >= '0' && ch <= '9') {
                                array[i++] = ch;
                                ch = fgetc(infile);
                            } else {
                                flag = 2;
                            }
                        }
                    }
                    word = new char[i + 1];
                    memcpy(word, array, i);
                    word[i] = '\0';
                    if (flag == 1) {
                        InsertError(word, FLOAT_ERROR, FLOAT_ERROR_NUM, line);
                    } else if (flag == 2) {
                        InsertError(word, DOUBLE_ERROR, DOUBLE_ERROR_NUM, line);
                    } else {
                        if (flag2 == 0) {
                            InsertToken(word, CONSTANT_DESC, INT_VAL, line);
                        } else {
                            InsertToken(word, CONSTANT_DESC, FLOAT_VAL, line);
                        }
                    }
                    fseek(infile, -1L, SEEK_CUR); //向后回退一位
                } else if (ch == '>') {
                    InsertToken("->", OPE_DESC, ARROW, line);
                } else if (ch == '-') {
                    InsertToken("--", OPE_DESC, SELF_SUB, line);
                } else if (ch == '=') {
                    InsertToken("--", OPE_DESC, SELF_SUB, line);
                } else {
                    InsertToken("-", OPE_DESC, SUB, line);
                    fseek(infile, -1L, SEEK_CUR);
                }
            }
            //处理+开头的运算符
            else if (ch == '+') {
                ch = fgetc(infile);
                if (ch == '+') {
                    InsertToken("++", OPE_DESC, SELF_ADD, line);
                } else if (ch == '=') {
                    InsertToken("+=", OPE_DESC, COMPLETE_ADD, line);
                } else {
                    InsertToken("+", OPE_DESC, ADD, line);
                    fseek(infile, -1L, SEEK_CUR);
                }
            }
            //处理*开头的运算符
            else if (ch == '*') {
                ch = fgetc(infile);
                if (ch == '=') {
                    InsertToken("*=", OPE_DESC, COMPLETE_MUL, line);
                } else {
                    InsertToken("*", OPE_DESC, MUL, line);
                    fseek(infile, -1L, SEEK_CUR);
                }
            }
            //处理按^开头的运算符
            else if (ch == '^') {
                ch = fgetc(infile);
                if (ch == '=') {
                    InsertToken("^=", OPE_DESC, COMPLETE_BYTE_XOR, line);
                } else {
                    InsertToken("^", OPE_DESC, BYTE_XOR, line);
                    fseek(infile, -1L, SEEK_CUR);
                }
            }
            //处理%开头的运算符
            else if (ch == '%') {
                ch = fgetc(infile);
                if (ch == '=') {
                    InsertToken("%=", OPE_DESC, COMPLETE_MOD, line);
                } else {
                    InsertToken("%", OPE_DESC, MOD, line);
                    fseek(infile, -1L, SEEK_CUR);
                }
            }
            //处理&开头的运算符
            else if (ch == '&') {
                ch = fgetc(infile);
                if (ch == '=') {
                    InsertToken("&=", OPE_DESC, COMPLETE_BYTE_AND, line);
                } else if (ch == '&') {
                    InsertToken("&&", OPE_DESC, AND, line);
                } else {
                    InsertToken("&", OPE_DESC, BYTE_AND, line);
                    fseek(infile, -1L, SEEK_CUR);
                }
            }
            //处理~开头的运算符
            else if (ch == '~') {
                ch = fgetc(infile);
                if (ch == '=') {
                    InsertToken("~=", OPE_DESC, COMPLETE_COMPLEMENT, line);
                } else {
                    InsertToken("~", OPE_DESC, COMPLEMENT, line);
                    fseek(infile, -1L, SEEK_CUR);
                }
            }
            //处理!开头的运算符
            else if (ch == '!') {
                ch = fgetc(infile);
                if (ch == '=') {
                    InsertToken("!=", OPE_DESC, NOT_EQUAL, line);
                } else {
                    InsertToken("!", OPE_DESC, NOT, line);
                    fseek(infile, -1L, SEEK_CUR);
                }
            }
            //处理<开头的运算符
            else if (ch == '<') {
                ch = fgetc(infile);
                if (ch == '<') {
                    InsertToken("<<", OPE_DESC, LEFT_MOVE, line);
                } else if (ch == '=') {
                    InsertToken("<=", OPE_DESC, LES_EQUAL, line);
                } else {
                    InsertToken("<", OPE_DESC, LES_THAN, line);
                    fseek(infile, -1L, SEEK_CUR);
                }
            }
            //处理>开头的运算符
            else if (ch == '>') {
                ch = fgetc(infile);
                if (ch == '>') {
                    InsertToken(">>", OPE_DESC, RIGHT_MOVE, line);
                } else if (ch == '=') {
                    InsertToken(">=", OPE_DESC, GRT_EQUAL, line);
                } else {
                    InsertToken(">", OPE_DESC, GRT_THAN, line);
                    fseek(infile, -1L, SEEK_CUR);
                }
            }
            //处理|开头的运算符
            else if (ch == '|') {
                ch = fgetc(infile);
                if (ch == '|') {
                    InsertToken("||", OPE_DESC, OR, line);
                } else {
                    InsertToken("|", OPE_DESC, BYTE_OR, line);
                    fseek(infile, -1L, SEEK_CUR);
                }
            } else if (ch == '=') {
                ch = fgetc(infile);
                if (ch == '=') {
                    InsertToken("==", OPE_DESC, EQUAL, line);
                } else {
                    InsertToken("=", OPE_DESC, ASG, line);
                    fseek(infile, -1L, SEEK_CUR);
                }
            } else if (ch == '(') {
                InsertToken("(", CLE_OPE_DESC, LEFT_BRA, line);
            } else if (ch == ')') {
                InsertToken(")", CLE_OPE_DESC, RIGHT_BRA, line);
            } else if (ch == '[') {
                InsertToken("[", CLE_OPE_DESC, LEFT_INDEX, line);
            } else if (ch == ']') {
                InsertToken("]", CLE_OPE_DESC, RIGHT_INDEX, line);
            } else if (ch == '{') {
                InsertToken("{", CLE_OPE_DESC, L_BOUNDER, line);
            } else if (ch == '}') {
                InsertToken("}", CLE_OPE_DESC, R_BOUNDER, line);
            } else if (ch == '.') {
                InsertToken(".", CLE_OPE_DESC, POINTER, line);
            } else if (ch == ',') {
                InsertToken(",", CLE_OPE_DESC, COMMA, line);
            } else if (ch == ';') {
                InsertToken(";", CLE_OPE_DESC, SEMI, line);
            } else {
                char temp[2];
                temp[0] = ch;
                temp[1] = '\0';
                InsertError(temp, CHAR_ERROR, CHAR_ERROR_NUM, line);
            }
        }
        ch = fgetc(infile);
    }
    fclose(infile);
}

#endif
View Code

SA.h:语法分析 

#ifndef __SA__
#define __SA__
#include "stdafx.h"
#include "Macro_Struct.h"
#include "initialize.h"
#define unScalsble false
#define Scalable true
vector<pair<char *, bool>> Signature;
int CodeStack[5000], TryStack[5000], tokenId[5000];
int Csize = 0, Tsize = 0;
int Expr[100][100];
int ExprNum = 0;
bool First[100][100];
bool visited[100];
bool Follow[100][100];
bool Select[100][100];
int ShiftList[100][100][10][100];
bool canBeNull[100];
int ArrayFlag;
int FindSignature(char * str) {
    for (int i = 0; i < Signature.size(); i++) {
        if (strcmp(str, Signature[i].first) == 0) {
            return i;
        }
    }
    return -1;
}
int Try(int top, int sn, int ptr) {
    if (ptr < 0 || Tsize <= top) {
        return -10;
    }
    int Expl = TryStack[top];
    Tsize += (ShiftList[Expl][CodeStack[ptr]][sn][0] - 1);
    for (int i = 1; i <= ShiftList[Expl][CodeStack[ptr]][sn][0]; i++) {
        TryStack[Tsize - i] = ShiftList[Expl][CodeStack[ptr]][sn][i];
    }
    while (Tsize > top) {
        if (ptr < 0) {
            if (canBeNull[TryStack[Tsize - 1]]) {
                Tsize--;
                continue;
            } else {
                printf("Line%2d:%s can\' t explain as %s \n", tokenList[tokenId[0]].line, tokenList[tokenId[0]].content, Signature[Expl].first);
                return -10;
            }
        }
        if (TryStack[Tsize - 1] == CodeStack[ptr]) {
            Tsize--;
            ptr--;
            continue;
        }
        if (Signature[TryStack[Tsize - 1]].second == unScalsble) {
            printf("Line%2d:%s can\' t explain as %s \n", tokenList[tokenId[ptr]].line, tokenList[tokenId[ptr]].content, Signature[Expl].first);
            return -10;
        }
        if (ShiftList[TryStack[Tsize - 1]][CodeStack[ptr]][0][0] == 0) {
            if (canBeNull[TryStack[Tsize - 1]]) {
                Tsize--;
                continue;
            } else {
                printf("Line%2d:%s can\' t explain as %s \n", tokenList[tokenId[ptr]].line, tokenList[tokenId[ptr]].content, Signature[Expl].first);
                return -10;
            }
        }
        bool Match = false;
        for (int i = 1; i <= ShiftList[TryStack[Tsize - 1]][CodeStack[ptr]][0][0]; i++) {
            int tempTs = Tsize;
            int tempTi = TryStack[Tsize - 1];
            int ret = Try(Tsize - 1, i, ptr);
            if (ret != -10) {
                Match = true;
                ptr = ret;
                break;
            } else {
                Tsize = tempTs;
                TryStack[Tsize - 1] = tempTi;
            }
        }
        if (!Match) {
            printf("Line%2d:%s can\' t explain as %s \n", tokenList[tokenId[ptr]].line, tokenList[tokenId[ptr]].content, Signature[Expl].first);
            return -10;
        }
    }
    return ptr;
}
void Analyse() {
    for (int i = tokenList.size() - 1; i >= 0; i--) {
        if (tokenList[i].type == AUTO ||
                tokenList[i].type == CONST ||
                tokenList[i].type == UNSIGNED ||
                tokenList[i].type == SIGNED ||
                tokenList[i].type == STATIC ||
                tokenList[i].type == VOLATILE) {
            tokenId[Csize] = i;
            CodeStack[Csize++] = FindSignature("describe");
        } else if (tokenList[i].type == INT_VAL) {
            tokenId[Csize] = i;
            CodeStack[Csize++] = FindSignature("digit");
        } else if (tokenList[i].type == CHAR ||
                   tokenList[i].type == DOUBLE ||
                   tokenList[i].type == FLOAT ||
                   tokenList[i].type == INT ||
                   tokenList[i].type == LONG ||
                   tokenList[i].type == SHORT ||
                   tokenList[i].type == VOID) {
            tokenId[Csize] = i;
            CodeStack[Csize++] = FindSignature("type");
        } else if (tokenList[i].type == STRING_VAL) {
            tokenId[Csize] = i;
            CodeStack[Csize++] = FindSignature("string");
        } else if (tokenList[i].type == DOU_QUE ||
                   tokenList[i].type == SIN_QUE ||
                   tokenList[i].type == NOTE1 ||
                   tokenList[i].type == NOTE2) {
        } else if (tokenList[i].type == IDENTIFER) {
            tokenId[Csize] = i;
            CodeStack[Csize++] = FindSignature("id");
        } else if (tokenList[i].type == FOR) {
            tokenId[Csize] = i;
            CodeStack[Csize++] = FindSignature("for");
        } else if (tokenList[i].type == IF) {
            tokenId[Csize] = i;
            CodeStack[Csize++] = FindSignature("if");
        } else if (tokenList[i].type == ELSE) {
            tokenId[Csize] = i;
            CodeStack[Csize++] = FindSignature("else");
        } else if (tokenList[i].type == RETURN) {
            tokenId[Csize] = i;
            CodeStack[Csize++] = FindSignature("return");
        } else {
            tokenId[Csize] = i;
            CodeStack[Csize++] = FindSignature(tokenList[i].content);
        }
        if (tokenList[i].type != DOU_QUE && tokenList[i].type != SIN_QUE) {
            printf("%15s  %15s  %15d\n", Signature[CodeStack[Csize - 1]].first, tokenList[i].content, tokenList[i].type);
        }
    }
    ArrayFlag = -1;
    while (Csize) {
        if (ShiftList[0][CodeStack[Csize - 1]][0][0] == 0) {
            printf("Error:Line%2d %s\n", tokenList[tokenId[Csize - 1]].line, tokenList[tokenId[Csize - 1]].content);
            break;
        }
        bool Match = false;
        for (int i = 1; i <= ShiftList[0][CodeStack[Csize - 1]][0][0]; i++) {
            Tsize = 1;
            TryStack[0] = 0;
            int ret = Try(0, i, Csize - 1);
            if (ret != -10) {
                Match = true;
                Csize = ret + 1;
                break;
            }
        }
        if (!Match) {
            printf("Error:Line%2d %s\n", tokenList[tokenId[Csize - 1]].line, tokenList[tokenId[Csize - 1]].content);
            break;
        }
    }
    if (Csize == 0) {
        printf("Successful\n");
    }
}
#endif
View Code

 Macro_Struct.h:宏定义以及结构体定义

#ifndef __MS__
#define __MS__

#define AUTO 1
#define BREAK 2
#define CASE 3
#define CHAR 4
#define CONST 5
#define CONTINUE 6
#define DEFAULT 7
#define DO 8
#define DOUBLE 9
#define ELSE 10
#define ENUM 11
#define EXTERN 12
#define FLOAT 13
#define FOR 14
#define GOTO 15
#define IF 16
#define INT 17
#define LONG 18
#define REGISTER 19
#define RETURN 20
#define SHORT 21
#define SIGNED 22
#define SIZEOF 23
#define STATIC 24
#define STRUCT 25
#define SWITCH 26
#define TYPEDEF 27
#define UNION 28
#define UNSIGNED 29
#define VOID 30
#define VOLATILE 31
#define WHILE 32
#define KEY_DESC "关键字"

//标志符
#define IDENTIFER 40
#define IDENTIFER_DESC "标志符"

//常量
#define INT_VAL 51 //整形常量
#define CHAR_VAL 52 //字符常量
#define FLOAT_VAL 53 //浮点数常量
#define STRING_VAL 54 //双精度浮点数常量
#define MACRO_VAL 55 //宏常量
#define CONSTANT_DESC "常量"

//运算符
#define NOT 61   // !
#define BYTE_AND 62 //&
#define COMPLEMENT 63 // ~
#define BYTE_XOR  64 // ^
#define MUL 65 // *
#define DIV 66// /
#define MOD 67 // %
#define ADD 68 // +
#define SUB 69 // -
#define LES_THAN 70 // <
#define GRT_THAN 71 // >
#define ASG 72 // =
#define ARROW 73 // ->
#define SELF_ADD 74 // ++
#define SELF_SUB 75 // --
#define LEFT_MOVE 76 // <<
#define RIGHT_MOVE 77 // >>
#define LES_EQUAL 78 // <=
#define GRT_EQUAL 79 // >=
#define EQUAL 80 // ==
#define NOT_EQUAL 81 // !=
#define AND 82 // &&
#define OR 83 // ||
#define COMPLETE_ADD 84 // +=
#define COMPLETE_SUB 85 // -=
#define COMPLETE_MUL 86 // *=
#define COMPLETE_DIV 87 // /=
#define COMPLETE_BYTE_XOR 88 // ^=
#define COMPLETE_BYTE_AND 89 // &=
#define COMPLETE_COMPLEMENT 90 // ~=
#define COMPLETE_MOD 91 //%=
#define BYTE_OR 92 // |
#define OPE_DESC "运算符"

//限界符
#define LEFT_BRA 100 // (
#define RIGHT_BRA 101 // )
#define LEFT_INDEX 102 // [
#define RIGHT_INDEX 103 // ]
#define L_BOUNDER 104 //  {
#define R_BOUNDER 105 // }
#define POINTER 106 // .
#define JING 107 // #
#define UNDER_LINE 108 // _
#define COMMA 109 // ,
#define SEMI 110 // ;
#define SIN_QUE 111 // '
#define DOU_QUE 112 // "

#define CLE_OPE_DESC "限界符"

#define NOTE1 120 // "/**/"注释
#define NOTE2 121 // "//"注释
#define NOTE_DESC "注释"


#define HEADER 130 //头文件
#define HEADER_DESC "头文件"

//错误类型
#define FLOAT_ERROR "float表示错误"
#define FLOAT_ERROR_NUM 1
#define DOUBLE_ERROR "double表示错误"
#define DOUBLE_ERROR_NUM 2
#define NOTE_ERROR "注释没有结束符"
#define NOTE_ERROR_NUM 3
#define STRING_ERROR "字符串常量没有结束符"
#define STRING_ERROR_NUM 4
#define CHARCONST_ERROR "字符常量没有结束符"
#define CHARCONST_ERROR_NUM 5
#define CHAR_ERROR "非法字符"
#define CHAR_ERROR_NUM 6
#define LEFT_BRA_ERROR "'('没有对应项"
#define LEFT_BRA_ERROR_NUM 7
#define RIGHT_BRA_ERROR "')'没有对应项"
#define RIGHT_BRA_ERROR_NUM 8
#define LEFT_INDEX_ERROR "'['没有对应项"
#define LEFT_INDEX_ERROR_NUM 9
#define RIGHT_INDEX_ERROR "']'没有对应项"
#define RIGHT_INDEX_ERROR_NUM 10
#define L_BOUNDER_ERROR "'{'没有对应项"
#define L_BOUNDER_ERROR_NUM 11
#define R_BOUNDER_ERROR "'}'没有对应项"
#define R_BOUNDER_ERROR_NUM 12
#define PRE_PROCESS_ERROR "预处理错误" //头文件或者宏定义错误
#define PRE_PROCESS_ERROR_NUM  13

#define _NULL "无"

#define DESCRIBE 4000
#define TYPE 4001
#define STRING 4002
#define DIGIT 4003

struct Token
{
    char content[30];//内容
    char describe[30];//描述
    int type;//种别码
    int line;//所在行数
};

struct Error {
    char content[30];//错误内容
    char describe[30];//错误描述
    int type;
    int line;//所在行数
};

#endif
View Code

stdafx.h:头文件包含

#ifndef __STDAFX__
#define __STDAFX__

#include <iostream>
#include <fstream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vector>
#include <iomanip>
#include <stack>
#include <regex>
using namespace std;

#endif

input.txt:要检查的程序

---------------2016.9.23更新---------------

  又改了好几天,这个程序终于告一段落了,最近几天在之前的基础上又修改了一些错误,增加了一些功能,主要包括以下几个点:

  1.把函数的声明和定义分开,在头文件中声明,在源文件中实现。

  2.修改了声明语句必须放在相应部分的头部的缺陷。

  3.修改了程序不认识true和false等缺陷。

  4.增加了对break和continue语句正确性的检查。

  5.增加了允许多维数组的语法规则。

  6.修改了return后必须有数值的缺陷。

  7.修改了程序不认识<=和>=的缺陷。

  8.增加了允许在for循环的小括号中定义变量的规则。

  9.增加了类类型的定义规则。

  10.增加了使用变量时允许使用.操作符以使用其成员的规则。

  11.增加了允许一个表达式在任何可以使用数字的地方作为数字出现,如数组下标,函数参数,逻辑表达式和逻辑表达式的一项等的规则。

  12.修改了预处理部分不计算在行数内的缺陷。

  13.增加了大错误出现位置的大致定位功能。

  14.增加了检查出错误后跳过一定长度继续检查的功能。

全部代码:

  头文件:

  Macro_Struct.h

#include"stdafx.h"
#ifndef __MACRO__
#define __MACRO__

#define AUTO 1
#define BREAK 2
#define CASE 3
#define CHAR 4
#define CONST 5
#define CONTINUE 6
#define DEFAULT 7
#define DO 8
#define DOUBLE 9
#define ELSE 10
#define ENUM 11
#define EXTERN 12
#define FLOAT 13
#define FOR 14
#define GOTO 15
#define IF 16
#define INT 17
#define LONG 18
#define REGISTER 19
#define RETURN 20
#define SHORT 21
#define SIGNED 22
//#define SIZEOF 23
#define STATIC 24
#define STRUCT 25
#define SWITCH 26
#define TYPEDEF 27
#define UNION 28
#define UNSIGNED 29
#define VOID 30
#define VOLATILE 31
#define WHILE 32
#define BOOL 33
#define TRUE 34
#define FALSE 35
#define KEY_DESC "关键字"

//标志符
#define IDENTIFER 40
#define IDENTIFER_DESC "标志符"

//常量
#define INT_VAL 51 //整形常量
#define CHAR_VAL 52 //字符常量
#define FLOAT_VAL 53 //浮点数常量
#define STRING_VAL 54 //双精度浮点数常量
#define MACRO_VAL 55 //宏常量
#define CONSTANT_DESC "常量"

//运算符
#define NOT 61   // !
#define BYTE_AND 62 //&
#define COMPLEMENT 63 // ~
#define BYTE_XOR  64 // ^
#define MUL 65 // *
#define DIV 66// /
#define MOD 67 // %
#define ADD 68 // +
#define SUB 69 // -
#define LES_THAN 70 // <
#define GRT_THAN 71 // >
#define ASG 72 // =
#define ARROW 73 // ->
#define SELF_ADD 74 // ++
#define SELF_SUB 75 // --
#define LEFT_MOVE 76 // <<
#define RIGHT_MOVE 77 // >>
#define LES_EQUAL 78 // <=
#define GRT_EQUAL 79 // >=
#define EQUAL 80 // ==
#define NOT_EQUAL 81 // !=
#define AND 82 // &&
#define OR 83 // ||
#define COMPLETE_ADD 84 // +=
#define COMPLETE_SUB 85 // -=
#define COMPLETE_MUL 86 // *=
#define COMPLETE_DIV 87 // /=
#define COMPLETE_BYTE_XOR 88 // ^=
#define COMPLETE_BYTE_AND 89 // &=
#define COMPLETE_COMPLEMENT 90 // ~=
#define COMPLETE_MOD 91 //%=
#define BYTE_OR 92 // |
#define OPE_DESC "运算符"

//限界符
#define LEFT_BRA 100 // (
#define RIGHT_BRA 101 // )
#define LEFT_INDEX 102 // [
#define RIGHT_INDEX 103 // ]
#define L_BOUNDER 104 //  {
#define R_BOUNDER 105 // }
#define POINTER 106 // .
#define JING 107 // #
#define UNDER_LINE 108 // _
#define COMMA 109 // ,
#define SEMI 110 // ;
#define SIN_QUE 111 // '
#define DOU_QUE 112 // "

#define CLE_OPE_DESC "限界符"

#define NOTE1 120 // "/**/"注释
#define NOTE2 121 // "//"注释
#define NOTE_DESC "注释"


#define HEADER 130 //头文件
#define HEADER_DESC "头文件"

//错误类型
#define FLOAT_ERROR "float表示错误"
#define FLOAT_ERROR_NUM 1
#define DOUBLE_ERROR "double表示错误"
#define DOUBLE_ERROR_NUM 2
#define NOTE_ERROR "注释没有结束符"
#define NOTE_ERROR_NUM 3
#define STRING_ERROR "字符串常量没有结束符"
#define STRING_ERROR_NUM 4
#define CHARCONST_ERROR "字符常量没有结束符"
#define CHARCONST_ERROR_NUM 5
#define CHAR_ERROR "非法字符"
#define CHAR_ERROR_NUM 6
#define LEFT_BRA_ERROR "'('没有对应项"
#define LEFT_BRA_ERROR_NUM 7
#define RIGHT_BRA_ERROR "')'没有对应项"
#define RIGHT_BRA_ERROR_NUM 8
#define LEFT_INDEX_ERROR "'['没有对应项"
#define LEFT_INDEX_ERROR_NUM 9
#define RIGHT_INDEX_ERROR "']'没有对应项"
#define RIGHT_INDEX_ERROR_NUM 10
#define L_BOUNDER_ERROR "'{'没有对应项"
#define L_BOUNDER_ERROR_NUM 11
#define R_BOUNDER_ERROR "'}'没有对应项"
#define R_BOUNDER_ERROR_NUM 12
#define PRE_PROCESS_ERROR "预处理错误" //头文件或者宏定义错误
#define PRE_PROCESS_ERROR_NUM  13

#define _NULL "无"

#define DESCRIBE 4000
#define TYPE 4001
#define STRING 4002
#define DIGIT 4003

#define unScalsble false
#define Scalable true

#define SHOWTRYDETAIL false
#define MAXLENGTH 10000
#define MAXSIGN 200

struct Token {
    char content[300];//内容
    char describe[300];//描述
    int type;//种别码
    int line;//所在行数
};

struct Error {
    char content[300];//错误内容
    char describe[300];//错误描述
    int type;
    int line;//所在行数
};
#endif
View Code

   initial.h

#ifndef __INITIAL__
#define __INITIAL__
#include "Macro_Struct.h"
void InitKeyMap();
void InitOperMap();
void InitLimitMap();
int FindSignature(char * str);
void DFS_NullPossibility(int x);
void ShowExprList();
void ShowShiftList();
void ReadExpr();
void DFS_FirstSet(int x);
void GetFirstSet();
void GetSelectSet();
void GetShiftList();
void Init();

#endif
View Code

  SA.h

#ifndef __SA__
#define __SA__
#include "Macro_Struct.h"
#include "initial.h"
void ShowTryStack(FILE * ofile);
void ShowCodeStack(FILE * ofile, int ptr);
bool SelfDefineType(int x);
int SearchNext(int x);
int Try(int top, int sn, int ptr);
void Analyse();
#endif
View Code

  WA.h

#ifndef __WA__
#define __WA__
#include "Macro_Struct.h"
#include "initial.h"
int SeekKey(char * word);
void InsertToken(char * content, char * describe, int type, int line);
void InsertError___(char * content, char * describe, int type, int line);
void preProcess(char * word, int line);
void ShowTokenList();
void Scan();
void Bracket();
#endif
View Code

  stdafx.h

#ifndef __STDAFX__
#define __STDAFX__

#include <iostream>
#include <fstream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <vector>
#include <iomanip>
#include <stack>
#include <regex>
#include <map>
#include <windows.h>
#include <process.h>
using namespace std;

#endif
View Code

  源文件:

  initial.cpp

#include "stdafx.h"
#include "initial.h"
vector<pair<const char *, int>> keyMap;
vector<pair<const char *, int>> operMap;
vector<pair<const char *, int>> limitMap;
vector<Token> tokenList;
vector<Error> errorList;

vector<pair<char *, bool>> Signature;
int Expr[MAXSIGN][100];
int ExprNum = 0;
bool First[MAXSIGN][MAXSIGN];
bool visited[MAXSIGN];
bool Follow[MAXSIGN][MAXSIGN];
bool Select[MAXSIGN][MAXSIGN];
int ShiftList[MAXSIGN][MAXSIGN][10][100];
int LoopDepth[MAXLENGTH];
int BracketMatch[MAXLENGTH];
bool canBeNull[MAXSIGN];
int cnt;

void InitKeyMap() {
    keyMap.clear();
    keyMap.push_back(make_pair("auto", AUTO));
    keyMap.push_back(make_pair("break", BREAK));
    keyMap.push_back(make_pair("case", CASE));
    keyMap.push_back(make_pair("char", CHAR));
    keyMap.push_back(make_pair("const", CONST));
    keyMap.push_back(make_pair("continue", CONTINUE));
    keyMap.push_back(make_pair("default", DEFAULT));
    keyMap.push_back(make_pair("do", DO));
    keyMap.push_back(make_pair("double", DOUBLE));
    keyMap.push_back(make_pair("else", ELSE));
    keyMap.push_back(make_pair("enum", ENUM));
    keyMap.push_back(make_pair("extern", EXTERN));
    keyMap.push_back(make_pair("float", FLOAT));
    keyMap.push_back(make_pair("for", FOR));
    keyMap.push_back(make_pair("goto", GOTO));
    keyMap.push_back(make_pair("if", IF));
    keyMap.push_back(make_pair("int", INT));
    keyMap.push_back(make_pair("long", LONG));
    keyMap.push_back(make_pair("register", REGISTER));
    keyMap.push_back(make_pair("return", RETURN));
    keyMap.push_back(make_pair("short", SHORT));
    keyMap.push_back(make_pair("signed", SIGNED));
    //keyMap.push_back(make_pair("sizeof", SIZEOF));
    keyMap.push_back(make_pair("static", STATIC));
    keyMap.push_back(make_pair("struct", STRUCT));
    keyMap.push_back(make_pair("switch", SWITCH));
    keyMap.push_back(make_pair("typedef", TYPEDEF));
    keyMap.push_back(make_pair("union", UNION));
    keyMap.push_back(make_pair("unsigned", UNSIGNED));
    keyMap.push_back(make_pair("void", VOID));
    keyMap.push_back(make_pair("volatile", VOLATILE));
    keyMap.push_back(make_pair("while", WHILE));
    keyMap.push_back(make_pair("bool", BOOL));
    keyMap.push_back(make_pair("true", TRUE));
    keyMap.push_back(make_pair("false", FALSE));
    //keyMap.push_back(make_pair("describe", DESCRIBE));
    //keyMap.push_back(make_pair("type", TYPE));
    //keyMap.push_back(make_pair("string", STRING));
    //keyMap.push_back(make_pair("digit", DIGIT));
}
void InitOperMap() {
    operMap.clear();
    operMap.push_back(make_pair("!", NOT));
    operMap.push_back(make_pair("&", BYTE_AND));
    operMap.push_back(make_pair("~", COMPLEMENT));
    operMap.push_back(make_pair("^", BYTE_XOR));
    operMap.push_back(make_pair("*", MUL));
    operMap.push_back(make_pair("/", DIV));
    operMap.push_back(make_pair("%", MOD));
    operMap.push_back(make_pair("+", ADD));
    operMap.push_back(make_pair("-", SUB));
    operMap.push_back(make_pair("<", LES_THAN));
    operMap.push_back(make_pair(">", GRT_THAN));
    operMap.push_back(make_pair("=", ASG));
    operMap.push_back(make_pair("->", ARROW));
    operMap.push_back(make_pair("++", SELF_ADD));
    operMap.push_back(make_pair("--", SELF_SUB));
    operMap.push_back(make_pair("<<", LEFT_MOVE));
    operMap.push_back(make_pair(">>", RIGHT_MOVE));
    operMap.push_back(make_pair("<=", LES_EQUAL));
    operMap.push_back(make_pair(">=", GRT_EQUAL));
    operMap.push_back(make_pair("==", EQUAL));
    operMap.push_back(make_pair("!=", NOT_EQUAL));
    operMap.push_back(make_pair("&&", AND));
    operMap.push_back(make_pair("||", OR));
    operMap.push_back(make_pair("+=", COMPLETE_ADD));
    operMap.push_back(make_pair("-=", COMPLETE_SUB));
    operMap.push_back(make_pair("*=", COMPLETE_MUL));
    operMap.push_back(make_pair("/=", COMPLETE_DIV));
    operMap.push_back(make_pair("^=", COMPLETE_BYTE_XOR));
    operMap.push_back(make_pair("&=", COMPLETE_BYTE_AND));
    operMap.push_back(make_pair("~=", COMPLETE_COMPLEMENT));
    operMap.push_back(make_pair("%=", COMPLETE_MOD));
    operMap.push_back(make_pair("|", BYTE_OR));
}
void InitLimitMap() {
    limitMap.clear();
    limitMap.push_back(make_pair("(", LEFT_BRA));
    limitMap.push_back(make_pair(")", RIGHT_BRA));
    limitMap.push_back(make_pair("[", LEFT_INDEX));
    limitMap.push_back(make_pair("]", RIGHT_INDEX));
    limitMap.push_back(make_pair("{", L_BOUNDER));
    limitMap.push_back(make_pair("}", R_BOUNDER));
    limitMap.push_back(make_pair(".", POINTER));
    limitMap.push_back(make_pair("#", JING));
    limitMap.push_back(make_pair("_", UNDER_LINE));
    limitMap.push_back(make_pair(",", COMMA));
    limitMap.push_back(make_pair(";", SEMI));
    limitMap.push_back(make_pair("'", SIN_QUE));
    limitMap.push_back(make_pair("\"", DOU_QUE));
}
//计算符号所对应的数字
int FindSignature(char * str) {
    for (int i = 0; i < Signature.size(); i++) {
        if (strcmp(str, Signature[i].first) == 0) {
            return i;
        }
    }
    return -1;
}
//数字x对应的符号能否为空
void DFS_NullPossibility(int x) {
    //printf("%s\n",Signature[x].first);
    if (visited[x]) {
        return;
    }
    visited[x] = true;
    for (int i = 0; i < ExprNum; i++) {
        if (Expr[i][0] != x) {
            continue;
        }
        bool ret = true;
        for (int j = 2; j <= Expr[i][1]; j++) {
            DFS_NullPossibility(Expr[i][j]);
            ret &= canBeNull[Expr[i][j]];
        }
        if (ret) {
            visited[x] = true;
            canBeNull[x] = true;
            return;
        }
    }
}
//输出产生式列表
void ShowExprList() {
    for (int i = 0; i < ExprNum; i++) {
        printf("%s -> ", Signature[Expr[i][0]].first);
        for (int j = 2; j <= Expr[i][1]; j++) {
            printf("%s ", Signature[Expr[i][j]].first);
        }
        printf("\n");
    }
}
//输出状态转移关系
void ShowShiftList() {
    for (int i = 0; i < Signature.size(); i++) {
        for (int j = 0; j < Signature.size(); j++) {
            if (ShiftList[i][j][0][0] <= 1 || i == j) {
                continue;
            }
            printf("%3d %30s -> %30s\n", ShiftList[i][j][0][0], Signature[i].first, Signature[j].first);
            for (int k = 1; k <= ShiftList[i][j][0][0]; k++) {
                printf("---------->");
                for (int h = 1; h <= ShiftList[i][j][k][0]; h++) {
                    printf("%s ", Signature[ShiftList[i][j][k][h]].first);
                }
                printf("\n");
            }
        }
    }
}
//读入语法产生式
void ReadExpr() {
    Signature.clear();
    ifstream fin("Grammar.txt");
    char str[50][50];
    int Length = 0;
    while (fin >> str[Length]) {
        //读入一行产生式
        if (strcmp(str[Length], "#") == 0) {
            for (int i = 0; i < Length; i++) {
                if (strcmp(str[i], "->") == 0) {
                    Expr[ExprNum][i] = Length - 1;
                    continue;
                }
                //将产生式中新出现的符号添加至符号列表
                int signID = FindSignature(str[i]);
                if (signID == -1) {
                    int tempLen = strlen(str[i]);
                    //添加非终结符
                    if (str[i][0] == '<' && str[i][tempLen - 1] == '>') {
                        pair<char *, bool> tempPair;
                        tempPair.first = new char [tempLen + 1];
                        memcpy(tempPair.first, str[i], tempLen);
                        tempPair.first[tempLen] = '\0';
                        tempPair.second = Scalable;
                        Signature.push_back(tempPair);
                    } else {//添加终结符
                        pair<char *, bool> tempPair;
                        tempPair.first = new char [tempLen + 1];
                        memcpy(tempPair.first, str[i], tempLen);
                        tempPair.first[tempLen] = '\0';
                        tempPair.second = unScalsble;
                        Signature.push_back(tempPair);
                    }
                    signID = Signature.size() - 1;
                }
                Expr[ExprNum][i] = signID;
            }
            Length = 0;
            ExprNum++;
        } else {
            Length++;
        }
    }
    fin.close();
    //计算一个符号是否可以为空
    memset(canBeNull, false, sizeof(canBeNull));
    for (int i = 0; i < Signature.size(); i++) {
        if (strcmp(Signature[i].first, "$") == 0) {
            canBeNull[i] = true;
        }
    }
    memset(visited, false, sizeof(visited));
    for (int i = 0; i < Signature.size(); i++) {
        if (Signature[i].second == Scalable) {
            DFS_NullPossibility(i);
        }
    }
    //加入符号未定义符号
    pair<char *, bool> tempPair;
    tempPair.first = new char [6];
    memcpy(tempPair.first, "undef", 5);
    tempPair.first[5] = '\0';
    tempPair.second = unScalsble;
    Signature.push_back(tempPair);
    canBeNull[Signature.size() - 1] = false;
    //ShowExprList();
}
//求数字x对应的符号的First集
void DFS_FirstSet(int x) {
    if (visited[x] || Signature[x].second == unScalsble) {
        return;
    }
    visited[x] = true;
    for (int i = 0; i < ExprNum; i++) {
        if (Expr[i][0] != x) {
            continue;
        }
        for (int j = 2; j <= Expr[i][1]; j++) {
            if (Signature[Expr[i][j]].second == unScalsble) {
                First[x][Expr[i][j]] = true;
            } else {
                DFS_FirstSet(Expr[i][j]);
                for (int k = 0; k < Signature.size(); k++) {
                    if (First[Expr[i][j]][k]) {
                        First[x][k] = true;
                    }
                }
            }
            if (!canBeNull[Expr[i][j]]) {
                break;
            }
        }
    }
}
//求所有非终结符的First集
void GetFirstSet() {
    memset(First, false, sizeof(First));
    memset(visited, false, sizeof(visited));
    for (int i = 0; i < Signature.size(); i++) {
        if (Signature[i].second == unScalsble) {
            continue;
        }
        DFS_FirstSet(i);
    }
}
//求所有表达式的Select集
void GetSelectSet() {
    memset(Select, false, sizeof(Select));
    for (int i = 0; i < ExprNum; i++) {
        for (int j = 2; j <= Expr[i][1]; j++) {
            if (Signature[Expr[i][j]].second == unScalsble) {
                Select[i][Expr[i][j]] = true;
            } else {
                for (int k = 0; k < Signature.size(); k++) {
                    if (First[Expr[i][j]][k]) {
                        Select[i][k] = true;
                    }
                }
            }
            if (!canBeNull[Expr[i][j]]) {
                break;
            }
        }
        if (!canBeNull[Expr[i][0]]) {
            Select[i][FindSignature("$")] = false;
        }
    }
}
//求非终结符->终结符的状态转移关系
void GetShiftList() {
    memset(ShiftList, 0, sizeof(ShiftList));
    int i, j;
    for (i = 0; i < ExprNum; i++) {
        for (j = 0; j < Signature.size(); j++) {
            if (!Select[i][j]) {
                continue;
            }
            ShiftList[Expr[i][0]][j][0][0]++;
            for (int k = 1; k <= Expr[i][1]; k++) {
                ShiftList[Expr[i][0]][j][ShiftList[Expr[i][0]][j][0][0]][k - 1] = Expr[i][k];
            }
            ShiftList[ Expr[i][0] ] [j] [ ShiftList[Expr[i][0]][j][0][0] ] [0]--;
        }
    }
    //ShowShiftList();
}
//初始化语法
void Init() {
    InitKeyMap();//初始化关键字
    InitOperMap();//初始化操作符
    InitLimitMap();//初始化限界符
    tokenList.clear();
    errorList.clear();
    memset(LoopDepth, 0, sizeof(LoopDepth));
    memset(BracketMatch, 0, sizeof(BracketMatch));
    ReadExpr();//读入语法产生式
    GetFirstSet();//计算First集
    GetSelectSet();//计算Select集
    GetShiftList();//计算状态转移关系
}
View Code

  WA.cpp

#include "stdafx.h"
#include "WA.h"
extern vector<pair<const char *, int>> keyMap;
extern vector<pair<const char *, int>> operMap;
extern vector<pair<const char *, int>> limitMap;
extern vector<Token> tokenList;
extern vector<Error> errorList;
extern int LoopDepth[MAXLENGTH];
extern int BracketMatch[MAXLENGTH];
int BracStack[MAXLENGTH];
int Bsize;
FILE * WAofile;
errno_t WAerr = fopen_s(&WAofile, "WA.txt", "w");
//求字符串对应的关键字
int SeekKey(char * word) {
    for (int i = 0; i < keyMap.size(); i++) {
        if (strcmp(word, keyMap[i].first) == 0) {
            return keyMap[i].second;
        }
    }
    return IDENTIFER;
}
//加入一个token
void InsertToken(char * content, char * describe, int type, int line) {
    Token tempToken;
    strcpy_s(tempToken.content, content);
    strcpy_s(tempToken.describe, describe);
    tempToken.type = type;
    tempToken.line = line;
    tokenList.push_back(tempToken);
}
//加入一个错误
void InsertError___(char * content, char * describe, int type, int line) {
    Error tempError;
    strcpy_s(tempError.content, content);
    strcpy_s(tempError.describe, describe);
    tempError.type = type;
    tempError.line = line;
    errorList.push_back(tempError);
    printf("Error:Line %d:%s\n", line, describe);
}
//检查预处理语句
void preProcess(char * word, int line) {
    regex INCLUDE_REGEX("#include\\s*<[a-zA-Z0-9_\\.]+>\\s*");
    regex DEFINE_REGEX("#define\\s+\\w+\\s+\\w+\\s*");
    if (regex_match(word, INCLUDE_REGEX)) {
        return;
    }
    if (regex_match(word, DEFINE_REGEX)) {
        return;
    }
    InsertError___(word, PRE_PROCESS_ERROR, PRE_PROCESS_ERROR_NUM, line);
}
//输出token列表
void ShowTokenList() {
    fprintf_s(WAofile, "\n------------------------------------------------------------------------------\n");
    fprintf_s(WAofile, "%20s %20s  %20s\n", "单词", "描述", "行数");
    for (int i = 0; i < tokenList.size(); i++) {
        fprintf_s(WAofile, "%20s %20s %20d\n", tokenList[i].content, tokenList[i].describe, tokenList[i].line);
    }
    fprintf_s(WAofile, "\n------------------------------------------------------------------------------\n");
}
//读入输入文件,分词
void Scan() {
    char ch;
    char array[300];//单词长度上限是30
    char word[300];
    int i;
    int line = 1;//行数
    FILE * infile;
    errno_t err = fopen_s(&infile, "input.txt", "r");
    ch = fgetc(infile);
    while (ch != EOF) {
        i = 0;
        //以字母或者下划线开头,处理关键字或者标识符
        if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || ch == '_') {
            while ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9') || ch == '_') {
                array[i++] = ch;
                ch = fgetc(infile);
            }
            memcpy(word, array, i);
            word[i] = '\0';
            int seekTemp = SeekKey(word);
            if (seekTemp != IDENTIFER) {
                InsertToken(word, KEY_DESC, seekTemp, line);
            } else {
                InsertToken(word, IDENTIFER_DESC, seekTemp, line);
            }
            fseek(infile, -1L, SEEK_CUR); //向后回退一位
        }
        //以数字开头,处理数字
        else if (ch >= '0' && ch <= '9') {
            int flag = 0;
            int flag2 = 0;
            //处理整数
            while (ch >= '0' && ch <= '9') {
                array[i++] = ch;
                ch = fgetc(infile);
            }
            //处理float
            if (ch == '.') {
                flag2 = 1;
                array[i++] = ch;
                ch = fgetc(infile);
                if (ch >= '0' && ch <= '9') {
                    while (ch >= '0' && ch <= '9') {
                        array[i++] = ch;
                        ch = fgetc(infile);
                    }
                } else {
                    flag = 1;
                }
                //处理Double
                if (ch == 'E' || ch == 'e') {
                    array[i++] = ch;
                    ch = fgetc(infile);
                    if (ch == '+' || ch == '-') {
                        array[i++] = ch;
                        ch = fgetc(infile);
                    }
                    if (ch >= '0' && ch <= '9') {
                        array[i++] = ch;
                        ch = fgetc(infile);
                    } else {
                        flag = 2;
                    }
                }
            }
            memcpy(word, array, i);
            word[i] = '\0';
            if (flag == 1) {
                InsertError___(word, FLOAT_ERROR, FLOAT_ERROR_NUM, line);
            } else if (flag == 2) {
                InsertError___(word, DOUBLE_ERROR, DOUBLE_ERROR_NUM, line);
            } else {
                if (flag2 == 0) {
                    InsertToken(word, CONSTANT_DESC, INT_VAL, line);
                } else {
                    InsertToken(word, CONSTANT_DESC, FLOAT_VAL, line);
                }
            }
            fseek(infile, -1L, SEEK_CUR); //向后回退一位
        }
        //以"/"开头
        else if (ch == '/') {
            ch = fgetc(infile);
            //处理运算符"/="
            if (ch == '=') {
                InsertToken("/=", OPE_DESC, COMPLETE_DIV, line);
            }
            //处理"/**/"型注释
            else if (ch == '*') {
                ch =  fgetc(infile);
                while (1) {
                    while (ch != '*') {
                        if (ch == '\n') {
                            line++;
                        }
                        ch = fgetc(infile);
                        if (ch == EOF) {
                            InsertError___(_NULL, NOTE_ERROR, NOTE_ERROR_NUM, line);
                            return;
                        }
                    }
                    ch = fgetc(infile);
                    if (ch == '/') {
                        break;
                    }
                    if (ch == EOF) {
                        InsertError___(_NULL, NOTE_ERROR, NOTE_ERROR_NUM, line);
                        return;
                    }
                }
                InsertToken(_NULL, NOTE_DESC, NOTE1, line);
            }
            //处理"//"型注释
            else if (ch == '/') {
                while (ch != '\n') {
                    ch = fgetc(infile);
                    if (ch == EOF) {
                        InsertToken(_NULL, NOTE_DESC, NOTE2, line);
                        return;
                    }
                }
                line++;
                InsertToken(_NULL, NOTE_DESC, NOTE2, line);
                if (ch == EOF) {
                    return;
                }
            }
            //处理除号
            else {
                InsertToken("/", OPE_DESC, DIV, line);
            }
        }
        //处理常量字符串
        else if (ch == '"') {
            InsertToken("\"", CLE_OPE_DESC, DOU_QUE, line);
            ch = fgetc(infile);
            i = 0;
            while (ch != '"') {
                array[i++] = ch;
                if (ch == '\n') {
                    line++;
                }
                if (ch == '\\') {
                    array[i++] = ch;
                    ch = fgetc(infile);
                    array[i++] = ch;
                }
                ch = fgetc(infile);
                if (ch == EOF) {
                    InsertError___(_NULL, STRING_ERROR, STRING_ERROR_NUM, line);
                    break;
                }
            }
            memcpy(word, array, i);
            word[i] = '\0';
            InsertToken(word, CONSTANT_DESC, STRING_VAL, line);
            InsertToken("\"", CLE_OPE_DESC, DOU_QUE, line);
        }
        //处理常量字符
        else if (ch == '\'') {
            InsertToken("\'", CLE_OPE_DESC, SIN_QUE, line);
            ch = fgetc(infile);
            i = 0;
            while (ch != '\'') {
                array[i++] = ch;
                if (ch == '\n') {
                    line++;
                }
                if (ch == '\\') {
                    array[i++] = ch;
                    ch = fgetc(infile);
                    array[i++] = ch;
                }
                ch = fgetc(infile);
                if (ch == EOF) {
                    InsertError___(_NULL, CHARCONST_ERROR, CHARCONST_ERROR_NUM, line);
                    break;
                }
            }
            memcpy(word, array, i);
            word[i] = '\0';
            InsertToken(word, CONSTANT_DESC, CHAR_VAL, line);
            InsertToken("\'", CLE_OPE_DESC, SIN_QUE, line);
        } else if (ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n') {
            if (ch == '\n') {
                line++;
            }
        } else {
            if (ch == EOF) {
                return;
            }
            //处理头文件和宏常量(预处理)
            else if (ch == '#') {
                while (ch != '\n' && ch != EOF) {
                    array[i++] = ch;
                    ch = fgetc(infile);
                }
                line++;
                memcpy(word, array, i);
                word[i] = '\0';
                preProcess(word, line);
                //fseek(infile, -1L, SEEK_CUR); //向后回退一位
            }
            //处理-开头的运算符
            else if (ch == '-') {
                array[i++] = ch;
                ch = fgetc(infile);
                if (ch >= '0' && ch <= '9') {
                    int flag = 0;
                    int flag2 = 0;
                    //处理整数
                    while (ch >= '0' && ch <= '9') {
                        array[i++] = ch;
                        ch = fgetc(infile);
                    }
                    //处理float
                    if (ch == '.') {
                        flag2 = 1;
                        array[i++] = ch;
                        ch = fgetc(infile);
                        if (ch >= '0' && ch <= '9') {
                            while (ch >= '0' && ch <= '9') {
                                array[i++] = ch;
                                ch = fgetc(infile);
                            }
                        } else {
                            flag = 1;
                        }
                        //处理Double
                        if (ch == 'E' || ch == 'e') {
                            array[i++] = ch;
                            ch = fgetc(infile);
                            if (ch == '+' || ch == '-') {
                                array[i++] = ch;
                                ch = fgetc(infile);
                            }
                            if (ch >= '0' && ch <= '9') {
                                array[i++] = ch;
                                ch = fgetc(infile);
                            } else {
                                flag = 2;
                            }
                        }
                    }
                    memcpy(word, array, i);
                    word[i] = '\0';
                    if (flag == 1) {
                        InsertError___(word, FLOAT_ERROR, FLOAT_ERROR_NUM, line);
                    } else if (flag == 2) {
                        InsertError___(word, DOUBLE_ERROR, DOUBLE_ERROR_NUM, line);
                    } else {
                        if (flag2 == 0) {
                            InsertToken(word, CONSTANT_DESC, INT_VAL, line);
                        } else {
                            InsertToken(word, CONSTANT_DESC, FLOAT_VAL, line);
                        }
                    }
                    fseek(infile, -1L, SEEK_CUR); //向后回退一位
                } else if (ch == '>') {
                    InsertToken("->", OPE_DESC, ARROW, line);
                } else if (ch == '-') {
                    InsertToken("--", OPE_DESC, SELF_SUB, line);
                } else if (ch == '=') {
                    InsertToken("--", OPE_DESC, SELF_SUB, line);
                } else {
                    InsertToken("-", OPE_DESC, SUB, line);
                    fseek(infile, -1L, SEEK_CUR);
                }
            }
            //处理+开头的运算符
            else if (ch == '+') {
                ch = fgetc(infile);
                if (ch == '+') {
                    InsertToken("++", OPE_DESC, SELF_ADD, line);
                } else if (ch == '=') {
                    InsertToken("+=", OPE_DESC, COMPLETE_ADD, line);
                } else {
                    InsertToken("+", OPE_DESC, ADD, line);
                    fseek(infile, -1L, SEEK_CUR);
                }
            }
            //处理*开头的运算符
            else if (ch == '*') {
                ch = fgetc(infile);
                if (ch == '=') {
                    InsertToken("*=", OPE_DESC, COMPLETE_MUL, line);
                } else {
                    InsertToken("*", OPE_DESC, MUL, line);
                    fseek(infile, -1L, SEEK_CUR);
                }
            }
            //处理按^开头的运算符
            else if (ch == '^') {
                ch = fgetc(infile);
                if (ch == '=') {
                    InsertToken("^=", OPE_DESC, COMPLETE_BYTE_XOR, line);
                } else {
                    InsertToken("^", OPE_DESC, BYTE_XOR, line);
                    fseek(infile, -1L, SEEK_CUR);
                }
            }
            //处理%开头的运算符
            else if (ch == '%') {
                ch = fgetc(infile);
                if (ch == '=') {
                    InsertToken("%=", OPE_DESC, COMPLETE_MOD, line);
                } else {
                    InsertToken("%", OPE_DESC, MOD, line);
                    fseek(infile, -1L, SEEK_CUR);
                }
            }
            //处理&开头的运算符
            else if (ch == '&') {
                ch = fgetc(infile);
                if (ch == '=') {
                    InsertToken("&=", OPE_DESC, COMPLETE_BYTE_AND, line);
                } else if (ch == '&') {
                    InsertToken("&&", OPE_DESC, AND, line);
                } else {
                    InsertToken("&", OPE_DESC, BYTE_AND, line);
                    fseek(infile, -1L, SEEK_CUR);
                }
            }
            //处理~开头的运算符
            else if (ch == '~') {
                ch = fgetc(infile);
                if (ch == '=') {
                    InsertToken("~=", OPE_DESC, COMPLETE_COMPLEMENT, line);
                } else {
                    InsertToken("~", OPE_DESC, COMPLEMENT, line);
                    fseek(infile, -1L, SEEK_CUR);
                }
            }
            //处理!开头的运算符
            else if (ch == '!') {
                ch = fgetc(infile);
                if (ch == '=') {
                    InsertToken("!=", OPE_DESC, NOT_EQUAL, line);
                } else {
                    InsertToken("!", OPE_DESC, NOT, line);
                    fseek(infile, -1L, SEEK_CUR);
                }
            }
            //处理<开头的运算符
            else if (ch == '<') {
                ch = fgetc(infile);
                if (ch == '<') {
                    InsertToken("<<", OPE_DESC, LEFT_MOVE, line);
                } else if (ch == '=') {
                    InsertToken("<=", OPE_DESC, LES_EQUAL, line);
                } else {
                    InsertToken("<", OPE_DESC, LES_THAN, line);
                    fseek(infile, -1L, SEEK_CUR);
                }
            }
            //处理>开头的运算符
            else if (ch == '>') {
                ch = fgetc(infile);
                if (ch == '>') {
                    InsertToken(">>", OPE_DESC, RIGHT_MOVE, line);
                } else if (ch == '=') {
                    InsertToken(">=", OPE_DESC, GRT_EQUAL, line);
                } else {
                    InsertToken(">", OPE_DESC, GRT_THAN, line);
                    fseek(infile, -1L, SEEK_CUR);
                }
            }
            //处理|开头的运算符
            else if (ch == '|') {
                ch = fgetc(infile);
                if (ch == '|') {
                    InsertToken("||", OPE_DESC, OR, line);
                } else {
                    InsertToken("|", OPE_DESC, BYTE_OR, line);
                    fseek(infile, -1L, SEEK_CUR);
                }
            } else if (ch == '=') {
                ch = fgetc(infile);
                if (ch == '=') {
                    InsertToken("==", OPE_DESC, EQUAL, line);
                } else {
                    InsertToken("=", OPE_DESC, ASG, line);
                    fseek(infile, -1L, SEEK_CUR);
                }
            } else if (ch == '(') {
                InsertToken("(", CLE_OPE_DESC, LEFT_BRA, line);
            } else if (ch == ')') {
                InsertToken(")", CLE_OPE_DESC, RIGHT_BRA, line);
            } else if (ch == '[') {
                InsertToken("[", CLE_OPE_DESC, LEFT_INDEX, line);
            } else if (ch == ']') {
                InsertToken("]", CLE_OPE_DESC, RIGHT_INDEX, line);
            } else if (ch == '{') {
                InsertToken("{", CLE_OPE_DESC, L_BOUNDER, line);
            } else if (ch == '}') {
                InsertToken("}", CLE_OPE_DESC, R_BOUNDER, line);
            } else if (ch == '.') {
                InsertToken(".", CLE_OPE_DESC, POINTER, line);
            } else if (ch == ',') {
                InsertToken(",", CLE_OPE_DESC, COMMA, line);
            } else if (ch == ';') {
                InsertToken(";", CLE_OPE_DESC, SEMI, line);
            } else {
                char temp[2];
                temp[0] = ch;
                temp[1] = '\0';
                InsertError___(temp, CHAR_ERROR, CHAR_ERROR_NUM, line);
            }
        }
        ch = fgetc(infile);
    }
    fclose(infile);
    for (int i = 1; i < tokenList.size(); i++) {
        if (tokenList[i - 1].type == STRUCT && tokenList[i].type == IDENTIFER) {
            tokenList[i].type = TYPE;
        }
    }
    ShowTokenList();
}
//检查括号是否匹配
void Bracket() {
    //大括号
    Bsize = 0;
    for (int i = 0; i < tokenList.size(); i++) {
        if (strcmp(tokenList[i].content, "{") == 0) {
            BracStack[Bsize++] = i;
        }
        if (strcmp(tokenList[i].content, "}") == 0) {
            if (Bsize) {
                if (strcmp(tokenList[BracStack[Bsize - 1]].content, "{") == 0) {
                    BracketMatch[BracStack[Bsize - 1]] = i;
                    BracketMatch[i] = BracStack[Bsize - 1];
                    Bsize--;
                } else {
                    BracStack[Bsize++] = i;
                }
            } else {
                BracStack[Bsize++] = i;
            }
        }
    }
    for (int i = 0; i < Bsize; i++) {
        if (strcmp(tokenList[BracStack[i]].content, "{") == 0) {
            printf("Error:Line %d:expect }\n", tokenList[BracStack[i]].line);
        } else {
            printf("Error:Line %d:unexpected }\n", tokenList[BracStack[i]].line);
        }
    }
    //中括号
    Bsize = 0;
    for (int i = 0; i < tokenList.size(); i++) {
        if (strcmp(tokenList[i].content, "[") == 0) {
            BracStack[Bsize++] = i;
        }
        if (strcmp(tokenList[i].content, "]") == 0) {
            if (Bsize) {
                if (strcmp(tokenList[BracStack[Bsize - 1]].content, "[") == 0) {
                    BracketMatch[BracStack[Bsize - 1]] = i;
                    BracketMatch[i] = BracStack[Bsize - 1];
                    Bsize--;
                } else {
                    BracStack[Bsize++] = i;
                }
            } else {
                BracStack[Bsize++] = i;
            }
        }
    }
    for (int i = 0; i < Bsize; i++) {
        if (strcmp(tokenList[BracStack[i]].content, "[") == 0) {
            printf("Error:Line %d:expect ]\n", tokenList[BracStack[i]].line);
        } else {
            printf("Error:Line %d:unexpected ]\n", tokenList[BracStack[i]].line);
        }
    }
    //小括号
    Bsize = 0;
    for (int i = 0; i < tokenList.size(); i++) {
        if (strcmp(tokenList[i].content, "(") == 0) {
            BracStack[Bsize++] = i;
        }
        if (strcmp(tokenList[i].content, ")") == 0) {
            if (Bsize) {
                if (strcmp(tokenList[BracStack[Bsize - 1]].content, "(") == 0) {
                    BracketMatch[BracStack[Bsize - 1]] = i;
                    BracketMatch[i] = BracStack[Bsize - 1];
                    Bsize--;
                } else {
                    BracStack[Bsize++] = i;
                }
            } else {
                BracStack[Bsize++] = i;
            }
        }
    }
    for (int i = 0; i < Bsize; i++) {
        if (strcmp(tokenList[BracStack[i]].content, "(") == 0) {
            printf("Error:Line %d:expect )\n", tokenList[BracStack[i]].line);
        } else {
            printf("Error:Line %d:unexpected )\n", tokenList[BracStack[i]].line);
        }
    }
    //计算每个token所在的循环深度
    int l, r;
    for (int i = 0; i < tokenList.size(); i++) {
        if (strcmp(tokenList[i].content, "for") == 0 || strcmp(tokenList[i].content, "while") == 0) {
            l = tokenList.size();
            for (int j = i + 1; j < tokenList.size(); j++) {
                if (strcmp(tokenList[j].content, "{") == 0) {
                    l = j;
                    break;
                }
            }
            r = (BracketMatch[l] == 0 ? tokenList.size() : BracketMatch[l]);
            for (int j = l; j <= r; j++) {
                LoopDepth[j]++;
            }
        }
    }
}
View Code

  SA.cpp

#include "stdafx.h"
#include "SA.h"

extern vector<Token> tokenList;
extern vector<pair<char *, bool>> Signature;
int CodeStack[MAXLENGTH], TryStack[MAXLENGTH], tokenId[MAXLENGTH];
int Csize = 0, Tsize = 0;
extern int ShiftList[MAXSIGN][MAXSIGN][10][100];
extern bool canBeNull[MAXSIGN];
extern int LoopDepth[MAXLENGTH];
extern int cnt;
int keyWord;
int ErrorCnt;
FILE * ofile;
errno_t err = fopen_s(&ofile, "detail.txt", "w");
int tokenNeed, tokenFound, unMatchLine, unMatchPtr, tryLength;
FILE * SAofile;
errno_t SAerr = fopen_s(&SAofile, "SA.txt", "w");
//输出匹配栈
void ShowTryStack(FILE * ofile) {
    if (Tsize <= 0) {
        printf("OMG\n");
    }
    fprintf_s(ofile, "\n-----------------------------------------------------------------------------------------------------------------\n");
    fprintf_s(ofile, "%15s     ", "TryStack:");
    for (int i = Tsize - 1; i >= 0; i--) {
        fprintf_s(ofile, "%s ", Signature[TryStack[i]].first);
    }
    fprintf_s(ofile, "\n");
}
//输出程序栈
void ShowCodeStack(FILE * ofile, int ptr) {
    fprintf_s(ofile, "%15s     ", "CodeStack:");
    for (int i = ptr; i >= 0; i--) {
        fprintf_s(ofile, "%s ", Signature[CodeStack[i]].first);
    }
    fprintf_s(ofile, "\n");
    fprintf_s(ofile, "-----------------------------------------------------------------------------------------------------------------\n");
}
//标识符是否为自定义类型
bool SelfDefineType(int x) {
    for (int i = 0; i < x; i++)
        if (strcmp(tokenList[i].content, tokenList[x].content) == 0 && tokenList[i].type == TYPE) {
            return true;
        }
    return false;
}
//匹配失败后重新开始位置
int SearchNext(int x) {
    int Mor = 0;
    bool changed = false;
    for (int i = x; i >= 0; i--) {
        if (strcmp(Signature[CodeStack[i]].first, "{") == 0) {
            Mor += 10000;
            changed = true;
        }
        if (strcmp(Signature[CodeStack[i]].first, "[") == 0) {
            Mor += 100;
            changed = true;
        }
        if (strcmp(Signature[CodeStack[i]].first, "(") == 0) {
            Mor += 1;
            changed = true;
        }
        if (strcmp(Signature[CodeStack[i]].first, "}") == 0) {
            Mor -= 10000;
            changed = true;
        }
        if (strcmp(Signature[CodeStack[i]].first, "]") == 0) {
            Mor -= 100;
            changed = true;
        }
        if (strcmp(Signature[CodeStack[i]].first, ")") == 0) {
            Mor -= 1;
            changed = true;
        }
        if (Mor == 0 && changed) {
            return i - 1;
        }
    }
    return -1;
}
//尝试展开非终结符
int Try(int top, int sn, int ptr) {
    if (ptr < 0 || Tsize <= top) {
        return -10;
    }
    int Expl = TryStack[top];
    Tsize += (ShiftList[Expl][CodeStack[ptr]][sn][0] - 1);
    for (int i = 1; i <= ShiftList[Expl][CodeStack[ptr]][sn][0]; i++) {
        TryStack[Tsize - i] = ShiftList[Expl][CodeStack[ptr]][sn][i];
    }
    keyWord = Expl;
    while (Tsize > top) {
        //fprintf_s(ofile, "\n%d", ++cnt);
        //ShowTryStack(ofile);
        //ShowCodeStack(ofile, ptr);
        //若程序栈为空
        if (ptr < 0) {
            if (canBeNull[TryStack[Tsize - 1]]) {
                Tsize--;
                continue;
            } else {
                if (SHOWTRYDETAIL) {
                    printf("Line %2d:%s:%s can\' t explain as %s \n", tokenList[tokenId[0]].line, Signature[keyWord].first, tokenList[tokenId[0]].content, Signature[TryStack[top]].first);
                }
                if ((unMatchPtr > ptr) || ((unMatchPtr == ptr) && (Tsize > tryLength))) {
                    unMatchPtr = ptr;
                    tryLength = Tsize;
                    tokenNeed = TryStack[Tsize - 1];
                    tokenFound = -1;
                    unMatchLine = tokenList[tokenId[0]].line;
                }
                return -10;
            }
        }
        //未定义符号
        if (CodeStack[ptr] == Signature.size() - 1) {
            printf("Error %d:Line %d:undefined sign     <--------\n", ++ErrorCnt, tokenList[tokenId[ptr]].line);
            ptr--;
            continue;
        }
        //是否为break或continue语句
        if (strcmp(Signature[CodeStack[ptr]].first, "break") == 0 || strcmp(Signature[CodeStack[ptr]].first, "continue") == 0) {
            if (LoopDepth[tokenId[ptr]] == 0) {
                printf("Error %d:Line %d:can\'t break or continue out of loop     <--------\n", ++ErrorCnt, tokenList[tokenId[ptr]].line);
            }
            ptr--;
            if (ptr >= 0) {
                if (strcmp(Signature[CodeStack[ptr]].first, ";") == 0) {
                    ptr--;
                } else {
                    printf("Error %d:Line %d:expect ;     <--------\n", ++ErrorCnt, tokenList[tokenId[ptr]].line);
                }
            } else {
                printf("Error %d:Line %d:expect ;     <--------\n", ++ErrorCnt, tokenList[tokenId[ptr]].line);
            }
        }
        //若两栈栈顶元素相同
        if (TryStack[Tsize - 1] == CodeStack[ptr]) {
            Tsize--;
            ptr--;
            continue;
        }
        //若匹配栈栈顶为终结符
        if (Signature[TryStack[Tsize - 1]].second == unScalsble) {
            if (SHOWTRYDETAIL) {
                printf("Line %2d:%s:%s can\' t explain as %s \n", tokenList[tokenId[0]].line, Signature[keyWord].first, tokenList[tokenId[0]].content, Signature[TryStack[top]].first);
            }
            if ((unMatchPtr > ptr) || ((unMatchPtr == ptr) && (Tsize > tryLength))) {
                unMatchPtr = ptr;
                tryLength = Tsize;
                tokenNeed = TryStack[Tsize - 1];
                tokenFound = CodeStack[ptr];
                unMatchLine = tokenList[tokenId[ptr]].line;
            }
            return -10;
        }
        //若无法由匹配栈栈顶转移至程序栈栈顶
        if (ShiftList[TryStack[Tsize - 1]][CodeStack[ptr]][0][0] == 0) {
            if (canBeNull[TryStack[Tsize - 1]]) {
                Tsize--;
                continue;
            } else {
                if (SHOWTRYDETAIL) {
                    printf("Line %2d:%s:%s can\' t explain as %s \n", tokenList[tokenId[0]].line, Signature[keyWord].first, tokenList[tokenId[0]].content, Signature[TryStack[top]].first);
                }
                if ((unMatchPtr > ptr) || ((unMatchPtr == ptr) && (Tsize > tryLength))) {
                    unMatchPtr = ptr;
                    tryLength = Tsize;
                    tokenNeed = TryStack[Tsize - 1];
                    tokenFound = CodeStack[ptr];
                    unMatchLine = tokenList[tokenId[ptr]].line;
                }
                return -10;
            }
        }
        //将匹配站栈顶按状态转移关系展开
        if (ShiftList[TryStack[Tsize - 1]][CodeStack[ptr]][0][0] == 1) {
            int temp = TryStack[Tsize - 1];
            keyWord = temp;
            Tsize += (ShiftList[temp][CodeStack[ptr]][1][0] - 1);
            for (int i = 1; i <= ShiftList[temp][CodeStack[ptr]][1][0]; i++) {
                TryStack[Tsize - i] = ShiftList[temp][CodeStack[ptr]][1][i];
            }
        } else {
            bool Match = false;
            int tempKeyWord = keyWord;
            int tempTs = Tsize;
            int tempTi = TryStack[Tsize - 1];
            int tempPtr = ptr;
            int MINptr = ptr;
            for (int i = ShiftList[TryStack[tempTs - 1]][CodeStack[tempPtr]][0][0]; i >= 1; i--) {
                int ret = Try(Tsize - 1, i, tempPtr);
                if (ret != -10) {
                    Match = true;
                    if (MINptr > ret) {
                        MINptr = ret;
                    }
                }
                Tsize = tempTs;
                TryStack[Tsize - 1] = tempTi;
            }
            if (!Match) {
                if (SHOWTRYDETAIL) {
                    printf("Line %2d:%s:%s can\' t explain as %s \n", tokenList[tokenId[0]].line, Signature[keyWord].first, tokenList[tokenId[0]].content, Signature[TryStack[top]].first);
                }
                if ((unMatchPtr > ptr) || ((unMatchPtr == ptr) && (Tsize > tryLength))) {
                    unMatchPtr = ptr;
                    tryLength = Tsize;
                    tokenNeed = TryStack[Tsize - 1];
                    tokenFound = CodeStack[ptr];
                    unMatchLine = tokenList[tokenId[ptr]].line;
                }
                return -10;
            } else {
                ptr = MINptr;
                Tsize--;
            }
            keyWord = tempKeyWord;
        }
    }
    return ptr;
}
//插入符号
void InsertSign(int i) {
    if (tokenList[i].type == AUTO || tokenList[i].type == CONST || tokenList[i].type == UNSIGNED || tokenList[i].type == SIGNED ||
            tokenList[i].type == STATIC || tokenList[i].type == VOLATILE) {
        tokenId[Csize] = i;
        CodeStack[Csize++] = FindSignature("describe");
    } else if (tokenList[i].type == INT_VAL || tokenList[i].type == FLOAT_VAL || tokenList[i].type == CHAR_VAL || tokenList[i].type == TRUE ||
               tokenList[i].type == FALSE) {
        tokenId[Csize] = i;
        CodeStack[Csize++] = FindSignature("digit");
    } else if (tokenList[i].type == CHAR || tokenList[i].type == DOUBLE || tokenList[i].type == FLOAT || tokenList[i].type == INT ||
               tokenList[i].type == LONG || tokenList[i].type == SHORT || tokenList[i].type == VOID || tokenList[i].type == BOOL ||
               tokenList[i].type == TYPE || SelfDefineType(i)) {
        tokenId[Csize] = i;
        CodeStack[Csize++] = FindSignature("type");
    } else if (tokenList[i].type == STRING_VAL) {
        tokenId[Csize] = i;
        CodeStack[Csize++] = FindSignature("string");
    } else if (tokenList[i].type == DOU_QUE || tokenList[i].type == SIN_QUE || tokenList[i].type == NOTE1 || tokenList[i].type == NOTE2) {
    } else if (tokenList[i].type == IDENTIFER) {
        tokenId[Csize] = i;
        CodeStack[Csize++] = FindSignature("id");
    } else if (tokenList[i].type == FOR) {
        tokenId[Csize] = i;
        CodeStack[Csize++] = FindSignature("for");
    } else if (tokenList[i].type == IF) {
        tokenId[Csize] = i;
        CodeStack[Csize++] = FindSignature("if");
    } else if (tokenList[i].type == ELSE) {
        tokenId[Csize] = i;
        CodeStack[Csize++] = FindSignature("else");
    } else if (tokenList[i].type == RETURN) {
        tokenId[Csize] = i;
        CodeStack[Csize++] = FindSignature("return");
    } else if (tokenList[i].type == STRUCT) {
        tokenId[Csize] = i;
        CodeStack[Csize++] = FindSignature("struct");
    } else {
        tokenId[Csize] = i;
        int temp = FindSignature(tokenList[i].content);
        if (temp != -1) {
            CodeStack[Csize++] = temp;
        } else {
            CodeStack[Csize++] = Signature.size() - 1;
        }
    }
    if (tokenList[i].type != DOU_QUE && tokenList[i].type != SIN_QUE) {
        fprintf_s(SAofile, "%5d %15s  %15s  %15d\n", Csize - 1, Signature[CodeStack[Csize - 1]].first, tokenList[i].content, tokenList[i].line);
    }
}
//语法检查
void Analyse() {
    //将token列表转化为程序栈
    fprintf_s(SAofile, " %5s  %15s   %15s  %15s\n", "标号" , "符号", "单词", "行数");
    for (int i = tokenList.size() - 1; i >= 0; i--) {
        InsertSign(i);
    }
    cnt = 0;
    //按语法产生式检查程序栈是否符合语法
    while (Csize) {
        if (ShiftList[0][CodeStack[Csize - 1]][0][0] == 0) {
            printf("Error:Line %2d %s     <--------\n", tokenList[tokenId[Csize - 1]].line, tokenList[tokenId[Csize - 1]].content);
            Csize = SearchNext(Csize - 1) + 1;
            continue;
        }
        bool Match = false;
        unMatchPtr = 0x7FFFFFFF;
        tryLength = 0x7FFFFFFF;
        for (int i = 1; i <= ShiftList[0][CodeStack[Csize - 1]][0][0]; i++) {
            Tsize = 1;
            TryStack[0] = 0;
            int ret = Try(0, i, Csize - 1);
            if (ret != -10) {
                Match = true;
                Csize = ret + 1;
                break;
            }
        }
        if (!Match) {
            printf("Error %d:Line %2d %s     <--------\n", ++ErrorCnt, tokenList[tokenId[Csize - 1]].line, tokenList[tokenId[Csize - 1]].content);
            printf("Error:Line %d:%s needed,%s found.\n", unMatchLine, Signature[tokenNeed].first, (tokenFound == -1 ? ("NULL") : (Signature[tokenFound].first)));
            Csize = SearchNext(Csize - 1) + 1;
        }
    }
    printf("Finish\n");
    fclose(ofile);
}
View Code

  Grammar.cpp

#include "stdafx.h"
#include "Macro_Struct.h"
#include "initial.h"
#include "WA.h"
#include "SA.h"


int main() {
    Init();//初始化语法
    Scan();//词法检查
    Bracket();//检查括号是否匹配
    Analyse();//语法检查
    getchar();
    return 0;
}
View Code

  资源文件:

  Grammar.txt

<程序闭包> -> <声明语句> #
<程序闭包> -> <函数定义> #
<程序闭包> -> <类定义> #
<程序闭包> -> $ #
<类定义> -> struct type { <声明语句闭包> } ; #
<函数定义> -> <修饰词闭包> <类型> <变量> ( <参数声明> ) { <函数块> } #
<修饰词闭包> -> <修饰词> <修饰词闭包> #
<修饰词闭包> -> $ #
<修饰词> -> describe #
<类型> -> type <取地址> #
<取地址> -> <星号闭包> #
<星号闭包> -> <星号> <星号闭包> #
<星号闭包> -> $ #
<星号> -> * #
<变量> -> <标志符闭包> <数组闭包> #
<标志符闭包> -> id <数组闭包> #
<标志符闭包> -> id <数组闭包> . <标志符闭包> #
<标志符闭包> -> id <数组闭包> . <标志符闭包> ( <参数列表> ) #
<数组闭包> -> <数组下标> <数组闭包> #
<数组闭包> -> $ #
<数组下标> -> [ <表达式> ] #
<数组下标> -> $ #
<因式> -> ( <表达式> ) #
<因式> -> <变量> #
<因式> -> <数字> #
<数字> -> digit #
<数字> -> string #
<表达式> -> <变量> ( <参数列表> ) #
<表达式> -> <因子> <项> #
<表达式> -> <后缀表达式> #
<表达式> -> <前缀表达式> #
<因子> -> <因式> <因式递归> #
<因式递归> -> * <因式> <因式递归> #
<因式递归> -> / <因式> <因式递归> #
<因式递归> -> $ #
<项> -> + <因子> <项> #
<项> -> - <因子> <项> #
<项> -> $ #
<参数声明> -> <声明> <声明闭包> #
<参数声明> -> $ #
<声明> -> <修饰词闭包> <类型> <变量> <赋初值> #
<赋初值> -> = <右值> #
<赋初值> -> $ #
<右值> -> <表达式> #
<右值> -> { <多个数据> } #
<多个数据> -> <数字> <数字闭包> #
<数字闭包> -> , <数字> <数字闭包> #
<数字闭包> -> $ #
<声明闭包> -> , <声明> <声明闭包> #
<声明闭包> -> $ #
<函数块> -> <函数块闭包> #
<声明语句闭包> -> <声明语句> <声明语句闭包> #
<声明语句闭包> -> $ #
<声明语句> -> <声明> ; #
<函数块闭包> -> <变量> ; <函数块闭包> #
<函数块闭包> -> <声明语句> <函数块闭包> #
<函数块闭包> -> <赋值函数> <函数块闭包> #
<函数块闭包> -> <for循环> <函数块闭包> #
<函数块闭包> -> <while循环> <函数块闭包> #
<函数块闭包> -> <条件语句> <函数块闭包> #
<函数块闭包> -> <函数返回> <函数块闭包> #
<函数块闭包> -> <表达式> ; <函数块闭包> #
<函数块闭包> -> $ #
<赋值函数> -> <变量> <赋值或函数调用> #
<赋值或函数调用> -> = <右值> ; #
<赋值或函数调用> -> ( <参数列表> ) ; # 
<参数列表> -> $ #
<参数列表> -> <参数> <参数闭包> #
<参数闭包> -> , <参数> <参数闭包> #
<参数闭包> -> $ #
<参数> -> <标志符闭包> #
<参数> -> <数字> #
<参数> -> <字符串> #
<参数> -> <表达式> #
<字符串> -> string #
<for循环> -> for ( <赋值函数> <逻辑表达式> ; <后缀表达式> ) { <函数块> } #
<for循环> -> for ( type <赋值函数> <逻辑表达式> ; <后缀表达式> ) { <函数块> } #
<while循环> -> while ( <逻辑表达式> ) { <函数块> } #
<逻辑表达式> -> <表达式> #
<逻辑表达式> -> <表达式> <逻辑运算符> <逻辑表达式> #
<逻辑运算符> -> < #
<逻辑运算符> -> > #
<逻辑运算符> -> == #
<逻辑运算符> -> != #
<逻辑运算符> -> <= #
<逻辑运算符> -> >= #
<逻辑运算符> -> || #
<逻辑运算符> -> && #
<后缀表达式> -> <变量> <后缀运算符> #
<后缀运算符> -> ++ #
<后缀运算符> -> -- #
<前缀表达式> -> <前缀运算符>  <变量> #
<前缀运算符> -> ++ #
<前缀运算符> -> -- #
<前缀运算符> -> ! #
<条件语句> -> if ( <逻辑表达式> ) { <函数块> } <否则语句> #
<否则语句> -> else { <函数块闭包> } #
<否则语句> -> $ #
<函数返回> -> return <因式> ; #
<函数返回> -> return ; #
<终结符> -> break #
<终结符> -> continue #
View Code

  input.txt

#define NOT 61   
#define BYTE_AND 62 
#define COMPLEMENT 63 
#define BYTE_XOR  64
#define MUL 65 
#define DIV 66
#define MOD 67 
#define ADD 68 
#define SUB 69 
#define GRT_THAN 71
#define ASG 72 
#define ARROW 73 
#define SELF_ADD 74 
#define SELF_SUB 75 
#define LEFT_MOVE 76
#define RIGHT_MOVE 77
#define LES_EQUAL 78 
#define GRT_EQUAL 79 
#define EQUAL 80 
#define NOT_EQUAL 81 
#define AND 82 
#define OR 83 
#define COMPLETE_ADD 84 
#define COMPLETE_SUB 85 
#define COMPLETE_MUL 86 
#define COMPLETE_DIV 87 
#define COMPLETE_BYTE_XOR 88 
#define COMPLETE_BYTE_AND 89 
#define COMPLETE_COMPLEMENT 90 
#define COMPLETE_MOD 91
#define BYTE_OR 92
struct Token {
    char content[300];
    char describe[300];
    int type;
    int line;
};
struct Error {
    char content[300];
    char describe[300];
    int type;
    int line;
};
int Expr[100][100];
int ExprNum = 0;
bool First[100][100];
bool visited[100];
bool Follow[100][100];
bool Select[100][100];
int ShiftList[100][100][10][100];
bool canBeNull[100];
int ArrayFlag;
int cnt;
int FindSignature(char * str) {
    for (i = 0; i < Signature.size(); i++) {
        if (strcmp(str, Signature[i].first) == 0) {
            return i;
        }
    }
    return -1;
}
void ShowExprList() {
    for (i = 0; i < ExprNum; i++) {
        printf("%s -> ", Signature[Expr[i][0]].first);
        for (j = 2; j < Expr[i][1]; j++) {
            printf("%s ", Signature[Expr[i][j]].first);
        }
        printf("\n");
    }
}
int DFS_NullPossibility(int x) {
    if (visited[x] == 1) {
        return 0;
    }
    visited[x] = 1;
    for (i = 0; i < ExprNum; i++) {
        if (Expr[i][0] != x) {
        }
        bool ret = 1;
        for (j = 2; j < Expr[i][1]; j++) {
            DFS_NullPossibility(Expr[i][j]);
            ret = canBeNull[Expr[i][j]];
        }
        if (ret == 1) {
            visited[x] = 1;
            canBeNull[x] = 1;
            return 0;
        }
    }
}
void ReadExpr() {
    Signature.clear();
    char str[50][50];
    int Length = 0;
    while (1 == 1) {
        if (strcmp(str[Length], "#") == 0) {
            for (i = 0; i < Length; i++) {
                if (strcmp(str[i], "->") == 0) {
                    Expr[ExprNum][i] = Length - 1;
                }
                int signID = FindSignature(str[i]);
                if (signID == -1) {
                    int tempLen = strlen(str[i]);
                    signID = Signature.size() - 1;
                }
                Expr[ExprNum][i] = signID;
            }
            Length = 0;
            ExprNum++;
        } else {
            Length++;
        }
    }
    fin.close();
    memset(canBeNull, false, sizeof(canBeNull));
    for (i = 0; i < Signature.size(); i++) {
        if (strcmp(Signature[i].first, "$") == 0) {
            canBeNull[i] = 1;
        }
    }
    memset(visited, false, sizeof(visited));
    for (i = 0; i < Signature.size(); i++) {
        if (Signature[i].second == Scalable) {
            DFS_NullPossibility(i);
        }
    }
    memcpy(tempPair.first, "undef", 5);
    tempPair.first[5] = "\0";
    tempPair.second = unScalsble;
    Signature.push_back(tempPair);
    canBeNull[Signature.size() - 1] = 0;
}
void DFS_FirstSet(int x) {
    visited[x] = 1;
    for (i = 0; i < ExprNum; i++) {
        if (Expr[i][0] != x) {
        }
        for (j = 2; j < Expr[i][1]; j++) {
            if (Signature[Expr[i][j]].second == unScalsble) {
                First[x][Expr[i][j]] = 1;
            } else {
                DFS_FirstSet(Expr[i][j]);
                for (k = 0; k < Signature.size(); k++) {
                    if (First[Expr[i][j]][k] == 1) {
                        First[x][k] = 1;
                    }
                }
            }
            if (canBeNull[Expr[i][j]] == 0) {
            }
        }
    }
}
void GetFirstSet() {
    memset(First, false, sizeof(First));
    memset(visited, false, sizeof(visited));
    for (int i = 0; i < Signature.size(); i++) {
        if (Signature[i].second == unScalsble) {
            continue;
        }
        DFS_FirstSet(i);
    }
}
void GetSelectSet() {
    memset(Select, false, sizeof(Select));
    for (int i = 0; i < ExprNum; i++) {
        for (int j = 2; j <= Expr[i][1]; j++) {
            if (Signature[Expr[i][j]].second == unScalsble) {
                Select[i][Expr[i][j]] = true;
            } else {
                for (int k = 0; k < Signature.size(); k++) {
                    if (First[Expr[i][j]][k]) {
                        Select[i][k] = true;
                    }
                }
            }
            if (!canBeNull[Expr[i][j]]) {
                break;
            }
        }
        if (!canBeNull[Expr[i][0]]) {
            Select[i][FindSignature("$")] = false;
        }
    }
}
void ShowShiftList() {
    for (int i = 0; i < Signature.size(); i++) {
        for (int j = 0; j < Signature.size(); j++) {
            if (ShiftList[i][j][0][0] <= 1 || i == j) {
                continue;
            }
            printf("%3d %30s -> %30s\n", ShiftList[i][j][0][0], Signature[i].first, Signature[j].first);
            for (int k = 1; k <= ShiftList[i][j][0][0]; k++) {
                printf("---------->");
                for (int h = 1; h <= ShiftList[i][j][k][0]; h++) {
                    printf("%s ", Signature[ShiftList[i][j][k][h]].first);
                }
                printf("\n");
            }
        }
    }
}
void GetShiftList() {
    memset(ShiftList, 0, sizeof(ShiftList));
    for (int i = 0; i < ExprNum; i++) {
        for (int j = 0; j < Signature.size(); j++) {
            if (!Select[i][j]) {
                continue;
            }
            ShiftList[Expr[i][0]][j][0][0]++;
            for (int k = 1; k <= Expr[i][1]; k++) {
                ShiftList[Expr[i][0]][j][ShiftList[Expr[i][0]][j][0][0]][k - 1] = Expr[i][k];
            }
            ShiftList[Expr[i][0]][j][ShiftList[Expr[i][0]][j][0][0]][0]--;
        }
    }
    //ShowShiftList();
}
void Init() {
    InitKeyMap();
    InitOperMap();
    InitLimitMap();
    tokenList.clear();
    errorList.clear();
    ReadExpr();
    GetFirstSet();
    GetSelectSet();
    GetShiftList();
}
int SeekKey(char * word) {
    for (int i = 0; i < keyMap.size(); i++) {
        if (strcmp(word, keyMap[i].first) == 0) {
            return keyMap[i].second;
        }
    }
    return IDENTIFER;
}
void InsertToken(char * content, char * describe, int type, int line) {
    Token tempToken;
    strcpy_s(tempToken.content, content);
    strcpy_s(tempToken.describe, describe);
    tempToken.type = type;
    tempToken.line = line;
    tokenList.push_back(tempToken);
}
void InsertToken(char * content, char * describe, int type, int line) {
    Token tempToken;
    strcpy_s(tempToken.content, content);
    strcpy_s(tempToken.describe, describe);
    tempToken.type = type;
    tempToken.line = line;
    tokenList.push_back(tempToken);
}
void InsertError___(char * content, char * describe, int type, int line) {
    Error tempError;
    strcpy_s(tempError.content, content);
    strcpy_s(tempError.describe, describe);
    tempError.type = type;
    tempError.line = line;
    errorList.push_back(tempError);
    printf("Line %d:%s\n", line, describe);
}
View Code

 

posted @ 2016-09-12 17:44  Иветта  阅读(3507)  评论(0编辑  收藏  举报
1 #00:00:08,550 --> 00:00:11,302 #- Ребята, у меня для вас хорошая новость. #- 伙计们 我有个好消息要告诉你们 # # #2 #00:00:11,550 --> 00:00:13,598 #6 урока не будет. #将没有第6课 # # #3 #00:00:13,598 --> 00:00:14,725 #- Ура! #- 干杯! # # #4 #00:00:14,725 --> 00:00:20,649 #- Вместо него мы идем на выставку «Русский лес и его влияние на русскую культуру». #- 相反 我们去参观 "俄罗斯森林及其对俄罗斯文化的影响 "展览 # # #5 #00:00:21,275 --> 00:00:24,975 #- Тамара Ивановна, а можно я не пойду в русский лес? У меня просто тренировка после уроков. #- 塔玛拉-伊万诺夫娜 我不能去俄罗斯森林吗 我只是放学后有练习 # # #6 #00:00:25,225 --> 00:00:27,451 #- А у меня после уроков планы РОНО. #- 而且我放学后有RONO计划 # # #7 #00:00:27,451 --> 00:00:28,731 #- А что я тренеру скажу? #- 我要怎么跟教练说呢 # # #8 #00:00:28,731 --> 00:00:34,075 #- Расскажешь про Шишкина и Левитана. Уверена, их творчество ему ни о чем не говорит. #- 告诉他关于希什金和列维坦的事 我相信他们的艺术对他来说并不意味着什么 # # #9 #00:00:34,350 --> 00:00:37,294 #- Творчество Лионеля Месси вам тоже ни о чем не говорит. #- 梅西的创造力也不能说明什么 # # #10 #00:00:38,650 --> 00:00:39,325 #- Васнецова! #- 瓦斯涅佐夫 # # #11 #00:00:39,325 --> 00:00:39,837 #- Что? #- 什么 # # #12 #00:00:40,350 --> 00:00:43,550 #- Совсем не участвуешь в общественной жизни! #- 你根本就没有参与公共生活 你根本就没有参与公共生活 # # #13 #00:00:43,550 --> 00:00:46,822 #Единственное, что ты делаешь вместе с классом – это сбегаешь с уроков. #你在课堂上唯一做的事情就是下课 # # #14 #00:00:48,225 --> 00:00:52,367 #- Тамара Ивановна, пожалуйста, это очень-очень важная для меня тренировка. #- 塔玛拉-伊万诺夫娜 拜托 这对我来说是一次非常非常重要的培训 # # #15 #00:00:53,175 --> 00:00:54,967 #Ну вот, вот, смотрите. #好了 你去看看 # # #16 #00:00:55,375 --> 00:01:00,973 #Тренер и ребята сегодня специально придут из-за моих гетр. #教练和孩子们今天特别来了 因为我的步枪 # # #17 #00:01:00,973 --> 00:01:02,419 #Ну не могу же я их подвести! #我不能让他们失望! # # #18 #00:01:03,575 --> 00:01:08,948 #- Шишкин и Левитан не простят мне, если ты появишься перед их картинами в таком виде. #- 如果你这样出现在他们的画前 希什金和列维坦不会原谅我 # # #19 #00:01:09,450 --> 00:01:12,202 #Но с другой стороны, не могу же я тебя отпустить просто так! #但话又说回来 我不能就这么让你走了 " # # #20 #00:01:12,525 --> 00:01:16,301 #- Не отпускайте меня просто так! Накричите на меня! #- 不要就这样让我走 对我大喊大叫! # # #21 #00:01:16,875 --> 00:01:20,375 #Да, скажите, что я позорю весь класс! #是啊 告诉我 我让全班人都很难堪 # # #22 #00:01:20,375 --> 00:01:27,415 #Чтоб глаза меня ваши здесь не видели! Сколько у вас кричалок там этих? #我不想让你的眼睛看到我在这里!你在那里有多少次喊叫 # # #23 #00:01:27,415 --> 00:01:32,350 #- Васнецова! Совсем стыд потеряла! #- 瓦斯涅佐娃 你已经失去了你的羞耻心! # # #24 #00:01:32,350 --> 00:01:33,950 #- Ну вот, тоже вариант. #- 嗯 这也是一种选择 # # #25 #00:01:33,950 --> 00:01:36,599 #- Так, иди сегодня со своими гетрами куда хочешь. #- 因此 今天就带着你的护具去你喜欢的地方吧 # # #26 #00:01:37,175 --> 00:01:41,015 #Но завтра на классный час ты приведешь нам интересного человека. #但明天你会带一个有趣的人去上课 # # #27 #00:01:41,300 --> 00:01:46,089 #- Кого? Вы такая интересная, Тамара Ивановна. «Приведешь». #- 谁 你太有意思了 塔玛拉-伊万诺夫娜 "你会的 " # # #28 #00:01:46,350 --> 00:01:50,702 #О! А давайте я вас приведу? Вы такая интересная сегодня. #О! 我为什么不把你带进去 你今天真是太有趣了 # # #29 #00:01:50,702 --> 00:01:55,822 #- Нет. По плану РОНО классный руководитель не может быть интересным человеком. #- 不 根据RONO计划 班主任不能是一个有趣的人 # # #30 #00:02:49,800 --> 00:02:56,648 #- Ой, Веник. Ты сегодня такой бледный. Надо срочно тебя поцеловать. #- 哦 扫帚 你今天看起来很苍白 我必须马上吻你 # # #31 #00:02:56,950 --> 00:03:01,174 #Только Маши нет дома, может, Галина Сергеевна подойдет? #只有玛莎不在家 所以也许加琳娜-谢尔盖耶夫娜可以过来 # # #32 #00:03:01,174 --> 00:03:04,102 #- Даш, да я не хочу целоваться, я пришел все объяснить. #- 小飞 我不想接吻 我是来解释的 # # #33 #00:03:04,425 --> 00:03:07,625 #- Как же тебе плохо, раз ты уже и целоваться не хочешь. #- 你真坏 因为你甚至不想接吻 # # #34 #00:03:08,675 --> 00:03:09,802 #Совсем заболел. #我完全生病了 # # #35 #00:03:17,525 --> 00:03:20,350 #- Даш, мне просто тогда было очень плохо. #- 小飞 我只是当时感觉非常糟糕 # # #36 #00:03:20,350 --> 00:03:23,742 #- Ага, и ты хотел, чтобы было очень хорошо. #- 是的 而且你希望它真的很好 # # #37 #00:03:32,150 --> 00:03:36,502 #- Да просто Маша хотела заболеть, и я через поцелуй передавал ей своих микробов! #- 只是玛莎想生病 而我却通过一个吻把我的病菌传给了她 " # # #38 #00:03:36,502 --> 00:03:41,372 #- Очень убедительно! Только знаешь что? Я на самом деле рада тому, что я вчера видела. #- 非常有说服力!但你知道吗 实际上 我对昨天看到的情况感到高兴 # # #39 #00:03:41,372 --> 00:03:44,124 #Теперь мы с тобой будем точно только друзьями. #从现在开始 你和我肯定只做朋友 # # #40 #00:03:44,325 --> 00:03:49,893 #Потому что я никогда не буду целоваться с человеком, который целовался с Машей. #因为我永远不会吻一个吻过玛莎的男人 # # #41 #00:03:51,475 --> 00:03:52,563 #- Ну хоть друзьями… #- 至少作为朋友... # # #42 #00:03:52,825 --> 00:03:55,641 #- Нет, мы даже друзьями не будем. Ты же как все. #- 不 我们甚至不会成为朋友 你就像其他人一样 # # #43 #00:03:55,641 --> 00:03:59,225 #Не получилось с одной – сразу к другой. Так что вали к своей Маше. #如果一个没有成功 就直接去找另一个 所以回到你的玛莎身边吧 # # #44 #00:04:06,325 --> 00:04:07,750 #- Даш, мы с Веником хотим… #- 小飞、韦尼克和我想... # # #45 #00:04:07,750 --> 00:04:11,270 #- Хотите – целуйтесь! Или что у вас там следующее по плану? #- 你想接吻!或者下一个议程是什么 # # #46 #00:04:16,400 --> 00:04:21,200 #- Веник, ну как доказать Дашке, что то, что она видела, на самом деле не то, что она видела? #- Wenik 你如何向Dashka证明她所看到的并不是她真正看到的 # # #47 #00:04:21,700 --> 00:04:23,940 #- Никак, она даже слушать не хочет. #- 不可能 她甚至不会听 # # #48 #00:04:24,200 --> 00:04:28,040 #- Не знаю, как ты, а я обязана доказать, что между нами ничего не было. #- 我不知道你怎么想的 但我必须证明我们之间什么都没发生 # # #49 #00:04:28,040 --> 00:04:31,453 #У меня и без этого поцелуя в семье репутация не очень. #没有那个吻 我在家里就没有什么名声 # # #50 #00:04:33,700 --> 00:04:36,296 #Правильно, Веник, думай. Я тебе тоже помогу. #没错 布隆姆 思考 我也会帮助你 # # #51 #00:04:37,850 --> 00:04:41,434 #Ты не сдавайся, ты бейся! Все не так уж и плохо. Дашка же взяла букет. #你不放弃 你要战斗 " 没有那么糟糕 达莎接过花束 # # #52 #00:04:44,775 --> 00:04:47,207 #- Веник, и забери свои веники. #- 扫帚 拿起你的扫帚 # # #53 #00:04:53,375 --> 00:04:56,319 #- Это мы с друзьями на даче. Так, ничего интересного. #- 这是我和我的朋友们在小屋里 所以 没有什么有趣的 # # #54 #00:04:56,319 --> 00:05:00,123 #- Да, ничего интересного, обычная дача с видом на Эйфелеву башню. #- 是的 没有什么有趣的 只是一个普通的避暑别墅 可以看到埃菲尔铁塔 # # #55 #00:05:00,123 --> 00:05:02,747 #- А это что, Дженнифер Лопес? Она тоже с вами отдыхала? #- 那是珍妮弗-洛佩兹吗 她也和你一起去度假了吗 # # #56 #00:05:02,747 --> 00:05:05,825 #- Нет, она работала. Спела «Владимирский централ» и улетела. #- 不 她在工作 她唱着弗拉基米尔的中央 飞走了 # # #57 #00:05:06,400 --> 00:05:10,048 #- О, Женька! Женька, смотри: Бэкхем шашлыки жарит, Жень! #- 哦 珍卡!珍卡 看:贝克汉姆在烤肉 珍卡! # # #58 #00:05:10,048 --> 00:05:12,525 #- Ой, Жень, посмотри, посмотри. #- 哦 振亚 看 看 看 # # #59 #00:05:12,525 --> 00:05:14,800 #- Жень… У тебя что, случилось что? #- 振亚 你出了什么事吗 # # #60 #00:05:15,400 --> 00:05:21,416 #- Нет, не случилось, но случится. Мне на классный час нужно привести какого-то интересного человека… #- 不 它还没有 但它会的 我需要带一些有趣的人去上课... # # #61 #00:05:21,725 --> 00:05:23,712 #- А что ты своего тренера по футболу не приведешь? #- 你为什么不把你的足球教练带来 # # #62 #00:05:23,712 --> 00:05:25,952 #Ты же говорила, что он ртом футбольный мяч надувает. #我以为你说他在用嘴吹足球 # # #63 #00:05:25,952 --> 00:05:30,625 #- Ну да, надувает ртом футбольный мяч за 1 минуту, а классный час длится 45 минут, #- 嗯 是的 在1分钟内用嘴吹了一个足球 而课时持续了45分钟 # # #64 #00:05:30,625 --> 00:05:34,025 #поэтому я не знаю, где ще достать 44 не надутых мяча. #所以我不知道从哪里可以得到44个不充气的球 # # #65 #00:05:34,025 --> 00:05:38,761 #- А ты Оксану позови! Смотри, какая она интересная. Самая настоящая Рублевская жена. #- 而你得到了奥克萨娜!看看她是多么有趣 一个真正的鲁布廖夫斯卡娅妻子 # # #66 #00:05:39,825 --> 00:05:43,850 #- Ну таких как я много. #- 嗯 有很多像我这样的人 # # #67 #00:05:43,850 --> 00:05:48,202 #- Тем более жизнь на Рублевке очень интересна всем. А книги Оксаны Робски все читают. #- 特别是鲁布廖夫卡的生活对每个人来说都非常有趣 而每个人都会读奥克萨娜-罗夫斯基的书 # # #68 #00:05:48,525 --> 00:05:51,341 #- Такую книгу может написать любая Рублевская жена. #- 这样的书可以由任何一位鲁布廖夫的妻子来写 # # #69 #00:05:51,341 --> 00:05:55,821 #Ну что писать? Взял диктофон, пришел на тусовку, нажал кнопочку, потом все записал. #有什么可写的 找一个录音机 去参加聚会 按一个按钮 然后把一切都写下来 # # #70 #00:05:55,821 --> 00:05:56,718 #Вот тебе и книга. #这本书的内容就这么多了 # # #71 #00:05:57,175 --> 00:05:58,711 #- Ты можешь писать Оксану Робски? #- 你能写奥克萨娜-罗夫斯基吗 # # #72 #00:05:59,750 --> 00:06:02,246 #- Я думаю, Джей Ло будет все-таки дешевле. #- 我认为J罗毕竟会更便宜 # # #73 #00:06:02,850 --> 00:06:04,450 #- Тогда давай ты придешь. #- 那么你为什么不来 # # #74 #00:06:05,950 --> 00:06:09,854 #- Но мне нечего рассказать. Понимаешь, я сама обычная Рублевская жена. #- 但我无话可说 你看 我自己就是一个普通的鲁布廖夫妻子 # # #75 #00:06:09,854 --> 00:06:14,142 #Мужу не изменяю, на тусовки не хожу. Я сижу целыми днями дома с ребенком. #我不欺骗我的丈夫 我不出去 我整天呆在家里照顾孩子 # # #76 #00:06:16,575 --> 00:06:17,446 #Где ребенок? #孩子在哪里 # # #77 #00:06:18,000 --> 00:06:20,240 #- Он у нас в комнате спит, все хорошо. #- 他睡在我们的房间里 一切都很好 # # #78 #00:06:21,400 --> 00:06:25,275 #- Ну вот, даже ребенок у меня спит. Рассказывать нечего. #- 嗯 连我的孩子都睡着了 没有什么可说的 # # #79 #00:06:26,600 --> 00:06:29,644 #- Блин, это же Дэвид Бэкхем шашлыки жарит! #- 伙计 那是大卫-贝克汉姆在烤羊肉串! # # #80 #00:06:29,975 --> 00:06:32,215 #Вот про него и расскажешь! #这就是你要告诉的人! # # #81 #00:06:32,950 --> 00:06:35,702 #- А что, это какой-то очень известный повар? #- 它是某种非常著名的厨师吗 # # #82 #00:06:35,702 --> 00:06:38,012 #- Оксаночка, а ты Викторию Бэкхем знаешь? #- 奥克萨娜 你认识维多利亚-贝克汉姆吗 # # #83 #00:06:38,012 --> 00:06:39,375 #- Ну конечно! #- 当然了! # # #84 #00:06:39,375 --> 00:06:41,375 #- Так вот этот повар – ее муж! #- 那么 那个厨师就是她的丈夫! # # #85 #00:06:42,225 --> 00:06:46,193 #- Оксаночка, я тебя очень прошу, пожалуйста, пожалуйста, не подведи меня. #- 奥克萨娜 我真的请求你 请 请不要让我失望 # # #86 #00:06:46,193 --> 00:06:49,009 #Если ты не придешь, физичка меня съест. #如果你不来 物理学家会吃掉我 # # #87 #00:06:49,400 --> 00:06:53,600 #- Да, я слышала, что у учителей маленькие зарплаты, но неужели настолько? #- 是的 我听说教师的工资很低 但真的有那么低吗 # # #88 #00:06:56,475 --> 00:07:01,083 #- Мам, что делать? Дашка с Веником поругалась, а я крайняя. #- 妈妈 我们应该怎么做 达什卡和维尼克打了一架 我很紧张 # # #89 #00:07:01,083 --> 00:07:02,775 #- Да? А из-за чего они поругались? #- 是吗 他们在争论什么呢 # # #90 #00:07:02,775 --> 00:07:06,295 #- Да из-за ерунды. Мы с Веником поцеловались. #- 这没什么 维尼克和我接吻了 # # #91 #00:07:08,225 --> 00:07:09,650 #- Ты целовалась с Веником? #- 你吻了维尼克吗 # # #92 #00:07:09,650 --> 00:07:13,687 #- Ну только не для того, чтобы поцеловаться, а для того, чтобы не писать контрольную, вот и все. #- 好吧 不是因为接吻 而是因为没有写考试 就这样 # # #93 #00:07:14,825 --> 00:07:19,126 #- Так, Маша, я не знаю, чему вас там учат в институте, но мне не нравится, #- 所以 玛莎 我不知道他们在那里教你什么 但我不喜欢这样 # # #94 #00:07:19,425 --> 00:07:23,201 #что тебе приходится целоваться для того, чтобы не писать контрольную. #你必须亲吻 以避免写一个测试 # # #95 #00:07:23,675 --> 00:07:28,347 #Веник тоже хорош! Разве можно целоваться с одним человеком, если любишь другого? #扫帚也不错!如果你爱另一个人 你能亲吻他吗 # # #96 #00:07:28,347 --> 00:07:33,083 #- Конечно можно. Ты же с Палкиным целовалась, когда был папа рядом. #- 当然 你可以 爸爸在的时候你在亲吻帕尔金 # # #97 #00:07:36,475 --> 00:07:41,773 #- У меня с Палкиным был совсем другой поцелуй! #- 我和帕尔金有一个非常不同的吻! # # #98 #00:07:41,773 --> 00:07:44,526 #- Поцелуй может и другой, а результат тот же. #- 吻可能不同 但结果是一样的 # # #99 #00:07:45,250 --> 00:07:50,498 #- Да если бы папа увидел всю ситуацию с самого начала, он бы сразу понял, что я не виновата. #- 是的 如果爸爸从一开始就看到整个情况 他就会直接意识到这不是我的错 # # #100 #00:07:50,775 --> 00:07:52,631 #- Вот если бы Дашка увидела всю си… #- 如果Dashka能看到整个过程...... # # #101 #00:07:54,500 --> 00:07:58,275 #Точно! Надо чтобы Дашка увидела всю ситуацию с самого начала! #正是如此!我们需要Dashka从一开始就看到整个情况 " # # #102 #00:07:58,275 --> 00:08:01,283 #Ура! Мамочка, ты гений! #耶!妈妈 你是个天才 # # #103 #00:08:02,800 --> 00:08:06,850 #- Эх, дочка. Делать женские глупости мы с тобой научились. #- 诶 女儿 你和我已经学会了如何做一个女人的蠢事 # # #104 #00:08:07,975 --> 00:08:10,790 #Осталось теперь научиться делать их без последствий. #现在剩下的就是学习如何不受影响地做这些事 # # #105 #00:08:13,850 --> 00:08:16,922 #- Ну, Васнецова. Где же твой интересный человек? #- 好吧 瓦斯涅佐娃 你那有趣的人在哪里 # # #106 #00:08:16,922 --> 00:08:19,162 #И интересно, кто это? #我想知道它是谁 # # #107 #00:08:19,625 --> 00:08:22,697 #- Вот видите, она еще не пришла, а вам уже интересно. #- 你看 她还没到 你就已经感兴趣了 # # #108 #00:08:25,275 --> 00:08:29,563 #- Извините, здравствуйте. Женечка, я надеюсь, я не опоздала. #- 对不起 你好 吉安尼 我希望我不会太晚 # # #109 #00:08:29,563 --> 00:08:34,363 #- А вот и она! Оксана Робски! #- 她来了 Oksana Robski! # # #110 #00:08:41,075 --> 00:08:44,851 #Оксана сейчас как раз работает над своей новой книгой. #奥克萨娜现在刚刚在写她的新书 # # #111 #00:08:45,350 --> 00:08:47,846 #Она, собственно, и пришла вам об этом рассказать. #她实际上是来告诉你这件事的 # # #112 #00:08:47,846 --> 00:08:51,366 #- Ну-ка быстро прекратили это безобразие. Убрали, убрали телефоны. #- 现在赶紧停止这种无稽之谈 把它收起来 把电话收起来 # # #113 #00:08:52,175 --> 00:08:53,967 #Севаков, у тебя камера на мобильном есть? #塞瓦科夫 你的手机上有摄像头吗 # # #114 #00:08:54,225 --> 00:08:59,921 #- А вот сними меня рядом с ней. Здравствуйте, Оксана! #- 这是我在她旁边的照片 你好 奥克萨娜! # # #115 #00:09:00,475 --> 00:09:04,507 #Оксана, вы являетесь продолжателем традиций русской литературы. #奥克萨娜 你是俄罗斯文学传统的延续者 # # #116 #00:09:04,750 --> 00:09:10,318 #Ваше имя стоит в одном ряду с Достоевским, с Толстым, прости Господи, с Дарьей Донцовой. #你的名字与陀思妥耶夫斯基 与托尔斯泰 上帝保佑 与达里娅-顿佐娃齐名 # # #117 #00:09:10,318 --> 00:09:12,804 #Кстати, передавайте ей привет, пожалуйста. #顺便说一下 请向她问好 # # #118 #00:09:13,975 --> 00:09:16,215 #- А как будет называться ваша новая книга? #- 你的新书会叫什么名字 # # #119 #00:09:16,525 --> 00:09:19,654 #- Моя новая книга будет называться «Подстава»! #- 我的新书将被称为《框架》! # # #120 #00:09:21,875 --> 00:09:27,823 #- До конца классного часа 10 минут, кому еще нужны книги Робски из библиотеки? #- 离下课时间还有10分钟 还有谁需要图书馆的罗伯斯基的书 # # #121 #00:09:27,823 --> 00:09:31,164 #Они все у меня и пока всего по 100 рублей. #我已经全部买下了 而且到目前为止每张只有100卢布 # # #122 #00:09:31,575 --> 00:09:35,326 #- Извините, но мне пора. Мне нужно до вечера дописать еще 3 книги. #- 我很抱歉 但我必须要走了 我还有三本书要在今天晚上之前完成 # # #123 #00:09:36,025 --> 00:09:42,937 #- Оксана, Оксаночка, прошу. Обещаю, что эти 3 книги мы прочитаем все всей школой. #- 奥克萨娜 奥克萨娜 请 我保证 我们将以学校为单位读完所有三本书 # # #124 #00:09:46,825 --> 00:09:53,225 #- Ой! Здравствуйте, Оксана! Здравствуйте, моя дорогая. #- 哦 你好 奥克萨娜你好 我亲爱的 # # #125 #00:09:53,600 --> 00:09:55,264 #- До свидания, Людмила Михайловна. #- 再见 柳德米拉-米哈伊洛夫娜 # # #126 #00:09:56,450 --> 00:10:03,746 #- Где эта Робски? У меня, как учителя русского языка, накопилось много вопросов по поводу ее русского языка. #- 这个Robski在哪里 作为一名俄语教师 我有很多关于她的俄语问题 # # #127 #00:10:04,450 --> 00:10:08,738 #- Людмила Михайловна, а вы только что с ней в дверях поздоровались. #- 柳德米拉-米哈伊洛夫娜 而您刚才在门口跟她打了招呼 # # #128 #00:10:11,650 --> 00:10:15,800 #- Это, конечно, была Оксана, но… Не Робски, а Федотова. #- 当然是奥克萨娜 但是......不是罗夫斯基 而是费多瓦 # # #129 #00:10:17,950 --> 00:10:21,662 #- Дашка, я сейчас тебе покажу на Полежайкине, что на самом деле у меня было с Веником. #- 达什卡 我将在波列沙金向你展示我与维尼克的真实情况 # # #130 #00:10:21,900 --> 00:10:28,900 #В смысле, что ничего не было. Так, Полежайкин, ты – больной Веник. #我的意思是 什么都没有发生 好吧 波列亚金 你是个变态的扫帚 # # #131 #00:10:29,775 --> 00:10:33,325 #Скоро у нас контрольная работа, поэтому я тоже хочу заболеть. #我们很快就要进行测试了 所以我也想生病 # # #132 #00:10:34,050 --> 00:10:36,482 #И ты должен меня заразить. #而你必须感染我 # # #133 #00:10:36,725 --> 00:10:39,800 #Я кричу: чихай на меня! #我喊道:对着我打喷嚏! # # #134 #00:10:39,800 --> 00:10:40,760 #- Ап-чхи! #- Upsy-daisy! # # #135 #00:10:42,375 --> 00:10:45,550 #- Ты что, сошел с ума? Зачем ты на меня чихаешь? #- 你疯了吗 你为什么对我打喷嚏 # # #136 #00:10:45,550 --> 00:10:46,482 #- Ты же сама сказала. #- 你自己说的 # # #137 #00:10:47,350 --> 00:10:54,262 #- Полежайкин! Ты – Веник, а он отказался на меня чихать, потому что сказал, что это негигиенично. #- Polezhaikin 你是一把扫帚 他拒绝对我打喷嚏 因为他说这是不卫生的 # # #138 #00:10:54,525 --> 00:10:56,701 #Давай сначала. Кашляй на меня. #先来吧 对着我咳嗽 # # #139 #00:10:59,325 --> 00:11:02,205 #Ты что! Я же сказала, что это негигиенично! #哦 来吧 我告诉过你这是不卫生的! # # #140 #00:11:02,205 --> 00:11:05,375 #- Ты сказала, что чихать – негигиенично, а про кашлять ничего не говорила. #- 你说打喷嚏是不卫生的 但你没有说过咳嗽 # # #141 #00:11:06,350 --> 00:11:10,766 #- Короче, Даш, Веник не захотел на меня ни кашлять, ни чихать. #- 总之 小飞 布罗姆不想对我咳嗽或打喷嚏 # # #142 #00:11:10,766 --> 00:11:14,932 #- Да, пока не очень убедительно, но зато очень весело. #- 是的 它还不是很有说服力 但它有很多乐趣 # # #143 #00:11:16,150 --> 00:11:18,150 #- Вот сейчас будет очень убедительно. #- 现在这将是非常有说服力的 # # #144 #00:11:18,525 --> 00:11:24,157 #Ах так? Ты не хочешь на меня ни чихать, ни кашлять? Тогда давай целоваться! #哦 是吗 你不想在我身上打喷嚏或咳嗽吗 那么让我们接吻吧! # # #145 #00:11:24,850 --> 00:11:26,898 #Полежайкин, сопротивляйся! #波列兹海金 反击 # # #146 #00:11:26,898 --> 00:11:27,740 #- Зачем? #- 为什么 # # #147 #00:11:28,325 --> 00:11:30,325 #- Потому что ты не хочешь, чтобы я тебя поцеловала! #- 因为你不想让我亲吻你! # # #148 #00:11:30,325 --> 00:11:32,423 #- Как это не хочу! Очень даже хочу! #- 你说我不想是什么意思 我确实想这样做! # # #149 #00:11:32,650 --> 00:11:36,490 #- Полежйкин, если хочешь, чтобы я тебя поцеловала, сопротивляйся. #- 波列金 如果你想让我吻你 那就忍住 # # #150 #00:11:42,950 --> 00:11:43,462 #- Илья! #- Ilya! # # #151 #00:11:45,600 --> 00:11:47,328 #- Галина Сергеевна, все не так как ты думаешь! #- 加利娜-谢尔盖耶夫娜 不是你想的那样 " # # #152 #00:11:47,328 --> 00:11:49,732 #- Даш, понимаешь, именно так все и было. #- 小飞 你看 这正是所发生的事情 # # #153 #00:11:49,925 --> 00:11:55,557 #- Илья, ты же женатый человек! Маша, тебе что, Дашиного Веника мало? #- 伊利亚 你是一个已婚男人 玛莎 达莎的扫帚对你来说还不够吗 # # #154 #00:11:55,557 --> 00:11:58,225 #- Хорошо, что Женькин Женька сейчас в Лондоне, #- 好在Zhenya的Zhenya现在在伦敦 # # #155 #00:11:58,225 --> 00:12:02,257 #и Маша до него не дотянется своими вездесущими губами. #而玛莎不会用她那无处不在的嘴唇伸向它 # # #156 #00:12:02,900 --> 00:12:05,588 #- Бублик, теперь от меня ни на шаг. #- 贝果 现在不要再离开我一步了 # # #157 #00:12:12,550 --> 00:12:18,733 #- Ты хоть понимаешь, что наделала? Ты свою классную… да что там классную. #- 你知道你做了什么吗 你已经做了你的酷......这有什么好酷的 # # #158 #00:12:19,200 --> 00:12:22,656 #Ты директора школы дискредитировала. #你让学校校长名誉扫地 # # #159 #00:12:22,925 --> 00:12:24,525 #- Это все Людмила Михайловна виновата. #- 这都是柳德米拉-米哈伊洛夫娜的错 # # #160 #00:12:24,900 --> 00:12:28,300 #Да если б она не пришла, у всех были бы фотки с Оксаной Робски. #如果她没有来 每个人都会有奥克萨娜-罗夫斯基的照片 # # #161 #00:12:28,975 --> 00:12:36,063 #- Короче, Васнецова. Я даже не представляю, кого ты должна привести на классный час завтра, #- 简而言之 瓦斯涅佐娃 我不知道你明天应该带谁去上课 # # #162 #00:12:36,063 --> 00:12:38,751 #чтобы восстановить мой авторитет. #以恢复我的可信度 # # #163 #00:12:40,400 --> 00:12:42,025 #В лице директора школы. #以学校校长的名义 # # #164 #00:12:44,300 --> 00:12:49,662 #- Девочки, мы не должны прощать Машу. Вчера она парня у сестры увела, а завтра? #- 女孩们 我们不应该原谅玛莎 昨天她偷了她姐姐的男朋友 而明天呢 # # #165 #00:12:49,900 --> 00:12:50,668 #Уведет у второй. #将从另一个人那里偷跑出来 # # #166 #00:12:50,668 --> 00:12:54,508 #- Да, у нас есть, где развернуться. Что с Полежайкиным? #- 是的 我们有很大的空间可以散开 波列亚金呢 # # #167 #00:12:54,825 --> 00:12:58,857 #- Да Илью я уже простила. Он же тупое оружие в руках Маши. #- 我已经原谅了伊利亚 他是玛莎手中的钝器 # # #168 #00:12:59,600 --> 00:13:02,992 #Знаете что, я предлагаю устроить Маше бойкот. #你知道吗 我建议我们抵制玛莎 # # #169 #00:13:03,625 --> 00:13:07,913 #- Я могу устроить Маше бойкот только до дня рождения. #- 我只能抵制玛莎 直到她的生日 # # #170 #00:13:07,913 --> 00:13:08,553 #- Почему? #- 为什么 # # #171 #00:13:08,873 --> 00:13:12,137 #- Маша подарит мне подарок, и я ее прощу. #- 玛莎会给我一份礼物 我会原谅她 # # #172 #00:13:17,200 --> 00:13:20,400 #- Галина Сергеевна, ты же на меня не обижаешься? #- 加利娜-谢尔盖耶夫娜 你不会对我生气吧 # # #173 #00:13:23,825 --> 00:13:26,705 #Даш, скажи Галине Сергеевне, что я не виновата! #小飞 告诉加林娜-谢尔盖耶夫娜 这不是我的错! # # #174 #00:13:28,950 --> 00:13:32,342 #Пуговка, скажи Даше, чтобы она сказала Галине Сергеевне, что я не виновата! #普戈夫卡 让达莎告诉加琳娜-谢尔盖耶夫娜 这不是我的错! # # #175 #00:13:33,750 --> 00:13:36,438 #Боже, первый раз в жизни я не виновата, а мне никто не верит! #天啊 这是我人生中第一次不是我的错 而且没有人相信我 " # # #176 #00:13:36,725 --> 00:13:39,989 #Бублик, а может, ты мне хоть поверишь? #贝果 你至少会相信我吗 # # #177 #00:13:41,275 --> 00:13:44,539 #Ах так! Тогда я ухожу! #啊 这就是了!那我就走了! # # #178 #00:13:46,875 --> 00:13:53,083 #Так вы и этому не верите? Смотрите, я ухожу! Навсегда, между прочим. #所以你也不相信 看 我要走了 顺便说一句 是好事 # # #179 #00:13:53,083 --> 00:13:54,569 #- Навсегда – это в другую сторону. #- 永远是反过来的 # # #180 #00:14:01,425 --> 00:14:02,513 #- Я пошла! #- 我走了! # # #181 #00:14:03,350 --> 00:14:04,566 #Я уже ушла. #我已经离开了 # # #182 #00:14:08,500 --> 00:14:12,916 #- Сегодняшнего нашего гостя знают все. Даже дети. #- 大家都知道我们今天的嘉宾 甚至是孩子们 # # #183 #00:14:13,250 --> 00:14:17,257 #Он уже давно стал национальным символом России. #长期以来 它一直是俄罗斯的一个国家象征 # # #184 #00:14:17,500 --> 00:14:20,572 #- Она что, самого Чебурашку привела? #- 她是否把切布拉什卡本人带来了 # # #185 #00:14:21,375 --> 00:14:24,767 #- Да пусть даже Чебурашку. Главное, Васнецова, чтобы настоящего! #- 我不在乎是否是Cheburashka 只要是真正的瓦斯涅佐夫! # # #186 #00:14:24,767 --> 00:14:26,809 #- Сейчас он зайдет, и вы все ахнете. #- 他马上就要走进来了 你们都要惊呼 # # #187 #00:14:31,950 --> 00:14:32,974 #- Здравствуйте! #- 你好! # # #188 #00:14:35,800 --> 00:14:41,560 #- Да, действительно, хочется сказать «ах». А кто это? #- 是的 它确实让你想说'啊' 那是谁 # # #189 #00:14:44,400 --> 00:14:45,975 #- Жень, я наверное пойду. #- 小郑 我该走了 # # #190 #00:14:45,975 --> 00:14:49,734 #- Подожди! У них просто шок. Они не верят своим глазам! #- 等等 他们只是受到了惊吓 他们无法相信自己的眼睛! # # #191 #00:14:50,375 --> 00:14:53,255 #Да вы что?! Вы что, не узнаете? Это же… #哦 真的吗 你不认得它吗 这不就是... # # #192 #00:14:55,600 --> 00:15:01,104 #- А! Он еще похож на чувака, который в «Бумере» снимался. Его еще там убили. #- 啊 他也看起来像《波尔》中的那个家伙 他也在其中被杀 # # #193 #00:15:01,425 --> 00:15:09,809 #- Совков, я сама тебя убью! Люди, да разуйте глаза, это же сам Емельян Палкин! #- 索夫科夫 我要亲手杀了你!人们 睁大你们的眼睛 那是叶梅利安-帕尔金本人! # # #194 #00:15:15,275 --> 00:15:18,000 #- Знаешь что, Женька? Пожалуй, я пойду. #- 你知道吗 珍卡 我想我要走了 # # #195 #00:15:18,000 --> 00:15:21,901 #- Стоять. Значит, Васнецова, ты утверждаешь, #- 停止 所以 瓦斯涅佐娃 你说 # # #196 #00:15:21,901 --> 00:15:27,853 #что вот это вот – знаменитый российский хоккеист Палкин, прости Господи. #这个人是著名的俄罗斯冰球运动员帕尔金 上帝保佑 # # #197 #00:15:28,750 --> 00:15:35,534 #А как нам это проверить? Я вот спортсменов в лицо не много знаю, кроме нашего физрука. #我们如何检查它呢 除了我们的体育老师之外 我不认识很多运动员 # # #198 #00:15:35,534 --> 00:15:36,919 #- Емельян, у тебя паспорт с собой? #- 埃米利安 你带着你的护照了吗 # # #199 #00:15:37,150 --> 00:15:38,942 #- Да зачем, меня и так все знают. #- 为什么 每个人都已经认识我了 # # #200 #00:15:38,942 --> 00:15:41,173 #- Так все тебя знают, а вот узнают тебя не все. #- 所以每个人都认识你 但不是每个人都认识你 # # #201 #00:15:44,175 --> 00:15:48,591 #- А давайте-ка я вам лучше смешную историю расскажу? #- 我为什么不告诉你一个有趣的故事呢 # # #202 #00:15:48,591 --> 00:15:53,135 #Однажды мы, значит, заходим к тренеру с Овечкиным и Малкиным. #有一天 我们和奥维契金和马尔金一起去教练办公室 # # #203 #00:15:53,375 --> 00:15:57,727 #Тренер говорит: «Ну, вы с канадцами играете?» Мы. Ну! #教练说:"好吧 你要和加拿大人比赛吗 "我们是 好吧! # # #204 #00:15:58,675 --> 00:16:05,587 #Он говорит: «Вы у них выиграете?» Мы. Ну! Ну и выиграли! Смешно, правда? #他说 "你会打败他们吗 "我们是 好吧!嗯 我们做到了!很有趣 不是吗 # # #205 #00:16:09,700 --> 00:16:10,724 #- Обхохочешься. #- 这是很搞笑的 # # #206 #00:16:20,425 --> 00:16:22,425 #- Веник, я пришла к тебе на время пожить. #- 布罗姆 我是来和你住一段时间的 # # #207 #00:16:23,350 --> 00:16:26,678 #- Да? А судя по количеству вещей, ты пришла до конца жизни. #- 是吗 从这些东西的数量来看 你在这里的余生都是如此 # # #208 #00:16:26,800 --> 00:16:30,050 #- На меня девочки обиделись из-за того, что я с Полежайкиным поцеловалась. #- 女孩们对我很生气 因为我吻了波列沙金 # # #209 #00:16:30,875 --> 00:16:32,475 #- Ты целовалась с Полежайкиным? #- 你和波列亚金亲热过吗 # # #210 #00:16:32,475 --> 00:16:35,505 #Слушай, а от него ты наверное хотела бицепсами заразиться, да? #听着 你可能想从他那里得到二头肌 不是吗 # # #211 #00:16:35,505 --> 00:16:40,951 #- Девчонки объявили мне бойкот, поэтому я написала им записку, что между мной Веником ничего не было. #- 女孩们抵制我 所以我给她们写了一张纸条 说我和韦尼克之间什么都没发生 # # #212 #00:16:40,951 --> 00:16:42,615 #Поэтому я ушла жить к Венику. #所以我去和维尼克一起生活 # # #213 #00:16:43,300 --> 00:16:46,700 #- Отличное доказательство, теперь они точно поверят, что между нами ничего не было. #- 很好的证据 现在他们肯定会相信我们之间什么都没发生 # # #214 #00:16:46,700 --> 00:16:49,644 #Мы просто с тобой живем в 1 комнате и спим на 1 кровати. #你和我只是住在一个房间 睡在一张床上 # # #215 #00:16:49,644 --> 00:16:50,860 #- Почему на одной? #- 为什么是一个 # # #216 #00:16:51,475 --> 00:16:53,350 #- Маш, потому что другой кровати здесь нет. #- 马什 因为这里没有别的床 # # #217 #00:16:53,350 --> 00:16:55,061 #- Ну а ты тогда где будешь спать? #- 那时你将在哪里睡觉 # # #218 #00:16:56,375 --> 00:17:01,047 #- Господи, ну что же я такого в прошлой жизни сделал, что я в этой жизни встретил тебя, Маша? #- 天啊 我前世做了什么 才会在今生遇到你 玛莎 # # #219 #00:17:01,047 --> 00:17:05,246 #- У меня от этих нервов так голова разболелась… Надо но-шпу выпить. #- 这些神经让我头疼不已......我需要一个鼻烟壶 # # #220 #00:17:06,100 --> 00:17:06,676 #Так… #所以... # # #221 #00:17:07,275 --> 00:17:07,915 #- Дай мне. #- 把它给我 # # #222 #00:17:08,375 --> 00:17:09,591 #- А тебе зачем? #- 你需要它来做什么 # # #223 #00:17:09,900 --> 00:17:13,164 #- У тебя от нервов голова болит, а у меня от тебя. #- 你的神经让你头疼 你让我头疼 # # #224 #00:17:14,825 --> 00:17:16,361 #- Может, тогда на брудершафт? #- 那就喝杯啤酒吧 # # #225 #00:17:17,200 --> 00:17:19,479 #- Маш, а ты можешь делать что-нибудь, не целуясь? #- 马什 不接吻你能做什么吗 # # #226 #00:17:19,925 --> 00:17:21,077 #- Ну конечно! #- 当然了! # # #227 #00:17:27,575 --> 00:17:28,727 #Какая прелесть! #多么可爱! # # #228 #00:17:34,000 --> 00:17:36,816 #- А вот еще смешнее история! #- 这里有一个更有趣的故事! # # #229 #00:17:36,816 --> 00:17:39,264 #- А, пошли вы с Овечкиным и Малкиным… #- 啊 去他妈的奥维契金和马尔金...... # # #230 #00:17:39,825 --> 00:17:43,857 #- Точно! А вы откуда знаете? Я эту историю еще не рассказывал. #- 对了!你怎么知道的 我还没有讲过这个故事 # # #231 #00:17:43,857 --> 00:17:47,121 #- А расскажи лучше, как вы кубок Стэнли получили! #- 告诉我们你是如何得到斯坦利杯的! # # #232 #00:17:47,500 --> 00:17:54,476 #- Точно! Помню – беру я кубок Стэнли… Извините. #- 这就对了!我记得--我把斯坦利杯......对不起 # # #233 #00:17:54,925 --> 00:17:58,061 #А он тогда тоже рядом стоял и молчал. #而他当时也站在我身边 一言不发 # # #234 #00:17:58,061 --> 00:18:03,625 #- Так, хватит на сегодня! В общем, Васнецова, никакой это не Палкин. #- 好了 今天就说到这里吧!总之 瓦斯涅佐娃 这不是巴尔金 # # #235 #00:18:04,150 --> 00:18:08,694 #Он со своими смешными историями про Малкина больше на Галкина похож! #他和他关于马尔金的有趣的故事更像加尔金 # # #236 #00:18:09,700 --> 00:18:11,700 #- Таисия Кирилловна, вы долго еще? #- 塔伊西娅-基里洛夫娜 你会很久吗 # # #237 #00:18:12,425 --> 00:18:13,385 #- Валера! #- 瓦莱拉 # # #238 #00:18:13,385 --> 00:18:14,368 #- Емеля! #- Emelya! # # #239 #00:18:14,900 --> 00:18:16,244 #- Валерьянка! #- Valerian! # # #240 #00:18:16,244 --> 00:18:17,043 #- Емельянка! #- 埃米利安卡 # # #241 #00:18:24,350 --> 00:18:26,350 #- Что здесь происходит? #- 这里发生了什么事 # # #242 #00:18:28,525 --> 00:18:32,148 #- Таисия Кирилловна, что же вы не сказали, что к нам Палкин в школу придет? #- 塔伊西娅-基里洛夫娜 你为什么不告诉我们巴尔金要来学校 # # #243 #00:18:32,400 --> 00:18:34,576 #Мы же с ним в Юльской сборной вместе играли! #他和我一起在尤里队打球 他是我的朋友 # # #244 #00:18:35,325 --> 00:18:37,693 #Я тогда травму получил, а он вызов. #当时我受伤了 他接到了这个电话 # # #245 #00:18:41,525 --> 00:18:45,557 #- Это что, правда что ли Палкин? Цветы, быстро-быстро-быстро! #- 那真的是帕尔金吗 鲜花 快 快 快! # # #246 #00:18:45,925 --> 00:18:53,310 #Ребята, что же вы молчите! У нас в гостях знаменитый российский хоккеист Палкин! #伙计们 你们为什么不说点什么 我们有著名的俄罗斯冰球运动员Palkin! # # #247 #00:18:59,525 --> 00:19:04,197 #- Круто, Васнецова! Сначала ненастоящая Робски, потом настоящий Палкин! #- 酷 瓦斯涅佐娃!首先是假的罗伯斯基 然后是真的帕尔金! # # #248 #00:19:04,197 --> 00:19:05,925 #Второй раз училок развела! #老师们第二次离婚了! # # #249 #00:19:12,750 --> 00:19:16,398 #- Да, Маш, только ты могла уйти из дома под одеяло. #- 是的 马什 只有你能在被子里离开房子 # # #250 #00:19:19,650 --> 00:19:22,722 #Веник! Ты что здесь делаешь? #扫帚 你在这里做什么 # # #251 #00:19:23,050 --> 00:19:28,106 #- Маша спит у меня в общаге. Если она заняла мою кровать, значит, я полное право имею занять ее. #- 玛莎睡在我的宿舍里 如果她占用了我的床 那么我就有权利占用她的 # # #252 #00:19:32,400 --> 00:19:34,050 #- Ты почему в трусах?! #- 你为什么要穿裤子 # # #253 #00:19:34,050 --> 00:19:36,050 #- Это не трусы, это шпаргалка! #- 这不是裤子 这是一张小抄! # # #254 #00:19:36,525 --> 00:19:39,981 #- Веник, ты что, дурак? А если сюда войдут? #- 布罗姆 你傻了吗 如果他们进来了怎么办 # # #255 #00:19:39,981 --> 00:19:43,245 #- Пускай, пускай войдут! Пускай войдут и подумают, что между нами что-то есть! #- 让他们进来 让他们进来!让他们进来 认为我们之间有什么东西! # # #256 #00:19:43,245 --> 00:19:46,959 #- Но между нами ничего нету! А ну слезай с кровати, я сказала! #- 但我们之间没有任何关系!从床上下来 我说 # # #257 #00:19:46,959 --> 00:19:47,663 #- Слезай! #- 下来 # # #258 #00:19:48,325 --> 00:19:52,677 #- Да все равно тебе никто не поверит, что между нами ничего нет. #- 反正没有人会相信你说我们之间没有什么 # # #259 #00:19:52,677 --> 00:19:55,365 #Ты же не поверила, что между мной и Машей ничего нет. #你不相信我和玛莎之间没有什么 # # #260 #00:19:55,365 --> 00:19:57,590 #- Ах так, тогда уйду я. #- 啊 这样 那我就去吧 # # #261 #00:19:57,590 --> 00:19:58,422 #- А ну-ка стой! #- 就在那里停下 # # #262 #00:19:58,422 --> 00:20:05,117 #- Мамочки! Нет-нет-нет. Я сейчас закричу. #- 妈咪 不 不 不 不 不 我要大叫了 # # #263 #00:20:05,117 --> 00:20:08,350 #- Даш, ты сама напросилась, я обязан заткнуть тебе рот. #- 小飞 是你自找的 我有义务让你闭嘴 # # #264 #00:20:16,425 --> 00:20:17,577 #- Маша… #- 玛莎... # # #265 #00:20:17,577 --> 00:20:18,468 #- Даша! #- Dasha! # # #266 #00:20:19,550 --> 00:20:21,550 #- Маш, это не то, что ты подумала. #- 马什 这不是你想的那样 # # #267 #00:20:21,900 --> 00:20:22,924 #- Веник. #- 扫帚 # # #268 #00:20:24,075 --> 00:20:24,843 #- Что? #- 什么 # # #269 #00:20:27,525 --> 00:20:30,213 #- Ну сколько можно повторять: мы не целовались. #- 我得告诉你多少次:我们没有接吻 # # #270 #00:20:30,475 --> 00:20:33,163 #- Ага, вы с ним физику учили. #- 是的 你和他一起学习物理学 # # #271 #00:20:33,500 --> 00:20:36,764 #Вот теперь понимаешь, Даш, что не всегда можно верить тому, что видишь. #现在你知道了 Dash 你不能总是相信你看到的东西 # # #272 #00:20:36,764 --> 00:20:37,975 #- Не знаю, мне понравилось. #- 我不知道 我喜欢它 # # #273 #00:20:38,275 --> 00:20:44,099 #- Веник, вот ты с виду скромный, а уже перецеловался с половиной семьи Васнецовых. #- 布罗姆 你看起来很谦虚 但你已经亲吻了半个瓦斯涅佐夫家族 # # #274 #00:20:45,200 --> 00:20:47,017 #- Ну Даш, мир? #- 好吧 Dash 和平 # # #275 #00:20:48,550 --> 00:20:49,638 #- Вот теперь мир. #- 现在 世界和平了 # # #276 #00:20:50,700 --> 00:20:56,396 #- Хорошо, все разрешилось. А то мне спать было негде, меня комендант из общаги выгнал. #- 很好 都整理好了 我没有地方睡觉 管理员把我从宿舍里赶了出来 # # #277 #00:20:56,396 --> 00:21:00,428 #- Отлично! Теперь мне спать негде. Меня уж точно комендант назад не пустит. #- 那很好啊!我没有地方可以睡觉 指挥官肯定不会让我再进去了 # # #278 #00:21:01,275 --> 00:21:04,650 #- Дашенька, а может, пусть Веник у нас переночует? #- 达申卡 我们为什么不让韦尼克过夜呢 # # #279 #00:21:05,150 --> 00:21:09,950 #- Ага, только надо ему рот скотчем заклеить, чтобы никого не целовал. #- 是的 但我们应该用胶带封住他的嘴 这样他就不会吻任何人 # # #280 #00:21:10,325 --> 00:21:15,876 #- Значит так, ложишься на полу, подальше от меня и от Маши тоже. #- 好吧 你躺在地上 离我远一点 也离玛莎远一点 # # #281 #00:21:17,950 --> 00:21:22,110 #- Доброе утро, девочки… и мальчики. #- 早上好 姑娘们......还有小伙子们 # # #282 #00:21:25,900 --> 00:21:29,612 #- Людмила Сергеевна, это не то, что вы подумали. #- 柳德米拉-谢尔盖耶夫娜 事情不是您想的那样 # # #283 #00:21:29,612 --> 00:21:35,820 #- А что я подумала? Что тебя не пустили в общежитие, и девочки пустили тебя переночевать у нас? #- 我是怎么想的 你不被允许进入宿舍 而女孩们却让你睡在那里 # # #284 #00:21:37,050 --> 00:21:39,400 #Быстро всем умываться и завтракать. #很快 大家洗漱完毕 吃了早餐 # # #285 #00:21:42,675 --> 00:21:43,955 #- Классная мама. #- 冷静的妈妈 # # #286 #00:21:44,775 --> 00:21:49,191 #- Ой, вот видишь, Веник, ты уже ее мамой называешь. #- 哦 你看 维尼克 你已经在叫她妈妈了 # # #287 #00:21:49,191 --> 00:21:50,502 #- Очень смешно. #- 非常有趣 # # #288 #00:21:54,450 --> 00:21:59,865 #- Дорогие ребята, чтобы больше не рисковать репутацией школы в лице ее директора, #- 亲爱的孩子们 不要再拿学校校长的名誉去冒险 # # #289 #00:22:00,100 --> 00:22:02,980 #интересных людей теперь буду приглашать я. #有趣的人现在将由我来邀请 # # #290 #00:22:03,675 --> 00:22:06,299 #- Сто пудов, опять физрука приведет. #- 我相信他一定会再把体育老师找来的 # # #291 #00:22:06,299 --> 00:22:11,022 #- Тихо! Вчера в очереди я познакомилась с замечательным человеком. #- 安静 昨天我在排队时遇到了一个很棒的人 # # #292 #00:22:11,975 --> 00:22:14,275 #- Наверное, замечательный человек ее в очереди пропустил. #- 一个优秀的人一定在排队中错过了她 # # #293 #00:22:14,275 --> 00:22:19,907 #- Васнецова! Оказалось, что это – народная артистка СССР. #- 瓦斯涅佐娃 它原来是苏联的人民艺术家 # # #294 #00:22:20,175 --> 00:22:22,927 #Она живет в доме, где когда-то жил Брежнев. #她住在勃列日涅夫曾经住过的房子里 # # #295 #00:22:23,200 --> 00:22:28,335 #В одном подъезде с Сережей Безруковым, Задорновым и Юрием Михайловичем Лужковым! #与谢廖莎-别兹鲁科夫、扎多诺夫和尤里-米哈伊洛维奇-卢日科夫在同一个入口处 这是对他们的尊重 # # #296 #00:22:28,675 --> 00:22:35,331 #Итак, встречайте: Ефросинья Петровна Жихарева-Болконская, прошу! #所以 请见见埃弗罗辛亚-彼得罗夫娜-日哈列娃-波尔孔斯卡娅吧 " # # #297 #00:22:38,750 --> 00:22:41,182 #- Спасибо, Таисия Кирилловна. #- 谢谢你 塔伊西娅-基里洛夫娜 # # #298 #00:22:41,725 --> 00:22:53,053 #Здравствуйте, дети. Помню, помню я, как мы с Леонидом Дежневым на работу шли. #你好 孩子们 我记得 我记得和列昂尼德-德日涅夫一起工作 # # #299 #00:22:53,375 --> 00:22:59,199 #Меня так приветливо в подъезде «Здравствуйте, Ефрося, проходите пожалуйста». #我在入口大厅受到了如此欢快的问候:"你好 艾弗罗莎 请进" # # #300 #00:22:59,575 --> 00:23:03,543 #И сам в подъезде мне дверь открывал. #他还亲自在入口大厅为我开门 # # #301 #00:23:03,975 --> 00:23:05,454 #- Здравствуйте, тетя Фрося. #- 你好 弗罗西娅阿姨 # # #302 #00:23:06,875 --> 00:23:08,795 #- Вы что, знакомы? #- 你们俩认识吗 # # #303 #00:23:09,500 --> 00:23:14,100 #- Конечно! Мы с тетей Фросей в одном подъезде живем, да, тетя Фрося? #- 当然 你是!我和Frosia阿姨住在同一个入口 对吗 Frosia阿姨 # # #304 #00:23:14,100 --> 00:23:19,175 #Да, с Безруковым и Брежневым. Кстати, тетя Фрося, #是的 与贝兹鲁科夫和勃列日涅夫 顺便说一句 弗罗莎阿姨 # # #305 #00:23:19,175 --> 00:23:24,793 #вы когда мусор выносите, не бросайте на лестничной клетке. Нехорошо, соседи жалуются. #当你倒垃圾的时候 不要把它扔在楼梯间 邻居们抱怨说 这可不行 # # #306 #00:23:24,793 --> 00:23:25,753 #Особенно Лужков. #特别是卢日科夫 # # #307 #00:23:26,625 --> 00:23:30,337 #- А я, дура, опять не там оставила. Надо пойти убрать. #- 我又愚蠢地把它放在了错误的地方 我得去把它清理干净 # # #308 #00:23:30,725 --> 00:23:33,989 #Пока Юрочка Лужков с трудовой работы не пришел. #直到尤洛奇卡-卢茨科夫下班回来 # # #309 #00:23:34,875 --> 00:23:39,867 #- Ну ты, Васнецова, спортсменка! Учителей в сухую разделала 3:0. #- 好吧 瓦斯涅佐娃 你是个运动员 你是个运动员 老师们3比0落后 # # #