Я новичок в лексинге и разоблачении, так что извините, если заголовок недостаточно ясен.Как вернуть несколько токенов с помощью Jison lexer
В принципе, я использую Jison для анализа некоторого текста, и я пытаюсь получить лексер, чтобы понять отступ. Вот этот бит:
(\r\n|\r|\n)+\s* %{
parser.indentCount = parser.indentCount || [0];
var indentation = yytext.replace(/^(\r\n|\r|\n)+/, '').length;
if (indentation > parser.indentCount[0]) {
parser.indentCount.unshift(indentation);
return 'INDENT';
}
var tokens = [];
while (indentation < parser.indentCount[0]) {
tokens.push('DEDENT');
parser.indentCount.shift();
}
if (tokens.length) {
return tokens;
}
if (!indentation.length) {
return 'NEWLINE';
}
%}
До сих пор почти все это работает так, как ожидалось. Одна проблема - это строка, в которой я пытаюсь вернуть массив токенов DEDENT
. Похоже, что Jison просто преобразует этот массив в строку, которая заставляет меня получить ошибку синтаксического анализа, например Expecting ........, got DEDENT,DEDENT
.
Что я могу сделать, чтобы обойти это, вручную надавите на стопку токены DEDENT
. Может быть, с функцией вроде this.pushToken('DEDENT')
или что-то в этом роде. Но документация Jison не так велика, и я мог бы использовать некоторую помощь.
Любые мысли?
EDIT:
Я, кажется, удалось взломать мой путь вокруг этого, посмотрев на сгенерированный код парсера. Вот что, кажется, работает ...
if (tokens.length) {
var args = arguments;
tokens.slice(1).forEach(function() {
lexer.performAction.apply(this, args);
}.bind(this));
return 'DEDENT';
}
Это фокусы лексера в выполнении другого действия, используя один и тот же вход для каждого DEDENT
мы имеем в стеке, таким образом, позволяя добавлять в соответствующем dedents. Тем не менее, это кажется грубым, и я беспокоюсь, что могут возникнуть непредвиденные проблемы.
Мне все равно понравилось бы, если бы у кого-нибудь были идеи по лучшему способу сделать это.