【编译原理】 实现一个LR(0)语法分析器

实验目的

1. 巩固对语法分析的基本功能和原理的认识。
2. 通过对语法分析表的自动生成加深语法分析表的认识。
3. 理解并处理语法分析中的异常和错误。

实验要求

1.掌握语法分析程序的总体框架,并将其实现。
2.在编程构造的语法分析表的基础上上机实现SLR(1)分析。
3.能够对类高级语言中的基本语句(包括:函数定义;变量说明;赋值;循环;分支)进行语法分析。
4. 针对一类语句的文法给出其语法分析表的生成程序(对应不同的语法分析方法产生不同的分析表)。
代码:

// 'use static';
/*jshint esversion: 6 */
var fs = require('fs');
var write = fs.writeFileSync;
const FILE_PATH = "output.txt";
var data = fs.readFileSync(FILE_PATH).toString().trim().split('\r\n').join('');
// var input = fs.readFileSync('input.txt').toString().trim();
var arr = data.split('\n');
var clousure = [];  //项目族集
var endIcon = ['a', 'b', '+', '=', '#']; //终结符集合
var nonEndIcon = ['S', 'B', 'T', 'A'];   //非终结符集合
var actionMap = new Array(endIcon.length);
var gotoMap = new Array(nonEndIcon.length);
var dfaMap = [];
// var grammer = ['SBB','BaB','Bb'];  //定义的语法序列
var grammer = ['ST=A', 'AB+B', 'BaB','Bb'];

function initClousure() {
    /*
    grammer:此项目族集中含有的语法序列
        item: 语法序列,
        posOfDot: 点的位置
    */
    // let data = fs.readFileSync('data.txt').toString().trim().split('\r\n');
    let data = grammer;
    clousure.push({
        grammer:[{item: 's.S',posOfDot: 1}] //点的位置
    });
    clousure.push({
        grammer:[{item: 'sS.', posOfDot: 2}]
    });
    for(let item of data) {
        data[data.indexOf(item)] = item.replace(';', '');
        item = item.replace(';', '');
        for(let i=2;i<=item.length;i++) {
            var t = {
                grammer:[{item: item.slice(0, i) + '.' + item.slice(i),posOfDot: i}]
            };
            clousure.push(t);
        }
    }
    for(let j=0,len=clousure.length;j<len;j++) {
        let items = clousure[j];
        let lastNumOfItem = items.grammer.length;
        while(true) {
            let item = items.grammer[items.grammer.length-1];
            if(item.item.length === parseInt(item.posOfDot) + 1) {
                break;
            }
            let char = item.item[item.posOfDot+1];
            for(let i=0;i<data.length;i++) {
                if(char === data[i][0]) {
                    let str = data[i][0] + '.';
                    let isExist = false;
                    for(let k=1;;k++) {
                        if(data[i].length === k) break;
                        str += data[i][k];
                    }
                    for(let k=0;k<items.grammer.length;k++) {
                        if(str === items.grammer[k].item) {
                            isExist = true;
                            break;
                        }
                    }
                    if(isExist) continue;
                    clousure[j].grammer.push({item: str, posOfDot: 1});
                }
            }
            if(lastNumOfItem === items.grammer.length) break;
            lastNumOfItem = items.grammer.length;
        }
    }
    for(let i=0;i<clousure.length;i++) {
        actionMap[i] = [];
        for(let j=0;j<endIcon.length;j++) {
            actionMap[i].push('err');
        }
        gotoMap[i] = [];
        for(let j=0;j<nonEndIcon.length;j++) {
            gotoMap[i].push('err');
        }
    }
    // for(let i=0;i
    //     gotoMap[i] = [];
    //     for(let j=0;j
    //         gotoMap[i].push('err');
    //     }
    // }
}
//计算dfa
function initDFA() {
    for(let i=0;i<clousure.length;i++) {
        let items = clousure[i].grammer;
        for(let g=0;g<items.length;g++) {
            let item = items[g];
            let str = item.item;
            if(item.item.length - 1 === parseInt(item.posOfDot)) continue;
            let symbol = item.item[item.posOfDot + 1];
            str = str.slice(0, item.posOfDot) + symbol + '.' + str.slice(item.posOfDot + 2);
            for(let j=0;j<clousure.length;j++) {
                let t = clousure[j];
                for(let k of t.grammer) {
                    if(k.item == str) dfaMap.push({x: i,y:j,symbol});
                }
            }
        }
    }
}
//初始化action表和goto表
function initChart() {
    actionMap[1][endIcon.indexOf('#')] = 'acc';
    for(let i=0;i<clousure.length;i++) {  
        let item = clousure[i].grammer;
        if(item.length === 1 && item[0].item.length === 1 + item[0].item.indexOf('.')) {
            let str = item[0].item;
            str = str.slice(0, str.indexOf('.'));
            for(let j=0;j<grammer.length;j++) {
                if(str === grammer[j]) {
                    for(let k=0;k<actionMap[i].length;k++) {
                        actionMap[i][k] = 'R' + (j+1);
                    }
                }
            }
        }
    }
    for(let item of dfaMap) {
        if(endIcon.indexOf(item.symbol) !== -1) actionMap[item.x][endIcon.indexOf(item.symbol)] = item.y;
        else actionMap[item.x][nonEndIcon.indexOf(item.symbol)] = item.y;
    }
    for(let item of dfaMap) {
        if(nonEndIcon.indexOf(item.symbol) !== -1) gotoMap[item.x][nonEndIcon.indexOf(item.symbol)] = item.y;
    }
}
function analyze() {
    let input = "T=A#";
    let stack = "";
    let status = [0];
    while(true) {
        stack += input[0];
        let char = input[0];
        input = input.slice(1);
        if(actionMap[status[status.length-1]][0][0] === 'R') {
            let t = parseInt(actionMap[status[status.length-1]][0].slice(1));
            let str = grammer[t-1].slice(1);
            stack = stack.slice(0, stack.indexOf(str));
            input = grammer[t-1][0] + input;
            status.pop();
        } else if(endIcon.indexOf(char) === -1) {
            if(nonEndIcon.indexOf(char) === -1) {
                console.log('error1');
                return;
            }
            if(gotoMap[status[status.length-1]][nonEndIcon.indexOf(char)] !== "err") {
                status.push(parseInt(gotoMap[status[status.length-1]][nonEndIcon.indexOf(char)]));
                while(true) {
                    try {
                        if(actionMap[status[status.length-1]][0].indexOf('R') !== -1) {
                            console.log("用"+actionMap[status[status.length-1]][0]+'归约');
                            let t = parseInt(actionMap[status[status.length-1]][0].slice(1));
                            let str = grammer[t-1].slice(1);
                            stack = stack.slice(0, stack.indexOf(str));
                            input = grammer[t-1][0] + input;
                            for(let item of str) {
                                status.pop();
                            }
                        } else {
                            break;
                        }
                    } catch(e) {
                        break;
                    }
                }
            } else {
                console.log('error2');
                return;
            }
        } else if(actionMap[status[status.length-1]][endIcon.indexOf(char)] === "err") {
            console.log('error3');
            return;
            
        } else if(actionMap[status[status.length-1]][endIcon.indexOf(char)] === "acc") {
            console.log('success');
            return;
        } else {
            if(typeof actionMap[status[status.length-1]][endIcon.indexOf(char)] === 'number') {
                status.push(parseInt(actionMap[status[status.length-1]][endIcon.indexOf(char)]));
                while(true) {
                    try {
                        if(actionMap[status[status.length-1]][0].indexOf('R') !== -1) {
                            console.log("用"+actionMap[status[status.length-1]][0]+'归约');
                            let t = parseInt(actionMap[status[status.length-1]][0].slice(1));
                            let str = grammer[t-1].slice(1);
                            stack = stack.slice(0, stack.indexOf(str));
                            input = grammer[t-1][0] + input;
                            for(let item of str) {
                                status.pop();
                            }
                        }
                    } catch(e) {
                        break;
                    }
                }
            }
            else {
                let t = parseInt(actionMap[status[status.length-1]][endIcon.indexOf(char)].slice(1));
                let str = grammer[t-1].slice(1);
                console.log("用"+'r'+t+'归约');
                stack = stack.slice(0, stack.indexOf(str));
                input = grammer[t-1][0] + input;
                for(let item of str) {
                    status.pop();
                }
            }
        }
    }
}
function init() {

}
initClousure();
initDFA();
initChart(); 
analyze();

你可能感兴趣的:(编译原理)