访问解析树中的正则表达式子树

accessing regexp subtree in parsetree

我有以下 Rascal 模块:

module foo

import IO;
import ParseTree;
extend lang::std::Layout;

lexical CHAR = [ab];
start syntax CharList = CHAR hd (','  CHAR)+ tl ';';

我的问题是如何在解析某些内容后到达 tl 部分的各个元素。例如:

rascal>import foo;
ok

rascal>pt = parse(#start[CharList], "a, b;");
start[CharList]: `a, b;`
Tree: appl(...
rascal>pt.top.tl;
(',' CHAR)+: `, b`
Tree: appl(regular(...

现在如何访问 , b 元素? pt.top.tl[0]好像方法不对

感谢您的帮助。

可能最简单的做法是使用 Rascal 内置的分隔列表结构,例如:

start syntax CharList = {CHAR ","}+ chars ';';

(如果您需要单独的头部和尾部,请参阅下面 Jurgen 的回答。您也可以在那里使用相同的符号。)

这定义了 1 个或多个(因为 +)逗号分隔的 CHAR 的列表。如果您需要 0 个或更多,您可以使用 *。 Rascal 允许您遍历分隔的列表,因此您可以像这样取回字符:

rascal> chars = [c | c <- pt.top.chars ];

对于您示例中的列表,这会返回以下信息:

list[CHAR]: [appl(
    prod(
      lex("CHAR"),
      [\char-class([range(97,98)])],
      {}),
    [char(97)])[
    @loc=|unknown:///|(0,1,<1,0>,<1,1>)
  ],appl(
    prod(
      lex("CHAR"),
      [\char-class([range(97,98)])],
      {}),
    [char(98)])[
    @loc=|unknown:///|(3,1,<1,3>,<1,4>)
  ]]

如果您想更轻松地查看它们或对它们的字符串值执行某些操作,您也可以将它们转换为字符串:

rascal>charsAsStrings = ["<c>" | c <- pt.top.chars ];
list[str]: ["a","b"]

首先可以这样写,这样更简单:

start syntax CharList =  CHAR hd "," {CHAR ","}+ tl ';';

然后:

rascal>t = parse(#start[CharList], "a,b;");
start[CharList]: `a,b;`
rascal>u = t.top;
CharList: `a,b;`
rascal>v = u.tl;
{CHAR  "," }+: `b`

v[0] 被破坏了,虽然这在这里看起来合乎逻辑 returns 元表示的 prod 而不是列表的实际第一个元素,但我们可以迭代列表中的元素select 只有第一个:

if (CHAR e <- v) println(e); 
b
ok