1

我有以下测试。和类。现在我只需要找到如何编写规则,它看起来很简单;-)。但我哪儿也去不了快。正如标签所说,我想为此使用和学习小猪。

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
4

1 回答 1

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之前声明,则会导致解析失败。您可能已经注意到,Piglet 默认会忽略空格,因此无需为它制定规则。如果不需要此设置,可以在配置器中将其关闭。(使用忽略方法)hybridIndicatorx

于 2012-10-23T13:35:22.970 回答