I tried to group together two cases to reduce code duplication in the grammar:
From
string = _{("'" ~ (string_value) ~ "'") | ("\"" ~ (string_value) ~ "\"") | ("\"" ~ (string_value_escape_1) ~ "\"") | ("'" ~ (string_value_escape_2) ~ "'")}
string_escape = @{"\\"}
string_value = @{(!("\""|"\\"|"'") ~ ANY)*}
string_value_escape_1 = @{((!("\""|"\\") ~ ANY)+ | string_escape ~ ("\"" | "\\"))*}
string_value_escape_2 = @{((!("'"|"\\") ~ ANY)+ | string_escape ~ ("'" | "\\"))*}
to
string = _{("'" ~ (string_value|string_value_escape_2) ~ "'") | ("\"" ~ (string_value|string_value_escape_1) ~ "\"")}
string_escape = @{"\\"}
string_value = @{(!("\""|"\\"|"'") ~ ANY)*}
string_value_escape_1 = @{((!("\""|"\\") ~ ANY)+ | string_escape ~ ("\"" | "\\"))*}
string_value_escape_2 = @{((!("'"|"\\") ~ ANY)+ | string_escape ~ ("'" | "\\"))*}
But that caused a build error in what I was sure is a simple grouping:
= help: message: grammar error
--> 3:20
|
3 | string = _{("'" ~ (string_value|string_value_escape_2) ~ "'") | ("\"" ~ (string_value|string_value_escape_1) ~ "\"")}
| ^----------^
|
= expression cannot fail; following choices cannot be reached
--> 3:74
|
3 | string = _{("'" ~ (string_value|string_value_escape_2) ~ "'") | ("\"" ~ (string_value|string_value_escape_1) ~ "\"")}
| ^----------^
|
= expression cannot fail; following choices cannot be reached
string_value
can potentially match the empty string (since it's an arbitrary repetition using the Kleene star*
). So it can't fail, as the error message says, because no matter where you are in the input, there's always an empty string in front of you.Thus,
(string_value|string_value_escape_2)
will never matchstring_value_escape_2
, because that won't be tried untilstring_value
fails.