.\" Man page generated from reStructuredText. . . .nr rst2man-indent-level 0 . .de1 rstReportMargin \\$1 \\n[an-margin] level \\n[rst2man-indent-level] level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] - \\n[rst2man-indent0] \\n[rst2man-indent1] \\n[rst2man-indent2] .. .de1 INDENT .\" .rstReportMargin pre: . RS \\$1 . nr rst2man-indent\\n[rst2man-indent-level] \\n[an-margin] . nr rst2man-indent-level +1 .\" .rstReportMargin post: .. .de UNINDENT . RE .\" indent \\n[an-margin] .\" old: \\n[rst2man-indent\\n[rst2man-indent-level]] .nr rst2man-indent-level -1 .\" new: \\n[rst2man-indent\\n[rst2man-indent-level]] .in \\n[rst2man-indent\\n[rst2man-indent-level]]u .. .TH "RE2C" 1 "" "" "" .SH "نام (NAME)" re2c \- تولید تحلیل‌گرهای لغوی سریع برای C/C++ .SH "خلاصه دستور (SYNOPSIS)" .sp نکته: برخی از مثال‌ها به زبان C++ هستند (اما می‌توان آن‌ها را با C تطبیق داد). .sp re2c \fB[ OPTIONS ]\fP \fB[ WARNINGS ]\fP \fBINPUT\fP .sp ورودی می‌تواند یک فایل یا \fB\-\fP برای stdin باشد. .SH "مقدمه (INTRODUCTION)" .sp ابزار re2c به عنوان یک پیش‌پردازنده عمل می‌کند. این ابزار فایل ورودی (که معمولاً برنامه‌ای به زبان C/C++ است، اما می‌تواند هر چیز دیگری باشد) را می‌خواند و به دنبال بلوک‌هایی از کد می‌گردد که در نشانگرهای آغاز/پایان با قالب خاص محصور شده‌اند. متنِ خارج از این بلوک‌ها عیناً به فایل خروجی کپی می‌شود. محتویات این بلوک‌ها توسط re2c\& پردازش می‌شوند؛ ابزار آن‌ها را به کدهای C/C++ ترجمه کرده و کد تولیدشده را در خروجی به جای بلوک مربوطه قرار می‌دهد. .sp در ادامه مثالی از یک برنامه کوچک آورده شده است که بررسی می‌کند آیا یک رشته داده‌شده حاوی یک عدد ده‌دهی است یا خیر: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C // re2c $INPUT \-o $OUTPUT \-i \-\-case\-ranges #include int lex(const char* YYCURSOR) { /*!re2c re2c:yyfill:enable = 0; re2c:define:YYCTYPE = \(dqunsigned char\(dq; [1\-9][0\-9]* { return 0; } * { return 1; } */ } int main() { assert(lex(\(dq1234\(dq) == 0); return 0; } .ft P .fi .UNINDENT .UNINDENT .sp در خروجی، re2c بلوک میانی را با کد تولیدشده جایگزین کرده است: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C /* Generated by re2c */ // re2c $INPUT \-o $OUTPUT \-i \-\-case\-ranges #include int lex(const char* YYCURSOR) { { unsigned char yych; yych = *YYCURSOR; switch (yych) { case \(aq1\(aq ... \(aq9\(aq: goto yy2; default: goto yy1; } yy1: ++YYCURSOR; { return 1; } yy2: yych = *++YYCURSOR; switch (yych) { case \(aq0\(aq ... \(aq9\(aq: goto yy2; default: goto yy3; } yy3: { return 0; } } } int main() { assert(lex(\(dq1234\(dq) == 0); return 0; } .ft P .fi .UNINDENT .UNINDENT.SH "مبانی (BASICS)" .sp یک برنامه re2c از دنباله‌ای از \fIبلوک‌ها\fP ترکیب‌شده با کد به زبان مقصد تشکیل شده است. یک بلوک می‌تواند شامل \fIتعاریف\fP، \fIپیکربندی‌ها\fP، \fIقواعد\fP، \fIکنش‌ها\fP و \fIدستورالعمل‌ها\fP با هر ترتیبی باشد: .INDENT 0.0 .TP .B \fBname = regular\-expression ;\fP یک \fIتعریف\fP، \fBname\fP را به \fBregular\-expression\fP مقید می‌کند\&. نام‌ها می‌توانند شامل نویسه‌های الفبایی‌عددی و خط زیر باشند. بخش \fI\%عبارات باقاعده\fP نمای کلی نحو re2c برای عبارات باقاعده را ارائه می‌دهد. پس از تعریف، \fBname\fP می‌تواند در سایر عبارات باقاعده و در قواعد استفاده شود. بازگشت در تعاریف نام‌گذاری‌شده مجاز نیست، و هر نام باید پیش از استفاده تعریف شود. یک بلوک تعاریف نام‌گذاری‌شده را از دامنه سراسری به ارث می‌برد. تعریف مجدد نامی که در دامنه فعلی وجود دارد خطا است. .TP .B \fBconfiguration = value ;\fP یک \fIپیکربندی\fP امکان تغییر رفتار re2c و سفارشی‌سازی کد تولید‌شده را فراهم می‌کند. برای مشاهده فهرست کامل پیکربندی‌های پشتیبانی‌شده توسط re2c، بخش \fI\%پیکربندی‌ها\fP را ببینید. بسته به پیکربندی مشخص، \fBvalue\fP می‌تواند یک کلیدواژه، یک عدد صحیح غیرمنفی یا یک رشته تک‌خطی باشد که باید در میان گیومه تکی یا دوتایی قرار گیرد، مگر اینکه فقط شامل نویسه‌های الفبایی‌عددی باشد. یک بلوک پیکربندی‌ها را از دامنه سراسری به ارث می‌برد و می‌تواند آن‌ها را مجدداً تعریف کرده یا موارد جدیدی اضافه کند. پیکربندی‌های تعریف‌شده درون یک بلوک بر کل بلوک تأثیر می‌گذارند، حتی اگر در انتهای آن قرار گرفته باشند. .TP .B \fBregular\-expression code\fP یک \fIقاعده\fP، \fBregular\-expression\fP را به کنش معنایی آن مقید می‌کند (بلوکی از کد درون آکوالادها، یا بلوکی از کد که با \fB:=\fP شروع شده و به یک خط جدید به همراه هر نویسه غیر فاصله ختم می‌شود). اگر \fBregular\-expression\fP مطابقت داشته باشد، \fBcode\fP مرتبط اجرا می‌شود. اگر چندین قاعده مطابقت داشته باشند، طولانی‌ترین تطابق اولویت دارد. اگر چندین قاعده با رشته یکسانی مطابقت داشته باشند، قاعده‌ای که زودتر آمده اولویت دارد. دو قاعده ویژه وجود دارد: قاعده پیش‌فرض \fB*\fP و قاعده پایان ورودی \fB$\fP\&. قاعده پیش‌فرض باید همیشه تعریف شود، صرف‌نظر از جایگاهش در بلوک دارای پایین‌ترین اولویت است، و با هر واحد کد مطابقت می‌یابد (نه لزوماً یک نویسه معتبر، به بخش \fI\%پشتیبانی از کدگذاری\fP مراجعه کنید). قاعده پایان ورودی در صورتی باید تعریف شود که روش متناظر برای \fI\%مدیریت پایان ورودی\fP به کار گرفته شده باشد. به همراه \fI\%شرایط شروع\fP، قواعد نحو پیچیده‌تری دارند. .TP .B \fB!action code\fP یک \fIکنش\fP یک بلوک \fBcode\fP تعریف‌شده توسط کاربر را به نقطه مشخصی در ماشین وضعیت متناهی تولیدشده متصل می‌کند (به همان شیوه‌ای که کنش‌های معنایی کد را به وضعیت‌های پایانی مقید می‌کنند). برای فهرست کاملی از کنش‌های از پیش تعریف‌شده، بخش \fI\%کنش‌ها\fP را ببینید. .TP .B \fB!directive ;\fP یک \fIدستورالعمل\fP یکی از گزاره‌های ویژه از پیش تعریف‌شده است. هر دستورالعمل هدف منحصربه‌فردی دارد. برای جزئیات به بخش \fI\%دستورالعمل‌ها\fP مراجعه کنید. .UNINDENT .SS "بلوک‌ها (Blocks)" .sp نشانگرهای آغاز و پایان بلوک یا \fB/*!re2c\fP و \fB*/\fP هستند، یا \fB%{\fP و \fB%}\fP (از هر دو سبک پشتیبانی می‌شود). از نسخه 2.2 به بعد، بلوک‌ها می‌توانند نام‌های اختیاری داشته باشند که امکان ارجاع به آن‌ها را در سایر بلوک‌ها فراهم می‌کند. انواع مختلفی از بلوک‌ها وجود دارد: .INDENT 0.0 .TP .B \fB/*!re2c[:] ... */\fP یا \fB%{[:] ... %}\fP یک \fIبلوک سراسری\fP شامل تعاریف، پیکربندی‌ها، قواعد و دستورالعمل‌ها است. re2c عبارات باقاعده مرتبط با هر قاعده را به یک اتوماتون متناهی معین کامپایل می‌کند، آن را در قالب پرش‌های شرطی در زبان مقصد کدگذاری کرده و بلوک را با کد تولیدشده جایگزین می‌نماید. نام‌ها و پیکربندی‌های تعریف‌شده در یک بلوک سراسری به دامنه سراسری اضافه شده و برای بلوک‌های بعدی قابل مشاهده می‌شوند. در آغاز برنامه، دامنه سراسری با \fI\%گزینه‌های\fP خط فرمان مقداردهی اولیه می‌شود\&. .TP .B \fB/*!local:re2c[:] ... */\fP یا \fB%{local[:] ... %}\fP یک \fIبلوک محلی\fP مانند یک بلوک سراسری است، اما نام‌ها و پیکربندی‌های موجود در آن دارای دامنه محلی هستند (بر سایر بلوک‌ها تأثیری نمی‌گذارند). .TP .B \fB/*!rules:re2c[:] ... */\fP یا \fB%{rules[:] ... %}\fP یک \fIبلوک قواعد\fP مانند یک بلوک محلی است، اما خودش به تنهایی هیچ کدی تولید نمی‌کند و هیچ تعریفی را هم به دامنه سراسری اضافه نمی‌کند \-\- هدف آن، استفاده مجدد در سایر بلوک‌ها است. این روشی برای به اشتراک‌گذاری کد است (جزئیات بیشتر در بخش \fI\%بلوک‌های قابل استفاده مجدد\fP). پیش از نسخه 2.2 re2c، بلوک‌های قواعد به گزینه \fB\-r \-\-reusable\fP نیاز داشتند. .TP .B \fB/*!use:re2c[:] ... */\fP یا \fB%{use[:] ... %}\fP یک بلوک استفاده که به یک بلوک قواعد از پیش تعریف‌شده ارجاع می‌دهد. اگر نام مشخص شده باشد، re2c به دنبال بلوک قواعدی با این نام می‌گردد. در غیر این صورت، جدیدترین بلوک قواعد استفاده می‌شود (خواه نام‌گذاری‌شده باشد یا بدون نام). یک بلوک استفاده می‌تواند تعاریف، پیکربندی‌ها و قواعد خاص خود را اضافه کند، که به موارد موجود در بلوک قواعد مرجع افزوده می‌شوند. پیش از نسخه 2.2 re2c، بلوک‌های استفاده به گزینه \fB\-r \-\-reusable\fP نیاز داشتند. .TP .B \fB/*!max:re2c[:[:...]] ... */\fP یا \fB%{max[:[:...]] ... %}\fP بلوکی که تعریف \fBYYMAXFILL\fP را تولید می‌کند. یک فهرست اختیاری از نام‌های بلوک مشخص می‌کند هنگام محاسبه مقدار \fBYYMAXFILL\fP کدام بلوک‌ها باید لحاظ شوند (اگر فهرست خالی باشد، همه بلوک‌ها لحاظ می‌شوند). به طور پیش‌فرض، کد تولیدشده یک تعریف ماکرو برای C (\fB#define YYMAXFILL \fP) یا یک متغیر سراسری برای Go (\fBvar YYMAXFILL int = \fP) است. این مقدار را می‌توان با پیکربندی اختیاری \fBformat\fP سفارشی کرد که یک رشته الگو را مشخص می‌کند که در آن \fB@@{max}\fP (یا به اختصار \fB@@\fP) با مقدار عددی \fBYYMAXFILL\fP جایگزین می‌شود\&. .TP .B \fB/*!maxnmatch:re2c[:[:...]] ... */\fP یا \fB%{maxnmatch[:[:...]] ... %}\fP بلوکی که تعریف \fBYYMAXNMATCH\fP را تولید می‌کند (به گزینه \fB\-P \-\-posix\-captures\fP نیاز دارد). یک فهرست اختیاری از نام‌های بلوک مشخص می‌کند هنگام محاسبه مقدار \fBYYMAXNMATCH\fP کدام بلوک‌ها باید لحاظ شوند (اگر فهرست خالی باشد، همه بلوک‌ها لحاظ می‌شوند). به طور پیش‌فرض، کد تولیدشده یک تعریف ماکرو برای C (\fB#define YYMAXNMATCH \fP) یا یک متغیر سراسری برای Go (\fBvar YYMAXNMATCH int = \fP) است. این مقدار را می‌توان با پیکربندی اختیاری \fBformat\fP سفارشی کرد که یک رشته الگو را مشخص می‌کند که در آن \fB@@{max}\fP (یا به اختصار \fB@@\fP) با مقدار عددی \fBYYMAXNMATCH\fP جایگزین می‌شود\&. .TP .B \fB/*!stags:re2c[:[:...]] ... */\fP, \fB/*!mtags:re2c[:[:...]] ... */\fP یا \fB%{stags[:[:...]] ... %}\fP, \fB%{mtags[:[:...]] ... %{\fP بلوک‌هایی که قطعه‌کدی الگویی را مشخص می‌کنند که به ازای هر متغیر s\-tag/m\-tag تولیدشده توسط re2c بسط می‌یابد\&. یک فهرست اختیاری از نام‌های بلوک مشخص می‌کند هنگام محاسبه مجموعه متغیرهای تگ کدام بلوک‌ها باید لحاظ شوند (اگر فهرست خالی باشد، همه بلوک‌ها لحاظ می‌شوند). دو پیکربندی اختیاری وجود دارد: \fBformat\fP و \fBseparator\fP\&. پیکربندی \fBformat\fP یک رشته الگو را تعیین می‌کند که در آن \fB@@{tag}\fP (یا به اختصار \fB@@\fP) با نام هر متغیر تگ جایگزین می‌شود. پیکربندی \fBseparator\fP قطعه‌کدی را مشخص می‌کند که برای پیوند دادن قطعات تولیدشده \fBformat\fP برای متغیرهای مختلف تگ استفاده می‌شود. .TP .B \fB/*!svars:re2c[:[:...]] ... */\fP, \fB/*!mvars:re2c[:[:...]] ... */\fP یا \fB%{svars[:[:...]] ... %}\fP, \fB%{mvars[:[:...]] ... %{\fP بلوک‌هایی که قطعه‌کدی الگویی را مشخص می‌کنند که به ازای هر s\-tag/m\-tag که یا به صراحت در قواعد ذکر شده است (با گزینه \fB\-\-tags\fP) یا به طور ضمنی توسط re2c تولید شده است (با گزینه‌های \fB\-\-captvars\fP یا \fB\-\-posix\-captvars\fP) بسط می‌یابد. یک فهرست اختیاری از نام‌های بلوک مشخص می‌کند هنگام محاسبه مجموعه تگ‌ها کدام بلوک‌ها باید لحاظ شوند (اگر فهرست خالی باشد، همه بلوک‌ها لحاظ می‌شوند). دو پیکربندی اختیاری وجود دارد: \fBformat\fP و \fBseparator\fP\&. پیکربندی \fBformat\fP یک رشته الگو را تعیین می‌کند که در آن \fB@@{tag}\fP (یا به اختصار \fB@@\fP) با نام هر تگ جایگزین می‌شود. پیکربندی \fBseparator\fP قطعه‌کدی را مشخص می‌کند که برای پیوند دادن قطعات تولیدشده \fBformat\fP برای تگ‌های مختلف استفاده می‌شود. .TP .B \fB/*!getstate:re2c[:[:...]] ... */\fP یا \fB%{getstate[:[:...]] ... %}\fP بلوکی که هدایت شرطی بر اساس وضعیت تحلیل‌گر لغوی را تولید می‌کند (به گزینه \fB\-\-storable\-state\fP نیاز دارد). یک فهرست اختیاری از نام‌های بلوک مشخص می‌کند کدام بلوک‌ها باید در هدایت وضعیت گنجانده شوند. گذار پیش‌فرض به برچسب شروع اولین بلوک در فهرست می‌رود. اگر فهرست خالی باشد، همه بلوک‌ها گنجانده می‌شوند، و گذار پیش‌فرض به اولین بلوکی در فایل که برچسب شروع دارد می‌رود. این نوع بلوک با گزینه \fB\-\-loop\-switch\fP ناسازگار است، زیرا به گذارهای بین‌بلوکی نیاز دارد که بدون \fBgoto\fP یا فراخوانی‌های تابع پشتیبانی نمی‌شوند. .TP .B \fB/*!conditions:re2c[:[:...]] ... */\fP, \fB/*!types:re2c... */\fP یا \fB%{conditions[:[:...]] ... %}\fP, \fB%{types... %}\fP بلوکی که شمارش شرط‌ها را تولید می‌کند (به گزینه \fB\-\-conditions\fP نیاز دارد). یک فهرست اختیاری از نام‌های بلوک مشخص می‌کند هنگام محاسبه مجموعه شرایط کدام بلوک‌ها باید لحاظ شوند (اگر فهرست خالی باشد، همه بلوک‌ها لحاظ می‌شوند). به طور پیش‌فرض کد تولیدشده یک شمارش \fBYYCONDTYPE\fP است\&. این کد را می‌توان با پیکربندی‌های اختیاری \fBformat\fP و \fBseparator\fP سفارشی کرد. پیکربندی \fBformat\fP یک رشته الگو را مشخص می‌کند که در آن \fB@@{cond}\fP (یا به اختصار \fB@@\fP) با نام هر شرط، و \fB@@{num}\fP با اندیس عددی آن شرط جایگزین می‌شود. پیکربندی \fBseparator\fP قطعه‌کدی را مشخص می‌کند که برای پیوند دادن قطعات تولیدشده \fBformat\fP برای شرایط مختلف استفاده می‌شود. .TP .B \fB/*!include:re2c */\fP یا \fB%{include %}\fP این بلوک امکان گنجاندن \fB\fP را فراهم می‌کند، که باید یک مسیر فایل درون گیومه دوتایی باشد. محتویات فایل به معنای واقعی کلمه در جای بلوک جایگزین می‌شود، دقیقاً به همان روشی که \fB#include\fP در C/C++ کار می‌کند. این بلوک می‌تواند همراه با گزینه \fB\-\-depfile\fP برای تولید وابستگی‌های سیستم ساخت بر روی فایل‌های گنجانده‌شده استفاده شود. .TP .B \fB/*!header:re2c:on*/\fP یا \fB%{header:on %}\fP این بلوک آغاز فایل سرآیند را مشخص می‌کند. تمام موارد پس از آن و تا بلوک \fBheader:off\fP بعدی توسط re2c پردازش شده و در فایل سرآیندی که با گزینه \fB\-t \-\-type\-header\fP مشخص شده نوشته می‌شود. .TP .B \fB/*!header:re2c:off*/\fP یا \fB%{header:off %}\fP این بلوک پایان فایل سرآیندی را که با بلوک \fBheader:on*/\fP آغاز شده بود مشخص می‌کند. .TP .B \fB/*!ignore:re2c ... */\fP یا \fB%{ignore ... %}\fP بلوکی که محتویات آن نادیده گرفته شده و از فایل خروجی حذف می‌شود. .UNINDENT.SS "پیکربندی‌ها (Configurations)" .sp در اینجا فهرست کاملی از پیکربندی‌های پشتیبانی‌شده توسط re2c آورده شده است: .INDENT 0.0 .TP .B \fBre2c:api\fP, \fBre2c:input\fP مشابه گزینه \fB\-\-api\fP. .TP .B \fBre2c:api:sigil\fP علامت‌گذار (\(dqنشانگر\(dq یا \(dqsigil\(dq) را مشخص می‌کند که برای جانگهدارنده‌های آرگومان در ساختارهای اولیه API استفاده می‌شود. مقدار پیش‌فرض \fB@@\fP است. یک جانگهدارنده با sigil آغاز شده و در ادامه نام آرگومان در آکولادها می‌آید. به عنوان مثال، اگر sigil روی \fB$\fP تنظیم شود، جانگهدارنده‌ها به فرم \fB${name}\fP خواهند بود. APIهای تک‌آرگومانی می‌توانند از نمادگذاری مختصر بدون نام در آکولاد استفاده کنند. این گزینه را می‌توان با گزینه‌های مربوط به ساختارهای اولیه جداگانه API بازنویسی کرد، مانند \fBre2c:YYFILL@len\fP برای \fBYYFILL\fP\&. .TP .B \fBre2c:api:style\fP سبک API را مشخص می‌کند. مقادیر ممکن عبارتند از \fBfunctions\fP (پیش‌فرض برای C) و \fBfree\-form\fP (پیش‌فرض برای Go و Rust). در سبک \fBfunctions\fP، ساختارهای اولیه API همراه با فهرستی از آرگومان‌ها درون پرانتز که پس از نام ساختار اولیه می‌آید تولید می‌شوند. آرگومان‌ها تنها برای پارامترهای خودکار تولیدشده فراهم می‌شوند (مانند تعداد نویسه‌های ارسال‌شده به \fBYYFILL\fP)، نه برای زمینه عمومی تحلیل‌گر واژگانی؛ بنابراین این ساختارهای اولیه بیشتر رفتاری شبیه به ماکروها در C/C++ یا بستارها (closures) در Go و Rust دارند. در سبک free\-form ساختارهای اولیه API فرم ثابتی ندارند: آنها باید به صورت رشته‌هایی شامل قطعه کدهای آزاد به همراه متغیرهای درون‌یابی‌شده با فرمت \fB@@{var}\fP یا \fB@@\fP تعریف شوند (که با آرگومان‌ها در سبک تابع‌گونه مطابقت دارند). این پیکربندی ممکن است برای ساختارهای اولیه جداگانه API بازنویسی شود؛ برای نمونه، پیکربندی \fBre2c:YYFILL:naked\fP را برای \fBYYFILL\fP ببینید. .TP .B \fBre2c:bit\-vectors\fP, \fBre2c:flags:bit\-vectors\fP, \fBre2c:flags:b\fP مشابه گزینه \fB\-\-bit\-vectors\fP، اما به تفکیک هر بلوک قابل پیکربندی است. .TP .B \fBre2c:captures\fP, \fBre2c:leftmost\-captures\fP مشابه گزینه \fB\-\-leftmost\-captures\fP، اما به تفکیک هر بلوک قابل پیکربندی است. .TP .B \fBre2c:captvars\fP, \fBre2c:leftmost\-captvars\fP مشابه گزینه \fB\-\-leftmost\-captvars\fP، اما به تفکیک هر بلوک قابل پیکربندی است. .TP .B \fBre2c:case\-insensitive\fP, \fBre2c:flags:case\-insensitive\fP مشابه گزینه \fB\-\-case\-insensitive\fP، اما به تفکیک هر بلوک قابل پیکربندی است. .TP .B \fBre2c:case\-inverted\fP, \fBre2c:flags:case\-inverted\fP مشابه گزینه \fB\-\-case\-inverted\fP، اما به تفکیک هر بلوک قابل پیکربندی است. .TP .B \fBre2c:case\-ranges\fP, \fBre2c:flags:case\-ranges\fP مشابه گزینه \fB\-\-case\-ranges\fP، اما به تفکیک هر بلوک قابل پیکربندی است. .TP .B \fBre2c:computed\-gotos\fP, \fBre2c:flags:computed\-gotos\fP, \fBre2c:flags:g\fP مشابه گزینه \fB\-\-computed\-gotos\fP، اما به تفکیک هر بلوک قابل پیکربندی است. .TP .B \fBre2c:computed\-gotos:relative\fP, \fBre2c:cgoto:relative\fP مشابه گزینه \fB\-\-computed\-gotos\-relative\fP، اما به تفکیک هر بلوک قابل پیکربندی است. .TP .B \fBre2c:computed\-gotos:threshold\fP, \fBre2c:cgoto:threshold\fP در صورت استفاده از \fBgoto\fPی محاسبه‌شده، این پیکربندی آستانه پیچیدگی‌ای را مشخص می‌کند که باعث تولید جدول‌های پرش به‌جای دستورهای \fBif\fP تو در تو و نقشه‌های بیتی (bitmaps) می‌شود. مقدار پیش‌فرض \fB9\fP است. .TP .B \fBre2c:cond:abort\fP اگر روی یک مقدار عددی صحیح مثبت تنظیم شود، حالت پیش‌فرض (default case) در توزیع شرطیِ تولیدشده، اجرای برنامه را متوقف می‌کند. .TP .B \fBre2c:cond:goto\fP قطعه کدی را مشخص می‌کند که برای قواعد میانبر خودکار تولیدشده \fB:=>\fP در شرایط استفاده می‌شود. مقدار پیش‌فرض \fBgoto @@;\fP است. جانگهدارنده \fB@@\fP با نام شرط جایگزین می‌شود (پیکربندی‌های \fBre2c:api:sigil\fP و \fBre2c:cond:goto@cond\fP را ببینید). .TP .B \fBre2c:cond:goto@cond\fP نشانگر (sigil) مورد استفاده برای جایگزینی آرگومان در تعریف \fBre2c:cond:goto\fP را مشخص می‌کند. مقدار پیش‌فرض \fB@@\fP است. پیکربندی عمومی‌تر \fBre2c:api:sigil\fP را بازنویسی می‌کند. .TP .B \fBre2c:cond:divider\fP جداکننده بلوک‌های شرط را تعریف می‌کند. مقدار پیش‌فرض \fB/* *********************************** */\fP است. جانگهدارنده‌ها با نام شرط جایگزین می‌شوند (نگاه کنید به \fBre2c:api;sigil\fP و \fBre2c:cond:divider@cond\fP). .TP .B \fBre2c:cond:divider@cond\fP نشانگر (sigil) مورد استفاده برای جایگزینی آرگومان در تعریف \fBre2c:cond:divider\fP را مشخص می‌کند. مقدار پیش‌فرض \fB@@\fP است. پیکربندی عمومی‌تر \fBre2c:api:sigil\fP را بازنویسی می‌کند. .TP .B \fBre2c:cond:prefix\fP, \fBre2c:condprefix\fP پیشوند مورد استفاده برای برچسب‌های شرط را مشخص می‌کند. مقدار پیش‌فرض \fByyc_\fP است. .TP .B \fBre2c:cond:enumprefix\fP, \fBre2c:condenumprefix\fP پیشوند مورد استفاده برای شناسه‌های شرط را مشخص می‌کند. مقدار پیش‌فرض \fByyc\fP است. .TP .B \fBre2c:debug\-output\fP, \fBre2c:flags:debug\-output\fP, \fBre2c:flags:d\fP مشابه گزینه \fB\-\-debug\-output\fP، اما به تفکیک هر بلوک قابل پیکربندی است. .TP .B \fBre2c:empty\-class\fP, \fBre2c:flags:empty\-class\fP مشابه گزینه \fB\-\-empty\-class\fP، اما به تفکیک هر بلوک قابل پیکربندی است. .TP .B \fBre2c:encoding:ebcdic\fP, \fBre2c:flags:ecb\fP, \fBre2c:flags:e\fP مشابه گزینه \fB\-\-ebcdic\fP، اما به تفکیک هر بلوک قابل پیکربندی است. .TP .B \fBre2c:encoding:ucs2\fP, \fBre2c:flags:wide\-chars\fP, \fBre2c:flags:w\fP مشابه گزینه \fB\-\-ucs2\fP، اما به تفکیک هر بلوک قابل پیکربندی است. .TP .B \fBre2c:encoding:utf8\fP, \fBre2c:flags:utf\-8\fP, \fBre2c:flags:8\fP مشابه گزینه \fB\-\-utf8\fP، اما به تفکیک هر بلوک قابل پیکربندی است. .TP .B \fBre2c:encoding:utf16\fP, \fBre2c:flags:utf\-16\fP, \fBre2c:flags:x\fP مشابه گزینه \fB\-\-utf16\fP، اما به تفکیک هر بلوک قابل پیکربندی است. .TP .B \fBre2c:encoding:utf32\fP, \fBre2c:flags:unicode\fP, \fBre2c:flags:u\fP مشابه گزینه \fB\-\-utf32\fP، اما به تفکیک هر بلوک قابل پیکربندی است. .TP .B \fBre2c:encoding\-policy\fP, \fBre2c:flags:encoding\-policy\fP مشابه گزینه \fB\-\-encoding\-policy\fP، اما به تفکیک هر بلوک قابل پیکربندی است. .TP .B \fBre2c:eof\fP نماد نشانگر انتها (sentinel symbol) مورد استفاده با قاعده پایان ورودی \fB$\fP را مشخص می‌کند. مقدار پیش‌فرض \fB\-1\fP است (قاعده \fB$\fP استفاده نمی‌شود). سایر مقادیر ممکن شامل تمام واحدهای کد (code units) معتبر است. تنها اعداد ده‌دهی تشخیص داده می‌شوند. .TP .B \fBre2c:header\fP, \fBre2c:flags:type\-header\fP, \fBre2c:flags:t\fP نام فایل سرآیند تولیدشده را به صورت نسبی نسبت به دایرکتوری فایل خروجی مشخص می‌کند. مشابه گزینه \fB\-\-header\fP، با این تفاوت که مسیر فایل نسبی است. .TP .B \fBre2c:indent:string\fP رشته مورد استفاده برای تورفتگی را مشخص می‌کند. مقدار پیش‌فرض یک نویسه تب تکی \fB\(dq\et\(dq\fP است. رشته تورفتگی فقط باید شامل نویسه‌های فاصله خالی (whitespace) باشد. برای غیرفعال کردن کامل تورفتگی، این پیکربندی را روی یک رشته خالی تنظیم کنید. .TP .B \fBre2c:indent:top\fP حداقل میزان تورفتگی مورد استفاده را مشخص می‌کند. مقدار پیش‌فرض صفر است. این مقدار باید یک عدد صحیح غیرمنفی باشد. .TP .B \fBre2c:invert\-captures\fP مشابه گزینه \fB\-\-invert\-captures\fP، اما به تفکیک هر بلوک قابل پیکربندی است. .TP .B \fBre2c:label:prefix\fP, \fBre2c:labelprefix\fP پیشوند مورد استفاده برای برچسب‌های وضعیت DFA را مشخص می‌کند. مقدار پیش‌فرض \fByy\fP است. .TP .B \fBre2c:label:start\fP, \fBre2c:startlabel\fP تولید برچسب آغاز بلوک را کنترل می‌کند. مقدار پیش‌فرض صفر است، به این معنی که برچسب آغاز تنها در صورتی تولید می‌شود که استفاده شده باشد. یک مقدار عددی صحیح بزرگ‌تر از صفر، تولید برچسب آغاز را حتی اگر توسط تحلیل‌گر واژگانی استفاده نشده باشد اجباری می‌کند. یک مقدار رشته‌ای نیز تولید برچسب آغاز را اجباری کرده و نام برچسب را روی رشته مشخص‌شده تنظیم می‌کند. این پیکربندی تنها برای بلوک فعلی اعمال می‌شود (برای بلوک بعدی به مقدار پیش‌فرض بازنشانی می‌شود). .TP .B \fBre2c:label:yyFillLabel\fP پیشوند برچسب‌های \fBYYFILL\fP مورد استفاده با \fBre2c:eof\fP و در حالت وضعیت قابل ذخیره‌سازی (storable state mode) را مشخص می‌کند. .TP .B \fBre2c:label:yyloop\fP نام برچسب نشان‌دهنده شروع حلقه تحلیل‌گر واژگانی همراه با گزینه \fB\-\-loop\-switch\fP را مشخص می‌کند. مقدار پیش‌فرض \fByyloop\fP است. .TP .B \fBre2c:label:yyNext\fP نام برچسب اختیاری‌ای را مشخص می‌کند که پس از سوییچ \fBYYGETSTATE\fP در حالت وضعیت قابل ذخیره‌سازی (که با \fBre2c:state:nextlabel\fP فعال می‌شود) می‌آید. مقدار پیش‌فرض \fByyNext\fP است. .TP .B \fBre2c:lookahead\fP, \fBre2c:flags:lookahead\fP منسوخ‌شده (گزینه منسوخ‌شده \fB\-\-no\-lookahead\fP را ببینید). .TP .B \fBre2c:monadic\fP اگر روی مقداری غیر از صفر تنظیم شود، تحلیل‌گر واژگانی تولیدشده از نمادگذاری مونادیک (monadic notation) استفاده خواهد کرد (این پیکربندی مخصوص Haskell است)..TP .B \fBre2c:nested\-ifs\fP, \fBre2c:flags:nested\-ifs\fP, \fBre2c:flags:s\fP مشابه گزینهٔ \fB\-\-nested\-ifs\fP است، اما می‌تواند به‌ازای هر بلوک پیکربندی شود. .TP .B \fBre2c:posix\-captures\fP, \fBre2c:flags:posix\-captures\fP, \fBre2c:flags:P\fP مشابه گزینهٔ \fB\-\-posix\-captures\fP است، اما می‌تواند به‌ازای هر بلوک پیکربندی شود. .TP .B \fBre2c:posix\-captvars\fP مشابه گزینهٔ \fB\-\-posix\-captvars\fP است، اما می‌تواند به‌ازای هر بلوک پیکربندی شود. .TP .B \fBre2c:tags\fP, \fBre2c:flags:tags\fP, \fBre2c:flags:T\fP مشابه گزینهٔ \fB\-\-tags\fP است، اما می‌تواند به‌ازای هر بلوک پیکربندی شود. .TP .B \fBre2c:tags:expression\fP عبارت مورد استفاده برای متغیرهای برچسب را مشخص می‌کند. به‌طور پیش‌فرض re2c عبارت‌هایی به فرم \fByyt\fP تولید می‌کند\&. این ممکن است ناخوشایند باشد، برای مثال اگر متغیرهای برچسب به‌صورت فیلدهایی در یک struct تعریف شده باشند. تمامی رخدادهای \fB@@{tag}\fP یا \fB@@\fP با نام واقعی برچسب جایگزین می‌شوند. برای مثال، \fBre2c:tags:expression = \(dqs.@@\(dq;\fP منجر به عبارت‌هایی به فرم \fBs.yyt\fP در کد تولیدشده خواهد شد. همچنین پیکربندی \fBre2c:api:sigil\fP را ببینید. .TP .B \fBre2c:tags:negative\fP عبارت ثابتی را مشخص می‌کند که برای مقدار منفی برچسب استفاده می‌شود (به‌طور معمول اگر برچسب‌ها آفست‌های صحیح در رشتهٔ ورودی باشند این مقدار \fB\-1\fP است، یا اگر اشاره‌گر باشند اشاره‌گر تهی خواهد بود). .TP .B \fBre2c:tags:prefix\fP پیشوند نام متغیرهای برچسب را مشخص می‌کند. مقدار پیش‌فرض \fByyt\fP است\&. .TP .B \fBre2c:sentinel\fP نماد دیده‌بان (sentinel) مورد استفاده برای بررسی‌های پایان ورودی را مشخص می‌کند (زمانی که بررسی‌های محدوده با \fBre2c:yyfill:enable = 0;\fP غیرفعال شده و \fBre2c:eof\fP تنظیم نشده باشد). این پیکربندی تأثیری بر تولید کد نمی‌گذارد: هدف آن راستی‌آزمایی این نکته است که نماد دیده‌بان در میانهٔ یک قاعده مجاز نباشد، و تضمین کند که تحلیل‌گر لغوی فراتر از انتهای بافر را نخواند. مقدار پیش‌فرض \fI\-1\(ga\fP است (در این حالت re2c فرض می‌کند که نماد دیده‌بان صفر است، که رایج‌ترین حالت می‌باشد). فقط اعداد ده‌دهی شناسایی می‌شوند. .TP .B \fBre2c:state:abort\fP اگر روی یک مقدار صحیح مثبت تنظیم شود، حالت پیش‌فرض (default case) در توزیع وضعیت تولیدشده، اجرای برنامه را متوقف می‌کند، و یک حالت صریح \fB\-1\fP شامل انتقال به ابتدای بلوک خواهد بود. .TP .B \fBre2c:state:nextlabel\fP کنترل می‌کند که آیا بعد از سوییچ \fBYYGETSTATE\fP یک برچسب \fByyNext\fP بیاید یا خیر (مقدار پیش‌فرض صفر است، که متناظر با نبود برچسب می‌باشد). به‌عنوان جایگزین می‌توان از \fBre2c:label:start\fP برای تولید یک برچسب شروع مشخص استفاده کرد، یا از یک بلوک صریح \fBgetstate\fP برای تولید سوییچ \fBYYGETSTATE\fP به‌طور جداگانه از بلوک تحلیل‌گر لغوی بهره برد. .TP .B \fBre2c:unsafe\fP, \fBre2c:flags:unsafe\fP مشابه گزینهٔ \fB\-\-no\-unsafe\fP است، اما می‌تواند به‌ازای هر بلوک پیکربندی شود. اگر روی صفر تنظیم شود، از تولید پوشش‌های \fBunsafe\fP در اطراف \fBYYPEEK\fP جلوگیری می‌کند\&. مقدار پیش‌فرض غیرصفر است (پوشش‌ها تولید می‌شوند). این پیکربندی مختص Rust است. .TP .B \fBre2c:YYBACKUP\fP, \fBre2c:define:YYBACKUP\fP عملگر اولیهٔ عمومی API به نام \fBYYBACKUP\fP را تعریف می‌کند\&. .TP .B \fBre2c:YYBACKUPCTX\fP, \fBre2c:define:YYBACKUPCTX\fP عملگر اولیهٔ عمومی API به نام \fBYYBACKUPCTX\fP را تعریف می‌کند\&. .TP .B \fBre2c:YYCONDTYPE\fP, \fBre2c:define:YYCONDTYPE\fP عملگر اولیهٔ API به نام \fBYYCONDTYPE\fP را تعریف می‌کند\&. .TP .B \fBre2c:YYCTYPE\fP, \fBre2c:define:YYCTYPE\fP عملگر اولیهٔ API به نام \fBYYCTYPE\fP را تعریف می‌کند\&. .TP .B \fBre2c:YYCTXMARKER\fP, \fBre2c:define:YYCTXMARKER\fP عملگر اولیهٔ API به نام \fBYYCTXMARKER\fP را تعریف می‌کند\&. .TP .B \fBre2c:YYCURSOR\fP, \fBre2c:define:YYCURSOR\fP عملگر اولیهٔ API به نام \fBYYCURSOR\fP را تعریف می‌کند\&. .TP .B \fBre2c:YYDEBUG\fP, \fBre2c:define:YYDEBUG\fP عملگر اولیهٔ API به نام \fBYYDEBUG\fP را تعریف می‌کند\&. .TP .B \fBre2c:YYFILL\fP, \fBre2c:define:YYFILL\fP عملگر اولیهٔ API به نام \fBYYFILL\fP را تعریف می‌کند\&. .TP .B \fBre2c:YYFILL@len\fP, \fBre2c:define:YYFILL@len\fP نماد (sigil) مورد استفاده برای جایگزینی آرگومان در تعریف \fBYYFILL\fP را مشخص می‌کند. مقدار پیش‌فرض \fB@@\fP است\&. پیکربندی عمومی‌ترِ \fBre2c:api:sigil\fP را بازنویسی می‌کند. .TP .B \fBre2c:YYFILL:naked\fP, \fBre2c:define:YYFILL:naked\fP پیکربندی عمومی‌ترِ \fBre2c:api:style\fP را برای \fBYYFILL\fP بازنویسی می‌کند\&. مقدار صفر متناظر با سبک API از نوع free\-form است. .TP .B \fBre2c:YYFN\fP عملگر اولیهٔ API به نام \fBYYFN\fP را تعریف می‌کند\&. .TP .B \fBre2c:YYINPUT\fP عملگر اولیهٔ API به نام \fBYYINPUT\fP را تعریف می‌کند\&. .TP .B \fBre2c:YYGETCOND\fP, \fBre2c:define:YYGETCONDITION\fP عملگر اولیهٔ API به نام \fBYYGETCOND\fP را تعریف می‌کند\&. .TP .B \fBre2c:YYGETCOND:naked\fP, \fBre2c:define:YYGETCONDITION:naked\fP پیکربندی عمومی‌ترِ \fBre2c:api:style\fP را برای \fBYYGETCOND\fP بازنویسی می‌کند\&. مقدار صفر متناظر با سبک API از نوع free\-form است. .TP .B \fBre2c:YYGETSTATE\fP, \fBre2c:define:YYGETSTATE\fP عملگر اولیهٔ API به نام \fBYYGETSTATE\fP را تعریف می‌کند\&. .TP .B \fBre2c:YYGETSTATE:naked\fP, \fBre2c:define:YYGETSTATE:naked\fP پیکربندی عمومی‌ترِ \fBre2c:api:style\fP را برای \fBYYGETSTATE\fP بازنویسی می‌کند\&. مقدار صفر متناظر با سبک API از نوع free\-form است. .TP .B \fBre2c:YYGETACCEPT\fP, \fBre2c:define:YYGETACCEPT\fP عملگر اولیهٔ API به نام \fBYYGETACCEPT\fP را تعریف می‌کند\&. .TP .B \fBre2c:YYLESSTHAN\fP, \fBre2c:define:YYLESSTHAN\fP عملگر اولیهٔ عمومی API به نام \fBYYLESSTHAN\fP را تعریف می‌کند\&. .TP .B \fBre2c:YYLIMIT\fP, \fBre2c:define:YYLIMIT\fP عملگر اولیهٔ API به نام \fBYYLIMIT\fP را تعریف می‌کند\&. .TP .B \fBre2c:YYMARKER\fP, \fBre2c:define:YYMARKER\fP عملگر اولیهٔ API به نام \fBYYMARKER\fP را تعریف می‌کند\&. .TP .B \fBre2c:YYMTAGN\fP, \fBre2c:define:YYMTAGN\fP عملگر اولیهٔ عمومی API به نام \fBYYMTAGN\fP را تعریف می‌کند\&. .TP .B \fBre2c:YYMTAGP\fP, \fBre2c:define:YYMTAGP\fP عملگر اولیهٔ عمومی API به نام \fBYYMTAGP\fP را تعریف می‌کند\&. .TP .B \fBre2c:YYPEEK\fP, \fBre2c:define:YYPEEK\fP عملگر اولیهٔ عمومی API به نام \fBYYPEEK\fP را تعریف می‌کند\&. .TP .B \fBre2c:YYRESTORE\fP, \fBre2c:define:YYRESTORE\fP عملگر اولیهٔ عمومی API به نام \fBYYRESTORE\fP را تعریف می‌کند\&. .TP .B \fBre2c:YYRESTORECTX\fP, \fBre2c:define:YYRESTORECTX\fP عملگر اولیهٔ عمومی API به نام \fBYYRESTORECTX\fP را تعریف می‌کند\&. .TP .B \fBre2c:YYRESTORETAG\fP, \fBre2c:define:YYRESTORETAG\fP عملگر اولیهٔ عمومی API به نام \fBYYRESTORETAG\fP را تعریف می‌کند\&. .TP .B \fBre2c:YYSETCOND\fP, \fBre2c:define:YYSETCONDITION\fP عملگر اولیهٔ API به نام \fBYYSETCOND\fP را تعریف می‌کند\&. .TP .B \fBre2c:YYSETCOND@cond\fP, \fBre2c:define:YYSETCONDITION@cond\fP نماد (sigil) مورد استفاده برای جایگزینی آرگومان در تعریف \fBYYSETCOND\fP را مشخص می‌کند. مقدار پیش‌فرض \fB@@\fP است\&. پیکربندی عمومی‌ترِ \fBre2c:api:sigil\fP را بازنویسی می‌کند. .TP .B \fBre2c:YYSETCOND:naked\fP, \fBre2c:define:YYSETCONDITION:naked\fP پیکربندی عمومی‌ترِ \fBre2c:api:style\fP را برای \fBYYSETCOND\fP بازنویسی می‌کند\&. مقدار صفر متناظر با سبک API از نوع free\-form است. .TP .B \fBre2c:YYSETSTATE\fP, \fBre2c:define:YYSETSTATE\fP عملگر اولیهٔ API به نام \fBYYSETSTATE\fP را تعریف می‌کند\&. .TP .B \fBre2c:YYSETSTATE@state\fP, \fBre2c:define:YYSETSTATE@state\fP نماد (sigil) مورد استفاده برای جایگزینی آرگومان در تعریف \fBYYSETSTATE\fP را مشخص می‌کند. مقدار پیش‌فرض \fB@@\fP است\&. پیکربندی عمومی‌ترِ \fBre2c:api:sigil\fP را بازنویسی می‌کند. .TP .B \fBre2c:YYSETSTATE:naked\fP, \fBre2c:define:YYSETSTATE:naked\fP پیکربندی عمومی‌ترِ \fBre2c:api:style\fP را برای \fBYYSETSTATE\fP بازنویسی می‌کند\&. مقدار صفر متناظر با سبک API از نوع free\-form است. .TP .B \fBre2c:YYSETACCEPT\fP, \fBre2c:define:YYSETACCEPT\fP عملگر اولیهٔ API به نام \fBYYSETACCEPT\fP را تعریف می‌کند\&. .TP .B \fBre2c:YYSKIP\fP, \fBre2c:define:YYSKIP\fP عملگر اولیهٔ عمومی API به نام \fBYYSKIP\fP را تعریف می‌کند\&. .TP .B \fBre2c:YYSHIFT\fP, \fBre2c:define:YYSHIFT\fP عملگر اولیهٔ عمومی API به نام \fBYYSHIFT\fP را تعریف می‌کند\&. .TP .B \fBre2c:YYCOPYMTAG\fP, \fBre2c:define:YYCOPYMTAG\fP عملگر اولیهٔ عمومی API به نام \fBYYCOPYMTAG\fP را تعریف می‌کند\&. .TP .B \fBre2c:YYCOPYSTAG\fP, \fBre2c:define:YYCOPYSTAG\fP عملگر اولیهٔ عمومی API به نام \fBYYCOPYSTAG\fP را تعریف می‌کند\&..TP .B \fBre2c:YYSHIFTMTAG\fP, \fBre2c:define:YYSHIFTMTAG\fP عنصر پایه generic API به نام \fBYYSHIFTMTAG\fP را تعریف می‌کند\&. .TP .B \fBre2c:YYSHIFTSTAG\fP, \fBre2c:define:YYSHIFTSTAG\fP عنصر پایه generic API به نام \fBYYSHIFTSTAG\fP را تعریف می‌کند\&. .TP .B \fBre2c:YYSTAGN\fP, \fBre2c:define:YYSTAGN\fP عنصر پایه generic API به نام \fBYYSTAGN\fP را تعریف می‌کند\&. .TP .B \fBre2c:YYSTAGP\fP, \fBre2c:define:YYSTAGP\fP عنصر پایه generic API به نام \fBYYSTAGP\fP را تعریف می‌کند\&. .TP .B \fBre2c:yyaccept\fP, \fBre2c:variable:yyaccept\fP عنصر پایه API به نام \fByyaccept\fP را تعریف می‌کند\&. .TP .B \fBre2c:yybm\fP, \fBre2c:variable:yybm\fP عنصر پایه API به نام \fByybm\fP را تعریف می‌کند\&. .TP .B \fBre2c:yybm:hex\fP, \fBre2c:variable:yybm:hex\fP اگر روی غیرصفر تنظیم شود، نگاشت‌های بیتی (bitmaps) برای گزینهٔ \fB\-\-bit\-vectors\fP در قالب شانزده‌شانزدهی (hexadecimal) تولید می‌شوند. پیش‌فرض صفر است (نگاشت‌های بیتی در قالب ده‌دهی هستند). .TP .B \fBre2c:yych\fP, \fBre2c:variable:yych\fP عنصر پایه API به نام \fByych\fP را تعریف می‌کند\&. .TP .B \fBre2c:yych:emit\fP, \fBre2c:variable:yych:emit\fP اگر روی صفر تنظیم شود، تعریف \fByych\fP تولید نمی‌شود. پیش‌فرض غیرصفر است. .TP .B \fBre2c:yych:conversion\fP, \fBre2c:variable:yych:conversion\fP اگر روی غیرصفر تنظیم شود، re2c هر بار که \fByych\fP خوانده می‌شود، به‌طور خودکار یک تبدیل به \fBYYCTYPE\fP تولید می‌کند. پیش‌فرض صفر است (بدون تبدیل). .TP .B \fBre2c:yych:literals\fP, \fBre2c:variable:yych:literals\fP قالب لیترال‌هایی که \fByych\fP با آن‌ها مطابقت داده می‌شود را مشخص می‌کند. مقادیر ممکن عبارتند از: \fBchar\fP (لیترال‌های نویسه‌ای در نقل‌قول تکی، که نویسه‌های غیرقابل‌چاپ در آن از توالی‌های گریزِ شروع‌شونده با بک‌اسلش استفاده می‌کنند)، \fBhex\fP (اعداد صحیح شانزده‌شانزدهی) و \fBchar_or_hex\fP (ترکیبی از هر دو؛ لیترال‌های نویسه‌ای برای نویسه‌های قابل‌چاپ و اعداد صحیح شانزده‌شانزدهی برای سایر موارد). .TP .B \fBre2c:yyctable\fP, \fBre2c:variable:yyctable\fP عنصر پایه API به نام \fByyctable\fP را تعریف می‌کند\&. .TP .B \fBre2c:yynmatch\fP, \fBre2c:variable:yynmatch\fP عنصر پایه API به نام \fByynmatch\fP را تعریف می‌کند\&. .TP .B \fBre2c:yypmatch\fP, \fBre2c:variable:yypmatch\fP عنصر پایه API به نام \fByypmatch\fP را تعریف می‌کند\&. .TP .B \fBre2c:yytarget\fP, \fBre2c:variable:yytarget\fP عنصر پایه API به نام \fByytarget\fP را تعریف می‌کند\&. .TP .B \fBre2c:yystable\fP, \fBre2c:variable:yystable\fP منسوخ شده است. .TP .B \fBre2c:yystate\fP, \fBre2c:variable:yystate\fP عنصر پایه API به نام \fByystate\fP را تعریف می‌کند\&. .TP .B \fBre2c:yyfill\fP, \fBre2c:variable:yyfill\fP عنصر پایه API به نام \fByyfill\fP را تعریف می‌کند\&. .TP .B \fBre2c:yyfill:check\fP اگر روی صفر تنظیم شود، از تولید بررسی پیش از \fBYYFILL\fP برای تعداد نویسه‌های ورودی (تعریف \fBYYLESSTHAN\fP در generic API و مقایسه مبتنی بر \fBYYLIMIT\fP در C pointer API) جلوگیری می‌کند. پیش‌فرض غیرصفر است (بررسی تولید می‌شود). .TP .B \fBre2c:yyfill:enable\fP اگر روی صفر تنظیم شود، از تولید \fBYYFILL\fP (همراه با بررسی آن) جلوگیری می‌کند. این تنظیم زمانی باید استفاده شود که کل ورودی در یک قطعه از حافظه جا شود (نیازی به بافرسازی نیست) و بررسی‌های پایان ورودی به بررسی‌های \fBYYFILL\fP وابسته نباشند (مثلاً زمانی که از یک نویسهٔ نشانگر پایان/sentinel استفاده می‌شود). از هشدارها (گزینهٔ \fB\-W\fP) و پیکربندی \fBre2c:sentinel\fP استفاده کنید تا مطمئن شوید تحلیل‌گر لغوی تولیدشده نمی‌تواند فراتر از انتهای ورودی را بخواند. پیش‌فرض غیرصفر است (\fBYYFILL\fP فعال است). .TP .B \fBre2c:yyfill:parameter\fP اگر روی صفر تنظیم شود، از تولید پارامتر ارسالی به \fBYYFILL\fP جلوگیری می‌کند\&. این پارامتر نشان‌دهندهٔ حداقل تعداد نویسه‌هایی است که باید تأمین شوند. پیش‌فرض غیرصفر است (پارامتر تولید می‌شود). این پیکربندی می‌تواند توسط \fBre2c:YYFILL:naked\fP یا \fBre2c:api:style\fP بازنویسی شود\&. .TP .B \fBre2c:yyfn:sep\fP جداکنندهٔ مورد استفاده در عناصر \fBYYFN\fP را مشخص می‌کند (پیش‌فرض نقطه‌ویرگول است). .TP .B \fBre2c:yyfn:throw\fP استثناهای پرتاب‌شده توسط تابع \fBYYFN\fP را مشخص می‌کند (پیش‌فرض خالی است، که به معنای عدم وجود هیچ استثنایی است). .UNINDENT.SS عبارت‌های منظم (Regular expressions) .sp ابزار re2c از ساختار دستوری زیر برای عبارت‌های منظم استفاده می‌کند: .INDENT 0.0 .TP .B \fB\(dqfoo\(dq\fP رشته لیترال حساس به بزرگ و کوچکی حروف. .TP .B \fB\(aqfoo\(aq\fP رشته لیترال غیرحساس به بزرگ و کوچکی حروف. .TP .B \fB[a\-xyz]\fP, \fB[^a\-xyz]\fP کلاس نویسه (احتمالاً نفی‌شده). .TP .B \fB\&.\fP هر نویسه‌ای به جز خط جدید. .TP .B \fBR \e S\fP تفاضل کلاس‌های نویسهٔ \fBR\fP و \fBS\fP\&. .TP .B \fBR*\fP صفر یا چند بار تکرار \fBR\fP\&. .TP .B \fBR+\fP یک یا چند بار تکرار \fBR\fP\&. .TP .B \fBR?\fP مورد اختیاری \fBR\fP\&. .TP .B \fBR{n}\fP تکرار \fBR\fP دقیقاً به تعداد \fBn\fP بار. .TP .B \fBR{n,}\fP تکرار \fBR\fP دست‌کم به تعداد \fBn\fP بار. .TP .B \fBR{n,m}\fP تکرار \fBR\fP از \fBn\fP تا \fBm\fP بار. .TP .B \fB(R)\fP صرفاً \fBR\fP؛ پرانتزها برای تغییر اولویت استفاده می‌شوند. اگر استخراج زیرتطابق فعال باشد، \fB(R)\fP بسته به گزینهٔ \fB\-\-invert\-captures\fP یک گروه ضبط‌کننده یا غیرضبط‌کننده است. .TP .B \fB(!R)\fP اگر استخراج زیرتطابق فعال باشد، \fB(!R)\fP بسته به گزینهٔ \fB\-\-invert\-captures\fP یک گروه غیرضبط‌کننده یا ضبط‌کننده است. .TP .B \fBR S\fP الحاق: \fBR\fP و به دنبال آن \fBS\fP\&. .TP .B \fBR | S\fP جایگزین: \fBR یا S\fP\&. .TP .B \fBR / S\fP پیش‌نگری (Lookahead): \fBR\fP و به دنبال آن \fBS\fP، اما \fBS\fP مصرف نمی‌شود. .TP .B \fBname\fP عبارت منظم تعریف‌شده با نام \fBname\fP (یا رشته لیترال \fB\(dqname\(dq\fP در حالت سازگاری با Flex). .TP .B \fB{name}\fP عبارت منظم تعریف‌شده با نام \fBname\fP در حالت سازگاری با Flex. .TP .B \fB@stag\fP یک \fIs\-tag\fP: آخرین موقعیت ورودی را که در آن \fB@stag\fP مطابقت دارد در یک متغیر به نام \fBstag\fP ذخیره می‌کند. .TP .B \fB#mtag\fP یک \fIm\-tag\fP: تمام موقعیت‌های ورودی را که در آن‌ها \fB#mtag\fP مطابقت دارد در یک متغیر به نام \fBmtag\fP ذخیره می‌کند. .TP .B \fB$\fP پایان ورودی. .UNINDENT .sp کلاس‌های نویسه و رشته‌های لیترال ممکن است شامل دنباله‌های گریز زیر باشند: \fB\ea\fP، \fB\eb\fP، \fB\ef\fP، \fB\en\fP، \fB\er\fP، \fB\et\fP، \fB\ev\fP، \fB\e\e\fP، گریزهای هشت‌هشتی \fB\eooo\fP و گریزهای شانزده‌شانزدهی \fB\exhh\fP، \fB\euhhhh\fP و \fB\eUhhhhhhhh\fP\&. .SS کنش‌ها (Actions) .sp در اینجا فهرستی از کنش‌های از پیش تعریف‌شده که توسط re2c پشتیبانی می‌شوند آورده شده است: .INDENT 0.0 .TP .B \fB!entry code\fP کنش ورودی (Entry action) یک بلوک \fBcode\fP تعریف‌شده توسط کاربر را به وضعیت آغازین ماشین حالت متناهی فعلی پیوند می‌دهد. اگر از \fI\%start conditions\fP (شرایط شروع) استفاده شود، کنش ورودی را می‌توان به طور جداگانه برای هر شرط تنظیم کرد. این کنش ممکن است برای انجام مقداردهی اولیه، مثلاً برای ذخیره موقعیت شروع یک نشانه (lexeme)، استفاده شود. .TP .B \fB!pre_rule code\fP کنش پیش‌قاعده (Pre\-rule action) یک بلوک \fBcode\fP تعریف‌شده توسط کاربر را به ابتدای کنش‌های معنایی تمام قواعد در بلوک فعلی (یا شرط، در صورت استفاده از \fI\%start conditions\fP) اضافه می‌کند. این کنش می‌تواند برای فاکتور گرفتن بخش مشترک تمام کنش‌های معنایی (مانند ذخیره موقعیت پایانی یک نشانه) به کار رود. .TP .B \fB!post_rule code\fP کنش پس‌قاعده (Post\-rule action) یک بلوک \fBcode\fP تعریف‌شده توسط کاربر را به انتهای کنش‌های معنایی تمام قواعد در بلوک فعلی (یا شرط، در صورت استفاده از \fI\%start conditions\fP) ضمیمه می‌کند. این کنش می‌تواند برای درج عبارت‌های تله (trap statements) جهت جلوگیری از جریان کنترل ناخواسته استفاده شود. .UNINDENT.SS "دستورالعمل‌ها (Directives)" .sp در اینجا فهرست کاملی از دستورالعمل‌های پشتیبانی‌شده توسط re2c آورده شده است: .INDENT 0.0 .TP .B \fB!use:name ;\fP یک دستورالعمل use درون‌بلوکی که یک بلوک قواعد از پیش تعریف‌شده با \fBname\fP مشخص را در بلوک فعلی ادغام می‌کند. تعاریف نام‌گذاری‌شده، پیکربندی‌ها و قواعد بلوک ارجاع‌داده‌شده به موارد فعلی افزوده می‌شوند. تداخل‌های میان قواعد و پیکربندی‌های هم‌پوشان به روش معمول حل‌وفصل می‌شوند: نخستین قاعده اولویت دارد، و آخرین پیکربندی بر موارد پیشین چیره می‌شود. یک استثنا، قواعد ویژهٔ \fB*\fP، \fB$\fP و \fB\fP هستند که برای آن‌ها تعریف محلی درون بلوک همیشه اولویت دارد. دستورالعمل use می‌تواند در هر جایی درون یک بلوک قرار گیرد، و استفاده از چندین دستورالعمل use مجاز است. .TP .B \fB!include file ;\fP این دستورالعمل همانند بلوک \fBinclude\fP عمل می‌کند: محتویات \fBfile\fP را عیناً در محل دستورالعمل درج می‌کند. .UNINDENT .SS "رابط برنامه (Program interface)" .sp کد تولیدشده به کمک \fIبنیادینه‌ها (primitives)\fP، که در مجموع به عنوان \fIAPI\fP نامیده می‌شوند، با برنامهٔ بیرونی ارتباط برقرار می‌کند. اینکه کدام بنیادینه‌ها باید برای یک برنامهٔ خاص تعریف شوند به عوامل متعددی بستگی دارد، از جمله پیچیدگی عبارات باقاعده، نحوهٔ نمایش ورودی، بافرینگ و استفاده از ویژگی‌های گوناگون. تمام بنیادینه‌های لازم باید توسط کاربر در قالب ماکروها، توابع، متغیرها یا هر شکل مناسب دیگری که کد تولیدشده را از نظر نحوی و معنایی درست کند، تعریف شوند. re2c تعاریف را بررسی نمی‌کند (و نمی‌تواند بررسی کند)، بنابراین اگر چیزی از قلم افتاده باشد یا به نادرستی تعریف شده باشد، ممکن است برنامهٔ تولیدشده با خطاهای زمان کامپایل یا زمان اجرا مواجه شود. این راهنما مثال‌هایی از تعاریف API را در متداول‌ترین حالت‌ها ارائه می‌دهد. .sp ابزار re2c دارای سه شیوهٔ مختلف API است که مجموعهٔ هستهٔ بنیادینه‌های مورداستفاده در یک برنامه را تعیین می‌کنند: .INDENT 0.0 .TP .B \fBSimple API\fP این شیوه، API پیش‌فرض برای بک‌اند C/C++ است. این رابط شامل بنیادینه‌های \fBYYCURSOR\fP، \fBYYMARKER\fP، \fBYYCTXMARKER\fP و \fBYYLIMIT\fP است که باید به عنوان اشاره‌گرهایی از نوع \fBYYCTYPE*\fP تعریف شوند. .nf .fi .sp .TP .B \fBRecord API\fP (\fIدر نسخهٔ 4.0 اضافه شد\fP) رابط Record API در مواردی مفید است که وضعیت تحلیل‌گر لغوی (lexer) باید در یک struct ذخیره شود. این رابط با گزینهٔ \fB\-\-api record\fP یا پیکربندی \fBre2c:api = record\fP فعال می‌شود. این API شامل یک متغیر \fByyrecord\fP است (این نام را می‌توان با \fBre2c:yyrecord\fP بازنویسی و جایگزین کرد) که باید به عنوان یک struct با فیلدهای \fByycursor\fP، \fByymarker\fP، \fByyctxmarker\fP و \fByylimit\fP تعریف شود (تنها فیلدهایی که توسط کد تولیدشده استفاده می‌شوند باید تعریف شوند، و نام آن‌ها نیز قابل پیکربندی است). .nf .fi .sp .TP .B \fBGeneric API\fP (\fIدر نسخهٔ 0.14 اضافه شد\fP) این شیوه منعطف‌ترین API است. این رابط با گزینهٔ \fB\-\-api generic\fP یا پیکربندی \fBre2c:api = generic\fP فعال می‌شود. این API شامل بنیادینه‌هایی برای عملیات‌های عمومی است: \fBYYPEEK\fP، \fBYYSKIP\fP، \fBYYBACKUP\fP، \fBYYBACKUPCTX\fP، \fBYYSTAGP\fP، \fBYYSTAGN\fP، \fBYYMTAGP\fP، \fBYYMTAGN\fP، \fBYYRESTORE\fP، \fBYYRESTORECTX\fP، \fBYYRESTORETAG\fP، \fBYYSHIFT\fP، \fBYYSHIFTSTAG\fP، \fBYYSHIFTMTAG\fP، \fBYYLESSTHAN\fP\&. \fBYYEND\fP\&. رابط Generic API از دو سبک پشتیبانی می‌کند که قالبی را که در آن بنیادینه‌ها باید تعریف شوند مشخص می‌سازند: .nf .fi .sp .INDENT 7.0 .TP .B \fBFree\-form\fP سبک آزاد (Free\-form) با پیکربندی \fBre2c:api:style = free\-form\fP فعال می‌شود. در این سبک، بنیادینه‌های رابط باید به صورت قطعه‌کدهای آزاد با متغیرهای درون‌یابی‌شده به شکل \fB@@{var}\fP، یا در صورت وجود تنها یک متغیر، به صورت اختیاری فقط به صورت \fB@@\fP تعریف شوند. مجموعهٔ متغیرها مختص هر بنیادینه است. در اینجا نحوهٔ تعریف Generic API به سبک آزاد بر حسب اشاره‌گرهای \fBcursor\fP، \fBlimit\fP، \fBmarker\fP و \fBctxmarker\fP آورده شده است: .INDENT 7.0 .INDENT 3.5 .sp .nf .ft C /*!re2c re2c:YYPEEK = \(dq*cursor\(dq; re2c:YYSKIP = \(dq++cursor;\(dq; re2c:YYBACKUP = \(dqmarker = cursor;\(dq; re2c:YYRESTORE = \(dqcursor = marker;\(dq; re2c:YYBACKUPCTX = \(dqctxmarker = cursor;\(dq; re2c:YYRESTORECTX = \(dqcursor = ctxmarker;\(dq; re2c:YYRESTORETAG = \(dqcursor = ${tag};\(dq; re2c:YYLESSTHAN = \(dqlimit \- cursor < @@{len}\(dq; re2c:YYEND = \(dqlimit == cursor\(dq; re2c:YYSTAGP = \(dq@@{tag} = cursor;\(dq; re2c:YYSTAGN = \(dq@@{tag} = NULL;\(dq; re2c:YYSHIFT = \(dqcursor += @@{shift};\(dq; re2c:YYSHIFTSTAG = \(dq@@{tag} += @@{shift};\(dq; */ .ft P .fi .UNINDENT .UNINDENT .nf .fi .sp .TP .B \fBFunction\-like\fP از نظر تاریخی، سبک تابع‌گونه (function\-like) سبک پیش‌فرض است. این سبک همچنین می‌تواند با پیکربندی \fBre2c:api:style = functions\fP فعال شود. در این سبک، بنیادینه‌ها باید به عنوان توابع یا ماکروهای دارای پرانتز که آرگومان‌های لازم را دریافت می‌کنند تعریف شوند. در اینجا نحوهٔ تعریف Generic API به سبک تابع‌گونه بر حسب اشاره‌گرهای \fBcursor\fP، \fBlimit\fP، \fBmarker\fP و \fBctxmarker\fP با استفاده از ماکروهای پیش‌پردازنده آورده شده است: .INDENT 7.0 .INDENT 3.5 .sp .nf .ft C #define YYPEEK() *cursor #define YYSKIP() ++cursor #define YYBACKUP() marker = cursor #define YYRESTORE() cursor = marker #define YYBACKUPCTX() ctxmarker = cursor #define YYRESTORECTX() cursor = ctxmarker #define YYRESTORETAG(tag) cursor = tag #define YYLESSTHAN(len) limit \- cursor < len #define YYEND() limit == cursor #define YYSTAGP(tag) tag = cursor #define YYSTAGN(tag) tag = NULL #define YYSHIFT(shift) cursor += shift #define YYSHIFTSTAG(tag, shift) tag += shift .ft P .fi .UNINDENT .UNINDENT .UNINDENT .UNINDENT .sp در اینجا فهرست کاملی از بنیادینه‌های API که ممکن است توسط کد تولیدشده جهت ارتباط با برنامهٔ بیرونی استفاده شوند آورده شده است. .INDENT 0.0 .TP .B \fBYYCTYPE\fP نوع نویسه‌های ورودی (واحدهای کد). برای رمزگذاری‌های ASCII، EBCDIC و UTF\-8 باید یک عدد صحیح بدون علامت ۱ بایتی باشد. برای UTF\-16 یا UCS\-2 باید یک عدد صحیح بدون علامت ۲ بایتی باشد. برای UTF\-32 باید یک عدد صحیح بدون علامت ۴ بایتی باشد. .TP .B \fBYYCURSOR\fP یک l\-value که موقعیت فعلی ورودی را ذخیره می‌کند (یک اشاره‌گر یا یک آفست عدد صحیح در \fBYYINPUT\fP). در ابتدا \fBYYCURSOR\fP باید به نخستین نویسهٔ ورودی اشاره کند، و سپس توسط کد تولیدشده به جلو برده می‌شود. هنگامی که یک قاعده تطبیق می‌یابد، موقعیت \fBYYCURSOR\fP برابر با موقعیت پس از آخرین نویسهٔ تطبیق‌یافته است. .TP .B \fBYYLIMIT\fP یک r\-value که موقعیت انتهای ورودی را ذخیره می‌کند (یک اشاره‌گر یا یک آفست عدد صحیح در \fBYYINPUT\fP). در ابتدا \fBYYLIMIT\fP باید به موقعیتِ پس از آخرین نویسهٔ موجود در ورودی اشاره کند. این مقدار توسط کد تولیدشده تغییر نمی‌کند. تحلیل‌گر لغوی \fBYYCURSOR\fP را با \fBYYLIMIT\fP مقایسه می‌کند تا تشخیص دهد آیا نویسه‌های ورودیِ کافی باقی مانده است یا خیر..TP .B \fBYYMARKER\fP یک l\-value که موقعیت آخرین قاعدهٔ تطبیق‌یافته را ذخیره می‌کند (یک اشاره‌گر یا یک آفست عدد صحیح در \fBYYINPUT\fP). برای بازیابی موقعیت \fBYYCURSOR\fP در صورتی که تطبیق طولانی‌تر ناموفق باشد و تحلیل‌گر لغوی نیاز به بازگشت به عقب (rollback) داشته باشد، استفاده می‌شود. مقداردهی اولیه لازم نیست. .TP .B \fBYYCTXMARKER\fP یک l\-value که موقعیت بافت پس‌رو (trailing context) را ذخیره می‌کند (یک اشاره‌گر یا یک آفست عدد صحیح در \fBYYINPUT\fP). هیچ مقداردهی اولیه‌ای لازم نیست. \fBYYCTXMARKER\fP تنها در صورتی نیاز است که عملگر پیش‌نگری \fB/\fP استفاده شده باشد. .TP .B \fBYYFILL\fP یک پایهٔ عمومی API با یک متغیر \fBlen\fP\&. \fBYYFILL\fP باید حداقل \fBlen\fP نویسهٔ ورودی بیشتر فراهم کند یا با شکست مواجه شود. اگر \fBre2c:eof\fP استفاده شود، \fBlen\fP همیشه \fB1\fP است و \fBYYFILL\fP باید همیشه به تابع فراخوان بازگردد؛ مقدار بازگشتی صفر نشان‌دهندهٔ موفقیت است. اگر \fBre2c:eof\fP استفاده نشود، مقدار بازگشتی \fBYYFILL\fP نادیده گرفته می‌شود و در صورت شکست نباید بازگردد. حداکثر مقدار \fBlen\fP برابر \fBYYMAXFILL\fP است. .TP .B \fBYYFN\fP یک پایه که پیش‌نمونهٔ تابع را در مدل کد \fB\-\-recursive\-functions\fP تعریف می‌کند. مقدار آن باید آرایه‌ای از یک یا چند رشته باشد، که در آن هر رشته شامل دو یا سه مؤلفه است که توسط رشتهٔ مشخص‌شده در پیکربندی \fBre2c:fn:sep\fP (معمولاً یک نقطه‌ویرگول) از هم جدا شده‌اند. اولین عنصر آرایه نام تابع و نوع بازگشتی را مشخص می‌کند (برای یک تابع void خالی است). عناصر بعدی آرگومان‌های تابع را تعریف می‌کنند: اول، عبارت برای آرگومان مورداستفاده در بدنهٔ تابع (معمولاً فقط یک نام)؛ دوم، نوع آرگومان؛ سوم، یک پارامتر رسمی اختیاری (پیش‌فرض آن مؤلفهٔ اول است \- معمولاً هر دو آرگومان و پارامتر شناسهٔ یکسانی دارند). .TP .B \fBYYINPUT\fP یک r\-value که دنبالهٔ نویسه‌های ورودی فعلی (رشته، بافر، و غیره) را ذخیره می‌کند. .TP .B \fBYYMAXFILL\fP یک ثابت عدد صحیح برابر با حداکثر مقدار آرگومانِ \fBYYFILL\fP\&. این مقدار می‌تواند با یک بلوک \fBmax\fP تولید شود. .TP .B \fBYYLESSTHAN\fP یک پایهٔ عمومی API با یک متغیر \fBlen\fP\&. باید به عنوان یک r\-value از نوع بولی تعریف شود که اگر و تنها اگر کمتر از \fBlen\fP نویسهٔ ورودی باقی مانده باشد، برابر با \fBtrue\fP است. .TP .B \fBYYEND\fP یک پایهٔ عمومی API بدون هیچ متغیری. باید به عنوان یک r\-value از نوع بولی تعریف شود که اگر و تنها اگر به انتهای \fIمنطقی\fP ورودی رسیده باشد (به استثنای هرگونه نماد فاصله‌گذاری یا نگهبان)، برابر با \fBtrue\fP است. \fBYYEND\fP برای پیاده‌سازی نماد \fB$\fP در عبارات باقاعده استفاده می‌شود. این با \fBYYLESSTHAN\fP تفاوت دارد که برای اطمینان از اینکه تحلیل‌گر لغوی فراتر از انتهای بافر نخواند، به کار می‌رود. .TP .B \fBYYPEEK\fP یک پایهٔ عمومی API بدون متغیر. باید به عنوان یک r\-value از نوع \fBYYCTYPE\fP تعریف شود که برابر با نویسه در موقعیت ورودی فعلی است. .TP .B \fBYYSKIP\fP یک پایهٔ عمومی API که باید موقعیت ورودی فعلی را به اندازهٔ یک واحد کد به جلو ببرد. .TP .B \fBYYBACKUP\fP یک پایهٔ عمومی API که باید موقعیت ورودی فعلی را ذخیره کند (تا بعداً با \fBYYRESTORE\fP بازیابی شود). .TP .B \fBYYRESTORE\fP یک پایهٔ عمومی API که باید موقعیت ورودی فعلی را به مقدار ذخیره‌شده توسط \fBYYBACKUP\fP بازیابی کند. .TP .B \fBYYBACKUPCTX\fP یک پایهٔ عمومی API که باید موقعیت ورودی فعلی را به عنوان موقعیت بافت پس‌رو ذخیره کند (تا بعداً با \fBYYRESTORECTX\fP بازیابی شود). .TP .B \fBYYRESTORECTX\fP یک پایهٔ عمومی API که باید موقعیت بافت پس‌رو ذخیره‌شده توسط \fBYYBACKUPCTX\fP را بازیابی کند. .TP .B \fBYYRESTORETAG\fP یک پایهٔ عمومی API با یک متغیر \fBtag\fP که باید موقعیت بافت پس‌رو را به مقدار \fBtag\fP بازیابی کند. .TP .B \fBYYSTAGP\fP یک پایهٔ عمومی API با یک متغیر \fBtag\fP، که در آن \fBtag\fP می‌تواند یک اشاره‌گر یا یک آفست در \fBYYINPUT\fP باشد (برای جزئیات به بخش استخراج تطبیق فرعی مراجعه کنید). \fBYYSTAGP\fP باید \fBtag\fP را روی موقعیت ورودی فعلی تنظیم کند. .TP .B \fBYYSTAGN\fP یک پایهٔ عمومی API با یک متغیر \fBtag\fP، که در آن \fBtag\fP می‌تواند یک اشاره‌گر یا یک آفست در \fBYYINPUT\fP باشد (برای جزئیات به بخش استخراج تطبیق فرعی مراجعه کنید). \fBYYSTAGN\fP باید \fBtag\fP را روی مقداری تنظیم کند که نشان‌دهندهٔ موقعیت ورودیِ ناموجود است. .TP .B \fBYYMTAGP\fP یک پایهٔ عمومی API با یک متغیر \fBtag\fP\&. \fBYYMTAGP\fP باید موقعیت فعلی را به تاریخچهٔ تطبیق فرعی \fBtag\fP اضافه کند (برای جزئیات به بخش استخراج تطبیق فرعی مراجعه کنید). .TP .B \fBYYMTAGN\fP یک پایهٔ عمومی API با یک متغیر \fBtag\fP\&. \fBYYMTAGN\fP باید مقداری را که نشان‌دهندهٔ موقعیت ورودی ناموجود است به تاریخچهٔ تطبیق فرعی \fBtag\fP اضافه کند (برای جزئیات به بخش استخراج تطبیق فرعی مراجعه کنید). .TP .B \fBYYSHIFT\fP یک پایهٔ عمومی API با یک متغیر \fBshift\fP که باید موقعیت ورودی فعلی را به اندازهٔ \fBshift\fP نویسه تغییر مکان دهد (مقدار جابه‌جایی ممکن است منفی باشد). .TP .B \fBYYCOPYSTAG\fP یک پایهٔ عمومی API با دو متغیر \fBlhs\fP و \fBrhs\fP که باید متغیر سمت راستِ s\-tag یعنی \fBrhs\fP را در متغیر سمت چپِ s\-tag یعنی \fBlhs\fP کپی کند. برای بیشتر زبان‌ها این پایه دارای تعریفی پیش‌فرض است که \fBlhs\fP را به \fBrhs\fP تخصیص می‌دهد. .TP .B \fBYYCOPYMTAG\fP یک پایهٔ عمومی API با دو متغیر \fBlhs\fP و \fBrhs\fP که باید متغیر سمت راستِ m\-tag یعنی \fBrhs\fP را در متغیر سمت چپِ m\-tag یعنی \fBlhs\fP کپی کند. برای بیشتر زبان‌ها این پایه دارای تعریفی پیش‌فرض است که \fBlhs\fP را به \fBrhs\fP تخصیص می‌دهد. .TP .B \fBYYSHIFTSTAG\fP یک پایهٔ عمومی API با دو متغیر \fBtag\fP و \fBshift\fP که باید \fBtag\fP را به اندازهٔ \fBshift\fP واحد کد جابه‌جا کند (مقدار جابه‌جایی ممکن است منفی باشد). .TP .B \fBYYSHIFTMTAG\fP یک پایهٔ عمومی API با دو متغیر \fBtag\fP و \fBshift\fP که باید آخرین مقدار در تاریخچهٔ \fBtag\fP را به اندازهٔ \fBshift\fP واحد کد جابه‌جا کند (مقدار جابه‌جایی ممکن است منفی باشد). .TP .B \fBYYMAXNMATCH\fP یک ثابت عدد صحیح برابر با حداکثر تعداد گروه‌های تسخیرکنندهٔ POSIX در یک قاعده. این مقدار با یک بلوک \fBmaxnmatch\fP تولید می‌شود. .TP .B \fBYYCONDTYPE\fP نوع شمارش شرط. می‌تواند با بلوک \fBconditions\fP یا گزینهٔ \fB\-\-header\fP تولید شود. .TP .B \fBYYGETACCEPT\fP یک پایه با یک متغیر \fBvar\fP که انتخاب‌کنندهٔ عددی قاعدهٔ پذیرفته‌شده را ذخیره می‌کند. برای بیشتر زبان‌ها این پایه دارای تعریفی پیش‌فرض است که از \fBvar\fP می‌خواند. .TP .B \fBYYSETACCEPT\fP یک پایه با دو متغیر: \fBvar\fP (یک l\-value که انتخاب‌کنندهٔ عددی قاعدهٔ پذیرفته‌شده را ذخیره می‌کند)، و \fBval\fP (مقدار انتخاب‌کننده). برای بیشتر زبان‌ها این پایه دارای تعریفی پیش‌فرض است که \fBvar\fP را به \fBval\fP تخصیص می‌دهد. .TP .B \fBYYGETCOND\fP یک r\-value از نوع \fBYYCONDTYPE\fP که برابر با شناسهٔ شرط فعلی است. .TP .B \fBYYSETCOND\fP یک پایه با یک متغیر \fBcond\fP که باید شناسهٔ شرط فعلی را به \fBcond\fP تنظیم کند. .TP .B \fBYYGETSTATE\fP یک r\-value از نوع عدد صحیح که برابر با وضعیت فعلی تحلیل‌گر لغوی است. باید با مقدار \fB\-1\fP مقداردهی اولیه شود. .TP .B \fBYYSETSTATE\fP یک پایه با یک متغیر \fBstate\fP که باید وضعیت فعلی تحلیل‌گر لغوی را روی \fBstate\fP تنظیم کند. .TP .B \fBYYDEBUG\fP این پایه فقط با گزینهٔ \fB\-d\fP یا \fB\-\-debug\-output\fP تولید می‌شود. هدف آن افزودن گزارش‌گیری به کد تولیدشده است (تعریف معمول \fBYYDEBUG\fP یک دستور چاپ است). دستورات \fBYYDEBUG\fP در هر وضعیت تولید می‌شوند و دو متغیر دارند: \fBstate\fP (یک نمایهٔ وضعیت DFA یا \fB\-1\fP) و \fBsymbol\fP (نماد ورودی فعلی). .TP .B \fByyaccept\fP یک l\-value از نوع عدد صحیح بدون علامت که شمارهٔ آخرین قاعدهٔ تطبیق‌یافته را ذخیره می‌کند. تعریف کاربر فقط با گزینهٔ \fB\-\-storable\-state\fP ضروری است. .TP .B \fByybm\fP جدولی حاوی نقشه‌های بیتی فشرده‌شده برای حداکثر ۸ انتقال (مورداستفاده با گزینهٔ \fB\-\-bitmaps\fP). جدول شامل ۲۵۶ عنصر است و توسط واحدهای کد ۱\-بایتی نمایه‌گذاری می‌شود. هر عنصر ۸\-بیتی مقادیر بولی را برای حداکثر ۸ انتقال با هم ترکیب می‌کند. بیت k\-اُم از عنصر n\-اُم درست است اگر و تنها اگر واحد کد n\-اُم در محدودهٔ انتقال k\-اُم باشد. ایدهٔ این نقشهٔ بیتی جایگزینی چندین شاخهٔ \fIif\fP یا موارد \fIswitch\fP با یک بررسیِ تک‌بیت در جدول است..TP .B \fByych\fP یک l\-value از نوع \fBYYCTYPE\fP که نویسه ورودی فعلی را ذخیره می‌کند. تعریف آن توسط کاربر تنها با گزینه \fB\-f\fP \fB\-\-storable\-state\fP ضروری است. .TP .B \fByyctable\fP جدول پرش تولیدشده برای اعزام شرایط اولیه (با ترکیب گزینه‌های \fB\-\-conditions\fP و \fB\-\-computed\-gotos\fP فعال می‌شود). .TP .B \fByyfill\fP یک l\-value که نتیجه فراخوانی \fBYYFILL\fP را ذخیره می‌کند (این ممکن است برای زبان‌های تابعی محض که در آن‌ها \fBYYFILL\fP یک تابع مونادیک با مقدار بازگشتی پیچیده است، ضروری باشد). .TP .B \fByynmatch\fP یک l\-value از نوع عددی صحیح بدون علامت که تعداد گروه‌های گیرانداز POSIX را در قاعده منطبق‌شده ذخیره می‌کند. تنها با گزینه \fB\-P\fP \fB\-\-posix\-captures\fP استفاده می‌شود. .TP .B \fByypmatch\fP آرایه‌ای از l\-valueها که برای نگهداری مقادیر برچسب متناظر با پرانتزهای گیرانداز در قاعده منطبق‌شده استفاده می‌شوند. طول آرایه باید حداقل \fByynmatch * 2\fP باشد (معمولاً \fBYYMAXNMATCH * 2\fP انتخاب خوبی است). تنها با گزینه \fB\-P\fP \fB\-\-posix\-captures\fP استفاده می‌شود. .TP .B \fByystable\fP منسوخ شده است. .TP .B \fByystate\fP یک l\-value که همراه با گزینه \fB\-\-loop\-switch\fP برای ذخیره وضعیت کنونی DFA استفاده می‌شود. .TP .B \fByytarget\fP جدول پرش شامل مقصدهای پرش (نشانی‌های برچسب) برای تمامی گذارها از یک وضعیت. این جدول برای هر وضعیت محلی است. تولید جدول‌های \fByytarget\fP با گزینه \fB\-\-computed\-gotos\fP فعال می‌شود. .UNINDENT .SS "گزینه‌ها (OPTIONS)" .sp برخی از گزینه‌ها دارای \fI\%پیکربندی‌های\fP متناظر هستند، برخی دیگر سراسری بوده و پس از شروع خواندن فایل ورودی توسط re2c قابل تغییر نیستند. گزینه‌های اشکال‌زدایی معمولاً نیازمند ساختن re2c در پیکربندی اشکال‌زدایی هستند. گزینه‌های داخلی برای آزمایش الگوریتم‌های به‌کاررفته در re2c مفید می‌باشند. .INDENT 0.0 .TP .B \fB\-? \-\-help \-h\fP نمایش پیام راهنما. .TP .B \fB\-\-api \fP مشخص کردن API استفاده‌شده توسط کد تولیدی برای برقراری ارتباط با کد تعریف‌شده توسط کاربر. گزینه \fBsimple\fP باید در حالت‌های ساده استفاده شود که نیازی به پر کردن مجدد بافر و ذخیره وضعیت تحلیل‌گر واژگانی وجود ندارد. گزینه \fBrecord\fP باید زمانی استفاده شود که وضعیت تحلیل‌گر واژگانی باید در یک رکورد (struct، class و غیره) ذخیره شود. گزینه \fBgeneric\fP باید در حالت‌های پیچیده‌ای که دو API دیگر به اندازه کافی منعطف نیستند، استفاده شود. .TP .B \fB\-\-bit\-vectors \-b\fP بهینه‌سازی پرش‌های شرطی با استفاده از ماسک‌های بیتی. این گزینه مستلزم \fB\-\-nested\-ifs\fP است\&. .TP .B \fB\-\-captures\fP, \fB\-\-leftmost\-captures\fP فعال‌سازی استخراج تطبیق فرعی با چپ‌ترین گروه‌های گیرانداز حریصانه. نتیجه در یک آرایه \fByybmatch\fP با گنجایش \fB2 * YYMAXNMATCH\fP جمع‌آوری شده، و \fByynmatch\fP روی تعداد گروه‌های قاعده منطبق‌شده تنظیم می‌شود. .TP .B \fB\-\-captvars\fP, \fB\-\-leftmost\-captvars\fP فعال‌سازی استخراج تطبیق فرعی با چپ‌ترین گروه‌های گیرانداز حریصانه. نتیجه در متغیرهای \fByytl\fP و \fByytr\fP برای \fBk\fP\-امین گروه گیرانداز جمع‌آوری می‌شود. .TP .B \fB\-\-case\-insensitive\fP در نظر گرفتن رشته‌های درون گیومه تکی و دوتایی بدون حساسیت به حروف کوچک و بزرگ. .TP .B \fB\-\-case\-inverted\fP معکوس کردن معنای رشته‌های درون گیومه تکی و دوتایی: در نظر گرفتن رشته‌های درون گیومه تکی به عنوان حساس به حروف کوچک و بزرگ و رشته‌های درون گیومه دوتایی به عنوان غیرحساس به حروف کوچک و بزرگ. .TP .B \fB\-\-case\-ranges\fP ادغام حالت‌های متوالی در یک دستور switch در قالب یک بازه به شکل \fBlow ... high\fP\&. این نحو، یک افزونه زبان C/C++ است که توسط کامپایلرهایی مانند GCC، Clang و Tcc پشتیبانی می‌شود. مزیت اصلی نسبت به استفاده از حالت‌های تکی، تولید کد کوچک‌تر و زمان تولید سریع‌تر است، هرچند برای برخی از کامپایلرها مانند Tcc به اندازه باینری کوچک‌تر نیز منجر می‌شود. .TP .B \fB\-\-computed\-gotos \-g\fP بهینه‌سازی پرش‌های شرطی با استفاده از افزونه غیراستاندارد \(dqcomputed goto\(dq (که باید توسط کامپایلر پشتیبانی شود). re2c تنها در موارد پیچیده با انشعاب‌های شرطی فراوان جدول‌های پرش را تولید می‌کند. آستانه پیچیدگی را می‌توان با پیکربندی \fBcgoto:threshold\fP تنظیم کرد. آفست‌های نسبی را می‌توان با پیکربندی \fBcgoto:relative\fP فعال نمود. این گزینه مستلزم \fB\-\-bit\-vectors\fP است\&. .TP .B \fB\-\-computed\-gotos\-relative\fP مشابه \-\-computed\-gotos اما در عوض آفست‌های نسبی را برای جدول‌های پرش تولید می‌کند (که باید توسط کامپایلر پشتیبانی شود). این گزینه مستلزم \fB\-\-computed\-gotos\fP است\&. .TP .B \fB\-\-conditions \-\-start\-conditions \-c\fP فعال‌سازی پشتیبانی از \(dqconditions\(dq مشابه Flex: چندین تحلیل‌گر واژگانی به‌هم‌پیوسته در یک بلوک. این یک جایگزین برای مشخص کردن دستی بلوک‌های مختلف re2c متصل‌شده با \fBgoto\fP یا فراخوانی‌های تابع است. .TP .B \fB\-\-depfile FILE\fP نوشتن اطلاعات وابستگی در \fBFILE\fP در قالب یک قاعده Makefile به شکل \fB : [include\-file ...]\fP\&. این امکان رهگیری وابستگی‌های ساخت را در حضور بلوک‌ها/دستورالعمل‌های \fBinclude\fP فراهم می‌کند، به‌طوری که به‌روزرسانی فایل‌های include باعث بازتولید فایل خروجی می‌شود. این گزینه به گزینه \fB\-\-output\fP وابسته است. .TP .B \fB\-\-ebcdic \-\-ecb \-e\fP تولید یک تحلیل‌گر واژگانی که ورودی را در کدگذاری EBCDIC می‌خواند. re2c فرض می‌کند که محدوده نویسه‌ها 0 \-\- 0xFF و اندازه هر نویسه ۱ بایت است. .TP .B \fB\-\-empty\-class \fP تعریف شیوه برخورد re2c با کلاس‌های نویسه خالی. با \fBmatch\-empty\fP (پیش‌فرض)، کلاس خالی با ورودی خالی تطبیق می‌یابد (که غیرمنطقی است اما سازگار با گذشته است). با \fBmatch\-none\fP کلاس خالی همیشه در تطبیق شکست می‌خورد. با \fBerror\fP کلاس خالی یک خطای کامپایل ایجاد می‌کند. .TP .B \fB\-\-encoding\-policy \fP تعریف شیوه برخورد re2c با جانشین‌های یونیکد. با \fBfail\fP برنامه re2c در صورت مواجهه با یک جانشین با خطا متوقف می‌شود. با \fBsubstitute\fP برنامه re2c بی‌صدا جانشین‌ها را با نقطه کد خطای 0xFFFD جایگزین می‌کند. با \fBignore\fP (پیش‌فرض) re2c با جانشین‌ها مانند نقاط کد عادی رفتار می‌کند. استاندارد یونیکد می‌گوید که جانشین‌های تنها نامعتبرند، اما کتابخانه‌ها و برنامه‌های دنیای واقعی رفتارهای متفاوتی دارند. .TP .B \fB\-\-flex\-syntax \-F\fP پشتیبانی جزئی از نحو Flex: در این حالت، تعاریف نام‌گذاری‌شده نیازی به علامت مساوی و نقطه\-ویرگول پایانی ندارند، و هنگام استفاده باید درون آکولاد قرار گیرند. نام‌های بدون آکولاد به عنوان رشته‌های درون گیومه دوتایی تلقی می‌شوند. .TP .B \fB\-\-goto\-label\fP استفاده از مدل کد \(dqgoto/label\(dq: کدگذاری DFA در قالب بلوک‌های کد برچسب‌دار متصل‌شده با گذارهای \fBgoto\fP میان بلوک‌ها. این تنها برای زبان‌هایی پشتیبانی می‌شود که دارای دستور \fBgoto\fP هستند. .TP .B \fB\-\-header \-\-type\-header \-t HEADER\fP تولید یک فایل \fBHEADER\fP. محتوای این فایل را می‌توان با استفاده از بلوک‌های ویژه \fBheader:on\fP و \fBheader:off\fP تعیین کرد\&. اگر از شرایط استفاده شود، سربرگ تولیدشده به‌طور خودکار یک enum شرطی به آن الصاق خواهد داشت (مگر اینکه یک بلوک صریح \fBconditions\fP وجود داشته باشد). .TP .B \fB\-I PATH\fP افزودن \fBPATH\fP به فهرست مکان‌هایی که هنگام جستجوی فایل‌های include استفاده می‌شوند. این گزینه در ترکیب با بلوک یا دستورالعمل \fBinclude\fP مفید است. re2c به دنبال \fBFILE\fP در دایرکتوری فایل والد و در مکان‌های include مشخص‌شده با گزینه \fB\-I\fP می‌گردد. .TP .B \fB\-\-input \fP نام مستعار منسوخ‌شده برای \fB\-\-api\fP\&. گزینه \fBdefault\fP متناظر با \fBsimple\fP است (در واقع برای بیشتر پیش‌رانه‌ها پیش‌فرض است، اما نه برای همه). گزینه \fBcustom\fP متناظر با \fBgeneric\fP است\&. .TP .B \fB\-\-input\-encoding \fP تعیین شیوه تجزیه عبارت‌های منظم توسط re2c. با \fBascii\fP (پیش‌فرض) re2c ورودی را با کدگذاری ASCII مدیریت می‌کند: هر دنباله‌ای از واحدهای کد، دنباله‌ای از نویسه‌های مستقل ۱ بایتی است. با \fButf8\fP re2c ورودی را با کدگذاری UTF8 مدیریت کرده و نویسه‌های چندبایتی را تشخیص می‌دهد. .TP .B \fB\-\-invert\-captures\fP معکوس کردن معنای گروه‌های گیرانداز و غیرگیرانداز. به‌طور پیش‌فرض \fB(...)\fP گیرانداز و \fB(! ...)\fP غیرگیرانداز است. با این گزینه \fB(! ...)\fP گیرانداز و \fB(...)\fP غیرگیرانداز خواهد بود. .TP .B \fB\-\-lang \fP مشخص کردن زبان مقصد. زبان‌های پشتیبانی‌شده عبارتند از C، D، Go، Haskell، Java، JS، OCaml، Python، Rust، Swift، V، Zig (زبان‌های بیشتری را می‌توان از طریق فایل‌های نحو تعریف‌شده توسط کاربر اضافه کرد، گزینه \fB\-\-syntax\fP را ببینید). گزینه \fBnone\fP پیکربندی‌های نحو پیش‌فرض را غیرفعال می‌کند تا زبان مقصد تعریف‌نشده باقی بماند. .TP .B \fB\-\-location\-format \fP مشخص کردن قالب مکان در پیام‌ها. با \fBgnu\fP مکان‌ها به‌صورت \(aqfilename:line:column: ...\(aq چاپ می‌شوند. با \fBmsvc\fP مکان‌ها به‌صورت \(aqfilename(line,column) ...\(aq چاپ می‌شوند. پیش‌فرض \fBgnu\fP است\&. .TP .B \fB\-\-loop\-switch\fP استفاده از مدل کد \(dqloop/switch\(dq: کدگذاری DFA در قالب یک حلقه بر روی دستور switch، جایی که وضعیت‌های منفرد همان حالت‌های دستور switch هستند. وضعیت در یک متغیر \fByystate\fP ذخیره می‌شود\&. گذارها میان وضعیت‌ها \fByystate\fP را به برچسب case وضعیت مقصد به‌روزرسانی کرده و اجرا را به ابتدای حلقه ادامه می‌دهند..TP .B \fB\-\-nested\-ifs \-s\fP استفاده از دستورهای \fBif\fP تو‌در‌تو به جای دستورهای \fBswitch\fP در پرش‌های شرطی. این کار معمولاً در کامپایلرهای فاقد بهینه‌سازی منجر به ایجاد کد کارآمدتری می‌شود. .TP .B \fB\-\-no\-debug\-info \-i\fP دستورالعمل‌های خط (line directives) را در خروجی قرار نده. این گزینه ممکن است هنگامی که کد تولیدشده در یک سیستم کنترل نسخه نگهداری می‌شود مفید باشد (برای جلوگیری از تفاوت‌ها یا diffهای عظیمِ تولیدشده به‌صورت خودکار بر اثر تغییرات کوچک). .TP .B \fB\-\-no\-generation\-date\fP جلوگیری از درج تاریخ در فایل تولیدشده. .TP .B \fB\-\-no\-version\fP جلوگیری از درج نسخه در فایل تولیدشده. .TP .B \fB\-\-no\-unsafe\fP پوشش \fBunsafe\fP را روی \fBYYPEEK\fP تولید نکن (این گزینه مخصوص Rust است). به دلایل عملکردی، \fBYYPEEK\fP باید از بررسی مرزها (bounds\-checking) خودداری کند، زیرا تحلیل‌گر لغوی (lexer) از قبل بررسی‌های انتهای ورودی را به شیوه‌ای کارآمدتر انجام می‌دهد. کاربر می‌تواند تعریف امنی از \fBYYPEEK\fP ارائه دهد، یا تعریفی که تنها در بیلدهای release ناامن است؛ در چنین حالتی، گزینه \fB\-\-no\-unsafe\fP به جلوگیری از هشدارهای مربوط به بلوک‌های \fBunsafe\fP زائد کمک می‌کند. .TP .B \fB\-\-output \-o OUTPUT\fP فایل \fBOUTPUT\fP را مشخص می‌کند. .TP .B \fB\-\-posix\-captures\fP, \fB\-P\fP استخراج زیرتطابق (submatch) را با گروه‌های ضبط به سبک POSIX فعال می‌کند. نتیجه در یک آرایه \fByybmatch\fP با ظرفیت \fB2 * YYMAXNMATCH\fP جمع‌آوری می‌شود، و \fByynmatch\fP روی تعداد گروه‌ها برای قاعده منطبق‌شده تنظیم می‌گردد. .TP .B \fB\-\-posix\-captvars\fP استخراج زیرتطابق را با گروه‌های ضبط به سبک POSIX فعال می‌کند. نتیجه در متغیرهای \fByytl\fP و \fByytr\fP برای \fBk\fP\-امین گروه ضبط جمع‌آوری می‌شود. .TP .B \fB\-\-recursive\-functions\fP استفاده از مدل کدی مبتنی بر توابع هم‌بازگشتی (co\-recursive)، که در آن هر حالت DFA یک تابع مجزا است که می‌تواند توابع حالت‌های دیگر یا خودش را فراخوانی کند. .TP .B \fB\-\-reusable \-r\fP از نسخه 2.2 منسوخ شده است (بلوک‌های قابل استفاده مجدد اکنون به‌طور پیش‌فرض مجاز هستند). .TP .B \fB\-\-skeleton \-S\fP کد رابط تعریف‌شده توسط کاربر را نادیده گرفته و یک برنامه خودکفای \(dqskeleton\(dq (اسکلت) تولید می‌کند. علاوه‌بر این، فایل‌های ورودی را با رشته‌های مشتق‌شده از دستور زبان باقاعده و نتایج تطابق فشرده‌شده تولید می‌کند که برای تأیید رفتار \(dqskeleton\(dq روی تمام ورودی‌ها استفاده می‌شوند. این گزینه برای یافتن باگ‌ها در بهینه‌سازی‌ها و تولید کد مفید است. این گزینه تنها برای C پشتیبانی می‌شود. .TP .B \fB\-\-storable\-state \-f\fP تولید یک تحلیل‌گر لغوی که می‌تواند وضعیت درونی خود را ذخیره کند. این قابلیت در تحلیل‌گرهای لغوی مدل push مفید است که وقتی ورودی کافی وجود ندارد توسط یک برنامه بیرونی متوقف می‌شوند و سپس با دردسترس قرار گرفتن ورودی بیشتر از سر گرفته می‌شوند. در این حالت کاربران باید علاوه‌بر این، دستورهای اولیه \fBYYGETSTATE\fP و \fBYYSETSTATE\fP را تعریف کنند، و متغیرهای \fByych\fP، \fByyaccept\fP و \fBstate\fP باید بخشی از وضعیت ذخیره‌شده لکسر باشند. .TP .B \fB\-\-syntax FILE\fP پیکربندی‌ها را از \fBFILE\fP مشخص‌شده بارگذاری کرده و آن‌ها را بر روی فایل نحو (syntax) پیش‌فرض اعمال می‌کند. توجه داشته باشید که \fBFILE\fP می‌تواند تنها چند پیکربندی را تعریف کند (اگر برای اصلاح فایل نحو پیش‌فرض استفاده شود)، یا می‌تواند یک بک‌اند زبانی کاملاً جدید را تعریف نماید (در مورد اخیر توصیه می‌شود از گزینه \fB\-\-lang none\fP استفاده کنید). .TP .B \fB\-\-tags \-T\fP استخراج زیرتطابق را با برچسب‌ها (tags) فعال می‌کند. .TP .B \fB\-\-ucs2 \-\-wide\-chars \-w\fP تولید لکسری که ورودی کدگذاری‌شده با UCS2 را می‌خواند. re2c فرض می‌کند که محدوده نویسه‌ها 0 \-\- 0xFFFF و اندازه نویسه ۲ بایت است. این گزینه مستلزم \fB\-\-nested\-ifs\fP\& است. .TP .B \fB\-\-utf8 \-\-utf\-8 \-8\fP تولید لکسری که ورودی با کدگذاری UTF\-8 را می‌خواند. re2c فرض می‌کند که محدوده نویسه‌ها 0 \-\- 0x10FFFF و اندازه نویسه ۱ بایت است. .TP .B \fB\-\-utf16 \-\-utf\-16 \-x\fP تولید لکسری که ورودی کدگذاری‌شده با UTF16 را می‌خواند. re2c فرض می‌کند که محدوده نویسه‌ها 0 \-\- 0x10FFFF و اندازه نویسه ۲ بایت است. این گزینه مستلزم \fB\-\-nested\-ifs\fP\& است. .TP .B \fB\-\-utf32 \-\-unicode \-u\fP تولید لکسری که ورودی کدگذاری‌شده با UTF32 را می‌خواند. re2c فرض می‌کند که محدوده نویسه‌ها 0 \-\- 0x10FFFF و اندازه نویسه ۴ بایت است. این گزینه مستلزم \fB\-\-nested\-ifs\fP\& است. .TP .B \fB\-\-verbose\fP نمایش یک پیام کوتاه در صورت موفقیت. .TP .B \fB\-\-vernum \-V\fP نمایش اطلاعات نسخه در قالب \fBMMmmpp\fP (اصلی، فرعی، وصله). .TP .B \fB\-\-version \-v\fP نمایش اطلاعات نسخه. .TP .B \fB\-\-single\-pass \-1\fP منسوخ شده است. کاری انجام نمی‌دهد (تک‌گذر بودن اکنون رفتار پیش‌فرض است). .UNINDENT .INDENT 0.0 .TP .B \fB\-\-debug\-output \-d\fP درج فراخوانی‌های \fBYYDEBUG\fP در کد تولیدشده. این مورد برای ردیابی اجرای لکسر مفید است. .TP .B \fB\-\-dump\-adfa\fP گزینه اشکال‌زدایی: خروجی دادن DFA پس از تونل‌زنی (tunneling) (در قالب .dot). .TP .B \fB\-\-dump\-cfg\fP گزینه اشکال‌زدایی: خروجی دادن گراف جریان کنترل متغیرهای برچسب (در قالب .dot). .TP .B \fB\-\-dump\-closure\-stats\fP گزینه اشکال‌زدایی: خروجی دادن آمار مربوط به تعداد حالت‌ها در بستار (closure). .TP .B \fB\-\-dump\-dfa\-det\fP گزینه اشکال‌زدایی: خروجی دادن DFA بلافاصله پس از قطعی‌سازی (determinization) (در قالب .dot). .TP .B \fB\-\-dump\-dfa\-min\fP گزینه اشکال‌زدایی: خروجی دادن DFA پس از کمینه‌سازی (minimization) (در قالب .dot). .TP .B \fB\-\-dump\-dfa\-tagopt\fP گزینه اشکال‌زدایی: خروجی دادن DFA پس از بهینه‌سازی‌های برچسب (در قالب .dot). .TP .B \fB\-\-dump\-dfa\-tree\fP گزینه اشکال‌زدایی: خروجی دادن DFA در حال ساخت با حالت‌هایی که به عنوان درخت‌های تاریخچه برچسب نمایش داده می‌شوند (در قالب .dot). .TP .B \fB\-\-dump\-dfa\-raw\fP گزینه اشکال‌زدایی: خروجی دادن DFA در حال ساخت با مجموعه‌حالت‌های بسط‌یافته (در قالب .dot). .TP .B \fB\-\-dump\-interf\fP گزینه اشکال‌زدایی: خروجی دادن جدول تداخل حاصل از تحلیل زنده بودن (liveness analysis) متغیرهای برچسب. .TP .B \fB\-\-dump\-nfa\fP گزینه اشکال‌زدایی: خروجی دادن NFA (در قالب .dot). .TP .B \fB\-\-emit\-dot \-D\fP به جای خروجی عادی، گراف لکسر را در قالب .dot تولید می‌کند. خروجی می‌تواند به کمک Graphviz به یک تصویر تبدیل شود (مثلاً دستورهایی مانند \fBdot \-Tpng \-odfa.png dfa.dot\fP). .UNINDENT .INDENT 0.0 .TP .B \fB\-\-dfa\-minimization \fP گزینه داخلی: الگوریتم کمینه‌سازی DFA مورد استفاده توسط re2c\&. گزینه \fBmoore\fP نشان‌دهنده الگوریتم مور (Moore) است (که پیش‌فرض می‌باشد). گزینه \fBtable\fP نشان‌دهنده الگوریتم \(dqپر کردن جدول\(dq (table filling) است. هر دو الگوریتم باید صرف‌نظر از برچسب‌گذاری مجدد حالت‌ها، DFA یکسانی تولید کنند؛ الگوریتم پر کردن جدول ساده‌تر و بسیار کندتر است و به عنوان پیاده‌سازی مرجع عمل می‌کند. .TP .B \fB\-\-eager\-skip\fP گزینه داخلی: باعث می‌شود لکسر تولیدشده موقعیت ورودی را به‌صورت مشتاقانه (eagerly) پیش ببرد \-\- بلافاصله پس از خواندن نماد ورودی. این گزینه رفتار پیش‌فرض را که در آن موقعیت ورودی به‌صورت تنبل (lazily) \-\- پس از گذار به حالت بعدی \-\- پیش می‌رود، تغییر می‌دهد. .TP .B \fB\-\-no\-lookahead\fP گزینه داخلی، منسوخ‌شده. قبلاً برای فعال کردن الگوریتم TDFA(0) استفاده می‌شد. بر خلاف TDFA(1)، الگوریتم TDFA(0) از پیش‌نگری یک‌نمادی (one\-symbol lookahead) استفاده نمی‌کند. این الگوریتم عملیات‌های ثبات را به جای گذارهای خروجی، روی گذارهای ورودی اعمال می‌کند. ارزیابی‌ها نشان دادند که الگوریتم TDFA(0) نسبت به TDFA(1) کارایی کمتری دارد. .TP .B \fB\-\-no\-optimize\-tags\fP گزینه داخلی: جلوگیری از بهینه‌سازی متغیرهای برچسب (مفید برای اشکال‌زدایی). .TP .B \fB\-\-posix\-closure \fP گزینه داخلی: تعیین الگوریتم کوتاه‌ترین مسیر مورد استفاده برای ساخت بستار اپسیلون (epsilon\-closure) با معناشناسی رفع ابهام POSIX: گزینه \fBgor1\fP (پیش‌فرض) نشان‌دهنده الگوریتم گلدبرگ\-رادزیک (Goldberg\-Radzik) است، و \fBgtop\fP نشان‌دهنده الگوریتم \(dqترتیب توپولوژیکی سراسری\(dq (global topological order) است. .TP .B \fB\-\-posix\-prectable \fP گزینه داخلی: مشخص کردن الگوریتم مورد استفاده برای محاسبه جدول اولویت POSIX. الگوریتم \fBcomplex\fP جدول اولویت را در یک پیمایش از درخت تاریخچه برچسب محاسبه می‌کند و دارای پیچیدگی مرتبه دوم در تعداد حالت‌های TNFA است؛ این گزینه پیش‌فرض است. الگوریتم \fBnaive\fP در بدترین حالت دارای پیچیدگی مرتبه سوم در تعداد حالت‌های TNFA است، اما بسیار ساده‌تر از \fBcomplex\fP بوده و در موارد عادی ممکن است کمی سریع‌تر باشد..TP .B \fB\-\-stadfa\fP گزینهٔ داخلی، منسوخ‌شده. در گذشته برای فعال‌سازی الگوریتم staDFA به کار می‌رفت، که تفاوت آن با TDFA در این است که عملیات ثبات‌ها به جای انتقال‌ها درون وضعیت‌ها قرار می‌گیرد. بنچمارک‌ها نشان دادند که الگوریتم staDFA کارایی کمتری نسبت به TDFA دارد. .TP .B \fB\-\-fixed\-tags \fP گزینهٔ داخلی: مشخص می‌کند که آیا بهینه‌سازی برچسب ثابت (fixed\-tag) باید روی همهٔ برچسب‌ها اعمال شود (\fBall\fP)، هیچ‌یک از آن‌ها (\fBnone\fP)، یا فقط روی برچسب‌های موجود در الحاق بالاترین سطح (\fBtoplevel\fP). مقدار پیش‌فرض \fBall\fP است\&. برچسب‌های \(dqثابت\(dq برچسب‌هایی هستند که در فاصلهٔ ثابتی از برچسبی دیگر (موسوم به \(dqپایه\(dq) قرار دارند. در چنین مواردی تنها نیاز به ردیابی برچسب پایه است، و مقدار برچسب ثابت می‌تواند از مقدار برچسب پایه به علاوهٔ یک آفست ایستا محاسبه شود. برای برچسب‌هایی که تحت جایگزینی یا تکرار هستند، بررسی اینکه آیا برچسب پایه مقدار عدم‌تطابق (no\-match) دارد نیز ضروری است (در این صورت برچسب ثابت نیز صرف‌نظر از آفست، باید روی no\-match تنظیم شود). برای برچسب‌های موجود در الحاق بالاترین سطح، این بررسی لازم نیست، زیرا آن‌ها همیشه تطبیق می‌یابند. .UNINDENT .SS "هشدارها (Warnings)" .sp هشدارها را می‌توان به‌صورت جداگانه فعال یا غیرفعال کرد و یا به یک خطا تبدیل نمود. .INDENT 0.0 .TP .B \fB\-W\fP فعال کردن تمام هشدارها. .TP .B \fB\-Werror\fP تبدیل هشدارها به خطا. توجه داشته باشید که این گزینه به تنهایی هیچ هشداری را فعال نمی‌کند؛ بلکه تنها بر هشدارهایی اثر می‌گذارد که تا کنون فعال شده‌اند یا بعداً فعال خواهند شد. .TP .B \fB\-W\fP فعال کردن \fBwarning\fP\&. .TP .B \fB\-Wno\-\fP غیرفعال کردن \fBwarning\fP\&. .TP .B \fB\-Werror\-\fP فعال کردن \fBwarning\fP و در نظر گرفتن آن به عنوان خطا (این گزینه متضمن \fB\-W\fP است). .TP .B \fB\-Wno\-error\-\fP با این \fBwarning\fP خاص به عنوان خطا برخورد نکن. این گزینه خودِ هشدار را غیرفعال نمی‌کند. .UNINDENT .INDENT 0.0 .TP .B \fB\-Wcondition\-order\fP هشدار در صورتی که برنامهٔ تولیدشده فرضیات ضمنی دربارهٔ شماره‌گذاری شرط‌ها داشته باشد. باید از گزینهٔ \fB\-\-header\fP یا بلوک \fBconditions\fP برای تولید نگاشتی از نام شرط‌ها به شماره‌ها استفاده شود و سپس نام‌های شرطِ تولیدشده به‌صورت خودکار به کار روند. .TP .B \fB\-Wempty\-character\-class\fP هشدار در صورتی که یک عبارت منظم حاوی یک کلاس نویسهٔ خالی باشد. تلاش برای تطبیق یک کلاس نویسهٔ خالی بی‌معنی است: همیشه باید ناموفق باشد. با این حال، به دلایل سازگاری عقبرو، re2c کلاس‌های نویسهٔ خالی را مجاز دانسته و با آن‌ها مانند رشته‌های خالی رفتار می‌کند. از گزینهٔ \fB\-\-empty\-class\fP برای تغییر رفتار پیش‌فرض استفاده کنید. .TP .B \fB\-Wmatch\-empty\-string\fP هشدار در صورتی که یک قاعده پوچ‌پذیر باشد (با یک رشتهٔ خالی تطبیق یابد). اگر تحلیل‌گر لغوی درون یک حلقه اجرا شود و تطبیق رشتهٔ خالی غیرعمدی باشد، تحلیل‌گر لغوی ممکن است به‌طور غیرمنتظره در یک حلقهٔ بی‌پایان متوقف شود. .TP .B \fB\-Wswapped\-range\fP هشدار در صورتی که کران پایین یک بازه بزرگ‌تر از کران بالای آن باشد. رفتار پیش‌فرض این است که بدون هشدار، جای کران‌های بازه جابه‌جا می‌شود. .TP .B \fB\-Wundefined\-control\-flow\fP هشدار در صورتی که برخی از رشته‌های ورودی باعث جریان کنترل تعریف‌نشده در تحلیل‌گر لغوی شوند (الگوهای دارای اشکال گزارش می‌شوند). این یک اشتباه خطرناک و رایج است. این مشکل را می‌توان به سادگی با افزودن قاعدهٔ پیش‌فرض \fB*\fP که کمترین اولویت را دارد، با هر واحد کد مطابقت دارد و همیشه یک واحد کد را مصرف می‌کند، برطرف ساخت. .TP .B \fB\-Wunreachable\-rules\fP هشدار دربارهٔ قواعدی که توسط قواعد دیگر پوشانده شده‌اند (shadowed) و هرگز تطبیق نخواهند یافت. .TP .B \fB\-Wdeprecated\-eof_rule\fP هشدار دربارهٔ قواعد مستقل پایان ورودی \fB$\fP که بر اثر تغییرات آینده از کار خواهند افتاد و نیاز به اصلاح دارند. در حال حاضر این قواعد هنگام تداخل با قواعد دیگر دارای اولویت هستند، اما پس از معرفی نماد عمومی پایان ورودی \fB$\fP، ترتیب اولویت تغییر خواهد کرد و این قواعد توسط قواعد دیگر پوشانده خواهند شد. .TP .B \fB\-Wuseless\-escape\fP هشدار در صورتی که یک نماد به اشتباه گریزدهی شده باشد (دارای escape باشد). به‌طور پیش‌فرض، re2c چنین گریزهایی را بی‌صدا نادیده می‌گیرد، اما این حالت می‌تواند نشان‌دهندهٔ یک اشتباه تایپی یا خطا در توالی گریز (escape sequence) باشد. .TP .B \fB\-Wnondeterministic\-tags\fP هشدار در صورتی که یک برچسب دارای درجهٔ \fBn\fPام از غیرقطعی بودن باشد، که در آن \fBn\fP بزرگ‌تر از ۱ است. .TP .B \fB\-Wsentinel\-in\-midrule\fP هشدار در صورتی که نماد نگهبان در میانهٔ یک قاعده رخ دهد \-\-\- این حالت ممکن است باعث خواندن داده‌ها فراتر از انتهای بافر، کرش کردن یا آسیب دیدن حافظه در تحلیل‌گر لغوی تولیدشده شود. این هشدار تنها زمانی اعمال می‌شود که روش نگهبان برای بررسی پایان ورودی استفاده شده باشد. در صورتی که از پیکربندی \fBre2c:sentinel\fP استفاده شود، این مورد به یک خطا تبدیل می‌گردد. .TP .B \fB\-Wundefined\-syntax\-config\fP هشدار در صورتی که فایل نحو مشخص‌شده با گزینهٔ \fB\-\-syntax\fP فاقد تعاریف برخی از پیکربندی‌ها باشد. این ویژگی به نگهداری فایل‌های نحو تعریف‌شده توسط کاربر کمک می‌کند: اگر انتشار جدیدی پیکربندی‌های جدیدی اضافه کند، فایل نحو قدیمی یک هشدار صادر خواهد کرد و کاربر مطلع می‌شود. اگر برخی پیکربندی‌ها استفاده نمی‌شوند و نیازی به تعریف ندارند، باید به صراحت روی \fB\fP تنظیم شوند\&. .UNINDENT.SS "فایل‌های نحو (Syntax files)" .sp پشتیبانی از زبان‌های گوناگون در re2c بر پایه ایده \fIsyntax files\fP (فایل‌های نحو) استوار است\&. یک فایل نحو، یک فایل پیکربندی است که نحو زبان مقصد را تعریف می‌کند \-\- نه تمام زبان، بلکه بخش کوچکی از آن را که توسط کد تولیدشده استفاده می‌شود. فایل‌های نحو re2c را بسیار انعطاف‌پذیر می‌سازند، اما نباید به عنوان جایگزینی برای پیکربندی‌های \fBre2c:\fP استفاده شوند: هدف آن‌ها تعریف نحو زبان مقصد است، نه سفارشی‌سازی یک تحلیل‌گر لغوی (lexer) خاص. تمام زبان‌های پشتیبانی‌شده دارای فایل‌های نحو پیش‌فرضی هستند که بخشی از توزیع برنامه می‌باشند (زیردایرکتوری \fBinclude/syntax\fP را ببینید)؛ آن‌ها همچنین در باینری re2c تعبیه شده‌اند. کاربران می‌توانند یک فایل نحو سفارشی ارائه دهند که چند پیکربندی را برای یکی از زبان‌های پشتیبانی‌شده بازنویسی کند، یا می‌توانند تمام پیکربندی‌ها را از نو تعریف کنند (در این حالت باید از گزینه \fB\-\-lang none\fP استفاده شود). فایل‌های نحو حاوی چهار نوع پیکربندی مختلف هستند: فهرست‌های ویژگی، پیکربندی‌های زبان، پیکربندی‌های درجا و الگوهای کد. .sp \fBفهرست‌های ویژگی (Feature lists)\fP .INDENT 0.0 .INDENT 3.5 چند پیکربندی فهرستی، ویژگی‌های مختلف پشتیبانی‌شده توسط یک بک‌اند مشخص را تعریف می‌کنند، تا در صورتی که کاربر برای فعال‌سازی یک ویژگی پشتیبانی‌نشده تلاش کند، re2c خطای واضحی صادر نماید: .INDENT 0.0 .TP .B \fBsupported_apis\fP فهرستی از APIهای پشتیبانی‌شده با مقادیر ممکن \fBsimple\fP، \fBrecord\fP، \fBgeneric\fP\&. .TP .B \fBsupported_api_styles\fP فهرستی از سبک‌های API پشتیبانی‌شده با مقادیر ممکن \fBfunctions\fP، \fBfree\-form\fP\&. .TP .B \fBsupported_code_models\fP فهرستی از مدل‌های کد پشتیبانی‌شده با مقادیر ممکن \fBgoto\-label\fP، \fBloop\-switch\fP، \fBrecursive\-functions\fP\&. .TP .B \fBsupported_targets\fP فهرستی از مقصدهای تولید کد پشتیبانی‌شده با مقادیر ممکن \fBcode\fP، \fBdot\fP، \fBskeleton\fP\&. .TP .B \fBsupported_features\fP فهرستی از ویژگی‌های پشتیبانی‌شده با مقادیر ممکن \fBnested\-ifs\fP، \fBbitmaps\fP، \fBcomputed\-gotos\fP، \fBcase\-ranges\fP، \fBmonadic\fP، \fBunsafe\fP، \fBtags\fP، \fBcaptures\fP، \fBcaptvars\fP\&. .UNINDENT .UNINDENT .UNINDENT .sp \fBپیکربندی‌های زبان (Language configurations)\fP .INDENT 0.0 .INDENT 3.5 چند پیکربندی بولی، ویژگی‌هایی از زبان مقصد را توصیف می‌کنند که بر تجزیه‌کننده (parser) و تولیدکننده کد re2c تأثیر می‌گذارند: .INDENT 0.0 .TP .B \fBsemicolons\fP غیر صفر اگر زبان پس از دستورها از سمی‌کالن (نقطه‌ویرگول) استفاده می‌کند. .TP .B \fBbacktick_quoted_strings\fP غیر صفر اگر زبان رشته‌های محصور در بک‌تیک دارد. .TP .B \fBsingle_quoted_strings\fP غیر صفر اگر زبان رشته‌های محصور در نقل‌قول تکی دارد. .TP .B \fBindentation_sensitive\fP غیر صفر اگر زبان به دندانه‌گذاری (indentation) حساس است. .TP .B \fBwrap_blocks_in_braces\fP غیر صفر اگر دستورهای مرکب باید درون آکوالاد محصور شوند. .UNINDENT .UNINDENT .UNINDENT .sp \fBپیکربندی‌های درجا (Inplace configurations)\fP .INDENT 0.0 .INDENT 3.5 فایل‌های نحو، مقادیر اولیه تمام پیکربندی‌های \fBre2c:\fP را تعریف می‌کنند، زیرا ممکن است این مقادیر برای زبان‌های مختلف متفاوت باشند. برای فهرست کامل تمام پیکربندی‌های درجا و معنای آن‌ها، بخش پیکربندی‌ها را ببینید. .UNINDENT .UNINDENT .sp \fBالگوهای کد (Code templates)\fP .INDENT 0.0 .INDENT 3.5 الگوهای کد نحو زبان مقصد را تعریف می‌کنند. آن‌ها در یک زبان ساده خاص‌دامنه با گرامر رسمی زیر نوشته می‌شوند: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C code\-template :: name \(aq=\(aq code\-exprs \(aq;\(aq | CODE_TEMPLATE \(aq;\(aq | \(aq\(aq \(aq;\(aq code\-exprs :: | code\-exprs code\-expr code\-expr :: STRING | VARIABLE | optional | list optional :: \(aq(\(aq CONDITIONAL \(aq?\(aq code\-exprs \(aq)\(aq | \(aq(\(aq CONDITIONAL \(aq?\(aq code\-exprs \(aq:\(aq code\-exprs \(aq)\(aq list :: \(aq[\(aq VARIABLE \(aq:\(aq code\-exprs \(aq]\(aq | \(aq[\(aq VARIABLE \(aq{\(aq NUMBER \(aq}\(aq \(aq:\(aq code\-exprs \(aq]\(aq | \(aq[\(aq VARIABLE \(aq{\(aq NUMBER \(aq,\(aq NUMBER \(aq}\(aq \(aq:\(aq code\-exprs \(aq]\(aq .ft P .fi .UNINDENT .UNINDENT .sp یک الگوی کد دنباله‌ای از رشته‌های لفظی، متغیرها، عناصر اختیاری و فهرست‌ها، یا ارجاعی به یک الگوی کد دیگر، یا مقدار ویژه \fB\fP است\&. متغیرها جای‌نگه‌دارهایی هستند که در طول مرحله تولید کد جایگزین می‌شوند. متغیرهای فهرستی خاص هستند: هنگام بسط الگوهای فهرستی، re2c عبارت‌های سمت راست دو‌نقطه را چند بار تکرار می‌کند، و هر بار رخدادهای متغیر فهرستی را با مقداری مختص به این تکرار جایگزین می‌نماید. فهرست‌ها دارای کران‌های اختیاری هستند (مقادیر منفی از انتها شمرده می‌شوند، برای نمونه \fB\-1\fP به معنای آخرین عنصر است). نام‌های شرطی با یک نقطه آغاز می‌شوند. هر دو مورد شرط‌ها و متغیرها می‌توانند محلی (مختص به الگوی کد داده‌شده) یا سراسری (مجاز در تمام الگوهای کد) باشند. هنگامی که re2c یک فایل نحو را می‌خواند، بررسی می‌کند که هر الگوی کد فقط از متغیرها و شرط‌هایی استفاده کند که در آن مجاز هستند. .sp برای نمونه، الگوی کد زیر ساختار if\-then\-else را برای یک زبان شبه C تعریف می‌کند: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C code:if_then_else = [branch{0}: topindent \(dqif \(dq cond \(dq {\(dq nl indent [stmt: stmt] dedent] [branch{1:\-1}: topindent \(dq} else\(dq (.cond ? \(dq if \(dq cond) \(dq {\(dq nl indent [stmt: stmt] dedent] topindent \(dq}\(dq nl; .ft P .fi .UNINDENT .UNINDENT .sp در اینجا \fBbranch\fP یک متغیر فهرستی است: \fBbranch{0}\fP به شاخه نخست بسط می‌یابد (که خاص است، زیرا بخش \fBelse\fP ندارد)، و \fBbranch{1:\-1}\fP به تمام شاخه‌های باقی‌مانده (در صورت وجود) بسط می‌یابد. \fBstmt\fP نیز یک متغیر فهرستی است: \fB[stmt: stmt]\fP یک فهرست تودرتو است که به فهرستی از دستورها در بدنه شاخه جاری بسط می‌یابد. \fBtopindent\fP، \fBindent\fP، \fBdedent\fP و \fBnl\fP متغیرهای سراسری هستند، و \fB\&.cond\fP یک شرط محلی است (معنای آن‌ها در ادامه شرح داده شده است). این الگوی کد می‌تواند کد زیر را تولید کند: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C if x { // do something } else if y { // do something else } else { // don\(aqt do anything } .ft P .fi .UNINDENT .UNINDENT .sp در اینجا فهرستی از تمام الگوهای کد پشتیبانی‌شده توسط re2c همراه با متغیرها و شرط‌های محلی آن‌ها آمده است. توجه داشته باشید که یک تعریف خاص ممکن است از متغیرها و شرط‌های محلی استفاده کند، اما الزامی به آن ندارد. هر الگوی کد استفاده‌نشده باید بر روی \fB\fP تنظیم شود\&. .INDENT 0.0.TP .B \fBcode:var_local\fP اعلان یا تعریف یک متغیر محلی. متغیرهای پشتیبانی‌شده: \fBtype\fP (نوع متغیر)، \fBname\fP (نام آن) و \fBinit\fP (مقدار اولیه، در صورت وجود). شرط‌ها: \fB\&.init\fP (در صورت وجود مقداردهی اولیه درست است). .TP .B \fBcode:var_global\fP مشابه \fBcode:var_local\fP، با این تفاوت که در بالاترین سطح (top\-level) استفاده می‌شود. .TP .B \fBcode:const_local\fP تعریف یک ثابت محلی. متغیرهای پشتیبانی‌شده: \fBtype\fP (نوع ثابت)، \fBname\fP (نام آن) و \fBinit\fP (مقدار اولیه). .TP .B \fBcode:const_global\fP مشابه \fBcode:const_local\fP، با این تفاوت که در بالاترین سطح (top\-level) استفاده می‌شود. .TP .B \fBcode:array_local\fP تعریف یک آرایه (جدول) محلی. متغیرهای پشتیبانی‌شده: \fBtype\fP (نوع عناصر آرایه)، \fBname\fP (نام آرایه)، \fBsize\fP (اندازه آن)، \fBrow\fP (یک متغیر فهرستی که به خودی خود کدی تولید نمی‌کند، بلکه عبارت فهرست را به تعداد سطرهای جدول بسط می‌دهد) و \fBelem\fP (یک متغیر فهرستی که به تمام عناصر جدول در سطر جاری بسط می‌یابد \-\- برای تودرتو شدن درون فهرست \fBrow\fP در نظر گرفته شده است). شرط پشتیبانی‌شده: \fB\&.const\fP (اگر آرایه تغییرناپذیر باشد درست است). .TP .B \fBcode:array_global\fP مشابه \fBcode:array_local\fP، با این تفاوت که در بالاترین سطح (top\-level) استفاده می‌شود. .TP .B \fBcode:array_elem\fP ارجاع به عنصری از یک آرایه (جدول). متغیرهای پشتیبانی‌شده: \fBarray\fP (نام آرایه) و \fBindex\fP (شاخص عنصر). .TP .B \fBcode:enum\fP تعریف یک شمارش (enumeration) (می‌تواند با استفاده از یک ساختار زبانی خاص برای شمارش‌ها، یا صرفاً به صورت چند ثابت مستقل تعریف شود). متغیرهای پشتیبانی‌شده عبارتند از \fBtype\fP (نوع شمارش تعریف‌شده توسط کاربر یا نوع ثابت‌ها)، \fBelem\fP (متغیر فهرستی که به نام هر عضو بسط می‌یابد) و \fBinit\fP (مقداردهی اولیه برای هر عضو). شرط‌ها: \fB\&.init\fP (در صورت وجود مقداردهی اولیه درست است). .TP .B \fBcode:enum_elem\fP عنصر شمارش (عضوی از یک نوع شمارشی تعریف‌شده توسط کاربر یا نام یک ثابت، بسته به نحوه تعریف \fBcode:enum\fP). متغیرهای پشتیبانی‌شده عبارتند از \fBname\fP (نام عنصر) و \fBtype\fP (نوع آن). .TP .B \fBcode:assign\fP دستور انتساب (assignment). متغیرهای پشتیبانی‌شده عبارتند از \fBlhs\fP (سمت چپ) و \fBrhs\fP (سمت راست). .TP .B \fBcode:type_int\fP نوع عدد صحیح علامت‌دار (signed integer). .TP .B \fBcode:type_uint\fP نوع عدد صحیح بدون علامت (unsigned integer). .TP .B \fBcode:type_yybm\fP نوع عناصر موجود در جدول \fByybm\fP. .TP .B \fBcode:type_yytarget\fP نوع عناصر موجود در جدول \fByytarget\fP. .TP .B \fBcode:type_yyctable\fP نوع عناصر موجود در جدول \fByyctable\fP. .TP .B \fBcode:cmp_eq\fP عملگر «برابر» (\(dqequals\(dq). .TP .B \fBcode:cmp_ne\fP عملگر «نابرابر» (\(dqnot equals\(dq). .TP .B \fBcode:cmp_lt\fP عملگر «کوچک‌تر از» (\(dqless than\(dq). .TP .B \fBcode:cmp_gt\fP عملگر «بزرگ‌تر از» (\(dqgreater than\(dq). .TP .B \fBcode:cmp_le\fP عملگر «کوچک‌تر یا مساوی» (\(dqless or equal\(dq). .TP .B \fBcode:cmp_ge\fP عملگر «بزرگ‌تر یا مساوی» (\(dqgreater or equal\(dq). .TP .B \fBcode:if_then_else\fP دستور if\-then\-else با یک یا چند شاخه. متغیرهای پشتیبانی‌شده: \fBbranch\fP (یک متغیر فهرستی که خود کدی تولید نمی‌کند، بلکه عبارت فهرست را به تعداد شاخه‌ها بسط می‌دهد)، \fBcond\fP (شرط شاخه جاری) و \fBstmt\fP (یک متغیر فهرستی که به تمام دستورهای شاخه جاری بسط می‌یابد). شرط‌ها: \fB\&.cond\fP (اگر شاخه جاری دارای شرط باشد درست است)، \fB\&.many\fP (اگر بیش از یک شاخه وجود داشته باشد درست است). .TP .B \fBcode:if_then_else_oneline\fP یک مورد خاص از \fBcode:if_then_else\fP برای زمانی که تمام شاخه‌ها دستورهای تک‌خطی دارند. اگر این مقدار \fB\fP باشد، به جای آن از \fBcode:if_then_else\fP استفاده می‌شود. .TP .B \fBcode:switch\fP یک دستور switch با یک یا چند مورد (case). متغیرهای پشتیبانی‌شده: \fBexpr\fP (عبارتی که switch روی آن انجام می‌شود) و \fBcase\fP (یک متغیر فهرستی که به تمام گروه‌های case به همراه بلوک‌های کدشان بسط می‌یابد). .TP .B \fBcode:switch_cases\fP گروهی از موارد switch که به یک بلوک کد واحد نگاشت می‌شوند. متغیرهای پشتیبانی‌شده عبارتند از \fBcase\fP (یک متغیر فهرستی که به تمام موارد در این گروه بسط می‌یابد) و \fBstmt\fP (یک متغیر فهرستی که به تمام دستورها در بلوک کد بسط می‌یابد). .TP .B \fBcode:switch_cases_oneline\fP یک مورد خاص از \fBcode:switch_cases\fP برای زمانی که بلوک کد شامل یک دستور تک‌خطی واحد است. اگر این مقدار \fB\fP باشد، به جای آن از \fBcode:switch_cases\fP استفاده می‌شود. .TP .B \fBcode:switch_case_range\fP یک مورد (case) منفرد از switch که محدوده‌ای از مقادیر را پوشش می‌دهد (احتمالاً شامل تنها یک مقدار). متغیر پشتیبانی‌شده: \fBval\fP (یک متغیر فهرستی که به تمام مقادیر موجود در محدوده بسط می‌یابد). شرط‌های پشتیبانی‌شده: \fB\&.many\fP (اگر بیش از یک مقدار در محدوده وجود داشته باشد درست است) و \fB\&.char_literals\fP (اگر یک switch روی لیترال‌های نویسه‌ای باشد درست است \-\- برخی زبان‌ها نحو ویژه‌ای برای این مورد ارائه می‌دهند). .TP .B \fBcode:switch_case_default\fP مورد پیش‌فرض (default) در دستور switch. .TP .B \fBcode:loop\fP حلقه‌ای که تا ابد اجرا می‌شود (مگر اینکه از درون بدنه حلقه متوقف شود). متغیرهای پشتیبانی‌شده: \fBlabel\fP (برچسب حلقه)، \fBstmt\fP (یک متغیر فهرستی که به تمام دستورهای درون بدنه حلقه بسط می‌یابد). .TP .B \fBcode:continue\fP دستور continue. متغیرهای پشتیبانی‌شده: \fBlabel\fP (برچسبی که اجرا باید از آن ادامه یابد). .TP .B \fBcode:goto\fP دستور goto. متغیرهای پشتیبانی‌شده: \fBlabel\fP (برچسب مقصد پرش). .TP .B \fBcode:cgoto\fP دستور \fBgoto\fP محاسباتی (computed). متغیرهای پشتیبانی‌شده: \fBarray\fP (جدول حاوی اطلاعات \fBgoto\fP محاسباتی)، \fBindex\fP (شاخص عنصر در جدول) و \fBbase\fP (برچسب پایه، فقط در صورتی استفاده می‌شود که \fB\&.cgoto.relative\fP درست باشد). .TP .B \fBcode:cgoto:data\fP عبارت مقداردهی اولیه برای یک عنصر منفرد در جدول \fBgoto\fP محاسباتی. متغیرهای پشتیبانی‌شده: \fBlabel\fP (برچسبی که برای مقداردهی اولیه به عنصر جاری استفاده می‌شود)، \fBtype\fP (نوع زیربنایی عناصر موجود در جدول) و \fBbase\fP (برچسب پایه \- فقط در صورتی استفاده می‌شود که \fB\&.cgoto.relative\fP درست باشد). .TP .B \fBcode:fndecl\fP اعلان تابع (function declaration). متغیرهای پشتیبانی‌شده: \fBname\fP (نام تابع)، \fBtype\fP (نوع بازگشتی)، \fBthrow\fP (استثناهای پرتاب‌شده توسط این تابع، که به پیکربندی \fBre2c:yyfn:throw\fP نگاشت می‌شود)، \fBarg\fP (یک متغیر فهرستی که خود کدی تولید نمی‌کند، بلکه عبارت فهرست را به تعداد آرگومان‌های تابع بسط می‌دهد)، \fBargname\fP (نام آرگومان جاری)، \fBargtype\fP (نوع آرگومان جاری). شرط: \fB\&.type\fP (درست است اگر این تابع غیر void باشد). .TP .B \fBcode:fndef\fP مشابه \fBcode:fndecl\fP، اما برای تعریف تابع به کار می‌رود؛ بنابراین دارای یک متغیر فهرستی اضافی به نام \fBstmt\fP است که به تمام دستورهای درون بدنه تابع بسط می‌یابد. .TP .B \fBcode:fncall\fP دستور فراخوانی تابع. متغیرهای پشتیبانی‌شده: \fBname\fP (نام تابع)، \fBretval\fP (مقدار چپ یا l\-value که مقدار بازگشتی در آن ذخیره می‌شود، در صورت وجود) و \fBarg\fP (یک متغیر فهرستی که به تمام آرگومان‌های تابع بسط می‌یابد). شرط‌ها: \fB\&.args\fP (درست است اگر تابع دارای آرگومان باشد) و \fB\&.retval\fP (درست است اگر مقدار بازگشتی نیاز به ذخیره شدن داشته باشد). .TP .B \fBcode:tailcall\fP دستور فراخوانی دم (tail call). متغیرهای پشتیبانی‌شده: \fBname\fP (نام تابع)، و \fBarg\fP (یک متغیر فهرستی که به تمام آرگومان‌های تابع بسط می‌یابد). شرط‌ها: \fB\&.args\fP (درست است اگر تابع دارای آرگومان باشد) و \fB\&.retval\fP (درست است اگر این یک تابع غیر void باشد). .TP .B \fBcode:recursive_functions\fP بدنه برنامه با مدل کد \fB\-\-recursive\-functions\fP. متغیرهای پشتیبانی‌شده: \fBfn\fP (یک متغیر فهرستی که خود کدی تولید نمی‌کند، بلکه عبارت فهرست را به تعداد توابع بسط می‌دهد)، \fBfndecl\fP (اعلان تابع جاری) و \fBfndef\fP (تعریف تابع جاری)..TP .B \fBcode:fingerprint\fP اثرانگشت (fingerprint) در بالای فایل خروجی تولیدشده. متغیرهای پشتیبانی‌شده: \fBver\fP (نسخهٔ re2c که برای تولید این خروجی استفاده شده است) و \fBdate\fP (تاریخ تولید). .TP .B \fBcode:line_info\fP قالب دستورالعمل‌های خط (اگر روی \fB\fP تنظیم شود، هیچ دستورالعملی تولید نمی‌شود). متغیرهای پشتیبانی‌شده: \fBline\fP (شمارهٔ خط) و \fBfile\fP (نام فایل). .TP .B \fBcode:abort\fP عبارتی که اجرای برنامه را متوقف (abort) می‌کند. .TP .B \fBcode:yydebug\fP عبارت \fBYYDEBUG\fP، احتمالاً تخصیص‌یافته برای APIهای مختلف. متغیرهای پشتیبانی‌شده: \fBYYDEBUG\fP، \fByyrecord\fP، \fByych\fP (که با پیکربندی‌های متناظر \fBre2c:\fP مطابقت دارند)، \fBstate\fP (شمارهٔ وضعیت DFA). .TP .B \fBcode:yypeek\fP عبارت \fBYYPEEK\fP، احتمالاً تخصیص‌یافته برای APIهای مختلف. متغیرهای پشتیبانی‌شده: \fBYYPEEK\fP، \fBYYCTYPE\fP، \fBYYINPUT\fP، \fBYYCURSOR\fP، \fByyrecord\fP، \fByych\fP (که با پیکربندی‌های متناظر \fBre2c:\fP مطابقت دارند). شرط‌ها: \fB\&.cast\fP (درست درصورتی‌که \fBre2c:yych:conversion\fP روی مقداری غیر از صفر تنظیم شده باشد). .TP .B \fBcode:yyskip\fP عبارت \fBYYSKIP\fP، احتمالاً تخصیص‌یافته برای APIهای مختلف. متغیرهای پشتیبانی‌شده: \fBYYSKIP\fP، \fBYYCURSOR\fP، \fByyrecord\fP (که با پیکربندی‌های متناظر \fBre2c:\fP مطابقت دارند). .TP .B \fBcode:yybackup\fP عبارت \fBYYBACKUP\fP، احتمالاً تخصیص‌یافته برای APIهای مختلف. متغیرهای پشتیبانی‌شده: \fBYYBACKUP\fP، \fBYYCURSOR\fP، \fBYYMARKER\fP، \fByyrecord\fP (که با پیکربندی‌های متناظر \fBre2c:\fP مطابقت دارند). .TP .B \fBcode:yybackupctx\fP عبارت \fBYYBACKUPCTX\fP، احتمالاً تخصیص‌یافته برای APIهای مختلف. متغیرهای پشتیبانی‌شده: \fBYYBACKUPCTX\fP، \fBYYCURSOR\fP، \fBYYCTXMARKER\fP، \fByyrecord\fP (که با پیکربندی‌های متناظر \fBre2c:\fP مطابقت دارند). .TP .B \fBcode:yyskip_yypeek\fP عبارت ترکیبی \fBcode:yyskip\fP و \fBcode:yypeek\fP (به‌طور پیش‌فرض \fBcode:yyskip\fP و به‌دنبال آن \fBcode:yypeek\fP). .TP .B \fBcode:yypeek_yyskip\fP عبارت ترکیبی \fBcode:yypeek\fP و \fBcode:yyskip\fP (به‌طور پیش‌فرض \fBcode:yypeek\fP و به‌دنبال آن \fBcode:yyskip\fP). .TP .B \fBcode:yyskip_yybackup\fP عبارت ترکیبی \fBcode:yyskip\fP و \fBcode:yybackup\fP (به‌طور پیش‌فرض \fBcode:yyskip\fP و به‌دنبال آن \fBcode:yybackup\fP). .TP .B \fBcode:yybackup_yyskip\fP عبارت ترکیبی \fBcode:yybackup\fP و \fBcode:yyskip\fP (به‌طور پیش‌فرض \fBcode:yybackup\fP و به‌دنبال آن \fBcode:yyskip\fP). .TP .B \fBcode:yybackup_yypeek\fP عبارت ترکیبی \fBcode:yybackup\fP و \fBcode:yypeek\fP (به‌طور پیش‌فرض \fBcode:yybackup\fP و به‌دنبال آن \fBcode:yypeek\fP). .TP .B \fBcode:yyskip_yybackup_yypeek\fP عبارت ترکیبی \fBcode:yyskip\fP، \fBcode:yybackup\fP و \fBcode:yypeek\fP (به‌طور پیش‌فرض \(ga\(gacode:yyskip\(ga\(ga و به‌دنبال آن \fBcode:yybackup\fP و پس از آن \fBcode:yypeek\fP). .TP .B \fBcode:yybackup_yypeek_yyskip\fP عبارت ترکیبی \fBcode:yybackup\fP، \fBcode:yypeek\fP و \fBcode:yyskip\fP (به‌طور پیش‌فرض \(ga\(gacode:yybackup\(ga\(ga و به‌دنبال آن \fBcode:yypeek\fP و پس از آن \fBcode:yyskip\fP). .TP .B \fBcode:yyrestore\fP عبارت \fBYYRESTORE\fP، احتمالاً تخصیص‌یافته برای APIهای مختلف. متغیرهای پشتیبانی‌شده: \fBYYRESTORE\fP، \fBYYCURSOR\fP، \fBYYMARKER\fP، \fByyrecord\fP (که با پیکربندی‌های متناظر \fBre2c:\fP مطابقت دارند). .TP .B \fBcode:yyrestorectx\fP عبارت \fBYYRESTORECTX\fP، احتمالاً تخصیص‌یافته برای APIهای مختلف. متغیرهای پشتیبانی‌شده: \fBYYRESTORECTX\fP، \fBYYCURSOR\fP، \fBYYCTXMARKER\fP، \fByyrecord\fP (که با پیکربندی‌های متناظر \fBre2c:\fP مطابقت دارند). .TP .B \fBcode:yyrestoretag\fP عبارت \fBYYRESTORETAG\fP، احتمالاً تخصیص‌یافته برای APIهای مختلف. متغیرهای پشتیبانی‌شده: \fBYYRESTORETAG\fP، \fBYYCURSOR\fP، \fByyrecord\fP (که با پیکربندی‌های متناظر \fBre2c:\fP مطابقت دارند)، \fBtag\fP (نام متغیر برچسب که برای بازیابی موقعیت استفاده می‌شود). .TP .B \fBcode:yyshift\fP عبارت \fBYYSHIFT\fP، احتمالاً تخصیص‌یافته برای APIهای مختلف. متغیرهای پشتیبانی‌شده: \fBYYSHIFT\fP، \fBYYCURSOR\fP، \fByyrecord\fP (که با پیکربندی‌های متناظر \fBre2c:\fP مطابقت دارند)، \fBoffset\fP (تعداد واحدهای کد برای تغییر مکان موقعیت فعلی). .TP .B \fBcode:yyshiftstag\fP عبارت \fBYYSHIFTSTAG\fP، احتمالاً تخصیص‌یافته برای APIهای مختلف. متغیرهای پشتیبانی‌شده: \fBYYSHIFTSTAG\fP، \fByyrecord\fP، \fBnegative\fP (که با پیکربندی‌های متناظر \fBre2c:\fP مطابقت دارند)، \fBtag\fP (متغیر برچسب که باید تغییر مکان داده شود)، \fBoffset\fP (تعداد واحدهای کد برای تغییر مکان). شرط‌ها: \fB\&.nested\fP (درست درصورتی‌که این یک برچسب تو‌در‌تو باشد \-\- در این حالت مقدار آن ممکن است برابر با \fBre2c:tags:negative\fP باشد که نباید تغییر مکان یابد). .TP .B \fBcode:yyshiftmtag\fP عبارت \fBYYSHIFTMTAG\fP، احتمالاً تخصیص‌یافته برای APIهای مختلف. متغیرهای پشتیبانی‌شده: \fBYYSHIFTMTAG\fP (که با پیکربندی متناظر \fBre2c:\fP مطابقت دارد)، \fBtag\fP (متغیر برچسب که باید تغییر مکان یابد)، \fBoffset\fP (تعداد واحدهای کد برای تغییر مکان). .TP .B \fBcode:yystagp\fP عبارت \fBYYSTAGP\fP، احتمالاً تخصیص‌یافته برای APIهای مختلف. متغیرهای پشتیبانی‌شده: \fBYYSTAGP\fP، \fBYYCURSOR\fP، \fByyrecord\fP (که با پیکربندی‌های متناظر \fBre2c:\fP مطابقت دارند)، \fBtag\fP (متغیر برچسب که باید به‌روزرسانی شود). .TP .B \fBcode:yymtagp\fP عبارت \fBYYMTAGP\fP، احتمالاً تخصیص‌یافته برای APIهای مختلف. متغیرهای پشتیبانی‌شده: \fBYYMTAGP\fP (که با پیکربندی متناظر \fBre2c:\fP مطابقت دارد)، \fBtag\fP (متغیر برچسب که باید به‌روزرسانی شود). .TP .B \fBcode:yystagn\fP عبارت \fBYYSTAGN\fP، احتمالاً تخصیص‌یافته برای APIهای مختلف. متغیرهای پشتیبانی‌شده: \fBYYSTAGN\fP، \fBnegative\fP، \fByyrecord\fP (که با پیکربندی‌های متناظر \fBre2c:\fP مطابقت دارند)، \fBtag\fP (متغیر برچسب که باید به‌روزرسانی شود). .TP .B \fBcode:yymtagn\fP عبارت \fBYYMTAGN\fP، احتمالاً تخصیص‌یافته برای APIهای مختلف. متغیرهای پشتیبانی‌شده: \fBYYMTAGN\fP (که با پیکربندی متناظر \fBre2c:\fP مطابقت دارد)، \fBtag\fP (متغیر برچسب که باید به‌روزرسانی شود). .TP .B \fBcode:yycopystag\fP عبارت \fBYYCOPYSTAG\fP، احتمالاً تخصیص‌یافته برای APIهای مختلف. متغیرهای پشتیبانی‌شده: \fBYYCOPYSTAG\fP، \fByyrecord\fP (که با پیکربندی‌های متناظر \fBre2c:\fP مطابقت دارند)، \fBlhs\fP، \fBrhs\fP (متغیرهای برچسب سمت چپ و راستِ عملیات کپی). .TP .B \fBcode:yycopymtag\fP عبارت \fBYYCOPYMTAG\fP، احتمالاً تخصیص‌یافته برای APIهای مختلف. متغیرهای پشتیبانی‌شده: \fBYYCOPYMTAG\fP، \fByyrecord\fP (که با پیکربندی‌های متناظر \fBre2c:\fP مطابقت دارند)، \fBlhs\fP، \fBrhs\fP (متغیرهای برچسب سمت چپ و راستِ عملیات کپی). .TP .B \fBcode:yygetaccept\fP عبارت \fBYYGETACCEPT\fP، احتمالاً تخصیص‌یافته برای APIهای مختلف. متغیرهای پشتیبانی‌شده: \fBYYGETACCEPT\fP، \fByyrecord\fP (که با پیکربندی‌های متناظر \fBre2c:\fP مطابقت دارند)، \fBvar\fP (که با پیکربندی \fBre2c:yyaccept\fP مطابقت دارد). .TP .B \fBcode:yysetaccept\fP عبارت \fBYYSETACCEPT\fP، احتمالاً تخصیص‌یافته برای APIهای مختلف. متغیرهای پشتیبانی‌شده: \fBYYSETACCEPT\fP، \fByyrecord\fP (که با پیکربندی‌های متناظر \fBre2c:\fP مطابقت دارند)، \fBvar\fP (که با پیکربندی \fBre2c:yyaccept\fP مطابقت دارد) و \fBval\fP (مقدار عددی قاعدهٔ پذیرفته‌شده). .TP .B \fBcode:yygetcond\fP عبارت \fBYYGETCOND\fP، احتمالاً تخصیص‌یافته برای APIهای مختلف. متغیرهای پشتیبانی‌شده: \fBYYGETCOND\fP، \fByyrecord\fP (که با پیکربندی‌های متناظر \fBre2c:\fP مطابقت دارند)، \fBvar\fP (که با پیکربندی \fBre2c:yycond\fP مطابقت دارد). .TP .B \fBcode:yysetcond\fP عبارت \fBYYSETCOND\fP، احتمالاً تخصیص‌یافته برای APIهای مختلف. متغیرهای پشتیبانی‌شده: \fBYYSETCOND\fP، \fByyrecord\fP (که با پیکربندی‌های متناظر \fBre2c:\fP مطابقت دارند)، \fBvar\fP (که با پیکربندی \fBre2c:yycond\fP مطابقت دارد) و \fBval\fP (شناسهٔ عددی شرط). .TP .B \fBcode:yygetstate\fP عبارت \fBYYGETSTATE\fP، احتمالاً تخصیص‌یافته برای APIهای مختلف. متغیرهای پشتیبانی‌شده: \fBYYGETSTATE\fP، \fByyrecord\fP (که با پیکربندی‌های متناظر \fBre2c:\fP مطابقت دارند)، \fBvar\fP (که با پیکربندی \fBre2c:yystate\fP مطابقت دارد). .TP .B \fBcode:yysetstate\fP عبارت \fBYYSETSTATE\fP، احتمالاً تخصیص‌یافته برای APIهای مختلف. متغیرهای پشتیبانی‌شده: \fBYYSETSTATE\fP، \fByyrecord\fP (که با پیکربندی‌های متناظر \fBre2c:\fP مطابقت دارند)، \fBvar\fP (که با پیکربندی \fBre2c:yystate\fP مطابقت دارد) و \fBval\fP (شمارهٔ وضعیت). .TP .B \fBcode:yylessthan\fP عبارت \fBYYLESSTHAN\fP، احتمالاً تخصیص‌یافته برای APIهای مختلف. متغیرهای پشتیبانی‌شده: \fBYYLESSTHAN\fP، \fBYYCURSOR\fP، \fBYYLIMIT\fP، \fByyrecord\fP (که با پیکربندی‌های متناظر \fBre2c:\fP مطابقت دارند)، \fBneed\fP (تعداد واحدهای کد برای بررسی در برابر آن). شرط: \fB\&.many\fP (درست درصورتی‌که \fBneed\fP بیش از یک باشد)..TP .B \fBcode:yyend\fP عبارت \fBYYEND\fP، احتمالاً سفارشی‌شده برای APIهای گوناگون. متغیرهای پشتیبانی‌شده: \fBYYEND\fP، \fBYYCURSOR\fP، \fBYYLIMIT\fP\&. .TP .B \fBcode:yybm_filter\fP شرطی که برای فیلتر کردن مقادیر \fByych\fP که توسط جدول \fByybm\fP پوشش داده نشده‌اند استفاده می‌شود (همراه با گزینهٔ \fB\-\-bitmaps\fP به کار می‌رود). متغیر پشتیبانی‌شده: \fByych\fP (به پیکربندی \fBre2c:yych\fP نگاشت می‌شود). .TP .B \fBcode:yybm_match\fP قالب بررسی جدول \fByybm\fP (تولیدشده با گزینهٔ \fB\-\-bitmaps\fP). متغیرهای پشتیبانی‌شده: \fByybm\fP، \fByych\fP (به پیکربندی‌های متناظر \fBre2c:\fP نگاشت می‌شوند)، \fBoffset\fP (آفست در جدول \fByybm\fP که باید به \fByych\fP افزوده شود) و \fBmask\fP (ماسک بیتی که باید روی مدخل جدول اعمال شود تا مقدار بولی مورد نیاز برای بررسی به دست آید). .TP .B \fBcode:yytarget_filter\fP شرطی که برای فیلتر کردن مقادیر \fByych\fP که توسط جدول \fByytarget\fP پوشش داده نشده‌اند استفاده می‌شود (همراه با گزینهٔ \fB\-\-computed\-gotos\fP به کار می‌رود). متغیر پشتیبانی‌شده: \fByych\fP (به پیکربندی \fBre2c:yych\fP نگاشت می‌شود). .UNINDENT .sp در اینجا فهرستی از تمام متغیرهای سراسری مجاز در فایل‌های نحو آمده است: .INDENT 0.0 .TP .B \fBnl\fP یک خط جدید (newline). .TP .B \fBindent\fP متغیری که هیچ کدی تولید نمی‌کند، اما دارای اثر جانبی افزایش سطح دندانه‌گذاری است. .TP .B \fBdedent\fP متغیری که هیچ کدی تولید نمی‌کند، اما دارای اثر جانبی کاهش سطح دندانه‌گذاری است. .TP .B \fBtopindent\fP رشتهٔ دندانه‌گذاری برای عبارت فعلی. سطح دندانه‌گذاری توسط تولیدکنندهٔ کد ردیابی شده و به‌طور خودکار به‌روزرسانی می‌شود. .UNINDENT .sp در اینجا فهرستی از تمام شرط‌های سراسری مجاز در فایل‌های نحو آمده است: .INDENT 0.0 .TP .B \fB\&.api.simple\fP True است اگر از API ساده استفاده شود (\fB\-\-api simple\fP یا \fBre2c:api = simple\fP). .TP .B \fB\&.api.generic\fP True است اگر از API عمومی استفاده شود (\fB\-\-api generic\fP یا \fBre2c:api = generic\fP). .TP .B \fB\&.api.record\fP True است اگر از API رکورد استفاده شود (\fB\-\-api record\fP یا \fBre2c:api = record\fP). .TP .B \fB\&.api_style.functions\fP True است اگر سبک API تابع‌گونه استفاده شود (\fBre2c:api\-style = functions\fP). .TP .B \fB\&.api_style.freeform\fP True است اگر سبک API آزاد استفاده شود (\fBre2c:api\-style = free\-form\fP). .TP .B \fB\&.case_ranges\fP True است اگر قابلیت بازه‌های case فعال باشد (\fB\-\-case\-ranges\fP یا \fBre2c:case\-ranges = 1\fP). .TP .B \fB\&.cgoto.relative\fP True است اگر حالت نسبی دستور \fBgoto\fP محاسباتی استفاده شود (\fB\-\-computed\-gotos\-relative\fP یا \fBre2c:cgoto:relative = 1\fP). .TP .B \fB\&.code_model.goto_label\fP True است اگر مدل کد مبتنی بر goto/label استفاده شود (\fB\-\-goto\-label\fP). .TP .B \fB\&.code_model.loop_switch\fP True است اگر مدل کد مبتنی بر loop/switch استفاده شود (\fB\-\-loop\-switch\fP). .TP .B \fB\&.code_model.recursive_functions\fP True است اگر مدل کد مبتنی بر توابع بازگشتی استفاده شود (\fB\-\-recursive\-function\fP). .TP .B \fB\&.date\fP True است اگر اثرانگشت (fingerprint) تولیدشده باید حاوی تاریخ تولید باشد. .TP .B \fB\&.loop_label\fP True است اگر حلقه‌های تولیدشده توسط re2c باید دارای برچسب باشند (\fBre2c:label:yyloop\fP روی یک رشتهٔ غیرخالی تنظیم شده باشد). .TP .B \fB\&.monadic\fP True است اگر کد تولیدشده باید به‌صورت مونادیک باشد (\fBre2c:monadic = 1\fP). این مورد تنها برای زبان‌های تابعی محض کاربرد دارد. .TP .B \fB\&.start_conditions\fP True است اگر شرایط شروع فعال باشند (\fB\-\-start\-conditions\fP). .TP .B \fB\&.storable_state\fP True است اگر وضعیت قابل ذخیره‌سازی فعال باشد (\fB\-\-storable\-state\fP). .TP .B \fB\&.unsafe\fP True است اگر re2c برای تولید کد سریع‌تر باید از بلوک‌های \(dqunsafe\(dq استفاده کند (\fB\-\-unsafe\fP، \fBre2c:unsafe = 1\fP). این مورد تنها برای زبان‌هایی مرتبط است که دارای قابلیت \(dqunsafe\(dq هستند. .TP .B \fB\&.version\fP True است اگر اثرانگشت تولیدشده باید حاوی نسخهٔ re2c باشد. .TP .B \fB\&.yyfill.enable\fP True است اگر \fBYYFILL\fP فعال باشد (\fBre2c:yyfill:enable = 1\fP). .TP .B \fB\&.yyfn.throw\fP True است اگر پیکربندی \fBre2c:yyfn:throw\fP روی یک رشتهٔ غیرخالی تعریف شده باشد. .UNINDENT .UNINDENT .UNINDENT.SH "مدیریت پایان ورودی (HANDLING THE END OF INPUT)" .sp یکی از چالش‌های اصلی تحلیل‌گر لغوی (lexer)، دانستن زمان توقف است. چندین شرط پایان‌دهنده وجود دارد: .INDENT 0.0 .IP \(bu 2 تحلیل‌گر لغوی ممکن است با قاعده‌ای (شامل قاعده پیش‌فرض \fB*\fP) تطابق یابد و به یک وضعیت نهایی برسد .IP \(bu 2 تحلیل‌گر لغوی ممکن است در تطبیق با هر قاعده‌ای شکست بخورد و به یک وضعیت پیش‌فرض برسد .IP \(bu 2 تحلیل‌گر لغوی ممکن است به پایان ورودی برسد .UNINDENT .sp دو شرط نخست تحلیل‌گر لغوی را به روشی \(dqطبیعی\(dq خاتمه می‌دهند: تحلیل‌گر به وضعیتی بدون هیچ انتقال خروجی می‌رسد و تطبیق به طور خودکار متوقف می‌شود. اما شرط سوم، یعنی پایان ورودی، متفاوت است: این حالت ممکن است در هر وضعیتی رخ دهد و تحلیل‌گر لغوی باید قادر به مدیریت آن باشد. بررسی پایان ورودی، روند کار عادی تحلیل‌گر لغوی را مختل کرده و شاخه‌های شرطی را به برنامه تولیدشده می‌افزاید؛ بنابراین به حداقل رساندن تعداد این بررسی‌ها ضروری است. ابزار re2c از چندین روش مختلف برای مدیریت پایان ورودی پشتیبانی می‌کند. انتخاب روش مناسب به پیچیدگی عبارات باقاعده، نیاز به بافرسازی، ملاحظات کارایی و عوامل دیگر بستگی دارد. در ادامه فهرستی از این روش‌ها آورده شده است: .INDENT 0.0 .IP \(bu 2 \fBنگهبان (Sentinel).\fP این روش نیاز به بررسی‌های پایان ورودی را به طور کامل برطرف می‌کند. این روش ساده و کارآمد است، اما محدود به مواردی است که یک نویسه \(dqنگهبان\(dq طبیعی وجود داشته باشد که هرگز در ورودی معتبر رخ ندهد. این نویسه همچنان ممکن است در ورودی نامعتبر ظاهر شود، اما نباید در عبارات باقاعده مجاز باشد، مگر شاید به عنوان آخرین نویسه یک قاعده. نگهبان به انتهای ورودی ضمیمه می‌شود و به عنوان سیگنال توقف عمل می‌کند: زمانی که تحلیل‌گر لغوی این نویسه را بخواند، یا خطای نحوی رخ داده یا به پایان ورودی رسیده است. در هر دو حالت، تحلیل‌گر باید متوقف شود. این روش زمانی استفاده می‌شود که \fBYYFILL\fP با \fBre2c:yyfill:enable = 0;\fP غیرفعال شده باشد و \fBre2c:eof\fP مقدار پیش‌فرض \fB\-1\fP را داشته باشد. .nf .fi .sp .IP \(bu 2 \fBنگهبان با بررسی مرزها (Sentinel with bounds checks).\fP این روش عمومی (generic) است: امکان مدیریت هر ورودی را بدون محدودیت روی عبارات باقاعده فراهم می‌کند. ایده این روش، کاهش تعداد بررسی‌های پایان ورودی از طریق انجام آن‌ها تنها روی نویسه‌هایی خاص است. مشابه روش \(dqنگهبان\(dq، یکی از نویسه‌ها به عنوان \(dqنگهبان\(dq انتخاب شده و به انتهای ورودی ضمیمه می‌شود. با این حال، هیچ محدودیتی در مورد محل وقوع نگهبان وجود ندارد (در واقع، هر نویسه‌ای را می‌توان برای نگهبان انتخاب کرد). هنگامی که تحلیل‌گر لغوی این نویسه را می‌خواند، علاوه بر آن بررسی مرز را نیز انجام می‌دهد. اگر موقعیت فعلی در محدوده مجاز باشد، تحلیل‌گر تطبیق را از سر گرفته و با نگهبان مانند یک نویسه معمولی رفتار می‌کند. در غیر این صورت، تابع \fBYYFILL\fP را فراخوانی می‌کند (مگر اینکه غیرفعال شده باشد). اگر ورودی بیشتری ارائه شود، تحلیل‌گر لغوی نویسه آخر را مجدداً تطبیق داده و چنان ادامه می‌دهد که گویی نویسه نگهبان اصلاً وجود نداشته است. در غیر این صورت باید پایان واقعی ورودی باشد و تحلیل‌گر متوقف می‌شود. این روش زمانی به کار می‌رود که \fBre2c:eof\fP مقداری غیرمنفی داشته باشد (باید روی مقدار عددی نویسه نگهبان تنظیم شود). استفاده از \fBYYFILL\fP اختیاری است. .nf .fi .sp .IP \(bu 2 \fBبررسی مرزها همراه با پدینگ (Bounds checks with padding).\fP این روش عمومی است، و ممکن است سریع‌تر از روش \(dqنگهبان با بررسی مرزها\(dq باشد، اما پیچیده‌تر نیز هست. ایده این است که وضعیت‌های DFA به مؤلفه‌های قویاً همبند (SCCs) افراز شوند و به ازای هر SCC یک بررسی منفرد برای نویسه‌هایی به تعداد کافی جهت پوشش طولانی‌ترین مسیر بدون حلقه در آن SCC ایجاد گردد. این کار تعداد بررسی‌ها را کاهش می‌دهد، اما مشکلی در رابطه با لکسم‌های (lexemes) کوتاه در پایان ورودی به وجود می‌آورد، زیرا بررسی نیازمند نویسه‌های کافی برای پوشش طولانی‌ترین لکسم است. این مشکل را می‌توان با پد کردن (تکمیل) ورودی با چند نویسه ساختگی که پسوند لکسم معتبری تشکیل ندهند (تا تحلیل‌گر نتواند آن‌ها را تطبیق دهد) برطرف کرد. طول این پدینگ باید \fBYYMAXFILL\fP باشد که با یک بلوک \fBmax\fP تولید می‌شود. اگر ورودی کافی نباشد، تحلیل‌گر لغوی \fBYYFILL\fP را فراخوانی می‌کند که باید حداقل تعداد نویسه‌های مورد نیاز را تأمین کند یا بازگشتی نداشته باشد. این روش زمانی استفاده می‌شود که \fBYYFILL\fP فعال باشد و \fBre2c:eof\fP برابر \fB\-1\fP باشد (این پیکربندی پیش‌فرض است). .nf .fi .sp .IP \(bu 2 \fBبررسی‌های سفارشی (Custom checks).\fP رابط عمومی (Generic API) امکان بازتعریف عملیات پایه‌ای مانند خواندن یک نویسه را فراهم می‌کند، که گنجاندن بررسی‌های پایان ورودی را به عنوان بخشی از آن‌ها ممکن می‌سازد. این رویکرد مستعد خطاست و باید با احتیاط استفاده شود. برای استفاده از یک روش سفارشی، Generic API را با \fB\-\-api custom\fP یا \fBre2c:api = custom;\fP فعال کرده و بررسی‌های پیش‌فرض مرزها را با \fBre2c:yyfill:enable = 0;\fP یا \fBre2c:yyfill:check = 0;\fP\& غیرفعال کنید. .UNINDENT .sp زیربخش‌های بعدی شامل نمونه‌ای برای هر یک از روش‌ها هستند..SS نگهبان (Sentinel) .sp این مثال از یک کاراکتر نگهبان (sentinel) برای مدیریت پایان ورودی استفاده می‌کند. این برنامه کلمات جداشده با فاصله را در یک رشتهٔ پایان‌یافته با null شمارش می‌کند. کاراکتر نگهبان همان null است: آخرین کاراکتر هر رشتهٔ ورودی است و توسط هیچ‌یک از قواعد در میانهٔ یک نشانه (lexeme) مجاز نیست (به‌ویژه، در بازه‌های کاراکتری که ممکن است نادیده گرفته شوند، گنجانده نشده است). اگر یک null در میانهٔ یک رشته رخ دهد، یک خطای نحو (syntax error) محسوب شده و تحلیل‌گر لغوی قاعدهٔ پیش‌فرض \fB*\fP را مطابقت خواهد داد، اما فراتر از پایان ورودی نخواهد خواند و متوقف (crash) نخواهد شد (برای بررسی این موضوع از هشدار \fI\%\-Wsentinel\-in\-midrule\fP و پیکربندی \fBre2c:sentinel\fP استفاده کنید). پیکربندی \fBre2c:yyfill:enable = 0;\fP از تولید بررسی‌های مرزی و فراخوانی‌های \fBYYFILL\fP جلوگیری می‌کند. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C // re2c $INPUT \-o $OUTPUT #include // Expect a null\-terminated string. static int lex(const char *YYCURSOR) { int count = 0; for (;;) { /*!re2c re2c:define:YYCTYPE = \(dqunsigned char\(dq; re2c:yyfill:enable = 0; * { return \-1; } [\ex00] { return count; } [a\-z]+ { ++count; continue; } [ ]+ { continue; } */ } } int main() { assert(lex(\(dq\(dq) == 0); assert(lex(\(dqone two three\(dq) == 3); assert(lex(\(dqf0ur\(dq) == \-1); return 0; } .ft P .fi .UNINDENT .UNINDENT .SS نگهبان به همراه بررسی‌های مرزی (Sentinel with bounds checks) .sp این مثال از روش نگهبان به همراه بررسی‌های مرزی (bounds checks) برای مدیریت پایان ورودی استفاده می‌کند (این روش در نسخهٔ 1.2 اضافه شد). این برنامه رشته‌های محصور در علامت نقل‌قول تکی (single-quoted) جداشده با فاصله را شمارش می‌کند. کاراکتر نگهبان null است که با پیکربندی \fBre2c:eof = 0;\fP مشخص می‌شود. همانند روش \fI\%sentinel\fP، کاراکتر null آخرین کاراکتر هر رشتهٔ ورودی است، اما در میانهٔ یک قاعده مجاز شمرده می‌شود (برای نمونه، \fB\(aqaaa\e0aa\(aq\e0\fP یک ورودی معتبر است، اما \fB\(aqaaa\e0\fP یک خطای نحو است). بررسی‌های مرزی در هر وضعیتی که با یک کاراکتر ورودی مطابقت دارد تولید می‌شوند، اما دامنهٔ آن‌ها به شاخه‌ای محدود است که null را مدیریت می‌کند. بررسی‌های مرزی به فرم \fBYYLIMIT <= YYCURSOR\fP یا \fBYYLESSTHAN(1)\fP با API عمومی (generic API) هستند. اگر شرط بررسی برقرار باشد، تحلیل‌گر لغوی به پایان ورودی رسیده است و باید متوقف شود (\fBYYFILL\fP با \fBre2c:yyfill:enable = 0;\fP غیرفعال شده است زیرا ورودی درون یک بافر جا می‌گیرد؛ برای مثالی که از \fBYYFILL\fP استفاده می‌کند بخش \fI\%YYFILL with sentinel\fP را ببینید). رسیدن به پایان ورودی سه احتمال ایجاد می‌کند: اگر تحلیل‌گر لغوی در وضعیت اولیه باشد با قاعدهٔ پایان ورودی \fB$\fP مطابقت پیدا خواهد کرد، در غیر این صورت ممکن است به قاعده‌ای که قبلاً مطابقت یافته (از جمله قاعدهٔ پیش‌فرض \fB*\fP) بازگردد یا به یک وضعیت پیش‌فرض برود که منجر به هشدار \fI\%\-Wundefined\-control\-flow\fP\& می‌شود. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C // re2c $INPUT \-o $OUTPUT #include // Expect a null\-terminated string. static int lex(const char *str, unsigned int len) { const char *YYCURSOR = str, *YYLIMIT = str + len, *YYMARKER; int count = 0; for (;;) { /*!re2c re2c:define:YYCTYPE = \(dqunsigned char\(dq; re2c:yyfill:enable = 0; re2c:eof = 0; str = [\(aq] ([^\(aq\e\e] | [\e\e][^])* [\(aq]; * { return \-1; } $ { return count; } str { ++count; continue; } [ ]+ { continue; } */ } } #define TEST(s, r) assert(lex(s, sizeof(s) \- 1) == r) int main() { TEST(\(dq\(dq, 0); TEST(\(dq\(aqqu\e0tes\(aq \(aqare\(aq \(aqfine: \e\e\(aq\(aq \(dq, 3); TEST(\(dq\(aqunterminated\e\e\(aq\(dq, \-1); return 0; } .ft P .fi .UNINDENT .UNINDENT.SS بررسی‌های محدوده با پدینگ (Bounds checks with padding) .sp این مثال از بررسی‌های محدوده با پدینگ برای مدیریت انتهای ورودی استفاده می‌کند (این روش به‌طور پیش‌فرض فعال است). این برنامه تعداد رشته‌های تک‌نقل‌قولیِ جداشده با فاصله را می‌شمارد. پدینگی شامل \fBYYMAXFILL\fP نویسهٔ null به انتهای ورودی الحاق شده است، که مقدار \fBYYMAXFILL\fP به‌طور خودکار توسط یک بلوک \fBmax\fP تولید می‌شود. استفاده از null برای پدینگ الزامی نیست \-\-\- از هر نویسه‌ای می‌توان استفاده کرد تا زمانی که یک پسوند معتبر برای نشانه (lexeme) تشکیل ندهد (در این مثال پدینگ نباید شامل تک‌نقل‌قول باشد، زیرا ممکن است با پسوند یک رشتهٔ تک‌نقل‌قولی اشتباه گرفته شود). یک قاعدهٔ \(dqstop\(dq وجود دارد که با نخستین نویسهٔ پدینگ (null) تطابق یافته و تحلیل‌گر لغوی را خاتمه می‌دهد (توجه داشته باشید که بررسی می‌کند آیا null در ابتدای پدینگ قرار دارد یا خیر، در غیر این صورت یک خطای نحوی است). بررسی‌های محدوده تنها در حالت‌هایی تولید می‌شوند که توسط مؤلفه‌های قویاً همبندِ اتوماتون زیرین تعیین شده باشند. این بررسی‌ها به شکل \fB(YYLIMIT \- YYCURSOR) < n\fP یا با API عمومی به‌صورت \fBYYLESSTHAN(n)\fP هستند، که در آن \fBn\fP حداقل تعداد نویسه‌های مورد نیاز برای ادامهٔ کار تحلیل‌گر لغوی است (همچنین به این معنی است که بررسی بعدی محدوده حداکثر در \fBn\fP نویسهٔ آینده رخ خواهد داد). اگر شرط بررسی درست باشد، تحلیل‌گر لغوی به انتهای ورودی رسیده است و \fBYYFILL(n)\fP را فراخوانی می‌کند که باید یا حداقل \fBn\fP نویسهٔ ورودی را فراهم سازد یا بازگشتی نداشته باشد. در این مثال \fBYYFILL\fP همیشه با شکست مواجه می‌شود و تحلیل‌گر لغوی را با یک خطا پایان می‌دهد (که مشکلی ایجاد نمی‌کند زیرا تمام ورودی در یک بافر جای می‌گیرد). برای مشاهدهٔ مثالی که بافر ورودی را با استفاده از \fBYYFILL\fP بازپر می‌کند، بخش \fI\%YYFILL with padding\fP را ببینید\&. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C // re2c $INPUT \-o $OUTPUT #include #include #include /*!max:re2c*/ static int lex(const char *str, unsigned int len) { // Make a copy of the string with YYMAXFILL zeroes at the end. char *buf = (char*) malloc(len + YYMAXFILL); memcpy(buf, str, len); memset(buf + len, 0, YYMAXFILL); const char *YYCURSOR = buf, *YYLIMIT = buf + len + YYMAXFILL; int count = 0; loop: /*!re2c re2c:api:style = free\-form; re2c:define:YYCTYPE = \(dqunsigned char\(dq; re2c:define:YYFILL = \(dqgoto fail;\(dq; str = [\(aq] ([^\(aq\e\e] | [\e\e][^])* [\(aq]; [\ex00] { // Check that it is the sentinel, not some unexpected null. if (YYCURSOR \- 1 == buf + len) goto exit; else goto fail; } str { ++count; goto loop; } [ ]+ { goto loop; } * { goto fail; } */ fail: count = \-1; exit: free(buf); return count; } #define TEST(s, r) assert(lex(s, sizeof(s) \- 1) == r) int main() { TEST(\(dq\(dq, 0); TEST(\(dq\(aqqu\e0tes\(aq \(aqare\(aq \(aqfine: \e\e\(aq\(aq \(dq, 3); TEST(\(dq\(aqunterminated\e\e\(aq\(dq, \-1); TEST(\(dq\(aqunexpected \e0 null\e\e\(aq\(dq, \-1); return 0; } .ft P .fi .UNINDENT .UNINDENT.SS "بررسی‌های سفارشی (Custom checks)" .sp این مثال از یک روش سفارشی برای مدیریت پایان ورودی بر پایه generic API استفاده می‌کند. این برنامه رشته‌های محصور در نقل‌قول تکیِ جداشده با فاصله را شمارش می‌کند. این مثال مانند مثال \fI\%sentinel\fP است، به‌جز اینکه ورودی با null خاتمه نیافته است. برای جبران عدم وجود نویسهٔ نگهبان در انتهای ورودی، \fBYYPEEK\fP بازتعریف شده است تا پیش از خواندن نویسهٔ ورودی بعدی، یک بررسی محدوده انجام دهد. این روش ناکارآمد است زیرا بررسی‌ها به دفعات بسیار زیاد انجام می‌شوند. اگر شرط بررسی شکست بخورد، \fBYYPEEK\fP نویسهٔ واقعی را برمی‌گرداند، در غیر این صورت یک نویسهٔ نگهبان ساختگی بازمی‌گرداند. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C // re2c $INPUT \-o $OUTPUT #include #include #include static int lex(const char *str, unsigned int len) { // For the sake of example create a string without terminating null. char *buf = (char*) malloc(len); memcpy(buf, str, len); const char *cur = buf, *lim = buf + len; int count = 0; for (;;) { /*!re2c re2c:yyfill:enable = 0; re2c:api = custom; re2c:api:style = free\-form; re2c:define:YYCTYPE = \(dqunsigned char\(dq; re2c:define:YYPEEK = \(dqcur < lim ? *cur : 0\(dq; // fake null re2c:define:YYSKIP = \(dq++cur;\(dq; * { count = \-1; break; } [\ex00] { break;; } [a\-z]+ { ++count; continue;; } [ ]+ { continue; } */ } free(buf); return count; } #define TEST(s, r) assert(lex(s, sizeof(s) \- 1) == r) int main() { TEST(\(dq\(dq, 0); TEST(\(dqone two three \(dq, 3); TEST(\(dqf0ur\(dq, \-1); return 0; } .ft P .fi .UNINDENT .UNINDENT .SH "بازپر کردن بافر (BUFFER REFILLING)" .sp نیاز به بافرینگ زمانی رخ می‌دهد که نتوان تمام ورودی را به‌یک‌باره در حافظه نگاشت کرد: یا ورودی بسیار بزرگ است، یا به صورت جریانی (مانند خواندن از یک سوکت) دریافت می‌شود. روش معمول در چنین مواردی تخصیص یک بافر حافظه با اندازهٔ ثابت و پردازش ورودی در تکه‌هایی است که در بافر جا می‌شوند. هنگامی که تکهٔ فعلی پردازش شد، به بیرون منتقل شده و داده‌های جدید وارد می‌شوند. در عمل این امر تا حدی پیچیده‌تر است، زیرا وضعیت تحلیل‌گر واژگانی صرفاً از یک موقعیت ورودی تشکیل نشده، بلکه مجموعه‌ای از موقعیت‌های به‌هم‌پیوسته است: .INDENT 0.0 .IP \(bu 2 مکان‌نما (cursor): نویسهٔ ورودی بعدی برای خوانده شدن (\fBYYCURSOR\fP در C pointer API یا \fBYYSKIP\fP/\fBYYPEEK\fP در generic API) .IP \(bu 2 حد (limit): موقعیت پس از آخرین نویسهٔ ورودیِ در دسترس (\fBYYLIMIT\fP در C pointer API، که به‌طور ضمنی توسط \fBYYLESSTHAN\fP در generic API مدیریت می‌شود) .IP \(bu 2 نشانه‌گذار (marker): موقعیت جدیدترین تطابق، در صورت وجود (\fBYYMARKER\fP در default API یا \fBYYBACKUP\fP/\fBYYRESTORE\fP در generic API) .IP \(bu 2 توکن (token): ابتدای جزء واژگانی (lexeme) فعلی (در re2c API ضمنی است، زیرا برای عملکرد عادی لکسر به آن نیازی نیست و می‌تواند توسط کاربر تعریف و به‌روزرسانی شود) .IP \(bu 2 نشانه‌گذار زمینه (context marker): موقعیت زمینهٔ پس‌آیند (\fBYYCTXMARKER\fP در C pointer API یا \fBYYBACKUPCTX\fP/\fBYYRESTORECTX\fP در generic API) .IP \(bu 2 متغیرهای برچسب (tag variables): موقعیت‌های زیرتطابق (تعریف‌شده با بلوک‌های \fBstags\fP و \fBmtags\fP و دستورات اولیهٔ generic API یعنی \fBYYSTAGP\fP/\fBYYSTAGN\fP/\fBYYMTAGP\fP/\fBYYMTAGN\fP) .UNINDENT .sp همهٔ این‌ها در هر حالتی استفاده نمی‌شوند، اما در صورت استفاده، باید توسط \fBYYFILL\fP\& به‌روزرسانی شوند. تمام موقعیت‌های فعال در بخشی میان token و cursor قرار دارند؛ بنابراین هر چیزی بین ابتدای بافر و token را می‌توان دور ریخت، بخش بین token تا limit باید به ابتدای بافر منتقل شود، و فضای خالی در انتهای بافر باید با داده‌های جدید پر شود. به منظور جلوگیری از فراخوانی‌های مکرر \fBYYFILL\fP، بهتر است تا حد امکان نویسه‌های ورودی بیشتری پر شوند (حتی اگر نویسه‌های کمتری برای از سرگیری کار لکسر کافی باشند). جزئیات پیاده‌سازی \fBYYFILL\fP بسته به اینکه کدام روش مدیریت EOF استفاده می‌شود کمی متفاوت است: حالت قاعدهٔ EOF تا حدی ساده‌تر از حالت بررسی محدوده همراه با پدینگ (padding) است. همچنین توجه داشته باشید که اگر گزینهٔ \fB\-f \-\-storable\-state\fP استفاده شود، \fBYYFILL\fP معناشناسی اندکی متفاوت خواهد داشت (که در بخش مربوط به وضعیت قابل ذخیره شرح داده شده است)..SS YYFILL همراه با نگهبان (sentinel) .sp اگر از قاعدهٔ EOF استفاده شود، \fBYYFILL\fP یک سازوکار پایه‌ای تابع‌گونه است که هیچ آرگومانی نمی‌پذیرد و مقداری را بازمی‌گرداند که با صفر مقایسه می‌شود. فراخوانی \fBYYFILL\fP با شرط \fBYYLIMIT <= YYCURSOR\fP در API اشاره‌گر C و \fBYYLESSTHAN()\fP در API عمومی راه‌اندازی می‌شود. یک مقدار بازگشتی غیرصفر به این معنی است که \fBYYFILL\fP با شکست مواجه شده است. یک فراخوانی موفق \fBYYFILL\fP باید دست‌کم یک نویسه را تأمین کرده و موقعیت‌های ورودی را بر همین اساس تنظیم کند. متغیر Limit باید همیشه روی یک خانه پس از آخرین موقعیت ورودی در بافر تنظیم شود، و نویسهٔ موجود در موقعیت limit باید نماد نگهبان مشخص‌شده با پیکربندی \fBre2c:eof\fP باشد. تصاویر زیر موقعیت‌های نسبی ورودی در بافر را پیش و پس از فراخوانی \fBYYFILL\fP نشان می‌دهند (نماد نگهبان با \fB#\fP مشخص شده است، و تصویر دوم حالتی را نشان می‌دهد که ورودی کافی برای پر کردن کل بافر وجود ندارد). .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C <\-\- shift \-\-> >\-A\-\-\-\-\-\-\-\-\-\-\-\-B\-\-\-\-\-\-\-\-\-C\-\-\-\-\-\-\-\-\-\-\-\-\-D#\-\-\-\-\-\-\-\-\-\-\-E\-> buffer token marker limit, cursor >\-A\-\-\-\-\-\-\-\-\-\-\-\-B\-\-\-\-\-\-\-\-\-C\-\-\-\-\-\-\-\-\-\-\-\-\-D\-\-\-\-\-\-\-\-\-\-\-\-E#\-> buffer, marker cursor limit token <\-\- shift \-\-> >\-A\-\-\-\-\-\-\-\-\-\-\-\-B\-\-\-\-\-\-\-\-\-C\-\-\-\-\-\-\-\-\-\-\-\-\-D#\-\-E (EOF) buffer token marker limit, cursor >\-A\-\-\-\-\-\-\-\-\-\-\-\-B\-\-\-\-\-\-\-\-\-C\-\-\-\-\-\-\-\-\-\-\-\-\-D\-\-\-E#........ buffer, marker cursor limit token .ft P .fi .UNINDENT .UNINDENT .sp در ادامه مثالی از برنامه‌ای آمده است که فایل ورودی \fBinput.txt\fP را در تکه‌های ۴۰۹۶ بایتی می‌خواند و از قاعدهٔ EOF استفاده می‌کند. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C // re2c $INPUT \-o $OUTPUT #include #include #include #define BUFSIZE 4095 typedef struct { FILE *file; char buf[BUFSIZE + 1], *lim, *cur, *mar, *tok; // +1 for sentinel int eof; } Input; static int fill(Input *in) { if (in\->eof) return 1; const size_t shift = in\->tok \- in\->buf; const size_t used = in\->lim \- in\->tok; // Error: lexeme too long. In real life could reallocate a larger buffer. if (shift < 1) return 2; // Shift buffer contents (discard everything up to the current token). memmove(in\->buf, in\->tok, used); in\->lim \-= shift; in\->cur \-= shift; in\->mar \-= shift; in\->tok \-= shift; // Fill free space at the end of buffer with new data from file. in\->lim += fread(in\->lim, 1, BUFSIZE \- used, in\->file); in\->lim[0] = 0; in\->eof = in\->lim < in\->buf + BUFSIZE; return 0; } static int lex(Input *in) { int count = 0; loop: in\->tok = in\->cur; /*!re2c re2c:api:style = free\-form; re2c:define:YYCTYPE = \(dqunsigned char\(dq; re2c:define:YYCURSOR = in\->cur; re2c:define:YYMARKER = in\->mar; re2c:define:YYLIMIT = in\->lim; re2c:define:YYFILL = \(dqfill(in) == 0\(dq; re2c:eof = 0; str = [\(aq] ([^\(aq\e\e] | [\e\e][^])* [\(aq]; * { return \-1; } $ { return count; } str { ++count; goto loop; } [ ]+ { goto loop; } */ } int main() { const char *fname = \(dqinput\(dq; const char content[] = \(dq\(aqqu\e0tes\(aq \(aqare\(aq \(aqfine: \e\e\(aq\(aq \(dq; // Prepare input file: a few times the size of the buffer, containing // strings with zeroes and escaped quotes. FILE *f = fopen(fname, \(dqw\(dq); for (int i = 0; i < BUFSIZE; ++i) { fwrite(content, 1, sizeof(content) \- 1, f); } fclose(f); int count = 3 * BUFSIZE; // number of quoted strings written to file // Initialize lexer state: all pointers are at the end of buffer. Input in; in.file = fopen(fname, \(dqr\(dq); in.cur = in.mar = in.tok = in.lim = in.buf + BUFSIZE; in.eof = 0; // Sentinel (at YYLIMIT pointer) is set to zero, which triggers YYFILL. in.lim[0] = 0; // Run the lexer. assert(lex(&in) == count); // Cleanup: remove input file. fclose(in.file); remove(fname); return 0; } .ft P .fi .UNINDENT .UNINDENT.SS "YYFILL با لایه‌گذاری (padding)" .sp در حالت پیش‌فرض (زمانی که قاعدهٔ EOF استفاده نمی‌شود)، \fBYYFILL\fP یک دستور اولیهٔ (primitive) تابع‌مانند است که یک آرگومان می‌پذیرد و هیچ مقداری بازنمی‌گرداند. فراخوانی \fBYYFILL\fP توسط شرط \fB(YYLIMIT \- YYCURSOR) < n\fP در API اشاره‌گر C و \fBYYLESSTHAN(n)\fP در API عمومی تحریک می‌شود. آرگومان فرستاده‌شده به \fBYYFILL\fP، کمینهٔ تعداد نویسه‌هایی است که باید تأمین شود. اگر در انجام این کار ناموفق باشد، \fBYYFILL\fP نباید کنترل را به تحلیل‌گر لغوی (lexer) بازگرداند (به همین دلیل بهتر است به صورت ماکرویی پیاده‌سازی شود که در صورت شکست، از تابع فراخواننده خارج شود). در صورت فراخوانی موفقیت‌آمیز \fBYYFILL\fP، موقعیت حد (limit) باید یا روی یکی پس از آخرین موقعیت ورودی در بافر تنظیم شود، یا روی انتهای لایه‌گذاری \fBYYMAXFILL\fP (در حالتی که \fBYYFILL\fP دست‌کم \fBn\fP نویسه را با موفقیت خوانده باشد، اما این مقدار برای پر کردن کل بافر کافی نباشد). تصاویر زیر موقعیت‌های نسبی مکان‌های ورودی در بافر را قبل و بعد از فراخوانی \fBYYFILL\fP نشان می‌دهند (لایه‌گذاری \fBYYMAXFILL\fP در تصویر دوم با نمادهای \fB#\fP مشخص شده است). .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C <\-\- shift \-\-> <\-\- need \-\-> >\-A\-\-\-\-\-\-\-\-\-\-\-\-B\-\-\-\-\-\-\-\-\-C\-\-\-\-\-D\-\-\-\-\-\-\-E\-\-\-F\-\-\-\-\-\-\-\-G\-> buffer token marker cursor limit >\-A\-\-\-\-\-\-\-\-\-\-\-\-B\-\-\-\-\-\-\-\-\-C\-\-\-\-\-D\-\-\-\-\-\-\-E\-\-\-F\-\-\-\-\-\-\-\-G\-> buffer, marker cursor limit token <\-\- shift \-\-> <\-\- need \-\-> >\-A\-\-\-\-\-\-\-\-\-\-\-\-B\-\-\-\-\-\-\-\-\-C\-\-\-\-\-D\-\-\-\-\-\-\-E\-F (EOF) buffer token marker cursor limit >\-A\-\-\-\-\-\-\-\-\-\-\-\-B\-\-\-\-\-\-\-\-\-C\-\-\-\-\-D\-\-\-\-\-\-\-E\-F############### buffer, marker cursor limit token <\- YYMAXFILL \-> .ft P .fi .UNINDENT .UNINDENT .sp در ادامه نمونه‌ای از برنامه‌ای آورده شده است که فایل ورودی \fBinput.txt\fP را در تکه‌های ۴۰۹۶ بایتی می‌خواند و از بررسی محدوده‌ها (bounds\-checking) به همراه لایه‌گذاری استفاده می‌کند. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C // re2c $INPUT \-o $OUTPUT #include #include #include /*!max:re2c*/ #define BUFSIZE (4096 \- YYMAXFILL) typedef struct { FILE *file; char buf[BUFSIZE + YYMAXFILL], *lim, *cur, *tok; int eof; } Input; static int fill(Input *in, size_t need) { if (in\->eof) return 1; const size_t shift = in\->tok \- in\->buf; const size_t used = in\->lim \- in\->tok; // Error: lexeme too long. In real life could reallocate a larger buffer. if (shift < need) return 2; // Shift buffer contents (discard everything up to the current token). memmove(in\->buf, in\->tok, used); in\->lim \-= shift; in\->cur \-= shift; in\->tok \-= shift; // Fill free space at the end of buffer with new data from file. in\->lim += fread(in\->lim, 1, BUFSIZE \- used, in\->file); // If read less than expected, this is end of input => add zero padding // so that the lexer can access characters at the end of buffer. if (in\->lim < in\->buf + BUFSIZE) { in\->eof = 1; memset(in\->lim, 0, YYMAXFILL); in\->lim += YYMAXFILL; } return 0; } static int lex(Input *in) { int count = 0; loop: in\->tok = in\->cur; /*!re2c re2c:api:style = free\-form; re2c:define:YYCTYPE = \(dqunsigned char\(dq; re2c:define:YYCURSOR = in\->cur; re2c:define:YYLIMIT = in\->lim; re2c:define:YYFILL = \(dqif (fill(in, @@) != 0) return \-1;\(dq; str = [\(aq] ([^\(aq\e\e] | [\e\e][^])* [\(aq]; [\ex00] { // Check that it is the sentinel, not some unexpected null. return in\->tok == in\->lim \- YYMAXFILL ? count : \-1; } str { ++count; goto loop; } [ ]+ { goto loop; } * { return \-1; } */ } int main() { const char *fname = \(dqinput\(dq; const char content[] = \(dq\(aqqu\e0tes\(aq \(aqare\(aq \(aqfine: \e\e\(aq\(aq \(dq; // Prepare input file: a few times the size of the buffer, containing // strings with zeroes and escaped quotes. FILE *f = fopen(fname, \(dqw\(dq); for (int i = 0; i < BUFSIZE; ++i) { fwrite(content, 1, sizeof(content) \- 1, f); } fclose(f); int count = 3 * BUFSIZE; // number of quoted strings written to file // Initialize lexer state: all pointers are at the end of buffer. // This immediately triggers YYFILL, as the check \(gain\->cur < in\->lim\(ga fails. Input in; in.file = fopen(fname, \(dqr\(dq); in.cur = in.tok = in.lim = in.buf + BUFSIZE; in.eof = 0; // Run the lexer. assert(lex(&in) == count); // Cleanup: remove input file. fclose(in.file); remove(fname); return 0; } .ft P .fi .UNINDENT .UNINDENT.SH "ویژگی‌ها (FEATURES)" .SS "بلوک‌های چندگانه (Multiple blocks)" .sp گاهی داشتن چندین تحلیل‌گر لغوی (lexer) مرتبط با یکدیگر ضروری است (برای نمونه، اگر یک ماشین حالت سطح‌بالا وجود داشته باشد که بین حالت‌های تحلیل‌گر جابه‌جا شود). این کار می‌تواند با استفاده از چندین بلوک متصل به هم re2c پیاده‌سازی شود. گزینه دیگر استفاده از \fI\%start conditions\fP\& است. .sp پیاده‌سازی اتصالات بین بلوک‌ها به زبان مقصد بستگی دارد. در زبان‌هایی که دارای دستور \fBgoto\fP هستند (مانند C/C++ و Go) می‌توان تمام بلوک‌ها را در یک تابع قرار داد، به‌طوری که پیش از هر یک از آن‌ها یک برچسب (label) قرار گیرد. انتقال از یک بلوک به بلوک دیگر با یک \fBgoto\fP\& ساده انجام می‌شود. در زبان‌هایی که فاقد \fBgoto\fP هستند (مانند Rust)، استفاده از یک حلقه به همراه switch روی متغیر حالت ضروری است، مشابه حلقه/switch متغیر \fByystate\fP تولیدشده توسط re2c، یا اینکه هر بلوک درون یک تابع قرار گیرد و از فراخوانی توابع استفاده شود. .sp مثال زیر از چندین بلوک برای تجزیه اعداد دودویی (binary)، هشت‌هشتی (octal)، ده‌دهی (decimal) و شانزده‌شانزدهی (hexadecimal) استفاده می‌کند. هر مبنا بلوک مختص به خود را دارد. بلوک اولیه مبنا را تعیین کرده و به بلوک‌های دیگر هدایت می‌کند. پیکربندی‌های مشترک در یک بلوک جداگانه در آغاز برنامه تعریف شده‌اند؛ آن‌ها توسط بلوک‌های دیگر به ارث برده می‌شوند. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C // re2c $INPUT \-o $OUTPUT \-i #include #include #include static const uint64_t ERROR = UINT64_MAX; #define CHECK(n) if (n > UINT32_MAX) return ERROR; static uint64_t parse_u32(const char *s) { const char *YYCURSOR = s, *YYMARKER; uint64_t u = 0; /*!re2c re2c:yyfill:enable = 0; re2c:define:YYCTYPE = \(dqunsigned char\(dq; end = \(dq\ex00\(dq; \(aq0b\(aq / [01] { goto bin; } \(dq0\(dq { goto oct; } \(dq\(dq / [1\-9] { goto dec; } \(aq0x\(aq / [0\-9a\-fA\-F] { goto hex; } * { return ERROR; } */ bin: /*!re2c end { return u; } [01] { u = u * 2 + (YYCURSOR[\-1] \- \(aq0\(aq); CHECK(u); goto bin; } * { return ERROR; } */ oct: /*!re2c end { return u; } [0\-7] { u = u * 8 + (YYCURSOR[\-1] \- \(aq0\(aq); CHECK(u); goto oct; } * { return ERROR; } */ dec: /*!re2c end { return u; } [0\-9] { u = u * 10 + (YYCURSOR[\-1] \- \(aq0\(aq); CHECK(u); goto dec; } * { return ERROR; } */ hex: /*!re2c end { return u; } [0\-9] { u = u * 16 + (YYCURSOR[\-1] \- \(aq0\(aq); CHECK(u); goto hex; } [a\-f] { u = u * 16 + (YYCURSOR[\-1] \- \(aqa\(aq + 10); CHECK(u); goto hex; } [A\-F] { u = u * 16 + (YYCURSOR[\-1] \- \(aqA\(aq + 10); CHECK(u); goto hex; } * { return ERROR; } */ } int main() { assert(parse_u32(\(dq\(dq) == ERROR); assert(parse_u32(\(dq1234567890\(dq) == 1234567890); assert(parse_u32(\(dq0b1101\(dq) == 13); assert(parse_u32(\(dq0x7Fe\(dq) == 2046); assert(parse_u32(\(dq0644\(dq) == 420); assert(parse_u32(\(dq9999999999\(dq) == ERROR); return 0; } .ft P .fi .UNINDENT .UNINDENT.SS شرط‌های شروع (Start conditions) .sp شرط‌های شروع با گزینهٔ \fB\-\-start\-conditions\fP فعال می‌شوند. آن‌ها روشی برای کدگذاری چندین خودکارهٔ (automata) مرتبط با یکدیگر را درون یک بلوک re2c یکسان فراهم می‌کنند. .sp هر شرط متناظر با یک خودکارهٔ منفرد است و دارای یک نام منحصربه‌فردِ تعیین‌شده توسط کاربر و یک شمارهٔ داخلی یکتاست که توسط re2c\& تعریف می‌شود. این شماره‌ها برای جابه‌جایی میان شرط‌ها به کار می‌روند: کد تولیدشده از تعاریف پایه‌ایِ \fBYYGETCOND\fP و \fBYYSETCOND\fP برای دریافت شرط فعلی یا تنظیم آن بر روی شمارهٔ ارائه‌شده استفاده می‌کند. از بلوک \fBconditions\fP، گزینهٔ \fB\-\-header\fP یا پیکربندی \fBre2c:header\fP برای تولید شناسه‌های عددی شرط‌ها استفاده کنید. پیکربندی \fBre2c:cond:enumprefix\fP پیشوند شناسه‌های تولیدشده را مشخص می‌کند. .sp در حالت شرط (condition mode)، هر قاعده باید پیشوندی از فهرستی از نام‌های شرط‌ها داشته باشد که با کاما از هم جدا شده و درون قلاب‌ها (angle brackets) قرار گرفته‌اند، یا از نویسهٔ عام \fB<*>\fP برای اشاره به تمام شرط‌ها استفاده کند. نحو قواعد به شرح زیر گسترش می‌یابد: .INDENT 0.0 .INDENT 3.5 .INDENT 0.0 .TP .B \fB< condition\-list > regular\-expression code\fP قاعده‌ای که در هر شرط موجود در \fBcondition\-list\fP ادغام می‌شود. این قاعده با \fBregular\-expression\fP مطابقت می‌یابد و \fBcode\fP مربوطه را اجرا می‌کند. .TP .B \fB< condition\-list > regular\-expression => condition code\fP قاعده‌ای که در هر شرط موجود در \fBcondition\-list\fP ادغام می‌شود. این قاعده با \fBregular\-expression\fP مطابقت یافته، شرط فعلی را به \fBcondition\fP تنظیم می‌کند و \fBcode\fP مربوطه را اجرا می‌نماید. .TP .B \fB< condition\-list > regular\-expression :=> condition\fP قاعده‌ای که در هر شرط موجود در \fBcondition\-list\fP ادغام می‌شود. این قاعده با \fBregular\-expression\fP مطابقت یافته و بلافاصله به \fBcondition\fP انتقال می‌یابد (هیچ کنش معنایی وجود ندارد). .TP .B \fB< condition\-list > !action code\fP قاعده‌ای که \fBcode\fP را به مکان تعریف‌شده توسط \fBaction\fP در هر یک از شرط‌های موجود در \fBcondition\-list\fP متصل می‌کند (برای انواع مختلف کنش‌ها به بخش \fI\%actions\fP مراجعه کنید). .TP .B \fB code\fP قاعده‌ای که \fBcode\fP را به ابتدای کنش‌های معناییِ تمام قواعد برای هر شرط در \fBcondition\-list\fP اضافه می‌کند. این نحو منسوخ شده است و به‌جای آن باید از کنش \fB!pre_rule\fP استفاده شود (دقیقاً همان عملکرد را دارد). .TP .B \fB< > code\fP قاعده‌ای که یک شرط ورودی ویژه با شمارهٔ صفر و نام \fB\(dq0\(dq\fP ایجاد می‌کند که پیش از جهش به سایر شرط‌ها، \fBcode\fP را اجرا می‌کند. این نحو منسوخ شده است و به‌جای آن باید از کنش \fB!entry\fP استفاده شود (کنترل دقیق‌تری فراهم می‌کند، زیرا کد می‌تواند بر مبنای هر شرط به‌طور جداگانه تعیین شود، و می‌توان مستقیماً بدون عبور از توزیع‌کنندهٔ شرط [condition dispatch] به ابتدای شرط جهش کرد). .TP .B \fB< > => condition code\fP مشابه قاعدهٔ قبلی است، با این تفاوت که \fBcondition\fP بعدی را تنظیم می‌کند. .TP .B \fB< > :=> condition\fP مشابه قاعدهٔ قبلی است، با این تفاوت که هیچ کد مرتبطی ندارد و بلافاصله به \fBcondition\fP جهش می‌کند. .UNINDENT .UNINDENT .UNINDENT .sp کدی که re2c برای شرط‌ها تولید می‌کند به این بستگی دارد که آیا re2c از رویکرد goto/label برای کدگذاری خودکاره‌ها استفاده می‌کند یا از رویکرد loop/switch. .sp در زبان‌هایی که دارای دستور \fBgoto\fP هستند (مانند C/C++ و Go)، شرط‌ها به‌طور طبیعی به‌صورت بلوک‌هایی از کد با برچسب‌هایی به فرم \fByyc_\fP پیاده‌سازی می‌شوند، که در آن \fBcond\fP نام شرط است (پیشوند برچسب را می‌توان با \fBre2c:cond:prefix\fP تغییر داد). انتقال بین شرط‌ها با استفاده از \fBgoto\fP و برچسب‌های شرط پیاده‌سازی می‌شود. پیش از تمام شرط‌ها، re2c یک ساختار switch اولیه بر روی \fBYYGETSTATE\fP تولید می‌کند که به وضعیت شروعِ شرط فعلی جهش می‌نماید. قواعد میان‌بر \fB:=>\fP ساختار switch اولیه را دور می‌زنند و مستقیماً به شرط مشخص‌شده جهش می‌کنند (از \fBre2c:cond:goto\fP می‌توان برای تغییر رفتار پیش‌فرض استفاده کرد). قواعد دارای کنش‌های معنایی به‌طور خودکار به شرط بعدی جهش نمی‌کنند؛ این کار باید توسط کد کنشِ تعریف‌شده توسط کاربر انجام شود. .sp در زبان‌هایی که دستور \fBgoto\fP ندارند (مانند Rust)، re2c از متغیر \fByystate\fP برای ذخیرهٔ شماره‌های شرط مجدداً استفاده می‌کند. هر شرط یک شناسهٔ عددی برابر با شمارهٔ وضعیت شروع خود دریافت می‌کند، و switch میان شرط‌ها تفاوتی با switch بین وضعیت‌های DFA یک شرط واحد ندارد. در این حالت نیازی به switch اولیهٔ مجزا برای شرط نیست. (از آنجا که همین رویکرد برای پیاده‌سازی وضعیت‌های قابل‌ذخیره استفاده می‌شود، در صورت استفادهٔ هم‌زمان از وضعیت‌های قابل‌ذخیره و شرط‌ها، \fBYYGETCOND\fP/\fBYYSETCOND\fP زاید خواهند بود). .sp برنامهٔ زیر از شرط‌های شروع برای تجزیهٔ اعداد در مبناهای دودویی (باینری)، هشت‌هشتی (اکتال)، ده‌دهی (دسیمال) و شانزده‌شانزدهی (هگزادسیمال) استفاده می‌کند. یک بلوک واحد وجود دارد که هر مبنا در آن دارای شرط اختصاصی خود است و شرط اولیه به همهٔ آن‌ها متصل است. متغیر تعریف‌شده توسط کاربر با نام \fBcond\fP شمارهٔ شرط فعلی را ذخیره می‌کند؛ این متغیر با شمارهٔ شرط اولیه که با بلوک \fBconditions\fP تولید شده مقداردهی اولیه می‌شود. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C // re2c $INPUT \-o $OUTPUT \-ci #include #include #include static const uint64_t ERROR = UINT64_MAX; /*!conditions:re2c*/ static uint64_t parse_u32(const char *s) { const char *YYCURSOR = s, *YYMARKER; int c = yycinit; uint64_t u = 0; /*!re2c re2c:api:style = free\-form; re2c:define:YYCTYPE = \(dqunsigned char\(dq; re2c:define:YYGETCONDITION = \(dqc\(dq; re2c:define:YYSETCONDITION = \(dqc = @@;\(dq; re2c:yyfill:enable = 0; <*> * { return ERROR; } \(aq0b\(aq / [01] :=> bin \(dq0\(dq :=> oct \(dq\(dq / [1\-9] :=> dec \(aq0x\(aq / [0\-9a\-fA\-F] :=> hex \(dq\ex00\(dq { return u; } [01] { u = u * 2 + (YYCURSOR[\-1] \- \(aq0\(aq); goto yyc_bin; } [0\-7] { u = u * 8 + (YYCURSOR[\-1] \- \(aq0\(aq); goto yyc_oct; } [0\-9] { u = u * 10 + (YYCURSOR[\-1] \- \(aq0\(aq); goto yyc_dec; } [0\-9] { u = u * 16 + (YYCURSOR[\-1] \- \(aq0\(aq); goto yyc_hex; } [a\-f] { u = u * 16 + (YYCURSOR[\-1] \- \(aqa\(aq + 10); goto yyc_hex; } [A\-F] { u = u * 16 + (YYCURSOR[\-1] \- \(aqA\(aq + 10); goto yyc_hex; } { if (u > UINT32_MAX) return ERROR; } */ } int main() { assert(parse_u32(\(dq\(dq) == ERROR); assert(parse_u32(\(dq1234567890\(dq) == 1234567890); assert(parse_u32(\(dq0b1101\(dq) == 13); assert(parse_u32(\(dq0x7Fe\(dq) == 2046); assert(parse_u32(\(dq0644\(dq) == 420); assert(parse_u32(\(dq9999999999\(dq) == ERROR); return 0; } .ft P .fi .UNINDENT .UNINDENT.SS وضعیت قابل ذخیره‌سازی (Storable state) .sp با گزینهٔ \fB\-\-storable\-state\fP، ابزار re2c تحلیل‌گر لغوی‌ای (lexer) تولید می‌کند که می‌تواند وضعیت کنونی خود را ذخیره کرده، به فراخواننده بازگردد، و بعداً عملیات را دقیقاً از همان‌جایی که متوقف شده بود از سر بگیرد. حالت پیش‌فرض کارکرد در re2c یک مدل «کِششی» (\(dqpull\(dq) است که در آن تحلیل‌گر لغوی هر زمان که نیاز داشته باشد ورودی بیشتری را «می‌کشد» (دریافت می‌کند). این حالت ممکن است در مواردی که ورودی به صورت تکه‌تکه در دسترس قرار می‌گیرد غیرقابل قبول باشد (برای نمونه، اگر تحلیل‌گر لغوی توسط تجزیه‌کننده (parser) فراخوانی شود، یا اگر برنامهٔ تحلیل‌گر لغوی از طریق پروتکل سوکت با برنامهٔ دیگری ارتباط برقرار کند که باید پیش از ارسال پیام بعدی، منتظر پاسخ از تحلیل‌گر لغوی بماند). قابلیت وضعیت قابل ذخیره‌سازی دقیقاً برای چنین مواردی در نظر گرفته شده است: این ویژگی امکان تولید تحلیل‌گرهای لغوی با مدل «رانشی» (\(dqpush\(dq) را فراهم می‌سازد. هنگامی که تحلیل‌گر لغوی به ورودی بیشتری نیاز داشته باشد، وضعیت خود را ذخیره کرده و کنترل را به فراخواننده بازمی‌گرداند. سپس، وقتی ورودی بیشتری آماده شد، فراخواننده تحلیل‌گر لغوی را دقیقاً از همان‌جایی که متوقف شده بود به کار می‌اندازد. در مقایسه با مدل «کِششی»، چند تغییر ضروری است: .INDENT 0.0 .IP \(bu 2 تعریف دستورهای اولیهٔ \fBYYSETSTATE()\fP و \fBYYGETSTATE(state)\fP. .IP \(bu 2 تعریف متغیرهای \fByych\fP، \fByyaccept\fP (در صورت استفاده) و \fBstate\fP به عنوان بخشی از وضعیت پایدار تحلیل‌گر لغوی. متغیر \fBstate\fP باید با مقدار \fB\-1\fP مقداردهی اولیه شود. .IP \(bu 2 دستور \fBYYFILL\fP باید به جای تلاش برای فراهم کردن ورودی بیشتر، به برنامهٔ بیرونی بازگردد. کد بازگشتی باید نشان دهد که تحلیل‌گر لغوی به ورودی بیشتری نیاز دارد. .IP \(bu 2 برنامهٔ بیرونی باید موقعیت‌هایی را که تحلیل‌گر لغوی به ورودی بیشتری نیاز دارد شناسایی کرده و واکنش مناسب نشان دهد. .IP \(bu 2 به صورت اختیاری، استفاده از بلوک \fBgetstate\fP برای تولید سوییچ \fBYYGETSTATE\fP جدا از تحلیل‌گر لغوی اصلی. این مورد تنها برای زبان‌هایی کار می‌کند که از \fBgoto\fP پشتیبانی می‌کنند (نه در حالت \fB\-\-loop\-switch\fP). .IP \(bu 2 استفاده از \fBre2c:eof\fP و روش \fI\%sentinel with bounds checks\fP برای مدیریت پایان ورودی. روش مبتنی بر لایه‌گذاری (padding) ممکن است کار نکند زیرا مشخص نیست چه زمانی باید لایه‌گذاری را اضافه کرد: پایان فعلی ورودی ممکن است پایان نهایی ورودی نباشد، و اضافه کردن زودهنگام لایه‌گذاری ممکن است نشانهٔ لغویِ (lexeme) حریصانه‌ای را که بخشی از آن خوانده شده، ناقص قطع کند. علاوه بر این، با توجه به منطق سطح‌بالای برنامه، دریافت ورودی بیشتر ممکن است به پردازش نشانهٔ لغوی انتهای بافر وابسته باشد (که از پیش به خاطر شرایط پایان ورودی مسدود شده است). .UNINDENT .sp در ادامه نمونه‌ای از یک تحلیل‌گر لغوی مدل «رانشی» (\(dqpush\(dq) آمده است که خواندن بسته‌ها از یک سوکت را شبیه‌سازی می‌کند. تحلیل‌گر لغوی حلقه می‌زند تا به پایان ورودی برسد و به تابع فراخواننده بازگردد. تابع فراخواننده با «ارسال» بستهٔ بعدی، ورودی بیشتری فراهم می‌کند و تحلیل لغوی را ادامه می‌دهد. این فرایند زمانی متوقف می‌شود که همهٔ بسته‌ها ارسال شده باشند یا خطایی رخ دهد. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C // re2c $INPUT \-o $OUTPUT \-f #include #include #include #define DEBUG 0 #define LOG(...) if (DEBUG) fprintf(stderr, __VA_ARGS__); // Use a small buffer to cover the case when a lexeme doesn\(aqt fit. // In real world use a larger buffer. #define BUFSIZE 10 typedef struct { FILE *file; char buf[BUFSIZE + 1], *lim, *cur, *mar, *tok; int state; } State; typedef enum {END, READY, WAITING, BAD_PACKET, BIG_PACKET} Status; static Status fill(State *st) { const size_t shift = st\->tok \- st\->buf; const size_t used = st\->lim \- st\->tok; const size_t free = BUFSIZE \- used; // Error: no space. In real life can reallocate a larger buffer. if (free < 1) return BIG_PACKET; // Shift buffer contents (discard already processed data). memmove(st\->buf, st\->tok, used); st\->lim \-= shift; st\->cur \-= shift; st\->mar \-= shift; st\->tok \-= shift; // Fill free space at the end of buffer with new data. const size_t read = fread(st\->lim, 1, free, st\->file); st\->lim += read; st\->lim[0] = 0; // append sentinel symbol return READY; } static Status lex(State *st, unsigned int *recv) { char yych; /*!getstate:re2c*/ for (;;) { st\->tok = st\->cur; /*!re2c re2c:api:style = free\-form; re2c:define:YYCTYPE = \(dqunsigned char\(dq; re2c:define:YYCURSOR = \(dqst\->cur\(dq; re2c:define:YYMARKER = \(dqst\->mar\(dq; re2c:define:YYLIMIT = \(dqst\->lim\(dq; re2c:define:YYGETSTATE = \(dqst\->state\(dq; re2c:define:YYSETSTATE = \(dqst\->state = @@;\(dq; re2c:define:YYFILL = \(dqreturn WAITING;\(dq; re2c:eof = 0; packet = [a\-z]+[;]; * { return BAD_PACKET; } $ { return END; } packet { *recv = *recv + 1; continue; } */ } } void test(const char **packets, Status expect) { // Create a \(dqsocket\(dq (open the same file for reading and writing). const char *fname = \(dqpipe\(dq; FILE *fw = fopen(fname, \(dqw\(dq); FILE *fr = fopen(fname, \(dqr\(dq); setvbuf(fw, NULL, _IONBF, 0); setvbuf(fr, NULL, _IONBF, 0); // Initialize lexer state: \(gastate\(ga value is \-1, all pointers are at the end // of buffer. State st; st.file = fr; st.cur = st.mar = st.tok = st.lim = st.buf + BUFSIZE; // Sentinel (at YYLIMIT pointer) is set to zero, which triggers YYFILL. st.lim[0] = 0; st.state = \-1; // Main loop. The buffer contains incomplete data which appears packet by // packet. When the lexer needs more input it saves its internal state and // returns to the caller which should provide more input and resume lexing. Status status; unsigned int send = 0, recv = 0; for (;;) { status = lex(&st, &recv); if (status == END) { LOG(\(dqdone: got %u packets\en\(dq, recv); break; } else if (status == WAITING) { LOG(\(dqwaiting...\en\(dq); if (*packets) { LOG(\(dqsent packet %u\en\(dq, send); fprintf(fw, \(dq%s\(dq, *packets++); ++send; } status = fill(&st); LOG(\(dqqueue: \(aq%s\(aq\en\(dq, st.buf); if (status == BIG_PACKET) { LOG(\(dqerror: packet too big\en\(dq); break; } assert(status == READY); } else { assert(status == BAD_PACKET); LOG(\(dqerror: ill\-formed packet\en\(dq); break; } } // Check results. assert(status == expect); if (status == END) assert(recv == send); // Cleanup: remove input file. fclose(fw); fclose(fr); remove(fname); } int main() { const char *packets1[] = {0}; const char *packets2[] = {\(dqzero;\(dq, \(dqone;\(dq, \(dqtwo;\(dq, \(dqthree;\(dq, \(dqfour;\(dq, 0}; const char *packets3[] = {\(dqzer0;\(dq, 0}; const char *packets4[] = {\(dqlooooooooooong;\(dq, 0}; test(packets1, END); test(packets2, END); test(packets3, BAD_PACKET); test(packets4, BIG_PACKET); return 0; } .ft P .fi .UNINDENT .UNINDENT.SS بلوک‌های قابل استفاده مجدد (Reusable blocks) .sp بلوک‌های قابل استفاده مجدد در قالب \fB/*!rules:re2c[:] ... */\fP یا \fB%{rules[:] ... %}\fP می‌توانند به هر تعداد بار مورد استفادهٔ مجدد قرار گیرند و با سایر بلوک‌های re2c ترکیب شوند. بخش \fB\fP اختیاری است. یک بلوک rules می‌تواند در یک بلوک یا دستورالعمل \fBuse\fP استفاده شود. کد مربوط به یک بلوک rules در هر نقطه از استفاده تولید می‌شود. .sp بلوک‌های use با \fB/*!use:re2c[:] ... */\fP یا \fB%{use[:] ... %}\fP\& تعریف می‌شوند. بخش \fB\fP اختیاری است: اگر مشخص نشود، بلوک rules مرتبط جدیدترین بلوک تعریف‌شده خواهد بود (چه نام‌دار باشد و چه بی‌نام). یک بلوک use می‌تواند تعاریف نام‌دار، پیکربندی‌ها و قواعد مختص به خود را اضافه کند. یک مورد کاربرد مهم برای بلوک‌های use، تحلیل‌گر لغوی است که از چندین کدگذاری ورودی پشتیبانی می‌کند: همان بلوک rules چندین بار با پیکربندی‌های مختص هر کدگذاری (encoding\-specific) مجدداً استفاده می‌شود (مثال زیر را ببینید). .sp دستورالعمل درون‌بلوکی use با ساختار \fB!use:;\fP می‌تواند از داخل یک بلوک re2c استفاده شود. این دستور، بلوک ارجاع‌داده‌شده با نام \fB\fP را در بلوک فعلی ادغام می‌کند. اگر برخی از قواعد و پیکربندی‌های ادغام‌شده با موارد تعریف‌شدهٔ پیشین هم‌پوشانی داشته باشند، تداخل‌ها به روش معمول برطرف می‌شوند: نخستین قاعده اولویت دارد، و جدیدترین پیکربندی موارد قبلی را بازنویسی می‌کند. یک استثنا، قواعد ویژهٔ \fB*\fP، \fB$\fP و (در حالت شرطی) \fB\fP هستند که برای آن‌ها تعریف محلی درون بلوک، بر هر تعریف به ارث‌رسیده‌ای اولویت دارد. دستورالعمل use به شما اجازه می‌دهد بلوک‌های مختلف re2c را با یکدیگر در یک بلوک ترکیب کنید (مثال زیر را ببینید). .sp بلوک‌های نام‌دار و دستورالعمل use درون‌بلوکی در نسخهٔ 2.2 ابزار re2c اضافه شدند. از آن نسخه به بعد، بلوک‌های قابل استفاده مجدد به‌طور پیش‌فرض مجاز هستند (نیازی به گزینهٔ خاصی نیست). پیش از نسخهٔ 2.2، حالت استفادهٔ مجدد با گزینهٔ \fB\-r \-\-reusable\fP فعال می‌شد. پیش از نسخهٔ 1.2، بلوک‌های قابل استفاده مجدد نمی‌توانستند با بلوک‌های معمولی ترکیب شوند. .SS مثالی از دستورالعمل \fB!use\fP (Example of a \fB!use\fP directive) .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C // re2c $INPUT \-o $OUTPUT #include // This example shows how to combine reusable re2c blocks: two blocks // (\(aqcolors\(aq and \(aqfish\(aq) are merged into one. The \(aqsalmon\(aq rule occurs // in both blocks; the \(aqfish\(aq block takes priority because it is used // earlier. Default rule * occurs in all three blocks; the local (not // inherited) definition takes priority. typedef enum { COLOR, FISH, DUNNO } What; /*!rules:re2c:colors * { assert(false); } \(dqred\(dq | \(dqsalmon\(dq | \(dqmagenta\(dq { return COLOR; } */ /*!rules:re2c:fish * { assert(false); } \(dqhaddock\(dq | \(dqsalmon\(dq | \(dqeel\(dq { return FISH; } */ static What lex(const char *s) { const char *YYCURSOR = s, *YYMARKER; /*!re2c re2c:yyfill:enable = 0; re2c:define:YYCTYPE = \(dqunsigned char\(dq; !use:fish; !use:colors; * { return DUNNO; } // overrides inherited \(aq*\(aq rules */ } int main() { assert(lex(\(dqsalmon\(dq) == FISH); assert(lex(\(dqwhat?\(dq) == DUNNO); return 0; } .ft P .fi .UNINDENT .UNINDENT .SS مثالی از بلوک \fB/*!use:re2c ... */\fP (Example of a \fB/*!use:re2c ... */\fP block) .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C // re2c $INPUT \-o $OUTPUT \-\-input\-encoding utf8 #include #include // This example supports multiple input encodings: UTF\-8 and UTF\-32. // Both lexers are generated from the same rules block, and the use // blocks add only encoding\-specific configurations. /*!rules:re2c re2c:yyfill:enable = 0; \(dq∀x ∃y\(dq { return 0; } * { return 1; } */ static int lex_utf8(const uint8_t *s) { const uint8_t *YYCURSOR = s, *YYMARKER; /*!use:re2c re2c:define:YYCTYPE = uint8_t; re2c:encoding:utf8 = 1; */ } static int lex_utf32(const uint32_t *s) { const uint32_t *YYCURSOR = s, *YYMARKER; /*!use:re2c re2c:define:YYCTYPE = uint32_t; re2c:encoding:utf32 = 1; */ } int main() { static const uint8_t s8[] = // UTF\-8 { 0xe2, 0x88, 0x80, 0x78, 0x20, 0xe2, 0x88, 0x83, 0x79 }; static const uint32_t s32[] = // UTF32 { 0x00002200, 0x00000078, 0x00000020, 0x00002203, 0x00000079 }; assert(lex_utf8(s8) == 0); assert(lex_utf32(s32) == 0); return 0; } .ft P .fi .UNINDENT .UNINDENT.SS "استخراج تطابق‌های فرعی (Submatch extraction)" .sp ابزار re2c دو روش برای استخراج تطابق‌های فرعی دارد. .INDENT 0.0 .TP .B \fBTags\fP روش نخست، استفاده از \fIبرچسب‌های (tags)\fP مستقل به فرم \fB@stag\fP یا \fB#mtag\fP است، که در آن \fBstag\fP و \fBmtag\fP نام‌های دلخواه تعریف‌شده توسط کاربر هستند. برچسب‌ها با گزینهٔ \fB\-T \-\-tags\fP یا پیکربندی \fBre2c:tags = 1\fP فعال می‌شوند. از نظر معنایی، برچسب‌ها نشانگرهای موقعیت هستند: آن‌ها می‌توانند در هر کجای یک عبارت منظم درج شوند، و به موقعیت (یا چندین موقعیت) متناظر در رشتهٔ ورودی مقید گردند. \fIS\-tag\fPها به آخرین موقعیت تطبیق‌یافته مقید می‌شوند، و \fIm\-tag\fPها به فهرستی از موقعیت‌ها مقید می‌گردند (می‌توان از آن‌ها در زیرعبارت‌های تکرار شونده استفاده کرد، جایی که یک موقعیت منفرد در یک عبارت منظم با چندین موقعیت در رشتهٔ ورودی مطابقت دارد). تمام برچسب‌ها باید توسط کاربر، به‌صورت دستی یا با کمک بلوک‌های \fBsvars\fP و \fBmvars\fP تعریف شوند. اگر بیش از یک روش برای تطبیق برچسب‌ها با ورودی وجود داشته باشد، رفع ابهام با استفاده از راهبرد چپ‌ترین حریصانه (leftmost greedy) انجام می‌گیرد. .TP .B \fBCaptures\fP روش دوم، استفاده از \fIگروه‌های گیرانداز (capturing groups)\fP است\&. آن‌ها با گزینهٔ \fB\-\-captures\fP یا پیکربندی \fBre2c:captures = 1\fP فعال می‌شوند. دو حالت مختلف برای سیاست‌های رفع ابهام وجود دارد؛ \fB\-\-leftmost\-captures\fP (پیش‌فرض) برای سیاست چپ‌ترین حریصانه (leftmost greedy)، و \fB\-\-posix\-captures\fP برای سیاست طولانی‌ترین تطابق پازیکس (POSIX longest\-match) است. در این حالت تمام زیرعبارت‌های داخل پرانتز به عنوان گروه‌های گیرانداز در نظر گرفته می‌شوند، و می‌توان از علامت تعجب برای مشخص کردن گروه‌های غیرگیرانداز استفاده کرد: \fB(! ... )\fP\&. با گزینهٔ \fB\-\-invert\-captures\fP یا پیکربندی \fBre2c:invert\-captures = 1\fP، معنای علامت تعجب معکوس می‌شود. تعداد گروه‌ها برای قاعدهٔ تطبیق‌یافته در متغیر \fByynmatch\fP ذخیره می‌شود (کل عبارت منظم، گروه شماره صفر است)، و نتایج تطابق فرعی در آرایهٔ \fByypmatch\fP ذخیره می‌گردند. هر دو متغیر \fByynmatch\fP و \fByypmatch\fP باید توسط کاربر تعریف شوند، و اندازهٔ \fByypmatch\fP باید حداقل \fB[yynmatch * 2]\fP باشد\&. از بلوک \fBmaxnmatch\fP برای تعریف \fBYYMAXNMATCH\fP استفاده کنید؛ ثابتی که برابر با بیشینهٔ مقدار \fByynmatch\fP در میان تمام قواعد است. .TP .B \fBCaptvars\fP روش دیگر برای استفاده از گروه‌های گیرانداز، گزینهٔ \fB\-\-captvars\fP یا پیکربندی \fBre2c:captvars = 1\fP است. تنها تفاوت با \fB\-\-captures\fP در شیوهٔ ذخیره نتایج تطابق فرعی توسط کد تولیدشده است: به‌جای \fByynmatch\fP و \fByypmatch\fP، ابزار re2c متغیرهای \fByytl\fP و \fByytr\fP را برای \fIk\fP\-امین گروه گیرانداز تولید می‌کند (کاربر باید این متغیرها را با استفاده از یک بلوک \fBsvars\fP اعلان کند). گیراندازی با متغیرها از دو سیاست رفع ابهام پشتیبانی می‌کند: \fB\-\-leftmost\-captvars\fP یا \fBre2c:leftmost\-captvars = 1\fP برای سیاست چپ‌ترین حریصانه (حالت پیش‌فرض) و \fB\-\-posix\-captvars\fP یا \fBre2c:posix\-captvars\fP برای سیاست طولانی‌ترین تطابق پازیکس. .UNINDENT .sp در پشت صحنه، تمام این گزینه‌ها به برچسب‌ها و \fI\%ماشین‌های خودکاره متناهی معین برچسب‌دار با پیش‌نگری (Tagged Deterministic Finite Automata with Lookahead)\fP ترجمه می‌شوند\&. ایدهٔ اصلی TDFA، به حداقل رساندن سربار استخراج تطابق فرعی است. در حالت حدی، اگر هیچ برچسب یا گروه گیراندازی در عبارت منظم وجود نداشته باشد، TDFA صرفاً یک DFA معمولی خواهد بود. اگر تعداد برچسب‌ها متعادل باشد، این سربار به‌ندرت محسوس است. ماشین TDFA تولیدشده از تعدادی \fIمتغیر برچسب (tag variables)\fP استفاده می‌کند که مستقیماً به برچسب‌ها نگاشت نمی‌شوند: یک متغیر واحد ممکن است برای برچسب‌های متفاوتی به کار رود، و یک برچسب ممکن است برای نگهداری تمام مقادیر احتمالی خود به چندین متغیر نیاز داشته باشد. در نهایت، ابهام برطرف شده و برای هر برچسب تنها یک متغیر نهایی باقی می‌ماند. متغیرهای برچسب باید با استفاده از بلوک‌های \fBstags\fP یا \fBmtags\fP تعریف شوند. اگر وضعیت تحلیل‌گر لغوی (lexer) ذخیره می‌شود، متغیرهای برچسب نیز باید بخشی از آن باشند. آن‌ها همچنین باید توسط \fBYYFILL\fP به‌روزرسانی شوند\&. .sp برچسب‌های S از عملیات‌های زیر پشتیبانی می‌کنند: .INDENT 0.0 .IP \(bu 2 ذخیرهٔ موقعیت ورودی در یک s\-tag: عبارت \fBt = YYCURSOR\fP با API اشاره‌گر C یا عملیات تعریف‌شده توسط کاربر \fBYYSTAGP(t)\fP با API عمومی (generic) .IP \(bu 2 ذخیرهٔ مقدار پیش‌فرض در یک s\-tag: عبارت \fBt = NULL\fP با API اشاره‌گر C یا عملیات تعریف‌شده توسط کاربر \fBYYSTAGN(t)\fP با API عمومی .IP \(bu 2 کپی کردن یک s\-tag در دیگری: \fBt1 = t2\fP .UNINDENT .sp برچسب‌های M از عملیات‌های زیر پشتیبانی می‌کنند: .INDENT 0.0 .IP \(bu 2 افزودن موقعیت ورودی به یک m\-tag: عملیات تعریف‌شده توسط کاربر \fBYYMTAGP(t)\fP با هر دو API پیش‌فرض و عمومی .IP \(bu 2 افزودن مقدار پیش‌فرض به یک m\-tag: عملیات تعریف‌شده توسط کاربر \fBYYMTAGN(t)\fP با هر دو API پیش‌فرض و عمومی .IP \(bu 2 کپی کردن یک m\-tag در دیگری: \fBt1 = t2\fP .UNINDENT .sp برچسب‌های S می‌توانند به صورت مقادیر اسکالر (اشاره‌گرها یا آفست‌ها) پیاده‌سازی شوند. برچسب‌های M به نمایش پیچیده‌تری نیاز دارند، چرا که باید دنباله‌ای از مقادیر برچسب را ذخیره کنند. ساده‌ترین و ناکارآمدترین نمایش برای یک m\-tag، فهرستی (آرایه، بردار) از مقادیر برچسب است؛ روش کارآمدتر، ذخیرهٔ تمام m\-tagها در یک درخت پیشوندی (prefix\-tree) است که به صورت آرایه‌ای از گره‌های \fB(v, p)\fP نمایش داده می‌شود، که در آن \fBv\fP مقدار برچسب و \fBp\fP اشاره‌گری به گره والد است. .sp در اینجا یک مثال ساده از کاربرد s\-tagها برای تجزیهٔ نگارش‌های معنایی (semantic versions) متشکل از سه مؤلفهٔ عددی آورده شده است: major، minor و patch (مورد آخر اختیاری است). برای مثال پیچیده‌تری که از \fBYYFILL\fP استفاده می‌کند، به ادامه مراجعه نمایید\&. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C // re2c $INPUT \-o $OUTPUT #include #include typedef struct { int major, minor, patch; } SemVer; static int s2n(const char *s, const char *e) { // pre\-parsed string to number int n = 0; for (; s < e; ++s) n = n * 10 + (*s \- \(aq0\(aq); return n; } static int lex(const char *str, SemVer *ver) { const char *YYCURSOR = str, *YYMARKER; // User\-defined tag variables that are available in semantic action. const char *t1, *t2, *t3, *t4, *t5; // Autogenerated tag variables used by the lexer to track tag values. /*!stags:re2c format = \(aqconst char *@@;\en\(aq; */ /*!re2c re2c:yyfill:enable = 0; re2c:define:YYCTYPE = \(dqunsigned char\(dq; re2c:tags = 1; num = [0\-9]+; @t1 num @t2 \(dq.\(dq @t3 num @t4 (\(dq.\(dq @t5 num)? [\ex00] { ver\->major = s2n(t1, t2); ver\->minor = s2n(t3, t4); ver\->patch = t5 != NULL ? s2n(t5, YYCURSOR \- 1) : 0; return 0; } * { return 1; } */ } int main() { SemVer v; assert(lex(\(dq23.34\(dq, &v) == 0 && v.major == 23 && v.minor == 34 && v.patch == 0); assert(lex(\(dq1.2.999\(dq, &v) == 0 && v.major == 1 && v.minor == 2 && v.patch == 999); assert(lex(\(dq1.a\(dq, &v) == 1); return 0; } .ft P .fi .UNINDENT .UNINDENT .sp در اینجا مثال پیچیده‌تری از کاربرد s\-tagها همراه با \fBYYFILL\fP برای تجزیهٔ یک فایل با نگارش‌های معنایی جداشده با خط جدید آمده است. متغیرهای برچسب بخشی از وضعیت تحلیل‌گر لغوی هستند، و همانند سایر موقعیت‌های ورودی در \fBYYFILL\fP تنظیم می‌شوند. توجه داشته باشید که این کار برای s\-tagها ضروری است، زیرا مقادیر آن‌ها پس از جابه‌جایی محتویات بافر نامعتبر می‌شوند. این امر ممکن است در پیاده‌سازی‌های سفارشی که متغیرهای برچسب در آن‌ها آفست‌های نسبی نسبت به ابتدای رشتهٔ ورودی (به‌جای بافر) را ذخیره می‌کنند ضروری نباشد، که می‌تواند برای m\-tagها این‌گونه باشد. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C // re2c $INPUT \-o $OUTPUT \-\-tags #include #include #include #include #include #define BUFSIZE 4095 struct Input { FILE *file; char buf[BUFSIZE + 1], *lim, *cur, *mar, *tok; // Tag variables must be part of the lexer state passed to YYFILL. // They don\(aqt correspond to tags and should be autogenerated by re2c. /*!stags:re2c format = \(aqconst char *@@;\(aq; */ bool eof; }; struct SemVer { int major, minor, patch; }; static bool operator==(const SemVer &x, const SemVer &y) { return x.major == y.major && x.minor == y.minor && x.patch == y.patch; } static int s2n(const char *s, const char *e) { // pre\-parsed string to number int n = 0; for (; s < e; ++s) n = n * 10 + (*s \- \(aq0\(aq); return n; } static int fill(Input &in) { if (in.eof) return 1; const size_t shift = in.tok \- in.buf; const size_t used = in.lim \- in.tok; // Error: lexeme too long. In real life could reallocate a larger buffer. if (shift < 1) return 2; // Shift buffer contents (discard everything up to the current token). memmove(in.buf, in.tok, used); in.lim \-= shift; in.cur \-= shift; in.mar \-= shift; in.tok \-= shift; // Tag variables need to be shifted like other input positions. The check // for non\-NULL is only needed if some tags are nested inside of alternative // or repetition, so that they can have NULL value. /*!stags:re2c format = \(dqif (in.@@) in.@@ \-= shift;\en\(dq; */ // Fill free space at the end of buffer with new data from file. in.lim += fread(in.lim, 1, BUFSIZE \- used, in.file); in.lim[0] = 0; in.eof = in.lim < in.buf + BUFSIZE; return 0; } static bool lex(Input &in, std::vector &vers) { // User\-defined local variables that store final tag values. // They are different from tag variables autogenerated with \(gastags:re2c\(ga, // as they are set at the end of match and used only in semantic actions. const char *t1, *t2, *t3, *t4; for (;;) { in.tok = in.cur; /*!re2c re2c:eof = 0; re2c:api:style = free\-form; re2c:define:YYCTYPE = \(dqunsigned char\(dq; re2c:define:YYCURSOR = in.cur; re2c:define:YYMARKER = in.mar; re2c:define:YYLIMIT = in.lim; re2c:define:YYFILL = \(dqfill(in) == 0\(dq; re2c:tags:expression = \(dqin.@@\(dq; num = [0\-9]+; num @t1 \(dq.\(dq @t2 num @t3 (\(dq.\(dq @t4 num)? [\en] { int major = s2n(in.tok, t1); int minor = s2n(t2, t3); int patch = t4 != NULL ? s2n(t4, in.cur \- 1) : 0; SemVer ver = {major, minor, patch}; vers.push_back(ver); continue; } $ { return true; } * { return false; } */} }int main() { const char *fname = \(dqinput\(dq; const SemVer semver = {1, 22, 333}; std::vector expect(BUFSIZE, semver), actual; // Prepare input file (make sure it exceeds buffer size). FILE *f = fopen(fname, \(dqw\(dq); for (int i = 0; i < BUFSIZE; ++i) fprintf(f, \(dq1.22.333\en\(dq); fclose(f); // Reopen input file for reading. f = fopen(fname, \(dqr\(dq); // Initialize lexer state: all pointers are at the end of buffer. Input in; in.file = f; in.cur = in.mar = in.tok = in.lim = in.buf + BUFSIZE; /*!stags:re2c format = \(dqin.@@ = in.lim;\en\(dq; */ in.eof = false; // Sentinel (at YYLIMIT pointer) is set to zero, which triggers YYFILL. *in.lim = 0; // Run the lexer and check results. assert(lex(in, actual) && expect == actual); // Cleanup: remove input file. fclose(f); remove(fname); return 0; } .ft P .fi .UNINDENT .UNINDENT .sp در اینجا مثالی از به‌کارگیری گروه‌های گیرانداز (capturing groups) برای تجزیه نگارش‌های معنایی آورده شده است. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C // re2c $INPUT \-o $OUTPUT #include #include typedef struct { int major, minor, patch; } SemVer; static int s2n(const char *s, const char *e) { // pre\-parsed string to number int n = 0; for (; s < e; ++s) n = n * 10 + (*s \- \(aq0\(aq); return n; } static int lex(const char *str, SemVer *ver) { const char *YYCURSOR = str, *YYMARKER; // Final tag variables available in semantic action. /*!svars:re2c format = \(aqconst char *@@;\en\(aq; */ // Intermediate tag variables used by the lexer (must be autogenerated). /*!stags:re2c format = \(aqconst char *@@;\en\(aq; */ /*!re2c re2c:yyfill:enable = 0; re2c:define:YYCTYPE = \(dqunsigned char\(dq; re2c:captvars = 1; num = [0\-9]+; (num) \(dq.\(dq (num) (\(dq.\(dq num)? [\ex00] { (void) yytl0; (void) yytr0; // some variables are unused ver\->major = s2n(yytl1, yytr1); ver\->minor = s2n(yytl2, yytr2); ver\->patch = yytl3 ? s2n(yytl3 + 1, yytr3) : 0; return 0; } * { return 1; } */ } int main() { SemVer v; assert(lex(\(dq23.34\(dq, &v) == 0 && v.major == 23 && v.minor == 34 && v.patch == 0); assert(lex(\(dq1.2.999\(dq, &v) == 0 && v.major == 1 && v.minor == 2 && v.patch == 999); assert(lex(\(dq1.a\(dq, &v) == 1); return 0; } .ft P .fi .UNINDENT .UNINDENT .sp در اینجا مثالی از به‌کارگیری m\-tagها برای تجزیه نگارشی با تعداد متغیری از مؤلفه‌ها آورده شده است. متغیرهای برچسب در یک trie ذخیره می‌شوند. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C // re2c $INPUT \-o $OUTPUT #include #include #include static const int MTAG_ROOT = \-1; // An m\-tag tree is a way to store histories with an O(1) copy operation. // Histories naturally form a tree, as they have common start and fork at some // point. The tree is stored as an array of pairs (tag value, link to parent). // An m\-tag is represented with a single link in the tree (array index). struct Mtag { const char *elem; // tag value int pred; // index of the predecessor node or root }; typedef std::vector MtagTrie; typedef std::vector Ver; // unbounded number of version components static int s2n(const char *s, const char *e) { // pre\-parsed string to number int n = 0; for (; s < e; ++s) n = n * 10 + (*s \- \(aq0\(aq); return n; } // Append a single value to an m\-tag history. static void add_mtag(MtagTrie &trie, int &mtag, const char *value) { Mtag m = {value, mtag}; mtag = (int)trie.size(); trie.push_back(m); } // Recursively unwind tag histories and collect version components. static void unfold(const MtagTrie &trie, int x, int y, Ver &ver) { // Reached the root of the m\-tag tree, stop recursion. if (x == MTAG_ROOT && y == MTAG_ROOT) return; // Unwind history further. unfold(trie, trie[x].pred, trie[y].pred, ver); // Get tag values. Tag histories must have equal length. assert(x != MTAG_ROOT && y != MTAG_ROOT); const char *ex = trie[x].elem, *ey = trie[y].elem; if (ex != NULL && ey != NULL) { // Both tags are valid pointers, extract component. ver.push_back(s2n(ex, ey)); } else { // Both tags are NULL (this corresponds to zero repetitions). assert(ex == NULL && ey == NULL); } } static bool parse(const char *str, Ver &ver) { const char *YYCURSOR = str, *YYMARKER; MtagTrie mt; // User\-defined tag variables that are available in semantic action. const char *t1, *t2; int t3, t4; // Autogenerated tag variables used by the lexer to track tag values. /*!stags:re2c format = \(aqconst char *@@ = NULL;\(aq; */ /*!mtags:re2c format = \(aqint @@ = MTAG_ROOT;\(aq; */ /*!re2c re2c:api:style = free\-form; re2c:define:YYCTYPE = \(dqunsigned char\(dq; re2c:define:YYSTAGP = \(dq@@ = YYCURSOR;\(dq; re2c:define:YYSTAGN = \(dq@@ = NULL;\(dq; re2c:define:YYMTAGP = \(dqadd_mtag(mt, @@, YYCURSOR);\(dq; re2c:define:YYMTAGN = \(dqadd_mtag(mt, @@, NULL);\(dq; re2c:yyfill:enable = 0; re2c:tags = 1; num = [0\-9]+; @t1 num @t2 (\(dq.\(dq #t3 num #t4)* [\ex00] { ver.clear(); ver.push_back(s2n(t1, t2)); unfold(mt, t3, t4, ver); return true; } * { return false; } */ } int main() { Ver v; assert(parse(\(dq1\(dq, v) && v == Ver({1})); assert(parse(\(dq1.2.3.4.5.6.7\(dq, v) && v == Ver({1, 2, 3, 4, 5, 6, 7})); assert(!parse(\(dq1.2.\(dq, v)); return 0; } .ft P .fi .UNINDENT .UNINDENT.SS "پشتیبانی از کدگذاری (Encoding support)" .sp درک تفاوت میان \fBنقطه‌کدها (code points)\fP و \fBواحدهای کد (code units)\fP ضروری است\&. نقطه‌کد، یک شناسهٔ عددی برای یک نماد است. واحد کد، کوچک‌ترین واحد ذخیره‌سازی در متن کدگذاری‌شده است. یک نقطه‌کد می‌تواند با یک یا چند واحد کد نمایش داده شود. در کدگذاری با طول ثابت (fixed\-length)، تمامی نقطه‌کدها با تعداد یکسانی از واحدهای کد نمایش می‌یابند. در کدگذاری با طول متغیر (variable\-length)، نقطه‌کدها ممکن است با تعداد متفاوتی از واحدهای کد نمایش داده شوند. توجه داشته باشید که قاعدهٔ \(dqany\(dq (هر چیز) \fB[^]\fP با هر نقطه‌کدی مطابقت می‌یابد، اما لزوماً با هر واحد کد مطابقت ندارد (تنها روش برای تطبیق با هر واحد کد بدون در نظر گرفتن نوع کدگذاری، قاعدهٔ پیش‌فرض \fB*\fP است). تحلیل‌گر لغوی تولیدشده با جریانی از واحدهای کد کار می‌کند: \fByych\fP یک واحد کد را ذخیره می‌کند و \fBYYCTYPE\fP نوع دادهٔ واحد کد است. در مقابل، عبارت‌های منظم بر اساس نقطه‌کدها مشخص می‌شوند. هنگامی که re2c عبارت‌های منظم را به اتوماتا کامپایل می‌کند، نقطه‌کدها را به واحدهای کد ترجمه می‌کند. این امر عموماً یک نگاشت ساده نیست: در کدگذاری‌های با طول متغیر، بازه‌ای از یک نقطه‌کد ممکن است به گرافی پیچیده از واحدهای کد ترجمه شود. کدگذاری‌های زیر پشتیبانی می‌شوند: .INDENT 0.0 .IP \(bu 2 \fBASCII\fP (به‌طور پیش‌فرض فعال است). یک کدگذاری با طول ثابت با فضای کد \fB[0\-255]\fP و نقطه‌کدها و واحدهای کد ۱ بایتی است. .IP \(bu 2 \fBEBCDIC\fP (با \fB\-\-ebcdic\fP یا \fBre2c:encoding:ebcdic\fP فعال می‌شود). یک کدگذاری با طول ثابت با فضای کد \fB[0\-255]\fP و نقطه‌کدها و واحدهای کد ۱ بایتی است. .IP \(bu 2 \fBUCS2\fP (با \fB\-\-ucs2\fP یا \fBre2c:encoding:ucs2\fP فعال می‌شود). یک کدگذاری با طول ثابت با فضای کد \fB[0\-0xFFFF]\fP و نقطه‌کدها و واحدهای کد ۲ بایتی است. .IP \(bu 2 \fBUTF8\fP (با \fB\-\-utf8\fP یا \fBre2c:encoding:utf8\fP فعال می‌شود). یک کدگذاری یونیکد با طول متغیر است. اندازهٔ واحد کد ۱ بایت است. نقطه‌کدها با ۱ تا ۴ واحد کد نمایش داده می‌شوند. .IP \(bu 2 \fBUTF16\fP (با \fB\-\-utf16\fP یا \fBre2c:encoding:utf16\fP فعال می‌شود). یک کدگذاری یونیکد با طول متغیر است. اندازهٔ واحد کد ۲ بایت است. نقطه‌کدها با ۱ تا ۲ واحد کد نمایش داده می‌شوند. .IP \(bu 2 \fBUTF32\fP (با \fB\-\-utf32\fP یا \fBre2c:encoding:utf32\fP فعال می‌شود). یک کدگذاری یونیکد با طول ثابت با فضای کد \fB[0\-0x10FFFF]\fP و نقطه‌کدها و واحدهای کد ۴ بایتی است. .UNINDENT .sp فایل‌های ضمیمهٔ \fBinclude/unicode_blocks.re\fP، \fBinclude/unicode_categories.re\fP و \fBinclude/unicode_properties.re\fP تعاریف re2c را برای بلوک‌ها، دسته‌بندی‌ها و ویژگی‌های توصیف‌شده در استاندارد Unicode فراهم می‌کنند. .sp گزینهٔ \fB\-\-input\-encoding\fP کدگذاری فایل مبدأ را مشخص می‌کند که می‌تواند برای فعال‌سازی نویسه‌واژه‌های (literals) یونیکد در عبارت‌های منظم استفاده شود. برای مثال \fB\-\-input\-encoding utf8\fP به re2c اعلام می‌کند که فایل منبع در قالب UTF8 است (این با گزینهٔ \fB\-\-utf8\fP که کدگذاری متن ورودی را تنظیم می‌کند متفاوت است). گزینهٔ \fB\-\-encoding\-policy\fP نحوهٔ برخورد re2c با جانشین‌های یونیکد (Unicode surrogates، نقطه‌کدهای موجود در بازهٔ \fB[0xD800\-0xDFFF]\fP) را تعیین می‌کند. .sp در زیر مثالی از یک تحلیل‌گر لغوی برای شناسه‌های یونیکد با کدگذاری UTF8 آمده است. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C // re2c $INPUT \-o $OUTPUT \-8 \-\-case\-ranges \-i #include #include /*!include:re2c \(dqunicode_categories.re\(dq */ static int lex(const char *s) { const char *YYCURSOR = s, *YYMARKER; /*!re2c re2c:define:YYCTYPE = \(dqunsigned char\(dq; re2c:yyfill:enable = 0; // Simplified \(dqUnicode Identifier and Pattern Syntax\(dq // (see https://unicode.org/reports/tr31) id_start = L | Nl | [$_]; id_continue = id_start | Mn | Mc | Nd | Pc | [\eu200D\eu05F3]; identifier = id_start id_continue*; identifier { return 0; } * { return 1; } */ } int main() { assert(lex(\(dq_Ыдентификатор\(dq) == 0); return 0; } .ft P .fi .UNINDENT .UNINDENT.SS "فایل‌های ضمیمه (Include files)" .sp ابزار re2c به شما اجازه می‌دهد فایل‌های دیگر را با استفاده از بلوکی به قالب \fB/*!include:re2c FILE */\fP یا \fB%{include FILE %}\fP، یا یک دستورالعمل درون‌بلوکیِ \fB!include FILE ;\fP ضمیمه کنید، که در آن \fBFILE\fP مسیر فایلی است که باید ضمیمه شود. re2c فایل‌های ضمیمه را در دایرکتوری فایلی که آن‌ها را ضمیمه کرده و همچنین در مکان‌های include (که می‌توان با گزینهٔ \fB\-I\fP تعیین کرد) جستجو می‌کند. بلوک‌ها/دستورالعمل‌های include در re2c همانند \fB#include\fP در C/C++ عمل می‌کنند: محتوای \fBFILE\fP عیناً به جای بلوک/دستورالعمل جای‌گذاری می‌شود. فایل‌های ضمیمه ممکن است خود دارای فایل‌های ضمیمهٔ دیگری باشند. برای ردیابی وابستگی‌های ساخت فایل خروجی به فایل‌های ضمیمه، از گزینهٔ \fB\-\-depfile\fP استفاده کنید. re2c چند فایل include از پیش تعریف‌شده ارائه می‌دهد که در زیردایرکتوری \fBinclude/\fP پروژه یافت می‌شوند. این فایل‌ها شامل تعاریفی هستند که ممکن است برای پروژه‌های دیگر نیز مفید باشند (مانند دسته‌بندی‌های Unicode) و چیزی شبیه به یک کتابخانهٔ استاندارد برای re2c می‌سازند\&. در ادامه مثالی از به‌کارگیری فایل‌های include آمده است. .SS "فایل ضمیمه ۱ (definitions.h)" .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C typedef enum { OK, FAIL } Result; /*!re2c number = [1\-9][0\-9]*; */ .ft P .fi .UNINDENT .UNINDENT .SS "فایل ضمیمه ۲ (extra_rules.re.inc)" .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C // floating\-point numbers frac = [0\-9]* \(dq.\(dq [0\-9]+ | [0\-9]+ \(dq.\(dq; exp = \(aqe\(aq [+\-]? [0\-9]+; float = frac exp? | [0\-9]+ exp; float { return OK; } .ft P .fi .UNINDENT .UNINDENT .SS "فایل ورودی (Input file)" .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C // re2c $INPUT \-o $OUTPUT \-i #include /*!include:re2c \(dqdefinitions.h\(dq */ Result lex(const char *s) { const char *YYCURSOR = s, *YYMARKER; /*!re2c re2c:define:YYCTYPE = \(dqunsigned char\(dq; re2c:yyfill:enable = 0; * { return FAIL; } number { return OK; } !include \(dqextra_rules.re.inc\(dq; */ } int main() { assert(lex(\(dq123\(dq) == OK); assert(lex(\(dq123.4567\(dq) == OK); return 0; } .ft P .fi .UNINDENT .UNINDENT.SS فایل‌های سرآیند (Header files) .sp ابزار re2c به شما اجازه می‌دهد با استفاده از گزینهٔ \fB\-\-header\fP یا پیکربندی \fBre2c:header\fP و جفت‌بلوک‌هایی به شکل \fB/*!header:re2c:on*/\fP و \fB/*!header:re2c:off*/\fP، یا \fB%{header:on%}\fP و \fB%{header:off%}\fP\&، از فایل ورودی \fB\&.re\fP فایل سرآیند تولید کنید. بلوک اول آغاز فایل سرآیند را مشخص می‌کند و بلوک دوم پایان آن را تعیین می‌نماید. هر آنچه بین این دو بلوک قرار گیرد توسط re2c پردازش می‌شود و کد تولیدشده در فایلی که با گزینهٔ \fB\-\-header\fP یا پیکربندی \fBre2c:header\fP مشخص شده (یا در صورت عدم استفاده از گزینه یا پیکربندی، در \fBstdout\fP) نوشته خواهد شد. تولید خودکار فایل سرآیند ممکن است در مواردی نیاز باشد که re2c برای تولید تعاریفی به کار می‌رود که باید از سایر واحدهای ترجمه (translation units) قابل مشاهده باشند. .sp در ادامه، مثالی از تولید یک فایل سرآیند آورده شده است که شامل تعریف وضعیت تحلیل‌گر با متغیرهای برچسب است (تعداد متغیرها به گرامر باقاعده بستگی دارد و برای برنامه‌نویس نامشخص است). .SS فایل ورودی (Input file) .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C // re2c $INPUT \-o $OUTPUT \-i \-\-header lexer/state.h #include #include #include \(dqlexer/state.h\(dq // the header is generated by re2c /*!header:re2c:on*/ typedef struct { const char *str, *cur; /*!stags:re2c format = \(dqconst char *@@;\(dq; */ } LexerState; /*!header:re2c:off*/ long lex(LexerState* st) { const char *t; /*!re2c re2c:header = \(dqlexer/state.h\(dq; re2c:yyfill:enable = 0; re2c:define:YYCTYPE = \(dqunsigned char\(dq; re2c:define:YYCURSOR = \(dqst\->cur\(dq; re2c:tags = 1; re2c:tags:expression = \(dqst\->@@\(dq; [a]* @t [b]* { return t \- st\->str; } */ } int main() { const char *s = \(dqab\(dq; LexerState st = { s, s /*!stags:re2c format = \(dq, NULL\(dq; */ }; assert(lex(&st) == 1); return 0; } .ft P .fi .UNINDENT .UNINDENT .SS فایل سرآیند (Header file) .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C /* Generated by re2c */ typedef struct { const char *str, *cur; const char *yyt1; } LexerState; .ft P .fi .UNINDENT .UNINDENT .SS برنامه‌های اسکلتی (Skeleton programs) .sp با گزینهٔ \fB\-S, \-\-skeleton\fP، ابزار re2c تمام کدهای غیر re2c را نادیده گرفته و یک برنامهٔ مستقل به زبان C تولید می‌کند که می‌تواند در ادامه کامپایل و اجرا شود. این برنامه شامل کد تحلیل‌گر و داده‌های ورودی است. برای هر DFA ساخته‌شده (بلوک یا شرط)، re2c یک تحلیل‌گر مستقل و دو فایل تولید می‌کند: یک فایل \fB\&.input\fP با رشته‌های مشتق‌شده از DFA و یک فایل \fB\&.keys\fP با نتایج تطابق مورد انتظار. برنامه هر تحلیل‌گر را بر روی فایل \fB\&.input\fP متناظر اجرا کرده و نتایج را با انتظارات مقایسه می‌کند. برنامه‌های اسکلتی به چند دلیل بسیار مفید هستند: .INDENT 0.0 .IP \(bu 2 می‌توانند درستی بهینه‌سازی‌های گوناگون re2c را بررسی کنند (داده‌ها در اوایل فرایند و پیش از انجام هرگونه تبدیل DFA تولید می‌شوند). .IP \(bu 2 تولید مجموعه‌ای از داده‌های ورودی با پوشش مناسب می‌تواند هم برای آزمون و هم برای محک‌زنی (benchmarking) مفید باشد. .IP \(bu 2 تولید برنامه‌های اجرایی مستقل اجازه می‌دهد موارد آزمون کمینه‌شده (minimized test cases) به دست آیند (کد اصلی ممکن است بزرگ بوده یا وابستگی‌های متعددی داشته باشد). .UNINDENT .sp دشواری تولید داده‌های ورودی در این است که به جز در ساده‌ترین حالت‌ها، تعداد رشته‌های ورودیِ ممکن بسیار زیاد است (حتی اگر طول رشته محدود باشد). re2c این دشواری را با تولید رشته‌های کافی به منظور پوشش دادن تقریباً تمام انتقال‌های DFA برطرف می‌کند. این ابزار از الگوریتم زیر استفاده می‌کند: ابتدا، اسکلتی از DFA می‌سازد. برای رمزگذاری‌هایی با اندازهٔ واحد کد ۱ بایتی (مانند ASCII، UTF\-8 و EBCDIC) اسکلت دقیقاً رونوشتی از DFA اصلی است. برای رمزگذاری‌هایی با واحدهای کد چندبایتی، اسکلت کپی‌ای از DFA با حذف برخی انتقال‌ها است: بدین صورت که re2c برای هر بازهٔ پیوسته و مجزا که با یک انتقال DFA متناظر است، حداکثر ۲۵۶ واحد کد برمی‌دارد. مقادیر انتخاب‌شده به‌طور یکنواخت توزیع شده و شامل کران‌های بازه نیز هستند. re2c به‌جای تلاش برای پوشش تمام مسیرهای ممکن در اسکلت (که کاری غیرعملی است)، مسیرهای کافی برای پوشش همهٔ انتقال‌های اسکلت را تولید می‌کند و بدین ترتیب پرش‌های شرطی مربوطه را در تحلیل‌گر فعال می‌سازد. پیاده‌سازی این الگوریتم به حدود ۱ گیگابایت انتقال محدود شده است و مقدار ثابتی از حافظه مصرف می‌کند (re2c داده‌ها را بلافاصله پس از تولید در فایل می‌نویسد)..SS "تصویرسازی و اشکال‌زدایی (Visualization and debug)" .sp با گزینهٔ \fB\-D, \-\-emit\-dot\fP، ابزار re2c کدی تولید نمی‌کند؛ در عوض، DFA تولیدشده را در قالب DOT خروجی می‌دهد (دامپ می‌کند). می‌توان این خروجی را با استفاده از Graphviz یا کتابخانه‌ای دیگر به تصویری از DFA تبدیل کرد. توجه داشته باشید که این گزینه، DFA نهایی را پس از گذر از چندین بهینه‌سازی و تبدیل نشان می‌دهد. مراحل پیشین را می‌توان با گزینه‌های اشکال‌زدایی مختلفی مانند \fB\-\-dump\-nfa\fP، \fB\-\-dump\-dfa\-raw\fP و غیره ذخیره کرد (فهرست کامل گزینه‌ها را ببینید). .SH "همچنین ببینید (SEE ALSO)" .sp می‌توانید اطلاعات بیشتری دربارهٔ re2c در وبگاه رسمی آن بیابید: \fI\%http://re2c.org\fP\&. برنامه‌های مشابه عبارتند از flex(1)، lex(1)، quex(\fI\%http://quex.sourceforge.net\fP). .SH "نویسندگان (AUTHORS)" .sp ابزار re2c در اصل در سال ۱۹۹۳ توسط Peter Bumbulis (\fI\%peter@csg.uwaterloo.ca\fP) نوشته شد. Marcus Boerger و Dan Nuffer چندین سال وقت صرف کردند تا ایدهٔ اولیه را به یک تولیدکنندهٔ کد آماده برای بهره‌برداری تبدیل کنند. از آن زمان به بعد، این پروژه توسط داوطلبان متعددی نگهداری و توسعه یافته است، به‌ویژه: Brian Young (\fI\%bayoung@acm.org\fP)، \fI\%Marcus Boerger\fP، Dan Nuffer (\fI\%nuffer@users.sourceforge.net\fP)، \fI\%Ulya Trofimovich\fP (\fI\%skvadrik@gmail.com\fP)، \fI\%Serghei Iakovlev\fP، \fI\%Sergei Trofimovich\fP، \fI\%Petr Skocik\fP، \fI\%ligfx\fP \fI\%raekye\fP و \fI\%PolarGoose\fP\&. .\" Generated by docutils manpage writer. .