I have been writing my CSS engine.

[sorry this reply might be a little off-topic here]

Long period before, someone in this mailing list asked if their are user
editable configuration file formats that can be used in real world
applications. `info.rkt` might be a choice but it is not designed for the
purpose. Finally I choose the syntax of CSS to achieve the goal because it
is elegant and expressive enough, although I cannot say I like it, it is
the only choice for web front-end guys.

As I have mentioned before, Scribble has already acted as a great and
powerful preprocessor, I think therefore there is no much necessary to
write a CSS front-end with s-exp looking in practice.

At the beginning of the task, I have struggled to work with the syntax
object (yes, it is one of the core essentials that make Racket different),
however it is hard to trace the datatypes of CSS itself (and
case-sensitivity), this is even more painful in Typed Racket. Thus, I think
write my own parser along with datatypes and exn trees is a better choice.

Meanwhile I have finished the engine of CSS syntaxes, grammars and
computation modeling(which is the supplement of what CSS preprocessors do),
and trying to make CSS interact with Racket efficiently. BTW, CSS is not
good architected as a programming language, I am not sure if I would keep
following their specs(I mean the language parts, I don't care the applied
parts), it is becoming too complicated but does not make much sense.

One of the major reasons I started this project is I need an expressive way
to describe (desktop) applications in Racket, maybe in the future I will
release a CSS-based GUI frameworks. Finally I still need to find a more
efficient computation model because this engine is running in the runtime,
after upgrading to Racket 6.7, it's surprisingly slower than before...

On Fri, Oct 28, 2016 at 3:17 AM, <lfacc...@jhu.edu> wrote:

> Hi, all.
>
> I am working on an embedded DSL for CSS in Racket. I want to get feedback
> from
> the community regarding the project’s goals and my choice of tools for
> implementing it.
>
>
> LANGUAGE
>
> I want to use Racket to generate CSS for me. I am not interested in a
> “#lang”
> language, but in a DSL that lives embedded in the code. In particular, I
> want
> “quote” and “unquote”. The best I can think of is something like:
>
>   (define main-background-color #'red)
>   (define the-css
>     #`([body #:background-color #,main-background-color]))
>   (css-expr->string the-css) ;; => "body{background-color:red;}"
>
> Note the explicit use of syntax objects. They allow for arbitrary “quote”
> and
> “unquote” and preserve source location information, which improves the
> quality
> of error messages. This is the best solution I could find, but I recognize
> it is
> unusual—I cannot name a single other example of embedded DSL in Racket that
> operates with syntax objects directly. Can you think of something better?
>
>
> COMPILER FRONT END
>
> I want good error messages, so I am using “syntax-parse”. I defined the
> concrete
> syntax tree in terms of syntax classes—each production rule on the
> context-free
> grammar for the concrete syntax tree is a “syntax-parse” syntax class. For
> example, the following defines a “stylesheet” as a list of “rules”:
>
>   (define-syntax-class stylesheet
>     (pattern (rule:rule ...)))
>
> The abstract syntax tree are typed structs, because I want to benefit from
> the
> correctness guarantees of Typed Racket. For example, the following is a
> struct
> for “stylesheets”:
>
>   (struct stylesheet ([rules : (Listof rule)]) #:transparent)
>
> Then, the parser uses “syntax-parse” with the syntax classes to generate
> the
> typed structs. For example, the following is a parser rule for
> “stylesheets”:
>
>   (define (parse/stylesheet expression)
>     (syntax-parse expression
>       [stylesheet:stylesheet
>        (extended:stylesheet (map parse/rule
>                                  (syntax->list #'(stylesheet.rule
> ...))))]))
>
> With this approach, I get a combination of good parsing error messages and
> typed
> structures to work on the compiler back end. But there is no
> “syntax-parse” in
> Typed Racket, so the parser module must be untyped. The interaction between
> untyped (compiler front end) and typed (compiler back end) modules leads to
> performance penalties. Overall, the whole architecture feels awkward, I
> feel
> like I am fighting the tools. Can you think of a better solution?
>
>
> COMPILER BACK END
>
> I use the typed structures in a module that concatenates strings to form
> CSS. This is the part I am happiest about, but I accept suggestions of more
> principled approaches than carefully constructed calls to “string-append”
> and
> “string-join”.
>
>
> OPINION
>
> My inspiration were the DSLs from http://www.cliki.net/CSS. I could not
> find a
> Racket equivalent. The following is an example of what the language looks
> like,
> recreating the CSS from http://bettermotherfuckingwebsite.com/:
>
>   ([body
>     {#:margin (40px auto)
>      #:max-width 650px
>      #:line-height 1.6
>      #:font-size 18px
>      #:color |#444|
>      #:padding (0 10px)}]
>    [h1 h2 h3
>        {#:line-height 1.2}])
>
>    ;; => body{margin:40px auto;…
>
> Furthermore, I implemented some ideas that I borrowed from other CSS
> preprocessors such as SASS/Less. For example, the language supports nested
> declarations and attributes, appropriately unnesting them when generating
> the
> CSS output. What I like about embedding this DSL in Racket is that some of
> the
> preprocessors’ features are free. For example, CSS variables and mixins
> are just
> “unquote” in Racket.
>
> I am using this DSL to build my website in Pollen, and so far I am happy
> with
> the results. I am envisioning more principled approach to CSS than
> concatenating
> strings, which other (excellent) projects do. For example, see Typography
> for
> Lawyers at
> https://github.com/mbutterick/pollen-tfl/blob/
> 1267be5bd002d4d0fe09aaef89b4089147128841/styles.css.pp.
>
> Is this something that interests you too? How do you think I can make this
> project better and more useful to the community?
>
> * * *
>
> Thank you very much for your attention and for the feedback.
>
> --
> You received this message because you are subscribed to the Google Groups
> "Racket Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to racket-users+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google Groups 
"Racket Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to racket-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to