问题
Some Request for Comments (RFCs) have these two rules:
1. Each comma character must be escaped with a backslash.
2. A backslash that is not being used to escape a comma must be escaped with a backslash.
Here are valid values:
A\,B
A\\\,B
A\\\\\\\,B
Here are invalid values:
A\\,B
A,B
A\\\B
I created two Alloy models.
My second Alloy model has two signatures for backslashes:
sig Backslash extends Char {}
sig EscapedBackslash extends Char {}
The latter, of course, represents a double backslash. The former represents a single backslash.
Given those two signatures, it was really easy to express the rules:
Each comma must be preceded by a backslash.
Each backslash must be followed by a comma.
I didn't need to worry about making sure certain backslashes were appropriately escaped. The EscapedBackslash
signature already took care of that.
In my first model I had only one signature for backslash:
sig Backslash extends Char {}
It was very hard to implement the two rules. In fact, I never succeeded in implementing the rules.
As I stated earlier, the second model has this signature:
sig EscapedBackslash extends Char {}
which enabled me to completely avoid the task of checking that every backslash that is not being used to escape a comma is escaped. Is that cheating?
Here is my Alloy model (second model):
one sig Text {
firstChar: Char
}
abstract sig Char {
next: lone Char,
prev: lone Char
}
sig A extends Char {}
sig B extends Char {}
sig C extends Char {}
sig Comma extends Char {}
sig Backslash extends Char {}
sig EscapedBackslash extends Char {}
fact Text_Structure {
// If the i'th character is c and c.next is c', then c'.prev equals c
all c: Char | some c.next => c.next.prev = c
// The first character has no previous character
no Text.firstChar.prev
// No cycles in the forward direction, i.e., if the i'th character is c, then the
// i'th + n character cannot be c
no c: Char | c in c.^next
// No cycles in the backward direction, i.e., if the i'th character is c, then the
// i'th - n character cannot be c
no c: Char | c in c.^prev
// This is not necesssary. I just don't like to see miscellaneous relations.
// This says that if a character is not in the string, then it has no next or previous character.
all c: Char | c not in Text.firstChar.*next => no c.next and no c.prev
}
// Rule: Every comma MUST be escaped.
fact Every_Comma_Escaped {
// The firstChar cannot be a comma
Text.firstChar not in Comma
all c: Text.firstChar.*next | c in Comma => c.prev in Backslash
}
// Rule: If a backslash is not being used to escape a character,
// then the backslash MUST be escaped, i.e., the single backslash
// must occur only when preceding a comma.
fact Every_Literal_Backslash_Escaped {
all c: Text.firstChar.*next | (c in Backslash) => (some c.next) and (c.next in Text.firstChar.*next) and (c.next in Comma)
}
来源:https://stackoverflow.com/questions/47168337/is-this-alloy-model-cheating