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
Maintainers
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 grionYoki Yarn orqali:
yarn add grionYoki 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 grionNatijada 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.json2-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
titleichida 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:
- 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>- 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); -->- 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:
Browser DevTools'da tekshiring:
- Element'ga qaysi class berilgan?
- CSS fayli yuklanganmi?
- Selector to'g'rimi?
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,dvw→vh,vw - ✅
lvh,lvw→vh,vw - ✅
svh,svw→vh,vw
Zamonaviy Xususiyatlar
- ✅
backdrop-filter→ opacity fallback - ✅
@container→@mediafallback - ✅
@property→@supportsbilan - ✅
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 kerakeski_element- qaysi elementni almashtirishyangi_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?
- Matnni oladi – butun kodni yoki matnni.
- Qoidalarni tekshiradi – masalan, raqamlar raqam tokeni, so‘zlar identifier tokeni.
- Tokenlarni chiqaradi – har bir tokenni ro‘yxatga qo‘shadi.
- Xatolarni aniqlaydi – agar matnda lexer tushunmaydigan belgilar bo‘lsa.
4. Misol
Matn:
3 + 4Lexer ishlashi:
3→ number token+→ operator token4→ 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
defaultmode’da ishlaydi. "belgisi kelganda,push: "string"orqali string modega o‘tadi.- String ichidagi matn
stringContenttokeni sifatida olinadi. "kelganda,pop: trueishlaydi va default modega qaytadi.
4. Mode stack tushunchasi
- Lexer bir vaqtning o‘zida bir nechta mode bilan ishlashi mumkin.
modeStackyordamida qaysi mode hozir ishlayotganini aniqlaydi.
5. Amaliy misol
Matn:
"Hello" worldLexer ishlash tartibi:
"– default mode → string mode (push: "string")Hello– string mode → stringContent token"– string mode → pop (default modega qaytish)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,42va hokazo).identifier→ o‘zgaruvchi nomlarini tanlaydi (x,totalSum).operator→ matematik yoki tenglik belgilarini tanlaydi (+,-,=).whitespace→ bo‘sh joylarni aniqlaydi, lekinskip: trueorqali 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: truebo‘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
letni token sifatida tanlaydi va qiymatiniLETga o‘zgartiradi.
6. Xulosa
- Token
typevapatternorqali aniqlanadi. - Lexer
createLexerorqali 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,emitbilan 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
- Lexer default mode bilan boshlaydi.
- Agar
" "kelib chiqsa →stringmode ga push qilinadi. - Agar
//yoki/*kelib chiqsa →commentmode ga push qilinadi. - Har bir mode o‘zining token qoidalari bilan ishlaydi.
- Mode oxirida
popishlaydi va lexer avvalgi modega qaytadi.
6. Xulosa
- Mode stack orqali lexer turli kontekstlarni ajrata oladi.
- String, comment va kod tokenlari bir vaqtda ishlashi mumkin.
pushvapopbilan 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 ishlaydiafterToken→ token stackga qo‘shilgandan keyin ishlaydionError→ 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: 85. Pluginlar yordamida qo‘shimcha imkoniyatlar
- Tokenlarni filtrlash yoki o‘zgartirish
const upperCaseKeywordPlugin = {
afterToken: (token) => {
if (token.type === "keyword") token.value = token.value.toUpperCase();
}
};- Maxsus xatolarni loglash yoki hisoblash
const errorCounterPlugin = {
onError: (err, ctx) => {
ctx.data.errorCount = (ctx.data.errorCount || 0) + 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
pushvapoporqali mode’lar stack bilan boshqariladi
3. Pluginlar yaratish
- 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)
};- Tokenlarni o‘zgartirish (keywordlarni katta harfga)
const upperCaseKeywordPlugin = {
afterToken: (token) => {
if (token.type === "keyword") token.value = token.value.toUpperCase();
}
};- 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:
Kod tahlili (Analysis)
- Masalan, o‘zgaruvchi ishlatilgan joylarni aniqlash.
Transformatsiya
- Kodni optimizatsiya qilish, masalan
x + 0→x.
- Kodni optimizatsiya qilish, masalan
Interpretatsiya / bajarish
- AST dan to‘g‘ridan-to‘g‘ri natija hisoblash.
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 tugunNumberLiteral→ child nodeschildren→ AST dagi keyingi elementlar
8.4 AST yaratish jarayoni
1-qadam: Lexer → tokenlar
5 + 10Lexer natijasi:
[
{ type: "Number", value: "5" },
{ type: "Plus", value: "+" },
{ type: "Number", value: "10" }
]2-qadam: Parser → AST
- Grammar qoidalariga muvofiq tokenlar tekshiriladi.
buildFnyoki helper funksiyalar yordamida AST tugunlari yaratiladi.
bin("+", num(5), num(10)) // AST tuguniNatija: 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 + 10Lexer 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")
