转义符语法



我想为标记语言创建一个Jison(Bison)语法,该语法允许转义标记分隔符。

这些将是有效的:

I like apples
I like [apples, oranges, pears]
I like [apples, oranges, pears] and [peanut butter, jelly]
I like [apples, oranges, pears] [when they're in season]
I like emoticons :-]

这些例子可能被解释为以下(在JSON表示中):

["I like apples"]
["I like ", ["apples", "oranges", "pears"]]
["I like ", ["apples", "oranges", "pears"], " and ", ["peanut butter", "jelly"]]
["I like ", ["apples", "oranges", "pears"], " [when they're in season]"]
["I like emoticons :-]"]

[],的转义是最低限度的,但允许对任何可打印字符进行转义可能是有意义的,即使转义是不必要的。

如果不支持转义不可打印的字符,那就太好了。也就是说,一行末尾的是非法的。正则表达式.可能免费提供,因为它可能不包括换行符,但对于其他不可打印的字符也应该如此。

很难在谷歌上搜索到这一点,因为它与Bison定义中转义文字字符的许多结果混淆在一起,等等。

在Bison定义的语言中,支持转义符的最优雅方式是什么?

编辑

这是我到目前为止所拥有的,可以在Jison上进行测试,但它不起作用(如果有什么作用的话,只返回1),我不希望文本在没有标题的情况下到达-这需要第二次通过。这是可以避免的吗?

/* description: markup */
/* lexical grammar */
%lex
%%
(\.|[^\[])+            return 'TOPTEXT'
(\.|[^\[],])+        return 'TEXT'
-?[0-9]+("."[0-9]+)?b   return 'NUMBER'
".."|"-"                  return '..'
"["                       return '['
"]"                       return ']'
","                       return ','
<<EOF>>                   return 'EOF'
/lex
%start markup
%%
markup
: template EOF
{ return $template; }
;
template
: template TOPTEXT
{ $$ = $template.push($TOPTEXT); }
| template dynamic
{ $$ = $template.push($dynamic); }
| /* empty */
{ $$ = []; }
;
dynamic
: '[' phraselist ']'
{ $$ = $phraselist; }
;
phraselist
: phraselist ',' phrase
{ $$ = $phraselist.push($phrase); }
| /* empty */
{ $$ = []; }
;
phrase
: TEXT
{ $$ = $phrase.push($TEXT); }
| phrase dynamic
{ $$ = $phrase.push($dynamic); }
| /* empty */
{ $$ = []; }
;

我认为您的代码存在不止一个问题。

第一个(这解释了1的输出)是[].push返回列表的新长度,所以您想要的可能是push,然后定义值:

template
: template TOPTEXT
{ $template.push($TOPTEXT); $$ = $template; }
| template dynamic
{ $template.push($dynamic); $$ = $template; }
| /* empty */
{ $$ = []; }
;

另一件事是,你似乎试图让太多的东西同时工作,而没有真正确定你想要它们,或者它们实际上是按照应该的方式工作的。

也许一个更好的策略是从小处着手,一次一条规则,从基础开始。

例如,您可以首先确保lexer适用于每种情况,使用一种只打印出标记的简单语法进行测试:

%lex
%%
(\\|\[|\]|\,|[^,\[]])+   return 'TEXT'
-?[0-9]+("."[0-9]+)?b             return 'NUMBER'
".."|"-"                            return 'RANGE'
"["                                 return '['
"]"                                 return ']'
","                                 return ','
/lex
%start lexertest
%%
lexertest:
token lexertest
| /* empty */
;
token:
TEXT    { console.log("Token TEXT: |" + $TEXT +  "|"); }
|
NUMBER  { console.log("Token NUMBER: |" + $NUMBER +  "|"); }
|
'['     { console.log("Token ["); }
|
']'     { console.log("Token ]"); }
|
','     { console.log("Token ,"); }
|
'RANGE' { console.log("Token RANGE: |" + $1 +  "|"); }
;

注意:在浏览器中运行时,console.log输出将仅在开发人员工具中。您可能会发现,在命令行中使用Jison和这样的脚本(对于Bash)可以更容易地通过多个输入进行测试

然后你完善它,直到你对它感到满意。在你对lexer感到满意之后,你就开始让语法发挥作用,再次一次测试一条规则。保留上面的规则,因为无论何时您想要调试lexer的输出,都可以更改%start规则。

最后,你可能会发现,你从一开始就不需要EOF,毕竟,也许你不需要两个不同的规则来匹配自由文本。

希望能有所帮助。

相关内容

  • 没有找到相关文章

最新更新