npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

grion

v2.2.1

Published

Grion is a lightweight, reactive web framework for building dynamic user interfaces with declarative HTML templating, event-driven interactions, and inline CSS styling. Features include event(), replace(), swap(), append(), prepend(), before(), after() an

Readme

Grionni o‘rgangan o‘quvchi endi yangi dasturlash tillari, framework’lar yoki o‘zining ijodiy loyihalarini yaratish uchun zarur bo‘lgan barcha asosiy texnologik ko‘nikmalarga ega bo‘ladi va yarata oladi. Shuningdek o'zining maxsus DSL xizmati ham mavjud va u ham Grion deb ataladi.

🚀 O‘rnatish

npm orqali:

npm install grion

Yoki Yarn orqali:

yarn add grion

Yoki pnpm orqali:

pnpm add grion

📦 Import qilish

● Lexer importi

import { createLexer } from "grion";

● Parser funksiyalari importi

import {
    t, lit, seq, or, many, opt, ref, rule,
    grammar, node, num, str, id, bin, call, program,
    createParser
} from "grion";

📌 O‘rnatmasdan turib (CDN orqali) import qilish

grion ni npm’dan o‘rnatmasdan ham ishlatishingiz mumkin. Buning uchun uni unpkg yoki jsDelivr orqali to‘g‘ridan-to‘g‘ri browserga yuklaysiz.

1️⃣ jsDelivr orqali import

● Lexer importi

<script type="module">
import { createLexer } from "https://cdn.jsdelivr.net/npm/grion/+esm";
</script>

● Parser funksiyalari importi

<script type="module">
import { t, lit, seq, or, many, opt, ref, rule, grammar, node, num, str, id, bin, call, program, createParser } from "https://cdn.jsdelivr.net/npm/grion/+esm";
</script>

2️⃣ unpkg orqali import

● Lexer importi

<script type="module">
import { createLexer } from "https://unpkg.com/grion?module";
</script>

● Parser funksiyalari importi

<script type="module">
import { t, lit, seq, or, many, opt, ref, rule, grammar, node, num, str, id, bin, call, program, createParser } from "https://unpkg.com/grion?module";
</script>

3️⃣ esm.run orqali import (eng barqaror variant)

● Lexer importi

<script type="module">
import { createLexer } from "https://esm.run/grion";
</script>

● Parser funksiyalari importi

<script type="module">
import { t, lit, seq, or, many, opt, ref, rule, grammar, node, num, str, id, bin, call, program, createParser } from "https://esm.run/grion";
</script>

Grion DSL

Grion - Zamonaviy HTML/CSS qisman JavaScript Preprocessor

📖 Kirish

Grion - bu HTML va CSS qisman JavaScript bilan ishlashni osonlashtiradigan va zamonaviylashtiruvchi preprocessor. U eski brauzerlar uchun avtomatik fallback yaratadi va kodingizni optimallashtiradi.


Grion DSL - To'liq Qo'llanma

1-dars: Ishga tushurish

Ishga tushurish uchun yuqoridagi usullarning biri yordamida o'rnatib olasiz. O'rnatib bo'lgach terminalga npx grion ni yozib kerakli strukturani yaratib olasiz.

npx grion

Natijada quyidagi struktura yaratiladi:

my-project/
├── src/
│   ├── index.grion
│   └── assets/
│       └── favicon.ico
├── dist/                    # avtomatik yaratiladi
│   ├── index.html
│   ├── css/
│   │   ├── reset.css
│   │   ├── variables.css
│   │   └── index.css
|   ├── js/
│   │   └── index.js
│   └── assets/
│       └── favicon.ico
└── package.json

2-dars: Fayl Strukturasi

HTML niki

<!DOCTYPE html>
<html lang="uz">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta name="description" content="This page is the default index.grion file created by Grion.">
        <meta name="author" content="Grion">
        <meta name="theme-color" content="#0000FF">
        <meta name="robots" content="index, follow">
        <link rel="shortcut icon" href="./assets/favicon.ico" type="image/x-icon">
        <title>Document</title>
    </head>
    <body>
        
    </body>
</html>

Grion niki

<grion lang="uz">
    <head
        description="This page is the default index.grion file created by Grion."
        author="Grion"
        theme-color="#0000FF"
        robots="index, follow"
    >
        <title src="./assets/favicon.ico">Document</title>
    </head>
    <body>
        
    </body>
</grion>

Afzalliklari:

  • ✅ Meta teglarni qisqaroq yozish mumkin
  • ✅ Favicon'ni title ichida belgilash
  • ✅ Kamroq kod yozish
  • ✅ O'qish oson

3-dars: <a> tegida fayl manzilini yozish

HTML niki

<a href="main.html">Havola</a>
<a href="about.html">Biz haqimizda</a>
<a href="blog/post-1.html">Blog yozuvi</a>

Grion niki

<!-- ❌ XATO -->
<a href="main.grion">Havola</a>

<!-- ✅ TO'G'RI -->
<a href="main">Havola</a>
<a href="about">Biz haqimizda</a>
<a href="blog/post-1">Blog yozuvi</a>

Grion avtomatik ravishda to'g'ri manzilni aniqlaydi:

| Fayl/Papka strukturasi | Grion'da | HTML'da | |------------------------|----------|---------| | main.grion fayli mavjud | href="main" | href="main.html" | | main/ papkasi mavjud | href="main" | href="main/" | | Ikkisi ham mavjud | href="main" | href="main/" (papka ustunlik qiladi) |

Misol:

src/
├── index.grion
├── about.grion
├── blog/
│   ├── index.grion
│   ├── post-1.grion
│   └── post-2.grion
└── contact.grion
<!-- index.grion da -->
<a href="about">Biz haqimizda</a>        <!-- → about.html -->
<a href="blog">Blog</a>                  <!-- → blog/ -->
<a href="blog/post-1">Birinchi post</a> <!-- → blog/post-1.html -->
<a href="contact">Aloqa</a>             <!-- → contact.html -->

🎯 Asosiy Imkoniyatlar

1. onstyle Atributi - Grion'ning Eng Kuchli Xususiyati

onstyle - bu Grion'ning asosiy innovatsiyasi. U HTML elementlariga to'g'ridan-to'g'ri CSS yozish imkonini beradi.

Oddiy Misol:

<div onstyle="
  display: flex;
  gap: 20px;
  background: oklch(0.7 0.2 180);
">
  Mening kontentim
</div>

Kompilatsiyadan keyingi natija:

HTML:

<div class="grion-abc123">
  Mening kontentim
</div>

CSS (avtomatik fallback bilan):

/* Eski brauzerlar uchun */
.grion-abc123 {
  display: flex;
  background: rgb(128, 180, 200);
}

/* Zamonaviy brauzerlar uchun */
@supports (gap: 20px) {
  .grion-abc123 {
    gap: 20px;
  }
}

@supports (color: oklch(0.7 0.2 180)) {
  .grion-abc123 {
    background: oklch(0.7 0.2 180);
  }
}

onstyle Afzalliklari:

Component-scoped styling - Har bir element o'z stiliga ega
Avtomatik class generation - O'zingiz class o'ylab topishingiz shart emas
Progressive enhancement - Eski brauzerlar uchun avtomatik fallback
CSS variables - Takroriy qiymatlar avtomatik variable'ga aylanadi
No naming conflicts - Class nomlari unique bo'ladi
Easy refactoring - Stil to'g'ridan-to'g'ri element yonida

onstyle bilan ishlash - To'liq qo'llanma:

A) Oddiy stil'lar:

<button onstyle="
  padding: 10px 20px;
  background: #3b82f6;
  color: white;
  border: none;
  border-radius: 5px;
  cursor: pointer;
">
  Tugma
</button>

B) Hover, focus, active holatlar:

<button onstyle="
  padding: 10px 20px;
  background: #3b82f6;
  
  &:hover {
    background: #2563eb;
  }
  
  &:active {
    background: #1d4ed8;
  }
  
  &:focus {
    outline: 2px solid #60a5fa;
    outline-offset: 2px;
  }
">
  Interaktiv tugma
</button>

C) Ichki elementlar uchun stil'lar:

<div onstyle="
  background: white;
  padding: 20px;
  border-radius: 10px;
  
  & h2 {
    font-size: 1.5em;
    margin-bottom: 10px;
  }
  
  & p {
    color: #666;
    line-height: 1.6;
  }
  
  & button {
    margin-top: 15px;
  }
">
  <h2>Sarlavha</h2>
  <p>Matn...</p>
  <button>Tugma</button>
</div>

D) Media queries:

<div onstyle="
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
  
  @media (max-width: 768px) {
    grid-template-columns: 1fr;
    gap: 10px;
  }
">
  <!-- Responsive grid -->
</div>

E) Animatsiyalar:

<div onstyle="
  @keyframes fadeIn {
    from {
      opacity: 0;
      transform: translateY(20px);
    }
    to {
      opacity: 1;
      transform: translateY(0);
    }
  }
  
  animation: fadeIn 0.5s ease-out;
">
  Animatsiyali element
</div>

F) Murakkab selektorlar:

<nav onstyle="
  display: flex;
  gap: 20px;
  
  & a {
    color: #333;
    text-decoration: none;
    padding: 5px 10px;
    
    &:hover {
      color: #3b82f6;
    }
    
    &.active {
      color: #3b82f6;
      border-bottom: 2px solid #3b82f6;
    }
  }
  
  & > ul {
    display: flex;
    gap: 10px;
    
    & > li {
      list-style: none;
    }
  }
">
  <ul>
    <li><a href="/" class="active">Bosh sahifa</a></li>
    <li><a href="/about">Biz haqimizda</a></li>
  </ul>
</nav>

G) Pseudo-elementlar:

<div onstyle="
  position: relative;
  padding: 20px;
  
  &::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    width: 4px;
    height: 100%;
    background: #3b82f6;
  }
  
  &::after {
    content: '→';
    margin-left: 5px;
  }
">
  Chiroyli element
</div>

onstyle + Regular class - Birgalikda ishlatish:

<!-- Tailwind CSS + Grion -->
<div class="container mx-auto" onstyle="
  padding: 40px;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
">
  <!-- Ikkala yondashuv birgalikda -->
</div>

<!-- Bootstrap + Grion -->
<button class="btn" onstyle="
  background: linear-gradient(to right, #ff6b6b, #ee5a6f);
  border: none;
  
  &:hover {
    background: linear-gradient(to right, #ee5a6f, #c44569);
  }
">
  Custom styled Bootstrap button
</button>

onstyle Performance Optimizatsiya:

Grion avtomatik ravishda:

  1. Bir xil stil'larni deduplication qiladi:
<!-- Bu ikkala element uchun bitta .grion-xxx class yaratiladi -->
<div onstyle="color: red; font-size: 20px;">1</div>
<div onstyle="color: red; font-size: 20px;">2</div>
  1. CSS variable'lar yaratadi:
<!-- Bu #3b82f6 uchun --color-3b82f6 variable yaratadi -->
<div onstyle="color: #3b82f6;">Matn 1</div>
<div onstyle="border: 1px solid #3b82f6;">Matn 2</div>

<!-- Natija: -->
<!-- :root { --color-3b82f6: #3b82f6; } -->
<!-- color: var(--color-3b82f6); -->
  1. Minimal CSS chiqaradi:
<!-- Faqat ishlatilgan stil'lar chiqariladi -->
<div onstyle="padding: 20px;">Content</div>
<!-- display, margin, width va boshqalar chiqarilmaydi -->

onstyle Best Practices:

✅ YAXSHI:

<!-- Stil'larni tashkillashtiring -->
<div onstyle="
  display: flex;
  flex-direction: column;
  gap: 20px;

  background: white;
  color: #333;
  
  font-size: 16px;
  line-height: 1.5;
">

❌ YOMON:

<!-- Tartibsiz, o'qish qiyin -->
<div onstyle="color: #333; display: flex; font-size: 16px; background: white; gap: 20px; flex-direction: column; line-height: 1.5;">

✅ YAXSHI:

<!-- Qisqa stil'lar uchun bir qatorda -->
<span onstyle="color: red; font-weight: bold;">Muhim</span>

<!-- Murakkab stil'lar uchun ko'p qator -->
<div onstyle="
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 20px;
">

❌ YOMON:

<!-- Juda ko'p nested selector'lar -->
<div onstyle="
  & > div > span > a > strong {
    color: red;
  }
">
<!-- Bu selector juda aniq, refactoring qiyin -->

onstyle Debugging:

Agar stil'laringiz ishlamasa:

  1. Browser DevTools'da tekshiring:

    • Element'ga qaysi class berilgan?
    • CSS fayli yuklanganmi?
    • Selector to'g'rimi?
  2. Sintaksis xatolarini tekshiring:

<!-- ❌ XATO: Yopilmagan { -->
<div onstyle="
  display: flex;
  & .child {
    color: red;
">

<!-- ✅ TO'G'RI -->
<div onstyle="
  display: flex;
  & .child {
    color: red;
  }
">

2. Nested CSS (Ichma-ich Stillar)

SCSS kabi nested selector'lardan foydalaning:

<div onstyle="
  color: blue;
  font-size: 16px;
  
  &:hover {
    color: red;
  }
  
  & .child {
    font-size: 14px;
  }
">
  <span class="child">Bola element</span>
</div>

3. Avtomatik CSS Variables

Grion takrorlanuvchi qiymatlarni avtomatik ravishda CSS variable'larga aylantiradi:

<div onstyle="color: #3b82f6;">Matn 1</div>
<div onstyle="background: #3b82f6;">Matn 2</div>

Natija:

:root {
  --color-3b82f6: #3b82f6;
}

.grion-xxx {
  color: var(--color-3b82f6);
}

.grion-yyy {
  background: var(--color-3b82f6);
}

🎨 Qo'llab-quvvatlanadigan CSS Xususiyatlar

Grion quyidagi zamonaviy CSS xususiyatlari uchun avtomatik fallback yaratadi:

Layout

  • ✅ CSS Grid → Flexbox fallback
  • gap → prefixlar bilan
  • aspect-ratio → height/width
  • inset → top/right/bottom/left

Ranglar

  • oklch() → RGB
  • lab() → RGB
  • lch() → RGB
  • ✅ Hex, RGB, HSL (to'g'ridan-to'g'ri)

Viewport Units

  • dvh, dvwvh, vw
  • lvh, lvwvh, vw
  • svh, svwvh, vw

Zamonaviy Xususiyatlar

  • backdrop-filter → opacity fallback
  • @container@media fallback
  • @property@supports bilan
  • position: sticky → prefix bilan
  • ✅ Logical properties (margin-inline, padding-block)

At-Rules

  • @keyframes - fallback bilan
  • @font-face
  • @import
  • @supports
  • @media
  • @container
  • @layer
  • @scope

📂 Chiqish Strukturasi

dist/
├── css/
│   ├── reset.css           # Browser reset
│   ├── variables.css       # CSS variables
│   ├── index.css           # index.grion'ning stillari
│   └── about.css           # about.grion'ning stillari
├── assets/
│   └── ...                 # Barcha asset fayllar
├── index.html
└── about.html

🔧 Advanced Misollar

1. Responsive Design

<div onstyle="
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 20px;
  padding: 20px;
  
  @container (min-width: 600px) {
    grid-template-columns: repeat(2, 1fr);
  }
  
  @media (max-width: 768px) {
    padding: 10px;
    gap: 10px;
  }
">
  <!-- Kontentingiz -->
</div>

2. Dark Mode

<div onstyle="
  background: white;
  color: black;
  
  @media (prefers-color-scheme: dark) {
    background: #1a1a1a;
    color: white;
  }
">
  Dark mode qo'llab-quvvatlanadi!
</div>

3. Animatsiyalar

<div onstyle="
  @keyframes fadeIn {
    from { opacity: 0; transform: translateY(20px); }
    to { opacity: 1; transform: translateY(0); }
  }
  
  animation: fadeIn 0.5s ease-out;
">
  Animatsiyali element
</div>

4. Custom Properties

<div onstyle="
  @property --my-color {
    syntax: '<color>';
    inherits: false;
    initial-value: blue;
  }
  
  background: var(--my-color);
  transition: --my-color 0.3s;
  
  &:hover {
    --my-color: red;
  }
">
  Animatsiyali rang o'zgarishi
</div>

5. Container Queries

<div onstyle="
  container-type: inline-size;
  
  & .card {
    display: flex;
    flex-direction: column;
    
    @container (min-width: 400px) {
      flex-direction: row;
    }
  }
">
  <div class="card">
    <!-- Card content -->
  </div>
</div>

📊 Performance

Grion avtomatik ravishda kodingizni optimallashtiradi:

  • CSS deduplication - bir xil stil'lar faqat bir marta yoziladi
  • Variable extraction - takrorlanuvchi qiymatlar variable'ga aylanadi
  • Minimal CSS - faqat ishlatilgan stil'lar chiqariladi
  • Fast rebuilds - faqat o'zgargan fayllar qayta kompilatsiya qilinadi
  • Parallel processing - bir nechta fayl bir vaqtda build qilinadi

❓ Ko'p so'raladigan savollar (FAQ)

Grion qaysi brauzerlarni qo'llab-quvvatlaydi?

Grion yaratgan HTML/CSS barcha zamonaviy brauzerlar va eski brauzerlar (IE11 gacha) bilan ishlaydi, chunki u avtomatik fallback'lar yaratadi.

onstyle vs oddiy CSS - qaysi yaxshiroq?

onstyle kichik komponentlar va tez prototiplash uchun juda qulay. Katta loyihalar uchun esa aralash yondashuvni tavsiya qilamiz.

Mavjud CSS framework'lar (Tailwind, Bootstrap) bilan ishlatamanmi?

Ha! Siz oddiy class atributi orqali har qanday CSS framework'dan foydalanishingiz mumkin.

<div class="container mx-auto" onstyle="padding: 20px;">
  <!-- Tailwind + Grion -->
</div>

Production uchun tayyormi?

Ha, Grion production-ready. U barcha zamonaviy CSS xususiyatlarini to'g'ri handle qiladi va eski brauzerlar uchun fallback beradi.

Muhim qoida.

onstyle atributini oxirgi atribut sifati yozing:

Xato:

<div onstyle="..." title="...">...</div>

To'g'ri:

<div title="..." onstyle="...">...</div>

Grion Event Tizimi

Event nima?

Event - bu foydalanuvchi harakati (click, hover, input va boshqalar) yuz berganda bajariladigan kod bloki.

Grion'da eventlar deklarativ tarzda yoziladi - HTMLga o'xshagan Grionning o'zida.

Oddiy misol:

event(click) {
    return replace(
        <button>Bosing</button>,
        <button>Bosildi!</button>
    )
}

Asosiy sintaksis

1. Event struktura

event(event_nomi) {
    return replace(
        eski_element,
        yangi_element
    )
}

Qismlar:

  • event(event_nomi) - qaysi hodisa (click, hover, input...)
  • return replace() - nima qilish kerak
  • eski_element - qaysi elementni almashtirish
  • yangi_element - nima bilan almashtirish

DOM Manipulation metodlari

Tushuncha

Har bir metod elementga qayerda qo'shish kerakligini bildiradi:


1. PREPEND (tashqi boshiga qo'shish)

Ma'nosi: Tanlangan elementning oldiga (tashqarida) yangi element qo'shadi.

<div id="list">
    <p>Item 1</p>
</div>

event(click) {
    return replace(
        <button>Prepend</button>,
        #list.prepend(<p>Item 0</p>)
    )
}

Natija:

<p>Item 0</p>     ← YANGI (tashqarida)
<div id="list">
    <p>Item 1</p>
</div>

Qachon ishlatiladi:

  • Elementdan oldin narsa qo'shish kerak bo'lsa
  • Yangi xabar yuqorida paydo bo'lishi kerak bo'lsa
  • Header qo'shish kerak bo'lsa

2. APPEND (tashqi oxiriga qo'shish)

Ma'nosi: Tanlangan elementning keyiniga (tashqarida) yangi element qo'shadi.

<div id="list">
    <p>Item 1</p>
</div>

event(click) {
    return replace(
        <button>Append</button>,
        #list.append(<p>Item 2</p>)
    )
}

Natija:

<div id="list">
    <p>Item 1</p>
</div>
<p>Item 2</p>     ← YANGI (tashqarida)

Qachon ishlatiladi:

  • Elementdan keyin narsa qo'shish kerak bo'lsa
  • Footer qo'shish kerak bo'lsa
  • Qo'shimcha ma'lumot ko'rsatish kerak bo'lsa

3. BEFORE (ichki boshiga qo'shish)

Ma'nosi: Tanlangan elementning ichiga, boshiga yangi element qo'shadi.

<div id="list">
    <p>Item 2</p>
</div>

event(click) {
    return replace(
        <button>Before</button>,
        #list.before(<p>Item 1</p>)
    )
}

Natija:

<div id="list">
    <p>Item 1</p>     ← YANGI (ichida, boshida)
    <p>Item 2</p>
</div>

Qachon ishlatiladi:

  • Ro'yxatning boshiga element qo'shish
  • Yangi item yuqorida paydo bo'lishi kerak
  • Eng muhim ma'lumotni tepaga qo'yish

4. AFTER (ichki oxiriga qo'shish)

Ma'nosi: Tanlangan elementning ichiga, oxiriga yangi element qo'shadi.

<div id="list">
    <p>Item 1</p>
</div>

event(click) {
    return replace(
        <button>After</button>,
        #list.after(<p>Item 2</p>)
    )
}

Natija:

<div id="list">
    <p>Item 1</p>
    <p>Item 2</p>     ← YANGI (ichida, oxirida)
</div>

Qachon ishlatiladi:

  • Ro'yxatning oxiriga element qo'shish
  • Yangi item pastda paydo bo'lishi kerak
  • Timeline'ga yangi post qo'shish

5. FILL (ichini to'liq almashtirish)

Ma'nosi: Elementning ichidagi hamma narsani o'chirib, yangi kontentni qo'yadi.

<div id="container">
    <p>Old 1</p>
    <p>Old 2</p>
    <p>Old 3</p>
</div>

event(click) {
    return replace(
        <button>Fill</button>,
        #container.fill(<p>Yangi content</p>)
    )
}

Natija:

<div id="container">
    <p>Yangi content</p>     ← Faqat bu qoldi
</div>

Qachon ishlatiladi:

  • Sahifani to'liq yangilash
  • Tab sistemasi (Home → About)
  • Search natijalarini ko'rsatish
  • Content zonasini almashtirish

6. SWAP (butun elementni almashtirish)

Ma'nosi: Butun elementni boshqa element bilan almashtiradi.

<div id="myDiv">
    <p>Bu DIV</p>
</div>

event(click) {
    return replace(
        <button>Swap</button>,
        #myDiv.swap(
            <section id="myDiv">
                <p>Bu SECTION</p>
            </section>
        )
    )
}

Natija:

<section id="myDiv">     ← DIV → SECTION
    <p>Bu SECTION</p>
</section>

Qachon ishlatiladi:

  • Element turini o'zgartirish (div → section)
  • Modal ko'rsatish/yashirish
  • Button → Loading spinner
  • Butun komponentni almashtirish

Metodlar taqqoslash jadvali

| Metod | Tashqi/Ichki | Joy | Eski content | Misol | |-------|--------------|-----|--------------|-------| | prepend | 🔵 Tashqi | Oldida | Saqlanadi | Header qo'shish | | append | 🔵 Tashqi | Keyinida | Saqlanadi | Footer qo'shish | | before | 🟢 Ichki | Boshida | Saqlanadi | Ro'yxat tepasiga | | after | 🟢 Ichki | Oxirida | Saqlanadi | Ro'yxat pastiga | | fill | 🟢 Ichki | Ichida | O'chiriladi | Sahifa yangilash | | swap | 🔴 Butun | O'sha o'rinda | O'chiriladi | Element almashtirish |


Event turlari

1. Mouse eventlari

click - bosish

event(click) {
    return replace(
        <button>Like</button>,
        <button onstyle="color: red">❤️ Liked</button>
    )
}

dblclick - ikki marta bosish

event(dblclick) {
    return replace(
        <div>Ikki marta bosing</div>,
        <div>Ikki marta bosildi!</div>
    )
}

mouseover - sichqoncha ustiga kelganda

event(mouseover) {
    return replace(
        <div>Hover me</div>,
        <div onstyle="background: yellow">Hovered!</div>
    )
}

mouseout - sichqoncha ketganda

event(mouseout) {
    return replace(
        <div onstyle="background: yellow">Hovered</div>,
        <div>Hover me</div>
    )
}

2. Form eventlari

submit - forma yuborilganda

<form>
    <input type="text" placeholder="Ismingiz">
    <button type="submit">Yuborish</button>
    
    event(submit) {
        return replace(
            <form>...</form>,
            <div>✅ Muvaffaqiyatli yuborildi!</div>
        )
    }
</form>

input - yozilayotganda

<input type="text">

event(input) {
    return replace(
        <input type="text">,
        #result.fill(<p>Siz yozyapsiz...</p>)
    )
}

change - o'zgarganda

<select>
    <option>Tanlang</option>
    <option>Option 1</option>
    <option>Option 2</option>
    
    event(change) {
        return replace(
            <select>...</select>,
            #result.fill(<p>Tanlov o'zgardi</p>)
        )
    }
</select>

Amaliy misollar

1. To-Do List

<grion>
<body>
    <h1>To-Do List</h1>
    
    <div id="todos">
        <p>Hozircha vazifa yo'q</p>
    </div>
    
    <input type="text" id="todoInput" placeholder="Yangi vazifa...">
    
    event(click) {
        return replace(
            <button>+ Qo'shish</button>,
            #todos.after(
                <div onstyle="
                    display: flex;
                    gap: 10px;
                    padding: 10px;
                    border: 1px solid #ddd;
                    margin: 5px 0;
                    border-radius: 5px;
                ">
                    <input type="checkbox">
                    <span>Yangi vazifa</span>
                    <button onstyle="
                        margin-left: auto;
                        background: red;
                        color: white;
                        padding: 5px 10px;
                        border: none;
                        border-radius: 3px;
                        cursor: pointer;
                    ">O'chirish</button>
                </div>
            )
        )
    }
</body>
</grion>

2. Tab System

<grion>
<body>
    <div onstyle="display: flex; gap: 10px; margin-bottom: 20px;">
        event(click) {
            return replace(
                <button onstyle="padding: 10px 20px; cursor: pointer;">Home</button>,
                #content.fill(
                    <div onstyle="padding: 20px; border: 1px solid #ccc;">
                        <h2>🏠 Home Page</h2>
                        <p>Bosh sahifaga xush kelibsiz!</p>
                    </div>
                )
            )
        }
        
        event(click) {
            return replace(
                <button onstyle="padding: 10px 20px; cursor: pointer;">About</button>,
                #content.fill(
                    <div onstyle="padding: 20px; border: 1px solid #ccc;">
                        <h2>ℹ️ About Page</h2>
                        <p>Biz haqimizda ma'lumot</p>
                    </div>
                )
            )
        }
        
        event(click) {
            return replace(
                <button onstyle="padding: 10px 20px; cursor: pointer;">Contact</button>,
                #content.fill(
                    <div onstyle="padding: 20px; border: 1px solid #ccc;">
                        <h2>📧 Contact Page</h2>
                        <p>Biz bilan bog'laning: [email protected]</p>
                    </div>
                )
            )
        }
    </div>
    
    <div id="content">
        <div onstyle="padding: 20px; border: 1px solid #ccc;">
            <h2>🏠 Home Page</h2>
            <p>Bosh sahifaga xush kelibsiz!</p>
        </div>
    </div>
</body>
</grion>

3. Counter (Hisoblagich)

<grion>
<body>
    <div onstyle="text-align: center; padding: 50px;">
        <div id="counter" onstyle="
            font-size: 72px;
            font-weight: bold;
            margin: 30px 0;
        ">0</div>
        
        <div onstyle="display: flex; gap: 20px; justify-content: center;">
            event(click) {
                return replace(
                    <button onstyle="
                        padding: 15px 30px;
                        font-size: 24px;
                        cursor: pointer;
                        background: #f44336;
                        color: white;
                        border: none;
                        border-radius: 10px;
                    ">−</button>,
                    #counter.fill(<span>Kamaydi</span>)
                )
            }
            
            event(click) {
                return replace(
                    <button onstyle="
                        padding: 15px 30px;
                        font-size: 24px;
                        cursor: pointer;
                        background: #9e9e9e;
                        color: white;
                        border: none;
                        border-radius: 10px;
                    ">Reset</button>,
                    #counter.fill(<span>0</span>)
                )
            }
            
            event(click) {
                return replace(
                    <button onstyle="
                        padding: 15px 30px;
                        font-size: 24px;
                        cursor: pointer;
                        background: #4caf50;
                        color: white;
                        border: none;
                        border-radius: 10px;
                    ">+</button>,
                    #counter.fill(<span>Ko'paydi</span>)
                )
            }
        </div>
    </div>
</body>
</grion>

4. Show/Hide Modal

<grion>
<body>
    event(click) {
        return replace(
            <button onstyle="
                padding: 10px 20px;
                cursor: pointer;
            ">Modalni ochish</button>,
            #modal.swap(
                <div id="modal" onstyle="
                    display: flex;
                    position: fixed;
                    top: 0;
                    left: 0;
                    width: 100%;
                    height: 100%;
                    background: rgba(0,0,0,0.5);
                    align-items: center;
                    justify-content: center;
                ">
                    <div onstyle="
                        background: white;
                        padding: 30px;
                        border-radius: 10px;
                        box-shadow: 0 4px 6px rgba(0,0,0,0.3);
                    ">
                        <h2>Modal Title</h2>
                        <p>Bu modal oyna</p>
                        
                        event(click) {
                            return replace(
                                <button onstyle="
                                    padding: 10px 20px;
                                    background: red;
                                    color: white;
                                    border: none;
                                    border-radius: 5px;
                                    cursor: pointer;
                                ">Yopish</button>,
                                #modal.swap(
                                    <div id="modal" onstyle="display: none;"></div>
                                )
                            )
                        }
                    </div>
                </div>
            )
        )
    }
    
    <div id="modal" onstyle="display: none;"></div>
</body>
</grion>

5. Like Button

<grion>
<body>
    <div onstyle="text-align: center; padding: 50px;">
        <div id="likeCount" onstyle="
            font-size: 48px;
            margin-bottom: 20px;
        ">0 ❤️</div>
        
        event(click) {
            return replace(
                <button onstyle="
                    padding: 15px 30px;
                    font-size: 20px;
                    background: white;
                    color: #333;
                    border: 2px solid #e0e0e0;
                    border-radius: 10px;
                    cursor: pointer;
                ">🤍 Like</button>,
                #likeCount.fill(<span onstyle="color: red">1 ❤️</span>)
            )
        }
    </div>
</body>
</grion>

6. Accordion

<grion>
<body>
    <div onstyle="max-width: 600px; margin: 50px auto;">
        <div onstyle="border: 1px solid #ddd; border-radius: 5px; margin: 10px 0;">
            <div id="acc1Content" onstyle="display: none; padding: 20px;">
                Bu birinchi accordion kontenti. Bu yerda batafsil ma'lumot bo'lishi mumkin.
            </div>
            
            event(click) {
                return replace(
                    <div onstyle="
                        padding: 15px;
                        background: #f5f5f5;
                        cursor: pointer;
                    ">
                        <strong>▶ Section 1</strong>
                    </div>,
                    #acc1Content.swap(
                        <div id="acc1Content" onstyle="display: block; padding: 20px;">
                            Bu birinchi accordion kontenti. Bu yerda batafsil ma'lumot bo'lishi mumkin.
                        </div>
                    )
                )
            }
        </div>
        
        <div onstyle="border: 1px solid #ddd; border-radius: 5px; margin: 10px 0;">
            <div id="acc2Content" onstyle="display: none; padding: 20px;">
                Bu ikkinchi accordion kontenti. Bu yerda batafsil ma'lumot bo'lishi mumkin.
            </div>
            
            event(click) {
                return replace(
                    <div onstyle="
                        padding: 15px;
                        background: #f5f5f5;
                        cursor: pointer;
                    ">
                        <strong>▶ Section 2</strong>
                    </div>,
                    #acc2Content.swap(
                        <div id="acc2Content" onstyle="display: block; padding: 20px;">
                            Bu ikkinchi accordion kontenti. Bu yerda batafsil ma'lumot bo'lishi mumkin.
                        </div>
                    )
                )
            }
        </div>
    </div>
</body>
</grion>

7. Search Filter

<grion>
<body>
    <input type="text" placeholder="Qidirish..." onstyle="
        width: 100%;
        padding: 10px;
        font-size: 16px;
        border: 1px solid #ddd;
        border-radius: 5px;
    ">
    
    event(input) {
        return replace(
            <input type="text" placeholder="Qidirish...">,
            #results.fill(
                <div>
                    <p>🔍 Qidirilmoqda...</p>
                </div>
            )
        )
    }
    
    <div id="results" onstyle="margin-top: 20px;">
        <p>Ma'lumot yo'q</p>
    </div>
</body>
</grion>

8. Notification System

<grion>
<body>
    <div id="notifications" onstyle="
        position: fixed;
        top: 20px;
        right: 20px;
        width: 300px;
    "></div>
    
    event(click) {
        return replace(
            <button onstyle="
                padding: 10px 20px;
                cursor: pointer;
            ">Show Notification</button>,
            #notifications.before(
                <div onstyle="
                    background: #4caf50;
                    color: white;
                    padding: 15px;
                    margin-bottom: 10px;
                    border-radius: 5px;
                    box-shadow: 0 2px 5px rgba(0,0,0,0.2);
                ">
                    ✅ Muvaffaqiyatli!
                </div>
            )
        )
    }
</body>
</grion>

Ilg'or texnikalar

1. Multiple events (Bir nechta eventlar)

<div>
    <button>Tugma</button>
    
    event(click) {
        return replace(
            <button>Tugma</button>,
            <button>Bosildi</button>
        )
    }
    
    event(mouseover) {
        return replace(
            <button>Tugma</button>,
            <button onstyle="background: yellow">Hover!</button>
        )
    }
    
    event(mouseout) {
        return replace(
            <button onstyle="background: yellow">Hover!</button>,
            <button>Tugma</button>
        )
    }
</div>

2. Nested events (Ichma-ich eventlar)

<div id="list"></div>

event(click) {
    return replace(
        <button>Add Item</button>,
        #list.after(
            <div onstyle="
                display: flex;
                gap: 10px;
                padding: 10px;
                border: 1px solid #ddd;
                margin: 5px 0;
            ">
                <span>Yangi item</span>
                
                event(click) {
                    return replace(
                        <button onstyle="background: red; color: white;">Delete</button>,
                        <span onstyle="color: red">O'chirildi</span>
                    )
                }
            </div>
        )
    )
}

Muhim eslatmalar

✅ To'g'ri

// 1. ID selector ishlatish
event(click) {
    return replace(
        <button>Add</button>,
        #list.after(<p>New item</p>)
    )
}

// 2. To'liq HTML yozish
event(click) {
    return replace(
        <button>Tugma</button>,
        <button>Yangi tugma</button>
    )
}

// 3. Nested HTML
event(click) {
    return replace(
        <button>Add</button>,
        #list.after(
            <div>
                <h3>Title</h3>
                <p>Content</p>
            </div>
        )
    )
}

❌ Noto'g'ri

// 1. "this" ishlatish (ishlamaydi)
event(click) {
    return replace(
        this,  // ❌ Xato!
        <button>Yangi</button>
    )
}

// 2. Class selector (faqat ID ishlaydi)
event(click) {
    return replace(
        <button>Add</button>,
        .myClass.after(<p>Item</p>)  // ❌ Xato!
    )
}

// 3. JavaScript o'zgaruvchilar (ishlamaydi)
event(click) {
    const text = "Hello";  // ❌ Xato!
    return replace(
        <button>Add</button>,
        <p>{text}</p>
    )
}

Xulosa

Event tizimining afzalliklari:

Oson o'rganish - oddiy sintaksis
Deklarativ - HTML bilan birgalikda
Kuchli - 6 ta manipulation metodi
Moslashuvchan - har qanday event turi
Optimizatsiya - avtomatik batching


Grion Extention bilan birga ishlating.


Bu yerdagi darslarni o'rganib o'z dasturlash tilingizni, fremworkingizni, DSLyingiz yaratishingiz mumkin bo'ladi.

1-dars: Tokenlar va Lexer

1. Token nima?

Token – bu matndagi ma’lum bir ma’noga ega bo‘lgan eng kichik bo‘lak.

Masalan, siz quyidagi kodni olasiz:

let x = 10 + 5;

Agar uni tokenlarga ajratsak:

| Token | Turi | Izoh | | ----- | ----------- | ---------------- | | let | keyword | JavaScript so‘zi | | x | identifier | o‘zgaruvchi nomi | | = | operator | tenglik belgisi | | 10 | number | raqam | | + | operator | qo‘shish belgisi | | 5 | number | raqam | | ; | punctuation | nuqta-vergul |

Token – matndagi “birlik”, bu kompyuter uchun ma’noli bo‘ladi.


2. Lexer nima?

Lexer (yoki lexical analyzer) – bu matnni tokenlarga ajratadigan dastur.

Agar misol bilan tushuntirsak:

Matn:

let x = 10 + 5;

Lexer uni tokenlarga ajratadi:

[let] [x] [=] [10] [+] [5] [;]

Qisqacha:

  • Lexer matnni “tahlil qiladi” va tokenlar ro‘yxatini hosil qiladi.
  • Tokenlar keyinchalik parser yoki interpreter tomonidan ishlatiladi.

3. Lexer qanday ishlaydi?

  1. Matnni oladi – butun kodni yoki matnni.
  2. Qoidalarni tekshiradi – masalan, raqamlar raqam tokeni, so‘zlar identifier tokeni.
  3. Tokenlarni chiqaradi – har bir tokenni ro‘yxatga qo‘shadi.
  4. Xatolarni aniqlaydi – agar matnda lexer tushunmaydigan belgilar bo‘lsa.

4. Misol

Matn:

3 + 4

Lexer ishlashi:

  1. 3 → number token
  2. + → operator token
  3. 4 → number token

Natija:

[
  { type: "number", value: "3" },
  { type: "operator", value: "+" },
  { type: "number", value: "4" }
]

Qisqacha esda tutish:

  • Token = matndagi eng kichik ma’noli bo‘lak.
  • Lexer = tokenlarni ajratuvchi dastur.
  • Lexer + Parser = dastur tilini tushunadigan tizim.

2-dars: Lexer Mode’lari

1. Mode nima?

Mode – lexer ishlash holati yoki konteksti.

  • Mode yordamida lexer qaysi qoidalar ishlashini biladi.
  • Misol: matnning bir qismi string bo‘lishi mumkin, bir qismi esa comment. Har bir holat uchun alohida qoidalar to‘plami (token turlari va regexlar) ishlatiladi.

2. Nega mode kerak?

Matnda turli kontekstlarda tokenlar turlicha ajratiladi.

Masalan, JavaScript kodi:

let text = "Hello, world!";
  • "Hello, world!" – bu string.
  • Lekin string ichidagi vergul yoki bo‘sh joy token emas, u stringning bir qismi.
  • Lexer default modedan string modega o‘tadi va string qoidalarini ishlatadi.

3. Mode bilan ishlash

Grion kodida mode bilan bog‘liq quyidagi xususiyatlar mavjud:

| Parametr | Izoh | | -------- | ------------------------------------------- | | push | Yangi mode’ga o‘tadi va stackga qo‘shiladi. | | pop | Stackdan hozirgi mode’ni olib tashlaydi. | | reset | Stackni faqat bitta mode bilan tiklaydi. |

Misol

const modes = {
  default: [
    { type: "stringStart", pattern: /"/, push: "string" },
  ],
  string: [
    { type: "stringContent", pattern: /[^"]+/ },
    { type: "stringEnd", pattern: /"/, pop: true }
  ]
};
  • Lexer default mode’da ishlaydi.
  • " belgisi kelganda, push: "string" orqali string modega o‘tadi.
  • String ichidagi matn stringContent tokeni sifatida olinadi.
  • " kelganda, pop: true ishlaydi va default modega qaytadi.

4. Mode stack tushunchasi

  • Lexer bir vaqtning o‘zida bir nechta mode bilan ishlashi mumkin.
  • modeStack yordamida qaysi mode hozir ishlayotganini aniqlaydi.

5. Amaliy misol

Matn:

"Hello" world

Lexer ishlash tartibi:

  1. " – default mode → string mode (push: "string")
  2. Hello – string mode → stringContent token
  3. " – string mode → pop (default modega qaytish)
  4. world – default mode → identifier token

Natija:

[
  { type: "stringStart", value: '"' },
  { type: "stringContent", value: "Hello" },
  { type: "stringEnd", value: '"' },
  { type: "identifier", value: "world" }
]

Xulosa

  • Mode = lexer ishlash holati.
  • Push / Pop / Reset orqali mode’larni boshqaramiz.
  • Mode stack lexerga kontekstni eslab qolish imkonini beradi.
  • Lexer har bir mode uchun alohida qoidalarni ishlatadi.

3-dars: Tokenlar yaratish type va pattern yordamida

1. Tokenni aniqlash uchun nimalar kerak?

Lexer tokenlarni aniqlash uchun qoidalarga muhtoj:

| Parametr | Ma’nosi | | --------- | ---------------------------------------------------------------------- | | type | Token turi (masalan, number, identifier, operator) | | pattern | Regex orqali tokenni aniqlash naqshi (masalan, /\d+/ raqamlar uchun) |


2. Token qoidalarini yozish

Lexer mode’larini Grion tuzilishga mos yozsak:

const modes = {
  default: [
    { type: "number", pattern: /\d+/ },
    { type: "identifier", pattern: /[a-zA-Z_]\w*/ },
    { type: "operator", pattern: /[+\-*/=]/ },
    { type: "whitespace", pattern: /\s+/, skip: true }
  ]
};
  • number → raqamlarni tanlaydi (123, 42 va hokazo).
  • identifier → o‘zgaruvchi nomlarini tanlaydi (x, totalSum).
  • operator → matematik yoki tenglik belgilarini tanlaydi (+, -, =).
  • whitespace → bo‘sh joylarni aniqlaydi, lekin skip: true orqali lexer ularni tokenlarga qo‘shmaydi.

3. Lexer yaratish

Grionning createLexer funksiyangizdan foydalanamiz:

const tokenize = createLexer(modes);
  • tokenize – bu endi matnni tokenlarga ajratuvchi funksiya.

4. Real matnni tokenlash

Matn:

let x = 10 + 5;

Tokenlash:

const input = "let x = 10 + 5;";
const result = tokenize(input);

console.log(result.tokens);

Natija:

[
  { type: "identifier", value: "let", start: {line:1, col:1}, end: {line:1, col:4} },
  { type: "identifier", value: "x", start: {line:1, col:5}, end: {line:1, col:6} },
  { type: "operator", value: "=", start: {line:1, col:7}, end: {line:1, col:8} },
  { type: "number", value: "10", start: {line:1, col:9}, end: {line:1, col:11} },
  { type: "operator", value: "+", start: {line:1, col:12}, end: {line:1, col:13} },
  { type: "number", value: "5", start: {line:1, col:14}, end: {line:1, col:15} },
  { type: "operator", value: ";", start: {line:1, col:15}, end: {line:1, col:16} }
]
  • Lexer tokenlarni chiqaradi, ular turi (type), qiymati (value) va joylashuvi (start, end) bilan birga keladi.
  • skip: true bo‘lgan tokenlar (bo‘sh joy) ro‘yxatga kirmaydi.

5. Qoidalar ustida ishlash

Siz qo‘shimcha xususiyatlarni ham ishlatishingiz mumkin:

| Parametr | Ma’nosi | | -------- | -------------------------------------------- | | value | Token qiymatini o‘zgartirish funksiyasi | | emit | Bir token o‘rniga bir nechta token chiqarish | | when | Token faqat shart bajarilganda ishlaydi |

Misol:

{ 
  type: "keyword", 
  pattern: /let|const|var/, 
  value: text => text.toUpperCase() 
}
  • Lexer let ni token sifatida tanlaydi va qiymatini LET ga o‘zgartiradi.

6. Xulosa

  • Token type va pattern orqali aniqlanadi.
  • Lexer createLexer orqali ishlatiladi va real matnni tokenlarga ajratadi.
  • Har bir token type, value, start va end bilan keladi.
  • Qo‘shimcha parametrlar orqali lexerni moslash va kuchaytirish mumkin.

4-dars: Lexer qoidalaridagi barcha key’lar

Lexer qoidalarida har bir token uchun turli parametrlar ishlatiladi. Grionda ular quyidagicha:

| Key | Ma’nosi | Misol | | | --------- | ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------ | -------------------------------------- | | type | Token turi (name) | "number", "identifier", "operator" | | | pattern | Regex orqali tokenni aniqlash | /\d+/ raqamlar uchun | | | skip | Agar true bo‘lsa, token ro‘yxatga qo‘shilmaydi | { type: "whitespace", pattern: /\s+/, skip: true } | | | push | Yangi mode’ga o‘tadi va modeStack ga qo‘shiladi | { type: "stringStart", pattern: /"/, push: "string" } | | | pop | ModeStack dan hozirgi mode’ni olib tashlaydi | { type: "stringEnd", pattern: /"/, pop: true } | | | reset | Stackni faqat bitta mode bilan tiklaydi | { type: "resetMode", pattern: /---/, reset: "default" } | | | value | Token qiymatini o‘zgartiradigan funksiya | { type: "keyword", pattern: /let, const/, value: t => t.toUpperCase() } | | emit | Bir token o‘rniga bir nechta token chiqarish funksiyasi | { type: "numbers", pattern: /\d+/, emit: val => [{type:"digit", value: val[0]}, {type:"digit", value: val[1]}] } | | | error | Agar true bo‘lsa, token topilmasa xatolik hisoblanadi | { type: "unknown", pattern: /./, error: true } | | | when | Token faqat shart bajarilganda ishlaydi | { type: "special", pattern: /[@#]/, when: ctx => ctx.modeStack.includes("default") } | | | fast | Tezkor filter: faqat ma’lum bir belgilar bilan boshlanadigan regexlar ishlaydi | { type: "number", pattern: /\d+/, fast: "0123456789" } | |


1. Mode bilan bog‘liq key’lar

  • push → yangi mode’ga o‘tadi, masalan string boshlanganda
  • pop → mode’ni tugatadi, masalan string oxirida
  • reset → mode stack ni faqat bitta mode bilan tiklaydi

Misol:

const modes = {
  default: [
    { type: "stringStart", pattern: /"/, push: "string" }
  ],
  string: [
    { type: "stringContent", pattern: /[^"]+/ },
    { type: "stringEnd", pattern: /"/, pop: true }
  ]
};

2. Token qiymati bilan ishlash

  • value → token qiymatini o‘zgartiradi
  • emit → token o‘rniga bir nechta token chiqaradi

Misol:

{ 
  type: "keyword", 
  pattern: /let|const/, 
  value: t => t.toUpperCase() 
}

{ 
  type: "digits", 
  pattern: /\d{2}/, 
  emit: val => [{type:"digit", value: val[0]}, {type:"digit", value: val[1]}] 
}

3. Xatolik va shartlar

  • error → agar token topilmasa xatolik sifatida qayd etadi
  • when → token faqat shart bajarilganda ishlaydi

Misol:

{ type: "unknown", pattern: /./, error: true }

{ type: "special", pattern: /[@#]/, when: ctx => ctx.modeStack.includes("default") }

4. Tezkor tokenlash

  • fast → faqat ma’lum belgilar bilan boshlanadigan regexlarni ishlatadi
  • Bu katta matnlarni tokenlashda tezlikni oshiradi

Misol:

{ type: "number", pattern: /\d+/, fast: "0123456789" }

5. Real matn misoli

Matn:

let x = 10 + 5;

Lexer qoidalari:

const modes = {
  default: [
    { type: "keyword", pattern: /let|const|var/ },
    { type: "identifier", pattern: /[a-zA-Z_]\w*/ },
    { type: "number", pattern: /\d+/ },
    { type: "operator", pattern: /[+\-*/=;]/ },
    { type: "whitespace", pattern: /\s+/, skip: true }
  ]
};

Tokenlash:

const tokenize = createLexer(modes);
const result = tokenize("let x = 10 + 5;");
console.log(result.tokens);

Natija:

[
  { type: "keyword", value: "let" },
  { type: "identifier", value: "x" },
  { type: "operator", value: "=" },
  { type: "number", value: "10" },
  { type: "operator", value: "+" },
  { type: "number", value: "5" },
  { type: "operator", value: ";" }
]

6. Xulosa

  • Lexerning barcha key’lari: type, pattern, skip, push, pop, reset, value, emit, error, when, fast.
  • Har bir key tokenlash jarayonini moslashtiradi.
  • Mode’lar va stack orqali lexer kontekstga qarab ishlaydi.
  • skip, value, emit bilan tokenlar ustida qo‘shimcha ishlar qilish mumkin.

5-dars: Kuchliroq Lexer va Turli Mode’lar

1. Nega turli mode’lar kerak?

Turli kontekstdagi matnlarni tokenlash uchun mode ishlatiladi. Misol:

  • default mode – oddiy kod
  • string mode" " ichidagi matn
  • comment mode// yoki /* */ ichidagi izohlar

Har bir mode o‘ziga xos token qoidalariga ega.


2. Mode’larni yaratish

const modes = {
  default: [
    { type: "keyword", pattern: /\b(let|const|var)\b/ },
    { type: "identifier", pattern: /[a-zA-Z_]\w*/ },
    { type: "number", pattern: /\d+/ },
    { type: "operator", pattern: /[+\-*/=;]/ },
    { type: "stringStart", pattern: /"/, push: "string" },
    { type: "commentStart", pattern: /\/\/|\/\*/, push: "comment" },
    { type: "whitespace", pattern: /\s+/, skip: true }
  ],
  
  string: [
    { type: "stringContent", pattern: /[^"]+/ },
    { type: "stringEnd", pattern: /"/, pop: true }
  ],
  
  comment: [
    { type: "singleLineComment", pattern: /\/\/.*/, pop: true },
    { type: "multiLineCommentContent", pattern: /[^*]+/ },
    { type: "multiLineCommentEnd", pattern: /\*\//, pop: true }
  ]
};

Izohlar:

  • "push" → yangi mode’ga o‘tadi
  • "pop" → hozirgi mode tugaydi va oldingi mode ga qaytadi
  • "skip" → bo‘sh joy tokenlarga qo‘shilmaydi

3. Lexer yaratish

const tokenize = createLexer(modes);

4. Real matn misoli

const code = `
let x = 42;
let msg = "Hello, world!";
// Bu comment
/* Bu
   multi-line
   comment */
`;

Tokenlash:

const result = tokenize(code);
console.log(result.tokens);

Natija:

[
  { type: "keyword", value: "let" },
  { type: "identifier", value: "x" },
  { type: "operator", value: "=" },
  { type: "number", value: "42" },
  { type: "operator", value: ";" },
  
  { type: "keyword", value: "let" },
  { type: "identifier", value: "msg" },
  { type: "operator", value: "=" },
  { type: "stringStart", value: '"' },
  { type: "stringContent", value: "Hello, world!" },
  { type: "stringEnd", value: '"' },
  { type: "operator", value: ";" },
  
  { type: "singleLineComment", value: "// Bu comment" },
  { type: "multiLineCommentContent", value: " Bu\n   multi-line\n   comment " },
  { type: "multiLineCommentEnd", value: "*/" }
]

5. Lexerning ishlash printsipi

  1. Lexer default mode bilan boshlaydi.
  2. Agar " " kelib chiqsa → string mode ga push qilinadi.
  3. Agar // yoki /* kelib chiqsa → comment mode ga push qilinadi.
  4. Har bir mode o‘zining token qoidalari bilan ishlaydi.
  5. Mode oxirida pop ishlaydi va lexer avvalgi modega qaytadi.

6. Xulosa

  • Mode stack orqali lexer turli kontekstlarni ajrata oladi.
  • String, comment va kod tokenlari bir vaqtda ishlashi mumkin.
  • push va pop bilan mode’larni boshqarish lexerga kuchli moslashuvchanlik beradi.
  • Bu yondashuv haqiqiy dasturlash tillari lexerlarida ishlatiladi.

6-dars: Lexer Pluginlari va Hook-lar

1. Plugin nima?

Plugin – lexerga qo‘shimcha xususiyat qo‘shadigan modul yoki funksiya.

  • Lexer asosiy tokenlashni qiladi, lekin pluginlar yordamida siz tokenlarni o‘zgartirish, tekshirish yoki xatolarni loglash kabi ishlarni bajarishingiz mumkin.
  • Grionda pluginlar quyidagi hook-larni ishlatadi:

| Hook | Ma’nosi | | ------------- | --------------------------------------------- | | beforeToken | Token ro‘yxatga qo‘shilishidan oldin ishlaydi | | afterToken | Token ro‘yxatga qo‘shilgandan keyin ishlaydi | | onError | Tokenlash vaqtida xatolik yuz bersa ishlaydi |


2. Plugin yaratish

Misol: tokenlarni log qilish va xatoliklarni ko‘rsatish

const loggerPlugin = {
  beforeToken: (def, ctx) => {
    console.log("Token chiqarishdan oldin:", def.type);
  },
  afterToken: (token, ctx) => {
    console.log("Token chiqarildi:", token.type, token.value);
  },
  onError: (err, ctx) => {
    console.error("Xatolik:", err.message, "line:", err.line, "col:", err.col);
  }
};
  • beforeToken → token stackga qo‘shilishidan oldin ishlaydi
  • afterToken → token stackga qo‘shilgandan keyin ishlaydi
  • onError → xatolik yuz berganda ishlaydi

3. Lexerga plugin qo‘shish

const tokenize = createLexer(modes, [loggerPlugin]);
  • Endi tokenlash jarayoni loggerPlugin orqali qo‘shimcha ishlarni bajaradi.
  • Har bir token chiqarilishida konsolga ma’lumot yoziladi.

4. Real misol

Matn:

let x = 10 + 5;

Tokenlash:

const result = tokenize("let x = 10 + 5;");

Konsol natijasi:

Token chiqarishdan oldin: keyword
Token chiqarildi: keyword let
Token chiqarishdan oldin: identifier
Token chiqarildi: identifier x
Token chiqarishdan oldin: operator
Token chiqarildi: operator =
Token chiqarishdan oldin: number
Token chiqarildi: number 10
...

Agar xatolik yuz bersa, masalan, noma’lum belgi bo‘lsa:

Xatolik: Unexpected token line: 1 col: 8

5. Pluginlar yordamida qo‘shimcha imkoniyatlar

  1. Tokenlarni filtrlash yoki o‘zgartirish
const upperCaseKeywordPlugin = {
  afterToken: (token) => {
    if (token.type === "keyword") token.value = token.value.toUpperCase();
  }
};
  1. Maxsus xatolarni loglash yoki hisoblash
const errorCounterPlugin = {
  onError: (err, ctx) => {
    ctx.data.errorCount = (ctx.data.errorCount || 0) + 1;
  }
};
  1. Token statistikasi
const statsPlugin = {
  afterToken: (token, ctx) => {
    ctx.data[token.type] = (ctx.data[token.type] || 0) + 1;
  }
};

6. Xulosa

  • Pluginlar lexerga qo‘shimcha ishlov berish imkonini beradi.
  • Har bir plugin beforeToken, afterToken yoki onError hooklariga ega bo‘lishi mumkin.
  • Siz tokenlarni loglash, o‘zgartirish, statistikalarni olish yoki xatolarni hisoblash kabi ishlarni bajarishingiz mumkin.
  • Lexerni modul tarzida kengaytirish va kuchaytirishning eng qulay yo‘li – pluginlar.

7-dars: To‘liq kuchli lexer yaratish

1. Maqsad

Bu darsda biz quyidagilarni birlashtiramiz:

  • Mode’lar: default, string, comment
  • Token qoidalari: keyword, identifier, number, operator, string, comment
  • Pluginlar: token loglash, xatolarni hisoblash, tokenlarni o‘zgartirish

Natijada lexer real dastur kodini to‘liq tokenlay oladi.


2. Mode’lar va token qoidalari

const modes = {
  default: [
    { type: "keyword", pattern: /\b(let|const|var|if|else|for|while)\b/ },
    { type: "identifier", pattern: /[a-zA-Z_]\w*/ },
    { type: "number", pattern: /\d+/ },
    { type: "operator", pattern: /[+\-*/=<>!]+/ },
    { type: "punctuation", pattern: /[;,.(){}]/ },
    { type: "stringStart", pattern: /"/, push: "string" },
    { type: "commentStart", pattern: /\/\/|\/\*/, push: "comment" },
    { type: "whitespace", pattern: /\s+/, skip: true }
  ],

  string: [
    { type: "stringContent", pattern: /[^"]+/ },
    { type: "stringEnd", pattern: /"/, pop: true }
  ],

  comment: [
    { type: "singleLineComment", pattern: /\/\/.*/, pop: true },
    { type: "multiLineCommentContent", pattern: /[^*]+/ },
    { type: "multiLineCommentEnd", pattern: /\*\//, pop: true }
  ]
};

Izoh:

  • default: oddiy kod va string/comment boshlanishlarini aniqlaydi
  • string: string ichidagi matnni tokenlaydi
  • comment: comment ichidagi matnni tokenlaydi
  • push va pop orqali mode’lar stack bilan boshqariladi

3. Pluginlar yaratish

  1. Token loglash
const loggerPlugin = {
  beforeToken: (def, ctx) => console.log("Token chiqarishdan oldin:", def.type),
  afterToken: (token, ctx) => console.log("Token chiqarildi:", token.type, token.value),
  onError: (err, ctx) => console.error("Xatolik:", err.message, "line:", err.line, "col:", err.col)
};
  1. Tokenlarni o‘zgartirish (keywordlarni katta harfga)
const upperCaseKeywordPlugin = {
  afterToken: (token) => {
    if (token.type === "keyword") token.value = token.value.toUpperCase();
  }
};
  1. Xatoliklar statistikasi
const errorCounterPlugin = {
  onError: (err, ctx) => {
    ctx.data.errorCount = (ctx.data.errorCount || 0) + 1;
  }
};

4. Lexer yaratish

const tokenize = createLexer(modes, [loggerPlugin, upperCaseKeywordPlugin, errorCounterPlugin]);
  • Endi lexer mode’lar va pluginlar bilan ishlaydi.

5. Real matn misoli

const code = `
let x = 42;
let msg = "Hello, world!";
// Bu comment
/* Multi-line
   comment */
if (x > 10) x = x + 1;
`;

Tokenlash:

const result = tokenize(code);
console.log(result.tokens);
console.log("Xatoliklar soni:", result.ctx.data.errorCount || 0);

Natija:

Token chiqarildi: keyword LET
Token chiqarildi: identifier x
Token chiqarildi: operator =
Token chiqarildi: number 42
Token chiqarildi: punctuation ;
...
Token chiqarildi: stringStart "
Token chiqarildi: stringContent Hello, world!
Token chiqarildi: stringEnd "
...
Token chiqarildi: singleLineComment // Bu comment
Token chiqarildi: multiLineCommentContent Multi-line\n   comment
Token chiqarildi: multiLineCommentEnd */
...
Xatoliklar soni: 0
  • Lexer string, comment, number, operator, identifier, keyword va punctuation tokenlarini ajratadi
  • Keyword’lar plugin orqali katta harfga aylantirildi
  • Xatoliklar plugin orqali hisoblandi

6. Xulosa

  • Mode’lar lexerga kontekstni eslatadi: default, string, comment
  • Push/Pop/Reset bilan mode stack boshqariladi
  • Token qoidalari: type va pattern orqali tokenlar aniqlanadi
  • Pluginlar: token loglash, o‘zgartirish va xatoliklar statistikasi qo‘shadi
  • Bu yondashuv haqiqiy, kuchli lexer yaratish uchun yetarli

8-Dars: AST (Abstract Syntax Tree) bilan tanishuv

8.1 AST nima?

AST (Abstract Syntax Tree) – bu dastur kodining semantik (ma’noli) daraxt ko‘rinishidagi tasviri.

  • “Abstract” – chunki AST har bir kichik token yoki bracketni ko‘rsatmaydi, faqat dastur semantikasini ifodalaydi.
  • “Syntax Tree” – chunki u kodni daraxt tuzilishida saqlaydi, har bir tugun (node) bir operatsiya yoki elementni ifodalaydi.

Oddiy qilib aytganda, AST — bu kodning kompyuter tushunadigan semantik modelidir.


8.2 AST nimaga kerak?

AST dasturda quyidagi vazifalarni bajaradi:

  1. Kod tahlili (Analysis)

    • Masalan, o‘zgaruvchi ishlatilgan joylarni aniqlash.
  2. Transformatsiya

    • Kodni optimizatsiya qilish, masalan x + 0x.
  3. Interpretatsiya / bajarish

    • AST dan to‘g‘ridan-to‘g‘ri natija hisoblash.
  4. Kompilyatsiya

    • AST dan boshqa tilga kod yozish yoki mashina kodiga aylantirish.

8.3 AST tuzilishi (node)

AST tugunlardan iborat:

  • Har bir tugun (node) bir elementni ifodalaydi.
  • Tugun turi (type) va qiymat (value) bo‘ladi.
  • Tugun ichida boshqa tugunlar (children) bo‘lishi mumkin.

Misol: 5 + 10

{
  type: "BinaryExpression",
  operator: "+",
  children: [
    { type: "NumberLiteral", value: 5, children: [] },
    { type: "NumberLiteral", value: 10, children: [] }
  ]
}
  • BinaryExpression → root tugun
  • NumberLiteral → child nodes
  • children → AST dagi keyingi elementlar

8.4 AST yaratish jarayoni

1-qadam: Lexer → tokenlar

5 + 10

Lexer natijasi:

[
  { type: "Number", value: "5" },
  { type: "Plus", value: "+" },
  { type: "Number", value: "10" }
]

2-qadam: Parser → AST

  • Grammar qoidalariga muvofiq tokenlar tekshiriladi.
  • buildFn yoki helper funksiyalar yordamida AST tugunlari yaratiladi.
bin("+", num(5), num(10))  // AST tuguni

Natija: AST

{
  type: "BinaryExpression",
  operator: "+",
  children: [
    { type: "NumberLiteral", value: 5, children: [] },
    { type: "NumberLiteral", value: 10, children: [] }
  ]
}

8.5 Xulosa

  • AST — bu kodning semantik daraxt ko‘rinishi.
  • Lexer → tokenlar, Parser + Grammar → AST.
  • AST yordamida siz kodni tahlil, transformatsiya, interpretatsiya yoki kompilyatsiya qilishingiz mumkin.
  • AST “toza” daraxt bo‘lgani uchun ortiqcha tokenlar yo‘q, faqat semantik ma’no mavjud.

9-Dars: Lexer tokenlaridan AST yaratish

9.1 Maqsad

  • Lexerdan olingan tokenlar → AST
  • AST tugunlarini yaratish uchun helperlar (num, bin, node, …) ishlatiladi
  • Grammar patternlari (seq, or, ref, rule) parser uchun ishlatiladi

9.2 Oddiy misol

Input:

5 + 10

Lexer natijasi:

const tokens = [
  { type: "Number", value: "5" },
  { type: "Plus", value: "+" },
  { type: "Number", value: "10" }
];

9.3 Grammar va buildFn

Parserga grammatikani aytamiz:

const grammarDef = grammar({
  Expr: rule(
    seq("Number", "Plus", "Number"),
    ([left, op, right]) => bin(op.value, num(left.value), num(right.value))
  )
});
  • `seq("Number", "Plus", "Number")