Доступ к поддереву регулярного выражения в 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], кажется, не правильный путь.
Спасибо за любую помощь.
2 ответа
Вероятно, проще всего сделать, если вам не нужно определять списки так, как вы делали выше, с отдельной головой и хвостом, - это использовать встроенную в Rascal конструкцию с разделенным списком, например, так:
start syntax CharList = {CHAR ","}+ chars ';';
(Если вам нужна отдельная голова и хвост, см. Ответ Юргена ниже. Вы можете использовать эту же запись там же.)
Это определяет список из 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] не работает, хотя это может показаться логичным: здесь возвращается результат мета-представления вместо фактического первого элемента списка, но мы можем перебрать элементы списка и выбрать только первый:
if (CHAR e <- v) println(e);
b
ok