用仔猪流利配置解析拉丁植物名称

时间:2012-10-23 09:18:52

标签: vb.net piglet

我有以下测试。和类。现在我只需要找到如何编写规则,它看起来很简单;-)。但我无处可去。正如标签所说,我想用它来学习仔猪。

Public Class Plant
    Public Property Genus As String
    Public Property Species As String
    Public Property SubSpecies As String
    Public Property IsHybrid As Boolean
End Class

Public Class ParserTests
    <Test>
    Public Sub IfGenusCanBeFoundWhenOnlyGenusAndSpiecesAreThere()
        Dim parser = New ParseLatinPlantName
        Dim result = parser.Parse("Salvia sylvatica")
        Assert.AreEqual("Salvia", result.Genus)
    End Sub

    <Test>
    Public Sub IfSpeciesCanBeFoundWhenOnlyGenusAndSpiecesAreThere()
        Dim parser = New ParseLatinPlantName
        Dim result = parser.Parse("Salvia sylvatica")
        Assert.AreEqual("sylvatica", result.Species)
    End Sub

    <Test>
    Public Sub IfSubSpeciesCanBeFoundWhenSubSpeciesIsProvided()
        Dim parser = New ParseLatinPlantName
        Dim result = parser.Parse("Salvia sylvatica sp. crimsonii")
        Assert.AreEqual("crimsonii", result.SubSpecies)
    End Sub

    <Test>
    Public Sub IfIsHybridIsTrueWhenxIsInNameCanBeFoundWhenSubSpeciesIsProvided()
        Dim parser = New ParseLatinPlantName
        Dim result = parser.Parse("Salvia x jamensis")
        Assert.IsTrue(result.IsHybrid)
    End Sub

End Class

这是我到目前为止所做的尝试。

Public Class ParseLatinPlantName

        Public Function Parse(ByVal name As String) As Plant
            Dim config = ParserFactory.Fluent()
            Dim expr = config.Rule()
            Dim name1 = config.Expression()
            name1.ThatMatches("[a-z]+").AndReturns(Function(f) f)

            Dim space1 = config.Expression()
            space1.ThatMatches(" ").AndReturns(Function(f) f)

            expr.IsMadeUp.By(name).As("Genus").Followed.By(name).As("Species").WhenFound(Function(f) New Plant With {.Genus = f.Genus})

            Dim parser = config.CreateParser()
            Dim result = DirectCast(parser.Parse(name), Plant)
            Return result
        End Function
    End Class

更新

我得到了前两个测试,感谢Randompunter。

Public Class ParseLatinPlantName

        Public Function Parse(ByVal name As String) As Plant
            Dim config = ParserFactory.Fluent()
            Dim expr = config.Rule()
            Dim name1 = config.Expression()
            name1.ThatMatches("\w+").AndReturns(Function(f) f)

            expr.IsMadeUp.By(name1).As("Genus") _
                    .Followed.By(name1).As("Species") _
                    .WhenFound(Function(f) New Plant With {.Genus = f.Genus, .Species = f.Species})

            Dim parser = config.CreateParser()
            Dim result = DirectCast(parser.Parse(name), Plant)
            Return result
        End Function
    End Class

1 个答案:

答案 0 :(得分:4)

首先,您的原始(然后更正的表达式仅匹配小写字母)。通过将其更改为与任何其他字母匹配的\w+来更正此问题。

您的第二个测试失败,因为您的语法不允许超过两个以下的字母。您需要添加规则才能使其正常工作。

例如,您有一个提供亚种的示例。假设这采用的形式是.sp xxx是一个可选的东西,需要为此提供一个单独的规则。

这通过了可选亚种的测试

Public Class ParseLatinPlantName

    Public Function Parse(ByVal name As String) As Plant
        Dim config = ParserFactory.Fluent()
        Dim expr = config.Rule()
        Dim subSpecies = config.Rule()
        Dim sp = config.Expression()
        sp.ThatMatches("sp\.").AndReturns(Function(f) f)
        Dim name1 = config.Expression()
        name1.ThatMatches("\w+").AndReturns(Function(f) f)
        Dim nothing1 = config.Rule()


        expr.IsMadeUp.By(name1).As("Genus") _
                .Followed.By(name1).As("Species") _
                .Followed.By(subSpecies).As("Subspecies") _
                .WhenFound(Function(f) New Plant With {.Genus = f.Genus, .Species = f.Species, .SubSpecies = f.Subspecies})
        subSpecies.IsMadeUp.By(sp).Followed.By(name1).As("Subspecies").WhenFound(Function(f) f.Subspecies) _
            .Or.By(nothing1)

        Dim parser = config.CreateParser()
        Dim result = DirectCast(parser.Parse(name), Plant)
        Return result
    End Function
End Class

请原谅我可能非常粗暴的VB,这是很久以前的事了。请注意,有一个表达式明确匹配“sp。”区别于任何其他类型的名称。然后,此规则也会与另一个不匹配的规则匹配。这使亚种部分成为可选的。

我不确定你想从混合规则解析什么。我认为它必须是一个名字后跟一个x然后跟着一些其他名字然后它是一个混合体。要匹配此项,请向解析器添加另一个规则。

以下解析器会传递所有测试:

Public Class ParseLatinPlantName

    Public Function Parse(ByVal name As String) As Plant
        Dim config = ParserFactory.Fluent()
        Dim expr = config.Rule()
        Dim subSpecies = config.Rule()
        Dim hybridIndicator = config.Expression
        hybridIndicator.ThatMatches("x").AndReturns(Function(f) f)

        Dim sp = config.Expression()
        sp.ThatMatches("sp\.").AndReturns(Function(f) f)
        Dim name1 = config.Expression()
        name1.ThatMatches("\w+").AndReturns(Function(f) f)
        Dim nothing1 = config.Rule()


        expr.IsMadeUp.By(name1).As("Genus") _
                .Followed.By(name1).As("Species") _
                .Followed.By(subSpecies).As("Subspecies") _
                .WhenFound(Function(f) New Plant With {.Genus = f.Genus, .Species = f.Species, .SubSpecies = f.Subspecies}) _
                .Or.By(name1).As("FirstSpecies").Followed.By(hybridIndicator).Followed.By(name1).As("SecondSpecies") _
                .WhenFound(Function(f) New Plant With {.IsHybrid = True})

        subSpecies.IsMadeUp.By(sp).Followed.By(name1).As("Subspecies").WhenFound(Function(f) f.Subspecies) _
            .Or.By(nothing1)

        Dim parser = config.CreateParser()
        Dim result = DirectCast(parser.Parse(name), Plant)
        Return result
    End Function
End Class

重要的是,如果表达式重叠,则按优先顺序声明。如果您在name1之前声明hybridIndicatorx将被识别为名称,导致解析失败。正如您可能已经注意到的那样,Piglet默认忽略空格,不需要为它制定规则。如果不需要此设置,可以选择在配置器中将其关闭。 (使用忽略方法)