我有以下测试。和类。现在我只需要找到如何编写规则,它看起来很简单;-)。但我无处可去。正如标签所说,我想用它来学习仔猪。
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
答案 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
之前声明hybridIndicator
,x
将被识别为名称,导致解析失败。正如您可能已经注意到的那样,Piglet默认忽略空格,不需要为它制定规则。如果不需要此设置,可以选择在配置器中将其关闭。 (使用忽略方法)