diff options
author | bptato <nincsnevem662@gmail.com> | 2024-12-07 20:53:36 +0100 |
---|---|---|
committer | bptato <nincsnevem662@gmail.com> | 2024-12-07 20:53:36 +0100 |
commit | 8c0efdda8b3a68e2de60e3333adde5beb90a8dd8 (patch) | |
tree | 5d06a3c74025c0d8a660737722c8b1d67009c2e5 | |
parent | a9d56468cec3ecfcc5a11a5b35b5c11558e8c69a (diff) | |
download | chawan-8c0efdda8b3a68e2de60e3333adde5beb90a8dd8.tar.gz |
cssparser: misc cleanup
another case of "the object model was unnecessarily complex"
-rw-r--r-- | src/css/cssparser.nim | 182 | ||||
-rw-r--r-- | src/css/sheet.nim | 2 | ||||
-rw-r--r-- | src/html/dom.nim | 4 |
3 files changed, 66 insertions, 122 deletions
diff --git a/src/css/cssparser.nim b/src/css/cssparser.nim index 9c8adbbd..9ca1ea44 100644 --- a/src/css/cssparser.nim +++ b/src/css/cssparser.nim @@ -14,10 +14,9 @@ type CSSTokenizerState = object at: int buf: string - curr: char CSSParseState = object - tokens: seq[CSSParsedItem] + tokens: seq[CSSComponentValue] at: int tflaga = enum @@ -26,8 +25,7 @@ type tflagb* = enum tflagbInteger, tflagbNumber - CSSParsedItem* = ref object of RootObj - CSSComponentValue* = ref object of CSSParsedItem + CSSComponentValue* = ref object of RootObj CSSToken* = ref object of CSSComponentValue case t*: CSSTokenType @@ -42,7 +40,7 @@ type unit*: string else: discard - CSSRule* = ref object of CSSParsedItem + CSSRule* = ref object of CSSComponentValue prelude*: seq[CSSComponentValue] oblock*: CSSSimpleBlock @@ -70,7 +68,7 @@ type CSSAnB* = tuple[A, B: int] # For debugging -proc `$`*(c: CSSParsedItem): string = +proc `$`*(c: CSSComponentValue): string = if c of CSSToken: let c = CSSToken(c) case c.t: @@ -142,16 +140,16 @@ proc `$`*(c: CSSParsedItem): string = result &= $CSSRule(c).prelude & "\n" result &= $CSSRule(c).oblock -func `==`*(a: CSSParsedItem, b: CSSTokenType): bool = +func `==`*(a: CSSComponentValue; b: CSSTokenType): bool = return a of CSSToken and CSSToken(a).t == b const IdentStart = AsciiAlpha + NonAscii + {'_'} const Ident = IdentStart + AsciiDigit + {'-'} proc consume(state: var CSSTokenizerState): char = - state.curr = state.buf[state.at] + let c = state.buf[state.at] inc state.at - return state.curr + return c proc seek(state: var CSSTokenizerState; n: int) = state.at += n @@ -174,19 +172,19 @@ proc has(state: var CSSTokenizerState; i: int = 0): bool = proc isValidEscape(a, b: char): bool = return a == '\\' and b != '\n' -proc isValidEscape(state: var CSSTokenizerState): bool = - return state.has() and isValidEscape(state.curr, state.peek()) +proc isValidEscape(state: var CSSTokenizerState; c: char): bool = + return state.has() and isValidEscape(c, state.peek()) # current + next + next(1) -proc startsWithIdentSequence(state: var CSSTokenizerState): bool = - case state.curr +proc startsWithIdentSequence(state: var CSSTokenizerState; c: char): bool = + case c of '-': return state.has() and state.peek() in IdentStart + {'-'} or - state.has(1) and state.isValidEscape() + state.has(1) and state.isValidEscape(c) of IdentStart: return true of '\\': - return state.isValidEscape() + return state.isValidEscape(c) else: return false @@ -252,9 +250,8 @@ proc consumeEscape(state: var CSSTokenizerState): string = else: return $c #NOTE this assumes the caller doesn't care about non-ascii -proc consumeString(state: var CSSTokenizerState): CSSToken = +proc consumeString(state: var CSSTokenizerState; ending: char): CSSToken = var s = "" - let ending = state.curr while state.has(): let c = state.consume() case c @@ -278,7 +275,7 @@ proc consumeIdentSequence(state: var CSSTokenizerState): string = var s = "" while state.has(): let c = state.consume() - if state.isValidEscape(): + if state.isValidEscape(c): s &= state.consumeEscape() elif c in Ident: s &= c @@ -332,12 +329,11 @@ proc consumeNumericToken(state: var CSSTokenizerState): CSSToken = proc consumeBadURL(state: var CSSTokenizerState) = while state.has(): - case state.consume() - of ')': - return - elif state.isValidEscape(): + let c = state.consume() + if c == ')': + break + if state.isValidEscape(c): discard state.consumeEscape() - else: discard const NonPrintable = { '\0'..char(0x08), '\v', char(0x0E)..char(0x1F), char(0x7F) @@ -364,8 +360,7 @@ proc consumeURL(state: var CSSTokenizerState): CSSToken = state.consumeBadURL() return CSSToken(t: cttBadUrl) of '\\': - state.reconsume() - if state.isValidEscape(): + if state.isValidEscape(c): res.value &= state.consumeEscape() else: state.consumeBadURL() @@ -409,13 +404,18 @@ proc consumeToken(state: var CSSTokenizerState): CSSToken = state.skipWhitespace() return CSSToken(t: cttWhitespace) of '"', '\'': - return consumeString(state) + return consumeString(state, c) of '#': - if state.has() and state.peek() in Ident or state.isValidEscape(): - result = CSSToken(t: cttHash) - if state.startsWithIdentSequence(): - result.tflaga = tflagaId - result.value = consumeIdentSequence(state) + if state.has() and state.peek() in Ident or state.isValidEscape(c): + let flag = if state.startsWithIdentSequence(c): + tflagaId + else: + tflagaUnrestricted + return CSSToken( + t: cttHash, + value: state.consumeIdentSequence(), + tflaga: flag + ) else: state.reconsume() return CSSToken(t: cttDelim, cvalue: state.consumeRChar()) @@ -438,7 +438,7 @@ proc consumeToken(state: var CSSTokenizerState): CSSToken = if state.has(1) and state.peek() == '-' and state.peek(1) == '>': state.seek(2) return CSSToken(t: cttCdc) - elif state.startsWithIdentSequence(): + elif state.startsWithIdentSequence(c): state.reconsume() return state.consumeIdentLikeToken() else: @@ -466,7 +466,7 @@ proc consumeToken(state: var CSSTokenizerState): CSSToken = return CSSToken(t: cttDelim, cvalue: c) of '[': return CSSToken(t: cttLbracket) of '\\': - if state.isValidEscape(): + if state.isValidEscape(c): state.reconsume() return state.consumeIdentLikeToken() else: @@ -482,7 +482,7 @@ proc consumeToken(state: var CSSTokenizerState): CSSToken = state.reconsume() return CSSToken(t: cttDelim, cvalue: state.consumeRChar()) -proc tokenizeCSS*(ibuf: string): seq[CSSParsedItem] = +proc tokenizeCSS(ibuf: string): seq[CSSComponentValue] = result = @[] var state = CSSTokenizerState(buf: ibuf) while state.has(): @@ -490,17 +490,17 @@ proc tokenizeCSS*(ibuf: string): seq[CSSParsedItem] = if state.has(): result.add(state.consumeToken()) -proc consume(state: var CSSParseState): CSSParsedItem = +proc consume(state: var CSSParseState): CSSComponentValue = result = state.tokens[state.at] inc state.at proc reconsume(state: var CSSParseState) = dec state.at -func has(state: CSSParseState; i: int = 0): bool = - return state.at + i < state.tokens.len +func has(state: CSSParseState): bool = + return state.at < state.tokens.len -func peek(state: CSSParseState): CSSParsedItem = +func peek(state: CSSParseState): CSSComponentValue = return state.tokens[state.at] proc skipWhitespace(state: var CSSParseState) = @@ -518,7 +518,7 @@ proc consumeSimpleBlock(state: var CSSParseState; tok: CSSToken): of cttLbracket: ending = cttRbracket else: doAssert false result = CSSSimpleBlock(token: tok) - while state.at < state.tokens.len: + while state.has(): let tok = state.consume() if tok == ending: break @@ -531,7 +531,7 @@ proc consumeSimpleBlock(state: var CSSParseState; tok: CSSToken): proc consumeFunction(state: var CSSParseState): CSSFunction = let t = CSSToken(state.consume()) let res = CSSFunction(name: t.value) - while state.at < state.tokens.len: + while state.has(): let t = state.consume() if t == cttRparen: break @@ -546,7 +546,7 @@ proc consumeComponentValue(state: var CSSParseState): CSSComponentValue = elif t == cttFunction: state.reconsume() return state.consumeFunction() - return CSSComponentValue(t) + return t proc consumeQualifiedRule(state: var CSSParseState): Option[CSSQualifiedRule] = var r = CSSQualifiedRule() @@ -566,7 +566,7 @@ proc consumeQualifiedRule(state: var CSSParseState): Option[CSSQualifiedRule] = proc consumeAtRule(state: var CSSParseState): CSSAtRule = let t = CSSToken(state.consume()) result = CSSAtRule(name: t.value) - while state.at < state.tokens.len: + while state.has(): let t = state.consume() if t of CSSSimpleBlock: result.oblock = CSSSimpleBlock(t) @@ -612,34 +612,15 @@ proc consumeDeclaration(state: var CSSParseState): Option[CSSDeclaration] = decl.value.setLen(decl.value.len - 1) return some(decl) -#> Note: Despite the name, this actually parses a mixed list of declarations -#> and at-rules, as CSS 2.1 does for @page. Unexpected at-rules (which could be -#> all of them, in a given context) are invalid and should be ignored by the -#> consumer. -#So we have two versions, one with at rules and one without. -proc consumeDeclarations(state: var CSSParseState): seq[CSSParsedItem] = - while state.has(): - let t = state.consume() - if t == cttWhitespace or t == cttSemicolon: - continue - elif t == cttAtKeyword: - state.reconsume() - result.add(state.consumeAtRule()) - elif t == cttIdent: - var tempList: seq[CSSParsedItem] - tempList.add(CSSToken(t)) - while state.has() and state.peek() != cttSemicolon: - tempList.add(state.consumeComponentValue()) - var tempState = CSSParseState(at: 0, tokens: tempList) - let decl = tempState.consumeDeclaration() - if decl.isSome: - result.add(decl.get) - else: - state.reconsume() - if state.peek() != cttSemicolon: - discard state.consumeComponentValue() - -proc consumeDeclarations2(state: var CSSParseState): seq[CSSDeclaration] = +# > Note: Despite the name, this actually parses a mixed list of +# > declarations and at-rules, as CSS 2.1 does for @page. Unexpected +# > at-rules (which could be all of them, in a given context) are +# > invalid and should be ignored by the consumer. +# +# Currently we never use nested at-rules, so the result of consumeAtRule +# is just discarded. This should be changed if we ever need nested at +# rules (e.g. add a flag to include at rules). +proc consumeDeclarations(state: var CSSParseState): seq[CSSDeclaration] = result = @[] while state.has(): let t = state.consume() @@ -647,11 +628,9 @@ proc consumeDeclarations2(state: var CSSParseState): seq[CSSDeclaration] = continue elif t == cttAtKeyword: state.reconsume() - discard state.consumeAtRule() + discard state.consumeAtRule() # see above elif t == cttIdent: - var tempList: seq[CSSParsedItem] = @[] - let tok = CSSToken(t) - tempList.add(tok) + var tempList = @[t] while state.has() and state.peek() != cttSemicolon: tempList.add(state.consumeComponentValue()) var tempState = CSSParseState(at: 0, tokens: tempList) @@ -665,7 +644,7 @@ proc consumeDeclarations2(state: var CSSParseState): seq[CSSDeclaration] = proc consumeListOfRules(state: var CSSParseState; topLevel = false): seq[CSSRule] = - while state.at < state.tokens.len: + while state.has(): let t = state.consume() if t == cttWhitespace: continue @@ -689,16 +668,14 @@ proc parseStylesheet(state: var CSSParseState): CSSRawStylesheet = return CSSRawStylesheet(value: state.consumeListOfRules(true)) proc parseStylesheet*(ibuf: string): CSSRawStylesheet = - var state = CSSParseState() - state.tokens = tokenizeCSS(ibuf) + var state = CSSParseState(tokens: tokenizeCSS(ibuf)) return state.parseStylesheet() proc parseListOfRules(state: var CSSParseState): seq[CSSRule] = return state.consumeListOfRules() proc parseListOfRules*(cvals: seq[CSSComponentValue]): seq[CSSRule] = - var state = CSSParseState() - state.tokens = cast[seq[CSSParsedItem]](cvals) + var state = CSSParseState(tokens: cvals) return state.parseListOfRules() proc parseRule(state: var CSSParseState): DOMResult[CSSRule] = @@ -718,48 +695,15 @@ proc parseRule(state: var CSSParseState): DOMResult[CSSRule] = return ok(res) proc parseRule*(ibuf: string): DOMResult[CSSRule] = - var state = CSSParseState() - state.tokens = tokenizeCSS(ibuf) + var state = CSSParseState(tokens: tokenizeCSS(ibuf)) return state.parseRule() -proc parseDeclaration(state: var CSSParseState): DOMResult[CSSDeclaration] = - state.skipWhitespace() - if not state.has() or state.peek() != cttIdent: - return errDOMException("No ident token found", "SyntaxError") - let d = state.consumeDeclaration() - if d.isSome: - return ok(d.get) - return errDOMException("No declaration found", "SyntaxError") - -proc parseDeclaration*(ibuf: string): DOMResult[CSSDeclaration] = - var state = CSSParseState() - state.tokens = tokenizeCSS(ibuf) - return state.parseDeclaration() - -proc parseDeclarations(state: var CSSParseState): seq[CSSParsedItem] = - return state.consumeDeclarations() - -proc parseDeclarations*(cvals: seq[CSSComponentValue]): - seq[CSSParsedItem] = - var state = CSSParseState(tokens: cast[seq[CSSParsedItem]](cvals)) +proc parseDeclarations*(cvals: seq[CSSComponentValue]): seq[CSSDeclaration] = + var state = CSSParseState(tokens: cvals) return state.consumeDeclarations() -proc parseDeclarations*(ibuf: string): seq[CSSParsedItem] = - var state = CSSParseState() - state.tokens = tokenizeCSS(ibuf) - return state.parseDeclarations() - -proc parseDeclarations2(state: var CSSParseState): seq[CSSDeclaration] = - return state.consumeDeclarations2() - -proc parseDeclarations2*(cvals: seq[CSSComponentValue]): - seq[CSSDeclaration] = - var state = CSSParseState(tokens: cast[seq[CSSParsedItem]](cvals)) - return state.consumeDeclarations2() - -proc parseDeclarations2*(ibuf: string): seq[CSSDeclaration] = - var state = CSSParseState(tokens: tokenizeCSS(ibuf)) - return state.parseDeclarations2() +proc parseDeclarations*(ibuf: string): seq[CSSDeclaration] = + return parseDeclarations(tokenizeCSS(ibuf)) proc parseComponentValue(state: var CSSParseState): DOMResult[CSSComponentValue] = @@ -799,7 +743,7 @@ proc parseCommaSepComponentValues(state: var CSSParseState): proc parseCommaSepComponentValues*(cvals: seq[CSSComponentValue]): seq[seq[CSSComponentValue]] = - var state = CSSParseState(tokens: cast[seq[CSSParsedItem]](cvals)) + var state = CSSParseState(tokens: cvals) return state.parseCommaSepComponentValues() proc parseAnB*(state: var CSSParseState): Option[CSSAnB] = @@ -953,6 +897,6 @@ proc parseAnB*(state: var CSSParseState): Option[CSSAnB] = return none(CSSAnB) proc parseAnB*(cvals: seq[CSSComponentValue]): (Option[CSSAnB], int) = - var state = CSSParseState(tokens: cast[seq[CSSParsedItem]](cvals)) + var state = CSSParseState(tokens: cvals) let anb = state.parseAnB() return (anb, state.at) diff --git a/src/css/sheet.nim b/src/css/sheet.nim index e55b947e..248033af 100644 --- a/src/css/sheet.nim +++ b/src/css/sheet.nim @@ -181,7 +181,7 @@ proc addRule(stylesheet: CSSStylesheet; rule: CSSQualifiedRule) = if sels.len > 0: var normalVals: seq[CSSComputedEntry] = @[] var importantVals: seq[CSSComputedEntry] = @[] - let decls = rule.oblock.value.parseDeclarations2() + let decls = rule.oblock.value.parseDeclarations() for decl in decls: let vals = parseComputedValues(decl.name, decl.value) if decl.important: diff --git a/src/html/dom.nim b/src/html/dom.nim index 1cb0a672..fe501029 100644 --- a/src/html/dom.nim +++ b/src/html/dom.nim @@ -3204,8 +3204,8 @@ proc delAttr(element: Element; i: int; keep = false) = proc newCSSStyleDeclaration(element: Element; value: string): CSSStyleDeclaration = - let inlineRules = value.parseDeclarations2() - var decls: seq[CSSDeclaration] + let inlineRules = value.parseDeclarations() + var decls: seq[CSSDeclaration] = @[] for rule in inlineRules: if rule.name.isSupportedProperty(): decls.add(rule) |