2013-08-17 3 views
1

Я пытаюсь разобрать DSL с OMetaJS и создать AST, который включает в себя значение токена, а также его индекс в исходном потоке.Создание AST с OMetaJS, которое включает значение токена и позицию

Я знаю, что могу использовать синтаксис Index Capture Rule (@<rule>), чтобы дать мне объект, содержащий индексы обрамления маркера, но это возможно, чтобы захватить этот , а также лексемы значения?

например для грамматики:

export ometa Test { 
    start = @<identifier>, 
    identifier = (letter | digit)+ 
} 

Синтаксический "Боб" дает:

{ fromIdx : 0, toIdx : 3 } 

Если я удалить '@' от 'идентификатор', то разбор дает "Боб" в качестве результата. То, что я бы в идеале хотел бы получить это сочетание два:

{ fromIdx : 0, toIdx : 3, value: 'Bob' } 

Я, конечно, могу взломать источник, но есть лучший способ сделать это?

Я хочу иметь как значение, так и позицию, потому что я пытаюсь создать визуальное представление DSL, которое позволяет редактировать имена идентификаторов, например. В этом случае мне нужно знать, где в исходном источнике появился идентификатор, поэтому я могу его изменить.

ответ

0

Учитывая, что вы хотите вещь и диапазон, как насчет использования оператору peek &? Это вернет токен, но не будет потреблять вход. Возможно, что-то вроде

spannedThing = (&identifier:token @identifier:span) -> combineThemSomehow(token, span) 

может делать то, что вы хотите? (Предупреждение: мой OMeta ржавый, выше не может использовать правильную грамматику.) Вы можете превратить это в параметризованное правило.

+0

Никогда не думал об использовании оператора lookahead. Хорошая идея. Конечно, это означает, что вы разбираете все дважды, не так ли? Во всяком случае, как ответ, поскольку я не нашел лучшего способа. Но для записи в итоге я просто использовал оператор '@<...>' и проиндексировал его в исходный текст. – emertechie

+0

Ну, разбор должен быть замечен, поэтому он не должен быть таким же плохим, как удар производительности 2x. Я не знаю о OMeta/JS, но вот как это работает в OMeta/Squeak. –

+0

@Frank: Недавно я смотрел на OMeta и наткнулся на некоторые старые вещи с вашим именем на нем и множеством неработающих ссылок. Все еще существует Пифия? (Извините за комментарий вне темы, но это было похоже на самый простой способ связаться с вами.) –

1

Я думаю, что то, о чем вы просите, очень полезно и, вероятно, заслуживает того, чтобы иметь свой собственный синтаксический сахар. Я обязательно подумаю об этом. Тем временем вы можете сделать что-то вроде этого:

ometa Test { 
    parse :r = @<apply(r):value>:node !(node.value = value) -> node, 

    identifier = (letter | digit)+, 
    start = parse("identifier") 
} 

Надеюсь, что это поможет!