better recursion?

This commit is contained in:
Christopher Jeffrey 2011-08-13 16:53:15 -05:00
parent 2f6396e217
commit a2cccfaf1d

View File

@ -32,6 +32,119 @@ var links;
* Lexer
*/
var lex_ = function lex(str, tokens, line) {
var i
, key
, rule;
while (str.length)
for (i = 0; i < len; i++) {
key = keys[i];
rule = rules[key];
cap = rule.exec(str);
if (!cap) continue;
str = str.substring(cap[0].length);
switch (key) {
case 'newline':
line++;
break;
case 'hr':
tokens.push({
type: 'hr',
line: line
});
break;
case 'lheading':
tokens.push({
type: 'heading',
depth: cap[2] === '=' ? 1 : 2,
text: cap[1],
line: line
});
break;
case 'heading':
tokens.push({
type: 'heading',
depth: cap[1].length,
text: cap[2],
line: line
});
break;
case 'block':
cap = cap[0].replace(/^ {4}/gm, '');
tokens.push({
type: 'block',
text: cap,
line: line
});
break;
case 'list':
tokens.push({
type: 'list_start',
ordered: isFinite(cap[2]),
line: line
});
// get each top-level
// item in the list
cap = cap[0].match(
/^( *)(\*|\+|-|\d+\.)[^\n]+(?:\n(?:\1 )+[^\n]+)*/gm
);
cap.forEach(function(item) {
// remove the list items sigil
// so its seen as the next token
item = item.replace(/^ *(\*|\+|-|\d+\.) */, '');
// outdent whatever the
// list item contains, hacky
var len = /\n( +)/.exec(item);
if (len) {
len = len[1].length;
item = item.replace(
new RegExp('^ {' + len + '}', 'gm'),
''
);
}
tokens.push({
type: 'list_item_start',
line: line
});
lex(item, tokens, line);
tokens.push({
type: 'list_item_end',
line: line
});
});
tokens.push({
type: 'list_end',
line: line
});
break;
case 'html':
case 'text':
tokens.push({
type: key,
text: cap[0],
line: line
});
break;
case 'blockquote':
tokens.push({
type: 'blockquote_start',
line: line
});
cap = cap[0].replace(/^ *>/gm, '');
lex(cap, tokens, line);
tokens.push({
type: 'blockquote_end',
line: line
});
break;
}
break;
}
};
var lex = function(str) {
var tokens = []
, line = 0;
@ -57,118 +170,7 @@ var lex = function(str) {
return '';
});
(function lex(str) {
var i
, key
, rule;
while (str.length)
for (i = 0; i < len; i++) {
key = keys[i];
rule = rules[key];
cap = rule.exec(str);
if (!cap) continue;
str = str.substring(cap[0].length);
switch (key) {
case 'newline':
line++;
break;
case 'hr':
tokens.push({
type: 'hr',
line: line
});
break;
case 'lheading':
tokens.push({
type: 'heading',
depth: cap[2] === '=' ? 1 : 2,
text: cap[1],
line: line
});
break;
case 'heading':
tokens.push({
type: 'heading',
depth: cap[1].length,
text: cap[2],
line: line
});
break;
case 'block':
cap = cap[0].replace(/^ {4}/gm, '');
tokens.push({
type: 'block',
text: cap,
line: line
});
break;
case 'list':
tokens.push({
type: 'list_start',
ordered: isFinite(cap[2]),
line: line
});
// get each top-level
// item in the list
cap = cap[0].match(
/^( *)(\*|\+|-|\d+\.)[^\n]+(?:\n(?:\1 )+[^\n]+)*/gm
);
cap.forEach(function(item) {
// remove the list items sigil
// so its seen as the next token
item = item.replace(/^ *(\*|\+|-|\d+\.) */, '');
// outdent whatever the
// list item contains, hacky
var len = /\n( +)/.exec(item);
if (len) {
len = len[1].length;
item = item.replace(
new RegExp('^ {' + len + '}', 'gm'),
''
);
}
tokens.push({
type: 'list_item_start',
line: line
});
lex(item, tokens);
tokens.push({
type: 'list_item_end',
line: line
});
});
tokens.push({
type: 'list_end',
line: line
});
break;
case 'html':
case 'text':
tokens.push({
type: key,
text: cap[0],
line: line
});
break;
case 'blockquote':
tokens.push({
type: 'blockquote_start',
line: line
});
cap = cap[0].replace(/^ *>/gm, '');
lex(cap, tokens);
tokens.push({
type: 'blockquote_end',
line: line
});
break;
}
break;
}
})(str);
lex_(str, tokens, line);
return tokens;
};