File size: 7,011 Bytes
ffc07fb | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | ! Layer 5 β Sovereign IDE Syntax Highlighting
! Query compiler + theme mapping
! Maps to: snapkitty-resonance-bridge token stream structure
MODULE sovereign_syntax
USE iso_c_binding
USE sovereign_runtime, ONLY: runtime_panic, str_intern
USE sovereign_parser, ONLY: parser_ctx_t, cst_node_t
IMPLICIT NONE
PRIVATE
! ββ Color IDs (theme slots) βββββββββββββββββββββββββββββββββββββββββββββββ
INTEGER, PARAMETER :: COLOR_DEFAULT = 0
INTEGER, PARAMETER :: COLOR_KEYWORD = 1
INTEGER, PARAMETER :: COLOR_IDENTIFIER = 2
INTEGER, PARAMETER :: COLOR_STRING = 3
INTEGER, PARAMETER :: COLOR_NUMBER = 4
INTEGER, PARAMETER :: COLOR_COMMENT = 5
INTEGER, PARAMETER :: COLOR_OPERATOR = 6
INTEGER, PARAMETER :: COLOR_TYPE = 7
INTEGER, PARAMETER :: COLOR_FUNCTION = 8
INTEGER, PARAMETER :: COLOR_ERROR = 9
INTEGER, PARAMETER :: N_COLORS = 10
! ββ Theme βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
! RGBA packed as 0xRRGGBBAA
TYPE :: theme_t
INTEGER(C_INT32_T) :: colors(N_COLORS)
LOGICAL :: worm_sealed = .FALSE.
END TYPE theme_t
! ββ Highlight span ββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
INTEGER, PARAMETER :: MAX_SPANS = 131072
TYPE :: span_t
INTEGER :: start_byte = 0
INTEGER :: end_byte = 0
INTEGER :: color_id = COLOR_DEFAULT
END TYPE span_t
TYPE :: span_list_t
TYPE(span_t) :: spans(MAX_SPANS)
INTEGER :: count = 0
END TYPE span_list_t
! ββ Query βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
INTEGER, PARAMETER :: MAX_QUERY_PATTERNS = 256
TYPE :: query_pattern_t
INTEGER(C_INT32_T) :: node_kind_id = 0
INTEGER :: color_id = COLOR_DEFAULT
END TYPE query_pattern_t
TYPE :: query_t
TYPE(query_pattern_t) :: patterns(MAX_QUERY_PATTERNS)
INTEGER :: pattern_count = 0
END TYPE query_t
PUBLIC :: syntax_init
PUBLIC :: syntax_load_theme
PUBLIC :: syntax_highlight
PUBLIC :: syntax_highlight_incremental
PUBLIC :: theme_default_sovereign_dark
CONTAINS
! ---------------------------------------------------------------------------
SUBROUTINE syntax_init()
WRITE(*,'(A)') '[syntax] init'
END SUBROUTINE syntax_init
! ---------------------------------------------------------------------------
! Load a theme; WORM-seal after load
SUBROUTINE syntax_load_theme(theme, path)
TYPE(theme_t), INTENT(INOUT) :: theme
CHARACTER(LEN=*), INTENT(IN) :: path
! TODO: parse theme file (JSON/TOML)
CALL theme_default_sovereign_dark(theme)
theme%worm_sealed = .TRUE.
WRITE(*,'(A,A)') '[syntax] theme loaded from ', TRIM(path)
END SUBROUTINE syntax_load_theme
! ---------------------------------------------------------------------------
! Sovereign dark theme β matches bob-ide color palette
SUBROUTINE theme_default_sovereign_dark(theme)
TYPE(theme_t), INTENT(INOUT) :: theme
theme%colors(COLOR_DEFAULT+1) = INT(Z'D4D4D4FF', C_INT32_T) ! #D4D4D4
theme%colors(COLOR_KEYWORD+1) = INT(Z'569CD6FF', C_INT32_T) ! #569CD6
theme%colors(COLOR_IDENTIFIER+1) = INT(Z'9CDCFEFF', C_INT32_T) ! #9CDCFE
theme%colors(COLOR_STRING+1) = INT(Z'CE9178FF', C_INT32_T) ! #CE9178
theme%colors(COLOR_NUMBER+1) = INT(Z'B5CEA8FF', C_INT32_T) ! #B5CEA8
theme%colors(COLOR_COMMENT+1) = INT(Z'6A9955FF', C_INT32_T) ! #6A9955
theme%colors(COLOR_OPERATOR+1) = INT(Z'D4D4D4FF', C_INT32_T)
theme%colors(COLOR_TYPE+1) = INT(Z'4EC9B0FF', C_INT32_T) ! #4EC9B0
theme%colors(COLOR_FUNCTION+1) = INT(Z'DCDCAAFF', C_INT32_T) ! #DCDCAA
theme%colors(COLOR_ERROR+1) = INT(Z'F44747FF', C_INT32_T) ! #F44747
theme%worm_sealed = .FALSE.
END SUBROUTINE theme_default_sovereign_dark
! ---------------------------------------------------------------------------
! Full highlight pass over entire CST
SUBROUTINE syntax_highlight(ctx, spans, query)
TYPE(parser_ctx_t), INTENT(IN) :: ctx
TYPE(span_list_t), INTENT(INOUT) :: spans
TYPE(query_t), INTENT(IN) :: query
spans%count = 0
CALL highlight_node(ctx, ctx%root, spans, query)
WRITE(*,'(A,I0,A)') '[syntax] highlight: ', spans%count, ' spans'
END SUBROUTINE syntax_highlight
! ---------------------------------------------------------------------------
! Incremental highlight β only reprocess changed CST subtree
SUBROUTINE syntax_highlight_incremental(ctx, spans, query, from_node)
TYPE(parser_ctx_t), INTENT(IN) :: ctx
TYPE(span_list_t), INTENT(INOUT) :: spans
TYPE(query_t), INTENT(IN) :: query
INTEGER, INTENT(IN) :: from_node
! TODO: invalidate spans overlapping from_node range, re-run from there
CALL highlight_node(ctx, from_node, spans, query)
END SUBROUTINE syntax_highlight_incremental
! ββ Internal ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
RECURSIVE SUBROUTINE highlight_node(ctx, idx, spans, query)
TYPE(parser_ctx_t), INTENT(IN) :: ctx
INTEGER, INTENT(IN) :: idx
TYPE(span_list_t), INTENT(INOUT) :: spans
TYPE(query_t), INTENT(IN) :: query
INTEGER :: i, color, child
IF (idx == 0) RETURN
! Match node kind against query patterns
color = COLOR_DEFAULT
IF (ctx%nodes(idx)%is_error) THEN
color = COLOR_ERROR
ELSE
DO i = 1, query%pattern_count
IF (query%patterns(i)%node_kind_id == ctx%nodes(idx)%kind) THEN
color = query%patterns(i)%color_id
EXIT
END IF
END DO
END IF
! Emit span if leaf
IF (ctx%nodes(idx)%n_children == 0) THEN
IF (spans%count < MAX_SPANS) THEN
spans%count = spans%count + 1
spans%spans(spans%count)%start_byte = ctx%nodes(idx)%start_byte
spans%spans(spans%count)%end_byte = ctx%nodes(idx)%end_byte
spans%spans(spans%count)%color_id = color
END IF
RETURN
END IF
! Recurse into children
DO i = 1, ctx%nodes(idx)%n_children
child = ctx%nodes(idx)%children(i)
CALL highlight_node(ctx, child, spans, query)
END DO
END SUBROUTINE highlight_node
END MODULE sovereign_syntax
|