Class: Rich::SQLLexer
Overview
SQL Lexer
Constant Summary collapse
- KEYWORDS =
%w[ SELECT FROM WHERE AND OR NOT NULL IS IN LIKE BETWEEN EXISTS INSERT INTO VALUES UPDATE SET DELETE CREATE TABLE DROP ALTER INDEX VIEW TRIGGER PROCEDURE FUNCTION AS ON JOIN LEFT RIGHT INNER OUTER FULL CROSS NATURAL USING ORDER BY ASC DESC GROUP HAVING LIMIT OFFSET UNION ALL DISTINCT CASE WHEN THEN ELSE END IF BEGIN COMMIT ROLLBACK TRANSACTION PRIMARY KEY FOREIGN REFERENCES UNIQUE DEFAULT CHECK CONSTRAINT CASCADE RESTRICT TRUE FALSE GRANT REVOKE WITH RECURSIVE ].freeze
- BUILTINS =
%w[ COUNT SUM AVG MIN MAX LENGTH UPPER LOWER TRIM CONCAT SUBSTRING REPLACE COALESCE NULLIF CAST CONVERT DATE TIME DATETIME YEAR MONTH DAY HOUR MINUTE SECOND NOW CURRENT_DATE CURRENT_TIME CURRENT_TIMESTAMP ABS ROUND FLOOR CEILING POWER SQRT MOD ROW_NUMBER RANK DENSE_RANK OVER PARTITION ].freeze
- TYPES =
%w[ INT INTEGER BIGINT SMALLINT TINYINT FLOAT DOUBLE DECIMAL NUMERIC REAL CHAR VARCHAR TEXT NCHAR NVARCHAR NTEXT DATE TIME DATETIME TIMESTAMP BOOLEAN BOOL BLOB BINARY VARBINARY UUID JSON XML ].freeze
Instance Method Summary collapse
Instance Method Details
#tokenize(line, theme) ⇒ Object
857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 |
# File 'lib/rich/syntax.rb', line 857 def tokenize(line, theme) segments = [] pos = 0 while pos < line.length if line[pos].match?(/\s/) ws_end = pos ws_end += 1 while ws_end < line.length && line[ws_end].match?(/\s/) segments << Segment.new(line[pos...ws_end]) pos = ws_end next end # Comment if line[pos..pos + 1] == "--" segments << Segment.new(line[pos..], style: theme[:comment]) break end # String if line[pos] == "'" str_end = pos + 1 str_end += 1 while str_end < line.length && line[str_end] != "'" str_end = [str_end, line.length - 1].min segments << Segment.new(line[pos..str_end], style: theme[:string]) pos = str_end + 1 next end # Number if line[pos].match?(/\d/) num_end = pos num_end += 1 while num_end < line.length && line[num_end].match?(/[\d.]/) segments << Segment.new(line[pos...num_end], style: theme[:number]) pos = num_end next end # Identifier if line[pos].match?(/[a-zA-Z_]/) word_end = pos word_end += 1 while word_end < line.length && line[word_end].match?(/\w/) word = line[pos...word_end] upper_word = word.upcase style = if KEYWORDS.include?(upper_word) theme[:keyword] elsif BUILTINS.include?(upper_word) theme[:name_builtin] || theme[:name] elsif TYPES.include?(upper_word) theme[:keyword_type] || theme[:keyword] else theme[:name] end segments << Segment.new(word, style: style) pos = word_end next end # Operators if line[pos].match?(/[+\-*\/%<>=!]/) op_end = pos + 1 op_end += 1 while op_end < line.length && line[op_end].match?(/[+\-*\/%<>=!]/) segments << Segment.new(line[pos...op_end], style: theme[:operator]) pos = op_end next end # Punctuation if line[pos].match?(/[(),;.]/) segments << Segment.new(line[pos], style: theme[:punctuation]) pos += 1 next end segments << Segment.new(line[pos]) pos += 1 end segments end |