【编译原理】 实现一个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<clousure.length;i++) {
    //     gotoMap[i] = [];
    //     for(let j=0;j<nonEndIcon.length;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();
  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。
LR语法分析器编译原理中的一种语法分析方法,它可以根据给定的文法规则,对输入的程序代码进行分析和解析。LR语法分析器使用自底向上的分析方法,通过构建一个状态机来识别输入的符号串是否符合给定的文法规则。 LR语法分析器实现通常使用工具,如Bison(Yacc的GNU版本),它可以根据给定的文法规则自动生成相应的语法分析器LR语法分析器的工作原理如下: 1. 构建LR分析表:根据给定的文法规则,LR语法分析器会构建一个分析表,该表记录了在不同状态下,对应不同输入符号的移进、规约或接受操作。 2. 状态转移:LR语法分析器通过状态转移来处理输入符号串。它从初始状态开始,根据当前状态和下一个输入符号,查找分析表中对应的操作,并执行相应的移进或规约操作。 3. 移进操作:当遇到终结符号时,LR语法分析器会将该符号移入栈中,并读取下一个输入符号。 4. 规约操作:当遇到非终结符号时,LR语法分析器会根据文法规则进行规约操作,将栈中的符号按照规约规则进行替换。 5. 接受操作:当输入符号串被完全分析并符合文法规则时,LR语法分析器会执行接受操作,表示输入符号串被成功地分析和解析。 通过使用LR语法分析器,可以对程序代码进行语法分析,并生成相应的抽象语法树(AST)。抽象语法树可以用于后续的语义分析和代码生成等编译过程。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值