tiempo próximos pronóstico para nueva norte los lexington kentucky hoy estado días clima carolina ahora parsing f# fsyacc fslex

parsing - próximos - Lexing y análisis al mismo tiempo en F#



pronóstico del tiempo en lexington kentucky (1)

¿Existe una manera fácil de obtener lexing y análisis para que se ejecuten al mismo tiempo cuando se usan fslex y fsyacc?


En primer lugar, en el caso real, el lexing y el análisis sintáctico son críticos para el tiempo. Especialmente si necesita procesar tokens antes de analizar. Por ejemplo: filtrado y recopilación de comentarios o resolución de conflictos dependientes del contexto. En este caso, el analizador a menudo espera un lexer.

La respuesta para una pregunta. Puede ejecutar lexing y analizar al mismo tiempo con MailboxProcessor.

Núcleo de la idea Puede ejecutar lexer en mailBoxProcessor. Lexer debería producir nuevos tokens, procesarlos y publicarlos. Lexer suele ser más rápido que el analizador, y a veces debería esperar a un analizador sintáctico. El analizador puede recibir el próximo token cuando sea necesario. Código proporcionado a continuación. Puede modificar los tiempos de espera, traceStep para encontrar el óptimo para su solución.

[<Literal>] let traceStep = 200000L let tokenizerFun = let lexbuf = Lexing.LexBuffer<_>.FromTextReader sr let timeOfIteration = ref System.DateTime.Now fun (chan:MailboxProcessor<lexer_reply>) -> let post = chan.Post async { while not lexbuf.IsPastEndOfStream do lastTokenNum := 1L + !lastTokenNum if (!lastTokenNum % traceStep) = 0L then let oldTime = !timeOfIteration timeOfIteration := System.DateTime.Now let mSeconds = int64 ((!timeOfIteration - oldTime).Duration().TotalMilliseconds) if int64 chan.CurrentQueueLength > 2L * traceStep then int (int64 chan.CurrentQueueLength * mSeconds / traceStep) |> System.Threading.Thread.Sleep let tok = Calc.Lexer.token lexbuf // Process tokens. Filter comments. Add some context-depenede information. post tok } use tokenizer = new MailboxProcessor<_>(tokenizerFun) let getNextToken (lexbuf:Lexing.LexBuffer<_>) = let res = tokenizer.Receive 150000 |> Async.RunSynchronously i := 1L + !i if (!i % traceStep) = 0L then let oldTime = !timeOfIteration timeOfIteration := System.DateTime.Now let seconds = (!timeOfIteration - oldTime).TotalSeconds res let res = tokenizer.Start() Calc.Parser.file getNextToken <| Lexing.LexBuffer<_>.FromString "*this is stub*"

La solución completa está disponible aquí: https://github.com/YaccConstructor/ConcurrentLexPars En esta solución, solo demostramos la implementación completa de la idea descrita. La comparación de rendimiento no es real porque el cálculo semántico es muy simple y no requiere procesamiento de tokens.

Para conocer el resultado de comparación de rendimiento, consulte el informe completo https://docs.google.com/document/d/1K43g5jokNKFOEHQJVlHM1gVhZZ7vFK2g9CJHyAVtUtg/edit?usp=sharing Aquí comparamos el rendimiento de la solución secuencial y concurrente para el analizador del subconjunto de T-SQL. Secuencial: 27 seg., Concurrente: 20 seg.

También usamos esta técnica en el traductor T-SQL de producción.