我正在尝试在JavaScript中为BBCode构建一个解析器,它允许我将带有BBCode的字符串转换为带有HTML的字符串。我脑子里想知道它是如何工作的,我甚至已经构建了两个解析器步骤。
现在,解析器的整个过程可以描述为
除了第四步,我总体上知道如何在脑海中完成所有这些工作。
当我到达第四步时,我在构建AST时遇到了问题。问题是如何递归地构建这棵树。我过去以递归方式构建了二维数组,但是变深度树超出了我的能力范围。
在我脑海中,我认为树应该是这样的:
// Hello, [b]World![/b]
{
"text": "Hello, ",
"tag": {
"type": "b",
"text": "World!"
}
}
但是当试图生成这个时,我有一个问题,递归地构建它。
更复杂的例子如下:
// [c=red]Hello Tom, [/c][b][c=green]how are you?[/c][/b]
{
"tag": {
type: "c",
"parameters": "red",
"text": "Hello Tom, "
"tag": {
"type": "b",
"tag": {
"type": "c",
"parameters": "green",
"text": "how are you?"
}
}
}
}
我遇到的主要问题是在建筑物的同时保持我的位置,而不会意外地覆盖整棵树。
目前我使用的代码是:
var bbcode = {};
bbcode._tokens = {
'TO_DEL': '[',
'TC_DEL': ']',
'TE_DEL': '/',
'EQ_DEL': '='
};
bbcode._tags = ['c', 'b'];
bbcode.parse = function(bbcode) {
var tokens = this._tokenize(bbcode);
tokens = this._lex(tokens);
var ast = this._parse(tokens);
console.log(JSON.stringify(ast, null, 4));
//return tokens;
};
bbcode._isToken = function(token) {
for (var k in this._tokens) {
if (this._tokens[k] === token) {
return true;
}
}
return false;
};
bbcode._isTag = function(token) {
return (this._tags.indexOf(token) > -1) ? true : false;
};
bbcode._getType = function(token) {
for (var k in this._tokens) {
if (this._tokens[k] === token) {
return k;
}
}
};
bbcode._next = function(tokens, curr) {
return tokens[curr + 1][0];
};
bbcode._previous = function(tokens, curr) {
return tokens[curr - 1][0];
};
bbcode._tokenize = function(bbcode) {
var tree = [];
var temp = '';
for (var i = 0; i < bbcode.length; i++) {
if (this._isToken(bbcode[i])) {
if (temp.length > 0) {
tree.push(temp);
temp = '';
}
tree.push(bbcode[i]);
} else {
temp += bbcode[i];
}
}
return tree;
};
bbcode._lex = function(tokens) {
var tree = [];
for (var i = 0; i < tokens.length; i++) {
if (this._isToken(tokens[i])) {
tree.push([this._getType(tokens[i]), tokens[i]]);
} else if (this._isTag(tokens[i])) {
tree.push(['BB_TAG', tokens[i]]);
} else {
tree.push(['BB_STRING', tokens[i]]);
}
}
return tree;
};
/*****************************************************************************/
/* I need help with the block below */
/*****************************************************************************/
bbcode._parse = function(tokens) {
var tree = {};
for (var i = 0; i < tokens.length; i++) {
if (tokens[i][0] === 'BB_STRING') {
if (tree['text']) {
tree['text'] += tokens[i][1];
} else {
tree['text'] = tokens[i][1];
}
} else if (tokens[i][0] === 'TO_DEL') {
if (this._next(tokens, i) === 'BB_TAG') {
tree['tag'] = {};
} else {
if (tree['text']) {
tree['text'] += tokens[i][1];
} else {
tree['text'] = tokens[i][1];
}
}
}
}
return tree;
};
/*****************************************************************************/