ساخت زبان برنامه نویسی

  • شروع کننده موضوع
  • #1

مثبت

مستِ بودن
ارسال‌ها
630
امتیاز
5,767
نام مرکز سمپاد
علامه حلی ۱
شهر
تهران
سال فارغ التحصیلی
1406
تلگرام
خب تازه یه آموزش پیدا کردم که چگونه میشه زبان برنامه نویسی
نوشت ( که آموزشش با node.js بود ) تصمیم گرفتم برای اینکه خودمم یاد بگیرم
و اینکه شاید برای شما هم جالب باشه یه آموزش با توضیحای ساده که حداقل در حد
فهم خودم هم باشه بذارم به زبان php که (در عین دور بودن ) به سی پلاس پلاس نزدیکه
( حقیقتا رو سیستم جدیدم هنوز وقت نکردم سی پلاس پلاس و سی شارپو راه بندازم
و از طرفی سخت میشه اون موقع مفهومش پیچیده تر میشه که من میخوام ساده تر باشه )

هدفمون اینه : مثلا میخوایم یه زبان برنامه نویسی بنویسیم که کاربردش برای مدیریت فایله
( میشه توابع بیشتری هم اضافه کرد ولی فعلا سه تا تابع برای آموزشمون مینویسیم واسه زبانمون )

خب شروع :
چیکارا باید بکنیم ؟
باید یه کامپایلر بنویسیم . به زبان ساده یعنی یه کدی که میاد کد های نامفهوم زبان جدید مون رو
به کد های استاندارد زبان پایه تبدیل میکنه ( مثلا زبان پایه پایتون ش میشه همون سی پلاس پلاس ، یعنی کد پایتون
رو به زبان سی پلاس پلاس کامپایل میکنه و بر اون اساس اجراش میکنه )

برای خودمون هم دو تا اصطلاح تعریف میکنیم :
زبان هدف ( زبانی که مینویسیم ) ، زبان مبدا ( زبانی که باهاش کامپایلر رو مینویسیم )

با این حساب اولین کاری که برای شروع کار باید بکنیم تعیین کردن سینتکس زبان هدفه که کدای زبان مبدا رو بر اون اساس مینویسیم
اینا سینتکسای کد زبان هدفمونه که توی فایل main.filer با فرمت اختصاصی خودمون یعنی .filer ذخیره میکنیم :
کد:
- we most define a way to add comments in our language
- we use "- " at first of line as a way to add comments :)
- only one function is executed in each line of our language ( like python )
fopen "../example.txt" as hello
- to open a file or folder and save as a variable named "hello"
fprint hello
- to print content if "hello" was a file ( not dir )
fdel hello
- to delete var and file in "hello"
fwrite hello
frname hello
- to rename or delete "hello"
flist hello
- to list files in "hello" if it was a folder
fclose hello
- to close an opened file or folder that saved as "hello" and removing this variable

یه زبان هدف ساده با همین توابع در همین سطح فعلا کافیه بنظرم :))
توضیح کاربرد هر تابع توی کامنت های کدمون نوشته شده
کامنت بودن هر متن با "- " اول اون خط مشخص میشه ( حتما توضیحاشو بخونین )
کدای زبان منبع ( filer.php همون کدای کامپایلر ) رو هم توی پست بعدی میذارم
( چون همین الان همزمان مینویسم شاید طول بکشه )
 
  • شروع کننده موضوع
  • #2

مثبت

مستِ بودن
ارسال‌ها
630
امتیاز
5,767
نام مرکز سمپاد
علامه حلی ۱
شهر
تهران
سال فارغ التحصیلی
1406
تلگرام
خب اینم یه کلیت پروژمون تا الان
Untitled.png

دو تا فایل سمت چپ example.txt ( فایلیه که قراره توسط زبان هدف برای مثال باهاش کار بشه )
و main.filer ( فایل یه کد معمولی زبان هدفه که باید درست کار کنه )
کد سمت راست مهمه که کدای زبان منبعمونه که اگه یذره هم برنامه نویسی کار کرده باشین
واضحه و احتیاجی به توضیح نداره تا اینجاش ( یه کلاس به نام filer برای تعریف توابع و کاربرداشون
و در کل خوندن فایل کد و کامپایل کردنش تعریف کردیم )

یه متغیر $keywords هم تعیین کردیم که هر چی داخلش قرار میگیره میشه
توابع تعریف شده زبان برنامه نویسی ما ( از اینجا میتونیم توابع بیشتر اضافه کنیم که
فعلا همین 5 6 تا رو گذاشتم ) داخل تابع run هم باید کد های کامپایل کردن
و نحوه خوندن کد و توابعشو بنویسیم

در واقع وقتی ما یه کد پایتون رو اجرا میکنیم اون فایل exe که باهاش کدمون رو اجرا میکنه
یه همچین کدیه که با زبان منبع خودش یعنی سی پلاس پلاس نوشته شده
حالا زبان ما هم در حال حاضر با اجرای این کد php اجرا میشه : ))
 
  • شروع کننده موضوع
  • #3

مثبت

مستِ بودن
ارسال‌ها
630
امتیاز
5,767
نام مرکز سمپاد
علامه حلی ۱
شهر
تهران
سال فارغ التحصیلی
1406
تلگرام
خب همونطوری که گفتیم توی هر خط filer فقط میشه
یه تابع رو صدا زد و یا یه کامنت گذاشت
پس باید کاری کنیم که کد به خط های سازندش تقسیم بشه
و در نهایت توی تابع run() همه خط ها رو بصورت متغیر $lines داریم
و کد داخل هر خط رو از طریق foreach بصورت $line داریم
PHP:
<?php

class filer
{
    public $code = [];
    public $keywords = ["fopen", "fprint", "fdel", "fwrite", "frname", "fclose"];

    function __construct($code)
    {
        $line_number = 1;
        $code = fopen($code, "r");
        while (($line = fgets($code)) !== false) {
            $this->code[] = $line;
            $line_number++;
        }

        fclose($code); // close the file
    }

    function run()
    {
        $variables = [];
        $lines = $this->code;
        foreach ($lines as $line) {
            // compile all lines
        }
    }
}

$program = new filer("main.filer");
$program->run();
?>
در ضمن همونطوری که اسم متغیر $variables مشخصه
یه متغیره که بعد از کامپایل کد ، متغیر هایی که توی کد هدف
برنامه نویس زبان ما قراره تعریف کنه رو توش ذخیره میکنیم
 
  • شروع کننده موضوع
  • #4

مثبت

مستِ بودن
ارسال‌ها
630
امتیاز
5,767
نام مرکز سمپاد
علامه حلی ۱
شهر
تهران
سال فارغ التحصیلی
1406
تلگرام
خب یه حرکت شوتی که من انجام دادم این بود
که $keywords که برای تعریف توابع و متغیر ها و اینا بود
رو توی کلاس به عنوان متغیر پابلیک تعریف کردم ،
که خب کارو سخت و اضافه میکنه ، بهترین کار اینه که
این کد رو از کلاس پرتابش کنیم به داخل تابع run()
چونکه فقط اینجا از این آرایه استفاده میشه ،
پس باید متغیر $keywords رو حذف کنیم
و داخل تابع run تعریفش کنیم که کد منطقی تر باشه
و در نهایت کد run() جدید این میشه :
PHP:
<?php

class filer
{
    public $code = [];

    function __construct($code)
    {
        $line_number = 1;
        $code = fopen($code, "r");
        while (($line = fgets($code)) !== false) {
            $this->code[] = $line;
            $line_number++;
        }

        fclose($code);
    }

    function run()
    {
        $variables = [];
        $keywords = ["fopen" => function ($value) {
            // codes for fopen
        }, "fprint" => function ($value) {
            // codes for fprint
        }, "fdel" => function ($value) {
            // codes for fdel
        }, "fwrite" => function ($value) {
            // codes for fwrite
        }, "frname" => function ($value) {
            // codes for frname
        }, "fclose" => function ($value) {
            // codes for fclose
        }, "flist" => function ($value) {
            // codes for flist
        }, "frnam" => function ($value) {
            // codes for frnam
        }];
        $lines = $this->code;
        $line_count = 0;
        foreach ($lines as $line) {
            $line_count++;
            if (substr($line, 0, 2) !== "- ") {
                // if this line was not commented :
                $line = trim($line);
                // to remove spaces from start and end of a line
                // for example : "     fwrite hello" to "fwrite hello"
                $keyword = "";
                $value = "";
                $keyword_changed = false;
                $selected_word = 0;
                foreach (str_split($line) as $word) {
                    $selected_word++;
                    if ($keyword_changed == 0) {
                        $keyword .= $word;
                        if (array_key_exists($keyword, $keywords)) {
                            $keyword_changed = 1;
                        }
                    } else {
                        $value .= $word;
                        if ($selected_word == strlen($line)) {
                            $value = trim($value);
                            $keywords[$keyword]($value);
                        }
                    }
                }
                if (!empty($line) && $keyword_changed == false) {
                    echo "no function found in line $line_count";
                    exit();
                }
            }
        }
    }
}

$program = new filer("main.filer");
$program->run();
?>
کار اضافه ای که انجام دادیم این بود که کامپایلر
بعد خوندن هر خط ، بره سراغ خوندن هر حرف داخل هر خط
و اگه تابع تعریف مجازی توی اون خط تعریف نشده بود
میگه که توی خط فلان هیچ تابعی وجود نداره و اگه وجود داشت
اون رو توی متغیر $keyword قرار میده ( با $keywords اشتباه نگیرین )
در نهایت مقدار ورودی هر خط رو داخل متغیر value میریزه
و با $keywords جدید هر تابعی که تعریف شده باشه توش رو با مقدار
$value اجرا میکنه ( دو تا تابع جدید هم به keywords اضافه کردیم ) ... ( پست بعدی )
 
  • شروع کننده موضوع
  • #5

مثبت

مستِ بودن
ارسال‌ها
630
امتیاز
5,767
نام مرکز سمپاد
علامه حلی ۱
شهر
تهران
سال فارغ التحصیلی
1406
تلگرام
از اینجای کار
دیگه هر کی میتونه بر اساس کاری که میخواد انجام بده
زبانش ، توابع و کلیدواژه های اضافه خودشو تعریف کنه ( چون زبان ما فقط تابع داره
لزوما قرار نیست که فقط همین طوری باشه ، میشه توی $keywords مثلا
دیتا تایپ تعریف کرد که بشه متغیر درست کرد توی زبانتون و بریزتش توی آرایه $variables
ولی خب زبان ما سادست و فقط برای مدیریت فایله ، پس هر فایلی که باز میشه بصورت
یه متغیر توی این آرایه هه ذخیره میشه
 
  • شروع کننده موضوع
  • #6

مثبت

مستِ بودن
ارسال‌ها
630
امتیاز
5,767
نام مرکز سمپاد
علامه حلی ۱
شهر
تهران
سال فارغ التحصیلی
1406
تلگرام
PHP:
<?php

class filer
{
public $code = [];

function __construct($code)
    {
$line_number = 1;
$code = fopen($code, "r");
while (($line = fgets($code)) !== false) {
$this->code[] = $line;
$line_number++;
        }

fclose($code);
    }

function run()
    {
global $variables;
 $variables = [];
global $contents;
 $contents = [];
global $line_count;
$line_count = 0;
function givevar($input, $allow_continue = 0)
        {
global $variables;
global $contents;
global $line_count;
if (((str_starts_with($input, '"') && str_ends_with($input, '"')) || (str_starts_with($input, "'") && str_ends_with($input, "'")))) {
if (file_exists(substr($input, 1, -1)) || is_dir(substr($input, 1, -1))) {
if ($allow_continue == 2) {
echo "\nfile already exists in path called in line $line_count";
 exit();
} else {
return substr($input, 1, -1);
                    }
} else {
if ($allow_continue == 2) {
fclose(fopen(substr($input, 1, -1), 'w'));
} elseif ($allow_continue == 3) {
return substr($input, 1, -1);
} else {
echo "\nno file exists in path called in line $line_count";
 exit();
                    }
                }
} else {
if (in_array($input, $variables)) {
if ($allow_continue == 0) {
return $contents[array_search($input, array_keys($variables))];
} else {
echo "\nvariable with name \"$input\" already defined with in line $line_count";
 exit();
                    }
} else {
if ($allow_continue == 0) {
echo "\nno variable exists named \"$input\" in line $line_count";
 exit();
} else {
$variables[] = $input;
                    }
                }
            }
        }

$keywords = ["fopen" => function ($input) {
$input = [trim(explode('as', $input)[0], ' \t\n\r\0\x0B'), trim(explode('as', $input)[1], ' \t\n\r\0\x0B')];
$input[1] = givevar($input[1], 1);
$input[0] = givevar($input[0]);
global $contents;
$contents[] = $input[0];
}, "fprint" => function ($input) {
$input = givevar(trim($input));
echo file_get_contents($input);
}, "fdel" => function ($input) {
$input = givevar(trim($input));
if (is_dir($input)) {
function clear_directory($dir)
                {
$files = glob($dir . '/{,.}*', GLOB_BRACE);
foreach ($files as $file) {
if (is_file($file)) {
unlink($file);
} elseif (is_dir($file)) {
clear_directory($file);
rmdir($file);
                        }
                    }
                }

clear_directory($input);
} else {
unlink($input);
            }
}, "fwrite" => function ($input) {
$input = [trim(explode('with', $input)[0], ' \t\n\r\0\x0B'), trim(explode('with', $input)[1], ' \t\n\r\0\x0B')];
$input[0] = givevar($input[0]);
if((str_starts_with($input, '"') && str_ends_with($input, '"')) || (str_starts_with($input, "'") && str_ends_with($input, "'"))){
fwrite(fopen($input[0], "w"), substr($input[1], 1, -1));
}else{
echo "variable is not usable as fwrite content";
            }
}, "flist" => function ($input) {
$input = givevar(trim($input));
}, "frnam" => function ($input) {
$input = [trim(explode('to', $input)[0], ' \t\n\r\0\x0B'), trim(explode('to', $input)[1], ' \t\n\r\0\x0B')];
$input[0] = givevar($input[0]);
$input[1] = givevar($input[1], 3);

rename($input[0], $input[1]);
}, "fnew" => function ($input) {
$input = [trim(explode('as', $input)[0], ' \t\n\r\0\x0B'), trim(explode('as', $input)[1], ' \t\n\r\0\x0B')];
$input[0] = givevar($input[0], 2);
$input[1] = givevar($input[1], 1);
global $contents;
$contents[] = $input[1];
        }];
$lines = $this->code;
global $line_count;
$line_count = 0;
foreach ($lines as $line) {
 $line_count++;
if (substr($line, 0, 2) !== "- ") {
// if this line was not commented :
                $line = trim($line);
// to remove spaces from start and end of a line
                // for example : "     fwrite hello" to "fwrite hello"
                $keyword = "";
$value = "";
$keyword_changed = false;
$selected_word = 0;
foreach (str_split($line) as $word) {
 $selected_word++;
if ($keyword_changed == 0) {
$keyword .= $word;
if (array_key_exists($keyword, $keywords)) {
$keyword_changed = 1;
                        }
} else {
$value .= $word;
if ($selected_word == strlen($line)) {
$value = trim($value);
$keywords[$keyword]($value);
                        }
                    }
                }
if (!empty($line) && $keyword_changed == false) {
echo "\nno function found in line $line_count";
 exit();
                }
            }
        }
    }
}

$program = new filer("main.filer");
$program->run();
?>

اینم کد کامل شده زبان جدید ما :))
به همین قشنگی و راحتی
فقط یسری جاهاش کامل نیستن ( مثلا همه اررورا بررسی نمیشن و
پیغام دیفالت خود php نشون داده میشه ، که اینم باید روش کار کرد بعدا )
اگه کسی کدو بهتر تونست بکنه بفرسته همین تاپیک تا فیض ببریم
چند تا از توابع زبان هدف رو هم عوض کردم :

کد:
- we most define a way to add comments in our language
- we use "- " at first of line as a way to add comments :)
- only one function is executed in each line of our language ( like python )
fopen "../example.txt" as hello
- to open a file or folder and save as a variable named "hello"
fprint hello
- to print content if "hello" was a file ( not dir )
fdel hello
- to delete var and file in "hello"
fwrite hello
frnam hello
- to rename or delete "hello"
( اون دو سه تا رو هم میتونستم بنویسم ولی دارم میرم ناهار بقولم :)) )
امیدوارم فیض برده باشید
1659783711251.jpg
 
بالا