تحليل التعبيرات
أنشئ شجرة تحليل
تحليل التعبيرات درس مجاني في C Academy على CoddyKit. هذا هو الدرس 2 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في C Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة C Academy 4 دروس في المجموع.
من الرموز إلى الشجرة
يحوّل التحليل النحوي تدفق الرموز المسطّح إلى شجرة بناء جملة مجردة (AST) منظّمة. وتشفّر الشجرة الأسبقية والتجميع اللذين لا توحي بهما الرموز الخام إلا ضمنيًا.
بالنسبة إلى 3 + 4 * 2، تضع AST عملية الضرب داخل عملية الجمع، ولذلك تكون النتيجة 11 لا 14.
بنية عقدة AST
كل عقدة إما ورقة تحتوي عددًا أو عملية ثنائية لها ابنان. وتحافظ بنية موسومة مع اتحاد على صغر استهلاك الذاكرة.
ويميز محرف العامل بين + و- و* و/ أثناء التشغيل.
typedef struct Node {
enum { N_NUM, N_BINOP } kind;
union {
int value; /* N_NUM */
struct { /* N_BINOP */
char op;
struct Node *left, *right;
} bin;
};
} Node;تخصيص العقد
تخصص دالتا إنشاء صغيرتان العقدَ في الكومة. ويعني بناء الشجرة من الأسفل إلى الأعلى إنشاء الأوراق أولًا، ثم تغليفها في عقد العوامل.
في مفسّر إنتاجي، ستتتبعون هذه التخصيصات لتحريرها لاحقًا.
#include <stdlib.h>
static Node *num(int v) {
Node *n = malloc(sizeof *n);
n->kind = N_NUM; n->value = v;
return n;
}
static Node *binop(char op, Node *l, Node *r) {
Node *n = malloc(sizeof *n);
n->kind = N_BINOP;
n->bin.op = op; n->bin.left = l; n->bin.right = r;
return n;
}القواعد النحوية
نستخدم قواعد نحوية كلاسيكية تعتمد على أسبقية العمليات. تتعامل expr مع + و-، وتتولى term معالجة * و/، بينما تتعامل factor مع الأعداد والأقواس.
ولأن القواعد ذات الأسبقية الأعلى تقع في مستويات أعمق، فإن الضرب يرتبط تلقائيًا بصرامة أكبر من الجمع.
/* Grammar (EBNF):
expr = term { ('+' | '-') term } ;
term = factor { ('*' | '/') factor } ;
factor = NUMBER | '(' expr ')' ; */مطابقة الرموز
تستهلك الدالة المساعدة expect رمزًا من النوع المطلوب أو توقف التنفيذ. وهي تمثل العقد الذي يربط المحلل المعجمي بالمحلل النحوي.
نعيد استخدام دالتي الاستطلاع cur وbump من درس المحلل المعجمي.
#include <stdio.h>
#include <stdlib.h>
static void expect(TokKind k) {
if (cur().kind != k) {
fprintf(stderr, "parse error: unexpected token\n");
exit(1);
}
bump();
}تحليل العامل
العامل هو العنصر الأساسي في القواعد النحوية: إما عدد حرفي أو تعبير فرعي محاط بالأقواس. وتعود الأقواس إلى parse_expr باستخدام الاستدعاء الذاتي.
وهذا الاستدعاء الذاتي هو سبب تسمية محللات النزول التكراري بهذا الاسم.
static Node *parse_expr(void);
static Node *parse_factor(void) {
if (cur().kind == TOK_NUM) {
int v = cur().value; bump();
return num(v);
}
expect(TOK_LPAREN);
Node *e = parse_expr();
expect(TOK_RPAREN);
return e;
}تحليل الحد
يحلل الحد عاملًا واحدًا، ثم يكرر العملية ما دام يرى * أو /، ويدمج كل عملية منهما في عقدة binop associativity يسارية.
تعني الترابطية اليسارية أن 8 / 4 / 2 تُحلل إلى (8 / 4) / 2 = 1.
static Node *parse_term(void) {
Node *left = parse_factor();
while (cur().kind == TOK_STAR || cur().kind == TOK_SLASH) {
char op = (cur().kind == TOK_STAR) ? '*' : '/';
bump();
left = binop(op, left, parse_factor());
}
return left;
}تحليل التعبير
تحاكي القاعدة العليا parse_term، لكنها تتعامل مع + و-. تستدعي كل طبقة القاعدة ذات الأسبقية الأعلى التالية، ولذلك تُبنى الشجرة بتداخل صحيح.
هذا الهيكل المؤلف من ثلاث دوال هو جوهر المحلل النحوي.
static Node *parse_expr(void) {
Node *left = parse_term();
while (cur().kind == TOK_PLUS || cur().kind == TOK_MINUS) {
char op = (cur().kind == TOK_PLUS) ? '+' : '-';
bump();
left = binop(op, left, parse_term());
}
return left;
}فحص الشجرة
يحلل هذا البرنامج تعبيرًا ثم يطبعه مجددًا بصيغة تحيط كل عناصرها بالأقواس، موضحًا كيفية حسم الأسبقية.
تستدعي أداة الطباعة المنسقة نفسها ذات بنية العقد التي بناها المحلل النحوي.
#include <stdio.h>
typedef struct Node {
int is_num; int value;
char op; struct Node *l, *r;
} Node;
static Node *N(int v){ Node*n=calloc(1,sizeof*n); n->is_num=1; n->value=v; return n; }
static Node *B(char o,Node*a,Node*b){ Node*n=calloc(1,sizeof*n); n->op=o; n->l=a; n->r=b; return n; }
static void show(Node *n){
if (n->is_num){ printf("%d", n->value); return; }
printf("("); show(n->l); printf(" %c ", n->op); show(n->r); printf(")");
}
int main(void){
/* 3 + 4 * 2 -> (3 + (4 * 2)) */
Node *ast = B('+', N(3), B('*', N(4), N(2)));
show(ast); printf("\n");
return 0;
}تجنب الاستدعاء الذاتي اليساري
إن قاعدة ساذجة مثل expr = expr '+' term ستجعل parse_expr تستدعي نفسها إلى ما لا نهاية. فلا يستطيع النزول التكراري التعامل مع الاستدعاء الذاتي اليساري المباشر.
وتتجنب إعادة كتابة القاعدة على شكل حلقة while تمر على { '+' term } هذا الاستدعاء الذاتي اللانهائي بالكامل.
لماذا نستخدم AST؟
تفصل AST بين البنية النحوية والتنفيذ. ويمكن تقييم الشجرة نفسها أو تحسينها أو ترجمتها إلى تعليمات bytecode من دون إعادة تحليلها.
سننتقل بعد ذلك عبر هذه الشجرة لحساب قيمتها.
تحقق سريع
تأمل كيفية فرض طبقات القواعد النحوية لأسبقية العمليات.
مراجعة
لقد كتبتم محللًا نحويًا بالنزول التكراري: هياكل عقد AST، ومنشئات، ودوال expr/term/factor التي ترمز إلى الأسبقية والترابطية اليسارية.
والشجرة الناتجة جاهزة للتقييم.
تعلم C مع معلم ذكاء اصطناعي — مجانًا
اكتب وقم بتشغيل أكوادك الفعلية في المتصفح، واحصل على مساعدة فورية من معلم ذكاء اصطناعي متاح 24/7، واستمر من حيث توقفت على الويب أو في التطبيق.
- الدورات
- 39
- الدروس
- 144
الأسئلة الشائعة
هل درس «تحليل التعبيرات» مجاني؟
نعم — نص درس «تحليل التعبيرات» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة C Academy، انتقل إلى CoddyKit PRO. تتضمن دورة C Academy 4 دروس في المجموع.
ماذا ستتعلم في «تحليل التعبيرات»؟
أنشئ شجرة تحليل تتمرن على C Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ C Academy؟
لا تُشترط خبرة سابقة. C Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 2 من أصل 4.
كم من الوقت يستغرق درس «تحليل التعبيرات»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس C Academy هذا؟
نعم. كل درس في C Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- تحويل الإدخال إلى رموز
- تحليل التعبيرات
- تقييم الشجرة
- إضافة المتغيرات