Skip to content

Commit

Permalink
refactor: reduce constructor parameters of CssParser
Browse files Browse the repository at this point in the history
  • Loading branch information
rafaeltonholo committed Dec 19, 2024
1 parent b1f2ece commit c802f53
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 66 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import dev.tonholo.s2c.extensions.extension
import dev.tonholo.s2c.io.FileManager
import dev.tonholo.s2c.parser.ast.css.CssParser
import dev.tonholo.s2c.parser.ast.css.CssSpecificity
import dev.tonholo.s2c.parser.ast.css.consumer.CssConsumers
import dev.tonholo.s2c.parser.ast.css.syntax.node.Declaration
import dev.tonholo.s2c.parser.ast.css.syntax.node.QualifiedRule
import okio.Path
Expand Down Expand Up @@ -205,7 +206,7 @@ sealed class ImageParser(
private fun SvgRootNode.resolveStyleTags() {
rules = styles
.flatMap { style ->
val parser = CssParser(content = style.content)
val parser = CssParser(consumers = CssConsumers(style.content))
style
.resolveTree(parser)
.children
Expand All @@ -220,9 +221,6 @@ sealed class ImageParser(
}
}
}

println(rules)
// .sorted()
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,9 @@ package dev.tonholo.s2c.parser.ast.css
import dev.tonholo.s2c.lexer.Token
import dev.tonholo.s2c.lexer.css.CssTokenKind
import dev.tonholo.s2c.parser.ast.AstParser
import dev.tonholo.s2c.parser.ast.css.consumer.AtRuleConsumer
import dev.tonholo.s2c.parser.ast.css.consumer.Consumer
import dev.tonholo.s2c.parser.ast.css.consumer.DeclarationConsumer
import dev.tonholo.s2c.parser.ast.css.consumer.QualifiedRuleConsumer
import dev.tonholo.s2c.parser.ast.css.consumer.SelectorListItemConsumer
import dev.tonholo.s2c.parser.ast.css.consumer.SimpleBlockConsumer
import dev.tonholo.s2c.parser.ast.css.consumer.SimpleDeclarationBlockConsumer
import dev.tonholo.s2c.parser.ast.css.consumer.SimpleRuleBlockConsumer
import dev.tonholo.s2c.parser.ast.css.consumer.SimpleSelectorConsumer
import dev.tonholo.s2c.parser.ast.css.consumer.StyleSheetConsumer
import dev.tonholo.s2c.parser.ast.css.consumer.ValueConsumer
import dev.tonholo.s2c.parser.ast.css.consumer.CssConsumers
import dev.tonholo.s2c.parser.ast.css.syntax.CssIterator
import dev.tonholo.s2c.parser.ast.css.syntax.node.AtRule
import dev.tonholo.s2c.parser.ast.css.syntax.node.Declaration
import dev.tonholo.s2c.parser.ast.css.syntax.node.QualifiedRule
import dev.tonholo.s2c.parser.ast.css.syntax.node.Rule
import dev.tonholo.s2c.parser.ast.css.syntax.node.Selector
import dev.tonholo.s2c.parser.ast.css.syntax.node.SelectorListItem
import dev.tonholo.s2c.parser.ast.css.syntax.node.StyleSheet
import dev.tonholo.s2c.parser.ast.css.syntax.node.Value

/**
* A parser for CSS (Cascading Style Sheets) code.
Expand All @@ -32,52 +15,14 @@ import dev.tonholo.s2c.parser.ast.css.syntax.node.Value
* to handle different parts of the CSS syntax, breaking down the parsing process
* into smaller, manageable units.
*
* @param content The CSS code to be parsed.
* @param selectorConsumer A consumer responsible for parsing selectors.
* @param selectorListItemConsumer A consumer responsible for parsing selector list items.
* @param valueConsumer A consumer responsible for parsing CSS values.
* @param declarationConsumer A consumer responsible for parsing CSS declarations.
* @param declarationBlockConsumer A consumer responsible for parsing declaration blocks.
* @param qualifiedRuleConsumer A consumer responsible for parsing qualified rules.
* @param ruleBlockConsumer A consumer responsible for parsing rule blocks.
* @param atRuleConsumer A consumer responsible for parsing at-rules.
* @param styleSheetConsumer A consumer responsible for parsing the entire style sheet.
* @property consumers The consumers used to parse the CSS syntax.
*/
internal class CssParser(
private val content: String,
private val selectorConsumer: Consumer<Selector> = SimpleSelectorConsumer(content),
private val selectorListItemConsumer: Consumer<SelectorListItem> = SelectorListItemConsumer(
content,
selectorConsumer,
),
private val valueConsumer: Consumer<Value> = ValueConsumer(content),
private val declarationConsumer: Consumer<Declaration> = DeclarationConsumer(content, valueConsumer),
private val declarationBlockConsumer: SimpleBlockConsumer<Declaration> = SimpleDeclarationBlockConsumer(
content = content,
declarationConsumer = declarationConsumer,
),
private val qualifiedRuleConsumer: Consumer<QualifiedRule> = QualifiedRuleConsumer(
content = content,
selectorListItemConsumer = selectorListItemConsumer,
blockConsumer = declarationBlockConsumer,
),
private val ruleBlockConsumer: SimpleBlockConsumer<Rule> = SimpleRuleBlockConsumer(
content = content,
qualifiedRuleConsumer = qualifiedRuleConsumer,
),
private val atRuleConsumer: Consumer<AtRule> = AtRuleConsumer(
content = content,
blockConsumer = ruleBlockConsumer,
),
private val styleSheetConsumer: Consumer<StyleSheet> = StyleSheetConsumer(
content = content,
atRuleConsumer = atRuleConsumer,
qualifiedRuleConsumer = qualifiedRuleConsumer,
),
private val consumers: CssConsumers,
) : AstParser<CssTokenKind, StyleSheet> {
override fun parse(tokens: List<Token<out CssTokenKind>>): StyleSheet {
val iterator = CssIterator(tokens)
val root = styleSheetConsumer.consume(iterator = iterator)
val root = consumers.styleSheetConsumer.consume(iterator = iterator)
return root
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package dev.tonholo.s2c.parser.ast.css.consumer

import dev.tonholo.s2c.parser.ast.css.syntax.node.AtRule
import dev.tonholo.s2c.parser.ast.css.syntax.node.Declaration
import dev.tonholo.s2c.parser.ast.css.syntax.node.QualifiedRule
import dev.tonholo.s2c.parser.ast.css.syntax.node.Rule
import dev.tonholo.s2c.parser.ast.css.syntax.node.Selector
import dev.tonholo.s2c.parser.ast.css.syntax.node.SelectorListItem
import dev.tonholo.s2c.parser.ast.css.syntax.node.StyleSheet
import dev.tonholo.s2c.parser.ast.css.syntax.node.Value

/**
* DSL marker for CssConsumers DSL.
*/
@DslMarker
internal annotation class CssConsumersDslMarker

/**
* Interface defining various consumers for CSS parsing.
*
* @property selectorConsumer A consumer responsible for parsing selectors.
* @property selectorListItemConsumer A consumer responsible for parsing selector list items.
* @property valueConsumer A consumer responsible for parsing CSS values.
* @property declarationConsumer A consumer responsible for parsing CSS declarations.
* @property declarationBlockConsumer A consumer responsible for parsing declaration blocks.
* @property qualifiedRuleConsumer A consumer responsible for parsing qualified rules.
* @property ruleBlockConsumer A consumer responsible for parsing rule blocks.
* @property atRuleConsumer A consumer responsible for parsing at-rules.
* @property styleSheetConsumer A consumer responsible for parsing the entire style sheet.
*/
@CssConsumersDslMarker
internal interface CssConsumers {
val selectorConsumer: Consumer<Selector>
val selectorListItemConsumer: Consumer<SelectorListItem>
val valueConsumer: Consumer<Value>
val declarationConsumer: Consumer<Declaration>
val declarationBlockConsumer: SimpleBlockConsumer<Declaration>
val qualifiedRuleConsumer: Consumer<QualifiedRule>
val ruleBlockConsumer: SimpleBlockConsumer<Rule>
val atRuleConsumer: Consumer<AtRule>
val styleSheetConsumer: Consumer<StyleSheet>
}

/**
* Builder class for creating instances of [CssConsumers].
*/
internal class CssConsumersBuilder {
var customSelectorConsumer: Consumer<Selector>? = null
var customSelectorListItemConsumer: Consumer<SelectorListItem>? = null
var customValueConsumer: Consumer<Value>? = null
var customDeclarationConsumer: Consumer<Declaration>? = null
var customDeclarationBlockConsumer: SimpleBlockConsumer<Declaration>? = null
var customQualifiedRuleConsumer: Consumer<QualifiedRule>? = null
var customRuleBlockConsumer: SimpleBlockConsumer<Rule>? = null
var customAtRuleConsumer: Consumer<AtRule>? = null
var customStyleSheetConsumer: Consumer<StyleSheet>? = null

/**
* Builds an instance of [CssConsumers] using the provided content and custom consumers.
*
* @param content The CSS content to be parsed.
* @return An instance of [CssConsumers].
*/
fun build(content: String): CssConsumers {
val customSelectorConsumer = customSelectorConsumer ?: SimpleSelectorConsumer(content)
val customValueConsumer = customValueConsumer ?: ValueConsumer(content)
val customDeclarationConsumer = customDeclarationConsumer ?: DeclarationConsumer(
content = content,
valueConsumer = customValueConsumer,
)
val customSelectorListItemConsumer = customSelectorListItemConsumer ?: SelectorListItemConsumer(
content,
simpleSelectorConsumer = customSelectorConsumer,
)
val customDeclarationBlockConsumer = customDeclarationBlockConsumer ?: SimpleDeclarationBlockConsumer(
content = content,
declarationConsumer = customDeclarationConsumer,
)
val customQualifiedRuleConsumer = customQualifiedRuleConsumer ?: QualifiedRuleConsumer(
content = content,
selectorListItemConsumer = customSelectorListItemConsumer,
blockConsumer = customDeclarationBlockConsumer,
)
val customRuleBlockConsumer = customRuleBlockConsumer ?: SimpleRuleBlockConsumer(
content = content,
qualifiedRuleConsumer = customQualifiedRuleConsumer,
)
val customAtRuleConsumer = customAtRuleConsumer ?: AtRuleConsumer(
content = content,
blockConsumer = customRuleBlockConsumer,
)
val customStyleSheetConsumer = customStyleSheetConsumer ?: StyleSheetConsumer(
content = content,
atRuleConsumer = customAtRuleConsumer,
qualifiedRuleConsumer = customQualifiedRuleConsumer,
)

return object : CssConsumers {
override val selectorConsumer: Consumer<Selector> = customSelectorConsumer
override val selectorListItemConsumer: Consumer<SelectorListItem> = customSelectorListItemConsumer
override val valueConsumer: Consumer<Value> = customValueConsumer
override val declarationConsumer: Consumer<Declaration> = customDeclarationConsumer
override val declarationBlockConsumer: SimpleBlockConsumer<Declaration> = customDeclarationBlockConsumer
override val qualifiedRuleConsumer: Consumer<QualifiedRule> = customQualifiedRuleConsumer
override val ruleBlockConsumer: SimpleBlockConsumer<Rule> = customRuleBlockConsumer
override val atRuleConsumer: Consumer<AtRule> = customAtRuleConsumer
override val styleSheetConsumer: Consumer<StyleSheet> = customStyleSheetConsumer
}
}
}

/**
* DSL function for creating an instance of [CssConsumers] with optional custom consumers.
*
* @param content The CSS content to be parsed.
* @param builder A lambda for configuring custom consumers.
* @return An instance of [CssConsumers].
*/
@CssConsumersDslMarker
internal fun CssConsumers(content: String, builder: CssConsumersBuilder.() -> Unit = {}): CssConsumers {
return CssConsumersBuilder().apply(builder).build(content)
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package dev.tonholo.s2c.parser.ast.css
import app.cash.burst.Burst
import dev.tonholo.s2c.lexer.Token
import dev.tonholo.s2c.lexer.css.CssTokenKind
import dev.tonholo.s2c.parser.ast.css.consumer.CssConsumers
import dev.tonholo.s2c.parser.ast.css.syntax.AstParserException
import dev.tonholo.s2c.parser.ast.css.syntax.node.Block
import dev.tonholo.s2c.parser.ast.css.syntax.node.CssLocation
Expand Down Expand Up @@ -1658,7 +1659,7 @@ class CssParserTest {
Token(kind = CssTokenKind.EndOfFile, startOffset = content.length, endOffset = content.length),
)

val parser = CssParser(content)
val parser = CssParser(consumers = CssConsumers(content))

// Act
val exception = assertFailsWith<AstParserException> {
Expand Down Expand Up @@ -1694,7 +1695,7 @@ class CssParserTest {
Token(kind = CssTokenKind.EndOfFile, startOffset = 37, endOffset = 37),
)

val parser = CssParser(content)
val parser = CssParser(consumers = CssConsumers(content))

// Act
val exception = assertFailsWith<AstParserException> {
Expand All @@ -1712,7 +1713,7 @@ class CssParserTest {
tokens: List<Token<out CssTokenKind>>,
expected: StyleSheet,
) {
val astParser = CssParser(content)
val astParser = CssParser(consumers = CssConsumers(content))
val actual = astParser.parse(tokens)
assertEquals(expected, actual)
}
Expand Down

0 comments on commit c802f53

Please sign in to comment.