Multi line tokenizer
This commit is contained in:
parent
2e70bf46fa
commit
fac85b2b27
4 changed files with 126 additions and 15 deletions
|
|
@ -71,7 +71,11 @@ BackgroundTokenizer.prototype.getTokens = function(row)
|
||||||
if (this.lines[row]) {
|
if (this.lines[row]) {
|
||||||
return this.lines[row].tokens;
|
return this.lines[row].tokens;
|
||||||
} else {
|
} else {
|
||||||
return getLineTokens(this.textLines[row] || "", "start").tokens;
|
var state = "start";
|
||||||
|
if (row > 0 && this.lines[row-1]) {
|
||||||
|
state = this.lines[row-1].state;
|
||||||
|
}
|
||||||
|
return getLineTokens(this.textLines[row] || "", state).tokens;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -101,14 +105,98 @@ var keywords = {
|
||||||
"with" : 1
|
"with" : 1
|
||||||
};
|
};
|
||||||
|
|
||||||
getLineTokens = function(line, state)
|
getLineTokens = function(line, startState)
|
||||||
{
|
{
|
||||||
var tokens = [];
|
var rules = {
|
||||||
|
start :
|
||||||
|
[
|
||||||
|
{
|
||||||
|
token: "comment",
|
||||||
|
regex: "\\/\\/.*$"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
token: "comment", // multi line comment in one line
|
||||||
|
regex: "\\/\\*.*?\\*\\/"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
token: "comment", // multi line comment in several lines
|
||||||
|
regex: "\\/\\*.*$",
|
||||||
|
next: "comment"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
token: "string", // single line
|
||||||
|
regex: '["][^"]*["]'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
token: "string", // single line
|
||||||
|
regex: "['][^']*[']"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
token: "number", // hex
|
||||||
|
regex: "0[xX][0-9a-fA-F]+\\b"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
token: "number", // float
|
||||||
|
regex: "[+-]?\\d+(?:(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)?\\b"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
token: function(value)
|
||||||
|
{
|
||||||
|
if (keywords[value]) {
|
||||||
|
return "keyword";
|
||||||
|
} else {
|
||||||
|
return "identifier"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
regex: "[a-zA-Z_][a-zA-Z0-9_]*\\b"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
token: function(value) {
|
||||||
|
//return parens[value];
|
||||||
|
return "text";
|
||||||
|
},
|
||||||
|
regex: "[\\[\\]\\(\\)\\{\\}]"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
token: "text",
|
||||||
|
regex: "\\s+"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"comment":
|
||||||
|
[
|
||||||
|
{
|
||||||
|
token: "comment", // closing comment
|
||||||
|
regex: ".*?\\*\\/",
|
||||||
|
next: "start"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
token: "comment", // comment spanning whole line
|
||||||
|
regex: ".+"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
var re = /(?:(\s+)|("[^"]*")|('[^']*')|([\[\]\(\)\{\}])|([a-zA-Z_][a-zA-Z0-9_]*)|(\/\/.*)|(.))/g
|
var regExps = {};
|
||||||
re.lastIndex = 0;
|
for (var key in rules)
|
||||||
|
{
|
||||||
|
var state = rules[key];
|
||||||
|
var ruleRegExps = [];
|
||||||
|
|
||||||
|
for (var i=0; i < state.length; i++) {
|
||||||
|
ruleRegExps.push(state[i].regex);
|
||||||
|
};
|
||||||
|
|
||||||
|
regExps[key] = new RegExp("(?:(" + ruleRegExps.join(")|(") + ")|(.))", "g");
|
||||||
|
}
|
||||||
|
|
||||||
var match;
|
|
||||||
|
var currentState = startState;
|
||||||
|
var state = rules[currentState];
|
||||||
|
var re = regExps[currentState];
|
||||||
|
re.lastIndex = 0;
|
||||||
|
|
||||||
|
var match, tokens = [];
|
||||||
|
|
||||||
while (match = re.exec(line))
|
while (match = re.exec(line))
|
||||||
{
|
{
|
||||||
var token = {
|
var token = {
|
||||||
|
|
@ -116,19 +204,38 @@ getLineTokens = function(line, state)
|
||||||
value: match[0]
|
value: match[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
if (match[2] || match[3]) {
|
//console.log(match);
|
||||||
token.type = "string";
|
|
||||||
} else if (match[5] && keywords[match[5]]) {
|
for (var i=0; i < state.length; i++)
|
||||||
token.type = "keyword";
|
{
|
||||||
} else if (match[6]) {
|
if (match[i+1])
|
||||||
token.type = "comment";
|
{
|
||||||
}
|
if (typeof state[i].token == "function") {
|
||||||
|
token.type = state[i].token(match[0]);
|
||||||
|
} else {
|
||||||
|
token.type = state[i].token;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state[i].next && state[i].next !== currentState)
|
||||||
|
{
|
||||||
|
currentState = state[i].next;
|
||||||
|
var state = rules[currentState];
|
||||||
|
var lastIndex = re.lastIndex;
|
||||||
|
|
||||||
|
var re = regExps[currentState];
|
||||||
|
re.lastIndex = lastIndex;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
tokens.push(token);
|
tokens.push(token);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//console.log(tokens, currentState)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
tokens: tokens,
|
tokens: tokens,
|
||||||
state: "start"
|
state: currentState
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
@ -158,7 +158,6 @@ function Editor(doc, renderer)
|
||||||
},
|
},
|
||||||
|
|
||||||
onTokenizerUpdate : function(startRow, endRow) {
|
onTokenizerUpdate : function(startRow, endRow) {
|
||||||
console.log("token update", startRow, endRow);
|
|
||||||
this.renderer.updateLines(startRow, endRow);
|
this.renderer.updateLines(startRow, endRow);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,10 @@
|
||||||
color: rgb(0, 102, 255);
|
color: rgb(0, 102, 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.line .number {
|
||||||
|
color: rgb(0, 0, 205);
|
||||||
|
}
|
||||||
|
|
||||||
.marker-layer .selection {
|
.marker-layer .selection {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
background: rgba(77, 151, 255, 0.33);
|
background: rgba(77, 151, 255, 0.33);
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ button.onclick = function()
|
||||||
{
|
{
|
||||||
var onComplete = function() {
|
var onComplete = function() {
|
||||||
console.log("complete");
|
console.log("complete");
|
||||||
|
console.log(tokenizer.lines);
|
||||||
};
|
};
|
||||||
|
|
||||||
var onUpdate = function(firstLine, lastLine) {
|
var onUpdate = function(firstLine, lastLine) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue