1#include "parser.h"
 2
 3#include <wctype.h>
 4
 5enum TokenType {
 6    DESCENDANT_OP,
 7    PSEUDO_CLASS_SELECTOR_COLON,
 8    ERROR_RECOVERY,
 9};
10
11static inline void advance(TSLexer *lexer) { lexer->advance(lexer, false); }
12
13static inline void skip(TSLexer *lexer) { lexer->advance(lexer, true); }
14
15void *tree_sitter_css_external_scanner_create() { return NULL; }
16
17void tree_sitter_css_external_scanner_destroy(void *payload) {}
18
19unsigned tree_sitter_css_external_scanner_serialize(void *payload, char *buffer) { return 0; }
20
21void tree_sitter_css_external_scanner_deserialize(void *payload, const char *buffer, unsigned length) {}
22
23bool tree_sitter_css_external_scanner_scan(void *payload, TSLexer *lexer, const bool *valid_symbols) {
24    if (valid_symbols[ERROR_RECOVERY]) {
25        return false;
26    }
27
28    if (iswspace(lexer->lookahead) && valid_symbols[DESCENDANT_OP]) {
29        lexer->result_symbol = DESCENDANT_OP;
30
31        lexer->advance(lexer, true);
32        while (iswspace(lexer->lookahead)) {
33            lexer->advance(lexer, true);
34        }
35        lexer->mark_end(lexer);
36
37        if (lexer->lookahead == '#' || lexer->lookahead == '.' || lexer->lookahead == '[' || lexer->lookahead == '-' ||
38            lexer->lookahead == '*' || iswalnum(lexer->lookahead)) {
39            return true;
40        }
41
42        if (lexer->lookahead == ':') {
43            lexer->advance(lexer, false);
44            if (iswspace(lexer->lookahead)) {
45                return false;
46            }
47            for (;;) {
48                if (lexer->lookahead == ';' || lexer->lookahead == '}' || lexer->eof(lexer)) {
49                    return false;
50                }
51                if (lexer->lookahead == '{') {
52                    return true;
53                }
54                lexer->advance(lexer, false);
55            }
56        }
57    }
58
59    if (valid_symbols[PSEUDO_CLASS_SELECTOR_COLON]) {
60        while (iswspace(lexer->lookahead)) {
61            lexer->advance(lexer, true);
62        }
63        if (lexer->lookahead == ':') {
64            advance(lexer);
65            if (lexer->lookahead == ':') {
66                return false;
67            }
68            lexer->mark_end(lexer);
69            // We need a { to be a pseudo class selector, a ; indicates a property
70            while (lexer->lookahead != ';' && lexer->lookahead != '\'' && lexer->lookahead != '}' &&
71                   !lexer->eof(lexer)) {
72                advance(lexer);
73                if (lexer->lookahead == '{') {
74                    lexer->result_symbol = PSEUDO_CLASS_SELECTOR_COLON;
75                    return true;
76                }
77            }
78            return false;
79        }
80    }
81
82    return false;
83}