fslex - Как переключаться между двумя наборами токенов?

Я пытаюсь написать небольшой синтаксический анализатор DSL, используя fslex и fsyacc. Входные данные состоят из чередующихся фрагментов двух разных языков, для которых требуются разные правила лексирования. Как мне написать свой файл fslex для поддержки этого?

(Думаю, похожим случаем было бы определение файла fslex для языка c, но с поддержкой встроенного ассемблера, для которого требуются другие правила лексирования?)

То, что у меня есть на данный момент, выглядит примерно так:

rule tokenize = parse
    | "core"        { core lexbuf }
    ...

and core = parse
    | ...

Дело в том, что как только парсер core возвращает токен, следующая часть ввода вместо этого передается tokenize. Однако я хочу остаться (как бы) в состоянии core. Как я могу это сделать?

Спасибо!


person Aviad P.    schedule 28.03.2014    source источник


Ответы (1)


Мне действительно удалось найти решение самостоятельно. Я определил свою собственную функцию токенизатора, которая на основе состояния BufferLocalStore решает, какой токенизатор вызывать.

let mytokenizer (lexbuf : LexBuffer<char>) =
    if lexbuf.BufferLocalStore.["state"].Equals("core") then FCLexer.core lexbuf
    else FCLexer.tokenize lexbuf

let aString (x : string) = 
    let lexbuf = LexBuffer<_>.FromString x
    lexbuf.BufferLocalStore.["state"] <- "fc"
    let y = try (FCParser.PROG mytokenizer) lexbuf
...

И я немного изменил свой входной файл fslex:

rule tokenize = parse
    | "core"        { lexbuf.BufferLocalStore.["state"] <- "core"; core lexbuf }
...

Удивительно, как простой вопрос может привести вас к решению, и я надеюсь, что это поможет кому-то, кроме меня :)

person Aviad P.    schedule 28.03.2014