在多字符令牌上切换到孤岛模式
Switching to island mode on multi-character token
我正在研究一种基本上是孤岛语法的语法。
假设 "island" 是大括号之间的所有内容,"sea" 是不是所有内容。像这样:
{(岛屿内容)}
那么这个简单的语法就可以工作了:
IslandStart
:
'{' -> pushMode(Island)
;
Fluff
:
~[\{\}]+
;
....
但是我很难想出一个类似的解决方案来解决我想要为我的 "island" 块打开复杂(多字符)的情况,如下所示:
{#(岛屿内容)}
在这种情况下,我不知道如何为 "Fluff" 制定规则(除了我的开场序列之外的所有内容)。
IslandStart
:
'{#' -> pushMode(Island)
;
Fluff
:
~[\{\}]+ /* Should now include opening braces as well
if they are not immaediately followed by # sign */
;
如何让它发挥作用?
编辑:GRosenberg 提出了一个解决方案,但我得到了很多令牌(每个字符一个)。这是演示此行为的示例:
我的词法分析器语法:
lexer grammar Demolex;
IslandStart
:
'{$' -> pushMode(Island)
;
Fluff
:
'{' ~'$' .* // any 2+ char seq that starts with '{', but not '{#'
| '{' '$$' .* // starts with hypothetical not IslandStart marker
| '{' // just the 1 char
| .*? ~'{' // minimum sequence that ends before an '{'
;
mode Island;
IslandEnd
:
'}' -> popMode
;
最简单的解析器语法:
grammar Demo;
options { tokenVocab = Demolex; }
template
:
Fluff+
;
当我在 Eclipse 的 antlr4 插件中调试它时,这会从输入 "somanytokens" 生成一个包含大量标记的树:
不太可能是插件问题。我可以很容易地想出一个令牌定义,它会在树中产生一个大胖令牌。
实际上,即使是最简单的语法形式也会给出这样的结果:
grammar Demo2;
template4
:
Fluff+
;
Fluff
:
.*? ~'{' // minimum sequence that ends before an '{'
;
只需要指定序列差的补码即可:
IslandStart : '{#' -> pushMode(Island) ;
Fluff : '{' ~'#' .* // any 2+ char seq that starts with '{', but not '{#'
| '{' '##' .* // starts with hypothetical not IslandStart marker
| '{' // just the 1 char
| .*? ~'{' // minimum sequence that ends before an '{'
;
当 Fluff alt2 是相对于 IslandStart 的较长匹配时,它会起作用。 Fluff alt3 仅在 IslandStart 和 Fluff alt1 不匹配以“{”开头的字符序列时才起作用。 Fluff alt4 是包含“{”之前但不包括“{”的内容的包罗万象,允许词法分析器考虑在“{”上对齐的序列。
更新
让它成为一个更合理完整的示例语法
parser grammar TestParser;
options{
tokenVocab=TestLexer;
}
template : ( Fluff | Stuff )+ EOF ;
和
lexer grammar TestLexer;
IslandStart : '{' '$' -> pushMode(Island),more ;
Fluff : '{' ~'$' ~'{'*? '}' // any 2+ char seq that starts with '{', but not '{$'
| '{' '$' '$' ~'{'*? '}' // or starts with hypothetical not IslandStart marker
| '{' '}' // just the empty pair
| ~'{'+ // minimum sequence that ends before an '{'
;
mode Island;
Stuff : '}' -> popMode ;
Char : . -> more ;
输入 so{$Island}many{}tokens{$$notIsland}and{inner}end
令牌转储:
Fluff: [@0,0:1='so',<1>,1:0]
Stuff: [@1,2:10='{$Island}',<2>,1:2]
Fluff: [@2,11:14='many',<1>,1:11]
Fluff: [@3,15:16='{}',<1>,1:15]
Fluff: [@4,17:22='tokens',<1>,1:17]
Fluff: [@5,23:35='{$$notIsland}',<1>,1:23]
Fluff: [@6,36:38='and',<1>,1:36]
Fluff: [@7,39:45='{inner}',<1>,1:39]
Fluff: [@8,46:48='end',<1>,1:46]
解析树:
(template so {$Island} many {} tokens {$$notIsland} and {inner} end <EOF>)
词法分析器规则的操作保持不变。进行了更改以适应正确的双亲匹配终端。 Alt4,作为简化,按最初的预期工作。不完全确定为什么一开始对 Antlr 来说是个问题,但无论如何越简单越好。
我正在研究一种基本上是孤岛语法的语法。
假设 "island" 是大括号之间的所有内容,"sea" 是不是所有内容。像这样:
{(岛屿内容)}
那么这个简单的语法就可以工作了:
IslandStart
:
'{' -> pushMode(Island)
;
Fluff
:
~[\{\}]+
;
....
但是我很难想出一个类似的解决方案来解决我想要为我的 "island" 块打开复杂(多字符)的情况,如下所示:
{#(岛屿内容)}
在这种情况下,我不知道如何为 "Fluff" 制定规则(除了我的开场序列之外的所有内容)。
IslandStart
:
'{#' -> pushMode(Island)
;
Fluff
:
~[\{\}]+ /* Should now include opening braces as well
if they are not immaediately followed by # sign */
;
如何让它发挥作用?
编辑:GRosenberg 提出了一个解决方案,但我得到了很多令牌(每个字符一个)。这是演示此行为的示例:
我的词法分析器语法:
lexer grammar Demolex;
IslandStart
:
'{$' -> pushMode(Island)
;
Fluff
:
'{' ~'$' .* // any 2+ char seq that starts with '{', but not '{#'
| '{' '$$' .* // starts with hypothetical not IslandStart marker
| '{' // just the 1 char
| .*? ~'{' // minimum sequence that ends before an '{'
;
mode Island;
IslandEnd
:
'}' -> popMode
;
最简单的解析器语法:
grammar Demo;
options { tokenVocab = Demolex; }
template
:
Fluff+
;
当我在 Eclipse 的 antlr4 插件中调试它时,这会从输入 "somanytokens" 生成一个包含大量标记的树:
不太可能是插件问题。我可以很容易地想出一个令牌定义,它会在树中产生一个大胖令牌。
实际上,即使是最简单的语法形式也会给出这样的结果:
grammar Demo2;
template4
:
Fluff+
;
Fluff
:
.*? ~'{' // minimum sequence that ends before an '{'
;
只需要指定序列差的补码即可:
IslandStart : '{#' -> pushMode(Island) ;
Fluff : '{' ~'#' .* // any 2+ char seq that starts with '{', but not '{#'
| '{' '##' .* // starts with hypothetical not IslandStart marker
| '{' // just the 1 char
| .*? ~'{' // minimum sequence that ends before an '{'
;
当 Fluff alt2 是相对于 IslandStart 的较长匹配时,它会起作用。 Fluff alt3 仅在 IslandStart 和 Fluff alt1 不匹配以“{”开头的字符序列时才起作用。 Fluff alt4 是包含“{”之前但不包括“{”的内容的包罗万象,允许词法分析器考虑在“{”上对齐的序列。
更新
让它成为一个更合理完整的示例语法
parser grammar TestParser;
options{
tokenVocab=TestLexer;
}
template : ( Fluff | Stuff )+ EOF ;
和
lexer grammar TestLexer;
IslandStart : '{' '$' -> pushMode(Island),more ;
Fluff : '{' ~'$' ~'{'*? '}' // any 2+ char seq that starts with '{', but not '{$'
| '{' '$' '$' ~'{'*? '}' // or starts with hypothetical not IslandStart marker
| '{' '}' // just the empty pair
| ~'{'+ // minimum sequence that ends before an '{'
;
mode Island;
Stuff : '}' -> popMode ;
Char : . -> more ;
输入 so{$Island}many{}tokens{$$notIsland}and{inner}end
令牌转储:
Fluff: [@0,0:1='so',<1>,1:0]
Stuff: [@1,2:10='{$Island}',<2>,1:2]
Fluff: [@2,11:14='many',<1>,1:11]
Fluff: [@3,15:16='{}',<1>,1:15]
Fluff: [@4,17:22='tokens',<1>,1:17]
Fluff: [@5,23:35='{$$notIsland}',<1>,1:23]
Fluff: [@6,36:38='and',<1>,1:36]
Fluff: [@7,39:45='{inner}',<1>,1:39]
Fluff: [@8,46:48='end',<1>,1:46]
解析树:
(template so {$Island} many {} tokens {$$notIsland} and {inner} end <EOF>)
词法分析器规则的操作保持不变。进行了更改以适应正确的双亲匹配终端。 Alt4,作为简化,按最初的预期工作。不完全确定为什么一开始对 Antlr 来说是个问题,但无论如何越简单越好。