软件构造编译原理程序自动生成First和Follow集

…最近快期末, 忙于考试和整理各种实验, 好久没有写博客了. 今天来补上一篇今天刚写完的实验. 本代码采用Node.js, 但逻辑看会了, 用C/C++改不是问题, 主要使用递归. 下面见如下代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
//主文件入口 index.js
const readline = require('readline');
const fs = require('fs');
const path = require('path');
const anylize = require('./anylaze').anylize;
const output = require('./output').output;


const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
prompt: 'xuan >',
});

rl.prompt();

let wenG = {};
let p = {};

rl.on('line', (line) => {
let command = line.trim().split(/\s+/);

if (command[0] == 'xuan') {
let fileName = path.resolve(__dirname, command[1]);
fs.exists(fileName, function (exists) {
if (exists) {
fs.readFile(fileName, 'utf-8', function (error, content) {//打开文件
if (error) {
console.log(`打开文件失败${fileName}`);
rl.prompt();
} else {
let arr = content.split(/\s+/);
for (let i = 0, length = arr.length; i < length; i++) {
let str = arr[i].split('->');
if (wenG[str[0]] == undefined) {
wenG[str[0]] = new Array();
p[str[0]] = new Object();
wenG[str[0]].push(str[1]);
} else {
wenG[str[0]].push(str[1]);
}
}
console.log(wenG);
console.log(" ");
anylize(p, wenG);
console.log(p);
rl.prompt();
}
})
} else {
console.log(`文件不存在${fileName}`);
rl.prompt();
}
})
} else if (command[0] == 'start') {
if (!wenG) {
console.log('未选择文法文件');
rl.prompt();
}
let left = "#E".split("");
let middle = command[1].split("");
let index = 1;
output(index, p, left, middle);
rl.prompt();
}
rl.prompt();
}).on('close', () => {
console.log('再见!');
process.exit(0);
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
//核心算法 anylize.js 递归生成First和Follow集
function diguiFirst(prop, i, params, result, grammer) {
let str;
if (grammer[result[0]] == undefined) {
params[prop][result[0]] = grammer[prop][i];
return;
} else {
for (let j = 0; j < grammer[result[0]].length; j++) {
let a = result;
a = grammer[result[0]][j] + result.substring(1);
diguiFirst(prop, i, params, a, grammer);
}
}
return;
}

function diguiFollow(prop, result, params, grammer, arr = new Array()) {
result = result.replace('$', '');
let index = result.indexOf(prop);
if (index != result.length - 1) {//递归结束条件
if (grammer[result[index + 1]] == undefined) {
params[prop][result[index + 1]] = '$';
return;
}
}
for (let i = 0; i < result.length; i++) {
if ((grammer[result[i]] != undefined) && (!arr.includes(result[i])) && (result[i] != prop)) {
arr.push(result[i]);
let str;
for (let j = 0; j < grammer[result[i]].length; j++) {
str = result.substring(0, i) + grammer[result[i]][j] + result.substring(i + 1);
diguiFollow(prop, str, params, grammer, arr);
}
}
}
return;
}

function Follow(prop, params, grammer) {
for (let i = 0; i < grammer[prop].length; i++) {
if (grammer[prop][i] == '$') {
return;
}
diguiFollow(prop, grammer[prop][i], params, grammer); //遍历所有项
}
}



function anylize(params, grammer) {
for (let prop in grammer) {
for (let i = 0; i < grammer[prop].length; i++) {
let str = '';
if (grammer[prop][i] != '$') {
str += 'first ' + grammer[prop][i];
console.log(str);
diguiFirst(prop, i, params, grammer[prop][i], grammer);
} else {
str += 'follow ' + prop;
console.log(str);
params[prop]['#'] = '$';
Follow(prop, params, grammer);
}
}
}
}


module.exports = {
anylize
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//输出 output.js 输出文件

function output(index, params, left, middle) {
if (middle.length == 0) {
return ;
}
let str;
if (left[left.length - 1] == middle[0]) {
str = middle[0] + " 匹配";
console.log(`${index++}\t${left.join("")}\t\t${middle.join("")}\t\t${str}`);
left.pop();
middle.shift();
} else {
str = params[left[left.length - 1]][middle[0]];
console.log(`${index++}\t${left.join("")}\t\t${middle.join("")}\t\t${left[left.length - 1]}->${str}`);
if (str == "$") {
str = "";
left.pop();//弹出最后一个值
} else {
str = str.split("");
left.pop();
for (let i = str.length - 1; i >= 0; i--) {
left.push(str[i]);
}
}
}
output(index, params, left, middle);
}

module.exports.output = output;
越来越多的平台(微信公众平台,新浪微博,简书,百度打赏等)支持打赏功能,付费阅读时代越来越近,特此增加了打赏功能,支持微信打赏和支付宝打赏。坚持原创技术分享,您的支持将鼓励我继续创作!