require c-comment

# Eat erroneous statement; stop at ; or \n
syntax .css-statementerror

state error
    char ";\n" END code
    eat this

# Eat erroneous selector; stop at whitespace or {
syntax .css-selectorerror

state error
    char -n " \t\n\r{" this
    noeat END

# Hex escape: [0-9a-fA-F]{1,6}
# One hex digit already eaten
# Can be terminated with whitespace character that is skipped
syntax .css-hex

state hex1 special
    char 0-9a-fA-F hex2
    noeat ws

state hex2 special
    char 0-9a-fA-F hex3
    noeat ws

state hex3 special
    char 0-9a-fA-F hex4
    noeat ws

state hex4 special
    char 0-9a-fA-F hex5
    noeat ws

state hex5 special
    char 0-9a-fA-F ws special
    noeat ws

state ws
    # Whitespace is always skipped, even if there are 6 hex digits!
    char "\t\n\r " END special
    noeat END

# Double quote
syntax .css-dq

state string
    char \" END string
    char \\ esc
    char "\n" END error
    eat this

state esc special
    # \\ + \n -> continue to next line
    char "\n\\\"" string special
    char 0-9a-fA-F .css-hex:string
    eat string error

# Single quote
syntax .css-sq

state string
    char \' END string
    char \\ esc
    char "\n" END error
    eat this

state esc special
    # \\ + \n -> continue to next line
    char "\n\\'" string special
    char 0-9a-fA-F .css-hex:string
    eat string error

syntax .css-ident

state ident
    char "a-zA-Z0-9\xa1-\xff_-" this
    noeat END

# Attribute selector [x=y], [x|=y], [x~=y]
syntax .css-attributeselector

state attributeselector code
    char -b a-zA-Z attribute
    noeat close

state attribute
    char -b a-zA-Z this
    char "|~" op
    char = value code
    noeat close

state op code
    char = value code
    eat END error

state value
    char \" .css-dq:close
    char \' .css-sq:close
    char a-zA-Z_- .css-ident:close
    noeat close

state close
    char ] END code
    eat END error

# url(...)
syntax .css-url

state url
    char \" .css-dq:close
    char \' .css-sq:close
    noeat plain

state plain code
    char ) END url
    char "\n" END error
    eat this

state close
    char ) END url
    eat END error

syntax .css-import

state import atkeyword
    char "\t\n " arg
    noeat error

state arg code
    char "\t\n " this
    char \" .css-dq:medialist
    char \' .css-sq:medialist
    str -i "url(" .css-url:medialist
    noeat error

state medialist
    char \; END code
    eat this

state error
    noeat .css-statementerror:END

syntax .css-namespace

state namespace atkeyword
    char "\t\n " arg1
    noeat error

state arg1 code
    char "\t\n " this
    str -i "url(" .css-url:namespace-end
    char a-zA-Z prefix
    noeat arg2

state prefix code
    char a-zA-Z0-9- this
    char "\t\n " arg2
    noeat error

state arg2 code
    char "\t\n " this
    char \" .css-dq:namespace-end
    char \' .css-sq:namespace-end
    str -i "url(" .css-url:namespace-end
    noeat error

state namespace-end
    char "\t\n " this
    char \; END code
    noeat error

state error
    noeat .css-statementerror:END

syntax css

state verybeginning
    # These 9 chars exactly + double quote
    str -i '@charset ' charset
    noeat start

state charset atkeyword
    char \" .css-dq:atend
    eat .css-statementerror:start

state atend code
    char "\t\n " this
    char \; start
    eat .css-statementerror:start

state start code
    char " \t\n" this
    char -b a-zA-Z maybe-element
    char . class
    char # id
    char -b : pseudo
    char [ .css-attributeselector:this
    char { block
    char 0-9_- .css-selectorerror:this
    str "/*" .c-comment:this
    char -b @ atrule
    eat this

state maybe-element
    char -b a-zA-Z0-9 this
    inlist element start tag
    char _- .css-selectorerror:start
    noeat start

state pseudo code
    char -b a-zA-Z0-9:- this
    inlist pseudoclass start
    inlist exprpseudo nth pseudoclass
    inlist pseudoelement start
    inlist pagepseudoclass start pseudoclass
    bufis -i :lang complexpseudo
    bufis -i :not complexpseudo
    noeat start

# lang(indetifier) { ... }
# not(table) { ... }
state complexpseudo pseudoclass
    char ( complexexpr
    eat .css-selectorerror:start

# nth-child(odd|even|an+b) etc.
state nth
    char ( nthexpr
    eat .css-selectorerror:start

state nthexpr expr
    char a-z0-9+- this
    char ) start expr
    eat .css-selectorerror:start

state complexexpr expr
    char ) start expr
    char -n "\n" this
    noeat start

state class
    char a-zA-Z0-9_- this
    noeat start

state id
    char a-zA-Z0-9_- this
    noeat start

state atrule code
    char -b a-zA-Z0-9_- this
    # Selectors
    inlist atkeyword start
    # @import { URI | string } [ media type, ...];
    bufis -i "@import" .css-import:start atkeyword
    # @namespace [prefix] { URI | string };
    bufis -i "@namespace" .css-namespace:start atkeyword
    bufis -i @media mediatypes atkeyword
    noeat start

state mediatypes code
    char { start
    eat this

state block code
    char " \t\n;" this
    char -b a-zA-Z- property
    char 0-9_- property-error
    char } start
    str "/*" .c-comment:this
    eat this

state property code
    char -b a-zA-Z- this
    char 0-9_ property-error
    inlist property property-end
    inlist fontfaceproperty property-end property
    # Could be unknown property
    noeat property-end

state property-end code
    char : values
    char " \t\n" this
    char ";" block
    char } start
    eat property-error

state values code
    char " \t\n" this
    char 0-9 int
    char -- - minus
    char # hexcolor
    char ";" block
    char \" .css-dq:this
    char \' .css-sq:this
    str -i "url(" .css-url:this
    char -b a-zA-Z_ value
    char } start
    str "/*" .c-comment:this
    eat this

state minus numeric
    char 0-9 int
    char . float
    noeat values

state int numeric
    char 0-9 this
    char . float
    char -b a-zA-Z% unit
    noeat values

state float numeric
    char 0-9 this
    char -b a-zA-Z% unit
    noeat values

state unit error
    char -b a-zA-Z% this
    inlist unit values numeric
    char ";" block
    char } start
    eat value-error

state value code
    char -b a-zA-Z0-9_- this
    inlist value values
    inlist color values
    inlist func func value
    noeat values

# FIXME: length must be 3 or 6
state hexcolor color
    char 0-9a-fA-F this
    char g-zG-Z_- value-error
    noeat values

state func code
    char " \t" this
    char ( params
    eat value-error

state params code
    char ) values
    char ";" block
    char } start
    eat this

state property-error error
    char a-zA-Z0-9_- this
    noeat property

state value-error error
    char a-zA-Z0-9_- this
    noeat values

list -i element \
    a abbr acronym address area b base bdo big blockquote body br \
    button caption cite code col colgroup dd del dfn div dl dt em \
    fieldset form h1 h2 h3 h4 h5 h6 head hr html i iframe img input \
    ins kbd label legend li link map meta noscript object ol optgroup \
    option p param pre q samp script select small span strong style \
    sub sup table tbody td textarea tfoot th thead title tr tt ul var \
\
    article aside audio canvas command datalist details embed figure \
    footer header hgroup keygen main mark meter nav output progress ruby \
    section time video wbr

# https://www.w3.org/Style/CSS/all-properties.en.json
list -i property \
    align-content align-items alignment-baseline align-self all \
    animation animation-delay animation-direction animation-duration \
    animation-fill-mode animation-iteration-count animation-name \
    animation-play-state animation-timing-function appearance azimuth \
    background background-attachment background-blend-mode \
    background-clip background-color background-image \
    background-image-transform background-origin background-position \
    background-repeat background-size baseline-shift block-size \
    block-step block-step-align block-step-insert block-step-round \
    block-step-size bookmark-label bookmark-level bookmark-state border \
    border-block border-block-color border-block-end \
    border-block-end-color border-block-end-style border-block-end-width \
    border-block-start border-block-start-color border-block-start-style \
    border-block-start-width border-block-style border-block-width \
    border-bottom border-bottom-color border-bottom-left-radius \
    border-bottom-right-radius border-bottom-style border-bottom-width \
    border-boundary border-collapse border-color border-image \
    border-image-outset border-image-repeat border-image-slice \
    border-image-source border-image-transform border-image-width \
    border-inline border-inline-color border-inline-end \
    border-inline-end-color border-inline-end-style \
    border-inline-end-width border-inline-start \
    border-inline-start-color border-inline-start-style \
    border-inline-start-width border-inline-style border-inline-width \
    border-left border-left-color border-left-style border-left-width \
    border-radius border-right border-right-color border-right-style \
    border-right-width border-spacing border-style border-top \
    border-top-color border-top-left-radius border-top-right-radius \
    border-top-style border-top-width border-width bottom \
    box-decoration-break box-shadow box-sizing box-snap break-after \
    break-before break-inside caption-side caret caret-animation \
    caret-color caret-shape chains clear clip clip-path clip-rule color \
    color-adjust color-interpolation-filters column-count column-fill \
    column-gap column-rule column-rule-color column-rule-style \
    column-rule-width columns column-span column-width contain content \
    continue counter-increment counter-reset counter-set cue cue-after \
    cue-before cursor direction display dominant-baseline elevation \
    empty-cells fill fill-break fill-color fill-image fill-opacity \
    fill-origin fill-position fill-repeat fill-rule fill-size filter \
    flex flex-basis flex-direction flex-flow flex-grow flex-shrink \
    flex-wrap float float-defer float-offset float-reference flood-color \
    flood-opacity flow flow-from flow-into font font-family \
    font-feature-settings font-kerning font-language-override \
    font-max-size font-min-size font-optical-sizing font-palette \
    font-presentation font-size font-size-adjust font-stretch font-style \
    font-synthesis font-variant font-variant-alternates \
    font-variant-caps font-variant-east-asian font-variant-ligatures \
    font-variant-numeric font-variant-position font-variation-settings \
    font-weight footnote-display footnote-policy gap \
    glyph-orientation-vertical grid grid-area grid-auto-columns \
    grid-auto-flow grid-auto-rows grid-column grid-column-end \
    grid-column-gap grid-column-start grid-gap grid-row grid-row-end \
    grid-row-gap grid-row-start grid-template grid-template-areas \
    grid-template-columns grid-template-rows hanging-punctuation height \
    hyphenate-character hyphenate-limit-chars hyphenate-limit-last \
    hyphenate-limit-lines hyphenate-limit-zone hyphens image-orientation \
    image-resolution initial-letter initial-letter-align \
    initial-letter-wrap inline-size inset inset-block inset-block-end \
    inset-block-start inset-inline inset-inline-end inset-inline-start \
    isolation justify-content justify-items justify-self left \
    letter-spacing lighting-color line-break line-grid line-height \
    line-height-step line-snap list-style list-style-image \
    list-style-position list-style-type margin margin-block \
    margin-block-end margin-block-start margin-bottom margin-inline \
    margin-inline-end margin-inline-start margin-left margin-right \
    margin-top marker marker-end marker-knockout-left \
    marker-knockout-right marker-mid marker-pattern marker-segment \
    marker-side marker-start marquee-direction marquee-loop \
    marquee-speed marquee-style mask mask-border mask-border-mode \
    mask-border-outset mask-border-repeat mask-border-slice \
    mask-border-source mask-border-width mask-clip mask-composite \
    mask-image mask-mode mask-origin mask-position mask-repeat mask-size \
    mask-type max-block-size max-height max-inline-size max-lines \
    max-width min-block-size min-height min-inline-size min-width \
    mix-blend-mode nav-down nav-left nav-right nav-up object-fit \
    object-position offset offset-after offset-anchor offset-before \
    offset-distance offset-end offset-path offset-position offset-rotate \
    offset-start opacity order orphans outline outline-color \
    outline-offset outline-style outline-width overflow overflow-style \
    overflow-wrap overflow-x overflow-y padding padding-block \
    padding-block-end padding-block-start padding-bottom padding-inline \
    padding-inline-end padding-inline-start padding-left padding-right \
    padding-top page page-break-after page-break-before \
    page-break-inside pause pause-after pause-before pitch pitch-range \
    place-content place-items place-self play-during position \
    presentation-level quotes region-fragment resize rest rest-after \
    rest-before richness right rotation rotation-point row-gap \
    ruby-align ruby-merge ruby-position running scrollbar-gutter \
    scroll-behavior scroll-padding scroll-padding-block \
    scroll-padding-block-end scroll-padding-block-start \
    scroll-padding-bottom scroll-padding-inline \
    scroll-padding-inline-end scroll-padding-inline-start \
    scroll-padding-left scroll-padding-right scroll-padding-top \
    scroll-snap-align scroll-snap-margin scroll-snap-margin-block \
    scroll-snap-margin-block-end scroll-snap-margin-block-start \
    scroll-snap-margin-bottom scroll-snap-margin-inline \
    scroll-snap-margin-inline-end scroll-snap-margin-inline-start \
    scroll-snap-margin-left scroll-snap-margin-right \
    scroll-snap-margin-top scroll-snap-stop scroll-snap-type \
    shape-image-threshold shape-inside shape-margin shape-outside size \
    speak speak-as speak-header speak-numeral speak-punctuation \
    speech-rate stress string-set stroke stroke-align stroke-alignment \
    stroke-break stroke-color stroke-dashadjust stroke-dasharray \
    stroke-dashcorner stroke-dash-corner stroke-dash-justify \
    stroke-dashoffset stroke-image stroke-linecap stroke-linejoin \
    stroke-miterlimit stroke-opacity stroke-origin stroke-position \
    stroke-repeat stroke-size stroke-width table-layout tab-size \
    text-align text-align-all text-align-last text-combine-upright \
    text-decoration text-decoration-color text-decoration-line \
    text-decoration-skip text-decoration-style text-emphasis \
    text-emphasis-color text-emphasis-position text-emphasis-style \
    text-indent text-justify text-orientation text-overflow text-shadow \
    text-space-collapse text-space-trim text-spacing text-transform \
    text-underline-position text-wrap top transform transform-box \
    transform-origin transition transition-delay transition-duration \
    transition-property transition-timing-function unicode-bidi \
    user-select vertical-align visibility voice-balance voice-duration \
    voice-family voice-pitch voice-range voice-rate voice-stress \
    voice-volume volume white-space widows width will-change word-break \
    word-spacing word-wrap wrap-after wrap-before wrap-flow wrap-inside \
    wrap-through writing-mode z-index

list -i value \
    absolute always armenian auto avoid baseline bidi-override blink \
    block bold bolder both bottom capitalize center circle \
    cjk-ideographic collapse compact condensed crop cross crosshair \
    dashed decimal decimal-leading-zero default disc dotted double \
    e-resize embed expanded extra-condensed extra-expanded fixed \
    georgian groove hebrew help hidden hide hiragana hiragana-iroha \
    inline inline-table inset inside italic justify katakana \
    katakana-iroha landscape large larger left lighter line-through \
    list-item lower-alpha lower-greek lower-latin lower-roman lowercase \
    ltr marker medium middle move n-resize narrower ne-resize no-repeat \
    none normal nowrap nw-resize oblique outset outside overline pointer \
    portrait pre relative repeat repeat-x repeat-y ridge right rtl run-in \
    s-resize scroll se-resize semi-condensed semi-expanded separate show \
    small small-caps smaller solid square static sub super sw-resize \
    table table-caption table-cell table-column table-column-group \
    table-footer-group table-header-group table-row table-row-group text \
    text-bottom text-top thick thin top ultra-condensed ultra-expanded \
    underline upper-alpha upper-latin upper-roman uppercase visible \
    w-resize wait wider x-large x-small xx-large xx-small

list -i color \
    aqua black blue fuchsia gray green lime maroon navy olive \
    purple red silver teal white yellow

# Simple pseudo-classes
list -i pseudoclass \
    :active :checked :disabled :empty :enabled :first-child \
    :first-of-type :focus :hover :last-child :last-of-type :link \
    :only-child :only-of-type :root :target :visited

# nth-child(odd) etc.
list -i exprpseudo :nth-child :nth-last-child :nth-last-of-type :nth-of-type

# CSS1 and CSS2 pseudo-elements can be prefixed with single colon
# CSS2.1 changed pseudo-elements start with a double colon
# support only double colon for CSS3 pseudo-elements
list -i pseudoelement \
    :after :before :first-letter :first-line \
    ::after ::before ::first-letter ::first-line \
    ::selection

# @page
list -i pagepseudoclass \
    :left :right :first

# @font-face
list -i fontfaceproperty \
    font-family font-stretch font-style font-weight src unicode-range

# %, distance, angle, time, frequency, resolution
list -i unit \
    % fr \
    ch cm em ex in mm pc pt px rem vh vw vmin vmax \
    deg grad rad turn \
    ms s \
    hz khz \
    dpcm dpi dppx

list -i func \
    attr clip counter rect rgb

# at-rules that work as selectors
list -i atkeyword @page @font-face

default keyword property
default type class id pseudoclass pseudoelement attribute
default special expr
default constant value color url
default special atkeyword
