ace 编辑器语法荧光笔中行尾的退出状态

Exit state at end of line in ace editor syntax highlighter

我正在为 Ace Editor 编写语法荧光笔,但我无法正确地对这种语言的函数调用进行词法分析。函数调用有两种基本形式:

带括号:

function(foo, "bar")

带冒号:

function: foo, "bar"

我可以检测到这两种形式,但是一旦我进入冒号式函数调用的状态,我就很难返回该状态的 out(这会弄乱以下几行)。特别是当函数调用以字符串结尾时会出现这个问题。

下面我做了一个缩小版的荧光笔,只针对这个问题。该结构可能看起来过于复杂,但请记住,这是一个更大的词法分析器的一部分,我认为这保证了复杂性。

您可以在 mode creator 中尝试使用以下代码片段,其中第三行未正确突出显示。

function(a, "bar")
function: a, "bar"
function("bar", a)
function: "bar", a
function("bar")

语法定义如下:

define(function(require, exports, module) {
"use strict";

var oop = require("../lib/oop");
var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;

var MyHighlightRules = function() {

    var functions = [ "function" ];

    this.$rules = {
        "start" : [
            {
                token : 'keyword',
                regex : '\b(?:' + functions.join('|') + ')(?=\s*[:(])',
                push  : [
                    { include : 'function' },
                ]
            }
        ],
        // A function call
        'function' : [
            {
                token : 'text',
                regex : /(?:[:(])/,
                push  : [
                    { include : 'comma_list' },
                ]
            }, {
                token : 'keyword',
                regex : /(?:\)|(?=$))/,
                next  : 'pop'
            }
        ],
        // A series of arguments, separated by commas
        'comma_list' : [
            {
                token : 'text',
                regex : /\s+/,
            }, {
                token : 'string',
                regex : /"/,
                next : 'string',
            }, {
                include : "variable_name"
            }
        ],
        'variable-name' : [
            {
                token : 'keyword',
                regex : /[a-z][a-zA-Z0-9_.]*/,
                // This makes no difference
                next : 'pop'
            },
        ],
        'string': [
            {
                token : 'string.quoted',
                regex : /"/,
                next  : 'pop'
            },
            { defaultToken : 'string.quoted' }
        ],
    };

    this.normalizeRules();
};

oop.inherits(MyHighlightRules, TextHighlightRules);

exports.MyHighlightRules = MyHighlightRules;
});

具体来说:function 中的 /(?:\)|(?=$))/ 似乎只有在前一个状态 不是 字符串时才匹配。不管怎样我怎样才能让它匹配,所以我的词法分析器即使使用冒号式函数调用也存在函数调用?

更令人困惑的是,如果我将正则表达式更改为 /(?:|(?=$))/,它会正确突出显示所有行,即使我不明白为什么。这是怎么回事?

主要问题是在行尾的 ace 只允许一个状态转换 https://github.com/ajaxorg/ace/blob/master/lib/ace/tokenizer.js#L317。所以在行尾匹配 " 并切换到函数状态后,它不会再次调用 regexp 所以 $ 不会匹配任何东西。您可能可以在 github.

上报告此问题

第二个问题是您的代码中 variable_name 变量名拼写错误。

这是您的荧光笔的修改版本,除了 $ 之外,它还使用 ^ 来获得与您想要的类似的突出显示效果。

define(function(require, exports, module) {
"use strict";

var oop = require("../lib/oop");
var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;

var MyHighlightRules = function() {

    var functions = [ "function" ];

    this.$rules = {
        "start" : [
            {
                token : 'keyword',
                regex : '\b(?:' + functions.join('|') + ')(?=\s*[:(])',
                push  : [
                    { include : 'function' },
                ]
            }
        ],
        // A function call
        'function' : [
            {
                token : 'paren',
                regex : /(?:[:(])/,
            },
            {
                token : 'paren',
                regex : /(?:\)|$|^)/,
                next  : 'pop'
            },
            { include : 'commaList' },
        ],
        // A series of arguments, separated by commas
        'commaList' : [
            {
                token : 'text',
                regex : /\s+/,
            }, {
                token : 'string.start',
                regex : /"/,
                push : 'string',
            }, {
                include : "variableName"
            }
        ],
        'variableName' : [
            {
                token : 'variable.parameter',
                regex : /[a-z][a-zA-Z0-9_.]*/
            },
        ],
        'string': [
            {
                token : 'string.end',
                regex : /"/,
                next  : 'pop'
            },
            { defaultToken : 'string.quoted' }
        ],
    };

    this.normalizeRules();
};

oop.inherits(MyHighlightRules, TextHighlightRules);

exports.MyHighlightRules = MyHighlightRules;
});