diff --git a/README.md b/README.md
index 6f9aea0..365a6aa 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,15 @@
 English | [简体中文](./README.zh-CN.md)
 > This project is IEC-61131-3 Compiler implementation for technologies research.
 
-![x](./screenshots/Screenshot_20231209_230838.png)
+<p align="center">
+<img src="./screenshots/Screenshot_20231216_233926.png"><br>
+LSP-based syntax highlighting
+</p>
+
+<p align="center">
+<img src="./screenshots/Screenshot_20231209_230838.png"><br>
+A compiler data viewer tools UI
+</p>
 
 ### TODO-List
 - [ ] LSP implementation
diff --git a/lib/src/parser/lexer.rs b/lib/src/parser/lexer.rs
index b43195d..4094225 100644
--- a/lib/src/parser/lexer.rs
+++ b/lib/src/parser/lexer.rs
@@ -430,6 +430,7 @@ impl<'input> StLexer<'input> {
                     return self.parse_floating(tok, s);
                 }
                 _ => {
+                    tok.length = s.len();
                     tok.tok = Tok::Literal(LiteralValue::UInt(s.parse().unwrap()));
                     return Some(Ok(tok));
                 }
diff --git a/lib/src/parser/token.rs b/lib/src/parser/token.rs
index b6df76f..20a9190 100644
--- a/lib/src/parser/token.rs
+++ b/lib/src/parser/token.rs
@@ -162,10 +162,12 @@ impl Tok {
     pub fn is_operator(&self) -> bool {
         matches!(
             self,
-            Tok::LessEqual
-                | Tok::Less
+            Tok::Less
+                | Tok::LessEqual
+                | Tok::Greater
                 | Tok::GreaterEqual
                 | Tok::Equal
+                | Tok::NotEqual
                 | Tok::Plus
                 | Tok::Minus
                 | Tok::Division
diff --git a/lsp/src/lsp.rs b/lsp/src/lsp.rs
index 1def73e..802ec81 100644
--- a/lsp/src/lsp.rs
+++ b/lsp/src/lsp.rs
@@ -1,5 +1,5 @@
 use serde_json::Value;
-use stc::parser::StLexerBuilder;
+use stc::parser::{StLexerBuilder, Tok};
 use tower_lsp::jsonrpc;
 use tower_lsp::jsonrpc::Result;
 use tower_lsp::lsp_types::*;
@@ -25,8 +25,11 @@ impl LanguageServer for StcLsp {
                     },
                     legend: SemanticTokensLegend {
                         token_types: vec![
+                            SemanticTokenType::KEYWORD,
                             SemanticTokenType::VARIABLE,
                             SemanticTokenType::NUMBER,
+                            SemanticTokenType::STRING,
+                            SemanticTokenType::OPERATOR,
                             SemanticTokenType::FUNCTION,
                         ],
                         token_modifiers: vec![],
@@ -92,11 +95,44 @@ impl LanguageServer for StcLsp {
         let lexer = StLexerBuilder::new()
             .build_file(params.text_document.uri.path())
             .map_err(|_| jsonrpc::Error::invalid_request())?;
-        for tok in lexer {
-            info!("{:?}", tok.unwrap().tok);
+
+        let mut last_line = 0;
+        let mut last_offset = 0;
+        let mut tokens: Vec<SemanticToken> = vec![];
+        for tok in lexer.flatten() {
+            if tok.pos.line != last_line {
+                last_offset = 0;
+            }
+
+            let tok_type = match tok.tok {
+                Tok::Identifier(_) => 1,
+                Tok::Literal(_) => 2,
+                Tok::String => 3,
+                op if op.is_operator() => 4,
+                _ => 0,
+            };
+
+            let token = SemanticToken {
+                delta_line: (tok.pos.line - last_line) as u32,
+                delta_start: (tok.pos.offset - last_offset) as u32,
+                length: tok.length as u32,
+                token_type: tok_type,
+                ..Default::default()
+            };
+            tokens.push(token);
+
+            last_line = tok.pos.line;
+            last_offset = tok.pos.offset;
         }
 
-        Ok(None)
+        for x in &tokens {
+            trace!("{:?}", x);
+        }
+
+        Ok(Some(SemanticTokensResult::Tokens(SemanticTokens {
+            result_id: None,
+            data: tokens,
+        })))
     }
 
     async fn semantic_tokens_full_delta(
diff --git a/screenshots/Screenshot_20231216_233926.png b/screenshots/Screenshot_20231216_233926.png
new file mode 100644
index 0000000..26fb3f7
Binary files /dev/null and b/screenshots/Screenshot_20231216_233926.png differ