mirror of
https://github.com/AdaCore/ace.git
synced 2026-02-12 13:03:02 -08:00
197 lines
5.8 KiB
JavaScript
197 lines
5.8 KiB
JavaScript
var fs = require("fs");
|
|
var util = require("util");
|
|
var lib = require("./lib");
|
|
var parseLanguage = lib.parsePlist;
|
|
|
|
|
|
function logDebug(string, obj) {
|
|
console.log(string, obj);
|
|
}
|
|
|
|
|
|
// tmLanguage processor
|
|
|
|
// for tracking token states
|
|
var states = {start: []};
|
|
var stateName = "start";
|
|
|
|
function processRules(rules){
|
|
if (rules.patterns)
|
|
states.start = processPatterns(rules.patterns);
|
|
if (rules.repository)
|
|
processRepository(rules.repository);
|
|
return states;
|
|
}
|
|
function processRepository(r) {
|
|
for (var key in r) {
|
|
var p = r[key];
|
|
if (p.begin)
|
|
var stateObj = [processPattern(r[key])];
|
|
else if (p.patterns && !p.repository)
|
|
var stateObj = processPatterns(p.patterns);
|
|
else
|
|
var stateObj = [processPattern(r[key])];
|
|
|
|
if (stateObj)
|
|
states["#" + key] = stateObj;
|
|
}
|
|
}
|
|
function processPatterns(pl) {
|
|
return pl.map(processPattern);
|
|
}
|
|
function processPattern(p) {
|
|
|
|
if (p.end == "(?!\\G)" && p.patterns && p.patterns.length == 1) {
|
|
var rule = processPattern(p.patterns[0]);
|
|
}
|
|
else if (p.begin && p.end) {
|
|
var rule = simpleRule(p.begin, p.name, p.beginCaptures || p.captures)
|
|
|
|
var next = processPatterns(p.patterns || []);
|
|
var endRule = simpleRule(p.end, p.name, p.endCaptures || p.captures);
|
|
endRule.next = "pop";
|
|
next.push(endRule);
|
|
|
|
if (p.name || p.contentName)
|
|
next.push({defaultToken: p.name || p.contentName});
|
|
|
|
rule.push = next;
|
|
}
|
|
else if (p.match) {
|
|
var rule = simpleRule(p.match, p.name, p.captures)
|
|
}
|
|
else if (p.include) {
|
|
var rule = {include: p.include};
|
|
}
|
|
|
|
if (p.comment)
|
|
rule.comment = (rule.comment || "") + p.comment;
|
|
|
|
if (p.repository)
|
|
processRepository(p.repository);
|
|
return rule;
|
|
}
|
|
function simpleRule(regex, name, captures) {
|
|
name = name || "text";
|
|
var rule = {};
|
|
|
|
var origRegex = regex
|
|
regex = transformRegExp(regex, rule);
|
|
if (captures) {
|
|
var tokenArray = [];
|
|
Object.keys(captures).forEach(function(x){
|
|
tokenArray[x] = captures[x] && captures[x].name;
|
|
});
|
|
if (tokenArray.length == 1) {
|
|
name = tokenArray[0];
|
|
} else {
|
|
for (var i = 0; i < tokenArray.length; i++)
|
|
if (!tokenArray[i])
|
|
tokenArray[i] = name;
|
|
name = tokenArray;
|
|
rule.todo = "fix grouping";
|
|
}
|
|
}
|
|
|
|
try {new RegExp(regex);} catch(e) {
|
|
rule.TODO = "FIXME: regexp doesn't have js equivalent";
|
|
rule.originalRegex = origRegex
|
|
}
|
|
rule.token = name;
|
|
rule.regex = regex;
|
|
return rule;
|
|
}
|
|
|
|
|
|
// regex transformation
|
|
|
|
function removeXFlag(str) {
|
|
if (str && str.slice(0,4) == "(?x)") {
|
|
str = str.replace(/\\.|\[([^\]\\]|\\.)*?\]|\s+|(?:#[^\n]*)/g, function(s) {
|
|
if (s[0] == "[")
|
|
return s;
|
|
if (s[0] == "\\")
|
|
return /[#\s]/.test(s[1]) ? s[1] : s;
|
|
return "";
|
|
}).substr(4);
|
|
}
|
|
return str;
|
|
}
|
|
|
|
function transformRegExp(str, rule) {
|
|
str = removeXFlag(str);
|
|
//str = str.replace(/\\n\$|\$\\n/g, '$');
|
|
str = str.replace(/\\n(?!\?).?/g, '$'); // replace newlines by $ except if its postfixed by ?
|
|
if (/\(\?[i]\:|\(?\w*i\w*\)/g.test(str)) {
|
|
str = str.replace(/\(\?[ims\-]\:/g, "(?:"); // checkForInvariantRegex
|
|
str = str.replace(/\(\?[imsx\-]\)/g, "");
|
|
rule && (rule.caseInsensitive = true);
|
|
}
|
|
str = str.replace(/(\\[xu]){([a-fA-F\d]+)}/g, '$1$2');
|
|
return str;
|
|
}
|
|
|
|
//
|
|
function extractPatterns(tmRules) {
|
|
var patterns = processRules(tmRules);
|
|
return lib.restoreJSONComments(lib.formatJSON(patterns, " "));
|
|
|
|
}
|
|
|
|
|
|
|
|
// cli stuff
|
|
var modeTemplate = fs.readFileSync(__dirname + "/mode.tmpl.js", "utf8");
|
|
var modeHighlightTemplate = fs.readFileSync(__dirname + "/mode_highlight_rules.tmpl.js", "utf8");
|
|
|
|
function convertLanguageFile(name) {
|
|
var path = /^(\/|\w:)/.test(name) ? name : process.cwd() + "/" + name
|
|
var tmLanguage = fs.readFileSync(path, "utf8");
|
|
parseLanguage(tmLanguage, function(language) {
|
|
var languageHighlightFilename = language.name.replace(/[-_]/g, "").toLowerCase();
|
|
var languageNameSanitized = language.name.replace(/-/g, "");
|
|
|
|
var languageHighlightFile = __dirname + "/../lib/ace/mode/" + languageHighlightFilename + "_highlight_rules.js";
|
|
var languageModeFile = __dirname + "/../lib/ace/mode/" + languageHighlightFilename + ".js";
|
|
|
|
console.log("Converting " + name + " to " + languageHighlightFile);
|
|
|
|
if (devMode) {
|
|
console.log(util.inspect(language.patterns, false, 4));
|
|
console.log(util.inspect(language.repository, false, 4));
|
|
}
|
|
|
|
var languageMode = lib.fillTemplate(modeTemplate, {
|
|
language: languageNameSanitized,
|
|
languageHighlightFilename: languageHighlightFilename
|
|
});
|
|
|
|
var patterns = extractPatterns(language);
|
|
|
|
var languageHighlightRules = lib.fillTemplate(modeHighlightTemplate, {
|
|
language: languageNameSanitized,
|
|
languageTokens: patterns.trim(),
|
|
uuid: language.uuid,
|
|
name: name
|
|
});
|
|
|
|
if (devMode) {
|
|
console.log(languageMode);
|
|
console.log(languageHighlightRules);
|
|
console.log("Not writing, 'cause we're in dev mode, baby.");
|
|
}
|
|
else {
|
|
fs.writeFileSync(languageHighlightFile, languageHighlightRules);
|
|
fs.writeFileSync(languageModeFile, languageMode);
|
|
}
|
|
});
|
|
}
|
|
|
|
var args = process.argv.splice(2);
|
|
var tmLanguageFile = args[0];
|
|
var devMode = args[1];
|
|
if (tmLanguageFile === undefined) {
|
|
console.error("Please pass in a language file via the command line.");
|
|
process.exit(1);
|
|
}
|
|
convertLanguageFile(tmLanguageFile); |