我目前正在研究一个小型的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;来完成这项工作。关键字作为我捕获的一部分。
我非常感谢您解决我的问题的任何见解!如果我没有清楚地解释我的问题,请告诉我,我会尽力澄清! 非常感谢提前!!
我也很乐意接受有关如何清理语法的任何建议。我现在对这个东西还很新,觉得我的东西现在变得一团糟:)。
答案 0 :(得分:1)
匹配字符串很容易,但不包括end
的第一个实例:
([^e]|e[^n]|en[^d])*
(它甚至不需要非贪婪的重复。)
但是,这不是你想要的。包含的JavaScript可能包括:
名称恰好包含字符end
(tendency
)
评论(/* Take the values up to the end of the line */
)
字符串(if (word == "end")
)
确实是单词end
本身,它不是js中的保留字。
真的,唯一干净的解决方案是能够lex javascript。幸运的是,你不必精确地做到这一点,因为你不是在解释它,但即便如此,这也是一点工作。与其他类似语言一样,javascript lexing中最烦人的部分是识别 / 是正则表达式的开头,何时只是除法;做到这一点需要大多数javascript解析器,特别是因为它还与分号规则交互。
为了处理包含的javascript实际上可能使用名为end
的变量的事实,我有几个选择,据我所知:
记录end
是保留字的事实。
只有当end
出现在括号之外和声明可能开始的地方时才会识别end
(如果最终构建足够的JS解析器以正确识别正则表达式,则不会太难)
只有当{{1}}出现在一条线上时才会识别它。
这最后的选择会真正简化你的问题,所以你可能想要考虑一下,虽然它不是很优雅。