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();