2015-07-19 3 views
0

Я использую Jison для проекта колледжа, и мне нужно сделать switch для каждого распознанного знак, так что я могу представить профессора что-то вроде:Как получить токены в Джисоне?

<identifier, s> 
<operator, => 
<identifier, a> 
<operator, +> 
<identifier, b> 

Любой способ, как получить это сделать без повторяющиеся регулярные выражения вручную? (Я имею в виду, Jison использует регулярное выражение внутренне, но это не мое дело)

То, что я попытался сделать это следующим образом:

var lex = parser.lexer, 
    token; 
lex.setInput('The code to parse'); 
while (!lex.done) { 
    token = lex.next(); 
} 

Но единственным, что я спасаюсь в token этом числе, и когда символ не определен в грамматике, он возвращает символический символ.

Заранее спасибо.

ответ

0

(Внимание: Некоторые из этого ответа был получен путем анализа кода, сгенерированного jison Поскольку интерфейсы не определены, не может выдержать испытание временем.).

parser.lexer.next() не является частью документированной лексере интерфейс, хотя лексический анализатор, созданный jison, как представляется, реализует его. Обратите внимание, что он не создает токен, если потребляемый вход соответствует лексическому правилу, которое не создает токен. (Например, правило, которое игнорирует пробелы.) Лучше использовать документированный интерфейс parser.lexer.lex(), который всегда создает токен.

Строго говоря, parser.lexer.lex() документирована как возвращающая имя терминала, но для повышения эффективности лексические анализаторы, сгенерированные jison возвращает внутренний числовой код для терминала, если jison способен выяснить, какой терминал лексическое правило будет возвращать , Таким образом, у вас есть несколько вариантов, если вы хотите, чтобы отслеживать фактические имена терминалов признаваемых:

  1. Вы можете победить эту оптимизацию, избегая использование формы return <string>. Например, если вы измените лексические правила:

    [A-Za-z][A-Za-z0-9] { return 'IDENTIFIER`; } 
    

    к

    [A-Za-z][A-Za-z0-9] { return '' + 'IDENTIFIER`; } 
    

    то генерируется лексический анализатор возвращает строку 'IDENTIFIER', а не какой-то числовой код.

  2. В качестве альтернативы вы можете использовать parser.terminals_, который в соответствии с комментарием в верхней части сгенерированного анализатора имеет форму terminals_: {associative list: number ==> name}, для поиска имени терминала с указанием номера маркера.

Чтобы получить исходную строку символов, связанную с лексемой, используйте parser.lexer.yytext.

Вот решение, используя второй вариант:

/* To reduce confusion, I change 'lex' to 'lexer' */ 
var lexer = parser.lexer, 
    token; 
lexer.setInput('The code to parse'); 
while (!lexer.done) { 
    token = lexer.lex(); 
    /* Look up the token name if necessary */ 
    if (token in parser.terminals_) { 
     token = parser.terminals_[token]; 
    } 
    console.log('<' + token + ', ' + lexer.yytext + '>') 
} 
+0

Спасибо за ответ. Я также должен был заглянуть в исходный исходный код парсера, чтобы выяснить, документация Jison по-прежнему немного недостаточна. BTW Я использовал форму, которую вы сделали :) – bryanjhv

Смежные вопросы