aboutsummaryrefslogtreecommitdiff
path: root/Map/Business
diff options
context:
space:
mode:
authorRuben Beltran del Rio <git@r.bdr.sh>2025-08-01 15:32:00 +0200
committerRuben Beltran del Rio <git@r.bdr.sh>2025-08-01 15:32:00 +0200
commit143f2bbb517c9f25b99d00a16d9850dbdbd09ae1 (patch)
treec3b4267286934436a20a95e0ae29297bd1097771 /Map/Business
parentb1d551ddcf05a9251814418e1b8fcf59afdb33bc (diff)
Add state tracking to better handle note text parsing
Diffstat (limited to 'Map/Business')
-rw-r--r--Map/Business/WmapParser/Lexer.swift79
1 files changed, 73 insertions, 6 deletions
diff --git a/Map/Business/WmapParser/Lexer.swift b/Map/Business/WmapParser/Lexer.swift
index 4b5659e..93ba712 100644
--- a/Map/Business/WmapParser/Lexer.swift
+++ b/Map/Business/WmapParser/Lexer.swift
@@ -14,11 +14,18 @@
// along with this program. If not, see https://map.tranquil.systems.
extension Wmap {
class Lexer {
+ private enum LexerState {
+ case normal
+ case afterNoteKeyword
+ case inNotePosition(tokensNeeded: Int) // tracks: leftParen(1), number(2), comma(3), number(4), rightParen(5)
+ case expectingText
+ }
+
let input: String
private var current: String.Index
private var line = 1
private var column = 1
- private var expectingText = false
+ private var state: LexerState = .normal
init(_ input: String) {
self.input = input
@@ -37,16 +44,23 @@ extension Wmap {
)
}
+ // Handle text scanning before character-specific parsing
+ if case .expectingText = state {
+ state = .normal // Reset after scanning text
+ return scanText()
+ }
+
let char = input[current].lowercased().first!
let pos = currentPosition()
let tokenStart = current
switch char {
case "\n", "\r":
- expectingText = false // Reset expectingText on newline
+ state = .normal // Reset state on newline
return scanLineEnding()
case "(":
+ updateStateForToken(.leftParen)
advance()
return Token(
type: .leftParen,
@@ -56,6 +70,7 @@ extension Wmap {
)
case ")":
+ updateStateForToken(.rightParen)
advance()
return Token(
type: .rightParen,
@@ -68,6 +83,7 @@ extension Wmap {
return scanBracketedToken()
case ",":
+ updateStateForToken(.comma)
advance()
return Token(
type: .comma,
@@ -115,12 +131,14 @@ extension Wmap {
}
case "0"..."9", ".":
- return scanNumber()
+ let numberToken = scanNumber()
+ updateStateForToken(.realNumber)
+ return numberToken
default:
// If we're expecting text, scan as text instead of vertex label
- if expectingText {
- expectingText = false // Reset after scanning text
+ if case .expectingText = state {
+ state = .normal // Reset after scanning text
return scanText()
}
@@ -130,6 +148,55 @@ extension Wmap {
}
}
+ private func updateStateForToken(_ tokenType: TokenType) {
+ switch state {
+ case .normal:
+ // No state changes needed for normal parsing
+ break
+
+ case .afterNoteKeyword:
+ if tokenType == .leftParen {
+ state = .inNotePosition(tokensNeeded: 1) // Expecting: number, comma, number, rightParen
+ } else {
+ state = .normal // Invalid sequence, reset
+ }
+
+ case .inNotePosition(let tokensNeeded):
+ switch tokensNeeded {
+ case 1: // Expecting first number
+ if tokenType == .realNumber {
+ state = .inNotePosition(tokensNeeded: 2)
+ } else {
+ state = .normal
+ }
+ case 2: // Expecting comma
+ if tokenType == .comma {
+ state = .inNotePosition(tokensNeeded: 3)
+ } else {
+ state = .normal
+ }
+ case 3: // Expecting second number
+ if tokenType == .realNumber {
+ state = .inNotePosition(tokensNeeded: 4)
+ } else {
+ state = .normal
+ }
+ case 4: // Expecting right paren
+ if tokenType == .rightParen {
+ state = .expectingText // Complete position sequence, now expect text
+ } else {
+ state = .normal
+ }
+ default:
+ state = .normal
+ }
+
+ case .expectingText:
+ // Text has been consumed, reset to normal
+ state = .normal
+ }
+ }
+
func scanText() -> Token {
let pos = currentPosition()
@@ -230,7 +297,7 @@ extension Wmap {
switch lowercaseContent {
case "note":
- expectingText = true // Set expectingText when we return a note keyword
+ state = .afterNoteKeyword // Set state to track note parsing sequence
return Token(
type: .noteKeyword,
value: "[Note]",