Story of Algorithm

Building a Code Syntax Highlighter with PHP

One of the most useful tools for developers is a syntax highlighter, a way to display source code on a webpage with colors that distinguish keywords, comments, strings, and other elements. This makes code easier to read and visually appealing, especially in tutorials or documentation.

Download from GitHub

How It Works

A PHP-based syntax highlighter typically follows these steps:
  • Keyword Lists: Define arrays of reserved words for each language (e.g., PHP, Java, C++, JavaScript).
  • File Reader: Read the source file contents and convert special characters into HTML entities so they display correctly in the browser.
  • Parser: Scan the file character by character, identifying tokens such as keywords, comments, strings, parentheses, and brackets.
  • Styling: Wrap each token in HTML tags with CSS classes (like .kC for keywords, .cC for comments, .qC for strings).
  • Output: Render the highlighted code inside a styled container, optionally showing the file name and line numbers.

This code combines HTML and PHP to display syntax‑highlighted source files on a webpage.
The <link href="style.css" rel="stylesheet" /> line attaches a CSS stylesheet for styling the page.
The PHP section loads a custom syntax highlighter class (highlighter.class.php) that applies color coding to code samples.
A highlighter object ($colorObj) is created, and its applycolor() method is used to render the contents of highlighter.class.php with syntax highlighting.
The showfilename(false) method hides the file name label for the next snippet.

index.php
1 <link href="style.css" rel="stylesheet" />
2 <?php
3 // Load the syntax highlighter class used to color code samples.
4 include_once("highlighter.class.php");
5 
6 // Create the highlighter object and render the first source file.
7 $colorObj = new highlighter();
8 $fileContent = $colorObj->applycolor("highlighter.class.php");
9 echo $fileContent;
10 
11 // Hide the file name label for the second snippet and display the current page.
12 $colorObj->showfilename(false);
13 $fileContent = $colorObj->applycolor("index.php");
14 echo $fileContent;
15 ?>


This PHP code defines a syntax highlighter class that reads source files and outputs them with color‑coded formatting for display in a browser.
It begins by including keywords.php, which contains the list of language keywords used for highlighting.
The Highlighter class stores details about the file being processed (name, extension, and whether to show the filename).
The constructor initializes default values.
The showfilename() method lets you toggle whether the file name should appear above the highlighted code block.

The applycolor() method is the core:
  • It checks if the file exists, reads its contents, and converts special characters into HTML entities.
  • It then parses the file character by character, detecting keywords, comments, strings, parentheses, brackets, and line breaks.

Each type of syntax is wrapped in tags with specific CSS classes (like kC for keywords, cC for comments, qC for quotes, etc.), so the output can be styled with colors.
Line numbers are added alongside the code.
The checker() method compares tokens against the keyword list for the file’s extension and applies keyword highlighting if matched.

highlighter.class.php
1 <?php
2 // Include the language keyword list used to detect syntax keywords.
3 include_once("keywords.php");
4 
5 // Main class that reads source code files and highlights matching syntax.
6 class Highlighter {
7 	// Store the current file name and extension for keyword lookups.
8 	private $fileName;
9 	private $fileExtension;
10 	private $showFileName;
11 	
12 	// Initialize the highlighter with default values.
13 	public function __construct() {
14 		$this->fileName = "";
15 		$this->fileExtension = "";
16 		$this->showFileName = true;
17 	}
18 	
19 	// Toggle whether the file name should be displayed above the code block.
20 	public function showfilename($value) {
21 		$this->showFileName = $value;
22 	}
23 
24 	// Read a file, parse it, and return the HTML-highlighted output.
25 	public function applycolor($fileLocation = "") {
26 		if($fileLocation == "") {
27 			return;
28 		}
29 		else
30 		{
31 			// Only continue when the requested file exists and can be read.
32 			if(file_exists$fileLocation) {
33 				$temp = explode("/",$fileLocation);
34 				$this->fileName = trim(end$temp);
35 				$temp = explode(".",$this->fileName);
36 				$this->fileExtension = trim(end$temp);
37 				$fileContent = trim(file_get_contents$fileLocation, true);
38 				$fileContent = htmlentities($fileContent,ENT_NOQUOTES);
39 				if($fileContent == "") {	
40 					return;	
41 				}
42 			}
43 			else
44 			{	
45 				return; 
46 			}
47 			
48 			// Track nested parentheses, brackets, and string delimiters during parsing.
49 			$parenthesisFound = 0;
50 			$bracketFound = 0;
51 			$foundCharacter = "";
52 
53 			$line = 1;
54 			$counter = 0;
55 			$contentSize = strlen($fileContent);
56 
57 			$content = "<font class='lI'>".$line."</font> ";
58 			while($counter < $contentSize) {
59 				$character = $fileContent[$counter];
60 				$code = intval(ord$character);
61 				if($code >= 97 && $code <= 122 || $code >= 65 && $code <= 90) { //Identify only alphabet(Capital/Small) characters
62 					$characterBuffer .= $character;	
63 				}
64 				else
65 				{
66 					if($characterBuffer != "") {	
67 						$content .= $this->checker($characterBuffer);
68 						$characterBuffer = "";
69 					}
70 
71 					if($character == "/" && isset$fileContent[$counter+1] && $fileContent[$counter+1] == "*" || $fileContent[$counter+1] == "/") { //Identify single comment or multiple comments
72 						$content .= "<font class='cC'>".$fileContent[$counter].$fileContent[$counter+1];
73 						if($fileContent[$counter+1] == "*") {
74 							$counter += 2;
75 							while($counter < $contentSize) {
76 								$character = $fileContent[$counter];
77 								$code = intval(ord$character);
78 								if($code != 10) { //Identify not '\n' character
79 									if($character == "*" && isset$fileContent[$counter+1] && $fileContent[$counter+1] == "/") {
80 										$counter++;
81 										$content .= $character.$fileContent[$counter]."</font>";
82 										break;
83 									}
84 									else
85 									{	
86 										$content .= $character;	
87 									}
88 								}
89 								else
90 								{
91 									$line++;
92 									$content .= "</font>".$character."<font class='lI'>".$line."</font> <font class='cC'>";
93 								}
94 								$counter++;
95 							}
96 						}
97 						else
98 						{
99 							$counter += 2;
100 							while($counter < $contentSize) {
101 								$character = $fileContent[$counter];
102 								$code = intval(ord$character);
103 								if($code == 10) { //Identify '\n' character
104 									$content .= "</font>";
105 									$counter--;
106 									break;
107 								}
108 								$content .= $character;
109 								$counter++;
110 							}
111 						}
112 					}
113 					else if($character == "'" || $character == "\"") { //Identify sigle quote or double quote character
114 						$foundCharacter = $character;
115 						$content .= "<font class='qC'>".$foundCharacter;
116 						$counter++;
117 						while($counter < $contentSize) {
118 							$character = $fileContent[$counter];
119 							$code = intval(ord$character);
120 							if($foundCharacter == $character) {
121 								if($foundCharacter == "\"") {
122 									if($fileContent[$counter-1] != "\\") {
123 										$content .= $foundCharacter."</font>";
124 										break;
125 									}
126 									else if($fileContent[$counter-2] == "\\" && $fileContent[$counter-1] == "\\") {
127 										$content .= $foundCharacter."</font>";
128 										break;
129 									}
130 									else
131 									{
132 										$content .= $character;
133 									}
134 								}
135 								else
136 								{
137 									$content .= $foundCharacter."</font>";
138 									break;
139 								}
140 							}
141 							else if($code == 10) { //Identify '\n' character
142 								$line++;
143 								$content .= $character;
144 								$content .= "<font class='lI'>".$line."</font> ";
145 							}
146 							else
147 							{
148 								$content .= $character;
149 							}
150 							$counter++;
151 						}
152 					}
153 					else if($character == "(" || $character == ")") { //Identify parenthesis character
154 						if($parenthesisFound == 0) {
155 							$content .= "<font class='pC'>".$character."</font><font class='iPC'>";
156 						}
157 						if($character == "(") {
158 							$parenthesisFound++;
159 						}
160 						else if($character == ")") {
161 							$parenthesisFound--;
162 						}
163 						if($parenthesisFound == 0) {
164 							$content .= "</font><font class='pC'>".$character."</font>";
165 						}
166 					}
167 					else if($character == "[" || $character == "]") { //Identify bracket character
168 						if($bracketFound == 0) {
169 							$content .= "<font class='bC'>".$character."</font><font class='iBC'>";
170 						}
171 						if($character == "[") {
172 							$bracketFound++;
173 						}
174 						else if($character == "]") {
175 							$bracketFound--;
176 						}
177 						if($bracketFound == 0) {
178 							$content .= "</font><font class='bC'>".$character."</font>";
179 						}
180 					}
181 					else if($code == 10) { //Identify '\n' character
182 						$line++;
183 						$content .= $character;
184 						$content .= "<font class='lI'>".$line."</font> ";
185 					}
186 					else
187 					{
188 						$content .= $character;
189 					}
190 				}
191 				$counter++;
192 			}
193 			
194 			$output = "<div class='codeSection'>";
195 			if($this->showFileName == true) {
196 				$output .= "<div class='fileName'>".$this->fileName."</div>";
197 			}
198 			$output .= "<div class='code'><pre>".$content."</pre></div>";
199 			$output .= "</div>";
200 			return $output;
201 		}
202 	}
203 
204 	// Check whether the current token matches a known language keyword.
205 	private function checker($value) {
206 		global $languageKeywords;		
207 		$value = trim($value);
208 		if(isset$languageKeywords[$this->fileExtension]) { //Identify file type extension			
209 			if(in_array$value,$languageKeywords[$this->fileExtension]) { //Identify keywords				
210 				$value = "<font class='kC'>".$value."</font>";	
211 			}
212 		}	
213 		return $value;
214 	}
215 }
216 ?>


This PHP snippet defines the keyword lists that the syntax highlighter uses to color‑code code samples depending on the programming language.
keywords.php
1 <?php
2 // Define the keyword lists used by the highlighter for supported languages.
3 // PHP keywords are matched by file extension before rendering the colored output.
4 $languageKeywords["php"] = array("function","if","else","isset","unset","foreach","for","while","do","new","private","public","protected");
5 
6 // C++ keywords for code snippets written in that language.
7 $languageKeywords["cpp"] = array("void","char","int","main","static","if","else","for","while","do","cout","cin","struct","unsigned","long","return");
8 
9 // Java keywords for standard syntax highlighting support.
10 $languageKeywords["java"] = array("if","else","for","while","do","return","public","private","static","void","import","class","try","catch","package","main","this","int","null","new"); 
11 
12 // JavaScript keywords used in simple browser-side examples.
13 $languageKeywords["js"] = array("var","function");
14 ?>


CSS snippet defines the styling for the syntax highlighter output that displays code with colors and formatting.
style.css
1 /* Main wrapper that holds the highlighted code block and optional file label. */
2 .codeSection {
3     font-size:16px;
4     padding:0px;
5     margin:0px;
6 }
7 
8 /* File title displayed above the code area. */
9 .fileName {
10     color:#c586c0;
11     margin-bottom:5px;
12     font-weight:600;
13     letter-spacing:0.03em;
14 }
15 
16 /* Container styling for the code snippet area. */
17 .code {
18     line-height:1.6;
19     padding:15px;
20     overflow:auto;
21     color:#e6edf3;
22     background-color:#0d1117;
23     border-left:5px solid #30363d;
24     border-radius:4px;
25 }
26 
27 /* Preserve whitespace and monospace formatting for the rendered code. */
28 pre {
29     margin:0px;
30     padding:0px;
31     font-family:Consolas, "Courier New", monospace;
32     -moz-tab-size:4;
33     -o-tab-size:4;
34     tab-size:4;
35 }
36 
37 /* Line-number text styling. */
38 .lI {
39     color:#e6edf3;
40 }
41 
42 /* Keyword color for recognized language keywords. */
43 .kC {
44     color:#ff7b72;
45 }
46 
47 /* Comment color for single-line and block comments. */
48 .cC {
49     color:#8b949e;
50 }
51 
52 /* String literal color for single and double quoted text. */
53 .qC { 
54     color:#a5d6ff;
55 }
56 
57 /* Parenthesis styling for grouped expression blocks. */
58 .pC {
59     color:#c9d1d9;
60 }
61 
62 .iPC {
63     color:#79c0ff;
64 }
65 
66 /* Bracket styling for array or collection access. */
67 .bC {
68     color:#c9d1d9;
69 }
70 
71 .iBC {
72     color:#79c0ff;
73 }