init
Some checks failed
Docker. / Ubuntu (push) Has been cancelled
User-agent updater. / User-agent (push) Failing after 15s
Lock Threads / lock (push) Failing after 10s
Waiting for answer. / waiting-for-answer (push) Failing after 22s
Close stale issues and PRs / stale (push) Successful in 13s
Needs user action. / needs-user-action (push) Failing after 8s
Can't reproduce. / cant-reproduce (push) Failing after 8s

This commit is contained in:
allhaileris
2026-02-16 15:50:16 +03:00
commit afb81b8278
13816 changed files with 3689732 additions and 0 deletions

View File

@@ -0,0 +1,64 @@
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto
###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs diff=csharp
###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln merge=binary
#*.csproj merge=binary
#*.vbproj merge=binary
#*.vcxproj merge=binary
#*.vcproj merge=binary
#*.dbproj merge=binary
#*.fsproj merge=binary
#*.lsproj merge=binary
#*.wixproj merge=binary
#*.modelproj merge=binary
#*.sqlproj merge=binary
#*.wwaproj merge=binary
###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg binary
#*.png binary
#*.gif binary
###############################################################################
# diff behavior for common document formats
#
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the
# entries below.
###############################################################################
#*.doc diff=astextplain
#*.DOC diff=astextplain
#*.docx diff=astextplain
#*.DOCX diff=astextplain
#*.dot diff=astextplain
#*.DOT diff=astextplain
#*.pdf diff=astextplain
#*.PDF diff=astextplain
#*.rtf diff=astextplain
#*.RTF diff=astextplain
libprisma/grammars.json eol=lf

View File

@@ -0,0 +1,28 @@
name: Update grammars
on: [ workflow_dispatch ]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18.x]
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: 18
- run: npm install
- run: npm start
- name: Upload a Build Artifact
uses: actions/upload-artifact@v3.1.3
with:
name: grammars.dat
path: ./libprisma/grammars.dat
- name: Create Pull Request
uses: peter-evans/create-pull-request@v5
with:
commit-message: Update grammars
title: Update grammars
branch: update-grammars

365
Telegram/ThirdParty/libprisma/.gitignore vendored Normal file
View File

@@ -0,0 +1,365 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Oo]ut/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Webstorm cache directory
.idea/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*.json
coverage*.xml
coverage*.info
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd

21
Telegram/ThirdParty/libprisma/LICENSE vendored Normal file
View File

@@ -0,0 +1,21 @@
MIT LICENSE
Copyright (c) 2012 Lea Verou
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

323
Telegram/ThirdParty/libprisma/README.md vendored Normal file
View File

@@ -0,0 +1,323 @@
This is a C++ porting of [prism.js](https://github.com/PrismJS/prism) library.
The code depends on Boost.Regex, as it's a faster and more comprehensive than STD's.
Grammars file is generated from prism.js source code itself, instructions later in the file.
### Key concepts:
```cpp
string text = ReadFile("grammars.dat");
m_highlighter = std::make_shared<SyntaxHighlighter>(text);
TokenList tokens = m_highlighter->tokenize(code, language);
for (auto it = tokens.begin(); it != tokens.end(); ++it)
{
auto& node = *it;
if (node.isSyntax())
{
const auto& child = dynamic_cast<const Syntax&>(node);
// child.type() <- main token type (eg "include")
// child.alias() <- "base" token type (eg "keyword")
// child.begin() + node.end() <- list of tokens
}
else
{
const auto& child = dynamic_cast<const Text&>(node);
// child.value() <- the actual text to highlight
}
}
```
### How to update
Run
```sh
npm install
npm start
```
The new version of `grammars.dat` will appear in the `libprisma/grammars.dat`.
### Supported languages
| Language | Aliases |
|----------|---------|
|`Markup`|`markup`,`markup`,`html`,`xml`,`svg`,`mathml`,`ssml`,`atom`,`rss`|
|`CSS`|`css`|
|`C-like`|`clike`|
|`Regex`|`regex`|
|`JavaScript`|`javascript`,`js`|
|`ABAP`|`abap`|
|`ABNF`|`abnf`|
|`ActionScript`|`actionscript`|
|`Ada`|`ada`|
|`Agda`|`agda`|
|`AL`|`al`|
|`ANTLR4`|`antlr4`,`g4`|
|`Apache Configuration`|`apacheconf`|
|`SQL`|`sql`|
|`Apex`|`apex`|
|`APL`|`apl`|
|`AppleScript`|`applescript`|
|`AQL`|`aql`|
|`C`|`c`|
|`C++`|`cpp`|
|`Arduino`|`arduino`,`ino`|
|`ARFF`|`arff`|
|`ARM Assembly`|`armasm`,`arm-asm`|
|`Bash`|`bash`,`bash`,`sh`,`shell`|
|`YAML`|`yaml`,`yml`|
|`Markdown`|`markdown`,`md`|
|`Arturo`|`arturo`,`art`|
|`AsciiDoc`|`asciidoc`,`adoc`|
|`C#`|`csharp`,`csharp`,`cs`,`dotnet`|
|`ASP.NET (C#)`|`aspnet`|
|`6502 Assembly`|`asm6502`|
|`Atmel AVR Assembly`|`asmatmel`|
|`AutoHotkey`|`autohotkey`|
|`AutoIt`|`autoit`|
|`AviSynth`|`avisynth`,`avs`|
|`Avro IDL`|`avro-idl`,`avdl`|
|`AWK`|`awk`,`gawk`|
|`BASIC`|`basic`|
|`Batch`|`batch`|
|`BBcode`|`bbcode`,`shortcode`|
|`BBj`|`bbj`|
|`Bicep`|`bicep`|
|`Birb`|`birb`|
|`Bison`|`bison`|
|`BNF`|`bnf`,`rbnf`|
|`BQN`|`bqn`|
|`Brainfuck`|`brainfuck`|
|`BrightScript`|`brightscript`|
|`Bro`|`bro`|
|`CFScript`|`cfscript`,`cfc`|
|`ChaiScript`|`chaiscript`|
|`CIL`|`cil`|
|`Cilk/C`|`cilkc`,`cilk-c`|
|`Cilk/C++`|`cilkcpp`,`cilkcpp`,`cilk-cpp`,`cilk`|
|`Clojure`|`clojure`|
|`CMake`|`cmake`|
|`COBOL`|`cobol`|
|`CoffeeScript`|`coffeescript`,`coffee`|
|`Concurnas`|`concurnas`,`conc`|
|`Content-Security-Policy`|`csp`|
|`Cooklang`|`cooklang`|
|`Ruby`|`ruby`,`rb`|
|`Crystal`|`crystal`|
|`CSV`|`csv`|
|`CUE`|`cue`|
|`Cypher`|`cypher`|
|`D`|`d`|
|`Dart`|`dart`|
|`DataWeave`|`dataweave`|
|`DAX`|`dax`|
|`Dhall`|`dhall`|
|`Diff`|`diff`|
|`Markup templating`|`markup-templating`|
|`Django/Jinja2`|`django`,`jinja2`|
|`DNS zone file`|`dns-zone-file`,`dns-zone`|
|`Docker`|`docker`,`dockerfile`|
|`DOT (Graphviz)`|`dot`,`gv`|
|`EBNF`|`ebnf`|
|`EditorConfig`|`editorconfig`|
|`Eiffel`|`eiffel`|
|`EJS`|`ejs`,`eta`|
|`Elixir`|`elixir`|
|`Elm`|`elm`|
|`Lua`|`lua`|
|`Embedded Lua templating`|`etlua`|
|`ERB`|`erb`|
|`Erlang`|`erlang`|
|`Excel Formula`|`excel-formula`,`excel-formula`,`xlsx`,`xls`|
|`F#`|`fsharp`|
|`Factor`|`factor`|
|`False`|`false`|
|`Firestore security rules`|`firestore-security-rules`|
|`Flow`|`flow`|
|`Fortran`|`fortran`|
|`FreeMarker Template Language`|`ftl`|
|`GameMaker Language`|`gml`,`gamemakerlanguage`|
|`GAP (CAS)`|`gap`|
|`G-code`|`gcode`|
|`GDScript`|`gdscript`|
|`GEDCOM`|`gedcom`|
|`gettext`|`gettext`,`po`|
|`Git`|`git`|
|`GLSL`|`glsl`|
|`GN`|`gn`,`gni`|
|`GNU Linker Script`|`linker-script`,`ld`|
|`Go`|`go`|
|`Go module`|`go-module`,`go-mod`|
|`Gradle`|`gradle`|
|`GraphQL`|`graphql`|
|`Groovy`|`groovy`|
|`Less`|`less`|
|`Sass (SCSS)`|`scss`|
|`Textile`|`textile`|
|`Haml`|`haml`|
|`Handlebars`|`handlebars`,`handlebars`,`hbs`,`mustache`|
|`Haskell`|`haskell`,`hs`|
|`Haxe`|`haxe`|
|`HCL`|`hcl`|
|`HLSL`|`hlsl`|
|`Hoon`|`hoon`|
|`HTTP Public-Key-Pins`|`hpkp`|
|`HTTP Strict-Transport-Security`|`hsts`|
|`JSON`|`json`,`webmanifest`|
|`URI`|`uri`,`url`|
|`HTTP`|`http`|
|`IchigoJam`|`ichigojam`|
|`Icon`|`icon`|
|`ICU Message Format`|`icu-message-format`|
|`Idris`|`idris`,`idr`|
|`.ignore`|`ignore`,`ignore`,`gitignore`,`hgignore`,`npmignore`|
|`Inform 7`|`inform7`|
|`Ini`|`ini`|
|`Io`|`io`|
|`J`|`j`|
|`Java`|`java`|
|`Scala`|`scala`|
|`PHP`|`php`|
|`JavaDoc-like`|`javadoclike`|
|`JavaDoc`|`javadoc`|
|`Java stack trace`|`javastacktrace`|
|`Jolie`|`jolie`|
|`JQ`|`jq`|
|`TypeScript`|`typescript`,`ts`|
|`JSDoc`|`jsdoc`|
|`N4JS`|`n4js`,`n4jsd`|
|`JSON5`|`json5`|
|`JSONP`|`jsonp`|
|`JS stack trace`|`jsstacktrace`|
|`Julia`|`julia`|
|`Keepalived Configure`|`keepalived`|
|`Keyman`|`keyman`|
|`Kotlin`|`kotlin`,`kotlin`,`kt`,`kts`|
|`Kusto`|`kusto`|
|`LaTeX`|`latex`,`latex`,`tex`,`context`|
|`Latte`|`latte`|
|`Scheme`|`scheme`|
|`LilyPond`|`lilypond`,`ly`|
|`Liquid`|`liquid`|
|`Lisp`|`lisp`,`lisp`,`emacs`,`elisp`,`emacs-lisp`|
|`LiveScript`|`livescript`|
|`LLVM IR`|`llvm`|
|`Log file`|`log`|
|`LOLCODE`|`lolcode`|
|`Magma (CAS)`|`magma`|
|`Makefile`|`makefile`|
|`Mata`|`mata`|
|`MATLAB`|`matlab`|
|`MAXScript`|`maxscript`|
|`MEL`|`mel`|
|`Mermaid`|`mermaid`|
|`METAFONT`|`metafont`|
|`Mizar`|`mizar`|
|`MongoDB`|`mongodb`|
|`Monkey`|`monkey`|
|`MoonScript`|`moonscript`,`moon`|
|`N1QL`|`n1ql`|
|`Nand To Tetris HDL`|`nand2tetris-hdl`|
|`Naninovel Script`|`naniscript`,`nani`|
|`NASM`|`nasm`|
|`NEON`|`neon`|
|`Nevod`|`nevod`|
|`nginx`|`nginx`|
|`Nim`|`nim`|
|`Nix`|`nix`|
|`NSIS`|`nsis`|
|`Objective-C`|`objectivec`,`objc`|
|`OCaml`|`ocaml`|
|`Odin`|`odin`|
|`OpenCL`|`opencl`|
|`OpenQasm`|`openqasm`,`qasm`|
|`Oz`|`oz`|
|`PARI/GP`|`parigp`|
|`Parser`|`parser`|
|`Pascal`|`pascal`,`objectpascal`|
|`Pascaligo`|`pascaligo`|
|`PATROL Scripting Language`|`psl`|
|`PC-Axis`|`pcaxis`,`px`|
|`PeopleCode`|`peoplecode`,`pcode`|
|`Perl`|`perl`|
|`PHPDoc`|`phpdoc`|
|`PlantUML`|`plant-uml`,`plantuml`|
|`PL/SQL`|`plsql`|
|`PowerQuery`|`powerquery`,`powerquery`,`pq`,`mscript`|
|`PowerShell`|`powershell`|
|`Processing`|`processing`|
|`Prolog`|`prolog`|
|`PromQL`|`promql`|
|`.properties`|`properties`|
|`Protocol Buffers`|`protobuf`|
|`Stylus`|`stylus`|
|`Twig`|`twig`|
|`Pug`|`pug`|
|`Puppet`|`puppet`|
|`PureBasic`|`purebasic`,`pbfasm`|
|`Python`|`python`,`py`|
|`Q#`|`qsharp`,`qs`|
|`Q (kdb+ database)`|`q`|
|`QML`|`qml`|
|`Qore`|`qore`|
|`R`|`r`|
|`Racket`|`racket`,`rkt`|
|`Razor C#`|`cshtml`,`razor`|
|`React JSX`|`jsx`|
|`React TSX`|`tsx`|
|`Reason`|`reason`|
|`Rego`|`rego`|
|`Ren'py`|`renpy`,`rpy`|
|`ReScript`|`rescript`,`res`|
|`reST (reStructuredText)`|`rest`|
|`Rip`|`rip`|
|`Roboconf`|`roboconf`|
|`Robot Framework`|`robotframework`,`robot`|
|`Rust`|`rust`|
|`SAS`|`sas`|
|`Sass (Sass)`|`sass`|
|`Shell session`|`shell-session`,`shell-session`,`sh-session`,`shellsession`|
|`Smali`|`smali`|
|`Smalltalk`|`smalltalk`|
|`Smarty`|`smarty`|
|`SML`|`sml`,`smlnj`|
|`Solidity (Ethereum)`|`solidity`,`sol`|
|`Solution file`|`solution-file`,`sln`|
|`Soy (Closure Template)`|`soy`|
|`Splunk SPL`|`splunk-spl`|
|`SQF: Status Quo Function (Arma 3)`|`sqf`|
|`Squirrel`|`squirrel`|
|`Stan`|`stan`|
|`Stata Ado`|`stata`|
|`Structured Text (IEC 61131-3)`|`iecst`|
|`SuperCollider`|`supercollider`,`sclang`|
|`Swift`|`swift`|
|`Systemd configuration file`|`systemd`|
|`T4 templating`|`t4-templating`|
|`T4 Text Templates (C#)`|`t4-cs`,`t4`|
|`VB.Net`|`vbnet`|
|`T4 Text Templates (VB)`|`t4-vb`|
|`TAP`|`tap`|
|`Tcl`|`tcl`|
|`Template Toolkit 2`|`tt2`|
|`TOML`|`toml`|
|`Tremor`|`tremor`,`tremor`,`trickle`,`troy`|
|`TypoScript`|`typoscript`,`tsconfig`|
|`UnrealScript`|`unrealscript`,`unrealscript`,`uscript`,`uc`|
|`UO Razor Script`|`uorazor`|
|`V`|`v`|
|`Vala`|`vala`|
|`Velocity`|`velocity`|
|`Verilog`|`verilog`|
|`VHDL`|`vhdl`|
|`vim`|`vim`|
|`Visual Basic`|`visual-basic`,`visual-basic`,`vb`,`vba`|
|`WarpScript`|`warpscript`|
|`WebAssembly`|`wasm`|
|`Web IDL`|`web-idl`,`webidl`|
|`WGSL`|`wgsl`|
|`Wiki markup`|`wiki`|
|`Wolfram language`|`wolfram`,`wolfram`,`mathematica`,`nb`,`wl`|
|`Wren`|`wren`|
|`Xeora`|`xeora`,`xeoracube`|
|`Xojo (REALbasic)`|`xojo`|
|`XQuery`|`xquery`|
|`YANG`|`yang`|
|`Zig`|`zig`|

View File

@@ -0,0 +1,42 @@
Prism.languages.tl = {
'builtin': [
/---(functions|types)---/,
{
pattern: /([^a-z0-9_])#/,
lookbehind: true,
greedy: true
},
{
pattern: /(\w*:)(#|flags\.\d*\?)/,
lookbehind: true,
greedy: true
}
],
'comment': [
{
pattern: /(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,
lookbehind: true,
greedy: true
},
{
pattern: /(^|[^\\:])\/\/.*/,
lookbehind: true,
greedy: true
}
],
'function': {
pattern: /(:(flags\d?\.\d+\?)?)([a-zA-Z0-9_!<>]+)/,
lookbehind: true,
greedy: true
},
'punctuation': /[{}[\];]/,
'operator': /[:=]/,
'entity': /#[a-fA-F0-9]+/,
'class-name': {
pattern: /(\s*=\s*)(.*);/,
lookbehind: true,
greedy: true
},
};
Prism.languages.typelanguage = Prism.languages.tl;

View File

@@ -0,0 +1,424 @@
const fs = require('fs')
const isEqual = require('lodash.isequal')
const SCRIPTS = {}
const include = function (src) {
// Some black magic of eval. Load the script from src to global scope. Source: https://stackoverflow.com/a/23699187/17140794
(1, eval)(src.toString())
}
async function loadScript(src) {
const script = await fetch(src)
const text = await script.text()
include(text)
}
async function loadLanguages(lngs) {
if (lngs) {
lngs = Array.isArray(lngs) ? lngs : [lngs];
for (const lng of lngs) {
await loadLanguage(lng)
}
}
}
let langNumber = 0
async function loadLanguage(lng) {
if (!components.languages[lng].title) {
return
}
await loadLanguages(components.languages[lng].optional)
await loadLanguages(components.languages[lng].require)
await loadLanguages(components.languages[lng].modify)
if (!SCRIPTS[lng]) {
SCRIPTS[lng] = true
langNumber += 1
console.log(`${langNumber} | Loading ${lng}`);
// TODO: version should probably not be hardcoded
await loadScript(`https://cdn.jsdelivr.net/npm/prismjs@1.29.0/components/prism-${lng}.min.js`)
}
}
function loadLocalLanguage(path, code, title, alias) {
include(fs.readFileSync(path))
components.languages[code] = {
title: title,
alias: alias
}
}
function unique(a, fn) {
if (a.length === 0 || a.length === 1) {
return a;
}
if (!fn) {
return a;
}
for (let i = 0; i < a.length; i++) {
for (let j = i + 1; j < a.length; j++) {
if (fn(a[i], a[j])) {
a.splice(i, 1);
}
}
}
return a;
}
function uniqlo(a, fn) {
var size = a.length;
do {
size = a.length
a = unique(a, fn)
}
while (size > a.length)
return a
}
async function generate() {
var tempPatterns = []
var tempLanguages = {}
var tempTokens = []
var tempGrammars = []
var weak = new WeakMap
function flatten(grammar) {
var keys = {}
var cache = weak.get(grammar)
if (cache !== undefined) {
return cache
}
weak.set(grammar, keys)
var copy = grammar;
var rest = copy.rest;
if (rest) {
copy = {}
Object.keys(grammar).forEach(name => {
copy[name] = grammar[name]
})
for (var token in rest) {
copy[token] = rest[token];
}
delete copy.rest;
}
function sanitize(pattern) {
// Unsupported:
// UTF-16 ranges
// [^] => [\s\S] <- matches any character, including new line
// [] => ?? <- matches _empty_ string
// All the whitelisted languages have 0xFFFF as maximum range
// This is not the case for all the grammars supported by Prisma.
pattern = pattern.replaceAll("\\uFFFF", "\\xFF");
pattern = pattern.replaceAll("[^]", "[\\s\\S]");
// TODO: This just bruteforces the regex to work, but of course
// result may vary from the original one.
//static const boost::regex hex(R"(\\u([0-9a-fA-F]{4}))");
//pattern = boost::regex_replace(pattern, hex, R"(\\xFF)");
// TODO: Again, none of the whitelisted languages use [], but others do.
// Howhever, it is unclear to me how [] is supposed to work.
pattern = pattern.replaceAll("|[])", ")");
pattern = pattern.replaceAll(":[]", ":");
return pattern
}
for (var token in copy) {
if (!copy.hasOwnProperty(token) || !copy[token]) {
continue;
}
var patterns = copy[token];
patterns = Array.isArray(patterns) ? patterns : [patterns];
var indexes = []
for (var j = 0; j < patterns.length; ++j) {
var patternObj = patterns[j];
var inside = patternObj.inside;
var lookbehind = !!patternObj.lookbehind;
var greedy = !!patternObj.greedy;
var alias = patternObj.alias;
//alias = Array.isArray(alias) ? alias : [alias];
//alias = alias.join('/')
alias = Array.isArray(alias) ? alias[0] : alias;
var pattern = patternObj.pattern || patternObj;
var patternStr = sanitize(pattern.toString())
if (lookbehind) {
patternStr += "l"
}
if (greedy) {
patternStr += "y"
}
var np
if (alias || inside) {
np = {
pattern: patternStr
}
if (alias) {
np.alias = alias
}
if (inside) {
np.inside = flatten(inside)
}
} else if (pattern instanceof RegExp) {
np = patternStr
} else {
debugger
}
tempPatterns.push(np)
indexes.push(np)
}
keys[token] = indexes
tempTokens.push(indexes)
}
tempGrammars.push(keys)
return keys
}
var unsupported = [
"bsl",
"coq",
"gherkin",
"jexl",
"kumir",
"pure",
"purescript",
"turtle",
"sparql" // requires turtle
]
await loadScript("https://cdn.jsdelivr.net/npm/prismjs@1.29.0/components/prism-core.min.js")
await loadScript("https://prismjs.com/components.js")
await loadLanguages(Object.keys(components.languages))
console.log(`\nLoaded all ${langNumber} languages`)
console.log("Processing...")
// Manually add local definitions
loadLocalLanguage('./components/prism-tl.js', 'typelanguage', 'TypeLanguage', 'tl')
Object.keys(Prism.languages).forEach(lng => {
if (unsupported.includes(lng) || !components.languages[lng]) {
return
}
tempLanguages[lng] = flatten(Prism.languages[lng])
})
var allTokens = uniqlo(tempTokens, isEqual)
var allGrammars = uniqlo(tempGrammars, isEqual)
var allPatterns = uniqlo(tempPatterns, isEqual)
Object.keys(tempLanguages).forEach(name => {
var find = allGrammars.find(x => isEqual(x, tempLanguages[name]))
if (find === undefined) {
debugger
}
tempLanguages[name] = find
})
for (var i = 0; i < allPatterns.length; i++) {
if (allPatterns[i].inside) {
var find = allGrammars.find(x => isEqual(x, allPatterns[i].inside))
if (find === undefined) {
debugger
}
allPatterns[i].inside = find
}
}
for (var i = 0; i < allTokens.length; i++) {
var token = allTokens[i]
for (var j = 0; j < token.length; j++) {
var find = allPatterns.find(x => isEqual(x, token[j]))
if (find === undefined) {
debugger
}
token[j] = find
}
}
for (var i = 0; i < allGrammars.length; i++) {
Object.keys(allGrammars[i]).forEach(name => {
var find = allTokens.find(x => isEqual(x, allGrammars[i][name]))
if (find === undefined) {
debugger
}
allGrammars[i][name] = find
})
}
for (var i = 0; i < allPatterns.length; i++) {
if (allPatterns[i].inside) {
allPatterns[i].inside = allGrammars.indexOf(allPatterns[i].inside)
}
}
for (var i = 0; i < allTokens.length; i++) {
var token = allTokens[i]
for (var j = 0; j < token.length; j++) {
token[j] = allPatterns.indexOf(token[j])
}
}
/*for (var i = 0; i < allGrammars.length; i++) {
Object.keys(allGrammars[i]).forEach(name => {
if (allGrammars[i][name].length == 1) {
allGrammars[i][name] = allGrammars[i][name][0]
}
})
}*/
for (var i = 0; i < allPatterns.length; i++) {
if (allPatterns[i].pattern) {
var patternStr = allPatterns[i].pattern + ",";
if (allPatterns[i].alias) {
patternStr += allPatterns[i].alias
}
patternStr += ","
if (allPatterns[i].inside) {
patternStr += allPatterns[i].inside
}
allPatterns[i] = patternStr
} else {
allPatterns[i] += ",,"
}
}
var allLanguages = {}
var languageNames = {}
Object.keys(tempLanguages).forEach(name => {
var find = allGrammars.find(x => isEqual(x, tempLanguages[name]))
if (find === undefined) {
debugger
}
allLanguages[name] = allGrammars.indexOf(find)
languageNames[name] = components.languages[name].title
var alias = components.languages[name].alias
if (alias) {
alias = Array.isArray(alias) ? alias : [alias];
for (const lng of alias) {
allLanguages[lng] = allGrammars.indexOf(find)
if (components.languages[name].aliasTitles) {
languageNames[lng] = components.languages[name].aliasTitles[lng]
} else {
languageNames[lng] = components.languages[name].title
}
}
}
})
var final = {
patterns: allPatterns,
grammars: allGrammars,
languages: allLanguages
}
const chunks = [];
const writeUint16 = i => chunks.push(new Uint16Array([i]))
const writeUint8 = i => chunks.push(new Uint8Array([i]))
const writeString = str => {
if (str.length < 253) {
writeUint8(str.length)
} else {
writeUint8(254 & 0xFF)
writeUint8(str.length & 0xFF)
writeUint8((str.length >> 8) & 0xFF)
writeUint8((str.length >> 16) & 0xFF)
}
chunks.push(new Uint8Array(str.split('').map(char => char.charCodeAt(0))))
}
// Patterns
writeUint16(allPatterns.length)
allPatterns.forEach(pattern => {
writeString(pattern)
})
// Grammars
writeUint16(allGrammars.length)
for (var i = 0; i < allGrammars.length; i++) {
writeUint8(Object.keys(allGrammars[i]).length)
Object.keys(allGrammars[i]).forEach(name => {
writeString(name)
writeUint8(allGrammars[i][name].length)
allGrammars[i][name].forEach(id => {
writeUint16(id)
})
})
}
// Languages
writeUint16(Object.keys(allLanguages).length)
Object.keys(allLanguages).forEach(name => {
writeString(name)
if (languageNames[name]) {
writeString(languageNames[name])
} else {
writeString("")
}
writeUint16(allLanguages[name])
})
const blob = new Blob(chunks, {type: 'application/octet-binary'});
console.log(blob)
return blob;
}
async function saveBlob(blob, filename) {
console.log(`Saving ${blob} to ${filename}`)
const buffer = Buffer.from(await blob.arrayBuffer())
fs.writeFileSync(filename, buffer)
}
const filepath = "libprisma/grammars.dat";
generate().then(blob => {
saveBlob(blob, filepath).then(() => {
console.log("Done! Saved to " + filepath)
})
})

View File

@@ -0,0 +1,42 @@
#include "Highlight.h"
#include "LanguageTree.h"
GrammarPtr::GrammarPtr(std::shared_ptr<LanguageTree> tree, size_t path)
: m_tree(tree)
, m_path(path)
{
}
const Grammar* GrammarPtr::operator->() const
{
return get();
}
const Grammar* GrammarPtr::get() const
{
return m_tree->resolveGrammar(m_path);
}
PatternPtr::PatternPtr(std::shared_ptr<LanguageTree> tree, size_t path)
: m_tree(tree)
, m_path(path)
{
}
const Pattern* PatternPtr::get() const
{
return m_tree->resolvePattern(m_path);
}
const Grammar* Pattern::inside() const
{
if (m_inside)
{
return m_inside->get();
}
return nullptr;
}

View File

@@ -0,0 +1,146 @@
#pragma once
#include <string>
#include <vector>
#include <boost/regex.hpp>
#include <map>
#include <functional>
class GrammarPtr;
class GrammarToken;
class Pattern;
class TokenList;
class LanguageTree;
struct Grammar {
std::vector<GrammarToken> tokens;
};
class GrammarPtr
{
public:
GrammarPtr(std::shared_ptr<LanguageTree> tree, size_t path);
const Grammar* operator->() const;
const Grammar* get() const;
private:
std::shared_ptr<LanguageTree> m_tree;
size_t m_path;
};
class Pattern
{
public:
Pattern(std::string_view pattern, boost::regex_constants::syntax_option_type flags, bool lookbehind, bool greedy, std::string alias, GrammarPtr inside)
: Pattern(pattern, flags, lookbehind, greedy, alias, std::make_shared<GrammarPtr>(inside))
{
}
Pattern(std::string_view pattern, boost::regex_constants::syntax_option_type flags, bool lookbehind = false, bool greedy = false, std::string alias = "", std::shared_ptr<GrammarPtr> inside = nullptr)
: m_regex(boost::regex(std::string{pattern}, flags | boost::regex_constants::optimize))
, m_lookbehind(lookbehind)
, m_greedy(greedy)
, m_alias(alias)
, m_inside(inside)
{
}
std::string_view match(bool& success, size_t& pos, std::string_view text) const
{
boost::cmatch m;
auto flags = boost::regex_constants::match_not_dot_newline;
auto match = boost::regex_search(text.data() + pos, text.data() + text.size(), m, m_regex, flags);
if (match)
{
success = true;
pos += m.position();
if (m_lookbehind && m[1].matched)
{
// change the match to remove the text matched by the Prism lookbehind group
auto lookbehindLength = m[1].length();
pos += lookbehindLength;
return text.substr(pos, m[0].length() - lookbehindLength);
}
return text.substr(pos, m[0].length());
}
return {};
}
bool lookbehind() const
{
return m_lookbehind;
}
bool greedy() const
{
return m_greedy;
}
std::string alias() const
{
return m_alias;
}
const Grammar* inside() const;
private:
boost::regex m_regex;
bool m_lookbehind;
bool m_greedy;
std::string m_alias;
std::shared_ptr<GrammarPtr> m_inside;
};
class PatternPtr
{
public:
PatternPtr(std::shared_ptr<LanguageTree> tree, size_t path);
const Pattern* operator->() const
{
return get();
}
const Pattern* get() const;
private:
std::shared_ptr<LanguageTree> m_tree;
size_t m_path;
};
class GrammarToken
{
public:
GrammarToken(const std::string name, std::vector<PatternPtr> patterns)
: m_name(name)
, m_patterns(std::move(patterns))
{
}
const std::string &name() const
{
return m_name;
}
std::vector<PatternPtr>::const_iterator cbegin() const noexcept
{
return m_patterns.cbegin();
}
std::vector<PatternPtr>::const_iterator cend() const noexcept
{
return m_patterns.cend();
}
private:
std::string m_name;
const std::vector<PatternPtr> m_patterns;
};

View File

@@ -0,0 +1,184 @@
#include "LanguageTree.h"
#include "TokenList.h"
#include <boost/regex.hpp>
void LanguageTree::load(const std::string& content)
{
Buffer buffer{ content };
parsePatterns(buffer);
parseGrammars(buffer);
parseLanguages(buffer);
}
inline uint8_t freadUint8(Buffer &buffer)
{
uint8_t value = 0;
if (buffer.offset + sizeof(uint8_t) <= buffer.content.size()) {
memcpy(&value, &buffer.content[buffer.offset], sizeof(uint8_t));
buffer.offset += sizeof(uint8_t);
}
return value;
}
inline uint16_t freadUint16(Buffer &buffer)
{
uint16_t value = 0;
if (buffer.offset + sizeof(uint16_t) <= buffer.content.size()) {
memcpy(&value, &buffer.content[buffer.offset], sizeof(uint16_t));
buffer.offset += sizeof(uint16_t);
}
return value;
}
inline std::string freadString(Buffer &buffer)
{
size_t length = freadUint8(buffer);
if (length >= 254)
{
size_t a = freadUint8(buffer);
size_t b = freadUint8(buffer);
size_t c = freadUint8(buffer);
length = a | (b << 8) | (c << 16);
}
std::string str(length, '\0');
if (buffer.offset + length <= buffer.content.size())
{
memcpy(&str[0], &buffer.content[buffer.offset], length);
buffer.offset += length;
}
return str;
}
void LanguageTree::parseLanguages(Buffer &buffer)
{
uint16_t count = freadUint16(buffer);
for (int i = 0; i < count; ++i)
{
std::string name = freadString(buffer);
std::string displayName = freadString(buffer);
size_t index = freadUint16(buffer);
m_languages.emplace(name, std::pair<std::string, size_t>(displayName, index));
}
}
void LanguageTree::parseGrammars(Buffer &buffer)
{
uint16_t count = freadUint16(buffer);
for (int i = 0; i < count; ++i)
{
auto grammar = std::make_shared<Grammar>();
const auto keys = freadUint8(buffer);
for (int j = 0; j < keys; ++j)
{
std::vector<PatternPtr> indices;
const auto key = freadString(buffer);
uint8_t ids = freadUint8(buffer);
for (int k = 0; k < ids; ++k)
{
indices.push_back(PatternPtr(shared_from_this(), freadUint16(buffer)));
}
grammar->tokens.push_back(GrammarToken(key, indices));
}
m_grammars.push_back(grammar);
}
}
void LanguageTree::parsePatterns(Buffer &buffer)
{
uint16_t count = freadUint16(buffer);
for (int i = 0; i < count; ++i)
{
std::string item = freadString(buffer);
std::string_view value(item);
std::string alias;
size_t beg = value.find_first_of('/');
size_t end = value.find_last_of('/');
if (beg != std::string::npos && end != std::string::npos)
{
std::string_view pattern = value.substr(beg + 1, end - (beg + 1));
std::string_view options = value.substr(end + 1);
size_t aliasBeg = options.find_first_of(',');
size_t aliasEnd = options.find_last_of(',');
std::string alias{ options.substr(aliasBeg + 1, aliasEnd - (aliasBeg + 1)) };
size_t inside = 0;
if (aliasEnd + 1 < options.size())
{
for (int i = aliasEnd + 1; i < options.size(); i++)
{
char c = options[i];
if (c >= '0' && c <= '9')
{
inside = inside * 10 + (c - '0');
}
else
{
assert(false);
}
}
}
else
{
inside = std::string::npos;
}
bool lookbehind = false;
bool greedy = false;
boost::regex_constants::syntax_option_type flags
= boost::regex_constants::ECMAScript | boost::regex_constants::no_mod_m;
for (char c : options.substr(0, aliasBeg))
{
switch (c)
{
case 'l':
lookbehind = true;
break;
case 'y':
greedy = true;
break;
case 'i':
flags |= boost::regex_constants::icase;
break;
case 'm':
flags &= ~boost::regex_constants::no_mod_m;
break;
}
}
if (inside != std::string::npos)
{
m_patterns.push_back(std::make_shared<Pattern>(pattern, flags, lookbehind, greedy, std::string{ alias }, std::make_shared<GrammarPtr>(shared_from_this(), inside)));
}
else
{
m_patterns.push_back(std::make_shared<Pattern>(pattern, flags, lookbehind, greedy, std::string{ alias }));
}
}
}
}
const Pattern* LanguageTree::resolvePattern(size_t path)
{
return m_patterns[path].get();
}
const Grammar* LanguageTree::resolveGrammar(size_t path)
{
return m_grammars[path].get();
}

View File

@@ -0,0 +1,60 @@
#pragma once
#include <sstream>
#include <fstream>
#include <optional>
#include "Highlight.h"
struct Buffer {
const std::string &content;
int64_t offset = 0;
};
class LanguageTree : public std::enable_shared_from_this<LanguageTree>
{
public:
LanguageTree() = default;
void load(const std::string& content);
const Pattern* resolvePattern(size_t path);
const Grammar* resolveGrammar(size_t path);
std::map<std::string, std::string> keys() const
{
std::map<std::string, std::string> keys;
for (const auto& kv : m_languages)
{
if (kv.second.first.empty())
{
continue;
}
keys.emplace(kv.first, kv.second.first);
}
return keys;
}
const Grammar* find(const std::string& key) const
{
const auto& value = m_languages.find(key);
if (value != m_languages.end())
{
return m_grammars[value->second.second].get();
}
return nullptr;
}
private:
void parseLanguages(Buffer &buffer);
void parseGrammars(Buffer &buffer);
void parsePatterns(Buffer &buffer);
std::map<std::string, std::pair<std::string, size_t>> m_languages;
std::vector<std::shared_ptr<Grammar>> m_grammars;
std::vector<std::shared_ptr<Pattern>> m_patterns;
};

View File

@@ -0,0 +1,202 @@
#include "SyntaxHighlighter.h"
#include "LanguageTree.h"
#include "TokenList.h"
SyntaxHighlighter::SyntaxHighlighter(const std::string& path)
{
m_tree = std::make_shared<LanguageTree>();
m_tree->load(path);
}
TokenList SyntaxHighlighter::tokenize(const std::string& text, const std::string& language)
{
const Grammar* grammar = m_tree->find(language);
if (grammar)
{
return tokenize(text, grammar);
}
return TokenList(text);
}
std::map<std::string, std::string> SyntaxHighlighter::languages() const
{
return m_tree->keys();
}
TokenList SyntaxHighlighter::tokenize(std::string_view text, const Grammar* grammar)
{
TokenList tokenList(text);
try {
matchGrammar(text, tokenList, grammar, tokenList.head, 0, nullptr);
} catch (...) {
}
return tokenList;
}
void SyntaxHighlighter::matchGrammar(std::string_view text, TokenList& tokenList, const Grammar* grammar, TokenListPtr startNode, size_t startPos, RematchOptions* rematch)
{
for (const auto& token : grammar->tokens)
{
int x = 0;
for (auto j = token.cbegin(); j != token.cend(); ++j)
{
if (rematch && rematch->j == x && rematch->token == token.name())
{
return;
}
const auto& pattern = *j;
const auto& inside = pattern->inside();
const bool greedy = pattern->greedy();
size_t pos = startPos;
// iterate the token list and keep track of the current token/string position
for (TokenListPtr currentNode = startNode->next;
currentNode != tokenList.head;
pos += currentNode->length(), currentNode = currentNode->next)
{
if (rematch && pos >= rematch->reach)
{
break;
}
if (tokenList.length > text.length())
{
// Something went terribly wrong, ABORT, ABORT!
return;
}
if (currentNode->isSyntax())
{
continue;
}
const auto& currentText = dynamic_cast<Text&>(*currentNode);
std::string_view str = currentText.value();
auto removeCount = 1; // this is the to parameter of removeBetween
std::string_view match;
bool matchSuccess = false;
size_t matchIndex = pos;
if (greedy)
{
match = pattern->match(matchSuccess, matchIndex, text);
if (!matchSuccess || matchIndex >= text.length())
{
break;
}
auto from = matchIndex;
auto to = matchIndex + match.length();
auto p = pos;
// find the node that contains the match
p += currentNode->length();
while (from >= p)
{
currentNode = currentNode->next;
p += currentNode->length();
}
// adjust pos (and p)
p -= currentNode->length();
pos = p;
// the current node is a Token, then the match starts inside another Token, which is invalid
if (currentNode->isSyntax())
{
continue;
}
// find the last node which is affected by this match
for (TokenListPtr k = currentNode;
k != tokenList.head && (p < to || !k->isSyntax());
k = k->next)
{
removeCount++;
p += k->length();
}
removeCount--;
// replace with the new match
str = text.substr(pos, p - pos);
matchIndex -= pos;
}
else
{
matchIndex = 0;
match = pattern->match(matchSuccess, matchIndex, str);
if (!matchSuccess)
{
continue;
}
}
auto from = matchIndex;
auto before = str.substr(0, from);
auto after = str.substr(from + match.length());
auto reach = pos + str.length();
if (rematch && reach > rematch->reach)
{
rematch->reach = reach;
}
TokenListPtr removeFrom = currentNode->prev;
if (before.size())
{
removeFrom = tokenList.addAfter(removeFrom, before);
pos += before.length();
}
tokenList.removeRange(removeFrom, removeCount);
TokenList tokenEntries = [&]() {
if (inside)
{
return tokenize(match, inside);
}
else
{
return TokenList(match);
}
}();
currentNode = tokenList.addAfter(removeFrom, token.name(),
std::move(tokenEntries),
pattern->alias(),
match.size());
if (after.size())
{
tokenList.addAfter(currentNode, after);
}
if (removeCount > 1)
{
// at least one Token object was removed, so we have to do some rematching
// this can only happen if the current pattern is greedy
RematchOptions nestedRematch = {
.token = token.name(),
.reach = reach,
.j = x
};
matchGrammar(text, tokenList, grammar, currentNode->prev, pos, &nestedRematch);
// the reach might have been extended because of the rematching
if (rematch && nestedRematch.reach > rematch->reach)
{
rematch->reach = nestedRematch.reach;
}
}
}
++x;
}
}
}

View File

@@ -0,0 +1,33 @@
#pragma once
#include <sstream>
#include "TokenList.h"
#include <vector>
#include <map>
#include <optional>
class LanguageTree;
struct Grammar;
struct RematchOptions
{
std::string token;
size_t reach;
int j;
};
class SyntaxHighlighter
{
public:
SyntaxHighlighter(const std::string& languages);
TokenList tokenize(const std::string& text, const std::string& language);
std::map<std::string, std::string> languages() const;
private:
TokenList tokenize(std::string_view text, const Grammar* grammar);
void matchGrammar(std::string_view text, TokenList& tokenList, const Grammar* grammar, TokenListPtr startNode, size_t startPos, RematchOptions* rematch);
std::shared_ptr<LanguageTree> m_tree;
};

View File

@@ -0,0 +1,71 @@
#include "TokenList.h"
TokenList::TokenList(std::string_view value)
: head(new TokenListNode())
, length(1)
{
const TokenListPtr newNode = new Text(head, head, value);
head->next = newNode;
}
TokenList::~TokenList()
{
TokenListPtr next = head->next;
while (head != next)
{
TokenListPtr current = next;
next = next->next;
delete current;
}
delete head;
}
TokenListPtr TokenList::addAfter(TokenListPtr node, const std::string& type, TokenList&& children, const std::string& alias, size_t textLength)
{
const TokenListPtr next = node->next;
const TokenListPtr newNode = new Syntax(node, next, type, std::move(children), alias, textLength);
node->next = newNode;
next->prev = newNode;
length++;
return newNode;
}
TokenListPtr TokenList::addAfter(TokenListPtr node, std::string_view value)
{
const TokenListPtr next = node->next;
const TokenListPtr newNode = new Text(node, next, value);
node->next = newNode;
next->prev = newNode;
length++;
return newNode;
}
void TokenList::removeRange(TokenListPtr node, size_t count)
{
TokenListPtr item = node->next;
for (size_t i = 0; i < count && item != nullptr; i++)
{
node->next = item->next;
node->next->prev = node;
delete item;
item = node->next;
length--;
}
}
Syntax::Syntax(TokenListPtr prev, TokenListPtr next, const std::string& type, TokenList&& children, const std::string& alias, size_t length)
: TokenListNode(prev, next)
, m_type(type)
, m_children(std::move(children))
, m_alias(alias)
, m_length(length)
{
}

View File

@@ -0,0 +1,170 @@
#pragma once
#include <memory>
#include <string>
struct TokenListNode
{
TokenListNode(TokenListNode* prev, TokenListNode* next)
: prev(prev)
, next(next)
{
}
TokenListNode()
: prev(nullptr)
, next(nullptr)
{
}
virtual ~TokenListNode() = default;
TokenListNode(const TokenListNode&) = delete;
TokenListNode& operator=(const TokenListNode&) = delete;
virtual size_t length() const
{
return 0;
}
virtual bool isSyntax() const
{
return true;
}
TokenListNode* prev;
TokenListNode* next;
};
typedef TokenListNode* TokenListPtr;
class TokenList
{
public:
TokenList(std::string_view text);
~TokenList();
TokenList(const TokenList&) = delete;
TokenList& operator=(const TokenList&) = delete;
TokenList(TokenList&& old) noexcept
{
head = old.head;
length = old.length;
old.head = new TokenListNode();
old.head->next = old.head;
old.length = 0;
}
struct ConstIterator
{
using iterator_category = std::forward_iterator_tag;
using difference_type = std::ptrdiff_t;
using value_type = const TokenListNode;
using pointer = const TokenListNode*;
using reference = const TokenListNode&;
ConstIterator(pointer ptr) : m_ptr(ptr) {}
reference operator*() const { return *m_ptr; }
pointer operator->() { return m_ptr; }
ConstIterator& operator++() { m_ptr = m_ptr->next; return *this; }
friend bool operator== (const ConstIterator& a, const ConstIterator& b) { return a.m_ptr == b.m_ptr; };
friend bool operator!= (const ConstIterator& a, const ConstIterator& b) { return a.m_ptr != b.m_ptr; };
private:
pointer m_ptr;
};
ConstIterator begin() const { return ConstIterator(head->next); }
ConstIterator end() const { return ConstIterator(head); }
TokenListPtr addAfter(TokenListPtr node, const std::string& type, TokenList&& children, const std::string& alias, size_t length);
TokenListPtr addAfter(TokenListPtr node, std::string_view value);
void removeRange(TokenListPtr node, size_t count);
TokenListPtr head;
size_t length;
};
class Text : public TokenListNode
{
public:
Text(TokenListPtr prev, TokenListPtr next, std::string_view value)
: TokenListNode(prev, next)
, m_value(value)
{
}
Text(const Text&) = delete;
Text& operator=(const Text&) = delete;
const std::string_view& value() const
{
return m_value;
}
size_t length() const
{
return m_value.size();
}
bool isSyntax() const
{
return false;
}
private:
const std::string_view m_value;
};
class Syntax : public TokenListNode
{
public:
Syntax(TokenListPtr prev, TokenListPtr next, const std::string& type, TokenList&& children, const std::string& alias, size_t length);
Syntax(const Syntax&) = delete;
Syntax& operator=(const Syntax&) = delete;
size_t length() const
{
return m_length;
}
bool isSyntax() const
{
return true;
}
const std::string &type() const
{
return m_type;
}
TokenList::ConstIterator begin() const
{
return m_children.begin();
}
TokenList::ConstIterator end() const
{
return m_children.end();
}
const std::string &alias() const
{
return m_alias;
}
const TokenList &children() const
{
return m_children;
}
public:
std::string m_type;
TokenList m_children;
std::string m_alias;
size_t m_length;
};

Binary file not shown.

21
Telegram/ThirdParty/libprisma/package-lock.json generated vendored Normal file
View File

@@ -0,0 +1,21 @@
{
"name": "libprisma",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "libprisma",
"version": "1.0.0",
"license": "MIT",
"dependencies": {
"lodash.isequal": "^4.5.0"
}
},
"node_modules/lodash.isequal": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
"integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ=="
}
}
}

View File

@@ -0,0 +1,22 @@
{
"name": "libprisma",
"version": "1.0.0",
"description": "This is a C++ porting of [prism.js](https://github.com/PrismJS/prism) library.\r The code depends on Boost.Regex, as it's a faster and more comprehensive than STD's.",
"main": "generate.js",
"scripts": {
"start": "node generate.js"
},
"repository": {
"type": "git",
"url": "git+https://github.com/TelegramMessenger/libprisma.git"
},
"author": "",
"license": "MIT",
"bugs": {
"url": "https://github.com/TelegramMessenger/libprisma/issues"
},
"homepage": "https://github.com/TelegramMessenger/libprisma#readme",
"dependencies": {
"lodash.isequal": "^4.5.0"
}
}