.net 缩短递归下降解析器中的活动模式

.net 缩短递归下降解析器中的活动模式,.net,parsing,linked-list,f#,pattern-matching,.net,Parsing,Linked List,F#,Pattern Matching,我想用类型tokenlist->Ast*tokenlist构建活动模式 我有一个简单的Pascal语法:=“program”“;”。。通过将代码重新建模到此语法,我必须制作程序、标识符和块模式,如: let rec (|Program|_|) tokens = match tokens with | Token.Program :: tokens -> match tokens with | Identifier (identifier, t

我想用类型
tokenlist->Ast*tokenlist
构建活动模式

我有一个简单的Pascal语法
:=“program”“;”。
。通过将代码重新建模到此语法,我必须制作
程序
标识符
模式,如:

let rec (|Program|_|) tokens =
    match tokens with
    | Token.Program :: tokens ->
        match tokens with
        | Identifier (identifier, tokens) ->
            match tokens with
            | Semicolon :: tokens ->
                match tokens with
                | Block (block, tokens) ->
                    match tokens with
                    | Dot :: tokens -> Some (Ast.Program (identifier, block), tokens)
                    | _ -> failwithf "Expected %A" Dot
                | _ -> failwith "Expected Block"
            | _ -> failwithf "Expected %A" Semicolon
        | _ -> failwith "Expected Identifier"
    | _ -> failwithf "Expected %A" Token.Program

and (|Identifier|_|) tokens =
    match tokens with
    | Token.Identifier identifier :: tokens ->
        Some (Ast.Identifier identifier, tokens)
    | _ -> failwith "Expected Identifier"
...
因为有许多重复选项
None
,我尝试将模式缩短为:

type rec (|Program|_|) tokens =
    match tokens with
    | Token.Program :: Identifier (ident, Semicolon :: Block (block, Dot :: rest)) ->
        Some (Ast.Program (identifier, block), rest)
    | _ -> None
新模式能如预期的那样工作吗?如何使活动模式变短,但在输入错误时也返回错误


此外,我还了解到FParsec用于解析和保留错误,我如何才能生成类似于FParsec的简单计算表达式。

简单的方法就是将所有内容展平:

let rec private (|Program|_|) tokens =
    match tokens with
    | Token.Program ::Identifier (identifier, Semicolon :: Block (block,Dot :: tokens) ) ->Some (Ast.Program (identifier, block), tokens)
    | Token.Program ::Identifier (identifier, Semicolon :: Block (block,_) ) ->failwith "Expected %A" Dot 
    | Token.Program ::Identifier (identifier, Semicolon ::_ ) ->failwith "Expected %A" Block
....

对于编写计算表达式,这是您最好的指南。而且,您的AST设计在我看来有点奇怪。为什么
标识符
联合案例“在”它们内部吸收了以下标记,而
程序
标记却没有?我希望看到更像
将令牌与标识符ident::tokens
匹配,即
标识符
大小写仅“吸收”标识符的名称。以下所有标记都“在”标识符案例中是没有意义的。我不知道我是否清楚地表达了我想说的话;你明白我的意思吗,或者我应该尝试重新表述吗?@rmunn所有活动模式都会吸收代币并返回剩余的代币。因为我从他们那里读到的应该是type
tokenlist->Ast*tokenlist
。但是,你的
标识符
令牌违反了这个规则。创建
Identifier
的任何函数都应该有一个签名,如
令牌列表->标识符*令牌列表
,但它的签名是
令牌列表->标识符
。其余的令牌已被
标识符
令牌的后半部分吸收,这不是它应该如何进行的。@rmun也许您应该再次检查签名,我添加了
标识符
图案以获得清晰的视觉效果,它返回
Ast.Identifier*Token list
。您知道如何快速查找或阻止标识符吗?e、 g.当我有
type Token=|字符串标识符
时,我想宣布“预期标识符”,并且
failwithf“预期%A”(标识符“)
将无法按预期工作。无法立即想到任何事情