Jison / Flex:尝试捕获两个令牌之间的任何(。*)但有问题

时间:2014-04-30 22:33:01

标签: javascript parsing bison flex-lexer jison

我目前正在研究一个小型的dsl,与rabl不同。我正在努力实施我的一条规则。在我们解决问题之前,我将解释一下我的语法/语法。 在我的小语言中,您可以定义属性,对象/数组块或自定义块(这些都用于构建json对象/数组)。 A"自定义块"可以是包含我的标准表达式(属性,对象/数组块等)或一些JavaScript的。这些表达式都是这样写的 -

-- An object block
object @model

    -- A property node
    property some, key(name="value")

    -- A custom node
    object custom_obj as 
        property some(name="key")
    end

    -- A custom script node
    property full_name as (u)
        // This is JavaScript
        return u.first_name + ' ' + u.last_name;
    end
end 

我遇到的问题是我的自定义脚本节点。我真的很难定义脚本令牌,以便JISON可以正确捕获块内的东西。 在我的词法分析器中,我目前有......

# script_param is basically a regex to match "(some_ident)"
{script_param}  { this.begin('js'); return 'SCRIPT_PARAM'; }
<js>(.|\n|\r)*?"end" %{ 
    this.popState();
    yytext = yytext.substr(0, yyleng - 3).trim();
    return 'SCRIPT';
%}

该SCRIPT令牌基本上匹配(u)到(包括)结束令牌(通常结束块)之后的任何内容。我真的不喜欢这个,因为我通常的块终结符(结束)实际上是脚本令牌的一部分,这对我来说完全是hacky。不幸的是,我无法找到更好的方法来捕捉(..)和结束之间的任何东西。 我尝试编写一个正则表达式来捕获任何以&#34 ;;&#34;结尾的内容,但是当我的dsl代码中有多个脚本节点时会出现问题。我只能通过加入&#34; end&#34;来完成这项工作。关键字作为我捕获的一部分。

以下是我的grammarlexer文件的链接。

我非常感谢您解决我的问题的任何见解!如果我没有清楚地解释我的问题,请告诉我,我会尽力澄清! 非常感谢提前!!

我也很乐意接受有关如何清理语法的任何建议。我现在对这个东西还很新,觉得我的东西现在变得一团糟:)。

1 个答案:

答案 0 :(得分:1)

匹配字符串很容易,但不包括end的第一个实例:

([^e]|e[^n]|en[^d])*

(它甚至不需要非贪婪的重复。)

但是,这不是你想要的。包含的JavaScript可能包括:

  • 名称恰好包含字符endtendency

  • 的变量
  • 评论(/* Take the values up to the end of the line */

  • 字符串(if (word == "end")

  • 确实是单词end本身,它不是js中的保留字。

真的,唯一干净的解决方案是能够lex javascript。幸运的是,你不必精确地做到这一点,因为你不是在解释它,但即便如此,这也是一点工作。与其他类似语言一样,javascript lexing中最烦人的部分是识别 / 是正则表达式的开头,何时只是除法;做到这一点需要大多数javascript解析器,特别是因为它还与分号规则交互。

为了处理包含的javascript实际上可能使用名为end的变量的事实,我有几个选择,据我所知:

  1. 记录end是保留字的事实。

  2. 只有当end出现在括号之外和声明可能开始的地方时才会识别end(如果最终构建足够的JS解析器以正确识别正则表达式,则不会太难)

  3. 只有当{{1}}出现在一条线上时才会识别它。

  4. 这最后的选择会真正简化你的问题,所以你可能想要考虑一下,虽然它不是很优雅。