[MTMathListBuilder] add support for some \not operators

This commit is contained in:
Nicolas Guillot
2025-09-30 09:51:01 +02:00
parent 4dcc7800d5
commit 5530f3910f

View File

@@ -94,6 +94,42 @@ public struct MTMathListBuilder {
currentCharIndex = string.index(before: currentCharIndex) currentCharIndex = string.index(before: currentCharIndex)
} }
} }
// Peek at next command without consuming it (for \not lookahead)
mutating func peekNextCommand() -> String {
let savedIndex = currentCharIndex
skipSpaces()
guard hasCharacters else {
currentCharIndex = savedIndex
return ""
}
let char = getNextCharacter()
let command: String
if char == "\\" {
command = readCommand()
} else {
command = ""
}
// Restore position
currentCharIndex = savedIndex
return command
}
// Consume the next command (after peeking)
mutating func consumeNextCommand() {
skipSpaces()
guard hasCharacters else { return }
let char = getNextCharacter()
if char == "\\" {
_ = readCommand()
}
}
mutating func expectCharacter(_ ch: Character) -> Bool { mutating func expectCharacter(_ ch: Character) -> Bool {
MTAssertNotSpace(ch) MTAssertNotSpace(ch)
@@ -127,6 +163,24 @@ public struct MTMathListBuilder {
.script: "scriptstyle", .script: "scriptstyle",
.scriptOfScript: "scriptscriptstyle" .scriptOfScript: "scriptscriptstyle"
] ]
// Comprehensive mapping of \not command combinations to Unicode negated symbols
public static let notCombinations: [String: String] = [
// Primary targets (user requested)
"equiv": "\u{2262}", // Not equivalent
"subset": "\u{2284}", // Not subset
"in": "\u{2209}", // Not element of
// Additional standard negations
"sim": "\u{2241}", // Not similar
"approx": "\u{2249}", // Not approximately equal
"cong": "\u{2247}", // Not congruent
"parallel": "\u{2226}", // Not parallel
"subseteq": "\u{2288}", // Not subset or equal
"supset": "\u{2285}", // Not superset
"supseteq": "\u{2289}", // Not superset or equal
"=": "\u{2260}", // Not equal (alternative to \neq)
]
init(string: String) { init(string: String) {
self.error = nil self.error = nil
@@ -644,6 +698,18 @@ public struct MTMathListBuilder {
inner.innerList = innerList inner.innerList = innerList
return inner return inner
} else if command == "not" {
// Handle \not command with lookahead for comprehensive negation support
let nextCommand = self.peekNextCommand()
if let negatedUnicode = Self.notCombinations[nextCommand] {
self.consumeNextCommand() // Remove base symbol from stream
return MTMathAtom(type: .relation, value: negatedUnicode)
} else {
let errorMessage = "Unsupported \\not\\\(nextCommand) combination"
self.setError(.invalidCommand, message: errorMessage)
return nil
}
} else { } else {
let errorMessage = "Invalid command \\\(command)" let errorMessage = "Invalid command \\\(command)"
self.setError(.invalidCommand, message:errorMessage) self.setError(.invalidCommand, message:errorMessage)