├── .gitignore ├── .vscode ├── c_cpp_properties.json └── settings.json ├── LICENSE ├── Makefile ├── README.md ├── bfpp.c ├── build_highlighter.pl ├── highlighters ├── all.hpp ├── asm2bf.lxi ├── brainfuck.lxi ├── c.lxi ├── cpp.lxi ├── lua.lxi ├── python.lxi └── x86asm.lxi ├── make_ascii.pl ├── tau.cpp.in └── tau.hpp.in /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | attic/ 3 | benchmark/ 4 | deps/ 5 | *.o 6 | tau 7 | tau.cpp 8 | tau.hpp 9 | bfpp 10 | -------------------------------------------------------------------------------- /.vscode/c_cpp_properties.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": [ 3 | { 4 | "name": "Linux", 5 | "includePath": [ 6 | "${workspaceFolder}/**", 7 | "${workspaceFolder}/highlighters" 8 | ], 9 | "defines": [], 10 | "compilerPath": "/usr/bin/clang", 11 | "cStandard": "c17", 12 | "cppStandard": "c++17", 13 | "intelliSenseMode": "linux-clang-x64" 14 | } 15 | ], 16 | "version": 4 17 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "*.lxx": "cpp", 4 | "regex": "cpp", 5 | "array": "cpp", 6 | "atomic": "cpp", 7 | "bit": "cpp", 8 | "*.tcc": "cpp", 9 | "bitset": "cpp", 10 | "cctype": "cpp", 11 | "clocale": "cpp", 12 | "cmath": "cpp", 13 | "compare": "cpp", 14 | "concepts": "cpp", 15 | "cstdarg": "cpp", 16 | "cstddef": "cpp", 17 | "cstdint": "cpp", 18 | "cstdio": "cpp", 19 | "cstdlib": "cpp", 20 | "cstring": "cpp", 21 | "ctime": "cpp", 22 | "cwchar": "cpp", 23 | "cwctype": "cpp", 24 | "deque": "cpp", 25 | "list": "cpp", 26 | "map": "cpp", 27 | "set": "cpp", 28 | "unordered_map": "cpp", 29 | "vector": "cpp", 30 | "exception": "cpp", 31 | "algorithm": "cpp", 32 | "functional": "cpp", 33 | "iterator": "cpp", 34 | "memory": "cpp", 35 | "memory_resource": "cpp", 36 | "numeric": "cpp", 37 | "optional": "cpp", 38 | "random": "cpp", 39 | "string": "cpp", 40 | "string_view": "cpp", 41 | "system_error": "cpp", 42 | "tuple": "cpp", 43 | "type_traits": "cpp", 44 | "utility": "cpp", 45 | "fstream": "cpp", 46 | "initializer_list": "cpp", 47 | "iomanip": "cpp", 48 | "iosfwd": "cpp", 49 | "iostream": "cpp", 50 | "istream": "cpp", 51 | "limits": "cpp", 52 | "new": "cpp", 53 | "ostream": "cpp", 54 | "ranges": "cpp", 55 | "sstream": "cpp", 56 | "stdexcept": "cpp", 57 | "streambuf": "cpp", 58 | "typeinfo": "cpp", 59 | "variant": "cpp", 60 | "cinttypes": "cpp", 61 | "chrono": "cpp", 62 | "codecvt": "cpp", 63 | "ratio": "cpp", 64 | "*.ipp": "cpp", 65 | "csetjmp": "cpp", 66 | "csignal": "cpp", 67 | "any": "cpp", 68 | "hash_map": "cpp", 69 | "hash_set": "cpp", 70 | "strstream": "cpp", 71 | "cfenv": "cpp", 72 | "complex": "cpp", 73 | "condition_variable": "cpp", 74 | "coroutine": "cpp", 75 | "forward_list": "cpp", 76 | "unordered_set": "cpp", 77 | "source_location": "cpp", 78 | "rope": "cpp", 79 | "slist": "cpp", 80 | "future": "cpp", 81 | "mutex": "cpp", 82 | "scoped_allocator": "cpp", 83 | "shared_mutex": "cpp", 84 | "span": "cpp", 85 | "stop_token": "cpp", 86 | "thread": "cpp", 87 | "typeindex": "cpp", 88 | "valarray": "cpp", 89 | "*.in": "cpp" 90 | } 91 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU AFFERO GENERAL PUBLIC LICENSE 2 | Version 3, 19 November 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU Affero General Public License is a free, copyleft license for 11 | software and other kinds of works, specifically designed to ensure 12 | cooperation with the community in the case of network server software. 13 | 14 | The licenses for most software and other practical works are designed 15 | to take away your freedom to share and change the works. By contrast, 16 | our General Public Licenses are intended to guarantee your freedom to 17 | share and change all versions of a program--to make sure it remains free 18 | software for all its users. 19 | 20 | When we speak of free software, we are referring to freedom, not 21 | price. Our General Public Licenses are designed to make sure that you 22 | have the freedom to distribute copies of free software (and charge for 23 | them if you wish), that you receive source code or can get it if you 24 | want it, that you can change the software or use pieces of it in new 25 | free programs, and that you know you can do these things. 26 | 27 | Developers that use our General Public Licenses protect your rights 28 | with two steps: (1) assert copyright on the software, and (2) offer 29 | you this License which gives you legal permission to copy, distribute 30 | and/or modify the software. 31 | 32 | A secondary benefit of defending all users' freedom is that 33 | improvements made in alternate versions of the program, if they 34 | receive widespread use, become available for other developers to 35 | incorporate. Many developers of free software are heartened and 36 | encouraged by the resulting cooperation. However, in the case of 37 | software used on network servers, this result may fail to come about. 38 | The GNU General Public License permits making a modified version and 39 | letting the public access it on a server without ever releasing its 40 | source code to the public. 41 | 42 | The GNU Affero General Public License is designed specifically to 43 | ensure that, in such cases, the modified source code becomes available 44 | to the community. It requires the operator of a network server to 45 | provide the source code of the modified version running there to the 46 | users of that server. Therefore, public use of a modified version, on 47 | a publicly accessible server, gives the public access to the source 48 | code of the modified version. 49 | 50 | An older license, called the Affero General Public License and 51 | published by Affero, was designed to accomplish similar goals. This is 52 | a different license, not a version of the Affero GPL, but Affero has 53 | released a new version of the Affero GPL which permits relicensing under 54 | this license. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | TERMS AND CONDITIONS 60 | 61 | 0. Definitions. 62 | 63 | "This License" refers to version 3 of the GNU Affero General Public License. 64 | 65 | "Copyright" also means copyright-like laws that apply to other kinds of 66 | works, such as semiconductor masks. 67 | 68 | "The Program" refers to any copyrightable work licensed under this 69 | License. Each licensee is addressed as "you". "Licensees" and 70 | "recipients" may be individuals or organizations. 71 | 72 | To "modify" a work means to copy from or adapt all or part of the work 73 | in a fashion requiring copyright permission, other than the making of an 74 | exact copy. The resulting work is called a "modified version" of the 75 | earlier work or a work "based on" the earlier work. 76 | 77 | A "covered work" means either the unmodified Program or a work based 78 | on the Program. 79 | 80 | To "propagate" a work means to do anything with it that, without 81 | permission, would make you directly or secondarily liable for 82 | infringement under applicable copyright law, except executing it on a 83 | computer or modifying a private copy. Propagation includes copying, 84 | distribution (with or without modification), making available to the 85 | public, and in some countries other activities as well. 86 | 87 | To "convey" a work means any kind of propagation that enables other 88 | parties to make or receive copies. Mere interaction with a user through 89 | a computer network, with no transfer of a copy, is not conveying. 90 | 91 | An interactive user interface displays "Appropriate Legal Notices" 92 | to the extent that it includes a convenient and prominently visible 93 | feature that (1) displays an appropriate copyright notice, and (2) 94 | tells the user that there is no warranty for the work (except to the 95 | extent that warranties are provided), that licensees may convey the 96 | work under this License, and how to view a copy of this License. If 97 | the interface presents a list of user commands or options, such as a 98 | menu, a prominent item in the list meets this criterion. 99 | 100 | 1. Source Code. 101 | 102 | The "source code" for a work means the preferred form of the work 103 | for making modifications to it. "Object code" means any non-source 104 | form of a work. 105 | 106 | A "Standard Interface" means an interface that either is an official 107 | standard defined by a recognized standards body, or, in the case of 108 | interfaces specified for a particular programming language, one that 109 | is widely used among developers working in that language. 110 | 111 | The "System Libraries" of an executable work include anything, other 112 | than the work as a whole, that (a) is included in the normal form of 113 | packaging a Major Component, but which is not part of that Major 114 | Component, and (b) serves only to enable use of the work with that 115 | Major Component, or to implement a Standard Interface for which an 116 | implementation is available to the public in source code form. A 117 | "Major Component", in this context, means a major essential component 118 | (kernel, window system, and so on) of the specific operating system 119 | (if any) on which the executable work runs, or a compiler used to 120 | produce the work, or an object code interpreter used to run it. 121 | 122 | The "Corresponding Source" for a work in object code form means all 123 | the source code needed to generate, install, and (for an executable 124 | work) run the object code and to modify the work, including scripts to 125 | control those activities. However, it does not include the work's 126 | System Libraries, or general-purpose tools or generally available free 127 | programs which are used unmodified in performing those activities but 128 | which are not part of the work. For example, Corresponding Source 129 | includes interface definition files associated with source files for 130 | the work, and the source code for shared libraries and dynamically 131 | linked subprograms that the work is specifically designed to require, 132 | such as by intimate data communication or control flow between those 133 | subprograms and other parts of the work. 134 | 135 | The Corresponding Source need not include anything that users 136 | can regenerate automatically from other parts of the Corresponding 137 | Source. 138 | 139 | The Corresponding Source for a work in source code form is that 140 | same work. 141 | 142 | 2. Basic Permissions. 143 | 144 | All rights granted under this License are granted for the term of 145 | copyright on the Program, and are irrevocable provided the stated 146 | conditions are met. This License explicitly affirms your unlimited 147 | permission to run the unmodified Program. The output from running a 148 | covered work is covered by this License only if the output, given its 149 | content, constitutes a covered work. This License acknowledges your 150 | rights of fair use or other equivalent, as provided by copyright law. 151 | 152 | You may make, run and propagate covered works that you do not 153 | convey, without conditions so long as your license otherwise remains 154 | in force. You may convey covered works to others for the sole purpose 155 | of having them make modifications exclusively for you, or provide you 156 | with facilities for running those works, provided that you comply with 157 | the terms of this License in conveying all material for which you do 158 | not control copyright. Those thus making or running the covered works 159 | for you must do so exclusively on your behalf, under your direction 160 | and control, on terms that prohibit them from making any copies of 161 | your copyrighted material outside their relationship with you. 162 | 163 | Conveying under any other circumstances is permitted solely under 164 | the conditions stated below. Sublicensing is not allowed; section 10 165 | makes it unnecessary. 166 | 167 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 168 | 169 | No covered work shall be deemed part of an effective technological 170 | measure under any applicable law fulfilling obligations under article 171 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 172 | similar laws prohibiting or restricting circumvention of such 173 | measures. 174 | 175 | When you convey a covered work, you waive any legal power to forbid 176 | circumvention of technological measures to the extent such circumvention 177 | is effected by exercising rights under this License with respect to 178 | the covered work, and you disclaim any intention to limit operation or 179 | modification of the work as a means of enforcing, against the work's 180 | users, your or third parties' legal rights to forbid circumvention of 181 | technological measures. 182 | 183 | 4. Conveying Verbatim Copies. 184 | 185 | You may convey verbatim copies of the Program's source code as you 186 | receive it, in any medium, provided that you conspicuously and 187 | appropriately publish on each copy an appropriate copyright notice; 188 | keep intact all notices stating that this License and any 189 | non-permissive terms added in accord with section 7 apply to the code; 190 | keep intact all notices of the absence of any warranty; and give all 191 | recipients a copy of this License along with the Program. 192 | 193 | You may charge any price or no price for each copy that you convey, 194 | and you may offer support or warranty protection for a fee. 195 | 196 | 5. Conveying Modified Source Versions. 197 | 198 | You may convey a work based on the Program, or the modifications to 199 | produce it from the Program, in the form of source code under the 200 | terms of section 4, provided that you also meet all of these conditions: 201 | 202 | a) The work must carry prominent notices stating that you modified 203 | it, and giving a relevant date. 204 | 205 | b) The work must carry prominent notices stating that it is 206 | released under this License and any conditions added under section 207 | 7. This requirement modifies the requirement in section 4 to 208 | "keep intact all notices". 209 | 210 | c) You must license the entire work, as a whole, under this 211 | License to anyone who comes into possession of a copy. This 212 | License will therefore apply, along with any applicable section 7 213 | additional terms, to the whole of the work, and all its parts, 214 | regardless of how they are packaged. This License gives no 215 | permission to license the work in any other way, but it does not 216 | invalidate such permission if you have separately received it. 217 | 218 | d) If the work has interactive user interfaces, each must display 219 | Appropriate Legal Notices; however, if the Program has interactive 220 | interfaces that do not display Appropriate Legal Notices, your 221 | work need not make them do so. 222 | 223 | A compilation of a covered work with other separate and independent 224 | works, which are not by their nature extensions of the covered work, 225 | and which are not combined with it such as to form a larger program, 226 | in or on a volume of a storage or distribution medium, is called an 227 | "aggregate" if the compilation and its resulting copyright are not 228 | used to limit the access or legal rights of the compilation's users 229 | beyond what the individual works permit. Inclusion of a covered work 230 | in an aggregate does not cause this License to apply to the other 231 | parts of the aggregate. 232 | 233 | 6. Conveying Non-Source Forms. 234 | 235 | You may convey a covered work in object code form under the terms 236 | of sections 4 and 5, provided that you also convey the 237 | machine-readable Corresponding Source under the terms of this License, 238 | in one of these ways: 239 | 240 | a) Convey the object code in, or embodied in, a physical product 241 | (including a physical distribution medium), accompanied by the 242 | Corresponding Source fixed on a durable physical medium 243 | customarily used for software interchange. 244 | 245 | b) Convey the object code in, or embodied in, a physical product 246 | (including a physical distribution medium), accompanied by a 247 | written offer, valid for at least three years and valid for as 248 | long as you offer spare parts or customer support for that product 249 | model, to give anyone who possesses the object code either (1) a 250 | copy of the Corresponding Source for all the software in the 251 | product that is covered by this License, on a durable physical 252 | medium customarily used for software interchange, for a price no 253 | more than your reasonable cost of physically performing this 254 | conveying of source, or (2) access to copy the 255 | Corresponding Source from a network server at no charge. 256 | 257 | c) Convey individual copies of the object code with a copy of the 258 | written offer to provide the Corresponding Source. This 259 | alternative is allowed only occasionally and noncommercially, and 260 | only if you received the object code with such an offer, in accord 261 | with subsection 6b. 262 | 263 | d) Convey the object code by offering access from a designated 264 | place (gratis or for a charge), and offer equivalent access to the 265 | Corresponding Source in the same way through the same place at no 266 | further charge. You need not require recipients to copy the 267 | Corresponding Source along with the object code. If the place to 268 | copy the object code is a network server, the Corresponding Source 269 | may be on a different server (operated by you or a third party) 270 | that supports equivalent copying facilities, provided you maintain 271 | clear directions next to the object code saying where to find the 272 | Corresponding Source. Regardless of what server hosts the 273 | Corresponding Source, you remain obligated to ensure that it is 274 | available for as long as needed to satisfy these requirements. 275 | 276 | e) Convey the object code using peer-to-peer transmission, provided 277 | you inform other peers where the object code and Corresponding 278 | Source of the work are being offered to the general public at no 279 | charge under subsection 6d. 280 | 281 | A separable portion of the object code, whose source code is excluded 282 | from the Corresponding Source as a System Library, need not be 283 | included in conveying the object code work. 284 | 285 | A "User Product" is either (1) a "consumer product", which means any 286 | tangible personal property which is normally used for personal, family, 287 | or household purposes, or (2) anything designed or sold for incorporation 288 | into a dwelling. In determining whether a product is a consumer product, 289 | doubtful cases shall be resolved in favor of coverage. For a particular 290 | product received by a particular user, "normally used" refers to a 291 | typical or common use of that class of product, regardless of the status 292 | of the particular user or of the way in which the particular user 293 | actually uses, or expects or is expected to use, the product. A product 294 | is a consumer product regardless of whether the product has substantial 295 | commercial, industrial or non-consumer uses, unless such uses represent 296 | the only significant mode of use of the product. 297 | 298 | "Installation Information" for a User Product means any methods, 299 | procedures, authorization keys, or other information required to install 300 | and execute modified versions of a covered work in that User Product from 301 | a modified version of its Corresponding Source. The information must 302 | suffice to ensure that the continued functioning of the modified object 303 | code is in no case prevented or interfered with solely because 304 | modification has been made. 305 | 306 | If you convey an object code work under this section in, or with, or 307 | specifically for use in, a User Product, and the conveying occurs as 308 | part of a transaction in which the right of possession and use of the 309 | User Product is transferred to the recipient in perpetuity or for a 310 | fixed term (regardless of how the transaction is characterized), the 311 | Corresponding Source conveyed under this section must be accompanied 312 | by the Installation Information. But this requirement does not apply 313 | if neither you nor any third party retains the ability to install 314 | modified object code on the User Product (for example, the work has 315 | been installed in ROM). 316 | 317 | The requirement to provide Installation Information does not include a 318 | requirement to continue to provide support service, warranty, or updates 319 | for a work that has been modified or installed by the recipient, or for 320 | the User Product in which it has been modified or installed. Access to a 321 | network may be denied when the modification itself materially and 322 | adversely affects the operation of the network or violates the rules and 323 | protocols for communication across the network. 324 | 325 | Corresponding Source conveyed, and Installation Information provided, 326 | in accord with this section must be in a format that is publicly 327 | documented (and with an implementation available to the public in 328 | source code form), and must require no special password or key for 329 | unpacking, reading or copying. 330 | 331 | 7. Additional Terms. 332 | 333 | "Additional permissions" are terms that supplement the terms of this 334 | License by making exceptions from one or more of its conditions. 335 | Additional permissions that are applicable to the entire Program shall 336 | be treated as though they were included in this License, to the extent 337 | that they are valid under applicable law. If additional permissions 338 | apply only to part of the Program, that part may be used separately 339 | under those permissions, but the entire Program remains governed by 340 | this License without regard to the additional permissions. 341 | 342 | When you convey a copy of a covered work, you may at your option 343 | remove any additional permissions from that copy, or from any part of 344 | it. (Additional permissions may be written to require their own 345 | removal in certain cases when you modify the work.) You may place 346 | additional permissions on material, added by you to a covered work, 347 | for which you have or can give appropriate copyright permission. 348 | 349 | Notwithstanding any other provision of this License, for material you 350 | add to a covered work, you may (if authorized by the copyright holders of 351 | that material) supplement the terms of this License with terms: 352 | 353 | a) Disclaiming warranty or limiting liability differently from the 354 | terms of sections 15 and 16 of this License; or 355 | 356 | b) Requiring preservation of specified reasonable legal notices or 357 | author attributions in that material or in the Appropriate Legal 358 | Notices displayed by works containing it; or 359 | 360 | c) Prohibiting misrepresentation of the origin of that material, or 361 | requiring that modified versions of such material be marked in 362 | reasonable ways as different from the original version; or 363 | 364 | d) Limiting the use for publicity purposes of names of licensors or 365 | authors of the material; or 366 | 367 | e) Declining to grant rights under trademark law for use of some 368 | trade names, trademarks, or service marks; or 369 | 370 | f) Requiring indemnification of licensors and authors of that 371 | material by anyone who conveys the material (or modified versions of 372 | it) with contractual assumptions of liability to the recipient, for 373 | any liability that these contractual assumptions directly impose on 374 | those licensors and authors. 375 | 376 | All other non-permissive additional terms are considered "further 377 | restrictions" within the meaning of section 10. If the Program as you 378 | received it, or any part of it, contains a notice stating that it is 379 | governed by this License along with a term that is a further 380 | restriction, you may remove that term. If a license document contains 381 | a further restriction but permits relicensing or conveying under this 382 | License, you may add to a covered work material governed by the terms 383 | of that license document, provided that the further restriction does 384 | not survive such relicensing or conveying. 385 | 386 | If you add terms to a covered work in accord with this section, you 387 | must place, in the relevant source files, a statement of the 388 | additional terms that apply to those files, or a notice indicating 389 | where to find the applicable terms. 390 | 391 | Additional terms, permissive or non-permissive, may be stated in the 392 | form of a separately written license, or stated as exceptions; 393 | the above requirements apply either way. 394 | 395 | 8. Termination. 396 | 397 | You may not propagate or modify a covered work except as expressly 398 | provided under this License. Any attempt otherwise to propagate or 399 | modify it is void, and will automatically terminate your rights under 400 | this License (including any patent licenses granted under the third 401 | paragraph of section 11). 402 | 403 | However, if you cease all violation of this License, then your 404 | license from a particular copyright holder is reinstated (a) 405 | provisionally, unless and until the copyright holder explicitly and 406 | finally terminates your license, and (b) permanently, if the copyright 407 | holder fails to notify you of the violation by some reasonable means 408 | prior to 60 days after the cessation. 409 | 410 | Moreover, your license from a particular copyright holder is 411 | reinstated permanently if the copyright holder notifies you of the 412 | violation by some reasonable means, this is the first time you have 413 | received notice of violation of this License (for any work) from that 414 | copyright holder, and you cure the violation prior to 30 days after 415 | your receipt of the notice. 416 | 417 | Termination of your rights under this section does not terminate the 418 | licenses of parties who have received copies or rights from you under 419 | this License. If your rights have been terminated and not permanently 420 | reinstated, you do not qualify to receive new licenses for the same 421 | material under section 10. 422 | 423 | 9. Acceptance Not Required for Having Copies. 424 | 425 | You are not required to accept this License in order to receive or 426 | run a copy of the Program. Ancillary propagation of a covered work 427 | occurring solely as a consequence of using peer-to-peer transmission 428 | to receive a copy likewise does not require acceptance. However, 429 | nothing other than this License grants you permission to propagate or 430 | modify any covered work. These actions infringe copyright if you do 431 | not accept this License. Therefore, by modifying or propagating a 432 | covered work, you indicate your acceptance of this License to do so. 433 | 434 | 10. Automatic Licensing of Downstream Recipients. 435 | 436 | Each time you convey a covered work, the recipient automatically 437 | receives a license from the original licensors, to run, modify and 438 | propagate that work, subject to this License. You are not responsible 439 | for enforcing compliance by third parties with this License. 440 | 441 | An "entity transaction" is a transaction transferring control of an 442 | organization, or substantially all assets of one, or subdividing an 443 | organization, or merging organizations. If propagation of a covered 444 | work results from an entity transaction, each party to that 445 | transaction who receives a copy of the work also receives whatever 446 | licenses to the work the party's predecessor in interest had or could 447 | give under the previous paragraph, plus a right to possession of the 448 | Corresponding Source of the work from the predecessor in interest, if 449 | the predecessor has it or can get it with reasonable efforts. 450 | 451 | You may not impose any further restrictions on the exercise of the 452 | rights granted or affirmed under this License. For example, you may 453 | not impose a license fee, royalty, or other charge for exercise of 454 | rights granted under this License, and you may not initiate litigation 455 | (including a cross-claim or counterclaim in a lawsuit) alleging that 456 | any patent claim is infringed by making, using, selling, offering for 457 | sale, or importing the Program or any portion of it. 458 | 459 | 11. Patents. 460 | 461 | A "contributor" is a copyright holder who authorizes use under this 462 | License of the Program or a work on which the Program is based. The 463 | work thus licensed is called the contributor's "contributor version". 464 | 465 | A contributor's "essential patent claims" are all patent claims 466 | owned or controlled by the contributor, whether already acquired or 467 | hereafter acquired, that would be infringed by some manner, permitted 468 | by this License, of making, using, or selling its contributor version, 469 | but do not include claims that would be infringed only as a 470 | consequence of further modification of the contributor version. For 471 | purposes of this definition, "control" includes the right to grant 472 | patent sublicenses in a manner consistent with the requirements of 473 | this License. 474 | 475 | Each contributor grants you a non-exclusive, worldwide, royalty-free 476 | patent license under the contributor's essential patent claims, to 477 | make, use, sell, offer for sale, import and otherwise run, modify and 478 | propagate the contents of its contributor version. 479 | 480 | In the following three paragraphs, a "patent license" is any express 481 | agreement or commitment, however denominated, not to enforce a patent 482 | (such as an express permission to practice a patent or covenant not to 483 | sue for patent infringement). To "grant" such a patent license to a 484 | party means to make such an agreement or commitment not to enforce a 485 | patent against the party. 486 | 487 | If you convey a covered work, knowingly relying on a patent license, 488 | and the Corresponding Source of the work is not available for anyone 489 | to copy, free of charge and under the terms of this License, through a 490 | publicly available network server or other readily accessible means, 491 | then you must either (1) cause the Corresponding Source to be so 492 | available, or (2) arrange to deprive yourself of the benefit of the 493 | patent license for this particular work, or (3) arrange, in a manner 494 | consistent with the requirements of this License, to extend the patent 495 | license to downstream recipients. "Knowingly relying" means you have 496 | actual knowledge that, but for the patent license, your conveying the 497 | covered work in a country, or your recipient's use of the covered work 498 | in a country, would infringe one or more identifiable patents in that 499 | country that you have reason to believe are valid. 500 | 501 | If, pursuant to or in connection with a single transaction or 502 | arrangement, you convey, or propagate by procuring conveyance of, a 503 | covered work, and grant a patent license to some of the parties 504 | receiving the covered work authorizing them to use, propagate, modify 505 | or convey a specific copy of the covered work, then the patent license 506 | you grant is automatically extended to all recipients of the covered 507 | work and works based on it. 508 | 509 | A patent license is "discriminatory" if it does not include within 510 | the scope of its coverage, prohibits the exercise of, or is 511 | conditioned on the non-exercise of one or more of the rights that are 512 | specifically granted under this License. You may not convey a covered 513 | work if you are a party to an arrangement with a third party that is 514 | in the business of distributing software, under which you make payment 515 | to the third party based on the extent of your activity of conveying 516 | the work, and under which the third party grants, to any of the 517 | parties who would receive the covered work from you, a discriminatory 518 | patent license (a) in connection with copies of the covered work 519 | conveyed by you (or copies made from those copies), or (b) primarily 520 | for and in connection with specific products or compilations that 521 | contain the covered work, unless you entered into that arrangement, 522 | or that patent license was granted, prior to 28 March 2007. 523 | 524 | Nothing in this License shall be construed as excluding or limiting 525 | any implied license or other defenses to infringement that may 526 | otherwise be available to you under applicable patent law. 527 | 528 | 12. No Surrender of Others' Freedom. 529 | 530 | If conditions are imposed on you (whether by court order, agreement or 531 | otherwise) that contradict the conditions of this License, they do not 532 | excuse you from the conditions of this License. If you cannot convey a 533 | covered work so as to satisfy simultaneously your obligations under this 534 | License and any other pertinent obligations, then as a consequence you may 535 | not convey it at all. For example, if you agree to terms that obligate you 536 | to collect a royalty for further conveying from those to whom you convey 537 | the Program, the only way you could satisfy both those terms and this 538 | License would be to refrain entirely from conveying the Program. 539 | 540 | 13. Remote Network Interaction; Use with the GNU General Public License. 541 | 542 | Notwithstanding any other provision of this License, if you modify the 543 | Program, your modified version must prominently offer all users 544 | interacting with it remotely through a computer network (if your version 545 | supports such interaction) an opportunity to receive the Corresponding 546 | Source of your version by providing access to the Corresponding Source 547 | from a network server at no charge, through some standard or customary 548 | means of facilitating copying of software. This Corresponding Source 549 | shall include the Corresponding Source for any work covered by version 3 550 | of the GNU General Public License that is incorporated pursuant to the 551 | following paragraph. 552 | 553 | Notwithstanding any other provision of this License, you have 554 | permission to link or combine any covered work with a work licensed 555 | under version 3 of the GNU General Public License into a single 556 | combined work, and to convey the resulting work. The terms of this 557 | License will continue to apply to the part which is the covered work, 558 | but the work with which it is combined will remain governed by version 559 | 3 of the GNU General Public License. 560 | 561 | 14. Revised Versions of this License. 562 | 563 | The Free Software Foundation may publish revised and/or new versions of 564 | the GNU Affero General Public License from time to time. Such new versions 565 | will be similar in spirit to the present version, but may differ in detail to 566 | address new problems or concerns. 567 | 568 | Each version is given a distinguishing version number. If the 569 | Program specifies that a certain numbered version of the GNU Affero General 570 | Public License "or any later version" applies to it, you have the 571 | option of following the terms and conditions either of that numbered 572 | version or of any later version published by the Free Software 573 | Foundation. If the Program does not specify a version number of the 574 | GNU Affero General Public License, you may choose any version ever published 575 | by the Free Software Foundation. 576 | 577 | If the Program specifies that a proxy can decide which future 578 | versions of the GNU Affero General Public License can be used, that proxy's 579 | public statement of acceptance of a version permanently authorizes you 580 | to choose that version for the Program. 581 | 582 | Later license versions may give you additional or different 583 | permissions. However, no additional obligations are imposed on any 584 | author or copyright holder as a result of your choosing to follow a 585 | later version. 586 | 587 | 15. Disclaimer of Warranty. 588 | 589 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 590 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 591 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 592 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 593 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 594 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 595 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 596 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 597 | 598 | 16. Limitation of Liability. 599 | 600 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 601 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 602 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 603 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 604 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 605 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 606 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 607 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 608 | SUCH DAMAGES. 609 | 610 | 17. Interpretation of Sections 15 and 16. 611 | 612 | If the disclaimer of warranty and limitation of liability provided 613 | above cannot be given local legal effect according to their terms, 614 | reviewing courts shall apply local law that most closely approximates 615 | an absolute waiver of all civil liability in connection with the 616 | Program, unless a warranty or assumption of liability accompanies a 617 | copy of the Program in return for a fee. 618 | 619 | END OF TERMS AND CONDITIONS 620 | 621 | How to Apply These Terms to Your New Programs 622 | 623 | If you develop a new program, and you want it to be of the greatest 624 | possible use to the public, the best way to achieve this is to make it 625 | free software which everyone can redistribute and change under these terms. 626 | 627 | To do so, attach the following notices to the program. It is safest 628 | to attach them to the start of each source file to most effectively 629 | state the exclusion of warranty; and each file should have at least 630 | the "copyright" line and a pointer to where the full notice is found. 631 | 632 | 633 | Copyright (C) 634 | 635 | This program is free software: you can redistribute it and/or modify 636 | it under the terms of the GNU Affero General Public License as published by 637 | the Free Software Foundation, either version 3 of the License, or 638 | (at your option) any later version. 639 | 640 | This program is distributed in the hope that it will be useful, 641 | but WITHOUT ANY WARRANTY; without even the implied warranty of 642 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 643 | GNU Affero General Public License for more details. 644 | 645 | You should have received a copy of the GNU Affero General Public License 646 | along with this program. If not, see . 647 | 648 | Also add information on how to contact you by electronic and paper mail. 649 | 650 | If your software can interact with users remotely through a computer 651 | network, you should also make sure that it provides a way for users to 652 | get its source. For example, if your program is a web application, its 653 | interface could display a "Source" link that leads users to an archive 654 | of the code. There are many ways you could offer source, and different 655 | solutions will be better for different programs; see section 13 for the 656 | specific requirements. 657 | 658 | You should also get your employer (if you work as a programmer) or school, 659 | if any, to sign a "copyright disclaimer" for the program, if necessary. 660 | For more information on this, and how to apply and follow the GNU AGPL, see 661 | . 662 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | CXX ?= g++ 3 | 4 | HFLAGS=-Ideps/RE-flex/include/ -I. -std=c++20 -Wall -Wextra 5 | 6 | STRIPPER.debug := : 7 | STRIPPER.release := strip 8 | STRIPPER.profile := : 9 | STRIPPER := $(or ${STRIPPER.${target}},:) 10 | 11 | ifeq ($(CXX),g++) 12 | CXXFLAGS.debug := -O0 -g3 -fsanitize=address -fsanitize=leak -fsanitize=undefined \ 13 | -fcf-protection=full -fstack-protector-strong -fstack-check 14 | CXXFLAGS.release := -O3 -march=native -funroll-loops -flto -flto=auto 15 | CXXFLAGS.profile := $(CXXFLAGS.release) -g3 16 | CXXFLAGS := $(or ${CXXFLAGS.${target}},-Wall -Wextra -O0) 17 | else 18 | ifeq ($(CXX),clang++) 19 | CXXFLAGS.debug := -O0 -g3 -fsanitize=address -fsanitize=leak -fsanitize=undefined \ 20 | -fcf-protection=full -fstack-protector-strong -fstack-check 21 | CXXFLAGS.release := -O3 -march=native -funroll-loops -flto \ 22 | -ffinite-loops -ffinite-math-only -fignore-exceptions -fno-math-errno -fno-stack-protector \ 23 | -funroll-loops -funsafe-math-optimizations -fvectorize -fwhole-program-vtables -fvirtual-function-elimination \ 24 | -fopenmp-simd -fopenmp -fslp-vectorize # line 2 & 3 are dangerous as fuck, remove when there's some trouble. 25 | CXXFLAGS.profile := $(CXXFLAGS.release) -g3 26 | CXXFLAGS := $(or ${CXXFLAGS.${target}},-Wall -Wextra -O0) 27 | else 28 | CXXFLAGS := -O2 29 | endif 30 | endif 31 | 32 | _S_HIGHLIGHTERS := x86asm c cpp lua python brainfuck asm2bf 33 | _S_HL_OBJS := $(patsubst %, highlighters/%.o, $(_S_HIGHLIGHTERS)) 34 | _S_HL_A_OBJS := $(patsubst %, highlighters/%.ascii.o, $(_S_HIGHLIGHTERS)) 35 | 36 | .PHONY: clean all clean-deps 37 | all: tau 38 | clean-deps: 39 | rm -rf deps 40 | clean: 41 | rm -f highlighters/*.cpp highlighters/*.o highlighters/*.lxx highlighters/*.ascii.lxi tau.o tau tau.hpp tau.cpp bfpp 42 | deps: 43 | mkdir deps 44 | cd deps && git clone https://github.com/Genivia/RE-flex && cd RE-flex && ./clean.sh && ./build.sh 45 | bfpp: 46 | $(CXX) -DLUA_USE_POPEN -O3 -flto bfpp.c -o bfpp -lm 47 | 48 | tau.hpp: bfpp tau.hpp.in 49 | bfpp < tau.hpp.in > tau.hpp 50 | 51 | tau.cpp: bfpp tau.cpp.in 52 | bfpp < tau.cpp.in > tau.cpp 53 | 54 | tau: $(_S_HL_OBJS) $(_S_HL_A_OBJS) tau.o 55 | $(CXX) $^ deps/RE-flex/lib/libreflex.a -lpthread -lm -o $@ $(CXXFLAGS) 56 | $(STRIPPER) --strip-all tau # stripper? never seen one. 57 | 58 | %.o: %.cpp tau.hpp 59 | $(CXX) $< -c -o $@ $(CXXFLAGS) $(HFLAGS) 60 | 61 | highlighters/%.lxx: highlighters/%.lxi 62 | perl build_highlighter.pl $< > $@ 63 | 64 | highlighters/%.ascii.lxi: highlighters/%.lxi 65 | cp $< $@ && perl -i make_ascii.pl $(<:.lxi=.ascii.lxi) 66 | 67 | highlighters/%.cpp: highlighters/%.lxx 68 | deps/RE-flex/bin/reflex --fast −−noindent $< -o $@ 69 | perl -pi -e "s/^(?:extern )?(void reflex\_code\_[A-Za-z]+)/static \$$1/;" $@ 70 | 71 | highlighters/%.o: highlighters/%.cpp tau.hpp 72 | $(CXX) $< -c -o $@ $(CXXFLAGS) $(HFLAGS) 73 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # tau - a reasonably fast (wip) syntax highlighter. 3 | 4 | Tau is a fast syntax highlighter capable of emitting HTML. It highlights the following languages: 5 | * python 6 | * lua 7 | * c 8 | * c++ 9 | * x86 assembly 10 | * brainfuck 11 | * asm2bf 12 | 13 | This is alpha-grade software, which means it may or may not have obvious bugs. It may also scare you off by it's code quality, but all that is a subject to change. 14 | 15 | ## Benchmarks 16 | 17 | Unicode mode: `0:01.51`s for Boost + a few highlighter sources; around 3'700'000 lines. ASCII mode: `0:00.75`s. 18 | Tau highlights (respectively) 2'000'000 lines of C++ code and ~4'900'000 lines of C++ code per second. 19 | Single thread performance - `648511.11` lines of x86 assembly per second (0.09s) on [this data](https://b.catgirlsare.sexy/kn4FQpJ2.txt). 20 | 21 | ## Building 22 | 23 | ```bash 24 | # Clone the repository 25 | git clone https://github.com/kspalaiologos/tau && cd tau 26 | 27 | # Start with downloading and building the dependencies. 28 | make deps 29 | 30 | # Find out the amount of parallel workers make can launch. 31 | thr=$(find /sys/devices/system/cpu/ -regextype sed -regex '.*/cpu[0-9]\{1,99\}' | wc -l) 32 | 33 | # Start the build 34 | make target=release "-j$thr" all 35 | 36 | # You can also try the following targets: `profile, debug`. 37 | # If you're concerned about compile time, don't set a target. 38 | # Tau usually takes quite a while to compile. 39 | ``` 40 | 41 | ## Usage 42 | 43 | ``` 44 | % ./tau -h 45 | tau: a reasonably fast syntax highlighter. 46 | copyright (c) kamila szewczyk, 2021, agplv3. 47 | usage: 48 | tau [--options] files...flags: 49 | -d dir - set the output directory. 50 | -s syn - override the syntax. 51 | -a - assume ASCII input (visible speedup). 52 | -i - ignore unknown languages. 53 | -j num - override the amount of worker threads. 54 | ``` 55 | 56 | ## Roadmap 57 | 58 | Project's roadmap: 59 | * Improved I/O performance (may require profiling in the ASCII mode to find out the main bottleneck except NFAs). 60 | * Faster highlighters (fancy/fast modes; more optimized regular expressions). 61 | * Code quality improvements - the code has been written hastily without concerns about it's quality. 62 | * asm2bf support 63 | * XML/HTML/CSS support 64 | * JavaScript support 65 | * JSON support 66 | * Perl support (might be tricky) 67 | * Configurable themes 68 | * Emitting all the output into a single file (might require some clever optimizations related to threading). 69 | * Stripping the output's header (fairly simple; will require a small redesign of `tau.hpp.in`'s code churn). 70 | * Less verbose syntax description language. 71 | * Improving the builtin theme; adding a few alternative themes. 72 | 73 | ## Licensing 74 | 75 | AGPLv3. 76 | 77 | ## Contributing 78 | 79 | I'd happily merge good quality changes to the codebase that address issues outlined in the roadmap. Contributors 80 | will be listed in a separate file (or in the readme) along with an outline of their changes in Tau. Feel free to 81 | add yourself on the list before starting a pull request. For the good of this software, I'd like the copyright 82 | over the changes be transferred to me. I make a few promises regarding the project, inter alia: 83 | * Contributor names will stay in the contributor list as long as their code or improvements are still present in the codebase. 84 | * The software won't be relicensed to a non-GPL and non-derivative licenses (if it'll ever be relicensed). 85 | * The software will always remain free and open-source. 86 | 87 | ## Adding your own language 88 | 89 | If you're reading this section, you probably want to add your own language's syntax highlighter to Tau. 90 | Great! Let's add syntax highlighting for brainfuck. First, update the makefile to build your highlighter. 91 | 92 | ```diff 93 | CXXFLAGS := $(or ${CXXFLAGS.${target}},-Wall -Wextra -O0) 94 | 95 | -_S_HIGHLIGHTERS := x86asm c cpp lua python 96 | +_S_HIGHLIGHTERS := x86asm c cpp lua python brainfuck 97 | _S_HL_OBJS := $(patsubst %, highlighters/%.o, $(_S_HIGHLIGHTERS)) 98 | _S_HL_A_OBJS := $(patsubst %, highlighters/%.ascii.o, $(_S_HIGHLIGHTERS)) 99 | ``` 100 | 101 | Then, let's create the highlighter's syntax description. 102 | 103 | ```bash 104 | touch highlighters/brainfuck.lxi 105 | ``` 106 | 107 | Start off by setting the name of your language and the colors you want to use in your highlighter. You can find an up-to-date list in `tau.hpp.in`. 108 | 109 | ``` 110 | [syntax brainfuck] 111 | [top #define COLOR_GROUP1 2] 112 | [top #define COLOR_GROUP2 5] 113 | [top #define COLOR_GROUP3 4] 114 | [top #define COLOR_GROUP4 9] 115 | [top #define COLOR_COMMENT 8] 116 | [top #define COLOR_NONE 0] 117 | ``` 118 | 119 | Then, define a few helper macros for your grammar: 120 | 121 | ``` 122 | -- set the source of data 123 | [reader wstr] 124 | -- we're making a unicode-aware highlighter. 125 | [unicode 1] 126 | -- the default prefix of literals (a consequence of `unicode`) 127 | [literalprefix L] 128 | ``` 129 | 130 | You can also set a few of other macros (we won't need them in this grammar): 131 | 132 | ``` 133 | [viewkind wstring_view] 134 | [strkind wstring] 135 | [identifier \p{UnicodeIdentifierStart}\p{UnicodeIdentifierPart}*] 136 | ``` 137 | 138 | They're later processed by another script which asciifies the highlighters (and replaces all the definitions). Let's move on to the grammar. 139 | 140 | ``` 141 | [grammar] 142 | 143 | %% 144 | 145 | .+ printer << COLOR_NONE << ${reader}(); 146 | 147 | %% 148 | ``` 149 | 150 | This very simple grammar will simply output whatever it reads. Let's make something better: 151 | 152 | ``` 153 | %% 154 | 155 | [\+\-]+ printer << COLOR_GROUP1 << ${reader}(); 156 | [><]+ printer << COLOR_GROUP2 << ${reader}(); 157 | [\.\,]+ printer << COLOR_GROUP3 << ${reader}(); 158 | [\[\]]+ printer << COLOR_GROUP4 << ${reader}(); 159 | [ \t\r\n\f\v] printer >> ${reader}()[0]; 160 | [^\+\-><\[\]\.\,]* printer << COLOR_COMMENT << ${reader}(); 161 | 162 | %% 163 | ``` 164 | 165 | Note: `>>` is used with _strings_ and _characters_. For _strings_, it highlights escape sequences inside them. 166 | With characters, it prints them. Use `<<` for anything else. 167 | 168 | Now, let's do something more advanced - `[-][...]` comments. The main issue that stops us from simply 169 | using `"[-][".*?"]"` is the fact, that for example `[-][test [test] test]` won't be highlighted correctly. 170 | For this, we will use multiple states. 171 | 172 | ``` 173 | [grammar] 174 | 175 | %x INCOMMENT 176 | 177 | %% 178 | 179 | (\[(.|\n)*?\])|([^\[\]]+) printer << COLOR_COMMENT << ${reader}(); 180 | \] printer << COLOR_COMMENT >> ${literalprefix}']'; start(INITIAL); 181 | 182 | "[-][" printer << COLOR_COMMENT << ${reader}(); start(INCOMMENT); 183 | [\+\-]+ printer << COLOR_GROUP1 << ${reader}(); 184 | [><]+ printer << COLOR_GROUP2 << ${reader}(); 185 | [\.\,]+ printer << COLOR_GROUP3 << ${reader}(); 186 | [\[\]]+ printer << COLOR_GROUP4 << ${reader}(); 187 | [ \t\r\n\f\v] printer >> ${reader}()[0]; 188 | [^\+\-><\[\]\.\,]* printer << COLOR_COMMENT << ${reader}(); 189 | 190 | %% 191 | ``` 192 | 193 | Now we're ready to add our highlighter to the recognition module (in `tau.cpp.in`): 194 | 195 | ```diff 196 | rewind(in); 197 | 198 | if(shebang[0] == '#' && shebang[1] == '!') { 199 | std::string str(shebang + 2); 200 | if(is_lang(str, "python")) { $(highlight_lang("python")) return; } 201 | + else if(is_lang(str, "tritium", "brainfuck", "/bf")) { $(highlight_lang("brainfuck")) return; } 202 | } 203 | ``` 204 | 205 | after we support the shebang (i.e. `#!/bin/bf` will be recognized as brainfuck), we register a new 206 | file extension: 207 | 208 | ```diff 209 | else if(ext == ".lua") 210 | $(highlight_lang("lua")) 211 | +else if(ext == ".bf") 212 | + $(highlight_lang("brainfuck")) 213 | else if(ext == ".py") 214 | $(highlight_lang("python")) 215 | ``` 216 | 217 | finally, we register the brainfuck highlighter in `highlighters/all.hpp`: 218 | 219 | ``` 220 | _all_highlighter(python); 221 | +_all_highlighter(brainfuck); 222 | 223 | _all_highlighter_ascii(c); 224 | _all_highlighter_ascii(x86asm); 225 | _all_highlighter_ascii(cpp); 226 | _all_highlighter_ascii(lua); 227 | _all_highlighter_ascii(python); 228 | +_all_highlighter_ascii(brainfuck); 229 | ``` 230 | 231 | ... and the language support is finished. now, you can `make -j4 all` to verify the correctness of 232 | your highlighter and then run `make target=release -j4 all` to build an optimized binary to benchmark 233 | your highlighter. 234 | -------------------------------------------------------------------------------- /build_highlighter.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # Tau - a reasonably fast syntax highlighter. 4 | # Copyright (C) 2021 Kamila Szewczyk 5 | # 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Affero General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU Affero General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Affero General Public License 17 | # along with this program. If not, see . 18 | 19 | use 5.010; use warnings; use strict; 20 | 21 | my $reading_grammar = 0; 22 | my %opt = (); 23 | my $grammar = ''; 24 | $opt{'toplevel'} = ''; 25 | 26 | while(<>) { 27 | if($_ =~ /^\-\-/) { next; } 28 | 29 | if(!$reading_grammar) { 30 | if($_ =~ /^\[[ \t]*([A-Za-z0-9_-]+)[ \t]*([^\r\n]*)[ \t]*\]$/) { 31 | if($1 eq 'grammar') { 32 | $reading_grammar = 1; next; 33 | } elsif($1 eq 'top') { 34 | $opt{'toplevel'} .= $2 . "\n"; 35 | } elsif($1 eq 'data') { 36 | $opt{'instdata'} .= $2 . "\n"; 37 | } else { 38 | $2 eq "" ? ($opt{$1} = "") : ($opt{$1} = $2); 39 | } 40 | } 41 | } 42 | 43 | $grammar .= $_ if($reading_grammar); 44 | } 45 | 46 | $opt{'instdata'} //= ''; 47 | $opt{'unicode'} //= ''; 48 | 49 | if($opt{'unicode'} eq '1') { 50 | $opt{'unicode'} = 'unicode'; 51 | $opt{'printer'} = 'printer'; 52 | } else { 53 | $opt{'unicode'} = ''; 54 | $opt{'printer'} = 'ascii_printer'; 55 | } 56 | 57 | $opt{'grammar'} = $grammar; 58 | 59 | while () { 60 | # replace twice 61 | s=\$\{([A-Za-z0-9_-]+)\}=$opt{$1}//die"undefined $1"=ge; 62 | s=\$\{([A-Za-z0-9_-]+)\}=$opt{$1}//die"undefined $1"=ge; 63 | print; 64 | } 65 | 66 | # printer: printer / ascii_printer 67 | # defines: add your custom highlighting colors. 68 | # syntax: [your language's name] 69 | # unicode: 1 / 0 70 | # grammar: [your language's grammar] 71 | 72 | __DATA__ 73 | %top { 74 | #include 75 | #include 76 | #include 77 | 78 | #define PRINTER_TYPE tau::${printer} 79 | 80 | ${toplevel} 81 | } 82 | 83 | %o class=${syntax}_highlight lex=process fast params="PRINTER_TYPE & printer" 84 | 85 | %{ 86 | class ${syntax}_highlight : public Lexer { 87 | public: 88 | using Lexer::process; 89 | int process(PRINTER_TYPE &); 90 | private: 91 | ${instdata} 92 | }; 93 | %} 94 | 95 | %o ${unicode} nodefault 96 | 97 | ${grammar} 98 | 99 | void highlight_${syntax}(FILE * f, PRINTER_TYPE & output) { ${syntax}_highlight highlight; highlight.process(f, output); } 100 | 101 | -------------------------------------------------------------------------------- /highlighters/all.hpp: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _ALL_HPP 3 | #define _ALL_HPP 4 | 5 | #include 6 | #include 7 | 8 | #define _all_highlighter(name) void highlight_##name(FILE * f, tau::printer & output) 9 | #define _all_highlighter_ascii(name) void highlight_##name##_a(FILE * f, tau::ascii_printer & output) 10 | 11 | _all_highlighter(c); 12 | _all_highlighter(x86asm); 13 | _all_highlighter(cpp); 14 | _all_highlighter(lua); 15 | _all_highlighter(python); 16 | _all_highlighter(brainfuck); 17 | _all_highlighter(asm2bf); 18 | 19 | _all_highlighter_ascii(c); 20 | _all_highlighter_ascii(x86asm); 21 | _all_highlighter_ascii(cpp); 22 | _all_highlighter_ascii(lua); 23 | _all_highlighter_ascii(python); 24 | _all_highlighter_ascii(brainfuck); 25 | _all_highlighter_ascii(asm2bf); 26 | 27 | #undef _all_highlighter 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /highlighters/asm2bf.lxi: -------------------------------------------------------------------------------- 1 | [syntax asm2bf] 2 | [top #define COLOR_KEY 2] 3 | [top #define COLOR_KEY_X 5] 4 | [top #define COLOR_KEY_Y 13] 5 | [top #define COLOR_META 4] 6 | [top #define COLOR_STR 9] 7 | [top #define COLOR_IMMEDIATE 11] 8 | [top #define COLOR_COMMENT 8] 9 | [top #define COLOR_FNS 14] 10 | [top #define COLOR_STAY_AWAY 1] 11 | [top #define COLOR_OPER 12] 12 | [top #define COLOR_NONE 0] 13 | 14 | [reader wstr] 15 | [viewkind wstring_view] 16 | [strkind wstring] 17 | [literalprefix L] 18 | [unicode 1] 19 | -- Tau - a reasonably fast syntax highlighter. 20 | -- Copyright (C) 2021 Kamila Szewczyk 21 | -- 22 | -- This program is free software: you can redistribute it and/or modify 23 | -- it under the terms of the GNU Affero General Public License as published by 24 | -- the Free Software Foundation, either version 3 of the License, or 25 | -- (at your option) any later version. 26 | -- 27 | -- This program is distributed in the hope that it will be useful, 28 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of 29 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 30 | -- GNU Affero General Public License for more details. 31 | -- 32 | -- You should have received a copy of the GNU Affero General Public License 33 | -- along with this program. If not, see . 34 | 35 | -- A knob for Lua highlighter to indicate if we're in single-line mode. 36 | [data bool is_single = false;] 37 | -- Depth of paren nesting (required to find where $() will close). 38 | [data unsigned paren_nesting = 0;] 39 | 40 | [grammar] 41 | 42 | %x LUA 43 | 44 | ID [a-zA-Z_][a-zA-Z_0-9]* 45 | n [0-9]+ 46 | exp [Ee][+-]?{n} 47 | number ({n}|{n}[.]{n}){exp}? 48 | 49 | %% 50 | 51 | { 52 | "--[["(.|\n)*?"]]" printer << COLOR_COMMENT << ${reader}(); 53 | "--[=["(.|\n)*?"]=]" printer << COLOR_COMMENT << ${reader}(); 54 | "--[==["(.|\n)*?"]==]" printer << COLOR_COMMENT << ${reader}(); 55 | "--[===["(.|\n)*?"]===]" printer << COLOR_COMMENT << ${reader}(); 56 | "--".*$ printer << COLOR_COMMENT << ${reader}(); 57 | "[["(.|\n)*?"]]" printer << COLOR_STR << ${reader}(); 58 | "[=["(.|\n)*?"]=]" printer << COLOR_STR << ${reader}(); 59 | "[==["(.|\n)*?"]==]" printer << COLOR_STR << ${reader}(); 60 | "[===["(.|\n)*?"]===]" printer << COLOR_STR << ${reader}(); 61 | \"([^\\\"]|\\.)*\" printer << COLOR_STR >> ${reader}(); 62 | \'([^\\\']|\\.)*\' printer << COLOR_STR >> ${reader}(); 63 | \( paren_nesting++; printer >> ${literalprefix}'('; 64 | \) paren_nesting--; printer >> ${literalprefix}')'; if(paren_nesting == 0 && !is_single) start(INITIAL); 65 | "..."|[;=\[\]><]|([\~<>=]=)|".."|[\+\-\*\/\%\&\|\~\#\^]|"<<"|">>" printer << COLOR_OPER << ${reader}(); 66 | not|or|and|break|goto|do|end|while|repeat|until|if|then|elseif|else|for|in|function|local|return printer << COLOR_KEY_X << ${reader}(); 67 | nil|false|true printer << COLOR_KEY << ${reader}(); 68 | [a-zA-Z_][a-zA-Z_0-9\.\:]* { 69 | if (${reader}().find_first_of(${literalprefix}":.") != std::${strkind}::npos) 70 | printer << COLOR_FNS << ${reader}(); 71 | else 72 | printer << COLOR_NONE << ${reader}(); 73 | } 74 | [a-zA-Z_][a-zA-Z_0-9\.\:]*[ \t]*\( printer << COLOR_FNS << std::${viewkind}(${reader}()).substr(0, ${reader}().length() - 1) << std::${strkind}(${literalprefix}"("); paren_nesting++; 75 | "<"{ID}">" printer << COLOR_META << ${reader}(); 76 | ::{ID}:: printer << COLOR_META << ${reader}(); 77 | \n printer << COLOR_NONE >> ${literalprefix}'\n'; if(is_single) start(INITIAL); 78 | [ \t\r]+ printer << COLOR_NONE << ${reader}(); 79 | {number} printer << COLOR_IMMEDIATE << ${reader}(); 80 | 0[xX][0-9A-Fa-f]+ printer << COLOR_IMMEDIATE << ${reader}(); 81 | . printer >> (${reader}()[0]); 82 | } 83 | 84 | ;.*$ printer << COLOR_COMMENT << ${reader}(); 85 | "$(" printer >> ${literalprefix}"$("; paren_nesting = 1; is_single = false; start(LUA); 86 | ^# printer >> ${literalprefix}'#'; is_single = true; start(LUA); 87 | \.. printer << COLOR_IMMEDIATE << ${reader}(); 88 | [0-9]+ printer << COLOR_IMMEDIATE << ${reader}(); 89 | r[1-6]|f[1-4]|[sS][pP] printer << COLOR_FNS << ${reader}(); 90 | \"([^\\\"]|\\.)*\" printer << COLOR_STR << ${reader}(); 91 | [\*\&][A-Za-z][0-9A-Za-z_]* printer << COLOR_KEY << ${reader}(); 92 | [\@\%][A-Za-z][0-9A-Za-z_]* printer << COLOR_OPER << ${reader}(); 93 | \?.*$ printer << COLOR_META << ${reader}(); 94 | raw|lbl|nav printer << COLOR_STAY_AWAY << ${reader}(); 95 | cbs|cbe|cbegin|cend|jnz|jz|jz_|cjnz|cjn|cjz|ret|end|cflip|x04|jmp printer << COLOR_OPER << ${reader}(); 96 | vxcall|rse|seg|stk|org|db|txt|rcl|sto|movf|rcl|crcl|crc|sto|csto|cst|amp|smp|ots|cot|cots|cam|csm|camp|csmp printer << COLOR_KEY << ${reader}(); 97 | pop|cpop|dp2|dup2|cpo|push|psh|cps|cpsh|cpush|srv|crv|csrv|finv|ret|fmul|fmu|fdiv|fdi|fadd|fad|fsub|fsu|dup|freduce|fre|sgt|spt|sle|tps|fcpush|fps|fcpsh|fcpop|fpo printer << COLOR_KEY_X << ${reader}(); 98 | pow|xgt|xle|xlt|axl|add|cadd|and|dec|div|cdi|cdiv|eq|eq_|ceq|ge|ge_|cge|gt|gt_|cgt|in|in_|cin|inc|le|le_|cle|lt|lt_|clt|mod|cmd|cmod|mov|lea|cmov|cmo|mul|cmu|cmul|ne|ne_|xor|neq|cne|neg|not|or|or_|out|cout|cou|sub|swp|xchg|cswp|csw|cxchg|clrf|band|bor|bxor|bneg|x00|x01|x02|x03|gcd|cgc|cgcd|par|cpa|cpar|candeq|candne|candle|candge|candlt|candgt|coreq|corne|corle|corge|corlt|cxoreq|cxorne|cxorle|cxorge|cxorgt|cxorlt|x0[5-9A-Fa-f]|x1[0-6]|shl|shr|sgmul|sgdiv|sgmod|sgsub|sgadd|sgn|abs|sneg|s0[012] printer << COLOR_KEY_Y << ${reader}(); 99 | [ \n\f\v\t\r]+ printer << COLOR_NONE << ${reader}(); 100 | . printer >> (${reader}()[0]); 101 | 102 | %% 103 | -------------------------------------------------------------------------------- /highlighters/brainfuck.lxi: -------------------------------------------------------------------------------- 1 | [syntax brainfuck] 2 | [top #define COLOR_GROUP1 2] 3 | [top #define COLOR_GROUP2 5] 4 | [top #define COLOR_GROUP3 4] 5 | [top #define COLOR_GROUP4 9] 6 | [top #define COLOR_COMMENT 8] 7 | [top #define COLOR_NONE 0] 8 | [reader wstr] 9 | [unicode 1] 10 | [literalprefix L] 11 | -- Tau - a reasonably fast syntax highlighter. 12 | -- Copyright (C) 2021 Kamila Szewczyk 13 | -- 14 | -- This program is free software: you can redistribute it and/or modify 15 | -- it under the terms of the GNU Affero General Public License as published by 16 | -- the Free Software Foundation, either version 3 of the License, or 17 | -- (at your option) any later version. 18 | -- 19 | -- This program is distributed in the hope that it will be useful, 20 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | -- GNU Affero General Public License for more details. 23 | -- 24 | -- You should have received a copy of the GNU Affero General Public License 25 | -- along with this program. If not, see . 26 | [grammar] 27 | 28 | %x INCOMMENT 29 | 30 | %% 31 | 32 | (\[(.|\n)*?\])|([^\[\]]+) printer << COLOR_COMMENT << ${reader}(); 33 | \] printer << COLOR_COMMENT >> ${literalprefix}']'; start(INITIAL); 34 | 35 | "[-][" printer << COLOR_COMMENT << ${reader}(); start(INCOMMENT); 36 | [\+\-]+ printer << COLOR_GROUP1 << ${reader}(); 37 | [><]+ printer << COLOR_GROUP2 << ${reader}(); 38 | [\.\,]+ printer << COLOR_GROUP3 << ${reader}(); 39 | [\[\]]+ printer << COLOR_GROUP4 << ${reader}(); 40 | [ \t\r\n\f\v] printer >> ${reader}()[0]; 41 | [^\+\-><\[\]\.\,]* printer << COLOR_COMMENT << ${reader}(); 42 | 43 | %% -------------------------------------------------------------------------------- /highlighters/c.lxi: -------------------------------------------------------------------------------- 1 | [syntax c] 2 | [top #define COLOR_KEY 2] 3 | [top #define COLOR_KEY_X 5] 4 | [top #define COLOR_META 4] 5 | [top #define COLOR_STR 9] 6 | [top #define COLOR_IMMEDIATE 11] 7 | [top #define COLOR_COMMENT 8] 8 | [top #define COLOR_FNS 14] 9 | [top #define COLOR_NONE 0] 10 | [top #define COLOR_OPER 12] 11 | [reader wstr] 12 | [viewkind wstring_view] 13 | [strkind wstring] 14 | [literalprefix L] 15 | [unicode 1] 16 | [identifier \p{UnicodeIdentifierStart}\p{UnicodeIdentifierPart}*] 17 | -- Tau - a reasonably fast syntax highlighter. 18 | -- Copyright (C) 2021 Kamila Szewczyk 19 | -- 20 | -- This program is free software: you can redistribute it and/or modify 21 | -- it under the terms of the GNU Affero General Public License as published by 22 | -- the Free Software Foundation, either version 3 of the License, or 23 | -- (at your option) any later version. 24 | -- 25 | -- This program is distributed in the hope that it will be useful, 26 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | -- GNU Affero General Public License for more details. 29 | -- 30 | -- You should have received a copy of the GNU Affero General Public License 31 | -- along with this program. If not, see . 32 | [grammar] 33 | 34 | O [0-7] 35 | D [0-9] 36 | NZ [1-9] 37 | L [a-zA-Z_] 38 | A [a-zA-Z_0-9] 39 | H [a-fA-F0-9] 40 | HP (0[xX]) 41 | E ([Ee][+-]?{D}+) 42 | P ([Pp][+-]?{D}+) 43 | FS (f|F|l|L) 44 | IS (((u|U)(l|L|ll|LL)?)|((l|L|ll|LL)(u|U)?)) 45 | CP (u|U|L) 46 | SP (u8|u|U|L) 47 | 48 | %% 49 | 50 | "/*"(.|\n)*?"*/" printer << COLOR_COMMENT << ${reader}(); 51 | "//".* printer << COLOR_COMMENT << ${reader}(); 52 | (auto|break|case|const|continue|default|do|else|enum|extern|for|goto|if|inline|register|restrict|return|short|sizeof|static|struct|switch|typedef|union|volatile|while|noreturn|static_assert|thread_local|alignof|alignas|asm|fortran|_Alignas|_Alignof|_Atomic|_Generic|_Noreturn|_Static_assert|_Thread_local)([ \t\r\f\n]*\()? { if(${reader}().back() != L'(') printer << COLOR_KEY_X << ${reader}(); else {printer << COLOR_KEY_X << std::${viewkind}(${reader}()).substr(0, ${reader}().length() - 1) << std::${strkind}(${literalprefix}"(");} } 53 | (size_t|false|true|int_least8_t|uint_least8_t|int_least16_t|uint_least16_t|int_least32_t|uint_least32_t|int_least64_t|uint_least64_t|int_fast8_t|uint_fast8_t|int_fast16_t|uint_fast16_t|int_fast32_t|uint_fast32_t|int_fast64_t|uint_fast64_t|intptr_t|uintptr_t|intmax_t|uintmax_t|va_list|char|double|float|int|long|short|signed|unsigned|void|_Boolean|_Complex|_Decimal128|_Decimal32|_Decimal64|_Imaginary|bool|complex|imaginary|int8_t|uint8_t|int16_t|uint16_t|int32_t|uint32_t|int64_t|uint64_t|__m64|__m128|__m256|__m512)([ \t\r\n\f]*\()? { if(${reader}().back() != L'(') printer << COLOR_KEY << ${reader}(); else {printer << COLOR_KEY << std::${viewkind}(${reader}()).substr(0, ${reader}().length() - 1) << std::${strkind}(${literalprefix}"(");} } 54 | \"([^\\\"]|\\.)*\" printer << COLOR_STR >> ${reader}(); 55 | L?'(\\.|[^\\'\n])+' printer << COLOR_STR << ${reader}(); 56 | "..."|(([\+\-\*\/\%\&\|\^]|"<<"|">>")?=)|"||"|"&&"|"=="|"!="|"<="|">="|"->"|"++"|"--"|[\+\-=\>\<\|\&\*\%\/\?\^\~\!]|"<<"|">>" printer << COLOR_OPER << ${reader}(); 57 | \#(.|\n)*?[^\\]\n printer << COLOR_META << ${reader}(); 58 | [ \t\r\f\n]+ printer << COLOR_NONE << ${reader}(); 59 | [A-Za-z_][A-Za-z0-9_]_t[ \t]+ printer << COLOR_KEY << ${reader}(); 60 | [A-Za-z_][A-Za-z0-9_]*[ \t\r\f\n]*\( { printer << COLOR_FNS << std::${viewkind}(${reader}()).substr(0, ${reader}().length() - 1) << std::${strkind}(${literalprefix}"("); } 61 | {HP}{H}+{IS}? printer << COLOR_IMMEDIATE << ${reader}(); 62 | {NZ}{D}*{IS}? printer << COLOR_IMMEDIATE << ${reader}(); 63 | "0"{O}*{IS}? printer << COLOR_IMMEDIATE << ${reader}(); 64 | {D}+{E}{FS}? printer << COLOR_IMMEDIATE << ${reader}(); 65 | {D}*"."{D}+{E}?{FS}? printer << COLOR_IMMEDIATE << ${reader}(); 66 | {D}+"."{E}?{FS}? printer << COLOR_IMMEDIATE << ${reader}(); 67 | {HP}{H}+{P}{FS}? printer << COLOR_IMMEDIATE << ${reader}(); 68 | {HP}{H}*"."{H}+{P}{FS}? printer << COLOR_IMMEDIATE << ${reader}(); 69 | {HP}{H}+"."{P}{FS}? printer << COLOR_IMMEDIATE << ${reader}(); 70 | ${identifier} printer << ${reader}(); 71 | . printer >> (${reader}()[0]); 72 | 73 | %% 74 | -------------------------------------------------------------------------------- /highlighters/cpp.lxi: -------------------------------------------------------------------------------- 1 | [syntax cpp] 2 | [top #define COLOR_KEY 2] 3 | [top #define COLOR_KEY_X 5] 4 | [top #define COLOR_META 4] 5 | [top #define COLOR_STR 9] 6 | [top #define COLOR_IMMEDIATE 11] 7 | [top #define COLOR_COMMENT 8] 8 | [top #define COLOR_FNS 14] 9 | [top #define COLOR_OPER 12] 10 | [top #define COLOR_NONE 0] 11 | [reader wstr] 12 | [viewkind wstring_view] 13 | [strkind wstring] 14 | [literalprefix L] 15 | [unicode 1] 16 | [identifier \p{UnicodeIdentifierStart}\p{UnicodeIdentifierPart}*] 17 | -- Tau - a reasonably fast syntax highlighter. 18 | -- Copyright (C) 2021 Kamila Szewczyk 19 | -- 20 | -- This program is free software: you can redistribute it and/or modify 21 | -- it under the terms of the GNU Affero General Public License as published by 22 | -- the Free Software Foundation, either version 3 of the License, or 23 | -- (at your option) any later version. 24 | -- 25 | -- This program is distributed in the hope that it will be useful, 26 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | -- GNU Affero General Public License for more details. 29 | -- 30 | -- You should have received a copy of the GNU Affero General Public License 31 | -- along with this program. If not, see . 32 | [grammar] 33 | 34 | O [0-7] 35 | D [0-9] 36 | NZ [1-9] 37 | L [a-zA-Z_] 38 | A [a-zA-Z_0-9] 39 | H [a-fA-F0-9] 40 | HP (0[xX]) 41 | E ([Ee][+-]?{D}+) 42 | P ([Pp][+-]?{D}+) 43 | FS (f|F|l|L) 44 | IS (((u|U)(l|L|ll|LL)?)|((l|L|ll|LL)(u|U)?)) 45 | CP (u|U|L) 46 | SP (u8|u|U|L) 47 | 48 | %% 49 | 50 | "/*"(.|\n)*?"*/" printer << COLOR_COMMENT << ${reader}(); 51 | "//".* printer << COLOR_COMMENT << ${reader}(); 52 | (and|or|not|requires|concept|reinterpret_cast|static_cast|template|thread_local|this|throw|try|typeid|typename|using|virtual|final|friend|mutable|namespace|noexcept|operator|override|private|protected|public|explicit|export|false|true|catch|class|constexpr|const_cast|decltype|delete|dynamic_cast|auto|break|case|const|continue|default|do|else|enum|extern|for|goto|if|inline|register|restrict|return|short|sizeof|static|struct|switch|typedef|union|volatile|while|noreturn|static_assert|thread_local|alignof|alignas|asm|fortran|_Alignas|_Alignof|_Atomic|_Generic|_Noreturn|_Static_assert|_Thread_local)([ \t\r\f\n]*\()? { if(${reader}().back() != L'(') printer << COLOR_KEY_X << ${reader}(); else {printer << COLOR_KEY_X << std::${viewkind}(${reader}()).substr(0, ${reader}().length() - 1) << std::${strkind}(${literalprefix}"(");} } 53 | (nullptr|int_least8_t|uint_least8_t|int_least16_t|uint_least16_t|int_least32_t|uint_least32_t|int_least64_t|uint_least64_t|int_fast8_t|uint_fast8_t|int_fast16_t|uint_fast16_t|int_fast32_t|uint_fast32_t|int_fast64_t|uint_fast64_t|intptr_t|uintptr_t|intmax_t|uintmax_t|va_list|char|double|float|int|long|short|signed|unsigned|void|_Boolean|_Complex|_Decimal128|_Decimal32|_Decimal64|_Imaginary|bool|complex|imaginary|int8_t|uint8_t|int16_t|uint16_t|int32_t|uint32_t|int64_t|uint64_t|__m64|__m128|__m256|__m512)([ \t\r\n\f]*\()? { if(${reader}().back() != L'(') printer << COLOR_KEY << ${reader}(); else {printer << COLOR_KEY << std::${viewkind}(${reader}()).substr(0, ${reader}().length() - 1) << std::${strkind}(${literalprefix}"(");} } 54 | ([LU]|(u(8?)))?\"([^\\\"]|\\.)*\" printer << COLOR_STR >> ${reader}(); 55 | [uUL]?'(\\.|[^\\'\n])+' printer << COLOR_STR >> ${reader}(); 56 | \#(.|\n)*?[^\\]\n printer << COLOR_META << ${reader}(); 57 | "..."|(([\+\-\*\/\%\&\|\^]|"<<"|">>")?=)|"<=>"|"||"|"&&"|"=="|"!="|"<="|">="|"->"|"++"|"--"|[\+\-=\>\<\|\&\*\%\/\?\^\~\!]|"<<"|">>" printer << COLOR_OPER << ${reader}(); 58 | [ \t\r\f\n]+ printer << COLOR_NONE << ${reader}(); 59 | [A-Za-z_]([A-Za-z0-9_]|\:\:)*_t[ \t]+ printer << COLOR_KEY << ${reader}(); 60 | [A-Za-z_]([A-Za-z0-9_]|\:\:)*[ \t\r\f\n]*\( { printer << COLOR_FNS << std::${viewkind}(${reader}()).substr(0, ${reader}().length() - 1) << std::${strkind}(${literalprefix}"("); } 61 | {HP}{H}+{IS}? printer << COLOR_IMMEDIATE << ${reader}(); 62 | {NZ}{D}*{IS}? printer << COLOR_IMMEDIATE << ${reader}(); 63 | "0"{O}*{IS}? printer << COLOR_IMMEDIATE << ${reader}(); 64 | {D}+{E}{FS}? printer << COLOR_IMMEDIATE << ${reader}(); 65 | {D}*"."{D}+{E}?{FS}? printer << COLOR_IMMEDIATE << ${reader}(); 66 | {D}+"."{E}?{FS}? printer << COLOR_IMMEDIATE << ${reader}(); 67 | {HP}{H}+{P}{FS}? printer << COLOR_IMMEDIATE << ${reader}(); 68 | {HP}{H}*"."{H}+{P}{FS}? printer << COLOR_IMMEDIATE << ${reader}(); 69 | {HP}{H}+"."{P}{FS}? printer << COLOR_IMMEDIATE << ${reader}(); 70 | ${identifier} printer << ${reader}(); 71 | . printer >> (${reader}()[0]); 72 | %% 73 | -------------------------------------------------------------------------------- /highlighters/lua.lxi: -------------------------------------------------------------------------------- 1 | [syntax lua] 2 | [top #define COLOR_KEY 2] 3 | [top #define COLOR_KEY_X 5] 4 | [top #define COLOR_META 4] 5 | [top #define COLOR_STR 9] 6 | [top #define COLOR_IMMEDIATE 11] 7 | [top #define COLOR_COMMENT 8] 8 | [top #define COLOR_FNS 14] 9 | [top #define COLOR_OPER 12] 10 | [top #define COLOR_NONE 0] 11 | [reader wstr] 12 | [viewkind wstring_view] 13 | [strkind wstring] 14 | [literalprefix L] 15 | [unicode 1] 16 | -- Tau - a reasonably fast syntax highlighter. 17 | -- Copyright (C) 2021 Kamila Szewczyk 18 | -- 19 | -- This program is free software: you can redistribute it and/or modify 20 | -- it under the terms of the GNU Affero General Public License as published by 21 | -- the Free Software Foundation, either version 3 of the License, or 22 | -- (at your option) any later version. 23 | -- 24 | -- This program is distributed in the hope that it will be useful, 25 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of 26 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 | -- GNU Affero General Public License for more details. 28 | -- 29 | -- You should have received a copy of the GNU Affero General Public License 30 | -- along with this program. If not, see . 31 | [grammar] 32 | 33 | ID [a-zA-Z_][a-zA-Z_0-9]* 34 | n [0-9]+ 35 | exp [Ee][+-]?{n} 36 | number ({n}|{n}[.]{n}){exp}? 37 | 38 | %% 39 | 40 | "--[["(.|\n)*?"]]" printer << COLOR_COMMENT << ${reader}(); 41 | "--[=["(.|\n)*?"]=]" printer << COLOR_COMMENT << ${reader}(); 42 | "--[==["(.|\n)*?"]==]" printer << COLOR_COMMENT << ${reader}(); 43 | "--[===["(.|\n)*?"]===]" printer << COLOR_COMMENT << ${reader}(); 44 | "--".*$ printer << COLOR_COMMENT << ${reader}(); 45 | "[["(.|\n)*?"]]" printer << COLOR_STR << ${reader}(); 46 | "[=["(.|\n)*?"]=]" printer << COLOR_STR << ${reader}(); 47 | "[==["(.|\n)*?"]==]" printer << COLOR_STR << ${reader}(); 48 | "[===["(.|\n)*?"]===]" printer << COLOR_STR << ${reader}(); 49 | \"([^\\\"]|\\.)*\" printer << COLOR_STR >> ${reader}(); 50 | \'([^\\\']|\\.)*\' printer << COLOR_STR >> ${reader}(); 51 | "..."|[;=\[\]><]|([\~<>=]=)|".."|[\+\-\*\/\%\&\|\~\#\^]|"<<"|">>" printer << COLOR_OPER << ${reader}(); 52 | not|or|and|break|goto|do|end|while|repeat|until|if|then|elseif|else|for|in|function|local|return printer << COLOR_KEY_X << ${reader}(); 53 | nil|false|true printer << COLOR_KEY << ${reader}(); 54 | [a-zA-Z_][a-zA-Z_0-9\.\:]* { 55 | if (${reader}().find_first_of(${literalprefix}":.") != std::${strkind}::npos) 56 | printer << COLOR_FNS << ${reader}(); 57 | else 58 | printer << COLOR_NONE << ${reader}(); 59 | } 60 | [a-zA-Z_][a-zA-Z_0-9\.\:]*[ \t]*\( printer << COLOR_FNS << std::${viewkind}(${reader}()).substr(0, ${reader}().length() - 1) << std::${strkind}(${literalprefix}"("); 61 | "<"{ID}">" printer << COLOR_META << ${reader}(); 62 | ::{ID}:: printer << COLOR_META << ${reader}(); 63 | [ \t\r\n]+ printer << COLOR_NONE << ${reader}(); 64 | {number} printer << COLOR_IMMEDIATE << ${reader}(); 65 | 0[xX][0-9A-Fa-f]+ printer << COLOR_IMMEDIATE << ${reader}(); 66 | . printer >> (${reader}()[0]); 67 | 68 | %% 69 | -------------------------------------------------------------------------------- /highlighters/python.lxi: -------------------------------------------------------------------------------- 1 | [syntax python] 2 | [top #define COLOR_KEY 2] 3 | [top #define COLOR_KEY_X 5] 4 | [top #define COLOR_META 4] 5 | [top #define COLOR_STR 9] 6 | [top #define COLOR_IMMEDIATE 11] 7 | [top #define COLOR_COMMENT 8] 8 | [top #define COLOR_FNS 14] 9 | [top #define COLOR_OPER 12] 10 | [top #define COLOR_NONE 0] 11 | [reader wstr] 12 | [viewkind wstring_view] 13 | [strkind wstring] 14 | [literalprefix L] 15 | [idstart \p{UnicodeIdentifierStart}] 16 | [idpart \p{UnicodeIdentifierPart}] 17 | [unicode 1] 18 | -- Tau - a reasonably fast syntax highlighter. 19 | -- Copyright (C) 2021 Kamila Szewczyk 20 | -- 21 | -- This program is free software: you can redistribute it and/or modify 22 | -- it under the terms of the GNU Affero General Public License as published by 23 | -- the Free Software Foundation, either version 3 of the License, or 24 | -- (at your option) any later version. 25 | -- 26 | -- This program is distributed in the hope that it will be useful, 27 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of 28 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 29 | -- GNU Affero General Public License for more details. 30 | -- 31 | -- You should have received a copy of the GNU Affero General Public License 32 | -- along with this program. If not, see . 33 | [grammar] 34 | 35 | %% 36 | 37 | \#.*$ printer << COLOR_COMMENT << ${reader}(); 38 | [uUfFbB]?\"([^\\\"]|\\.)*\" printer << COLOR_STR >> ${reader}(); 39 | [uUfFbB]?\'([^\\\']|\\.)*\' printer << COLOR_STR >> ${reader}(); 40 | [rR][uUfFbB]?\"([^\\\"]|\\.)*\" printer << COLOR_STR << ${reader}(); 41 | [rR][uUfFbB]?\'([^\\\']|\\.)*\' printer << COLOR_STR << ${reader}(); 42 | [uUfFbB][rR]\"([^\\\"]|\\.)*\" printer << COLOR_STR << ${reader}(); 43 | [uUfFbB][rR]\'([^\\\']|\\.)*\' printer << COLOR_STR << ${reader}(); 44 | \'\'\'(.|\n)*?\'\'\' printer << COLOR_STR << ${reader}(); 45 | \"\"\"(.|\n)*?\"\"\" printer << COLOR_STR << ${reader}(); 46 | (0[bB][01_]+)|(0[oO][0-7_]+) printer << COLOR_IMMEDIATE << ${reader}(); 47 | (0[xX][0-9A-Fa-f_]+)|([0-9]+) printer << COLOR_IMMEDIATE << ${reader}(); 48 | [0-9_]+\.([0-9_]+)?([eE][\+\-][0-9_]+)?[jJ]? printer << COLOR_IMMEDIATE << ${reader}(); 49 | print printer << COLOR_FNS << ${reader}(); 50 | from|yield|if|for|class|lambda|if|else|except|with|finally|try|while|elif|assert|nonlocal|global|as|import|from|raise|return|continue|break|pass|del|def printer << COLOR_KEY_X << ${reader}(); 51 | None|True|False printer << COLOR_KEY << ${reader}(); 52 | (\*\*?)|[:=\+\-\~\*\@\%\&\|\^><]|(\.\.\.)|(\/\/?)|">>"|"<<"|in|([=><\!\+\-\*\@\/\%\&\|\^]=)|"<>"|"not"|"is"|"and"|"or"|"as"|"->"|(("<<"|">>"|"**"|"//")=) printer << COLOR_OPER << ${reader}(); 53 | ${idstart}[${idpart}\.]* { 54 | if (${reader}().find(${literalprefix}'.') != std::${strkind}::npos) 55 | printer << COLOR_FNS << ${reader}(); 56 | else 57 | printer << COLOR_NONE << ${reader}(); 58 | } 59 | ${idstart}[${idpart}\.]*[ \t]*\( printer << COLOR_FNS << std::${viewkind}(${reader}()).substr(0, ${reader}().length() - 1) << std::${strkind}(${literalprefix}"("); 60 | [ \t\r\n]+ printer << COLOR_NONE << ${reader}(); 61 | . printer >> (${reader}()[0]); 62 | 63 | %% 64 | -------------------------------------------------------------------------------- /highlighters/x86asm.lxi: -------------------------------------------------------------------------------- 1 | [syntax x86asm] 2 | [top #define COLOR_MNEMONIC 1] 3 | [top #define COLOR_MNEMONIC_X 5] 4 | [top #define COLOR_META 4] 5 | [top #define COLOR_STR 10] 6 | [top #define COLOR_IMMEDIATE 11] 7 | [top #define COLOR_COMMENT 8] 8 | [top #define COLOR_NONE 0] 9 | [reader wstr] 10 | [unicode 1] 11 | -- Tau - a reasonably fast syntax highlighter. 12 | -- Copyright (C) 2021 Kamila Szewczyk 13 | -- 14 | -- This program is free software: you can redistribute it and/or modify 15 | -- it under the terms of the GNU Affero General Public License as published by 16 | -- the Free Software Foundation, either version 3 of the License, or 17 | -- (at your option) any later version. 18 | -- 19 | -- This program is distributed in the hope that it will be useful, 20 | -- but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | -- GNU Affero General Public License for more details. 23 | -- 24 | -- You should have received a copy of the GNU Affero General Public License 25 | -- along with this program. If not, see . 26 | [grammar] 27 | 28 | %% 29 | (?i:\.code|\.data|\.model|\.end|proc|endp|db|dw|dd|dq|dt|do|resb|resw|resd|resq|rest|reso|incbin|equ|times|byte|word|dword|qword|xmmword|tbyte|nosplit|near|far|org|endstruc|istruc|iend|at|align|alignb|ends|offset|short|length|size|public|goto|seg|repeat|until) printer << COLOR_META << ${reader}(); 30 | (?i:al|ah|ax|eax|bl|bh|bx|ebx|cl|ch|cx|ecx|dl|dh|dx|edx|si|esi|di|edi|bp|ebp|sp|esp|cs|ds|ss|es|fs|gs|ip|eip|eflags|id|vip|vif|ac|vm|rf|nt|iopl|of|df|if|tf|sf|zf|af|pf|cf|st0|st1|st2|st3|st4|st5|st6|st7|ss0|ss1|ss2|esp0|esp1|esp2|mm0|mm1|mm2|mm3|mm4|mm5|mm6|mm7|xmm0|xmm1|xmm2|xmm3|xmm4|xmm5|xmm6|xmm7|xmcrt|cr0|cr2|cr3|cr4|gdtr|ldtr|idtr|dr0|dr1|dr2|dr3|dr6|dr7|msr|rax|rbx|rcx|rdx|rsi|rdi|rsp|rbp|r8|r9|r10|r11|r12|r13|r14|r15|r8d|r9d|r10d|r11d|r12d|r13d|r14d|r15d|r8w|r9w|r10w|r11w|r12w|r13w|r14w|r15w|r8l|r9l|r10l|r11l|r12l|r13l|r14l|r15l) printer << COLOR_IMMEDIATE << ${reader}(); 31 | [0-9]+ printer << COLOR_IMMEDIATE << ${reader}(); 32 | [0-9][A-Fa-f0-9]+[hH] printer << COLOR_IMMEDIATE << ${reader}(); 33 | [0-9]+[dD] printer << COLOR_IMMEDIATE << ${reader}(); 34 | 0d[0-9]+ printer << COLOR_IMMEDIATE << ${reader}(); 35 | 0[xhHX][0-9A-Fa-f]+ printer << COLOR_IMMEDIATE << ${reader}(); 36 | \$0[0-9A-Fa-f]+ printer << COLOR_IMMEDIATE << ${reader}(); 37 | [0-7]+[oqOQ] printer << COLOR_IMMEDIATE << ${reader}(); 38 | 0[oqOQ][0-7]+ printer << COLOR_IMMEDIATE << ${reader}(); 39 | 0[byBY][01_]+ printer << COLOR_IMMEDIATE << ${reader}(); 40 | [01_]+[byBY] printer << COLOR_IMMEDIATE << ${reader}(); 41 | aaa|aad|aam|aas|adc|add|and|call|cbw|cdqe|clc|cld|cli|cmc|cmp|cmpsb|cmpsw|cwd|daa|das|dec|div|esc|hlt|idiv|imul|in|inc|int|into|iret|ja|jae|jb|jbe|jc|jcxz|je|jg|jge|jl|jle|jna|jnae|jnb|jnbe|jnc|jne|jng|jnge|jnl|jnle|jno|jnp|jns|jnz|jo|jp|jpe|jpo|js|jz|jmp|lahf|lar|lds|lea|les|lock|lodsb|lodsw|loop|loope|loopz|loopnz|loopne|mov|movs|movsb|movsw|mul|neg|nop|not|or|out|pop|popf|push|pushf|rcl|rcr|rep|repe|repne|repnz|repz|ret|retn|retf|rol|ror|sahf|sal|sar|sbb|scasb|scasw|shl|shr|stc|std|sti|stosb|stosw|sub|test|wait|xchg|xlat|xor|bound|enter|ins|leave|outs|popa|pusha|arpl|clts|lar|lgdt|lidt|lldt|lmsw|loadall|lsl|ltr|sgdt|sidt|sldt|smsw|str|verr|verw|bsf|bsr|bt|btc|btr|bts|cdq|cmpsd|cwde|insb|insw|insd|iret|iretd|jcxz|jecxz|lsf|lgs|lss|lodsd|loopw|loopd|loopew|looped|loopzw|loopzd|loopnew|loopned|loopnzw|loopnzd|movsw|movsd|movsx|movzx|popad|popfd|pushad|pushfd|scasd|seta|setae|setb|setbe|setc|sete|setg|setge|setl|setle|setna|setnae|setnb|setnbe|setnc|setne|setng|setnge|setnl|setnle|setno|setnp|setns|setnz|seto|setp|setpe|setpo|sets|setz|shld|shrd|stosb|stosw printer << COLOR_MNEMONIC << ${reader}(); 42 | bswap|cmpxchg|invd|invlpg|wbinvd|xadd|cpuid|cmpxchg8b|rdmsr|rdtsc|wrmsr|rsm|rdpmc|emms|movd|movq|packssdw|packsswb|packuswb|paddb|paddd|paddsb|paddsw|paddusb|paddusw|paddw|pand|pandn|pcmpeqb|pcmpeqd|pcmpeqw|pcmpgtb|pcmpgtd|pcmpgtw|pmaddwd|pmulhw|pmullw|por|pslld|psllq|psllw|psrad|psraw|psrld|psrlq|psrlw|psubb|psubd|psubsb|psubsw|psubusb|psubusw|psubw|punpckhbw|punpckhdq|punpckhwd|punpcklbw|punpckldq|punpcklwd|pxor|paveb|paddsiw|pmagw|pdistib|psubsiw|pmvzb|pmulhrw|pmvnzb|pmvlzb|pmvgezb|pmulhriw|pmachriw|syscall|sysret|femms|pavgusb|pf2id|pfacc|pfadd|pfcmpeq|pfcmpge|pfcmpgt|pfmax|pfmin|pfmul|pfrcp|pfrcpit1|pfrcpit2|pfrsqit1|pfrsqrt|pfsub|pfsubr|pi2fd|pmulhrw|prefetch|prefetchw|pf2iw|pfnacc|pfpnacc|pi2fw|pswapd|cmova|cmovae|cmovb|cmovbe|cmovc|cmove|cmovg|cmovge|cmovl|cmovle|cmovna|cmovnae|cmovnb|cmovnbe|cmovnc|cmovne|cmovng|cmovnge|cmovnl|cmovnle|cmovno|cmovnp|cmovns|cmovnz|cmovo|cmovp|cmovpe|cmovpo|cmovs|cmovz|sysenter|sysexit|ud2|fcmov|fcmovb|fcmovbe|fcmove|fcmovnb|fcmovnbe|fcmovne|fcmovnu|fcmovu|fcomi|fcomip|fucomi|fucomip|maskmovq|movntps|movntq|prefetch0|prefetch1|prefetch2|prefetchnta|sfence|fxrstor|fxsaveaddps|addss|cmpps|cmpss|comiss|cvtpi2ps|cvtps2pi|cvtsi2ss|cvtss2si|cvttps2pi|cvttss2si|divps|divss|ldmxcsr|maxps|maxss|minps|minss|movaps|movhlps|movhps|movlhps|movlps|movmskps|movntps|movss|movups|mulps|mulss|rcpps|rcpss|rsqrtps|rsqrtss|shufps|sqrtps|sqrtss|stmxcsr|subps|subss|ucomiss|unpckhps|unpcklpsi|andnps|andps|orps|pavgb|pavgw|pextrw|pinsrw|pmaxsw|pmaxub|pminsw|pminub|pmovmskb|pmulhuw|psadbw|pshufw|xorps|mask|movq|psadbw|pmaxsw|pminsw|movntq|pmulhuw|pavgw|pavgb|pmaxub|pminub|pmovmskb|shufps|pextrw|pinsrw|cmpss|cmpps|sfence|stmxcsr|ldmxcsr|pshufw|maxss|maxps|divss|divps|minss|minps|subss|subps|mulss|mulps|addss|addps|xorps|orps|andnps|andps|rcpss|rcpps|rsqrtss|rsqrtp|sqrtss|sqrtps|comiss|ucomiss|cvtss2si|cvtps2pi|cvttss2si|cvttps2pi|movntps|cvtsi2ss|cvtpi2ps|movaps|movaps|prefetch2|prefetch1|prefetch0|prefetchnta|movhps|movlhps|movhps|unpckhps|unpcklps|movlps|movhlps|movlps|movss|movups|movss|movupsclflush|lfence|maskmovdqu|mfence|movntdq|movnti|movntpd|pause|addpd|addsd|andnpd|andpd|cmppd|cmpsd|comisd|cvtdq2pd|cvtdq2ps|cvtpd2dq|cvtpd2pi|cvtpd2ps|cvtpi2pd|cvtps2dq|cvtps2pd|cvtsd2si|cvtsd2ss|cvtsi2sd|cvtss2sd|cvttpd2dq|cvttpd2pi|cvttps2dq|cvttsd2si|divpd|divsd|maxpd|maxsd|minpd|minsd|movapd|movhpd|movlpd|movmskpd|movsd|movupd|mulpd|mulsd|orpd|shufpd|sqrtpd|sqrtsd|subpd|subsd|ucomisd|unpckhpd|unpcklpd|xorpd|movdq2q|movdqa|movdqu|movq2dq|paddq|psubq|pmuludq|pshufhw|pshuflw|pshufd|pslldq|psrldq|punpckhqdq|punpcklqdq|addsubpd|addsubps|haddpd|haddps|hsubpd|hsubps|movddup|movshdup|movsldup|psignw|psignd|psignb|pshufb|pmulhrsw|pmaddubsw|phsubw|phsubsw|phsubd|phaddw|phaddsw|phaddd|palignr|pabsw|pabsd|pabsb|mpsadbw|phminposuw|pmulld|pmuldq|dpps|dppd|blendps|blendpd|blendvps|blendvpd|pblendvb|pblendw|pminsb|pmaxsb|pminuw|pmaxuw|pminud|pmaxud|pminsd|pmaxsd|roundps|roundss|roundpd|roundsd|insertps|pinsrb|pinsrd|pinsrq|extractps|pextrb|pextrw|pextrd|pextrq|pmovsxbw|pmovzxbw|pmovsxbd|pmovzxbd|pmovsxbq|pmovzxbq|pmovsxwd|pmovzxwd|pmovsxwq|pmovzxwq|pmovsxdq|pmovzxdq|ptest|pcmpeqq|packusdw|movntdqa|lzcnt|popcnt|extrq|insertq|movntsd|movntss|crc32|pcmpestri|pcmpestrm|pcmpistri|pcmpistrm|pcmpgtq|vfmaddpd|vfmaddps|vfmaddsd|vfmaddss|vfmaddsubpd|vfmaddsubps|vfmsubaddpd|vfmsubaddps|vfmsubpd|vfmsubps|vfmsubsd|vfmsubss|vfnmaddpd|vfnmaddps|vfnmaddsd|vfnmaddss|vfnmsubpd|vfnmsubps|vfnmsubsd|vfnmsubss printer << COLOR_MNEMONIC_X << ${reader}(); 43 | ;.*$ printer << COLOR_COMMENT << ${reader}(); 44 | \.?[A-Za-z_][A-Za-z0-9_]* printer << ${reader}(); 45 | \"([^\\\"]|\\.)*\" printer << COLOR_STR << ${reader}(); 46 | \'([^\\\']|\\.)*\' printer << COLOR_STR << ${reader}(); 47 | [ \t\r\f\n]+ printer << COLOR_NONE << ${reader}(); 48 | . printer >> (${reader}()[0]); 49 | %% 50 | -------------------------------------------------------------------------------- /make_ascii.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | # Tau - a reasonably fast syntax highlighter. 4 | # Copyright (C) 2021 Kamila Szewczyk 5 | # 6 | # This program is free software: you can redistribute it and/or modify 7 | # it under the terms of the GNU Affero General Public License as published by 8 | # the Free Software Foundation, either version 3 of the License, or 9 | # (at your option) any later version. 10 | # 11 | # This program is distributed in the hope that it will be useful, 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | # GNU Affero General Public License for more details. 15 | # 16 | # You should have received a copy of the GNU Affero General Public License 17 | # along with this program. If not, see . 18 | 19 | while(<>) { 20 | if($_ =~ /^\[[ \t]*grammar[ \t]*\]$/) { 21 | print; print "AIDENT [A-Za-z_][A-Za-z0-9_]+\n"; 22 | print "IDSTART [A-Za-z_]\n"; 23 | while(<>) { print; } 24 | exit; 25 | } else { 26 | s/^\[[ \t]*reader[ \t]*wstr[ \t]*\]$/[reader str]/; 27 | s/^\[[ \t]*unicode[ \t]*1[ \t]*\]\n//; 28 | s/^\[[ \t]*identifier(.*)\]$/[identifier {AIDENT}]/; 29 | s/^\[[ \t]*syntax[ \t]*(.*)\]$/[syntax \1_a]/; 30 | s/^\[[ \t]*viewkind[ \t]*wstring_view[ \t]*\]$/[viewkind string_view]/; 31 | s/^\[[ \t]*idstart[ \t]*.*[ \t]*\]$/[idstart {IDSTART}]/; 32 | s/^\[[ \t]*idpart[ \t]*.*[ \t]*\]$/[idpart A-Za-z0-9_]/; 33 | s/^\[[ \t]*strkind[ \t]*wstring[ \t]*\]$/[strkind string]/; 34 | s/^\[[ \t]*literalprefix[ \t]*L[ \t]*\]$/[literalprefix]/; 35 | print; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /tau.cpp.in: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Tau - a reasonably fast syntax highlighter. 4 | * Copyright (C) 2021 Kamila Szewczyk 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | // All the include files. 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include "tau.hpp" 34 | #include "highlighters/all.hpp" 35 | 36 | static void help() { 37 | std::cerr << "tau: a reasonably fast syntax highlighter.\n" 38 | << "copyright (c) kamila szewczyk, 2021, agplv3.\n" 39 | << "usage:\n" 40 | << " tau [--options] files..." 41 | << "flags:\n" 42 | << " -d dir - set the output directory.\n" 43 | << " -s syn - override the syntax.\n" 44 | << " -a - assume ASCII input (visible speedup).\n" 45 | << " -i - ignore unknown languages.\n" 46 | << " -j num - override the amount of worker threads.\n" 47 | << std::endl; 48 | std::exit(1); 49 | } 50 | 51 | static bool is_lang(const std::string & shebang, const std::string & sig) { 52 | return shebang.find(sig) != std::string::npos; } 53 | 54 | template 55 | static bool is_lang(const std::string & shebang, const std::string & sig, const Sig& ... sigs) { 56 | return shebang.find(sig) != std::string::npos ? true : is_lang(shebang, sigs...); } 57 | 58 | #function choice(pred, o1, o2) if pred then return o1; else return o2; end; end 59 | 60 | #function make_highlighter(is_ascii) 61 | # local function highlight_lang(name) return 'highlight_' .. name .. choice(is_ascii, "_a", "") .. '(in, output);'; end 62 | static void highlight(std::string ext, FILE * in, $(choice(is_ascii, "std::", "std::w"))ostream & out, bool iflag) { 63 | $(choice(is_ascii, "tau::ascii_printer output(out);", "std::locale locale(\"en_US.utf8\"); out.imbue(locale); tau::printer output(out);")) 64 | char shebang[64]; 65 | fgets(shebang, 63, in); 66 | shebang[63] = 0; 67 | rewind(in); 68 | 69 | if(shebang[0] == '#' && shebang[1] == '!') { 70 | std::string str(shebang + 2); 71 | if(is_lang(str, "python")) { $(highlight_lang("python")) return; } 72 | else if(is_lang(str, "tritium", "brainfuck", "/bf")) { $(highlight_lang("brainfuck")) return; } 73 | } 74 | 75 | for(auto & c : ext) c = std::tolower(c); 76 | 77 | if(ext == ".c") 78 | $(highlight_lang("c")) 79 | else if(ext == ".asm" || ext == ".x86") 80 | $(highlight_lang("x86asm")) 81 | else if(ext == ".lua") 82 | $(highlight_lang("lua")) 83 | else if(ext == ".py") 84 | $(highlight_lang("python")) 85 | else if(ext == ".cpp" || ext == ".hpp" || ext == ".cc" || ext == ".hh" || ext == ".hxx" || ext == ".cxx") 86 | $(highlight_lang("cpp")) 87 | else if(ext == ".bf") 88 | $(highlight_lang("brainfuck")) 89 | else if(ext == ".asm2bf") 90 | $(highlight_lang("asm2bf")) 91 | else if(!iflag) { 92 | std::cerr << ("`" + ext + "' - unrecognized file type.") << std::endl; 93 | std::exit(1); 94 | } 95 | } 96 | #end 97 | 98 | #make_highlighter(true) 99 | #make_highlighter(false) 100 | 101 | void process_files(std::queue & files, std::mutex & mtx, 102 | std::string & dflag, std::string & sflag, bool iflag, bool aflag) { 103 | const bool sp = sflag != ""; 104 | mtx.lock(); 105 | while(!files.empty()) { 106 | const std::string file(files.front()); 107 | files.pop(); 108 | mtx.unlock(); 109 | 110 | const std::string extension = sp ? sflag : std::string(std::filesystem::path(file).extension()); 111 | FILE * input = fopen(file.c_str(), "rb"); 112 | 113 | if(!input) { 114 | std::cerr << ("unable to open " + file) << std::endl; 115 | std::exit(1); 116 | } 117 | 118 | const std::string output = dflag + std::string(std::filesystem::path(file).filename()) + ".html"; 119 | 120 | if(aflag) { 121 | std::ofstream out(output); 122 | highlight(extension, input, out, iflag); 123 | } else { 124 | std::wofstream out(output); 125 | highlight(extension, input, out, iflag); 126 | } 127 | mtx.lock(); 128 | } 129 | 130 | mtx.unlock(); 131 | } 132 | 133 | int main(int argc, char * argv[]) { 134 | std::ios_base::sync_with_stdio(false); 135 | std::queue files; 136 | unsigned int no_files = 0; int jflag = 0; 137 | std::string dflag = "", sflag; 138 | bool iflag = false, aflag = false; 139 | 140 | if(argc == 1) 141 | help(); 142 | for(int i = 1; i <= argc - 1; i++) { 143 | if(argv[i][0] == '-') { 144 | if(argv[i][1] == 'i') 145 | iflag = true; 146 | else if(argv[i][1] == 'a') 147 | aflag = true; 148 | else if((argv[i][1] == 'd' || argv[i][1] == 's' || argv[i][1] == 'j') && i++ < argc) 149 | if(argv[i-1][1] == 'd') 150 | dflag = std::string(argv[i]); 151 | else if(argv[i-1][1] == 's') 152 | sflag = "." + std::string(argv[i]); 153 | else 154 | jflag = std::stoi(argv[i]); 155 | else 156 | help(); 157 | } else { 158 | // file / directory. 159 | if(!std::filesystem::exists(argv[i])) { 160 | std::cerr << '`' << argv[i] << "': file not found." << std::endl; 161 | std::exit(1); 162 | } else if(std::filesystem::is_directory(argv[i])) { 163 | std::cerr << '`' << argv[i] << "' is a directory." << std::endl; 164 | std::exit(1); 165 | } else { 166 | files.push(std::string(argv[i])); 167 | no_files++; 168 | } 169 | } 170 | } 171 | 172 | if(files.empty()) 173 | return 0; 174 | 175 | if(dflag == "") 176 | dflag = "./"; 177 | if(*(dflag.end() - 1) != std::filesystem::path::preferred_separator) 178 | dflag += std::filesystem::path::preferred_separator; 179 | 180 | std::mutex mtx; 181 | 182 | if(no_files > 2) { 183 | auto processor_count = jflag > 0 ? jflag : std::thread::hardware_concurrency(); 184 | 185 | // 0: unable to detect; assume dual-core. 186 | if(processor_count == 0) 187 | processor_count = 2; 188 | 189 | std::vector threads; 190 | 191 | for(unsigned i = 0; i < processor_count; i++) { 192 | std::thread thread_object([&mtx, &files, iflag, aflag](std::string dflag, std::string sflag) { 193 | process_files(files, mtx, dflag, sflag, iflag, aflag); 194 | }, dflag, sflag); 195 | 196 | threads.push_back(std::move(thread_object)); 197 | } 198 | 199 | for(auto & thr : threads) 200 | thr.join(); 201 | } else { 202 | process_files(files, mtx, dflag, sflag, iflag, aflag); 203 | } 204 | } 205 | -------------------------------------------------------------------------------- /tau.hpp.in: -------------------------------------------------------------------------------- 1 | 2 | /** 3 | * Tau - a reasonably fast syntax highlighter. 4 | * Copyright (C) 2021 Kamila Szewczyk 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU Affero General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU Affero General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU Affero General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #ifndef _TAU_HPP 21 | #define _TAU_HPP 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | /* 30 | available colors: 31 | 1 dark red 32 | 2 dark green 33 | 3 dark yellow 34 | 4 dark blue 35 | 5 dark purple 36 | 6 dark aqua 37 | 7 dark gray 38 | 8 light gray 39 | 9 light red 40 | 10 light green 41 | 11 light yellow 42 | 12 light blue 43 | 13 light purple 44 | 14 light aqua 45 | */ 46 | 47 | $( 48 | local function starts_with(str, start) 49 | return str:sub(1, #start) == start 50 | end 51 | 52 | local function ends_with(str, ending) 53 | return ending == "" or str:sub(-#ending) == ending 54 | end 55 | 56 | function rdbuf_app(s, p) 57 | local l = (loadstring("return #'" .. s .. "'"))() 58 | return 'str.rdbuf()->sputn(' .. p .. '"' .. s .. '", ' .. l .. ');' 59 | end 60 | 61 | function emit_html_escape(var, suffix) 62 | print( 63 | "switch(" .. var .. ") {" .. 64 | "case '&': " .. rdbuf_app("&", suffix) .. "break;" .. 65 | "case '\"': " .. rdbuf_app(""", suffix) .. "break;" .. 66 | "case '\\\'': " .. rdbuf_app("'", suffix) .. "break;" .. 67 | "case '<': " .. rdbuf_app("<", suffix) .. "break;" .. 68 | "case '>': " .. rdbuf_app(">", suffix) .. "break;" .. 69 | "default: str.rdbuf()->sputc(" .. var .. ");}" 70 | ) 71 | end 72 | 73 | function emit_escape_fn(type, suffix) 74 | print("void escape(const " .. type .. " c) {") 75 | if ends_with(type, "&") then 76 | print("for(const auto z : c)") 77 | emit_html_escape("z", suffix) 78 | else 79 | emit_html_escape("c", suffix) 80 | end 81 | print("}") 82 | end 83 | 84 | function esc_xlat_consumer(kind) 85 | return function(from, to) 86 | print("case '" .. from .. "': " .. rdbuf_app(to, kind) .. " break;") 87 | end 88 | end 89 | 90 | function esc_xlat(consumer) 91 | local esc_xlat_t = {} 92 | 93 | local function e(a) 94 | esc_xlat_t[a] = a; 95 | end 96 | 97 | esc_xlat_t["\\'"] = "'"; 98 | esc_xlat_t["\""] = """; 99 | e("a"); e("b"); e("a"); e("f"); e("n"); e("r"); e("t"); 100 | e("v"); 101 | 102 | for k,v in pairs(esc_xlat_t) do 103 | consumer(k,"\\\\"..v.."") 104 | end 105 | end 106 | ) 107 | 108 | #function writer_body(escaper, prefix) 109 | if(col && *col != 0) { 110 | $(rdbuf_app("sputc(" .. prefix .. "'" .. string.format("%x", i) .. "'); break;"); end) 113 | } 114 | $(rdbuf_app("\\\">", prefix)) 115 | $(escaper)(c); 116 | $(rdbuf_app("", prefix)) 117 | } else 118 | $(escaper)(c); 119 | col.reset(); 120 | #end 121 | 122 | namespace tau { 123 | class printer { 124 | private: 125 | std::wostream & str; 126 | std::optional col; 127 | 128 | $(emit_escape_fn("std::wstring &", "L")) 129 | $(emit_escape_fn("wchar_t", "L")) 130 | $(emit_escape_fn("std::wstring_view &", "L")) 131 | 132 | void escape_b(const std::wstring & c) { 133 | for(std::wstring::size_type i = 0; i < c.length(); i++) { 134 | auto z = c[i]; 135 | if(z == '\\' && i < c.length() - 1) { 136 | z = c[++i]; 137 | switch(z) { 138 | $(esc_xlat(esc_xlat_consumer("L"))) 139 | default: 140 | const auto is_octal = [](wchar_t c) { 141 | return c >= '0' && c <= '7'; 142 | }; 143 | if(i < c.length() - 2) { 144 | if(is_octal(z) && is_octal(c[i+1]) && is_octal(c[i+2])) { 145 | $(rdbuf_app("\\\\", "L")) 146 | str.rdbuf()->sputc(z);str.rdbuf()->sputc(c[i+1]);str.rdbuf()->sputc(c[i+2]); 147 | $(rdbuf_app("", "L")) 148 | i+=2; 149 | break; 150 | } else if(z == 'x' && std::isxdigit(c[i+1]) && std::isxdigit(c[i+2])) { 151 | $(rdbuf_app("\\\\x", "L")) 152 | str.rdbuf()->sputc(c[i+1]);str.rdbuf()->sputc(c[i+2]); 153 | $(rdbuf_app("", "L")) 154 | i+=2; 155 | break; 156 | } 157 | } 158 | if((z == L'u' || z == L'U') && i < c.length() - 4 && std::isxdigit(c[i+1]) && std::isxdigit(c[i+2]) 159 | && std::isxdigit(c[i+3]) && std::isxdigit(c[i+4])) { 160 | $(rdbuf_app("\\\\", "L")) 161 | str.rdbuf()->sputc(z); 162 | $(for i = 1, 4 do print("str.rdbuf()->sputc(c[i+" .. i .. "]);"); end) 163 | $(rdbuf_app("", "L")) 164 | i += 4; 165 | break; 166 | } else if(i < c.length() - 1 && is_octal(z) && is_octal(c[i+1])) { 167 | $(rdbuf_app("\\\\", "L")) 168 | str.rdbuf()->sputc(z);str.rdbuf()->sputc(c[i+1]); 169 | $(rdbuf_app("", "L")) 170 | i++; 171 | break; 172 | } 173 | str.rdbuf()->sputc(L'\\'); 174 | str.rdbuf()->sputc(z); 175 | } 176 | } else $(emit_html_escape("z", "L")) 177 | } 178 | } 179 | 180 | template 181 | void write(const T& c) { 182 | $(writer_body("escape", "L")) 183 | } 184 | 185 | void write_b(const std::wstring & c) { 186 | $(writer_body("escape_b", "L")) 187 | } 188 | 189 | public: 190 | printer(std::wostream & str_v) : str(str_v) { 191 | str << 192 | L"" 193 | L"" 194 | L"" 195 | L"" 215 | L"" 216 | L"" 217 | L"
";
218 |             }
219 | 
220 |             ~printer() {
221 |                 str <<      L"
" 222 | L"" 223 | L"\n"; 224 | } 225 | 226 | printer& operator<<(unsigned int c) { 227 | col.emplace(c); 228 | return *this; 229 | } 230 | 231 | printer& operator<<(const std::wstring & c) { 232 | write(c); return *this; 233 | } 234 | 235 | printer& operator>>(const wchar_t c) { 236 | write(c); return *this; 237 | } 238 | 239 | printer& operator>>(const std::wstring & c) { 240 | write_b(c); return *this; 241 | } 242 | 243 | printer& operator<<(const std::wstring_view & c) { 244 | write(c); return *this; 245 | } 246 | }; 247 | 248 | class ascii_printer { 249 | private: 250 | std::ostream & str; 251 | std::optional col; 252 | 253 | $(emit_escape_fn("std::string &", "")) 254 | $(emit_escape_fn("char", "")) 255 | $(emit_escape_fn("std::string_view &", "")) 256 | 257 | void escape_b(const std::string & c) { 258 | for(std::string::size_type i = 0; i < c.length(); i++) { 259 | auto z = c[i]; 260 | if(z == '\\' && i < c.length() - 1) { 261 | z = c[++i]; 262 | switch(z) { 263 | $(esc_xlat(esc_xlat_consumer(""))) 264 | default: 265 | const auto is_octal = [](char c) { 266 | return c >= '0' && c <= '7'; 267 | }; 268 | if(i < c.length() - 2) { 269 | if(is_octal(z) && is_octal(c[i+1]) && is_octal(c[i+2])) { 270 | $(rdbuf_app("\\\\", "")) 271 | str.rdbuf()->sputc(z);str.rdbuf()->sputc(c[i+1]);str.rdbuf()->sputc(c[i+2]); 272 | $(rdbuf_app("", "")) 273 | i+=2; 274 | break; 275 | } else if(z == 'x' && std::isxdigit(c[i+1]) && std::isxdigit(c[i+2])) { 276 | $(rdbuf_app("\\\\x", "")) 277 | str.rdbuf()->sputc(c[i+1]);str.rdbuf()->sputc(c[i+2]); 278 | $(rdbuf_app("", "")) 279 | i+=2; 280 | break; 281 | } 282 | } 283 | if((z == 'u' || z == 'U') && i < c.length() - 4 && std::isxdigit(c[i+1]) && std::isxdigit(c[i+2]) 284 | && std::isxdigit(c[i+3]) && std::isxdigit(c[i+4])) { 285 | $(rdbuf_app("\\\\", "")) 286 | str.rdbuf()->sputc(z); 287 | $(for i = 1, 4 do print("str.rdbuf()->sputc(c[i+" .. i .. "]);"); end) 288 | $(rdbuf_app("", "")) 289 | i += 4; 290 | break; 291 | } else if(i < c.length() - 1 && is_octal(z) && is_octal(c[i+1])) { 292 | $(rdbuf_app("\\\\", "")) 293 | str.rdbuf()->sputc(z);str.rdbuf()->sputc(c[i+1]); 294 | $(rdbuf_app("", "")) 295 | i++; 296 | break; 297 | } 298 | str.rdbuf()->sputc('\\'); 299 | str.rdbuf()->sputc(z); 300 | } 301 | } else $(emit_html_escape("z", "")) 302 | } 303 | } 304 | 305 | template 306 | void write(const T& c) { 307 | $(writer_body("escape", "")) 308 | } 309 | 310 | void write_b(const std::string & c) { 311 | $(writer_body("escape_b", "")) 312 | } 313 | 314 | public: 315 | ascii_printer(std::ostream & str_v) : str(str_v) { 316 | str << 317 | "" 318 | "" 319 | "" 320 | "" 340 | "" 341 | "" 342 | "
";
343 |             }
344 | 
345 |             ~ascii_printer() {
346 |                 str <<      "
" 347 | "" 348 | "\n"; 349 | } 350 | 351 | ascii_printer& operator<<(unsigned int c) { 352 | col.emplace(c); 353 | return *this; 354 | } 355 | 356 | ascii_printer& operator<<(const std::string & c) { 357 | write(c); return *this; 358 | } 359 | 360 | ascii_printer& operator>>(const char c) { 361 | write(c); return *this; 362 | } 363 | 364 | ascii_printer& operator>>(const std::string & c) { 365 | write_b(c); return *this; 366 | } 367 | 368 | ascii_printer& operator<<(const std::string_view & c) { 369 | write(c); return *this; 370 | } 371 | }; 372 | } 373 | 374 | #endif 375 | --------------------------------------------------------------------------------