Search code examples
javaregexdice

D&D-style compound dice expression regex


I'm working on a project in Java that involves a user entering a dice expression. I'm using a regex to validate the input to ensure it's a valid D&D style dice expression. What I mean by that is that expressions like these:

d20
2D12+ 4 - 2
12d4-2d6+7 + d8
7 + 1d12

Would all be valid. Whereas expressions like these:

-2d6+4
-d8 - 5
12
2d0 + 5
1d6 + 0d2 - 1
0d6

Would all be invalid. So far, the closest regex I've managed to make is:

^((((0+\d+|[1-9]\d*|)(d|D)(0+\d+|[1-9]\d*))|(\d+))((\ *(\+|\-)\ *)(?=(((0+\d+|[1-9]\d*|)(d|D)(0+\d+|[1-9]\d*))|(\d+))))?)+$

However, this regex still matches expressions like "0d6". Any assistance in creating a regex for this would be much appreciated.


Solution

  • ^(?!\d+$)(([1-9]\d*)?[Dd]?[1-9]\d*( ?[+-] ?)?)+(?<![+-] ?)$

    Explanation:

    ^              | Enforce beginning of string
    (?!\\d+$)      | If 1+ digits at end of string are matched, don't match the following:
    (              | Begin group
      ([1-9]\\d*)? |   Optionally match numbers not starting with 0 of any length
      [Dd]?        |   Optionally match either "D" or "d"
      [1-9]\\d*    |   Match numbers not starting with 0 of any length
      ( ?[+-] ?)?  |   Optionally match a "+" or "-" optionally surrounded by spaces
    )+             | End group; one or more of these should exist
    (?<![+-] ?)    | A "+" or "-" with an optional space shouldn't precede the end
    $              | Enforce end of string
    

    Try it here

    Example code:

    String userInput = "12d4-2d6+7 + d8";
    
    Pattern p = Pattern.compile("^(?!\\d+$)(([1-9]\\d*)?[Dd]?[1-9]\\d*( ?[+-] ?)?)+$");
    Matcher m = p.matcher(userInput);
    boolean b = m.matches();
    
    System.out.println(b); // true