نگاه کن اگه بخوای مستقل از Platform عمل کنی نمی تونی یه کد رو برای چند Platform کامپایل کنی. باید برای Windows از API استفاده کنی، برای Lunux از وقفه ی 80h استفاده کنی و برای فلانی فلان کارو کنی. حالا اگه نه بتونی از وقفه استفاده کنی، نه حداقل API تعریف کنی، هیچ کار نمی تونی بکنی. بعدشم قرار نیست توابعی که با API ها یا وقفه ها تعریف می شن رو هر دفعه کاربر تعریف کنه. بلکه باید یه بار اینا رو توی فایل های lib تعریف کنیم. حالا اگه بخوایم یه روال بنویسیم برای چند Platform، باید همین کاری که در زبان C یا زبان های دیگه می کنند رو انجام بدیم، یعنی یه سری If تعریف کنیم که اینا اجرا نشن، فقط کامپایلر موقع کامپایل چکشون کنه یا حالا هر کار دیگه ای... مثلا اگه با FASM کار کنی می بینی که یه کتابخانه ای ساختن برای Windows، Linux و DOS که تو یک کد رو می نویسی و برای Platform های مختلف کامپایل می کنی. اما از کجا می فهمه Platform ات چی می خوای باشه، می بینه که System رو (نام یه ثابت هست) برابر با چی قرار دادی تو برنامت.
می بینی که هر زبانی (که مستقل از Platform هست) یه روشی رو برای کامپیال کردن واسه Platform مورد نظر، در نظر گرفته. اما در نهایت باید امکان استفاده از امکانات هر Platform وجود داشته باشه که حالا بخواد انتخابی صورت بگیره.
اگه می خوای مستقل از Platform بنویسیم باید هم بتونه از Interrupt ها استفاده کنه و هم بتونه از API ها استفاده کنه (API ها مختص Windows نیستن هر سیستمی API های مربوط به خودشو می تونه داشته باشه)، حالا این استفاده کننده هر کی که می خواد باشه، چه کسی باشه که برنامه های کاربردیشو می نویسه و چه کسی باشه که lib ها رو می نویسه و جزئیات رو از دید پنهان می کنه.
در مورد for هم من یه پیشنهاد دارم:
for (counter,1,100,+2)
دستورات
revert for
توضیحات:
آرگومان اول یک متغیر شمارنده هست
آرگومان دوم نشان دهنده مقدار شمارنده در شروع حلقه
آرگومان سوم هم حداکثر تعداد تکرار
و آرگومان چهارم که اختیاری هست یرای مشخص کردن step هست که میتونه منفی هم باشه.
نظرت چه؟
من با استفاده برنامه نویس از API اصلآ مشکلی ندارم. فقط میگم نباید برای کارهای اصلی زبان مثل خواندن و نوشتن در کنسول, برنامه نویس مجبور باشه از API استفاده کنه.
تو اگه چند زبان به عنوان نمونه بهم نشون بدی که از این روش استفاده میکنند.اونوقت قانع میشم و این کارو منطقی میدونم.
کار های مربوط به Import کردن توابع رو FASM انجام می ده، ما فقط کافیه کد رو تولید کنیم که بهش بگیم Import کن.
مثلا این طوری:
section '.idata' import data readable writeable
dd 0,0,0,RVA kernel_name,RVA kernel_table
dd 0,0,0,RVA user_name,RVA user_table
dd 0,0,0,0,0
kernel_table:
ExitProcess dd RVA _ExitProcess
dd 0
user_table:
MessageBox dd RVA _MessageBoxA
dd 0
kernel_name db 'KERNEL32.DLL',0
user_name db 'USER32.DLL',0
البته می تونیم به طور ساده تر از macro استفاده کنیم.
بعضی زبان هایی که خوندن و نوشتن در Console جزیی از وظایف کامپایلرشون نیست:
اول از همه که خود زبان Assemby مثلا MASM،
زبان C، مثلا ++VC.
و برعکس:
زبان BASIC مثلا QBASIC، برای سادگی این کارو کرده،
زبان Pascal که نمی دونم به خاطر سادگی این کارو کرده یا اون زمانی که نوشتنش شرایط این طوری بوده یا ... .
کامپایلر های معروف برای هر سیستم عاملی یک نسخه مخصوص اون دارن. ولی اگه دقت کنی تقریبآ ساختار زبان و دستورات در محیطهای مختلف یکیه.
ببخشیدا!! ولی فکر میکنم این خیلی خنده دار باشه که مثلا تو کتاب آموزش زبان سی بخونی که برای نوشتن در خط فرمان در ویندوز از api استفاده میشه ولی چون تو لینوکس API ویندوز نیست باید از وقفه یا از فایلهای کتابخانه ای استفاده کنی.
معلومه که خنده داره، چون قراره طرف زبان C رو یاد بگیره، نه نحوه ی کار توابع API ویندوز یا وقفه های Linux. اما حقیتا این طوریه، شما الان یه برنامه ی ساد با ++C بنویس، مثلا من با Dev نوشتم، همون برنامه ی معروف Hello World همیشگی در Console. بعد Compile کن و فایل exe رو در PE Explorer باز کن، ببین توی کدش چی کار کرده، از توابع API موجود در کتابخانه ی [؟] استفاده می کنه.
آره، ولی اگه یکی بخواد تو محیط Windows فایل برای Linux تولید کنه باید بتونه.کامپایلر های معروف برای هر سیستم عاملی یک نسخه مخصوص اون دارن.
ببینید مثلا در زبان FASM یا MASM یا ... بدون API چه طور می خواید برای Windows برنامه بنویسید؟!من منظورم کامپایلری بود که برای نوشتن در خط فرمان, برنامه نویس راه دیگه ای جز استفاده از API نداشته باشه. نه این که در کنار دستورات اصلی خودش بتونی از API هم استفاده کنی.
ببین باید تمام جوانب رو در نظر گرفت. حالتی رو در نظر بگیر که برنامه نویس از یه تابع که در dll نیست استفاده کنه.خوب در این حالت یعنی ما باید فرض کنیم که تابع درسته و بسپاریم به اسمبلر که اونم با مشکل مواجه میشه و برای فهمیدن مشکل مجبوریم باز در کد اسمبلر دست ببریم که کار رو مشکل میکنه.
در ثانی اصلا شاید منظور برنامه نویس تابع درون dll هم نبود. و کلآ یه تابع تعریف نشده در برنامه بود.اونوقت چی؟؟
ولی همونطور که گفتم این یه راه حل ساده داره که ما میتونیم توابع و آرگومانهای dll رو بدست بیاریم و به این ترتیب این توابع رو از نظر نام و آرگومان بررسی کنیم. و در صورت عدم اشکال به اسمبلر اجازه استفاده از تابع رو بدیم. به همین سادگی.
سلام
موضوع جالبیه!
اول خیلی سطحی صفحه اول و صفحه آخر این تاپیک رو خوندم و خواستم یه نظر دیگه اینجا بنویسم... گفتم بذار کامل بخونمش. فکر نمی کردم اینقدر به این موضوع ساده نگاه کرده باشید.
ببینید یه نمونه خیلی ساده برای درخت تجزیه. ما می خوایم یه قانون بذاریم برای انواع عملیات ضرب و جمع و پرانتز:
E ----> E+E|E*E|(E)|Id
خوب ظاهرا ما یه قانون داریم باهاش می تونیم یه گرامر بسازیم و از روی اون یه درخت پارسر داشته باشیم. اما خیلی زود به این مشکلات بر می خوریم:
اولا برای یک عبارت ممکنه دو تا درخت تجزیه ایجاد کرد. مثلا عبارت id*id+id رو به دو شکل میشه ایجاد کرد و این به تنهایی اثبات کننده گنگ بودن این گرامره. برای گرامر گنگ نمیشه به همین شکل کاری کرد.
ضمن اینکه ما در اینجا چپگردی داریم. چپ گردی به معنای ایجاد تداخل در شروط داخل توابع پیاده سازیه قوانینه.
خب ما باید اول رفع گنگی بکنیم:
E ----> E+T|T
T----> T*F|F
F----> (E)|id
خب ما با تغییراتی که دایدم تونستیم رفع گنگی بکنیم. اما هنوز رفع چپگردی نکردیم. باید هرجا چپگردی ضمنی هم هست کشف کنیم و گرامر رو عوض کنیم تا بتونیم از ین مرحله سر سلامت رد کنیم.
E---->TE’
E’---->+TE’|ε
T---->FT’
T’---->*FT’|ε
F---->(E)|id
تمام اینکارا رو کردیم تا بتونیم قوانین ضرب و جمع و پرانتز خیلی ساده رو بتونیم بدون تداخل یا چپگردی یا گنگی داشته باشم تا بتونیم با مثلا سی یا هرچیه دیگه پیاده سازی کنیم.
درخت تجزیه بسته به نوع گرامری که انتخاب می کنید(پایین به بالا یا بالا به پایین) قابل بدست آوردنه. در پارس ورودی هر گرامر با استفاده از جدول مربوط به هر نوع گرامر میشه درخت تجزیه رو رسم کرد.
مثال بالا فقط یک مثال بود. ما همین مشکل رو در if و else های متوالی داریم. اونجا هم باید به همین شیوه برخورد کرد.
قدرتمند ترین گرامری که من می شناسم گرامر clr(0) هستش. برای رسیدن به این گرامر باید از پایه درست عمل بشه.
شما یکسری توانایی های خوبی دارید. من هم قبول دارم. اما اینها هیچ ربطی به کاری که براش آستین بالا زدید نداره.
شما API رو خوب بلدید کار با زبان VB رو هم خوب بلدید یا هر ابزار دیگه رو... خوب اینا چه ارتباطی با مفاهیم ایجاد یک کامپایلر داره.
پیشنهاد من اینه: بطور عمقی... خیلی بیشتر از چیزایی که برای نمره احتمالا بالایی که در این درس آوردید... مطلب بخونید. با اساتیدتون بطور تنگاتنگ ارتباط برقرار کنید. مطمئن باشید می تونید اگر دانشجو هستید بعنوان پروژه پایانی روش سرمایه گذاری کنید یا حداقل یه مقاله ای چیزی باهاش بدید. یه کاری که ارزش داشته باشه و انگیزه هم به اندازه کافی ایجاد کنه. اگر هم دانشجو نیستید یه تجربه بسیار عالیه. البته رایگان هم نخواهد بود.(انرژی و زمان)
گذشته از این مفاهیم شما رو دعوت می کنم به بررسی زبان هایی مثل RUBY. زبانی کاملا متفاوت با چیزایی که تابحال دیدید(البته اگه اینو ندیده باشید.)
اصلا در چه حیطه ای می خواید زبان ایجاد کنید. در حیطه ی هوش مصنوعی. در حیطه شی گرایی در حیطه ارتباط با سرور یا... . شما بنظر دارید چیزایی که دیدید رو اینبار اونجور که می خواید تغییر می دید. خوب؟ بهبودش کجاست؟ چه معنای جدیدی رو قراره بهش اضافه کنید؟ چه ایده خلاقانه ای براش درنظر گرفتید؟ و از همه مهمتر در کجا قصد دارید ازش استفاده کنید. چه حیطه ای؟
کار، کار پر بار و خوش محصولیه. اما اگر اصولی از ابتدا پیش برید به نتیجه می رسید. مطالب و سر فصل های منابع اصلی اصول طراحی زبانهای برنامه نویسی و مفاهیم طراحی کامپایلر ها می تونه واقعا مفید باشه. مثه یه نقشه راه. اما بسیار بیشتر از اینکه تابحال کار کردید باید عمیق بشید.
قدری دانش Exploid هم یاد بگیرید تا در طراحی کدهاتون بتونید مشکلاتی که بعضی زبانها دارن رو به حداقل برسونید.
شاید برای شروع کمی زیاد اوج گرفتید. فعلا زمان یادگرفتنه. اصلا تابحال فکر کرده بودید چرا یه زبان نیاز به قوانین و گرامر داره. ماشیا آتاماتا به چه درد می خوره. NFAو DFA چه ربطی به زبانهای برنامه نویسی دارن. چرا آقای نوام چامسکی که یک زبان دان و فیلسوف هست و بعنوان پدر زبانشناسی مدرنه همچنین درمورد روانشناسی تالیفاتی داره... چرا این آدم نظریه هایی در مورد زبانشناسی اونم در حیطه زبانهای کامپیوتری داده؟
وقتی داشتم در مورد انواع زبان برنامه نویسی موازی تحقیق می کردم این اسم رو مدام می دیدم Per Brinch Hansen
این شخص آدم جالبیه و در آزمایشگاهش زبانهای زیادی رو تولید و گسترش داده. (پاسکال یکیشه...)
بنظرم مطالعه در مورد روش کار این آدم و کارهایی که کرده می تونه مفید باشه.
شرطها و حلقه ها وامثال اینها واقعا مسائل و مفاهیمی هستن که باید پایه ای تر بهشون فکر کنید. اینکه چطور پیاده سازی بشن مسئله شما نیست. مسئله شما اینه که چطور قراره مفاهیمش رو پیاده کنید. فقط خود همین if و else های متوالی رو کمی بیشتر درموردش فکر کنید. شما یه برنامه می نویسید کلی باگ و ارور و وارنینگ داره حالا چطور از همون روش می خواید استفاده کنید برای طراحی یک کامپایلر که خودش باید اینا رو تشخیص بده؟
حالا اینا به کنار. کاربر یه گرامر غلط وارد می کنه. چطور می خواید درستش رو بهش بگید؟ یعنی در ارور یا وارنینگ چه گزارش خطایی باید ثبت بشه؟ چه عبارتی پیشنهاد بشه؟ اصلا چه سیاساتی باید اعمال بشه؟ حذف از ورودی تا درست شدن گرامر یا کامپایل کردن بقیه کد و درنهایت دادن یک گزارش کلی...
تابحال به این فکر کردید کامپایلر زبانی مثلا مثل جاوا رو با چی نوشتن؟ و اگه با هرچی نوشتن پس باید کامپایلر اون زبان هم داخل کامپایلر جاوا تعبیه شده باشه؟(منظورم اینجا اسمبلی نیست)
قصدم ازطرح این مطالب و سوالات به معنای سنگ اندازی یا دادن حس ناامیدی نیست. بلکه جدا با این شوری که در این حدود 120 تا پستی که خوندم دیدم گفتن این مطالب لازمه.
اگه دانشگاه هستید با 3 تا استاد حتما صحبت کنید. استاد درس PL و استاد درس نظریه زبانها و ماشینها و استاد درس اصول طراحی کامپایلرها. اگه کسی رو می شناسید که توی هر 3 تای اینا دستی داره قدرش رو بدونید.
براتون آرزوی موفقیت می کنم.
من نمیدونم شاید منظورتون رو از استفاده از API برای کارهای ساده بد متوجه شدم. اگه منظورتون استفاده ما برای پیاده سازی و در مرحله ایجاد کد اسمبلی هست و برنامه نویس کاری به اون نداره, من اشکالی نمیبینم. ولی اگه منظورتون اینه که برنامه نویس مجبور باشه برای انجام کارهای ساده ای مثل نوشتن در خط فرمان از API استفاده کنه, کاملآ مخالفم.
دوست عزیز ممنون از نظرتون. راستش اینقدر که کاربر دیگه ای رو در تاپیک نداشتیم اولش شما رو با اون دوست همیشگی اشتباه گرفتم.به هر حال ببخشید.
می خوام یه جواب کلی به نظراتتون بدم.البته اگه روی سخنتون با من بود. ببینید این مسائلی که فرمودید کاملا درست بود اما فکر میکنم که الان زمان حل این مشکلات نیست. مثلا بحث گرامرهای مبهم رو برای دستورات شرطی درنظر بگیرید.ما وقتی هنوز ساختار دستورات شرطیمون مشخص نیست چطور باید به فکر حل این مشکل باشیم.شاید شاید شاید ساختاری که ما طراحی کردیم اصلا مشکل ابهام نداشته باشه.در مورد نحوه برخورد با خطاها هم به همین شکل(پوشش خطا یا توقف). من نظرم این بود که اول بدنه اصلی ساختار نحوی مشخص بشه. و بعد به این مشکلات رسیدگی کنیم و یا حتی در صورت لزوم ساختار نحوی رو تغییر بدیم. ولی در کل با شما موافقم که باید در مورد ساختارهای اصلی مثل ساختار شرطی و..... به شکل عمیقتری بحث بشه.بازم ممنون.
در ضمن انصافآ نوام چامسکی رو نمیشه فقط در زبانشناسی و روانشناسی خلاصه کرد. اون رو میشه در خیلی از عرصه های علمی یا غیر علمی یک اسطوره در عصر حاضر دونست.
آخرین ویرایش به وسیله amin32 : پنج شنبه 06 بهمن 1390 در 21:50 عصر
ترجیه می دم بجای جواب کلی قدری بیشتر به نکات مختلفی که طرح کردم فکر کنید.
تاحالا چند بار در این فروم در تاپیکهای مختلف استارت طراحی یه کامپایلر کوچیک یا بزرگ و یا بخشی از اون زده شده و دفعاتی که من پیگیرش بودم موفقیتی ندیدم دقیقا به همین دلایلی که عرض کردم.
مهمترین چیزی که دوس داشتم بعد خوندن مطلب بالا بنظر برسه اینه که مسلط بودن بر tools فرق اساسی با مسلط بودن به یک دانش داره.
و این دقیقا اولین مشکلیه که در طراحی یک کامپایلر راه رو به بیراهه می بره. پروژه های نیمه کاره... افراد با استعداد ناامید ... .
همین ساختارهای شرطی و ... اینها بعد از خیلی از مفاهیم پایه ایه نوع زبانتون مشخص میشه.
به نظرتون احترام میگذارام اما باز فکر میکنم شما تمام تاپیک رو نخوندید و دارید در مورد من قضاوت میکنید.
https://barnamenevis.org/showthread.p...=1#post1421219
این رو هم اضافه کنم که من استارت پروژه رو نزدم و اینجام تا زمانی که وقت آزاد دارم و تا جایی که بتونم در این مورد راهنمایی کنم.
اما به نظر من اصلا منطقی به نظر نمیاد وقتی هنوز ساختار زبان شخص نیست بیایم تصمیم بگیریم که مثلآ از (LALR(1 استفاده کنیم یا از (clr(0 یا حتی اگه بهینگی برامون زیاد اهمیتی نداشت شاید (LR(1
همه 140 پست رو خوندم. فایلهای ضمیمه شده رو هم دانلود کردم اما هنوز ندیدم. ولی اینا و همه اینایی که گفتم رو به خودتون و شخصتتون نگیرد من جدا دوست دارم شما در این تاپیک موفق بشید.
من جرات اینکه اینجا قضاوتی بکنم ندارم. چه اینکه بارها در برخی از پستها از خودم پرسیدم من اصلا در مورد مقطع تحصیلی و یا دانش این دوستان اطلاعی ندارم. شاید اینا که بگم قدری از سطح دوستان پایینتر باشه.
لینک این صفحه رو به دوستان و اساتیدی که می شناسم می دم تا نظر اونها رو بدونم.
شما هم بحث رو گسترش بدید.
خوب خیلی خوب شد، از 3 نفر کار بیش تری بر می آد ... .
ببینید در مورد تسلط به ابزار و کد مقصد و ...، فکر نمی کنم مشکلی باشه.
فقط باید تمام فکر و ذکرمونو، بذاریم رو این که چه طور یه کامپایلر رو بر اساس مفاهیم و روش های استانداردی که هست، پیاده سازی کنیم. اتفاقا این که شما یه سری مسائل و مشکلات رو از قبل در میون می ذارید خیلی خوبه، این باعث می شه که کارو با احتیاط بیش تری ادامه بدیم، و خیلی دوست دارم که این قضیه ی گوشزد کردن مشکلات (نه ناامید کردن) ادامه پیدا کنه.
حالا قبل از این که به هر مشکلی در زمینه ی طراحی بر بخوریم، به نظرم اول باید بفهمیم چیو می خوایم طراحی کنیم و با چی روبه رو هستیم.
در مورد مسائل تئوری هم من همزمان دارم سعی می کنم بیش تر و بیش تر بفهمم، از روی کتاب ها برم جلو.
امیدوارم از تجربه های هم استفاده کنیم و با مشارکت هم بریم جلو.
موفق باشیم!/
دوست عزیز لطف کن و تمام ساختارهایی که به توفق رسیدیم رو جمع آوری کن و قرار بده.
فقط من هنوز روی than مربوط به if مشکل دارم و میخوام تغییر کنه مثلا ':' که قبلا هم گفتم.
Function main() : Integer
End Function
Procedure PrintString(StringAddress : Pointer To String)
End Procedure
Do While a <> b :
Loop
Do For i = 1 To 10 Step 2 :
Loop
Do Until a = b :
Loop
If a <> b :
End If
Public i : Integer
Public j : Unsigned Integer
Private p : Pointer To Integer
Private M(1 To 10) : Integer
text1 : String
test2(1 To 100) : Character
a : Byte
Apple : Fruit
Orange : Fruit
blnVariable : Boolean
Select blnVariable
Case True :
Break 1
Case False :
Break
Case Not True :
Case Else :
End Select
If i = j :
Else If b = True :
Else :
End If
AddressOfVariable1 = &Variable1
ValueOfVariable1 = @AddressOfVariable1
Import Function “DeleteDC” From “GDI32.DLL” As DelDC (ByVal hdc : Long) : Long
blnVariable = (a = b)?
اگه چبزی رو کم گذاشتم یا اشتباه، چک کنید تغییر بدید...![]()
خوب پس برای متغیر ها از Variable استفاده کنیم و برای اشیاء هم از Object.
در مورد تعریف چیزای جدید:
1. تعریف Struct (این کار که مثل آب خوردنه! چون در FASM تعریف Struct به راحتی تعریف متغیر هست)
2. تعریف Type (تعریف انواع داده ی جدید. مثل VB6 با Struct ادغامش کنیم یا ... ؟)
3. تعریف Object از روی Class
در مورد سومی یه ابهاماتی داشتم که برطرف شد.
می تونیم برای مرحله ی اول حداقل تا یه حدودی پیاده سازیش کنیم.
بر اساس اون چه که در مورد C With Classes خوندم، این کارو می تونیم بکنیم:
بیایم از داده های Class یه Struct تعریف کنیم، بعد هر بار که Object ای جدید از اون نوع Class تعریف می شه یه Struct جدید بسازیم برای اون Object جدید،
برای توابع و روال های تمام Object ها یه سری توابع و روال های مشترک در نظر می گیریم که به همشون یه پارامتر ورودی جدید اضافه می کنیم: آدرس Struct ای که Object مورد نظرمون داره.
use "iostream.lib" به کار بردن کتابخانه
Import Function “DeleteDC” From “GDI32.DLL” As DelDC (ByVal hdc : Long) : Long API معرفی
define:
variable e:integer
variable f:sinteger
variable g:binteger
variable h:float تعریف متغیرهای عمومی
variable i:bfloat
variable j:char
variable k:str
end define
Function main() : Integer تابع اصلی
M = x * y
End Function
Function Multiply(x : Integer, y : Integer) : Integer توابع فرعی
Multiply = x * y
End Function
If a <> b :
شرط ساده
End If
If i = j :
If b = True : شرط تودرتو
End If
Else :
End If
لطفآ اگر اشکالی میبینید الان اعلام کنید و نگذارید برای بعد.
آه! نگرانیم بر طرف شد > cs.saddleback.edu/ccarroll/CS3B/Slides3B/Section10.pdf
خوب من با همه جاش موافقم، فقط در مورد define یه مسئله هست:
وقتی برنامه نویس متغیر ها رو در کلاس یا هر جای دیگه ای که تعریف می کنه می خواد که Public یا Private باشن، که مجبوریم این کلمات کلیدی رو قبل از Variable بیاریم، خوب چرا یهو نیایم برای تعریف متغیر های عمومی از همون Public قبل از Variable استفاده کنیم؟
خوب حلقه ها که تعریف شد فکر کنم ...
اما فکر کنم هنوز تکلیف Select Case معلوم نشد.
ببین سادست! متغیرهایی که قراره تو تمام توابع در برنامه استفاده بشن(public) داخل بلاک define قرار میگیره
متغیرهایی که قراره فقط در یک تابع استفاده بشن (private) داخل همون تابع تعریف میشن
متغیرهایی هم که قراره در کتابخانه ها تعریف بشن و در برنامه اصلی استفاده شن به این شکل:
share:
variable i : integer
end share
الان شما با کدهای پست ۱۵۱ مشکل دارید؟
خوب خوبه...![]()
در مورد انواع داده ی اولیّه، این جا رو بررسی کن...![]()