|
<?php |
|
|
|
class Birnarsa { |
|
private $code; |
|
/* Ruxsat etilgan funksiyalar */ |
|
const BUILT_IN_KEYWORDS = ["chopet", "yangiqator"]; |
|
/* Kalit so'zlar (funksiya nomlar, o'zgaruvchilar) uchun ruxsat etilgan belgilar */ |
|
const ALLOWED_KEYWORD_CHARS = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_'; |
|
|
|
function __construct( $code ) { |
|
$this->code = $code; |
|
} |
|
|
|
public function tokenize() { |
|
$length = strlen( $this->code ); |
|
$pos = 0; |
|
$tokens = []; |
|
|
|
while ( $pos < $length ) { |
|
$currentChar = $this->code[$pos]; |
|
|
|
//Joriy indeks bo'sh belgi yoki yangi qatorga mos kelsa siklni shunchaki davom etish |
|
if ($currentChar === " " || $currentChar === "\n") { |
|
$pos++; |
|
continue; |
|
} else if ($currentChar === '"') { //agar joriy belgi " bo'lsa satr kuzatilgan |
|
$res = ""; |
|
$pos++; |
|
|
|
// keyingi belgi " yoki \n belgilariga mos kelmasa kod tugallanmagan |
|
while ($pos < $length-1 && $this->code[$pos] !== '"' && $this->code[$pos] !== '\n') { |
|
$res .= $this->code[$pos]; |
|
$pos++; |
|
} |
|
//Yuqoridagi sikldan so'ng " belgisi topilmasa demak tugallanmagan satr haqida xatolik qaytarish |
|
if ($this->code[$pos] !== '"') { |
|
return [ |
|
'error' => ( $pos+1 ) . "-pozitsiyadagi qo'shtirnoq yopilsa keyin ishga tushish haqida o'ylab ko'raman :)" |
|
]; |
|
} |
|
|
|
$pos++; |
|
//Shartlar mos kelsa token massiviga satrni qo'shish |
|
$tokens[] = [ |
|
'type' => 'string', |
|
'value' => $res, |
|
]; |
|
} else if ( strpos( self::ALLOWED_KEYWORD_CHARS , $currentChar ) !== FALSE) { |
|
$res = $currentChar; |
|
$pos++; |
|
// satr tugallagunga qadar ruxat etilgan kalit so'z belgilariga tekshirish |
|
while($pos < $length && strpos( self::ALLOWED_KEYWORD_CHARS, $this->code[$pos] ) !== FALSE) { |
|
$res .= $this->code[$pos]; |
|
$pos++; |
|
} |
|
//Token ruxsat etilgan funksiyalar doirasida bo'lmasa |
|
if ( ! in_array($res, self::BUILT_IN_KEYWORDS ) ) { |
|
return [ |
|
'error' => "\"$res\" vazifasi haqida bilmayman, faqat matn chop etishdan xabarim bor" |
|
]; |
|
} |
|
|
|
//Shartlar mos kelsa token massiviga funksiyani qo'shish |
|
$tokens[] = [ |
|
'type' => 'keyword', |
|
'value' => $res, |
|
]; |
|
} else { // kodda keraksiz belgi mavjud |
|
return [ |
|
'error' => "$pos-pozitsiyadagi belgi ($currentChar) juda qiziqarli, lekin tushunarsiz" |
|
]; |
|
} |
|
} |
|
|
|
// Tokenlarni parser uchun qaytarish |
|
return [ |
|
'error' => FALSE, |
|
'tokens' => $tokens |
|
]; |
|
} |
|
|
|
public function parse( $tokens ) { |
|
$len = count( $tokens ); |
|
$pos = 0; |
|
while($pos < $len) { |
|
$token = $tokens[$pos]; |
|
// Token chopetga mos kelsa |
|
if($token['type'] === "keyword" && $token['value'] === "chopet") { |
|
//chopet argumenti uchun keyingi indeksdagi tokenni tekshirish |
|
if(empty($tokens[$pos + 1])) { |
|
exit( ($pos + 1) . "-qator uchun argumentni enamdan olamanmi?"); |
|
} |
|
//chopet argumenti sifatida keyingi token "string"ga mos kelishini tekshirish |
|
if($tokens[$pos + 1]['type'] != "string") { |
|
exit( ($pos + 1) . "-qatorda ikkita qo'chqor kallasi bitta qozonda qaynamasligiga misol ko'rish mumkin"); |
|
} |
|
|
|
//Tekshiruv o'tgan chopet argumentini o'zak til orqali ekranga chiqarish |
|
echo $tokens[$pos + 1]['value']; |
|
$pos += 2; |
|
}else if($token['type'] === "keyword" && $token['value'] === "yangiqator") { |
|
echo PHP_EOL; |
|
$pos += 1; |
|
}else{ |
|
//Token hech qaysi qoidalarga mos kelmasa |
|
exit ("\"{$token['value']}\" vazifasi haqida bilmayman, faqat matn chop etishdan xabarim bor"); |
|
} |
|
} |
|
} |
|
|
|
public function run() { |
|
$result = $this->tokenize(); |
|
if ( !empty( $result['error'] ) ) { |
|
exit( $result['error'] ); |
|
} |
|
|
|
echo "Token: " . json_encode($result['tokens']) .PHP_EOL; |
|
echo "Natija:".PHP_EOL; |
|
echo str_repeat('-', 30).PHP_EOL; |
|
$this->parse( $result['tokens'] ); |
|
echo PHP_EOL.str_repeat('-', 30).PHP_EOL; |
|
} |
|
} |
|
|
|
|
|
if( !empty($argv[1]) ){ |
|
if (!file_exists($argv[1]) ) { |
|
exit( "Ko'rsatilgan fayl topilmadi".PHP_EOL ); |
|
} |
|
$code = file_get_contents($argv[1]); |
|
$compiler = new Birnarsa( $code ); |
|
$compiler->run(); |
|
}else{ |
|
exit( "Kompiliyatsiya uchun dastur kodi ko'rsatilmadi".PHP_EOL ); |
|
} |