2010-11-22 6 views
0

Я пишу свой синтаксический ярлык в javascript для удовольствия и вижу пару подходов, но у них обоих есть профи и некоторые довольно серьезные минусы, которые я не могу обойти. Что вы, ребята, думаете об этих подходах, и есть ли лучшие методы, которые мне не хватает?дизайн подсветки синтаксиса

Успенская

код для выделения существует в виде одной строки.

Подходы

  1. код Лечить в это виде строки и использовать регулярные выражения для поиска шаблонов.
    Pros
    Простой для определения и поиска моделей
    Против
    Трудно игнорировать ключевые слова внутри цитаты или комментарии

  2. Разбить строку пробелами и переносами и цикл по массив.
    Pros
    Легко следить за рамки
    Cons
    Трудно уследить пространств и переносами после раскола


EDIT:Лексический анализ
Итак, если я это понимаю, используя Лексический анализ, вы разбиваете строку на токены. Это как-то звучит так же, как подход номер 2? Как вы подходите к сборке токенов в исходную строку?

+7

3. Собственно синтаксический анализ исходного кода на лексемы и правильно относиться к ним. Плюсы: Правильно. Минусы: Жесткий. – 2010-11-22 22:37:22

+1

Ваш # 2, если вы действительно имеете в виду буквально * «... пробелами и разрывами строк ...» *, будет разбиваться в основном на любой из языков с синтаксисом B-производного (C, C++, C#, Java, JavaScript, D, и около десятка других). Рассмотрим `if (x> y) {foo();} else {bar();}`. – 2010-11-22 22:38:42

ответ

1

Примечание: Это использует jQuery. Это может быть хорошо переписано для работы с прямым javascript, если вы хотите.

Я на самом деле написал небольшой плагин для удовольствия, что делает это:

(function($) { 
$.fn.codeBlock = function(blockComment) { 

    // Setup keyword regex 
    var keywords = /(abstract|boolean|break|byte|case|catch|char|class|const|continue|debugger|default|delete|do|double|else|enum|export|extends|final|finally|float|for|function|goto|if|implements|import|in|instanceof|int|interface|long|native|new|package|private|protected|public|return|short|static|super|switch|synchronized|this|throw|throws|transient|try|typeof|var|void|volatile|while|with|true|false|prototype)(?!\w|=)/gi; 

    // Booleans to toggle comment, regex, quote exclusions 
    var comment = false; 
    var quote = false; 
    var regex = false; 

    /* Array used to store values of regular expressions, quotes, etc. 
    so they can be used to ID locations to be skipped durring keyword 
    regexing. 
    */ 
    var locator = new Array(); 
    var locatorIndex = 0; 

    if (blockComment) locator[locatorIndex++] = 0; 

    var text = $(this).html(); 
    var continuation; 
    var numerals = /[0-9]/; 

    var arr = ($(this).html()).split(""); 
    var outhtml = ""; 

    for (key in arr) { 
    // Assign three variables common 'lookup' values for faster aquisition 
    var keyd = key; 
    var val = arr[keyd]; 
    var nVal = arr[keyd - 1]; 
    var pVal = arr[++keyd]; 

    if ((val == "\"" || val == "'") && nVal != "\\") { 
    if (quote == false) { 
    quote = true; 
    outhtml += val; 
    } 
    else { 
    outhtml += val; 
    quote = false; 
    } 
    locator[locatorIndex++] = parseInt(key); 
    } 
    else if (numerals.test(val) && quote == false && blockComment == false && regex == false) { 
    outhtml += '<span class="num">' + val + '</span>'; 
    } 
    else if (val == "/" && nVal != "<") { 
    var keys = key; 
    if (pVal == "/") { 
    comment = true; 
    continuation = key; 
    break; 
    } 
    else if (pVal == "*") { 
    outhtml += "/"; 
    blockComment = true; 
    locator[locatorIndex++] = parseInt(key); 
    } 
    else if (nVal == "*") { 
    outhtml += "/"; 
    blockComment = false; 
    locator[locatorIndex++] = parseInt(key); 
    } 
    else if (pVal == "[" && regex == false) { 
    outhtml += "<span class='res'>/"; 
    regex = true; 
    } 
    else { 
    outhtml += "/"; 
    } 
    } 
    else if (val == "," || val == ";" && regex == true) { 
    outhtml += "</span>" + val; 
    regex = false; 
    } 
    else { 
    outhtml += val; 
    } 
    } 

    if (comment == true) { 
    outhtml = outhtml.replace(keywords, "<span class='res'>$1</span>"); 
    outhtml += '<span class="com">'; 
    outhtml += text.substring(continuation, text.length); 
    outhtml += '</span>'; 
    } 
    else { 
    if ((locator.length % 2) != 0) locator[locator.length] = (text.length - 1); 

    if (locator.length != 0) { 
    text = outhtml; 

    outhtml = text.substring(0, locator[0]).replace(keywords, "<span class=\"res\">$1</span>"); 

    for (var i = 0; i < locator.length;) { 
    qTest = text.substring(locator[i], locator[i] + 1); 
    if (qTest == "'" || qTest == "\"") outhtml += "<span class=\"quo\">"; 
    else outhtml += "<span class=\"com\">"; 

    outhtml += text.substring(locator[i], locator[++i] + 1) + "</span>"; 

    outhtml += text.substring(locator[i] + 1, locator[++i]).replace(keywords, "<span class=\"res\">$1</span>"); 
    } 
    } 
    else { 
    outhtml = outhtml.replace(keywords, "<span class=\"res\">$1</span>"); 
    } 
    } 

    text = outhtml; 
    $(this).html(text); 
    return blockComment; 
} 
})(jQuery); 

Я не буду утверждать, что это наиболее эффективный способ сделать это или лучше, но это действительно работает. Есть еще несколько ошибок, в которых я еще не ID'd (и я знаю, но не получил исправления), но это должно дать вам представление о том, как вы можете может пойти об этом, если вы как.

Предлагаемая нами реализация заключается в создании textarea или что-то в этом роде, и при запуске плагина при нажатии кнопки или что-то в этом отношении (насколько это возможно при тестировании), и, конечно, вы можете установить текст в textarea к некоторому стартовому коду, чтобы убедиться, что он работает (Совет. Вы можете поместить теги между тегом <textarea> и он будет отображаться как текст, а не HTML).

Кроме того, blockComment является логическим, обязательно передайте false, потому что true вызовет кавычки блока. Если вы решили разобрать что-то построчно, как:

<a>code</a> 
<a>some more code</a> 

ли что-то вроде:

blockComment = false; 
$("a").each(function() { 
    blockComment = $(this).codeBlock(blockComment); 
}); 
Смежные вопросы