gpt4 book ai didi

f# - fslex 中的 Lua 长字符串

转载 作者:行者123 更新时间:2023-12-04 15:15:38 26 4
gpt4 key购买 nike

我一直在业余时间研究 Lua fslex 词法分析器,使用 ocamllex 手册作为引用。

我在尝试正确标记长字符串时遇到了一些障碍。 “长字符串”由 '[' ('=')* '[' 分隔和 ']' ('=')* ']'代币; =的数量标志必须相同。

在第一个实现中,词法分析器似乎无法识别 [[图案,生产两个 LBRACKET尽管有最长匹配规则,但 [=[和正确识别的变化。此外,正则表达式未能确保使用正确的结束标记,在第一个 ']' ('=')* ']' 处停止。捕获,无论实际的长字符串“级别”。此外,fslex 似乎不支持正则表达式中的“as”结构。

let lualongstring = '[' ('=')* '[' ( escapeseq | [^ '\\' '[' ] )* ']' ('=')* ']'

(* ... *)
| lualongstring { (* ... *) }
| '[' { LBRACKET }
| ']' { RBRACKET }
(* ... *)


我一直在尝试用词法分析器中的另一个规则来解决这个问题:

rule tokenize = parse
(* ... *)
| '[' ('=')* '[' { longstring (getLongStringLevel(lexeme lexbuf)) lexbuf }
(* ... *)

and longstring level = parse
| ']' ('=')* ']' { (* check level, do something *) }
| _ { (* aggregate other chars *) }

(* or *)

| _ {
let c = lexbuf.LexerChar(0);
(* ... *)
}

但是我被卡住了,有两个原因:首先,我认为一旦我读完长字符串,我就不能“推送”下一个规则的标记;其次,我不喜欢在找到正确的结束标记之前逐个读取字符的想法,这使得当前的设计毫无用处。

如何在 fslex 中标记 Lua 长字符串?谢谢阅读。

最佳答案

如果我回答我自己的问题,我很抱歉,但我想用我自己的解决方案来解决这个问题,以供将来引用。

我使用 LexBuffer<_>.BufferLocalStore 属性在词法分析器函数调用中保持状态,它只是一个可写的 IDictionary 实例。

注意:长括号用于长字符串和多行注释。这通常是 Lua 语法中被忽视的部分。



let beginlongbracket = '[' ('=')* '['
let endlongbracket = ']' ('=')* ']'

rule tokenize = parse
| beginlongbracket
{ longstring (longBracketLevel(lexeme lexbuf)) lexbuf }

(* ... *)

and longstring level = parse
| endlongbracket
{ if longBracketLevel(lexeme lexbuf) = level then
LUASTRING(endLongString(lexbuf))
else
longstring level lexbuf
}

| _
{ toLongString lexbuf (lexeme lexbuf); longstring level lexbuf }

| eof
{ failwith "Unexpected end of file in string." }

Here are the functions I use to simplify storing data into the BufferLocalStore:

let longBracketLevel (str : string) =
str.Count(fun c -> c = '=')

let createLongStringStorage (lexbuf : LexBuffer<_>) =
let sb = new StringBuilder(1000)
lexbuf.BufferLocalStore.["longstring"] <- box sb
sb

let toLongString (lexbuf : LexBuffer<_>) (c : string) =
let hasString, sb = lexbuf.BufferLocalStore.TryGetValue("longstring")
let storage = if hasString then (sb :?> StringBuilder) else (createLongStringStorage lexbuf)
storage.Append(c.[0]) |> ignore

let endLongString (lexbuf : LexBuffer<_>) : string =
let hasString, sb = lexbuf.BufferLocalStore.TryGetValue("longstring")
let ret = if not hasString then "" else (sb :?> StringBuilder).ToString()
lexbuf.BufferLocalStore.Remove("longstring") |> ignore
ret

也许它不是很实用,但它似乎正在完成工作。
  • 使用标记化规则直到找到长括号的开头
  • 切换到长串规则并循环直到找到相同级别的闭合长括号
  • 将每个与同一级别的结束长括号不匹配的词素存储到 StringBuilder 中,然后将其存储到 LexBuffer BufferLocalStore 中。
  • 一旦 longstring 结束,清除 BufferLocalStore。

  • 编辑:您可以在 http://ironlua.codeplex.com 找到该项目.词法分析和解析应该没问题。我打算使用 DLR。欢迎提出意见和 build 性批评。

    关于f# - fslex 中的 Lua 长字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4351074/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com