编译原理实验(二)之语法分析

版权声明:本文为博主原创文章,纯粹自娱。 https://blog.csdn.net/moakun/article/details/86412707

采用实验1的简单语言,设计并实现含多条简单赋值语句的语法分析程序,要求采用算符优先的分析算法。   

注意与实验1、2的衔接。

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SyntaxAnalysis {
    struct Error {
        Word word;
        string text;
    }
    class SyntaxAnalysis {
        WordPicker wordPicker = new WordPicker("text.txt");
        List<Word> words = new List<Word>();
        int index = -1;
        List<Error> errors = new List<Error>();

        static void Main(string[] args) {
            SyntaxAnalysis syntax = new SyntaxAnalysis();
            syntax.grammerParser();
            Console.ReadKey();
        }
        /// <summary>
        /// 语法分析
        /// </summary>
        public void grammerParser() {
            do {
                functionParser();
            } while(nextWord().typeNum != WordPicker.endTypeNumber);
            if(success)
                Console.WriteLine("成功");
        }

        private void functionParser() {

            Word word = nextWord();
            //返回类型
            if(!KeyWords.isReturnType(word)) {
                addError(word, "返回值错误");
            }
            word = nextWord();
            //函数名
            if(!isIdentifier(word)) {
                addError(word, "函数名错误");
            }
            //(参数){
            word = nextWord();
            if(!isLeftBracket(word)) {
                addError(word, "(缺失");
            }
            arguments();
            word = nextWord();
            if(!isRightBracket(word)) {
                addError(word, ")缺失");
            }
            word = nextWord();
            if(word.typeNum != Symbols.left_curly_bracket.typeNum) {
                addError(word, "{缺失");
            }
            //语句串
            statementSequence();
            //}
            word = nextWord();
            if(word.typeNum != Symbols.right_curly_bracket.typeNum) {
                addError(word, "}缺失");
                retractWord();
            }

        }
        private bool isLeftBracket(Word word) {
            return word.typeNum == Symbols.left_bracket.typeNum;
        }

        private bool isRightBracket(Word word) {
            return word.typeNum == Symbols.right_bracket.typeNum;
        }

        bool success = true;
        private void addBeforeError(Word word, string v) {
            success = false;
            Console.WriteLine(word.ToPositionInfo() + "\t之前 " + v);
        }
        private void addError(Word word, string v) {
            success = false;
            Console.WriteLine(word.ToPositionInfo() + "\t" + v);
        }
        /// <summary>
        /// 参数
        /// </summary>
        private void arguments() {
            Word word = nextWord();
            if(!KeyWords.isType(word)) {
                if(isIdentifier(word))
                    addBeforeError(word, "参数类型缺失");
                else {
                    if(lastWord().typeNum == Symbols.comma.typeNum)
                        addBeforeError(word, ",多余");
                    retractWord();
                    return;
                }
            }
            word = nextWord();
            if(!isIdentifier(word)) {
                addBeforeError(word, "参数标识符错误");
                if(isRightBracket(word)) {
                    retractWord();
                    return;
                }
            }
            //逗号
            word = nextWord();
            if(word.typeNum == Symbols.comma.typeNum) {
                arguments();
            }
            else if(isRightBracket(word)) {
                retractWord();
                return;
            }

        }

        private bool isIdentifier(Word word) {
            return word.typeNum == WordPicker.identifierTypeNumber;
        }


        /// <summary>
        /// 语串
        /// </summary>
        private void statementSequence() {
            Word word = nextWord();
            while(word.typeNum != Symbols.right_curly_bracket.typeNum && word.typeNum != WordPicker.endTypeNumber) {

                if(KeyWords.isType(word)) {
                    defineStatement();
                }
                else if(isIdentifier(word)) {
                    assignStatement();
                }
                else {
                    addError(word, "多余");
                }
                /*  else if(KeyWords.isCondition(word)) {

                   }
                   else if(KeyWords.isFORLoop(word)) {

                   }
                   else {
                      // addError(word, "多余");
                   }*/
                word = nextWord();
            }
            retractWord();
        }
        /// <summary>
        /// 定义语句
        /// </summary>
        private void defineStatement() {
            Word word = nextWord();
            if(!isIdentifier(word)) {
                addBeforeError(word, "变量名缺失");
                retractWord();
            }
            word = nextWord();
            if(word.typeNum == Symbols.assign.typeNum) {
                expressStatement();
                word = nextWord();
            }
           
            if(word.typeNum == Symbols.comma.typeNum) {
                defineStatement();
            }
            else if(word.typeNum != Symbols.semicolon.typeNum) {
                addBeforeError(word, ";缺失");
                retractWord();
            }

        }
        /// <summary>
        /// 赋值语句
        /// </summary>
        private void assignStatement() {
            Word word = nextWord();
            if(word.typeNum != Symbols.assign.typeNum) {
                addBeforeError(word, "=缺失");
                retractWord();
            }
            expressStatement();
            word = nextWord();
            if(word.typeNum != Symbols.semicolon.typeNum) {
                    addBeforeError(word, ";缺失");
                    retractWord();
            }
           
        }
        /// <summary>
        /// 表达式
        /// </summary>
        private void expressStatement() {
           
            term();
            Word word = nextWord();
            while(word.typeNum == Symbols.add.typeNum || word.typeNum == Symbols.sub.typeNum) {
                term();
                word = nextWord();
            }         
            retractWord();

        }

        private void term() {
            factor();
            Word word = nextWord();
            while(word.typeNum == Symbols.mul.typeNum || word.typeNum == Symbols.except.typeNum || word.typeNum == Symbols.remain.typeNum) {
                factor();
                word = nextWord();
            }
            retractWord();
        }
        /// <summary>
        /// 表达式因子
        /// </summary>
        private void factor() {
            Word word = nextWord();
            if(isValue(word))
                return;
            if(word.typeNum == Symbols.left_bracket.typeNum) {
                expressStatement();
                word = nextWord();
                if(word.typeNum != Symbols.right_bracket.typeNum) {
                    addBeforeError(word, ")缺失");
                    retractWord();
                }
            }
            else {
                addBeforeError(word, "表达式错误");
                retractWord();
            }


        }
        /// <summary>
        /// 判断是否是数值类型
        /// </summary>
        /// <param name="word"></param>
        /// <returns></returns>
        private bool isValue(Word word) {
            return word.typeNum == WordPicker.numberTypeNumber
                || word.typeNum == WordPicker.charTypeNumber
                || word.typeNum == WordPicker.stringTypeNumber
                || word.typeNum == WordPicker.identifierTypeNumber;
        }
        /// <summary>
        /// 读取下一个词
        /// </summary>
        /// <returns></returns>
        private Word nextWord() {
            index++;
            if(words.Count <= index) {
                Word w = wordPicker.Scanner();
                if(words.Count == 0 || words[words.Count - 1].typeNum != WordPicker.endTypeNumber)
                    words.Add(w);
                index = words.Count - 1;
            }
            return words[index];
        }
        /// <summary>
        /// 现在的词
        /// </summary>
        /// <returns></returns>
        private Word nowWord() {

            if(words.Count > index && index >= 0) {
                return words[index];
            }
            return null;
        }
        /// <summary>
        /// 上一个词
        /// </summary>
        /// <returns></returns>
        private Word lastWord() {

            if(index > 0) {

                return words[index - 1];
            }
            else {
                return null;
            }

        }
        /// <summary>
        /// 回退一个词
        /// </summary>
        private void retractWord() {

            if(index >= 0) {
                index--;
            }

        }
    }
}
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace SyntaxAnalysis {
    /// <summary>
    /// 词
    /// </summary>
    class Word {
        public int typeNum;
        public string word;
        public int col=0;
        public int row=0;
        public override string ToString() {
            return "(" + typeNum + "," + word + ")";
        }
        public string ToPositionInfo() {
            return "行:"+(row+1)+"\t列:"+col+"\t码:"+typeNum + "\t字:" + word;
        }
    }
    

    class WordPicker {
   
        string[] input;
        //int input_index = 0;
        int row = 0;
        int col = 0;
        char character;
       
        /// <summary>
        /// 操作符表
        /// </summary>    
        string[] operatorSort = null;

        public static int identifierTypeNumber;    //变量名类型
        public static int numberTypeNumber;        //数值类型
        public static int charTypeNumber;          //字符类型
        public static int stringTypeNumber;        //字符串类型
        public static int endTypeNumber = -1;      //结束符类型
        public static int errorTypeNumber = -2;    //出错类型
        public static int noDefine = -3;           //未定义类型
        public static char nullChar = '\0';

        public WordPicker(string file) {
            input= File.ReadAllLines(file);           
            identifierTypeNumber = KeyWords.keyWordTable.Length+1;
            numberTypeNumber = KeyWords.keyWordTable.Length + 2;
            charTypeNumber = KeyWords.keyWordTable.Length + 3;
            stringTypeNumber = KeyWords.keyWordTable.Length + 4;

            operatorSort = new string[Symbols.operatorTable.Length];
            Array.Copy(Symbols.operatorTable, operatorSort, Symbols.operatorTable.Length);
            Array.Sort(operatorSort);
            Array.Reverse(operatorSort);
        }



        /// <summary>
        /// 读词
        /// </summary>
        /// <returns></returns>
        public Word Scanner() {
            Word myWord;          
            read();
            readValidChar();
            //标识符
            if(char.IsLetter(character)) {
                myWord=readWord();
            }//数值
            else if(char.IsDigit(character)) {
                myWord = readDigit();
            }//字符常量
            else if(character == '\'') {
                myWord = readConstChar();
            }//字符串
            else if(character == '\"') {
                myWord = readConstString();
            }/*//结束符
            else if(character == endChar) {
                myWord.word = "" + endChar;
                myWord.typeNum = endTypeNumber;
            }*///空值
            else if(character == nullChar) {
                myWord = new Word();
                myWord.row = row;
                myWord.col = col;
                myWord.word = "Ending";
                myWord.typeNum = endTypeNumber;
            }//其他字符
            else {
                myWord = readOtherChar();
            }
            return myWord;

        }
        /// <summary>
        /// 标识符
        /// </summary>
        /// <param name="myWord"></param>
        private Word readWord() {
            Word myWord = new Word();
            myWord.row = row;
            myWord.col = col;
            while(char.IsLetter(character) || char.IsDigit(character)) {
                myWord.word += character;
                read();
            }
            retract();
            myWord.typeNum = KeyWords.getTypeNumber(myWord.word);
            return myWord;
        }
        /// <summary>
        /// 其他字符
        /// </summary>
        /// <param name="myWord"></param>
        private Word readOtherChar() {
            Word myWord = new Word();
            myWord.row = row;
            myWord.col = col;
            string s = "" + character;
            for(int i = 0; i < 2; i++) {
                read();
                if(character == nullChar) {
                    break;
                }
                s += character;
            }
            foreach(string op in operatorSort) {
                if(s.StartsWith(op)) {
                    retract(s.Length - op.Length);
                    s = op;
                    break;
                }
            }
            myWord.word = s;
            myWord.typeNum = Symbols.getTypeNumber(myWord.word);
            return myWord;
        }

        private void retract(int v) {
            if(v == 0)
                return;
            col=col-v-1;
            if(col < 0) {
                row--;
                col = input[row].Length + col;
            }
            read();
        }



        /// <summary>
        /// 识别数字常量
        /// </summary>
        /// <param name="myWord"></param>
        private Word readDigit() {
            Word myWord = new Word();
            myWord.row = row;
            myWord.col = col;
            while(char.IsDigit(character)) {
                myWord.word += character;
                read();
            }
            if(character == '.') {
                myWord.word += character;
                read();
                while(char.IsDigit(character)) {
                    myWord.word += character;
                    read();
                }
            }
            retract();
            myWord.typeNum = numberTypeNumber;
             return myWord;
        }

        /// <summary>
        /// 识别字符常量
        /// </summary>
        /// <param name="myWord"></param>
        private Word readConstChar() {
            Word myWord = new Word();
            myWord.row = row;
            myWord.col = col;
            // myWord.word = "" + character;
            read();
            //读取直到'\''结束
            while(character != '\'') {
                myWord.word += character;
                read();
                //读到空字符或结束字符
                if(character == nullChar /*|| character == endChar*/|| char.IsControl(character)) {
                    /* if(character == endChar) {
                         myWord.word +=endChar;
                     } */
                    myWord.typeNum = errorTypeNumber;
                    return myWord;
                }
            }
            // myWord.word += character;
            Match r = Regex.Match(myWord.word, "^(\\\\([0-7]{1,3}|x[0-9a-fA-F]+|[abfnrtv\\\\\'\"?])|[^\\\\])$");
            //转义字符模式匹配
            if(!r.Success) {
                myWord.typeNum = errorTypeNumber;
                return myWord;
            }
            myWord.typeNum = charTypeNumber;
            return myWord;

        }
        /// <summary>
        /// 识别常量字符串
        /// </summary>
        /// <param name="myWord"></param>
        private Word readConstString() {
            Word myWord = new Word();
            myWord.row = row;
            myWord.col = col;
            // myWord.word = "" + character;
            read();
            while(character != '\"') {
                myWord.word += character;
                read();
                //读到空字符或结束字符
                if(character == nullChar || char.IsControl(character)) {
                    // myWord.word += "0";
                    myWord.typeNum = errorTypeNumber;
                    return myWord;
                }
            }
            // myWord.word += character;

            //转义字符模式匹配
            if(!isLegalString(myWord.word)) {
                myWord.typeNum = errorTypeNumber;
                return myWord;
            }
            myWord.typeNum = stringTypeNumber;
            return myWord;
        }

        /// <summary>
        /// 合法字符串书写
        /// </summary>
        /// <param name="word"></param>
        /// <returns></returns>
        private bool isLegalString(string word) {

            int i = 0;
            while(i < word.Length) {
                if(word[i] == '\\') {
                    if(++i == word.Length)
                        return false;
                    foreach(char c in translateChar) {
                        if(c == word[i]) {
                            goto aLabel;
                        }
                    }
                    return false;
                }
            aLabel:
                i++;
            }

            return true;
        }

        const string translateChar = "abfnrtv\\\'\"?";
        const string realChar = "\a\b\f\n\r\t\v\\\'\"?";

       

        /// <summary>
        /// 转换为真实字符串
        /// </summary>
        /// <param name="word"></param>
        /// <returns></returns>
        private string toRealString(string word) {
            string res = "";
            int index;
            for(int i = 0; i < word.Length; i++) {
                if(word[i] == '\\') {
                    if(++i == word.Length)
                        throw new Exception("字符串以\\结尾异常");

                    index = translateChar.IndexOf(word[i]);
                    if(index == -1)
                        throw new Exception("\\" + word[i] + "解析异常");
                    res += realChar[index];
                }
                else {
                    res += word[i];
                }
            }
            return res;
        }
        /// <summary>
        /// 读一个字符
        /// </summary>
        void read() {
            if(input.Length <= row|| input.Length == row+1 && input[input.Length-1].Length<=col) {
                character = '\0';
            }
            else {
                if(col >= input[row].Length) {
                    col = 0;
                    row++;
                }
                character = input[row][col];
                col++;
            }
                
        }
        /// <summary>
        /// 去除无效字符
        /// </summary>
        void readValidChar() {

            while(char.IsWhiteSpace(character)) {
                if(character == '\0') {
                    return;
                }
                read();              
            }
            //判断注释
            if(character == '/' && input[row].Length > col) {
                ignoreNote();
            }
        }

        private void ignoreNote() {
            read();
            //注释‘//’
            if(character == '/') {
                row++;
                col = 0;                              
                read();
                readValidChar();
            }//注释‘/*。。。*/’
            else if(character == '*') {
               
                read();
                if(character == '\0') {
                    return;
                }
                char c;
                while(true) {
                    
                    c = character;
                    read();
                    if('*' == c && '/' == character) {
                        read();
                        readValidChar();
                        return;
                    }
                    if(character == '\0') {
                        return;
                    }                
                }
            }
            else {
                retract();
            }
        }
 
        void retract() {            
            col=col-2;
            if(col < 0) {
                row--;
                col = input[row].Length + col;
            }
            read();
        }

    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace SyntaxAnalysis {
    class KeyWords {
        /// <summary>
        /// 关键字表
        /// </summary>
        public static string[] keyWordTable = {
            "auto","break","case", "char","const",
            "continue","default","do","double",
            "else","enum","extern","float","for",
            "goto","if", "int","long", "register",
            "return","short","signed","sizeof","static",
            "struct","switch","typedef","union","unsigned",
            "void","volatile","while"};

        public static Word AUTO, BREAK, CASE, CHAR, CONST,
        CONTINUE, DEFAULT, DO, DOUBLE,
        ELSE, ENUM, EXTERN, FLOAT, FOR,
        GOTO, IF, INT, LONG, REGISTER,
        RETURN, SHORT, SIGNED, SIZEOF, STATIC,
        STRUCT, SWITCH, TYPEDEF, UNION, UNSIGNED,
        VOID, VOLATILE, WHILE;

        static KeyWords() {
            Type t = typeof(KeyWords);

            FieldInfo[] fields = t.GetFields();
            Word word;
            foreach(FieldInfo f in fields)
                if(f.FieldType.Equals(typeof(Word))) {
                    word = new Word();
                    word.word = f.Name.ToLower();
                    word.typeNum = getTypeNumber(word.word);
                    f.SetValue(t, word);
                }
        }
        /// <summary>
        /// 获取关键字编码
        /// </summary>
        /// <returns></returns>
        public static int getTypeNumber(string s) {
            for(int i = 0; i < keyWordTable.Length; i++) {
                if(keyWordTable[i] == s) {
                    return i+1;
                }
            }

            return WordPicker.identifierTypeNumber;
        }
        public static bool isPrefType(Word w) {
            return SIGNED.typeNum == w.typeNum
               || UNSIGNED.typeNum == w.typeNum;
        }
        public static bool isType(Word w) {
            return INT.typeNum == w.typeNum
                || CHAR.typeNum == w.typeNum
                || DOUBLE.typeNum == w.typeNum
                || FLOAT.typeNum == w.typeNum
                || SHORT.typeNum == w.typeNum;               
        }

        public static bool isReturnType(Word w) {
            return isType(w) || VOID.typeNum == w.typeNum;
        }

        internal static bool isCondition(Word word) {
            return word.typeNum == IF.typeNum;
        }

        internal static bool isFORLoop(Word word) {
            return word.typeNum == FOR.typeNum|| word.typeNum == WHILE.typeNum;
        }
        internal static bool isWhileLoop(Word word) {
            return word.typeNum == WHILE.typeNum;
        }
        internal static bool isDoLoop(Word word) {
            return  word.typeNum == DO.typeNum;
        }

        internal static bool isKeyWord(Word word) {
            return word.typeNum > 0 && word.typeNum <= keyWordTable.Length;
        }
    }
    class Symbols {
        public static string[] operatorTable = {
            "{","}","[","]","(",")","->",".",
            "++","--",
            "!","&&","||",
            "~","&","|","^",
            "+","-","*","/","%",
            "<<",">>",
            "<",">",">=","<=",
            "==","!=","?",":",",",";",
            "=","+=","-=","*=","/=","%=",
            "&=","^=","|=","<<=",">>="
        };

        public static Word left_curly_bracket, right_curly_bracket,
            left_square_bracket, right_square_bracket,
            left_bracket, right_bracket,
            arrow, point, two_add, two_sub,
            logic_not, logic_and, logic_or,
            bitwise_not, bitwise_and, bitwise_or, bitwise_xor,
            add, sub, mul, except, remain,
            left_move, right_move,
            less, greater, greater_equal, less_equal,
            equal, not_equal, question_mark, colon, comma, semicolon,
            assign, add_assign, sub_assign, mul_assign, except_assign, remain_assign,
            and_assign, xor_assign, or_assign, left_move_assign, right_move_assign;

        internal static bool isSemicolo(Word word) {
            return word .typeNum == semicolon.typeNum;
        }

        static Symbols() {
            Type t = typeof(Symbols);

            FieldInfo[] fields = t.GetFields();
            Word word;
            int index = 0;
            foreach(FieldInfo f in fields)
                if(f.FieldType.Equals(typeof(Word))) {
                    word = new Word();
                    word.word = operatorTable[index++];
                    word.typeNum = getTypeNumber(word.word);
                    f.SetValue(t, word);
                }
        }

        public static int getTypeNumber(string s) {
            int start = 100;
            for(int i = 0; i < operatorTable.Length; i++) {
                if(operatorTable[i] == s) {
                    return start + i;
                }
            }
            return WordPicker.noDefine;
        }

       
    }
}

输入text.txt:

void main(int a,int b){	
   //int a=4-2;
   int a=a,b=a*82,c= a;
   b=12-12*x
   //long b=a-a8 b-2-2;
   //int bc=b-c*88/9;
}

输出:

猜你喜欢

转载自blog.csdn.net/moakun/article/details/86412707