در علوم کامپیوتر، **تجزیه‌کنندهٔ بازگشتی دنباله** یک اشتقاق از تجزیه‌کنندههای شایع‌تر بازگشتی تنزلی است. تجزیه‌کننده‌های بازگشتی دنباله بیشتر برای تجزیه کردن دستور زبان‌های چپ‌گرد استفاده می‌شوند. آن‌ها نسبت به تجزیه‌کننده‌های بازگشتی تنزلی از فضای پشته‌ای کمتری استفاده می‌کنند. پیاده‌سازی آن‌ها نیز ساده است. تجزیه‌کننده‌های بازگشتی تنزلی نمی‌توانند دستور زبان‌های چپ‌گرد را تجزیه کنند (چون در حلقهٔ بی‌نهایت گیر می‌کنند). تجزیه‌کننده‌های بازگشتی دنباله به وسیله روش بازپدری(reparenting) این کار را میسر کرده‌اند.

مثال
----

یک دستور زبان EBNF مانند زیر را در اختیار داریم:

```
 E: T
 T: T { '+' F } | F
 F: F { '\*' I } | I
 I: <identifier>

```
یک تجزیه‌کنندهٔ بازگشتی دنباله ساده می‌تواند بسیار شبیه به یک تجزیه‌کنندهٔ بازگشتی تنزلی نوشته شود. الگوریتم معمول برای تجزیهٔ یک دستور زبان مانند دستور زبان بالا با استفاده از یک درخت نحو انتزاعی(AST) بدین شکل است:

1. سطح بعدی دستور زبان را تجزیه کن و درخت خروجی‌اش را به دست آور، به عنوان اولین درخت F تعیینش کن.
2. زمانی که یک برچسب پایانی T وجود دارد، می‌تواند به عنوان گره پدر این گره گذاشته شود:
	1. یک گره جدید اختصاص بده به نام N
	2. عملگر کنونی N را به عنوان برچسب ورودی کنونی قرار بده.
	3. ورودی را به اندازه یک برچسب جلو ببر.
	4. درخت‌چه سمت چپ N را F قرار بده.
	5. سطح بعدی دستور زبان را تجزیه کن و به عنوان درخت بعدی X ذخیره‌اش کن.
	6. درخت‌چه سمت چپ N را X قرار بده.
	7. بعد F را برابر N قرار بده.
3. و N را به عنوان خروجی برگردان.

در زیر می‌توان یک برنامه پیاده‌سازی شده این تجزیه‌کننده را در زبان برنامه‌نویسی سی دید:

```
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>

enum node\_type
{
 NODE\_NUMBER,
 NODE\_OPERATOR,
 NODE\_IDENTIFIER,
 NODE\_MUL,
 NODE\_ADD
};

typedef struct \_exptree exptree;
 struct \_exptree {
 int val;
 char\* token;
 int line\_number;
 exptree \*left;
 exptree \*right;
 };

struct \_lexval {
 int ival;
 char \*sval;
 int line;
 enum node\_type typ;
} lexval;

int line\_number = 0;
FILE \*fs,\*fd;

exptree \*parse\_e(void);
exptree \*parse\_t(void);
exptree \*parse\_f(void);
exptree \*parse\_i(void);

void next\_token(){
while (1){
int t;
char \*buff;

t = fgetc(fs);
//printf("after getchar = %d\n",t);
if (t == ' ' || t == '\t' || t=='\n'){
 //printf("white space\n"); /\* ignore whitespace \*/
}
else if (t == '\n')
{
 line\_number++;
 //printf("line = %i\n",line\_number);
 return;
}
else if(t == EOF){
return;
}
else if(isdigit(t))
{
 //ungetc (t, stdin);
 fseek(fs,ftell(fs)-1,SEEK\_SET);
 fscanf (fs,"%d", &lexval.ival);
 //printf("in lexer ival = %d\n",lexval.ival);
 lexval.sval = "";
 lexval.line = line\_number;
 lexval.typ = NODE\_NUMBER;
 return;
} else if (t == '\*'){
//printf("lexer mul\n");
//ungetc (t, stdin);
//scanf ("%s", buff);
lexval.sval = "\*";

//printf("in lexer ival = %s\n",lexval.sval);
lexval.line = line\_number;
lexval.typ = NODE\_MUL;
return;
} else if (t == '+'){
//printf("lexer add\n");
//ungetc (t, stdin);
//scanf ("%s0", buff);
lexval.sval = "+";
//printf("in lexer ival = %s\n",lexval.sval);
lexval.line = line\_number;
lexval.typ = NODE\_ADD;
return;
}
}
}

exptree\* alloc\_tree(){
return (exptree \*) malloc(sizeof(exptree));
}

exptree \*parse\_e(void)
 {
 //printf("in e ival = %d\n",lexval.ival);
 return parse\_t();
 }

 exptree \*parse\_t(void)
 {
//printf("in t\n");
//printf("in t ival = %d\n",lexval.ival);
 exptree \*first\_f = parse\_f();

 while(lexval.typ == NODE\_ADD) {
 //printf("in t loop\n");
 exptree \*replace\_tree = alloc\_tree();
 replace\_tree->token = lexval.sval;
 replace\_tree->left = first\_f;
 //printf("in t loop begin next\_token\n");
 next\_token();
 //printf("parse\_t = %c\n",replace\_tree->token);
 replace\_tree->right = parse\_f();
 replace\_tree->val = replace\_tree->left->val + replace\_tree->right->val;
 printf("hasil t = %d\n",replace\_tree->val);
 first\_f = replace\_tree;
 }

 return first\_f;
 }

 exptree \*parse\_f(void)
 {
 //printf("in f\n");
 //printf("in f ival = %d\n",lexval.ival);
 exptree \*first\_i = parse\_i();
 //printf("before f loop\n");
 while(lexval.typ == NODE\_MUL) {
 //printf("in f loop\n");
 exptree \*replace\_tree = alloc\_tree();
 replace\_tree->token = lexval.sval;
 replace\_tree->left = first\_i;
 //printf("in f loop begin next\_token\n");
 next\_token();
 //printf("parse\_f = %c\n",replace\_tree->token);
 replace\_tree->right = parse\_i();

 replace\_tree->val = replace\_tree->left->val \* replace\_tree->right->val;
 printf("hasil f = %d\n",replace\_tree->val);
 first\_i = replace\_tree;

 }
 //printf("about to exit from f\n");
 return first\_i;
 }

exptree \*parse\_i(void)
{
 //printf("in i\n");
 exptree \*i = alloc\_tree();
 i->left = i->right = NULL;
 i->val = lexval.ival;
 //printf("in i ival = %d\n",lexval.ival);
 //printf("in i = %d\n",i->val);
 next\_token();
 //printf("parse\_i = %c\n",i->token);
 return i;
 }

int main( int argc, char\*\* argv){

if(argc != 2) return 1;

fs = fopen(argv[1], "r");
if (fs == NULL) {
perror("Failed to open file ");
}

//char \* = strcat(
fd = fopen (strcat(argv[1],".c"),"w");
if (fd == NULL) {
perror("Failed to open file ");
}
char \*template = "#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <ctype.h>\n#include <sys/types.h>\nvoid main(){\n";

fputs(template,fd);

char \*buffer = malloc(35);
 next\_token();

exptree \*temp = parse\_e();
printf("hasil akhir = %d\n",temp->val);
snprintf(buffer, 30, "printf(\"hasil = %d\\n\");\n", temp->val);
fputs(buffer,fd);
fputs("}",fd);

fclose(fs);
fclose(fd);

char \*substr = strdup(argv[1]);
char \* pch;
pch = strstr(substr,".lol");
strncpy(pch,"\0",1);

snprintf(buffer, 30, "gcc -o %s %s", substr,argv[1]);

system(buffer);

return 0;
 }

```

جستارهای وابسته
---------------

* متا دوم

برای مطالعهٔ بیشتر
------------------

* مقاله در ژانویه 2006 edition دکتر دابز مجله "بازگشتی نزول دم بازگشت و مخوف دو تقسیم"

منابع
-----

1. ↑  «نسخه آرشیو شده». بایگانی‌شده از اصلی در ۸ دسامبر ۲۰۱۷. دریافت‌شده در ۷ دسامبر ۲۰۱۷.

| * ن
* ب
* و
الگوریتم‌های تجزیه‌کننده |
| --- |
| تحلیلگر بالا به پایین | 
* تجزیه‌کننده ال‌ال
* تجزیه‌کننده کاهشی بازگشتی
	+ تجزیه‌کننده بازگشتی دنباله
	+ Pratt parser

 |
| تجزیه از پایین به بالا | 
* Precedence
	+ تجزیه اولویت ساده
	+ تجزیه‌کننده عملگر اولویت
		- Shunting-yard
* Bounded-context
* تجزیه‌کننده ال‌آر
	+ تجزیه‌کننده ال‌آر ساده
	+ تجزیه‌کننده ال‌ای‌ال‌آر
	+ تجزیه‌کننده ال‌آر استاندارد
	+ تجزیه‌کننده جی‌ال‌آر
* الگوریتم سی وای کا
* Recursive ascent
* پارسر انتقال کاهش

 |
| Mixed, other | 
* ترکیب کننده تجزیه‌گر
* Chart
* تجزیه ایرلی

 |
| Related topics | 
* پارسنگ اکسپرشن گرامر
* گرامرهای عبارت قطعی
* برنامه‌نویسی پویا
* مموایز کردن
* کامپایلر-کامپایلر
	+ LALR
* کامپایلر-کامپایلر
* نمودار درختی تجزیه
* درخت نحو انتزاعی
* Scannerless parsing
* تاریخچه ساخت مترجم
* Comparison of parser generators

 |