Serenity Operating System
at master 99 lines 3.0 kB view raw
1/* 2 * Copyright (c) 2021, Dylan Katz <dykatz@uw.edu> 3 * Copyright (c) 2022, the SerenityOS developers. 4 * 5 * SPDX-License-Identifier: BSD-2-Clause 6 */ 7 8#include <AK/Debug.h> 9#include <LibGfx/Palette.h> 10#include <LibSQL/AST/Lexer.h> 11#include <LibSQL/AST/SyntaxHighlighter.h> 12 13namespace SQL::AST { 14 15static Syntax::TextStyle style_for_token_type(Gfx::Palette const& palette, TokenType type) 16{ 17 switch (Token::category(type)) { 18 case TokenCategory::Keyword: 19 return { palette.syntax_keyword(), true }; 20 case TokenCategory::Identifier: 21 return { palette.syntax_identifier(), false }; 22 case TokenCategory::Number: 23 return { palette.syntax_number(), false }; 24 case TokenCategory::Blob: 25 case TokenCategory::String: 26 return { palette.syntax_string(), false }; 27 case TokenCategory::Operator: 28 return { palette.syntax_operator(), false }; 29 case TokenCategory::Punctuation: 30 return { palette.syntax_punctuation(), false }; 31 case TokenCategory::Invalid: 32 default: 33 return { palette.base_text(), false }; 34 } 35} 36 37bool SyntaxHighlighter::is_identifier(u64 token) const 38{ 39 auto sql_token = static_cast<TokenType>(static_cast<size_t>(token)); 40 return sql_token == TokenType::Identifier; 41} 42 43void SyntaxHighlighter::rehighlight(Palette const& palette) 44{ 45 auto text = m_client->get_text(); 46 47 Lexer lexer(text); 48 49 Vector<GUI::TextDocumentSpan> spans; 50 51 auto append_token = [&](Token const& token) { 52 if (token.value().is_empty()) 53 return; 54 GUI::TextDocumentSpan span; 55 span.range.set_start({ token.start_position().line - 1, token.start_position().column - 1 }); 56 span.range.set_end({ token.end_position().line - 1, token.end_position().column - 1 }); 57 auto style = style_for_token_type(palette, token.type()); 58 span.attributes.color = style.color; 59 span.attributes.bold = style.bold; 60 span.data = static_cast<u64>(token.type()); 61 spans.append(span); 62 63 dbgln_if(SYNTAX_HIGHLIGHTING_DEBUG, "{} @ '{}' {}:{} - {}:{}", 64 token.name(), 65 token.value(), 66 span.range.start().line(), span.range.start().column(), 67 span.range.end().line(), span.range.end().column()); 68 }; 69 70 for (;;) { 71 auto token = lexer.next(); 72 append_token(token); 73 if (token.type() == TokenType::Eof) 74 break; 75 } 76 77 m_client->do_set_spans(move(spans)); 78 79 m_has_brace_buddies = false; 80 highlight_matching_token_pair(); 81 82 m_client->do_update(); 83} 84 85Vector<SyntaxHighlighter::MatchingTokenPair> SyntaxHighlighter::matching_token_pairs_impl() const 86{ 87 static Vector<SyntaxHighlighter::MatchingTokenPair> pairs; 88 if (pairs.is_empty()) { 89 pairs.append({ static_cast<u64>(TokenType::ParenOpen), static_cast<u64>(TokenType::ParenClose) }); 90 } 91 return pairs; 92} 93 94bool SyntaxHighlighter::token_types_equal(u64 token1, u64 token2) const 95{ 96 return static_cast<TokenType>(token1) == static_cast<TokenType>(token2); 97} 98 99}