Cucumber Expressions parser and matcher for MoonBit
Dependencies
moon add moonrockz/cucumber-expressionslet expr = @cucumber-expressions.Expression::parse!("I have {int} cucumber(s) in my {word}")
let m = expr.match_("I have 42 cucumbers in my basket").unwrap()
// m.params[0].value => IntVal(42), m.params[0].raw => "42"
// m.params[1].value => WordVal("basket"), m.params[1].raw => "basket"| Parameter | Description | Example match | Value type |
|---|---|---|---|
| {int} | Integers, optionally negative | 42, -1 | IntVal(Int) |
| {float} | Decimal and scientific notation | 3.14, -1.5e10 | FloatVal(Double) |
| {double} | Same as float | 3.14, 1.5e10 | DoubleVal(Double) |
| {long} | 64-bit integers | 9223372036854775807 | LongVal(Int64) |
| {byte} | Integers from -128 to 127 | 127, -128 | ByteVal(Byte) (two's complement) |
| {short} | Integers from -32768 to 32767 | 8080 | ShortVal(Int) |
| {bigdecimal} | Arbitrary-precision decimals | 99.99 | BigDecimalVal(Decimal) |
| {biginteger} | Arbitrary-precision integers | 12345678901234567890 | BigIntegerVal(BigInt) |
| {string} | Single- or double-quoted strings | "hello", 'hi' | StringVal(String) |
| {word} | A single word (no whitespace) | banana | WordVal(String) |
| {} | Anonymous — matches anything | whatever you want | AnonymousVal(String) |
let expr = @cucumber-expressions.Expression::parse!("{word} costs {float} dollars")
let m = expr.match_("coffee costs 4.50 dollars").unwrap()
// m.params[0].value => WordVal("coffee"), m.params[0].raw => "coffee"
// m.params[1].value => FloatVal(4.5), m.params[1].raw => "4.50"let expr = @cucumber-expressions.Expression::parse!("I have {int} cucumber(s)")
expr.match_("I have 1 cucumber") // matches
expr.match_("I have 5 cucumbers") // matcheslet expr = @cucumber-expressions.Expression::parse!("I have a cat/dog")
expr.match_("I have a cat") // matches
expr.match_("I have a dog") // matcheslet registry = @cucumber-expressions.ParamTypeRegistry::default()
registry.register(
"color",
@cucumber-expressions.ParamType::Custom("color"),
[@cucumber-expressions.RegexPattern("red|green|blue")],
transformer=@cucumber-expressions.Transformer::new(fn(groups) {
@cucumber-expressions.ParamValue::StringVal(groups[0].to_upper())
}),
)
let expr = @cucumber-expressions.Expression::parse_with_registry!(
"the {color} ball",
registry,
)
let m = expr.match_("the red ball").unwrap()
// m.params[0].value => StringVal("RED"), m.params[0].raw => "red"let registry = @cucumber-expressions.ParamTypeRegistry::default()
let color = registry.define1("color", [@cucumber-expressions.RegexPattern("red|green|blue")], Color::new)
let coord = registry.define2("coord", [@cucumber-expressions.RegexPattern("(\\d+),(\\d+)")], (x, y) => {
Coord::new(@string.parse_int(x), @string.parse_int(y))
})
let expr = @cucumber-expressions.Expression::parse_with_registry("a {color} ball at {coord}", registry)
let m = expr.match_("a red ball at 3,4").unwrap()
let c : Color = color.get(m.params[0]) // raises if params[0] is not a {color}
let p : Coord = m.get(coord) // the only {coord} of the match
let all : Array[Color] = m.get_all(color)let seat = registry.define_with(
"seat",
[@cucumber-expressions.RegexPattern("(\\d+)-(\\w+)-(\\d+)")],
@cucumber-expressions.Captures::int()
.zip(@cucumber-expressions.Captures::string())
.zip(@cucumber-expressions.Captures::int())
.map((row, block, number) => Seat::new(row, block, number)),
)let person = @cucumber-expressions.Captures::string().zip(@cucumber-expressions.Captures::string()).map((first, last) => Person::new(first, last))
let customer = person.zip(address).zip(contact).map((p, a, c) => Customer::new(p, a, c))impl @cucumber-expressions.ParameterTypeDef for Color with name() { "color" }
impl @cucumber-expressions.ParameterTypeDef for Color with regexps() {
[@cucumber-expressions.RegexPattern("red|green|blue")]
}
impl @cucumber-expressions.FromGroups1 for Color with from_groups(name) { Color::new(name) }
let color : @cucumber-expressions.ParameterType[Color] = registry.define_type1()let expr = @cucumber-expressions.Expression::parse!("{word} is {int}")
match expr.match_("MoonBit is 1") {
Some(m) => {
let name = m.params[0] // { value: WordVal("MoonBit"), type_: Word, raw: "MoonBit" }
let num = m.params[1] // { value: IntVal(1), type_: Int, raw: "1" }
}
None => println("no match")
}let expr = @cucumber-expressions.RegularExpression::new("^I have (\\d+) cukes? in my (.+)$")
let m = expr.match_("I have 3 cukes in my belly").unwrap()
// m.params[0].value => IntVal(3), m.params[1].value => AnonymousVal("belly")let factory = @cucumber-expressions.ExpressionFactory::new(registry)
let expr = factory.create_expression("^I have (\\d+) cukes$") // Regular(...)
let expr = factory.create_expression("I have {int} cukes") // Cucumber(...)let generator = @cucumber-expressions.CucumberExpressionGenerator::new(registry)
let generated = generator.generate_expressions("I have 2 cucumbers and 1.5 tomato")
// generated[0].source() => "I have {int} cucumbers and {float} tomato"
// generated[0].parameter_names() => ["int", "float"]| Variant | Cause |
|---|---|
| UnmatchedBrace | Missing closing } |
| UnmatchedParen | Missing closing ) |
| CannotEscape | Invalid escape sequence |
| UnexpectedEscapeEnd | Backslash at end of expression |
| ValidationError | Structural errors (empty alternation, nested optionals, etc.) |
| UnknownParameterType | Unregistered {name} in expression |
This Cucumber Expression has a problem at column 3:
(a(b))
^-^
An optional may not contain an other optional.
If you did not mean to use an optional type you can use '\(' to escape the '('. For more complicated expressions consider using a regular expression instead.try {
let _ = @cucumber-expressions.Expression::parse!("{unknown}")
} catch {
@cucumber-expressions.ExpressionError::UnknownParameterType(name~, ..) =>
println("Unknown parameter: " + name)
}pub(open) trait FromGroups1 {
fn from_groups(String) -> Self raise
}pub(open) trait FromGroups2 {
fn from_groups(String, String) -> Self raise
}pub(open) trait FromGroups3 {
fn from_groups(String, String, String) -> Self raise
}pub(open) trait FromGroups4 {
fn from_groups(String, String, String, String) -> Self raise
}pub(open) trait FromGroups5 {
fn from_groups(String, String, String, String, String) -> Self raise
}pub(open) trait FromGroups6 {
fn from_groups(String, String, String, String, String, String) -> Self raise
}pub(open) trait FromGroups7 {
fn from_groups(String, String, String, String, String, String, String) -> Self raise
}pub(open) trait FromGroups8 {
fn from_groups(String, String, String, String, String, String, String, String) -> Self raise
}pub(open) trait ParameterTypeDef {
fn name() -> String
fn regexps() -> Array[RegexPattern]
fn use_for_snippets() -> Bool = _
fn prefer_for_regexp_match() -> Bool = _
}impl Show for AmbiguousParameterTypeErrorfn AmbiguousParameterTypeError::output(self : AmbiguousParameterTypeError, logger : &Logger) -> Unit#deprecated("`AmbiguousParameterTypeError::to_repr` is deprecated, use `@moonbitlang/core/debug.Debug::to_repr` instead.")
fn AmbiguousParameterTypeError::to_repr(AmbiguousParameterTypeError) -> Reprpub suberror ExpressionError {
UnmatchedBrace(position~ : Int, message~ : String)
UnmatchedParen(position~ : Int, message~ : String)
CannotEscape(position~ : Int, character~ : Char, message~ : String)
UnexpectedEscapeEnd(position~ : Int, message~ : String)
ValidationError(position~ : Int, message~ : String)
UnknownParameterType(name~ : String, position~ : Int, message~ : String)
} derive(Debug)impl Show for ExpressionError#deprecated("`ExpressionError::to_repr` is deprecated, use `@moonbitlang/core/debug.Debug::to_repr` instead.")
fn ExpressionError::to_repr(ExpressionError) -> Reprpub suberror ParameterTypeError {
DuplicateParameterType(name~ : String)
IllegalParameterName(name~ : String)
NoRegexps(name~ : String)
DuplicatePreferentialParameterType(regexp~ : String, first~ : String, second~ : String)
WrongParameterType(expected~ : String, actual~ : String)
MissingParameter(name~ : String)
AmbiguousParameter(name~ : String, count~ : Int)
GroupDidNotMatch(name~ : String, index~ : Int)
ArityMismatch(name~ : String, expected~ : Int, groups~ : Int)
InvalidRegexp(name~ : String, regexp~ : String)
WrongGroupCount(name~ : String, expected~ : Int, actual~ : Int)
} derive(Debug)impl Show for ParameterTypeError#deprecated("`ParameterTypeError::to_repr` is deprecated, use `@moonbitlang/core/debug.Debug::to_repr` instead.")
fn ParameterTypeError::to_repr(ParameterTypeError) -> Reprpub enum Captures {
}Captures::int().zip(Captures::string()).map((n, s) => Item::new(n, s))pub struct Captures1[T] {
// private fields
}pub struct Captures2[A, B] {
// private fields
}pub struct Captures3[A, B, C] {
// private fields
}pub struct Captures4[A, B, C, D] {
// private fields
}pub struct Captures5[A, B, C, D, E] {
// private fields
}pub struct Captures6[A, B, C, D, E, F] {
// private fields
}pub struct Captures7[A, B, C, D, E, F, G] {
// private fields
}pub struct Captures8[A, B, C, D, E, F, G, H] {
// private fields
}pub(all) struct CucumberExpressionGenerator {
// private fields
}fn CucumberExpressionGenerator::generate_expressions(self : CucumberExpressionGenerator, text : String) -> Array[GeneratedExpression]pub(all) struct Expression {
// private fields
}fn Expression::parse_with_registry(expression : String, registry : ParamTypeRegistry) -> Expression raise ExpressionErrorpub(all) struct ExpressionFactory {
// private fields
}fn ExpressionFactory::create_expression(self : ExpressionFactory, expression : String) -> StepExpression raise ExpressionErrorpub(all) struct Param {
value : ParamValue
type_ : ParamType
raw : String
group : Group
} derive(Eq, Debug)pub(all) struct ParamTypeEntry {
name : String
type_ : ParamType
patterns : Array[RegexPattern]
transformer : Transformer
use_for_snippets : Bool
prefer_for_regexp_match : Bool
} derive(Debug)impl Eq for ParamTypeEntry#deprecated("`ParamTypeEntry::equal` is deprecated, use `Eq::equal` instead.")
fn ParamTypeEntry::equal(self : ParamTypeEntry, other : ParamTypeEntry) -> Bool#deprecated("`ParamTypeEntry::not_equal` is deprecated, use `Eq::not_equal` instead.")
fn ParamTypeEntry::not_equal(x : ParamTypeEntry, y : ParamTypeEntry) -> Bool#deprecated("`ParamTypeEntry::to_repr` is deprecated, use `@moonbitlang/core/debug.Debug::to_repr` instead.")
fn ParamTypeEntry::to_repr(ParamTypeEntry) -> Reprpub(all) struct ParamTypeRegistry {
// private fields
}fn[T] ParamTypeRegistry::define1(self : ParamTypeRegistry, name : String, regexps : Array[RegexPattern], transformer : (String) -> T raise, use_for_snippets? : Bool, prefer_for_regexp_match? : Bool) -> ParameterType[T] raise ParameterTypeErrorfn[T] ParamTypeRegistry::define2(self : ParamTypeRegistry, name : String, regexps : Array[RegexPattern], transformer : (String, String) -> T raise, use_for_snippets? : Bool, prefer_for_regexp_match? : Bool) -> ParameterType[T] raise ParameterTypeErrorfn[T] ParamTypeRegistry::define3(self : ParamTypeRegistry, name : String, regexps : Array[RegexPattern], transformer : (String, String, String) -> T raise, use_for_snippets? : Bool, prefer_for_regexp_match? : Bool) -> ParameterType[T] raise ParameterTypeErrorfn[T] ParamTypeRegistry::define4(self : ParamTypeRegistry, name : String, regexps : Array[RegexPattern], transformer : (String, String, String, String) -> T raise, use_for_snippets? : Bool, prefer_for_regexp_match? : Bool) -> ParameterType[T] raise ParameterTypeErrorfn[T] ParamTypeRegistry::define5(self : ParamTypeRegistry, name : String, regexps : Array[RegexPattern], transformer : (String, String, String, String, String) -> T raise, use_for_snippets? : Bool, prefer_for_regexp_match? : Bool) -> ParameterType[T] raise ParameterTypeErrorfn[T] ParamTypeRegistry::define6(self : ParamTypeRegistry, name : String, regexps : Array[RegexPattern], transformer : (String, String, String, String, String, String) -> T raise, use_for_snippets? : Bool, prefer_for_regexp_match? : Bool) -> ParameterType[T] raise ParameterTypeErrorfn[T] ParamTypeRegistry::define7(self : ParamTypeRegistry, name : String, regexps : Array[RegexPattern], transformer : (String, String, String, String, String, String, String) -> T raise, use_for_snippets? : Bool, prefer_for_regexp_match? : Bool) -> ParameterType[T] raise ParameterTypeErrorfn[T] ParamTypeRegistry::define8(self : ParamTypeRegistry, name : String, regexps : Array[RegexPattern], transformer : (String, String, String, String, String, String, String, String) -> T raise, use_for_snippets? : Bool, prefer_for_regexp_match? : Bool) -> ParameterType[T] raise ParameterTypeErrorfn[T : ParameterTypeDef + FromGroups1] ParamTypeRegistry::define_type1(self : ParamTypeRegistry) -> ParameterType[T] raise ParameterTypeErrorfn[T : ParameterTypeDef + FromGroups2] ParamTypeRegistry::define_type2(self : ParamTypeRegistry) -> ParameterType[T] raise ParameterTypeErrorfn[T : ParameterTypeDef + FromGroups3] ParamTypeRegistry::define_type3(self : ParamTypeRegistry) -> ParameterType[T] raise ParameterTypeErrorfn[T : ParameterTypeDef + FromGroups4] ParamTypeRegistry::define_type4(self : ParamTypeRegistry) -> ParameterType[T] raise ParameterTypeErrorfn[T : ParameterTypeDef + FromGroups5] ParamTypeRegistry::define_type5(self : ParamTypeRegistry) -> ParameterType[T] raise ParameterTypeErrorfn[T : ParameterTypeDef + FromGroups6] ParamTypeRegistry::define_type6(self : ParamTypeRegistry) -> ParameterType[T] raise ParameterTypeErrorfn[T : ParameterTypeDef + FromGroups7] ParamTypeRegistry::define_type7(self : ParamTypeRegistry) -> ParameterType[T] raise ParameterTypeErrorfn[T : ParameterTypeDef + FromGroups8] ParamTypeRegistry::define_type8(self : ParamTypeRegistry) -> ParameterType[T] raise ParameterTypeErrorfn[T] ParamTypeRegistry::define_with(self : ParamTypeRegistry, name : String, regexps : Array[RegexPattern], captures : Captures1[T], use_for_snippets? : Bool, prefer_for_regexp_match? : Bool) -> ParameterType[T] raise ParameterTypeErrorfn ParamTypeRegistry::lookup_by_regexp(self : ParamTypeRegistry, regexp : String, expression_regexp : String, text : String) -> ParamTypeEntry? raise AmbiguousParameterTypeErrorfn ParamTypeRegistry::register(self : ParamTypeRegistry, name : String, type_ : ParamType, patterns : Array[RegexPattern], transformer? : Transformer, use_for_snippets? : Bool, prefer_for_regexp_match? : Bool) -> Unit raise ParameterTypeErrorpub(all) enum ParamValue {
IntVal(Int)
FloatVal(Double)
DoubleVal(Double)
LongVal(Int64)
ByteVal(Byte)
ShortVal(Int)
StringVal(String)
WordVal(String)
AnonymousVal(String)
BigDecimalVal(Decimal)
BigIntegerVal(BigInt)
NullVal
TypedVal(TypedValue)
}impl Eq for ParamValueimpl Show for ParamValueimpl Debug for ParamValue#deprecated("`ParamValue::equal` is deprecated, use `Eq::equal` instead.")
fn ParamValue::equal(self : ParamValue, other : ParamValue) -> Bool#deprecated("`ParamValue::not_equal` is deprecated, use `Eq::not_equal` instead.")
fn ParamValue::not_equal(x : ParamValue, y : ParamValue) -> Bool#deprecated("`ParamValue::to_repr` is deprecated, use `@moonbitlang/core/debug.Debug::to_repr` instead.")
fn ParamValue::to_repr(self : ParamValue) -> Repr#deprecated("`ParameterInfo::equal` is deprecated, use `Eq::equal` instead.")
fn ParameterInfo::equal(ParameterInfo, ParameterInfo) -> Bool#deprecated("`ParameterInfo::not_equal` is deprecated, use `Eq::not_equal` instead.")
fn ParameterInfo::not_equal(x : ParameterInfo, y : ParameterInfo) -> Bool#deprecated("`ParameterInfo::to_repr` is deprecated, use `@moonbitlang/core/debug.Debug::to_repr` instead.")
fn ParameterInfo::to_repr(ParameterInfo) -> Reprpub struct ParameterType[T] {
// private fields
}#deprecated("`RegexPattern::equal` is deprecated, use `Eq::equal` instead.")
fn RegexPattern::equal(RegexPattern, RegexPattern) -> Bool#deprecated("`RegexPattern::not_equal` is deprecated, use `Eq::not_equal` instead.")
fn RegexPattern::not_equal(x : RegexPattern, y : RegexPattern) -> Bool#deprecated("`RegexPattern::to_repr` is deprecated, use `@moonbitlang/core/debug.Debug::to_repr` instead.")
fn RegexPattern::to_repr(RegexPattern) -> Reprpub(all) struct RegularExpression {
// private fields
}fn RegularExpression::new(regexp : String, registry? : ParamTypeRegistry) -> RegularExpression raise ExpressionErrorpub(all) struct Transformer {
// private fields
}impl Debug for Transformer#deprecated("`Transformer::to_repr` is deprecated, use `@moonbitlang/core/debug.Debug::to_repr` instead.")
fn Transformer::to_repr(_self : Transformer) -> Reprpub struct TypedValue {
// private fields
}fn compile_expression(expression : String, registry? : ParamTypeRegistry) -> String raise ExpressionErrorfn version() -> StringInstall
Download zipCucumber Expressions parser and matcher for MoonBit
Dependencies