
# Arkitektur

shikiphp omvandlar källkod till temafärgad, markerad HTML med hjälp av TextMate-grammatiker
och VS Code-teman, utan några PHP-tillägg utöver `json`/`mbstring`, ingen Node-
körmiljö och ingen inbyggd Oniguruma-bindning. Den här sidan sammanfattar flödet; det fullständiga normativa avtalet finns i `ARCHITECTURE.md` i arkivet.

## Flödet

```
source code
  └─ Highlighter::codeToTokens()
       ├─ Grammar\Registry        loads the grammar (+ its includes / embedded langs)
       ├─ Grammar\Tokenizer       line by line, driving an OnigScanner per rule state
       │     └─ Oniguruma\OnigScanner.findNextMatch()
       │           └─ Oniguruma\PatternConverter   Oniguruma pattern → JS regex
       │                 └─ Shikiphp\Regex (Parser + Matcher)   JS RegExp runtime
       ├─ Theme\Theme.match(scopeStack) → StyleAttributes   per token
       └─ Render\ThemedToken[]   (text + style) per line
  └─ Render\HtmlRenderer  → <pre class="shiki">…</pre>
```

Allt arbetar med offsetar i **UTF-16-kodenheter** — samma utrymme som regexmotorn JS och tokeniseraren i Shiki. För ASCII motsvarar detta byteoffsetar.

## Regexkörmiljön

I botten finns `Shikiphp\Regex`, en komplett ECMAScript-regexmotor i ren PHP
**medföljande från [`inline0/phasis`](https://github.com/inline0/phasis)** (en
regexmotor i ren PHP JavaScript). Den tolkar en JS-RegExp-källa plus flaggor och kör
framåtsökningar med semantik enligt Oniguruma `onig_search`.

## Konvertering från Oniguruma till JS

TextMate-grammatiker skrivs i Oniguruma. `Shikiphp\Oniguruma\PatternConverter`
är en PHP-portering av
[`oniguruma-to-es`](https://github.com/slevithan/oniguruma-to-es): den omvandlar ett
Oniguruma-mönster till en källa och en flaggsträng som är kompatibla med JS-RegExp och som regexmotorn godtar. Det är samma väg från Oniguruma till RegExp som regexmotorn i Shiki JavaScript följer, vilket gör att shikiphp kan matcha motorns resultat offset för offset. Konverteraren
hanterar de konstruktioner som används i verkliga grammatiker: POSIX-klasser, possessiva
kvantifierare och atomära grupper, inline-flaggor, namngivna grupper och bakåtreferenser,
Unicode-egenskaper med mera.

## Skannern och dess snabba PCRE-väg

`Shikiphp\Oniguruma\OnigScanner` efterliknar skannern i `vscode-oniguruma`: den byggs
en gång per regel från en lista med mönster och hittar den vänstraste matchningen vid eller efter en
startposition.

Matcharen som går igenom trädet är korrekt men långsam, så skannern har en **PCRE-snabbväg med ekvivalenskontroll** i två nivåer. En `PcreTranslator` skriver om konverterarens JS-källa till ett inbyggt PCRE-mönster endast när den kan bevisa resultatet:

- **Fullständig matchning.** När översättningen fungerar identiskt med matcharen,
  inklusive varje fångst, körs mönstret direkt i PCRE. Namngivna grupper,
  bakåtreferenser, `\p{}`, `\b`, `\G`, emulering av atomära grupper och fångster vars
  semantik för JavaScript skiljer sig från PCRE (inuti en kvantifierad grupp eller en
  lookbehind) avvisas på den här nivån.
- **Endast position.** När bara fångsterna kan skilja sig tillåter en andra översättning
  dessa konstruktioner (`\b` och `\B` som exakta ASCII-lookarounds, atomära
  grupper som inbyggd `(?>…)`, `\p{…}` när PCRE kan kompilera det). PCRE hittar då bara
  positionen för nästa matchning, och matcharen körs igen vid den offseten för att
  ta fram de faktiska fångsterna. Bakåtreferenser och `\G` avvisas även här.

Allt annat körs enbart med matcharen. För de paketerade grammatikerna vid Shiki
3.23.0 körs cirka 39 % av de 14,234 distinkta mönstren helt i PCRE, cirka 57 %
använder positionsnivån och cirka 4 % körs med matcharen. Klassificeringen kontrolleras av ett utvecklingsverktyg i arkivet
(`bin/.oracle-tools/pcre-equivalence.php`), som jämför snabbvägen med
matcharen — index, slut och, för den första nivån, varje fångstintervall — för
scenariernas indata och en uppsättning syntetiska strängar, utan att några avvikelser tillåts.

## Grammatik och tema

- **Grammatik** (`Shikiphp\Grammar`) är en trogen portering av `vscode-textmate`: en
  `Registry` löser grammatiker efter scope-namn (inklusive `include`-referenser,
  inbäddade språk och injektioner), och en `Tokenizer` hanterar regel- och
  scope-stackarna rad för rad.
- **Tema** (`Shikiphp\Theme`) porterar temamatchningen i `vscode-textmate`:
  förgrund och teckensnittsformat löses utifrån scope-väljarens specificitet och
  matchning av överordnade scope.

## Rendering

`Shikiphp\Render\HtmlRenderer` bygger det exakta `pre.shiki > code > span.line >
span` HAST-trädet Shiki bygger och serialiserar det sedan. I läget med ett tema skrivs vanliga färger; i läget med två teman skrivs variablerna `--shiki-light` / `--shiki-dark` CSS.

## Validerat mot Shiki

Shiki är själv facit, låst till `shiki` 3.23.0 med sin JavaScript-regexmotor. Katalogen `scenarios/` innehåller **214** testfall, där varje testfall är en indata i ett språk och ett tema. Tillsammans täcker de 167 av de 253 paketerade grammatikerna,
`lang: 'ansi'` och alla 65 teman. `bin/test-regression` markerar varje kodprov med
båda motorerna och kontrollerar att resultatet i HTML är identiskt efter att inledande och avslutande blanksteg tagits bort. Alternativ och transformatorer kontrolleras med paritetstester
mot resultat som fångats från samma Shiki och `@shikijs/transformers` 4.2.0.
Den ofrånkomliga regeln är att markeringsresultatet inte får försämras jämfört med
Shiki.
