我当前的项目涉及lexing和解析脚本代码,因此我使用的是fslex和fsyacc。 Fslex LexBuffers可以有LexBuffer<char>
和LexBuffer<byte>
种类,我希望可以同时使用它们。
为了同时使用两者,我需要一个类型为^ buf - &gt;的lexeme函数。串。到目前为止,我的专业化尝试看起来像:
let inline lexeme (lexbuf: ^buf) : ^buf -> string where ^buf : (member Lexeme: char array) =
new System.String(lexbuf.Lexeme)
let inline lexeme (lexbuf: ^buf) : ^buf -> string where ^buf : (member Lexeme: byte array) =
System.Text.Encoding.UTF8.GetString(lexbuf.Lexeme)
我收到一个类型错误,指出函数体应该是^buf -> string
类型,但推断类型只是string
。显然,我正在做某事(主要是?)错误。
我在F#中尝试甚至可能吗?如果是这样,有人能指出我正确的道路吗?
谢谢!
答案 0 :(得分:2)
标记为inline
的功能和成员无法重载,因此您的原始策略无效。您需要为两个声明编写不同的代码,因此您需要使用重载(如果您想在没有装箱和动态类型测试的情况下编写它)。
如果您使用的是标准F#工具,那么您将作为缓冲区获得的类型始终为LexBuffer<'T>
,并且您希望根据类型参数进行两次重载。在这种情况下,您根本不需要静态成员约束,只能编写:
type Utils =
static member lexeme(buf:LexBuffer<char>) =
new System.String(buf.Lexeme)
static member lexeme(buf:LexBuffer<byte>) =
System.Text.Encoding.UTF8.GetString(buf.Lexeme)
答案 1 :(得分:0)
您确定使用不同参数类型重新定义inline
函数的策略是否有效?看起来你正试图给我超载......
答案 2 :(得分:0)
type LexBuffer<'a>(data : 'a []) =
member this.Lexeme = data
let lexeme (buf : LexBuffer<'a>) =
match box buf.Lexeme with
| :? (char array) as chArr ->
new System.String(chArr)
| :? (byte array) as byArr ->
System.Text.Encoding.UTF8.GetString(byArr)
| _ -> invalidArg "buf" "must be either char or byte LexBuffer"
new LexBuffer<byte>([| 97uy; 98uy; 99uy |])
|> lexeme
|> printfn "%A"
new LexBuffer<char>([| 'a'; 'b'; 'c' |])
|> lexeme
|> printfn "%A"