.\" 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 "RE2D" 1 "" "" "" .SH "نام (NAME)" re2d \- تولید تحلیل‌گرهای لغوی سریع برای D .SH "خلاصه دستور (SYNOPSIS)" .sp re2d \fB[ OPTIONS ]\fP \fB[ WARNINGS ]\fP \fBINPUT\fP .sp ورودی می‌تواند یک فایل یا \fB\-\fP برای stdin باشد. .SH "مقدمه (INTRODUCTION)" .sp ابزار re2d به عنوان یک پیش‌پردازنده عمل می‌کند. این ابزار فایل ورودی را (که معمولاً یک برنامه به زبان D است، اما می‌تواند هر چیز دیگری نیز باشد) خوانده و به دنبال بلوک‌های کدی می‌گردد که در نشانگرهای آغاز/پایان با شکل خاص محصور شده‌اند. متن خارج از این بلوک‌ها عیناً به فایل خروجی رونویسی می‌شود. محتویات بلوک‌ها توسط re2d پردازش می‌شوند. این ابزار آن‌ها را به کد D ترجمه کرده و کد تولیدشده را به جای بلوک در خروجی قرار می‌دهد. .sp در ادامه مثالی از یک برنامه کوچک آمده است که بررسی می‌کند آیا یک رشته داده‌شده شامل یک عدد ده‌دهی است یا خیر: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C // re2d $INPUT \-o $OUTPUT \-i module main; private bool lex(const(char)* yycursor) { /*!re2c re2c:YYCTYPE = char; re2c:yyfill:enable = 0; [1\-9][0\-9]* { return true; } * { return false; } */ } void main() { assert(lex(\(dq1234\(dq)); } .ft P .fi .UNINDENT .UNINDENT .sp در خروجی، re2d بلوک میانی را با کد تولیدشده جایگزین کرده است: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C /* Generated by re2d */ // re2d $INPUT \-o $OUTPUT \-i module main; private bool lex(const(char)* yycursor) { { char yych; yych = *yycursor; switch (yych) { case \(aq1\(aq: .. case \(aq9\(aq: goto yy2; default: goto yy1; } yy1: ++yycursor; { return false; } yy2: yych = *++yycursor; switch (yych) { case \(aq0\(aq: .. case \(aq9\(aq: goto yy2; default: goto yy3; } yy3: { return true; } } } void main() { assert(lex(\(dq1234\(dq)); } .ft P .fi .UNINDENT .UNINDENT .SH "مفاهیم پایه (BASICS)" .sp یک برنامه re2d از دنباله‌ای از \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\%regular expressions\fP مروری کلی از نحو re2d برای عبارت‌های منظم ارائه می‌دهد. پس از تعریف، \fBname\fP می‌تواند در دیگر عبارت‌های منظم و در قواعد استفاده شود. بازگشت در تعاریف نام‌گذاری‌شده مجاز نیست و هر نام باید پیش از استفاده تعریف شود. یک بلوک تعاریف نام‌گذاری‌شده را از حوزه سراسری به ارث می‌برد. تعریف مجدد نامی که در حوزه کنونی وجود دارد، یک خطا است. .TP .B \fBconfiguration = value ;\fP یک \fIپیکربندی\fP امکان تغییر رفتار re2d و سفارشی‌سازی کد تولیدشده را فراهم می‌سازد. برای مشاهده فهرست کامل پیکربندی‌های پشتیبانی‌شده توسط re2d بخش \fI\%configurations\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\%encoding support\fP را ببینید). قاعده پایان ورودی در صورتی باید تعریف شود که روش متناظر برای \fI\%handling the end of input\fP استفاده شده باشد. با \fI\%start conditions\fP قواعد از نحو پیچیده‌تری برخوردار خواهند بود. .TP .B \fB!action code\fP یک \fIکنش\fP، یک بلوک \fBcode\fP تعریف‌شده توسط کاربر را به نقطه خاصی در ماشین حالت متناهی تولیدشده مقید می‌سازد (دقیقاً همان‌طور که کنش‌های معنایی کد را به وضعیت‌های پایانی مقید می‌کنند). برای مشاهده فهرست کامل کنش‌های از پیش تعریف‌شده بخش \fI\%actions\fP را ببینید. .TP .B \fB!directive ;\fP یک \fIدستورالعمل\fP یکی از گزاره‌های ویژه از پیش تعریف‌شده است. هر دستورالعمل هدف منحصربه‌فردی دارد. برای جزئیات بیشتر بخش \fI\%directives\fP را ببینید. .UNINDENT.SS "بلوک‌ها (Blocks)" .sp نشانگرهای آغاز و پایان بلوک یا \fB/*!re2c\fP و \fB*/\fP هستند، یا \fB%{\fP و \fB%}\fP (از هر دو سبک پشتیبانی می‌شود). از نسخهٔ ۲.۲ به بعد، بلوک‌ها می‌توانند نام‌های اختیاری داشته باشند که امکان ارجاع به آن‌ها را در سایر بلوک‌ها فراهم می‌سازد. انواع مختلفی از بلوک‌ها وجود دارند: .INDENT 0.0 .TP .B \fB/*!re2c[:] ... */\fP یا \fB%{[:] ... %}\fP یک \fIبلوک سراسری\fP شامل تعاریف، پیکربندی‌ها، قواعد و دستورالعمل‌ها است. re2d عبارت‌های باقاعده مرتبط با هر قاعده را به یک اتوماتون متناهی معین (DFA) کامپایل می‌کند، آن را در قالب پرش‌های شرطی در زبان مقصد کُدگذاری کرده و بلوک را با کد تولیدشده جایگزین می‌نماید. نام‌ها و پیکربندی‌های تعریف‌شده در یک بلوک سراسری به حوزهٔ سراسری افزوده شده و برای بلوک‌های بعدی قابل مشاهده خواهند بود. در آغاز برنامه، حوزهٔ سراسری با \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). پیش از نسخهٔ ۲.۲ re2d، بلوک‌های قواعد نیازمند گزینهٔ \fB\-r \-\-reusable\fP بودند. .TP .B \fB/*!use:re2c[:] ... */\fP یا \fB%{use[:] ... %}\fP یک بلوک use که به یک بلوک قواعد قبلاً تعریف‌شده ارجاع می‌دهد. اگر نام مشخص شده باشد، re2d به دنبال بلوک قواعدی با این نام می‌گردد؛ در غیر این صورت، از جدیدترین بلوک قواعد (خواه نام‌گذاری‌شده یا بدون نام) استفاده می‌شود. یک بلوک use می‌تواند تعاریف، پیکربندی‌ها و قواعد مختص به خود را داشته باشد که به موارد بلوک قواعد ارجاع‌شده اضافه می‌شوند. پیش از نسخهٔ ۲.۲ re2d، بلوک‌های use نیازمند گزینهٔ \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 تولیدشده توسط re2d بسط می‌یابد\&. یک فهرست اختیاری از نام بلوک‌ها مشخص می‌کند که هنگام محاسبهٔ مجموعهٔ متغیرهای برچسب، چه بلوک‌هایی باید لحاظ شوند (اگر فهرست خالی باشد، همهٔ بلوک‌ها لحاظ می‌شوند). دو پیکربندی اختیاری وجود دارد: \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) یا به‌طور ضمنی توسط re2d تولید شده است (با گزینه‌های \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 را فراهم می‌کند، که باید یک مسیر فایل درون نقل‌قول جفتی (double-quoted) باشد. محتویات فایل دقیقاً به‌جای بلوک جایگزین می‌شود؛ درست همان‌گونه که \fB#include\fP در C/C++ عمل می‌کند. این بلوک می‌تواند همراه با گزینهٔ \fB\-\-depfile\fP برای تولید وابستگی‌های سامانهٔ ساخت به فایل‌های گنجانده‌شده به کار رود. .TP .B \fB/*!header:re2c:on*/\fP یا \fB%{header:on %}\fP این بلوک نشان‌دهندهٔ آغاز فایل سرآیند است. همه‌چیز پس از آن و تا بلوک بعدیِ \fBheader:off\fP توسط re2d پردازش شده و در فایل سرآیندِ مشخص‌شده با گزینهٔ \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 در اینجا فهرست کاملی از پیکربندی‌های پشتیبانی‌شده توسط re2d آورده شده است: .INDENT 0.0 .TP .B \fBre2c:api\fP, \fBre2c:input\fP مشابه گزینهٔ \fB\-\-api\fP\&. .TP .B \fBre2c:api:sigil\fP نشانگری (\(dqsigil\(dq) را مشخص می‌کند که برای جای‌نگه‌دار‌های آرگومان در اولیه‌های API استفاده می‌شود. پیش‌فرض \fB@@\fP است. یک جای‌نگه‌دار با نشانه شروع شده و به دنبال آن نام آرگومان درون آکولاد قرار می‌گیرد. برای مثال، اگر نشانه روی \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 تو‌در‌تو و نقشه‌های بیتی می‌شود. مقدار پیش‌فرض \fB9\fP است. .TP .B \fBre2c:cond:abort\fP اگر روی یک مقدار عدد صحیح مثبت تنظیم شود، حالت پیش‌فرض در توزیع شرط تولیدشده، اجرای برنامه را متوقف (abort) می‌کند. .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 نشانگر مورد استفاده برای جایگزینی آرگومان را در تعریف \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 نشانگر مورد استفاده برای جایگزینی آرگومان در تعریف \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 نماد نگهبان مورد استفاده با قاعدهٔ پایان ورودی \fB$\fP را تعیین می‌کند. مقدار پیش‌فرض \fB\-1\fP است (قاعدهٔ \fB$\fP استفاده نمی‌شود). سایر مقادیر ممکن شامل تمام واحدهای کد معتبر است. تنها اعداد ده‌دهی شناسایی می‌شوند. .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 است. رشتهٔ تورفتگی باید تنها شامل نویسه‌های فضای خالی باشد. برای غیرفعال کردن کامل تورفتگی، این پیکربندی را روی یک رشتهٔ خالی تنظیم کنید. .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 و در حالت وضعیت قابل‌ذخیره را مشخص می‌کند. .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 اگر روی مقداری غیر از صفر تنظیم شود، تحلیل‌گر واژگانی تولیدشده از نشانه‌گذاری مونادیک استفاده خواهد کرد (این پیکربندی مختص به زبان 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 عبارت مورد استفاده برای متغیرهای برچسب را مشخص می‌کند. به‌طور پیش‌فرض re2d عبارت‌هایی به فرم \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، و در صورتی که اشاره‌گر باشند، یک اشاره‌گر تهی (null pointer) خواهد بود). .TP .B \fBre2c:tags:prefix\fP پیشوند نام متغیرهای برچسب را مشخص می‌کند. مقدار پیش‌فرض \fByyt\fP\& است. .TP .B \fBre2c:sentinel\fP نماد سنتینل مورد استفاده برای بررسی‌های پایان ورودی را مشخص می‌کند (هنگامی که بررسی‌های مرز با \fBre2c:yyfill:enable = 0;\fP غیرفعال شده باشند و \fBre2c:eof\fP تنظیم نشده باشد). این پیکربندی بر تولید کد تأثیری ندارد: هدف آن اطمینان از این است که نماد سنتینل در میانه یک قاعده مجاز نباشد، و تضمین این‌که تحلیل‌گر لغوی فراتر از پایان بافر را نخواند. مقدار پیش‌فرض \fI\-1\(ga\fP است (در این حالت re2d فرض می‌کند که سنتینل صفر است، که معمول‌ترین حالت است). تنها اعداد ده‌دهی شناسایی می‌شوند. .TP .B \fBre2c:state:abort\fP اگر روی یک مقدار عدد صحیح مثبت تنظیم شود، حالت پیش‌فرض در توزیع وضعیت تولیدشده اجرای برنامه را لغو (abort) می‌کند، و یک حالت صریح \fB\-1\fP حاوی انتقال به ابتدای بلوک خواهد بود. .TP .B \fBre2c:state:nextlabel\fP کنترل می‌کند که آیا به دنبال عبارت switch مربوط به \fBYYGETSTATE\fP برچسب \fByyNext\fP بیاید یا خیر (مقدار پیش‌فرض صفر است که نشان‌دهنده نبود برچسب است). به‌طور جایگزین می‌توان از \fBre2c:label:start\fP برای تولید یک برچسب شروع مشخص، یا از یک بلوک صریح \fBgetstate\fP برای تولید عبارت switch مربوط به \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 است. .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 است. .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 است. .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 است. .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 عنصر پایه عمومی API با نام \fBYYSHIFTMTAG\fP را تعریف می‌کند. .TP .B \fBre2c:YYSHIFTSTAG\fP, \fBre2c:define:YYSHIFTSTAG\fP عنصر پایه عمومی API با نام \fBYYSHIFTSTAG\fP را تعریف می‌کند. .TP .B \fBre2c:YYSTAGN\fP, \fBre2c:define:YYSTAGN\fP عنصر پایه عمومی API با نام \fBYYSTAGN\fP را تعریف می‌کند. .TP .B \fBre2c:YYSTAGP\fP, \fBre2c:define:YYSTAGP\fP عنصر پایه عمومی 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 در قالب هگزادسیمال تولید می‌شوند. پیش‌فرض صفر است (نقشه‌های بیتی در قالب ده‌دهی هستند). .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 اگر روی غیرصفر تنظیم شود، re2d در هر بار خوانده شدن \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 در API عمومی و مقایسه مبتنی بر \fBYYLIMIT\fP در API اشاره‌گر C) جلوگیری می‌کند. مقدار پیش‌فرض غیرصفر است (بررسی تولید می‌شود). .TP .B \fBre2c:yyfill:enable\fP در صورت تنظیم روی صفر، از تولید \fBYYFILL\fP (همراه با بررسی آن) جلوگیری می‌کند. این مورد باید زمانی استفاده شود که کل ورودی در یک قطعه از حافظه قرار می‌گیرد (نیازی به بافرسازی نیست) و بررسی‌های پایان ورودی به بررسی‌های \fBYYFILL\fP وابسته نیستند (برای مثال در صورتی که از یک نویسه نگهبان (sentinel) استفاده شده باشد). از هشدارها (گزینه \fB\-W\fP) و پیکربندی \fBre2c:sentinel\fP استفاده کنید تا مطمئن شوید تحلیل‌گر واژگانی (lexer) تولیدشده نمی‌تواند فراتر از پایان ورودی را بخواند. مقدار پیش‌فرض غیرصفر است (\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 re2d از نحو زیر برای عبارات باقاعده استفاده می‌کند: .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 هر نویسه‌ای به جز خط جدید (newline). .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؛ از پرانتز برای تغییر اولویت تقدم استفاده می‌شود. اگر استخراج زیرتطابق (submatch) فعال باشد، بسته به گزینه \fB\-\-invert\-captures\fP، \fB(R)\fP یک گروه ضبط‌کننده یا غیرضبط‌کننده خواهد بود. .TP .B \fB(!R)\fP اگر استخراج زیرتطابق فعال باشد، بسته به گزینه \fB\-\-invert\-captures\fP، \fB(!R)\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 در اینجا فهرستی از کنش‌های از پیش تعریف‌شده که توسط re2d پشتیبانی می‌شوند آمده است: .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 در اینجا فهرست کاملی از دستورالعمل‌های پشتیبانی‌شده توسط re2d آورده شده است: .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\& شناخته می‌شوند، با برنامه بیرونی ارتباط برقرار می‌کند. اینکه چه بنیادینه‌هایی باید برای یک برنامه خاص تعریف شوند به عوامل متعددی از جمله پیچیدگی عبارات باقاعده، شیوه نمایش ورودی، بافرینگ و استفاده از ویژگی‌های گوناگون بستگی دارد. تمام بنیادینه‌های لازم باید توسط کاربر در قالب ماکروها، توابع، متغیرها یا هر شکل مناسب دیگری که کد تولیدشده را از نظر نحوی و معنایی صحیح سازد، تعریف شوند. ابزار re2d تعاریف را بررسی نمی‌کند (و نمی‌تواند بررسی کند)، بنابراین اگر چیزی جا افتاده باشد یا به نادرستی تعریف شده باشد، برنامه تولیدشده ممکن است در زمان کامپایل یا اجرا دچار خطا شود. این راهنما مثال‌هایی از تعاریف API را در رایج‌ترین موارد ارائه می‌دهد. .sp ابزار re2d دارای سه سبک API است که مجموعه اصلی بنیادینه‌های مورد استفاده یک برنامه را مشخص می‌کنند: .INDENT 0.0 .TP .B \fBSimple API\fP این API پیش‌فرض برای بک‌اند D است. این رابط شامل بنیادینه‌های \fBYYCURSOR\fP، \fBYYMARKER\fP، \fBYYCTXMARKER\fP و \fBYYLIMIT\fP است که باید به عنوان اشاره‌گرهایی از نوع \fBYYCTYPE*\fP\& تعریف شوند. .nf .fi .sp .TP .B \fBRecord API\fP رابط Record API در مواردی مفید است که وضعیت تحلیل‌گر لغوی باید درون یک 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 این انعطاف‌پذیرترین API است. این رابط با گزینه \fB\-\-api generic\fP یا پیکربندی \fBre2c:api = generic\fP فعال می‌شود. این رابط شامل بنیادینه‌هایی برای عملیات‌های عمومی است: \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\&. .UNINDENT .sp در اینجا فهرست کاملی از بنیادینه‌های API که ممکن است توسط کد تولیدشده جهت ارتباط با برنامه بیرونی به کار روند آمده است. .INDENT 0.0 .TP .B \fBYYCTYPE\fP نوع نویسه‌های ورودی (code units). برای کدگذاری‌های 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). در صورتی که تطبیق طولانی‌تر ناموفق باشد و تحلیل‌گر لغوی نیاز به عقب‌گرد (rollback) داشته باشد، برای بازیابی موقعیت \fBYYCURSOR\fP استفاده می‌شود. نیازی به مقداردهی اولیه نیست. .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 از نوع boolean تعریف شود که برابر با \fBtrue\fP است اگر و تنها اگر کمتر از \fBlen\fP نویسه ورودی باقی مانده باشد. .TP .B \fBYYEND\fP یک بنیادینه عمومی API بدون متغیر. باید به صورت یک r\-value از نوع boolean تعریف شود که برابر با \fBtrue\fP است اگر و تنها اگر پایان \fIمنطقی\fP ورودی فرا رسیده باشد (بدون در نظر گرفتن هرگونه نماد فاصله‌ساز یا نگهبان). \fBYYEND\fP برای پیاده‌سازی نماد \fB$\fP در عبارات باقاعده استفاده می‌شود. این بنیادینه با \fBYYLESSTHAN\fP، که برای اطمینان از اینکه تحلیل‌گر فراتر از پایان بافر نخواند به کار می‌رود، تفاوت دارد. .TP .B \fBYYPEEK\fP یک بنیادینه عمومی API بدون متغیر. باید به عنوان یک r\-value از نوع \fBYYCTYPE\fP تعریف شود که برابر با نویسه در موقعیت فعلی ورودی است. .TP .B \fBYYSKIP\fP یک بنیادینه عمومی API که باید موقعیت فعلی ورودی را به اندازه یک واحد کد (code unit) جلو ببرد. .TP .B \fBYYBACKUP\fP یک بنیادینه عمومی API که باید موقعیت فعلی ورودی را ذخیره کند (تا بعداً با \fBYYRESTORE\fP بازیابی شود). .TP .B \fBYYRESTORE\fP یک بنیادینه عمومی API که باید موقعیت فعلی ورودی را به مقدار ذخیره‌شده توسط \fBYYBACKUP\fP\& بازگرداند. .TP .B \fBYYBACKUPCTX\fP یک بنیادینه عمومی API که باید موقعیت فعلی ورودی را به عنوان موقعیت بافت پسین (trailing context) ذخیره کند (تا بعداً با \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 نوع شمارش (enum) شرط. می‌تواند با بلوک \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\-ام درست (true) است اگر و تنها اگر واحد کد 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 باید در موارد ساده که نیازی به پر کردن مجدد بافر و ذخیرهٔ وضعیت تحلیل‌گر لغوی (lexer) نیست استفاده شود. گزینهٔ \fBrecord\fP باید هنگامی استفاده شود که وضعیت تحلیل‌گر لغوی باید در یک رکورد (struct، class و غیره) ذخیره گردد. گزینهٔ \fBgeneric\fP باید در موارد پیچیده که دو API دیگر به‌اندازهٔ کافی انعطاف‌پذیر نیستند به کار رود. .TP .B \fB\-\-bit\-vectors \-b\fP بهینه‌سازی پرش‌های شرطی با استفاده از ماسک‌های بیتی (bit masks). این گزینه مستلزم \fB\-\-nested\-ifs\fP است. .TP .B \fB\-\-captures\fP, \fB\-\-leftmost\-captures\fP فعال‌سازی استخراج تطابق‌های فرعی با گروه‌های گیرانداز حریصانه از چپ‌ترین حالت (leftmost greedy). نتیجه در یک آرایهٔ \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 ادغام caseهای متوالی در دستورات switch به یک بازه با قالب \fBlow ... high\fP\&. این نحو یک افزونهٔ زبان C/C++ است که توسط کامپایلرهایی مانند GCC، Clang و Tcc پشتیبانی می‌شود. مزیت اصلی نسبت به استفاده از caseهای تکی، تولید کد کوچک‌تر و زمان تولید سریع‌تر است، هرچند برای برخی از کامپایلرها مانند Tcc منجر به اندازهٔ دودویی (binary) کوچک‌تر نیز می‌شود. .TP .B \fB\-\-computed\-gotos \-g\fP بهینه‌سازی پرش‌های شرطی با استفاده از افزونهٔ غیراستاندارد \(dqcomputed goto\(dq (که باید توسط کامپایلر پشتیبانی شود). re2d تنها در موارد پیچیده با شاخه‌های شرطی بسیار، جدول‌های پرش را تولید می‌کند. آستانهٔ پیچیدگی را می‌توان با پیکربندی \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: چندین تحلیل‌گر لغوی مرتبط درون یک بلوک. این گزینه جایگزینی برای مشخص کردن دستی بلوک‌های مختلف re2d است که با \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 می‌خواند. re2d فرض می‌کند که محدودهٔ نویسه 0 \-\- 0xFF و اندازهٔ هر نویسه ۱ بایت است. .TP .B \fB\-\-empty\-class \fP تعیین شیوهٔ برخورد re2d با رده‌های نویسه‌ای تهی. با \fBmatch\-empty\fP (پیش‌فرض)، ردهٔ تهی با ورودی خالی تطابق می‌یابد (که غیرمنطقی است، اما با نسخه‌های قبلی سازگار است). با \fBmatch\-none\fP ردهٔ تهی همواره در تطبیق ناموفق است. با \fBerror\fP ردهٔ تهی خطای کامپایل ایجاد می‌کند. .TP .B \fB\-\-encoding\-policy \fP تعیین شیوهٔ برخورد re2d با جانشین‌های یونیکد (surrogates). با \fBfail\fP با مواجهه با یک surrogate، پردازش re2d با خطا متوقف می‌شود. با \fBsubstitute\fP برنامهٔ re2d بی‌صدا جانشین‌ها را با کد پوینت خطای 0xFFFD جایگزین می‌کند. با \fBignore\fP (پیش‌فرض) re2d با جانشین‌ها مانند کد پوینت‌های معمولی رفتار می‌کند. استاندارد یونیکد بیان می‌کند که جانشین‌های مستقل نامعتبر هستند، اما کتابخانه‌ها و برنامه‌های دنیای واقعی رفتارهای متفاوتی دارند. .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 مشخص کرد. اگر از conditionها استفاده شود، یک enum شرط به‌طور خودکار به انتهای هدر تولیدشده افزوده می‌شود (مگر اینکه یک بلوک صریح \fBconditions\fP وجود داشته باشد). .TP .B \fB\-I PATH\fP افزودن \fBPATH\fP به فهرست مکان‌هایی که هنگام جستجو برای فایل‌های include استفاده می‌شوند. این گزینه در ترکیب با بلوک یا دستورالعمل \fBinclude\fP مفید است. re2d فایل \fBFILE\fP را در دایرکتوری فایل والد و در مکان‌های include مشخص‌شده با گزینهٔ \fB\-I\fP جستجو می‌کند. .TP .B \fB\-\-input \fP نام مستعار منسوخ‌شده برای \fB\-\-api\fP\&. گزینهٔ \fBdefault\fP معادل \fBsimple\fP است (در واقع برای بیشتر backendها پیش‌فرض است، اما نه برای همه). گزینهٔ \fBcustom\fP معادل \fBgeneric\fP است. .TP .B \fB\-\-input\-encoding \fP مشخص کردن نحوهٔ تجزیهٔ عبارت‌های باقاعده توسط re2d. با \fBascii\fP (پیش‌فرض) re2d ورودی را با کدگذاری ASCII مدیریت می‌کند: هر دنباله‌ای از واحدهای کد (code units)، دنباله‌ای از نویسه‌های تک‌بایتی مستقل در نظر گرفته می‌شود. با \fButf8\fP re2d ورودی را با کدگذاری UTF8 مدیریت کرده و نویسه‌های چندبایتی را تشخیص می‌دهد. .TP .B \fB\-\-invert\-captures\fP معکوس کردن مفهوم گروه‌های گیرانداز (capturing) و غیرگیرانداز (non\-capturing). به‌طور پیش‌فرض \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، که در آن هر وضعیت مجزا یک case از 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) در خروجی. این گزینه هنگامی که کد تولیدشده در یک سیستم کنترل نسخه ذخیره می‌شود می‌تواند مفید باشد (برای جلوگیری از تفاوت‌های حجیم خودکار ناشی از تغییرات کوچک). .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) خودداری کند، چرا که تحلیل‌گر لغوی از پیش بررسی‌های پایان ورودی را به شیوه‌ای کارآمدتر انجام می‌دهد. کاربر می‌تواند یک تعریف امن از \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 فعال‌سازی استخراج تطابق‌های فرعی با گروه‌های گیرانداز به سبک 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 نادیده گرفتن کد رابط تعریف‌شده توسط کاربر و تولید یک برنامهٔ خودکفای \(dqاسکلت\(dq (skeleton). علاوه بر این، فایل‌های ورودی حاوی رشته‌های مشتق‌شده از گرامر باقاعده و نتایج فشرده‌شدهٔ تطبیق را تولید می‌کند که برای تأیید رفتار \(dqاسکلت\(dq روی تمام ورودی‌ها به کار می‌روند. این گزینه برای یافتن باگ‌ها در بهینه‌سازی‌ها و تولید کد مفید است. این گزینه تنها برای C پشتیبانی می‌شود..TP .B \fB\-\-storable\-state \-f\fP تولید یک lexer که می‌تواند وضعیت درونی خود را ذخیره کند. این قابلیت در lexerهای مبتنی بر مدل push که هنگام نبود ورودی کافی توسط یک برنامهٔ بیرونی متوقف شده و سپس با فراهم شدن ورودی بیشتر از سر گرفته می‌شوند، مفید است. در این حالت، کاربران باید علاوه بر این دستورهای اولیهٔ \fBYYGETSTATE\fP و \fBYYSETSTATE\fP را تعریف کنند، و متغیرهای \fByych\fP، \fByyaccept\fP و \fBstate\fP باید بخشی از وضعیت ذخیره‌شدهٔ lexer باشند. .TP .B \fB\-\-syntax FILE\fP بارگذاری پیکربندی‌ها از \fBFILE\fP مشخص‌شده و اعمال آن‌ها بر روی فایل نحو (syntax) پیش‌فرض. توجه داشته باشید که \fBFILE\fP می‌تواند تنها تعداد کمی پیکربندی را تعریف کند (در صورتی که برای اصلاح فایل نحو پیش‌فرض استفاده شود)، یا یک backend زبان کاملاً جدید را تعریف کند (در مورد اخیر توصیه می‌شود از گزینهٔ \fB\-\-lang none\fP استفاده شود). .TP .B \fB\-\-tags \-T\fP فعال‌سازی استخراج زیرتطابق با برچسب‌ها. .TP .B \fB\-\-ucs2 \-\-wide\-chars \-w\fP تولید یک lexer که ورودی با کدگذاری UCS2 را می‌خواند. re2d فرض می‌کند که بازهٔ نویسه‌ها 0 \-\- 0xFFFF و اندازهٔ نویسه ۲ بایت است. این گزینه مستلزم \fB\-\-nested\-ifs\fP است\&. .TP .B \fB\-\-utf8 \-\-utf\-8 \-8\fP تولید یک lexer که ورودی را با کدگذاری UTF\-8 می‌خواند. re2d فرض می‌کند که بازهٔ نویسه‌ها 0 \-\- 0x10FFFF و اندازهٔ نویسه ۱ بایت است. .TP .B \fB\-\-utf16 \-\-utf\-16 \-x\fP تولید یک lexer که ورودی با کدگذاری UTF16 را می‌خواند. re2d فرض می‌کند که بازهٔ نویسه‌ها 0 \-\- 0x10FFFF و اندازهٔ نویسه ۲ بایت است. این گزینه مستلزم \fB\-\-nested\-ifs\fP است\&. .TP .B \fB\-\-utf32 \-\-unicode \-u\fP تولید یک lexer که ورودی با کدگذاری UTF32 را می‌خواند. re2d فرض می‌کند که بازهٔ نویسه‌ها 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 در کد تولیدشده. این مورد برای ردیابی اجرای lexer مفید است. .TP .B \fB\-\-dump\-adfa\fP گزینهٔ اشکال‌زدایی: خروجی دادن DFA پس از تونل‌زنی (در قالب .dot). .TP .B \fB\-\-dump\-cfg\fP گزینهٔ اشکال‌زدایی: خروجی دادن گراف جریان کنترل متغیرهای برچسب (در قالب .dot). .TP .B \fB\-\-dump\-closure\-stats\fP گزینهٔ اشکال‌زدایی: خروجی دادن آمار مربوط به تعداد وضعیت‌ها در بستار (closure). .TP .B \fB\-\-dump\-dfa\-det\fP گزینهٔ اشکال‌زدایی: خروجی دادن DFA بلافاصله پس از قطعی‌سازی (در قالب .dot). .TP .B \fB\-\-dump\-dfa\-min\fP گزینهٔ اشکال‌زدایی: خروجی دادن DFA پس از کمینه‌سازی (در قالب .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 گزینهٔ اشکال‌زدایی: خروجی دادن جدول تداخل حاصل از تحلیل زنده‌بودن متغیرهای برچسب. .TP .B \fB\-\-dump\-nfa\fP گزینهٔ اشکال‌زدایی: خروجی دادن NFA (در قالب .dot). .TP .B \fB\-\-emit\-dot \-D\fP تولید گراف lexer در قالب .dot به جای خروجی عادی. خروجی را می‌توان با کمک Graphviz به یک تصویر تبدیل کرد (مثلاً دستوری مانند \fBdot \-Tpng \-odfa.png dfa.dot\fP). .UNINDENT .INDENT 0.0 .TP .B \fB\-\-dfa\-minimization \fP گزینهٔ داخلی: الگوریتم کمینه‌سازی DFA مورد استفاده توسط re2d\&. گزینهٔ \fBmoore\fP الگوریتم مور (Moore) است (که پیش‌فرض می‌باشد). گزینهٔ \fBtable\fP الگوریتم \(dqپر کردن جدول\(dq است. هر دو الگوریتم باید صرف‌نظر از بازنام‌گذاری وضعیت‌ها، DFA یکسانی تولید کنند؛ پر کردن جدول ساده‌تر و بسیار کندتر است و به عنوان پیاده‌سازی مرجع عمل می‌کند. .TP .B \fB\-\-eager\-skip\fP گزینهٔ داخلی: وادار کردن lexer تولیدشده به جلو بردن مشتاقانهٔ موقعیت ورودی \-\- بلافاصله پس از خواندن نماد ورودی. این تغییر، رفتار پیش‌فرض را که در آن موقعیت ورودی به صورت تنبلانه \-\- پس از گذار به وضعیت بعدی، به جلو برده می‌شود، عوض می‌کند. .TP .B \fB\-\-no\-lookahead\fP گزینهٔ داخلی، منسوخ‌شده. در گذشته برای فعال‌سازی الگوریتم TDFA(0) به کار می‌رفت. برخلاف TDFA(1)، الگوریتم TDFA(0) از پیش‌نگری یک‌نمادی استفاده نمی‌کند. این الگوریتم عملیات ثبات را به جای گذارهای خروجی، روی گذارهای ورودی اعمال می‌کند. ارزیابی‌ها نشان دادند که کارایی الگوریتم 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 می‌باشد. .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 اگر یک عبارت باقاعده حاوی یک کلاس نویسهٔ خالی باشد، هشدار می‌دهد. تلاش برای تطبیق یک کلاس نویسهٔ خالی معنایی ندارد: همیشه باید با شکست مواجه شود. با این حال، به دلایل سازگاری با گذشته، re2d کلاس‌های نویسهٔ خالی را مجاز می‌داند و با آن‌ها مانند رشته‌های خالی رفتار می‌کند. برای تغییر این رفتار پیش‌فرض از گزینهٔ \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 دربارهٔ قواعدی هشدار می‌دهد که زیر سایهٔ قواعد دیگر قرار گرفته‌اند و هرگز مطابقت نخواهند یافت. .TP .B \fB\-Wdeprecated\-eof_rule\fP دربارهٔ قواعد مستقل پایان ورودی \fB$\fP هشدار می‌دهد که بر اثر تغییرات آینده از کار خواهند افتاد و نیاز به اصلاح دارند. در حال حاضر، این قواعد هنگام تداخل با قواعد دیگر اولویت دارند، اما پس از معرفی نماد تعمیم‌یافتهٔ پایان ورودی \fB$\fP، ترتیب اولویت تغییر خواهد کرد و این قواعد زیر سایهٔ قواعد دیگر قرار خواهند گرفت. .TP .B \fB\-Wuseless\-escape\fP اگر نویسه‌ای فرار (escape) داده شود در حالی که نیازی نبوده، هشدار می‌دهد. به‌طور پیش‌فرض، re2d چنین مواردی را نادیده می‌گیرد، اما این موضوع ممکن است نشان‌دهندهٔ یک غلط املایی یا خطا در توالی گریز (escape sequence) باشد. .TP .B \fB\-Wnondeterministic\-tags\fP اگر یک برچسب دارای درجهٔ نامعین بودن \fBn\fP باشد، در جایی که \fBn\fP بزرگ‌تر از ۱ است، هشدار می‌دهد. .TP .B \fB\-Wsentinel\-in\-midrule\fP اگر نماد دیده‌بان (sentinel) در میانهٔ یک قاعده ظاهر شود هشدار می‌دهد \-\-\- این امر ممکن است باعث خواندن فراتر از انتهای بافر، خرابی (crash) یا فساد حافظه در تحلیل‌گر لغوی تولیدشده شود. این هشدار تنها در صورتی کاربرد دارد که روش دیده‌بان برای بررسی پایان ورودی استفاده شده باشد. در صورت استفاده از پیکربندی \fBre2c:sentinel\fP، این هشدار به خطا تبدیل می‌شود. .TP .B \fB\-Wundefined\-syntax\-config\fP اگر فایل نحو مشخص‌شده با گزینهٔ \fB\-\-syntax\fP فاقد تعاریف برخی از پیکربندی‌ها باشد، هشدار می‌دهد. این امر به نگهداری فایل‌های نحو سفارشی کمک می‌کند: اگر نسخهٔ جدیدی پیکربندی‌هایی را اضافه کند، فایل نحو قدیمی هشداری صادر کرده و کاربر مطلع می‌شود. اگر برخی از پیکربندی‌ها بدون استفاده هستند و نیازی به تعریف ندارند، باید به‌صراحت روی \fB\fP تنظیم شوند\&. .UNINDENT .SS "فایل‌های نحو (Syntax files)" .sp پشتیبانی از زبان‌های مختلف در re2c بر پایهٔ ایدهٔ \fIفایل‌های نحو\fP استوار است. یک فایل نحو، فایلی پیکربندی است که نحو زبان مقصد را تعریف می‌کند \-\- نه کل زبان، بلکه بخش کوچکی از آن که توسط کد تولیدشده استفاده می‌شود. فایل‌های نحو انعطاف‌پذیری بالایی به re2c می‌بخشند، اما نباید به عنوان جایگزینی برای پیکربندی‌های \fBre2c:\fP استفاده شوند: هدف آن‌ها تعریف نحو زبان مقصد است، نه سفارشی‌سازی یک تحلیل‌گر لغوی خاص. تمام زبان‌های پشتیبانی‌شده دارای فایل‌های نحو پیش‌فرضی هستند که بخشی از توزیع به شمار می‌روند (زیردایرکتوری \fBinclude/syntax\fP را ببینید)؛ آن‌ها همچنین در فایل باینری re2d تعبیه شده‌اند. کاربران می‌توانند یک فایل نحو سفارشی ارائه دهند که چند پیکربندی را برای یکی از زبان‌های پشتیبانی‌شده بازنویسی می‌کند، یا می‌توانند همهٔ پیکربندی‌ها را مجدداً تعریف کنند (در این حالت باید از گزینهٔ \fB\-\-lang none\fP استفاده شود). فایل‌های نحو شامل پیکربندی‌هایی در چهار نوع مختلف هستند: فهرست ویژگی‌ها، پیکربندی‌های زبان، پیکربندی‌های درون‌جایی و الگوهای کد. .sp \fBفهرست‌های ویژگی (Feature lists)\fP .INDENT 0.0 .INDENT 3.5 چندین پیکربندی فهرستی، ویژگی‌های گوناگونِ پشتیبانی‌شده توسط یک后端 مشخص را تعریف می‌کنند، تا در صورتی که کاربر تلاش کند ویژگی پشتیبانی‌نشده‌ای را فعال سازد، re2d خطای روشنی صادر کند: .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 چندین پیکربندی بولی ویژگی‌هایی از زبان مقصد را توصیف می‌کنند که بر تجزیه‌کننده و تولیدکنندهٔ کد re2d تأثیر می‌گذارند: .INDENT 0.0 .TP .B \fBsemicolons\fP غیرصفر در صورتی که زبان پس از دستورها از نقطه‌ویرگول (semicolon) استفاده کند. .TP .B \fBbacktick_quoted_strings\fP غیرصفر در صورتی که زبان دارای رشته‌های محصور در بک‌تیک (backtick) باشد. .TP .B \fBsingle_quoted_strings\fP غیرصفر در صورتی که زبان دارای رشته‌های محصور در نقل‌قول تکی (single-quote) باشد. .TP .B \fBindentation_sensitive\fP غیرصفر در صورتی که زبان به تورفتگی حساس باشد. .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 است. متغیرها جانگهدارنده‌هایی هستند که در مرحلهٔ تولید کد جایگزین می‌شوند. متغیرهای فهرست خاص هستند: هنگام بسط الگوهای فهرست، re2d عبارت‌های سمت راست دونقطه را چند بار تکرار می‌کند، و هر بار رخدادهای متغیر فهرست را با مقداری مخصوص به همان تکرار جایگزین می‌سازد. فهرست‌ها دارای کران‌های اختیاری هستند (مقادیر منفی از انتها شمرده می‌شوند، برای نمونه \fB\-1\fP به معنای آخرین مؤلفه است). نام‌های شرطی با یک نقطه شروع می‌شوند. هم شرط‌ها و هم متغیرها می‌توانند محلی (مخصوص همان الگوی کد) یا سراسری (مجاز در تمام الگوهای کد) باشند. هنگامی که re2d فایل نحو را می‌خواند، بررسی می‌کند که هر الگوی کد تنها از متغیرها و شرط‌هایی استفاده کند که در آن مجاز شناخته شده‌اند. .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 در ادامه فهرستی از تمام الگوهای کد پشتیبانی‌شده در re2d به همراه متغیرها و شرط‌های محلی آن‌ها آورده شده است. توجه داشته باشید که یک تعریف مشخص می‌تواند از متغیرها و شرط‌های محلی استفاده کند، اما الزامی به این کار ندارد. تمام الگوهای کد بدون استفاده باید روی \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 تعریف یک شمارشگر یا enum (ممکن است با ساختار زبانی ویژه‌ای برای شمارش‌ها تعریف شود، یا صرفاً به صورت چند مقدار ثابت مستقل). متغیرهای پشتیبانی‌شده عبارتند از: \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 دستور انتساب. متغیرهای پشتیبانی‌شده عبارتند از: \fBlhs\fP (سمت چپ) و \fBrhs\fP (سمت راست). .TP .B \fBcode:type_int\fP نوع عدد صحیح علامت‌دار (signed). .TP .B \fBcode:type_uint\fP نوع عدد صحیح بدون علامت (unsigned). .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 عملگر \(dqبرابر با\(dq (equals). .TP .B \fBcode:cmp_ne\fP عملگر \(dqنابرابر با\(dq (not equals). .TP .B \fBcode:cmp_lt\fP عملگر \(dqکوچک‌تر از\(dq (less than). .TP .B \fBcode:cmp_gt\fP عملگر \(dqبزرگ‌تر از\(dq (greater than). .TP .B \fBcode:cmp_le\fP عملگر \(dqکوچک‌تر یا مساوی\(dq (less or equal). .TP .B \fBcode:cmp_ge\fP عملگر \(dqبزرگ‌تر یا مساوی\(dq (greater or equal). .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 یک حالت 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 \fBgoto\fP). متغیرهای پشتیبانی‌شده: \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 اعلان تابع. متغیرهای پشتیبانی‌شده: \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 (نسخهٔ re2d مورد استفاده برای تولید این مورد) و \fBdate\fP (تاریخ تولید). .TP .B \fBcode:line_info\fP قالب دستورات خط (line directives) (اگر روی \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 در اینجا فهرستی از تمام متغیرهای سراسری مجاز در فایل‌های نحو (syntax files) آمده است: .INDENT 0.0 .TP .B \fBnl\fP یک خط جدید (newline). .TP .B \fBindent\fP متغیری که هیچ کدی تولید نمی‌کند، اما اثر جانبی افزایش سطح تورفتگی را دارد..TP .B \fBdedent\fP متغیری که هیچ کدی تولید نمی‌کند، اما دارای اثر جانبیِ کاهش سطح دندانه‌گذاری است. .TP .B \fBtopindent\fP رشته دندانه‌گذاری برای دستور فعلی. سطح دندانه‌گذاری توسط تولیدکننده کد ردیابی شده و به‌طور خودکار به‌روزرسانی می‌شود. .UNINDENT .sp در اینجا فهرستی از تمام شرط‌های سراسریِ مجاز در فایل‌های نحو (syntax) آورده شده است: .INDENT 0.0 .TP .B \fB\&.api.simple\fP درست است اگر از API ساده استفاده شود (\fB\-\-api simple\fP یا \fBre2c:api = simple\fP). .TP .B \fB\&.api.generic\fP درست است اگر از API عمومی استفاده شود (\fB\-\-api generic\fP یا \fBre2c:api = generic\fP). .TP .B \fB\&.api.record\fP درست است اگر از API رکوردی استفاده شود (\fB\-\-api record\fP یا \fBre2c:api = record\fP). .TP .B \fB\&.api_style.functions\fP درست است اگر سبک API تابع‌گونه استفاده شود (\fBre2c:api\-style = functions\fP). .TP .B \fB\&.api_style.freeform\fP درست است اگر سبک API آزاد (free\-form) استفاده شود (\fBre2c:api\-style = free\-form\fP). .TP .B \fB\&.case_ranges\fP درست است اگر ویژگی بازه‌های case فعال باشد (\fB\-\-case\-ranges\fP یا \fBre2c:case\-ranges = 1\fP). .TP .B \fB\&.cgoto.relative\fP درست است اگر حالت نسبی دستور \fBgoto\fP محاسباتی استفاده شود (\fB\-\-computed\-gotos\-relative\fP یا \fBre2c:cgoto:relative = 1\fP). .TP .B \fB\&.code_model.goto_label\fP درست است اگر مدل کد مبتنی بر goto/label استفاده شود (\fB\-\-goto\-label\fP). .TP .B \fB\&.code_model.loop_switch\fP درست است اگر مدل کد مبتنی بر loop/switch استفاده شود (\fB\-\-loop\-switch\fP). .TP .B \fB\&.code_model.recursive_functions\fP درست است اگر مدل کد مبتنی بر توابع بازگشتی استفاده شود (\fB\-\-recursive\-function\fP). .TP .B \fB\&.date\fP درست است اگر اثرانگشت (fingerprint) تولیدشده باید حاوی تاریخ تولید باشد. .TP .B \fB\&.loop_label\fP درست است اگر حلقه‌های تولیدشده توسط re2d باید دارای برچسب باشند (\fBre2c:label:yyloop\fP روی یک رشته غیرخالی تنظیم شده باشد). .TP .B \fB\&.monadic\fP درست است اگر کد تولیدشده باید به‌صورت مونادیک باشد (\fBre2c:monadic = 1\fP). این مورد تنها برای زبان‌های تابعی محض مرتبط است. .TP .B \fB\&.start_conditions\fP درست است اگر شرایط شروع (start conditions) فعال باشند (\fB\-\-start\-conditions\fP). .TP .B \fB\&.storable_state\fP درست است اگر وضعیت قابل ذخیره‌سازی فعال باشد (\fB\-\-storable\-state\fP). .TP .B \fB\&.unsafe\fP درست است اگر re2d برای تولید کد سریع‌تر باید از بلوک‌های \(dqunsafe\(dq استفاده کند (\fB\-\-unsafe\fP، \fBre2c:unsafe = 1\fP). این مورد تنها برای زبان‌هایی کاربرد دارد که دارای ویژگی \(dqunsafe\(dq هستند. .TP .B \fB\&.version\fP درست است اگر اثرانگشت (fingerprint) تولیدشده باید حاوی نسخه re2d باشد. .TP .B \fB\&.yyfill.enable\fP درست است اگر \fBYYFILL\fP فعال باشد (\fBre2c:yyfill:enable = 1\fP). .TP .B \fB\&.yyfn.throw\fP درست است اگر پیکربندی \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 دو شرط اول کار تحلیل‌گر لغوی را به‌طور «طبیعی» خاتمه می‌دهند: تحلیل‌گر به وضعیتی بدون گذارهای خروجی می‌رسد و تطبیق به‌طور خودکار متوقف می‌شود. اما شرط سوم، یعنی پایان ورودی، متفاوت است: این وضعیت ممکن است در هر حالتی رخ دهد و تحلیل‌گر باید بتواند آن را مدیریت کند. بررسی پایان ورودی، جریان عادی کار تحلیل‌گر لغوی را قطع کرده و شاخه‌های شرطی به برنامه تولیدشده اضافه می‌کند؛ از این رو لازم است تعداد این بررسی‌ها به حداقل برسد. re2d از چند روش مختلف برای مدیریت پایان ورودی پشتیبانی می‌کند. انتخاب روش به پیچیدگی عبارات باقاعده، نیاز به بافرسازی، ملاحظات کارایی و عوامل دیگر بستگی دارد. در ادامه فهرستی از این روش‌ها آورده شده است: .INDENT 0.0 .IP \(bu 2 \fBنگهبان (Sentinel).\fP این روش نیاز به بررسی‌های پایان ورودی را به‌کلی برطرف می‌کند. این روش ساده و کارآمد است، اما به مواردی محدود می‌شود که یک نویسه «نگهبان» طبیعی وجود داشته باشد که هرگز در ورودی معتبر ظاهر نشود. این نویسه ممکن است همچنان در ورودی نامعتبر رخ دهد، اما نباید توسط عبارات باقاعده مجاز شمرده شود، مگر شاید به عنوان آخرین نویسه یک قاعده. نویسه نگهبان به انتهای ورودی افزوده می‌شود و نقش سیگنال توقف را ایفا می‌کند: هنگامی که تحلیل‌گر لغوی این نویسه را می‌خواند، یا خطای نحوی رخ داده است یا به پایان ورودی رسیده است. در هر دو حالت، تحلیل‌گر باید متوقف شود. این روش زمانی استفاده می‌شود که \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 این یک روش عمومی است: امکان مدیریت هرگونه ورودی را بدون محدودیت بر روی عبارات باقاعده فراهم می‌کند. ایده کار این است که تعداد بررسی‌های پایان ورودی با انجام آن‌ها تنها روی نویسه‌هایی خاص کاهش یابد. مشابه روش «نگهبان»، یکی از نویسه‌ها به عنوان «نگهبان» انتخاب شده و به انتهای ورودی متصل می‌شود. با این حال، هیچ محدودیتی در محل وقوع نگهبان وجود ندارد (در واقع، هر نویسه‌ای را می‌توان به عنوان نگهبان انتخاب کرد). هنگامی که تحلیل‌گر این نویسه را می‌خواند، علاوه بر آن بررسی مرز را نیز انجام می‌دهد. اگر موقعیت فعلی در محدوده مجاز باشد، تحلیل‌گر تطبیق را از سر گرفته و با نگهبان مانند یک نویسه عادی رفتار می‌کند. در غیر این صورت \fBYYFILL\fP را فراخوانی می‌کند (مگر اینکه غیرفعال شده باشد). اگر ورودی بیشتری فراهم شود، تحلیل‌گر لغوی نویسه آخر را دوباره بررسی کرده و طوری ادامه می‌دهد که گویی نگهبان وجود نداشته است. در غیر این صورت، این نقطه پایان واقعی ورودی است و تحلیل‌گر متوقف می‌شود. این روش زمانی استفاده می‌شود که \fBre2c:eof\fP مقداری غیرمنفی داشته باشد (باید روی مقدار عددی نویسه نگهبان تنظیم شود). استفاده از \fBYYFILL\fP اختیاری است. .nf .fi .sp .IP \(bu 2 \fBبررسی مرزها با لایه‌گذاری (Bounds checks with padding).\fP این یک روش عمومی است و ممکن است از روش «نگهبان همراه با بررسی مرزها» سریع‌تر باشد، اما پیچیده‌تر نیز هست. ایده این است که وضعیت‌های DFA به مؤلفه‌های قویاً همبند (SCCها) افراز شوند و به ازای هر SCC، یک بررسی منفرد برای نویسه‌های کافی تولید شود تا طولانی‌ترین مسیرِ بدون حلقه در آن SCC پوشش داده شود. این کار تعداد بررسی‌ها را کاهش می‌دهد، اما مشکلی در مورد لکسم‌های کوتاه در پایان ورودی به وجود می‌آید، زیرا این بررسی به نویسه‌های کافی برای پوشش طولانی‌ترین لکسم نیاز دارد. این مشکل را می‌توان با لایه‌گذاری (padding) ورودی با چند نویسه ساختگی که پسوند لکسم معتبری تشکیل نمی‌دهند (به طوری که تحلیل‌گر نتواند با آن‌ها تطبیق یابد) برطرف کرد. طول این پدینگ باید \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 در میانهٔ رشته رخ دهد، یک خطای نحوی است و تحلیل‌گر لغوی با قاعدهٔ پیش‌فرض \fB*\fP مطابقت می‌یابد، اما فراتر از انتهای ورودی را نمی‌خواند و کرش نمی‌کند (برای بررسی این موضوع از هشدار \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 // re2d $INPUT \-o $OUTPUT module main; // Expect a null\-terminated string. private int lex(const(char)* yycursor) { uint count = 0; for (;;) { /*!re2c re2c:YYCTYPE = char; re2c:yyfill:enable = 0; * { return \-1; } [\ex00] { return count; } [a\-z]+ { ++count; continue; } [ ]+ { continue; } */ } assert(0); // unreachable } void main() { assert(lex(\(dq\(dq) == 0); assert(lex(\(dqone two three\(dq) == 3); assert(lex(\(dqf0ur\(dq) == \-1); } .ft P .fi .UNINDENT .UNINDENT .SS نگهبان با بررسی‌های مرزی (Sentinel with bounds checks) .sp این مثال از نگهبان به همراه بررسی‌های مرزی برای مدیریت پایان ورودی استفاده می‌کند (این روش در نسخهٔ 1.2 اضافه شد). برنامه رشته‌های محصور در تک‌کوتیشن که با فاصله جدا شده‌اند را شمارش می‌کند. کاراکتر نگهبان null است که با پیکربندی \fBre2c:eof = 0;\fP مشخص می‌شود. همانند روش \fI\%sentinel\fP، نویسهٔ null آخرین کاراکتر هر رشتهٔ ورودی است، اما در میانهٔ یک قاعده مجاز است (برای نمونه، \fB\(aqaaa\e0aa\(aq\e0\fP یک ورودی معتبر است، ولی \fB\(aqaaa\e0\fP خطای نحوی است). بررسی‌های مرزی در هر وضعیتی که با یک کاراکتر ورودی مطابقت داشته باشد تولید می‌شوند، اما دامنهٔ آن‌ها به شاخه‌ای که null را مدیریت می‌کند محدود است. بررسی‌های مرزی به شکل \fBYYLIMIT <= YYCURSOR\fP یا با API عمومی به صورت \fBYYLESSTHAN(1)\fP هستند. اگر شرط بررسی درست باشد، تحلیل‌گر لغوی به پایان ورودی رسیده است و باید متوقف شود (\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 // re2d $INPUT \-o $OUTPUT module main; // Expect a null\-terminated string. private int lex(immutable char[] s) { const(char)* yycursor = s.ptr, yylimit = s.ptr + s.length, yymarker; int count = 0; for (;;) { /*!re2c re2c:YYCTYPE = char; re2c:yyfill:enable = 0; re2c:eof = 0; str = [\(aq] ([^\(aq\e\e] | [\e\e][^])* [\(aq]; * { return \-1; } $ { return count; } str { ++count; continue; } [ ]+ { continue; } */ } assert(0); // unreachable } void main() { assert(lex(\(dq\(dq) == 0); assert(lex(\(dq\(aqqu\e0tes\(aq \(aqare\(aq \(aqfine: \e\e\(aq\(aq \(dq) == 3); assert(lex(\(dq\(aqunterminated\e\e\(aq\(dq) == \-1); } .ft P .fi .UNINDENT .UNINDENT .SS بررسی‌های مرزی با پدینگ (Bounds checks with padding) .sp این مثال از بررسی‌های مرزی همراه با پدینگ برای مدیریت پایان ورودی استفاده می‌کند (این روش به‌طور پیش‌فرض فعال است). برنامه رشته‌های محصور در تک‌کوتیشن که با فاصله جدا شده‌اند را شمارش می‌کند. پدینگی شامل \fBYYMAXFILL\fP کاراکتر null به انتهای ورودی افزوده شده است، که مقدار \fBYYMAXFILL\fP به‌طور خودکار توسط یک بلوک \fBmax\fP تولید می‌شود. استفاده از null برای پدینگ الزامی نیست \-\-\- هر کاراکتری را می‌توان استفاده کرد تا زمانی که یک پسوند معتبر برای جزء واژگانی (lexeme) تشکیل ندهند (در این مثال، پدینگ نباید شامل تک‌کوتیشن باشد، زیرا ممکن است به عنوان پسوند یک رشتهٔ محصور در تک‌کوتیشن اشتباه گرفته شود). یک قاعدهٔ \(dqstop\(dq وجود دارد که با اولین کاراکتر پدینگ (null) مطابقت یافته و تحلیل‌گر لغوی را پایان می‌دهد (توجه داشته باشید که بررسی می‌کند آیا null در ابتدای پدینگ قرار دارد، در غیر این صورت یک خطای نحوی محسوب می‌شود). بررسی‌های مرزی تنها در برخی وضعیت‌ها تولید می‌شوند که توسط مؤلفه‌های قویاً همبند (strongly connected components) اتوماتای زیرین تعیین می‌گردند. بررسی‌ها به شکل \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 // re2d $INPUT \-o $OUTPUT module main; import core.stdc.stdlib; import core.stdc.string; /*!max:re2c*/ private int lex(immutable char[] s) { // Make a copy of the string with YYMAXFILL zeroes at the end. char *buf = cast(char*) malloc(s.length + YYMaxFill); memcpy(buf, cast(const(void*)) s, s.length); memset(buf + s.length, 0, YYMaxFill); const(char)* yycursor = buf; const(char)* yylimit = buf + s.length + YYMaxFill; int count = 0; loop: /*!re2c re2c:YYCTYPE = char; re2c: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 + s.length) goto exit; else goto fail; } str { ++count; goto loop; } [ ]+ { goto loop; } * { goto fail; } */ fail: count = \-1; exit: free(buf); return count; } void main() { assert(lex(\(dq\(dq) == 0); assert(lex(\(dq\(aqqu\e0tes\(aq \(aqare\(aq \(aqfine: \e\e\(aq\(aq \(dq) == 3); assert(lex(\(dq\(aqunterminated\e\e\(aq\(dq) == \-1); assert(lex(\(dq\(aqunexpected \e0 null\e\e\(aq\(dq) == \-1); } .ft P .fi .UNINDENT .UNINDENT.SS "بررسی‌های سفارشی (Custom checks)" .sp این مثال از یک روش سفارشی برای مدیریت پایان ورودی بر پایهٔ generic API استفاده می‌کند. این برنامه رشته‌های محصور در علامت نقل‌قول تکی را که با فاصله از هم جدا شده‌اند، شمارش می‌کند. این مثال همانند مثال \fI\%sentinel\fP است، با این تفاوت که ورودی با نویسهٔ پوچ (null-terminated) خاتمه نیافته است. برای جبران نبودِ نویسهٔ نگهبان در پایان ورودی، \fBYYPEEK\fP بازتعریف شده است تا پیش از خواندن نویسهٔ بعدی ورودی، بررسی محدوده (bounds check) را انجام دهد. این کار ناکارآمد است زیرا بررسی‌ها بسیار تکرار می‌شوند. اگر شرط بررسی برقرار نباشد، \fBYYPEEK\fP نویسهٔ واقعی را برمی‌گرداند، در غیر این صورت یک نویسهٔ نگهبان ساختگی بازمی‌گرداند. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C // re2d $INPUT \-o $OUTPUT module main; import core.stdc.stdlib; import core.stdc.string; private int lex(immutable char[] s) { // For the sake of example create a string without terminating null. char *buf = cast(char*) malloc(s.length); memcpy(buf, cast(const(void*)) s, s.length); const(char) *cur = buf, lim = buf + s.length; int count = 0; for (;;) { /*!re2c re2c:api = generic; re2c:yyfill:enable = 0; re2c:YYCTYPE = char; re2c:YYPEEK = \(dqcur < lim ? *cur : 0\(dq; // fake null re2c:YYSKIP = \(dq++cur;\(dq; * { count = \-1; break; } [\ex00] { break;{} } [a\-z]+ { ++count; continue;{} } [ ]+ { continue; } */ } free(buf); return count; } void main() { assert(lex(\(dq\(dq) == 0); assert(lex(\(dqone two three \(dq) == 3); assert(lex(\(dqf0ur\(dq) == \-1); } .ft P .fi .UNINDENT .UNINDENT .SH "پر کردن مجدد بافر (BUFFER REFILLING)" .sp نیاز به بافرسازی زمانی پیش می‌آید که ورودی نتواند به‌یکباره در حافظه نگاشت شود: یا بیش از حد بزرگ است، یا به صورت جریانی (مانند خواندن از یک سوکت) دریافت می‌شود. روش معمول در این موارد، تخصیص یک بافر حافظه با اندازهٔ ثابت و پردازش ورودی در تکه‌هایی است که در این بافر جا می‌شوند. هنگامی که تکهٔ فعلی پردازش شد، به بیرون منتقل شده و داده‌های جدید وارد می‌شوند. در عمل این موضوع تا حدی پیچیده‌تر است، زیرا وضعیت تحلیل‌گر لغوی (lexer) تنها از یک موقعیت ورودی تشکیل نشده، بلکه مجموعه‌ای از موقعیت‌های مرتبط با یکدیگر است: .INDENT 0.0 .IP \(bu 2 مکان‌نما (cursor): نویسهٔ بعدی ورودی که باید خوانده شود (\fBYYCURSOR\fP در API اشاره‌گر C یا \fBYYSKIP\fP/\fBYYPEEK\fP در generic API) .IP \(bu 2 حد (limit): موقعیت بعد از آخرین نویسهٔ موجود ورودی (\fBYYLIMIT\fP در API اشاره‌گر C، که به‌طور ضمنی توسط \fBYYLESSTHAN\fP در generic API مدیریت می‌شود) .IP \(bu 2 نشانگر (marker): موقعیت جدیدترین تطابق، در صورت وجود (\fBYYMARKER\fP در API پیش‌فرض یا \fBYYBACKUP\fP/\fBYYRESTORE\fP در generic API) .IP \(bu 2 توکن (token): آغاز لکسم (lexeme) جاری (در API مربوط به re2d ضمنی است، زیرا برای عملکرد عادی lexer نیازی به آن نیست و می‌تواند توسط کاربر تعریف و به‌روزرسانی شود) .IP \(bu 2 نشانگر بافتار (context marker): موقعیت بافتار پس‌آیند (\fBYYCTXMARKER\fP در API اشاره‌گر C یا \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، بهتر است تا جای ممکن نویسه‌های ورودی بیشتری پر شوند (حتی اگر نویسه‌های کمتری برای ازسرگیری کار lexer کافی باشد). جزئیات پیاده‌سازی \fBYYFILL\fP بسته به اینکه از کدام روش مدیریت EOF استفاده می‌شود اندکی متفاوت است: حالت قاعدهٔ EOF تا حدودی ساده‌تر از حالت بررسی محدوده همراه با لایه پرکننده (padding) است. همچنین توجه داشته باشید که اگر گزینهٔ \fB\-f \-\-storable\-state\fP استفاده شود، \fBYYFILL\fP معناشناسی متفاوتی خواهد داشت (که در بخش مربوط به وضعیت قابل‌ذخیره شرح داده شده است). .SS "YYFILL با نویسه نگهبان (YYFILL with sentinel)" .sp اگر از قاعدهٔ EOF استفاده شود، \fBYYFILL\fP یک دستور اولیه شبه‌تابع است که هیچ آرگومانی نمی‌پذیرد و مقداری را بازمی‌گرداند که با صفر مقایسه می‌شود. فراخوانی \fBYYFILL\fP با شرط \fBYYLIMIT <= YYCURSOR\fP در API اشاره‌گر C و \fBYYLESSTHAN()\fP در generic 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 // re2d $INPUT \-o $OUTPUT module main; import core.stdc.string; import core.stdc.stdio; enum BUFSIZE = 4095; struct Input { FILE* file; char[BUFSIZE + 1] buffer;// +1 for sentinel char* yylimit, yycursor, yymarker, token; bool eof; }; private int fill(ref Input it) { if (it.eof) return 1; const size_t shift = it.token \- it.buffer.ptr; const size_t used = it.yylimit \- it.token; // 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(cast(void*)it.buffer.ptr, it.token, used); it.yylimit \-= shift; it.yycursor \-= shift; it.yymarker \-= shift; it.token \-= shift; // Fill free space at the end of buffer with new data from file. it.yylimit += fread(it.yylimit, 1, BUFSIZE \- used, it.file); it.yylimit[0] = 0; it.eof = it.yylimit < (it.buffer.ptr + BUFSIZE); return 0; } private int lex(ref Input yyrecord) { int count = 0; for (;;) { yyrecord.token = yyrecord.yycursor; /*!re2c re2c:api = record; re2c:YYCTYPE = \(dqchar\(dq; re2c:YYFILL = \(dqfill(yyrecord) == 0\(dq; re2c:eof = 0; str = [\(aq] ([^\(aq\e\e] | [\e\e][^])* [\(aq]; * { return \-1; } $ { return count; } str { ++count; continue; } [ ]+ { continue; } */ } assert(0); } void 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.ptr, \(dqw\(dq); for (int i = 0; i < BUFSIZE; ++i) { fwrite(cast(const(void*)) content.ptr, 1, content.length \- 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 it; it.file = fopen(fname.ptr, \(dqr\(dq); it.yycursor = it.yymarker = it.token = it.yylimit = it.buffer.ptr + BUFSIZE; it.eof = 0; // Sentinel (at YYLIMIT pointer) is set to zero, which triggers YYFILL. it.yylimit[0] = 0; // Run the lexer. assert(lex(it) == count); // Cleanup: remove input file. fclose(it.file); remove(fname.ptr); } .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 عمومی (generic) فعال می‌شود. آرگومان ارسال‌شده به \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 // re2d $INPUT \-o $OUTPUT module main; import core.stdc.string; import core.stdc.stdio; /*!max:re2c*/ enum BufSize = (4096 \- YYMaxFill); struct Input { FILE* file; char[BufSize + YYMaxFill] buffer; char* yylimit, yycursor, token; bool eof; }; private int fill(ref Input it, size_t need) { if (it.eof) return 1; const size_t shift = it.token \- it.buffer.ptr; const size_t used = it.yylimit \- it.token; // 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(it.buffer.ptr, it.token, used); it.yylimit \-= shift; it.yycursor \-= shift; it.token \-= shift; // Fill free space at the end of buffer with new data from file. it.yylimit += fread(it.yylimit, 1, BufSize \- used, it.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 (it.yylimit < it.buffer.ptr + BufSize) { it.eof = true; memset(it.yylimit, 0, YYMaxFill); it.yylimit += YYMaxFill; } return 0; } private int lex(ref Input yyrecord) { int count = 0; for (;;) { yyrecord.token = yyrecord.yycursor; /*!re2c re2c:api = record; re2c:YYCTYPE = \(dqchar\(dq; re2c:YYFILL = \(dqif (fill(yyrecord, @@) != 0) return \-1;\(dq; str = [\(aq] ([^\(aq\e\e] | [\e\e][^])* [\(aq]; [\ex00] { // Check that it is the sentinel, not some unexpected null. return yyrecord.token == yyrecord.yylimit \- YYMaxFill ? count : \-1; } str { ++count; continue; } [ ]+ { continue; } * { return \-1; } */ } assert(0); } void 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.ptr, \(dqw\(dq); for (int i = 0; i < BufSize; ++i) { fwrite(content.ptr, 1, content.length \- 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 \(gait.yycursor < it.yylimit\(ga fails. Input it; it.file = fopen(fname.ptr, \(dqr\(dq); it.yycursor = it.token = it.yylimit = it.buffer.ptr + BufSize; it.eof = 0; // Run the lexer. assert(lex(it) == count); // Cleanup: remove input file. fclose(it.file); remove(fname.ptr); } .ft P .fi .UNINDENT .UNINDENT.SH "ویژگی‌ها (FEATURES)" .SS "بلوک‌های چندگانه (Multiple blocks)" .sp گاهی اوقات وجود چندین تحلیل‌گر لغوی (lexer) مرتبط با یکدیگر ضروری است (برای مثال، اگر یک ماشین حالت سطح‌بالا وجود داشته باشد که بین حالت‌های مختلف تحلیل‌گر لغوی جابه‌جا می‌شود). این قابلیت می‌تواند با استفاده از چندین بلوک متصل re2d پیاده‌سازی شود. گزینهٔ دیگر استفاده از \fI\%شرایط شروع (start conditions)\fP\& است. .sp پیاده‌سازی ارتباط بین بلوک‌ها به زبان مقصد بستگی دارد. در زبان‌هایی که دارای دستور \fBgoto\fP هستند (مانند C/C++ و Go) می‌توان تمام بلوک‌ها را در یک تابع قرار داد، به طوری که پیشوند هر کدام یک برچسب (label) باشد. انتقال از یک بلوک به بلوک دیگر یک \fBgoto\fP ساده است. در زبان‌هایی که فاقد \fBgoto\fP هستند (مانند Rust)، لازم است از یک حلقه به همراه یک switch روی متغیر حالت استفاده شود، مشابه حلقه/switch مربوط به \fByystate\fP که توسط re2d تولید می‌شود؛ یا این که هر بلوک درون یک تابع قرار داده شده و از فراخوانی توابع استفاده گردد. .sp مثال زیر از چندین بلوک برای تجزیه اعداد دودویی (binary)، هشت‌هشتی (octal)، ده‌دهی (decimal) و شانزده‌شانزدهی (hexadecimal) استفاده می‌کند. هر مبنا بلوک مخصوص به خود را دارد. بلوک اولیه مبنا را تعیین کرده و به بلوک‌های دیگر هدایت می‌کند. پیکربندی‌های مشترک در یک بلوک جداگانه در ابتدای برنامه تعریف شده‌اند؛ این پیکربندی‌ها توسط بلوک‌های دیگر به ارث برده می‌شوند. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C // re2d $INPUT \-o $OUTPUT \-i module main; enum ERROR = ulong.max; private void add(ulong BASE)(ref ulong u, int d) { u = u * BASE + d; if (u > uint.max) { u = ERROR; } } private ulong parse_u32(const(char)* s) { const(char)* yycursor = s, yymarker; ulong u = 0; /*!re2c re2c:yyfill:enable = 0; re2c:YYCTYPE = char; 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] { add!(2)(u, yycursor[\-1] \- \(aq0\(aq); goto bin; } * { return ERROR; } */ oct: /*!re2c end { return u; } [0\-7] { add!(8)(u, yycursor[\-1] \- \(aq0\(aq); goto oct; } * { return ERROR; } */ dec: /*!re2c end { return u; } [0\-9] { add!(10)(u, yycursor[\-1] \- \(aq0\(aq); goto dec; } * { return ERROR; } */ hex: /*!re2c end { return u; } [0\-9] { add!(16)(u, yycursor[\-1] \- \(aq0\(aq); goto hex; } [a\-f] { add!(16)(u, yycursor[\-1] \- \(aqa\(aq + 10); goto hex; } [A\-F] { add!(16)(u, yycursor[\-1] \- \(aqA\(aq + 10); goto hex; } * { return ERROR; } */ } void 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); } .ft P .fi .UNINDENT .UNINDENT .SS "شرایط شروع (Start conditions)" .sp شرایط شروع با گزینهٔ \fB\-\-start\-conditions\fP فعال می‌شوند. آن‌ها روشی برای کدگذاری چندین اتوماتای مرتبط با یکدیگر در یک بلوک re2d یکسان ارائه می‌دهند. .sp هر شرط متناظر با یک اتوماتای منفرد است و یک نام یکتا دارد که توسط کاربر مشخص می‌شود و یک شمارهٔ داخلی یکتا که توسط re2d تعریف می‌گردد. این شماره‌ها برای جابه‌جایی میان شرایط استفاده می‌شوند: کد تولیدشده از سازوکارهای اولیهٔ \fBYYGETCOND\fP و \fBYYSETCOND\fP برای دریافت شرط کنونی یا تنظیم آن روی شمارهٔ داده‌شده استفاده می‌کند. برای تولید شناسه‌های عددی شرایط، از بلوک \fBconditions\fP، گزینهٔ \fB\-\-header\fP یا پیکربندی \fBre2c:header\fP استفاده کنید. پیکربندی \fBre2c:cond:enumprefix\fP پیشوند شناسه‌های تولیدشده را مشخص می‌کند. .sp در حالت شرط، هر قاعده باید پیشوندی از فهرستی از نام‌های شرایط جداشده با ویرگول در علامت‌های قلاب‌دار (< >)، یا نویسهٔ عمومی \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 استفاده شود (کنترل دقیق‌تری فراهم می‌کند، زیرا کد می‌تواند به ازای هر شرط مشخص شود و می‌توان مستقیماً بدون گذر از توزیع شرط، به ابتدای شرط پرش کرد). .TP .B \fB< > => condition code\fP مشابه قاعدهٔ قبلی، با این تفاوت که \fBcondition\fP بعدی را تنظیم می‌کند. .TP .B \fB< > :=> condition\fP مشابه قاعدهٔ قبلی، با این تفاوت که کد مرتبطی ندارد و فوراً به \fBcondition\fP پرش می‌کند. .UNINDENT .UNINDENT .UNINDENT .sp کدی که re2d برای شرایط تولید می‌کند بستگی به این دارد که re2d از رویکرد goto/label استفاده می‌کند یا رویکرد loop/switch برای کدگذاری اتوماتا. .sp در زبان‌هایی که دارای دستور \fBgoto\fP هستند (مانند C/C++ و Go)، شرایط به‌طور طبیعی به صورت بلوک‌هایی از کد با پیشوند برچسب‌هایی به شکل \fByyc_\fP پیاده‌سازی می‌شوند، که در آن \fBcond\fP نام شرط است (پیشوند برچسب را می‌توان با \fBre2c:cond:prefix\fP تغییر داد). جابه‌جایی‌ها میان شرایط با استفاده از \fBgoto\fP و برچسب‌های شرط پیاده‌سازی می‌شوند. پیش از تمام شرایط، re2d یک switch اولیه روی \fBYYGETSTATE\fP تولید می‌کند که به وضعیت شروع شرط کنونی پرش می‌کند. قواعد میان‌بر \fB:=>\fP از switch اولیه عبور کرده و مستقیماً به شرط مشخص‌شده پرش می‌کنند (می‌توان از \fBre2c:cond:goto\fP برای تغییر رفتار پیش‌فرض استفاده کرد). قواعد دارای کنش‌های معنایی به‌طور خودکار به شرط بعدی پرش نمی‌کنند؛ این کار باید توسط کد کنش تعریف‌شده توسط کاربر انجام شود. .sp در زبان‌هایی که دستور \fBgoto\fP را ندارند (مانند Rust)، ابزار re2d از متغیر \fByystate\fP برای ذخیره شماره‌های شرایط استفاده مجدد می‌کند. هر شرط یک شناسهٔ عددی برابر با شمارهٔ وضعیت شروع خود دریافت می‌کند، و جابه‌جایی بین شرایط هیچ تفاوتی با switch میان وضعیت‌های DFA در یک شرط واحد ندارد. نیازی به یک switch اولیهٔ جداگانه برای شرایط وجود ندارد. (از آنجا که رویکرد یکسانی برای پیاده‌سازی وضعیت‌های قابل ذخیره استفاده می‌شود، در صورتی که هر دو قابلیت وضعیت‌های قابل ذخیره و شرایط استفاده شوند، \fBYYGETCOND\fP/\fBYYSETCOND\fP زائد خواهند بود). .sp برنامهٔ زیر از شرایط شروع برای تجزیه اعداد دودویی، هشت‌هشتی، ده‌دهی و شانزده‌شانزدهی استفاده می‌کند. یک بلوک منفرد وجود دارد که در آن هر مبنا شرط مخصوص به خود را دارد و شرط اولیه به همهٔ آن‌ها متصل است. متغیر تعریف‌شده توسط کاربر با نام \fBcond\fP شمارهٔ شرط کنونی را ذخیره می‌کند؛ این متغیر با شمارهٔ شرط اولیه که توسط بلوک \fBconditions\fP تولید شده است، مقداردهی اولیه می‌شود. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C // re2d $INPUT \-o $OUTPUT \-ci module main; enum ERROR = ulong.max; /*!conditions:re2c*/ private void add(ulong BASE)(ref ulong u, int d) { u = u * BASE + d; if (u > uint.max) { u = ERROR; } } private ulong parse_u32(const(char)* s) { const(char)* yycursor = s, yymarker; YYCond yycond = YYCond.yycinit; ulong u = 0; /*!re2c re2c:yyfill:enable = 0; re2c:YYCTYPE = char; <*> * { 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] { add!(2)(u, yycursor[\-1] \- \(aq0\(aq); goto yyc_bin; } [0\-7] { add!(8)(u, yycursor[\-1] \- \(aq0\(aq); goto yyc_oct; } [0\-9] { add!(10)(u, yycursor[\-1] \- \(aq0\(aq); goto yyc_dec; } [0\-9] { add!(16)(u, yycursor[\-1] \- \(aq0\(aq); goto yyc_hex; } [a\-f] { add!(16)(u, yycursor[\-1] \- \(aqa\(aq + 10); goto yyc_hex; } [A\-F] { add!(16)(u, yycursor[\-1] \- \(aqA\(aq + 10); goto yyc_hex; } */ } void 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); } .ft P .fi .UNINDENT .UNINDENT.SS وضعیت ذخیره‌پذیر (Storable state) .sp با گزینهٔ \fB\-\-storable\-state\fP، ابزار re2d تحلیل‌گر لغوی‌ای تولید می‌کند که می‌تواند وضعیت فعلی خود را ذخیره کند، به فراخواننده بازگردد، و بعداً عملیات را دقیقاً از همان‌جایی که متوقف شده بود از سر بگیرد. حالت پیش‌فرض عملکرد در re2d یک مدل «کششی» (\(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 را به‌عنوان بخشی از وضعیت ماندگار (persistent) تحلیل‌گر لغوی تعریف کنید. متغیر \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 در اینجا مثالی از یک تحلیل‌گر لغوی مدل «رانشی» آورده شده است که خواندن بسته‌ها از یک سوکت را شبیه‌سازی می‌کند. تحلیل‌گر لغوی تا زمانی که با پایان ورودی مواجه شود حلقه می‌زند و به تابع فراخواننده بازمی‌گردد. تابع فراخواننده با «ارسال» بستهٔ بعدی، ورودی بیشتری فراهم کرده و تحلیل لغوی را از سر می‌گیرد. این فرایند زمانی که تمام بسته‌ها ارسال شوند، یا خطایی رخ دهد، متوقف می‌شود. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C // re2d $INPUT \-o $OUTPUT \-f module main; import core.stdc.stdio; import core.stdc.string; // Use a small buffer to cover the case when a lexeme doesn\(aqt fit. // In real world use a larger buffer. enum BUFSIZE = 10; struct State { FILE* file; char[BUFSIZE + 1] buffer; char* yylimit, yycursor, yymarker, token; int yystate; }; enum Status {END, READY, WAITING, BAD_PACKET, BIG_PACKET}; private Status fill(ref State st) { const size_t shift = st.token \- cast(char*)st.buffer; const size_t used = st.yylimit \- st.token; const size_t free = BUFSIZE \- used; // Error: no space. In real life can reallocate a larger buffer. if (free < 1) return Status.BIG_PACKET; // Shift buffer contents (discard already processed data). memmove(cast(void*)st.buffer, st.token, used); st.yylimit \-= shift; st.yycursor \-= shift; st.yymarker \-= shift; st.token \-= shift; // Fill free space at the end of buffer with new data. const size_t read = fread(st.yylimit, 1, free, st.file); st.yylimit += read; st.yylimit[0] = 0; // append sentinel symbol return Status.READY; } private Status lex(ref State yyrecord, uint* recv) { char yych; /*!getstate:re2c*/ for (;;) { yyrecord.token = yyrecord.yycursor; /*!re2c re2c:api = record; re2c:YYCTYPE = char; re2c:YYFILL = \(dqreturn Status.WAITING;\(dq; re2c:eof = 0; packet = [a\-z]+[;]; * { return Status.BAD_PACKET; } $ { return Status.END; } packet { *recv = *recv + 1; continue; } */ } assert(0); // unreachable } private void test(string[] packets, Status expect) { // Create a pipe (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.yycursor = st.yymarker = st.token = st.yylimit = cast(char*)st.buffer + BUFSIZE; // Sentinel (at YYLIMIT pointer) is set to zero, which triggers YYFILL. st.yylimit[0] = 0; st.yystate = \-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; uint send = 0, recv = 0; for (;;) { status = lex(st, &recv); if (status == Status.END) { debug{printf(\(dqdone: got %u packets\en\(dq, recv);} break; } else if (status == Status.WAITING) { debug{printf(\(dqwaiting...\en\(dq);} if (send < packets.length) { debug{printf(\(dqsent packet %u\en\(dq, send);} fprintf(fw, \(dq%s\(dq, cast(char*)packets[send]); ++send; } status = fill(st); debug{printf(\(dqqueue: \(aq%s\(aq\en\(dq, cast(char*)st.buffer);} if (status == Status.BIG_PACKET) { debug{printf(\(dqerror: packet too big\en\(dq);} break; } assert(status == Status.READY); } else { assert(status == Status.BAD_PACKET); debug{printf(\(dqerror: ill\-formed packet\en\(dq);} break; } } // Check results. assert(status == expect); if (status == Status.END) assert(recv == send); // Cleanup: remove input file. fclose(fw); fclose(fr); remove(fname); } void main() { string[] packets1 = []; string[] packets2 = [\(dqzero;\(dq, \(dqone;\(dq, \(dqtwo;\(dq, \(dqthree;\(dq, \(dqfour;\(dq]; string[] packets3 = [\(dqzer0;\(dq]; string[] packets4 = [\(dqlooooooooooong;\(dq]; test(packets1, Status.END); test(packets2, Status.END); test(packets3, Status.BAD_PACKET); test(packets4, Status.BIG_PACKET); } .ft P .fi .UNINDENT .UNINDENT.SS "بلوک‌های قابل استفاده مجدد (Reusable blocks)" .sp بلوک‌های قابل استفاده مجدد با ساختار \fB/*!rules:re2c[:] ... */\fP یا \fB%{rules[:] ... %}\fP می‌توانند به هر تعداد بار مجدداً استفاده شوند و با سایر بلوک‌های re2d ترکیب گردند. بخش \fB\fP اختیاری است. یک بلوک قوانین (rules block) می‌تواند در یک بلوک یا دستور \fBuse\fP به کار گرفته شود. کد مربوط به یک بلوک قوانین، در هر نقطهٔ استفاده تولید می‌شود. .sp بلوک‌های use با \fB/*!use:re2c[:] ... */\fP یا \fB%{use[:] ... %}\fP\& تعریف می‌شوند. شناسهٔ \fB\fP اختیاری است: اگر مشخص نشده باشد، بلوک قوانین مرتبط، نزدیک‌ترین بلوک قبلی خواهد بود (خواه نام‌گذاری‌شده یا بدون نام). یک بلوک use می‌تواند تعاریف نام‌گذاری‌شده، پیکربندی‌ها و قوانین اختصاصی خود را اضافه کند. یک کاربرد مهم برای بلوک‌های use، تحلیل‌گر لغوی (lexer) با پشتیبانی از چندین کدگذاری ورودی است: همان بلوک قوانین چندین بار با پیکربندی‌های مختص هر کدگذاری مجدداً استفاده می‌شود (مثال زیر را ببینید). .sp دستور درون‌بلوکیِ \fB!use:;\fP می‌تواند از داخل یک بلوک re2d استفاده شود. این دستور، بلوک ارجاع‌داده‌شدهٔ \fB\fP را با بلوک فعلی ادغام می‌کند. اگر برخی از قوانین و پیکربندی‌های ادغام‌شده با موارد تعریف‌شدهٔ قبلی هم‌پوشانی داشته باشند، تداخل‌ها به روش معمول حل می‌شوند: نخستین قاعده اولویت دارد، و آخرین پیکربندی بر موارد پیشین ارجحیت می‌یابد (آن‌ها را رونویسی می‌کند). یک استثنا قوانین ویژهٔ \fB*\fP، \fB$\fP و (در حالت شرطی) \fB\fP هستند که برای آن‌ها تعریف محلیِ بلوک بر هرگونه تعریف به ارث‌رسیده برتری دارد. دستور use امکان ترکیب بلوک‌های مختلف re2d را با یکدیگر در یک بلوک واحد فراهم می‌سازد (مثال زیر را ببینید). .sp بلوک‌های نام‌گذاری‌شده و دستور درون‌بلوکی use در نگارش 2.2 از re2d اضافه شدند. از آن نگارش به بعد، استفاده از بلوک‌های قابل استفاده مجدد به‌طور پیش‌فرض مجاز است (نیازی به گزینهٔ خاصی نیست). پیش از نگارش 2.2، حالت استفادهٔ مجدد با گزینهٔ \fB\-r \-\-reusable\fP فعال می‌شد. پیش از نگارش 1.2، بلوک‌های قابل استفاده مجدد نمی‌توانستند با بلوک‌های معمولی ترکیب شوند. .SS "مثالی از دستور \fB!use\fP" .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C // re2d $INPUT \-o $OUTPUT module main; // 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. enum What { COLOR, FISH, DUNNO }; /*!rules:re2c:colors * { assert(false); } \(dqred\(dq | \(dqsalmon\(dq | \(dqmagenta\(dq { return What.COLOR; } */ /*!rules:re2c:fish * { assert(false); } \(dqhaddock\(dq | \(dqsalmon\(dq | \(dqeel\(dq { return What.FISH; } */ private What lex(const(char)* s) { const(char)* yycursor = s, yymarker; /*!re2c re2c:YYCTYPE = \(dqchar\(dq; re2c:yyfill:enable = 0; !use:fish; !use:colors; * { return What.DUNNO; } // overrides inherited \(aq*\(aq rules */ } void main() { assert(lex(\(dqsalmon\(dq) == What.FISH); assert(lex(\(dqwhat?\(dq) == What.DUNNO); } .ft P .fi .UNINDENT .UNINDENT .SS "مثالی از بلوک \fB/*!use:re2c ... */\fP" .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C // re2d $INPUT \-o $OUTPUT \-\-input\-encoding utf8 module main; import std.stdint; // 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; } */ private int lex_utf8(const(uint8_t)* s) { const(uint8_t)* yycursor = s, yymarker; /*!use:re2c re2c:YYCTYPE = uint8_t; re2c:encoding:utf8 = 1; */ } private int lex_utf32(const(uint32_t)* s) { const(uint32_t)* yycursor = s, yymarker; /*!use:re2c re2c:YYCTYPE = uint32_t; re2c:encoding:utf32 = 1; */ } void main() { immutable uint8_t[] s8 = // UTF\-8 [ 0xe2, 0x88, 0x80, 0x78, 0x20, 0xe2, 0x88, 0x83, 0x79 ]; immutable uint32_t[] s32 = // UTF32 [ 0x00002200, 0x00000078, 0x00000020, 0x00002203, 0x00000079 ]; assert(lex_utf8(cast(const(uint8_t)*)s8) == 0); assert(lex_utf32(cast(const(uint32_t)*)s32) == 0); } .ft P .fi .UNINDENT .UNINDENT.SS "استخراج زیرتطابق (Submatch extraction)" .sp ابزار re2d دو گزینه برای استخراج زیرتطابق (submatch extraction) دارد. .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 (پیش‌فرض) برای سیاست حریصانه‌ترین از چپ، و \fB\-\-posix\-captures\fP برای سیاست طولانی‌ترین تطابق بر پایه POSIX (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، ابزار re2d متغیرهای \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 برای سیاست طولانی‌ترین تطابق بر پایه POSIX. .UNINDENT .sp در پشت صحنه، تمام این گزینه‌ها به برچسب‌ها و \fI\%Tagged Deterministic Finite Automata with Lookahead\fP (اتوماتون‌های متناهی معین برچسب‌دار با نگاه به جلو یا TDFA) ترجمه می‌شوند\&. ایده بنیادین TDFA به حداقل رساندن سربار ناشی از استخراج زیرتطابق است. در حالت نهایی، اگر هیچ برچسب یا تسخیری در یک عبارت باقاعده وجود نداشته باشد، TDFA دقیقاً همانند یک DFA معمولی خواهد بود. اگر تعداد برچسب‌ها متعادل باشد، سربار به سختی قابل توجه است. اتوماتون TDFA تولیدشده از تعدادی \fIمتغیرهای برچسب (tag variables)\fP استفاده می‌کند که مستقیماً به برچسب‌ها نگاشت نمی‌شوند: ممکن است یک متغیر منفرد برای برچسب‌های متفاوتی استفاده شود، و یک برچسب ممکن است برای نگهداری تمام مقادیر احتمالی خود به چندین متغیر نیاز داشته باشد. سرانجام ابهام رفع می‌شود، و تنها یک متغیر نهایی به ازای هر برچسب باقی می‌ماند. متغیرهای برچسب باید با استفاده از بلوک‌های \fBstags\fP یا \fBmtags\fP تعریف شوند. اگر وضعیت تحلیل‌گر لغوی (lexer state) ذخیره شود، متغیرهای برچسب نیز باید بخشی از آن باشند. آن‌ها همچنین باید توسط \fBYYFILL\fP به‌روزرسانی شوند\&. .sp برچسب‌های S\-tag از عملیات‌های زیر پشتیبانی می‌کنند: .INDENT 0.0 .IP \(bu 2 ذخیره موقعیت ورودی در یک s\-tag: عبارت \fBt = YYCURSOR\fP با API اشاره‌گر C یا عملیات تعریف‌شده توسط کاربر \fBYYSTAGP(t)\fP با API عمومی (generic API) .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\-tag از عملیات‌های زیر پشتیبانی می‌کنند: .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\-tag را می‌توان به‌صورت مقادیر اسکالر (اشاره‌گرها یا آفست‌ها) پیاده‌سازی کرد. برچسب‌های M\-tag به نمایشی پیچیده‌تر نیاز دارند، چرا که باید دنباله‌ای از مقادیر برچسب را ذخیره کنند. ساده‌لوحانه‌ترین و ناکارآمدترین بازنمایی از یک 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 // re2d $INPUT \-o $OUTPUT module main; struct SemVer { int major; int minor; int patch; }; private 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; } private bool lex(const(char)* str, ref 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:tags = 1; re2c:YYCTYPE = \(dqchar\(dq; 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 true; } * { return false; } */ } void main() { SemVer v; assert(lex(\(dq23.34\(dq, v) && v.major == 23 && v.minor == 34 && v.patch == 0); assert(lex(\(dq1.2.999\(dq, v) && v.major == 1 && v.minor == 2 && v.patch == 999); assert(!lex(\(dq1.a\(dq, v)); } .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 // re2d $INPUT \-o $OUTPUT \-\-tags module main; import core.stdc.string; import core.stdc.stdio; import std.stdio; enum BUFSIZE = 4095; struct Input { FILE* file; char[BUFSIZE + 1] buffer;// +1 for sentinel char* yylimit, yycursor, yymarker, token; // Intermediate 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 = \(aqchar* @@;\(aq; */ bool eof; }; struct SemVer { int major; int minor; int patch; }; private 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; } private int fill(ref Input it) { if (it.eof) return 1; const size_t shift = it.token \- it.buffer.ptr; const size_t used = it.yylimit \- it.token; // 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(cast(void*)it.buffer.ptr, it.token, used); it.yylimit \-= shift; it.yycursor \-= shift; it.yymarker \-= shift; it.token \-= 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 (it.@@) it.@@ \-= shift;\en\(dq; */ // Fill free space at the end of buffer with new data from file. it.yylimit += fread(it.yylimit, 1, BUFSIZE \- used, it.file); it.yylimit[0] = 0; it.eof = it.yylimit < (it.buffer.ptr + BUFSIZE); return 0; } private bool lex(ref Input yyrecord, ref SemVer[] vers) { // Final variables available in semantic actions. /*!svars:re2c format = \(aqchar* @@;\(aq; */ for (;;) { yyrecord.token = yyrecord.yycursor; /*!re2c re2c:api = record; re2c:YYCTYPE = \(dqchar\(dq; re2c:YYFILL = \(dqfill(yyrecord) == 0\(dq; re2c:eof = 0; num = [0\-9]+; num @t1 \(dq.\(dq @t2 num @t3 (\(dq.\(dq @t4 num)? [\en] { int major = s2n(yyrecord.token, t1); int minor = s2n(t2, t3); int patch = t4 != null ? s2n(t4, yyrecord.yycursor \- 1) : 0; SemVer ver = SemVer(major, minor, patch); vers ~= ver; continue; } $ { return true; } * { return false; } */ } assert(0); } void main() { const char[] fname = \(dqinput\(dq; const char[] content = \(dq1.22.333\en\(aq \(dq; SemVer[BUFSIZE] expect = SemVer(1, 22, 333); SemVer[] actual; // Prepare input file: a few times the size of the buffer, containing // strings with zeroes and escaped quotes. FILE* f = fopen(fname.ptr, \(dqw\(dq); for (int i = 0; i < BUFSIZE; ++i) { fwrite(cast(const(void*)) content.ptr, 1, content.length \- 2, f); // skip null\-terminator } fclose(f); // Initialize lexer state: all pointers are at the end of buffer. Input it; it.file = fopen(fname.ptr, \(dqr\(dq); it.yycursor = it.yymarker = it.token = it.yylimit = it.buffer.ptr + BUFSIZE; it.eof = 0; // Sentinel (at YYLIMIT pointer) is set to zero, which triggers YYFILL. it.yylimit[0] = 0; // Run the lexer. assert(lex(it, actual) && actual == expect); // Cleanup: remove input file. fclose(it.file); remove(fname.ptr); } .ft P .fi .UNINDENT .UNINDENT .sp در اینجا مثالی از استفاده از گروه‌های تسخیر (capturing groups) برای تجزیه نگارش‌های معنایی آورده شده است. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C // re2d $INPUT \-o $OUTPUT module main; struct SemVer { int major, minor, patch; }; private 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; } private bool lex(const(char)* str, ref 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:captvars = 1; re2c:YYCTYPE = \(dqchar\(dq; num = [0\-9]+; (num) \(dq.\(dq (num) (\(dq.\(dq num)? [\ex00] { ver.major = s2n(yytl1, yytr1); ver.minor = s2n(yytl2, yytr2); ver.patch = yytl3 ? s2n(yytl3 + 1, yytr3) : 0; return true; } * { return false; } */ } void main() { SemVer v; assert(lex(\(dq23.34\(dq, v) && v.major == 23 && v.minor == 34 && v.patch == 0); assert(lex(\(dq1.2.999\(dq, v) && v.major == 1 && v.minor == 2 && v.patch == 999); assert(!lex(\(dq1.a\(dq, v)); } .ft P .fi .UNINDENT .UNINDENT .sp در اینجا مثالی از به‌کارگیری m\-tagها برای تجزیه یک نگارش با تعداد متغیری از مؤلفه‌ها آورده شده است. متغیرهای برچسب در یک ترای (trie) ذخیره می‌شوند. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C // re2d $INPUT \-o $OUTPUT module main; enum MtagRoot = \-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 }; alias MtagTrie = Mtag[]; alias Ver = int[]; private 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. private void add_mtag(ref MtagTrie trie, ref int mtag, const(char)* value) { Mtag m = {value, mtag}; mtag = cast(int)trie.length; trie ~= [m]; } // Recursively unwind tag histories and collect version components. private void unfold(const ref MtagTrie trie, int x, int y, ref Ver ver) { // Reached the root of the m\-tag tree, stop recursion. if (x == MtagRoot && y == MtagRoot) return; // Unwind history further. unfold(trie, trie[x].pred, trie[y].pred, ver); // Get tag values. Tag histories must have equal length. assert(x != MtagRoot && y != MtagRoot); const(char)* ex = trie[x].elem, ey = trie[y].elem; if (ex != null && ey != null) { // Both tags are valid pointers, extract component. ver ~= [s2n(ex, ey)]; } else { // Both tags are null (this corresponds to zero repetitions). assert(ex == null && ey == null); } } private bool parse(const(char)* str, ref Ver ver) { const(char)* yycursor = str, yymarker; MtagTrie mt; // Final tag variables available in semantic action. /*!svars:re2c format = \(dqconst(char)* @@;\(dq; */ /*!mvars:re2c format = \(dqint @@;\(dq; */ // Intermediate tag variables used by the lexer (must be autogenerated). /*!stags:re2c format = \(dqconst(char)* @@ = null;\(dq; */ /*!mtags:re2c format = \(dqint @@ = MtagRoot;\(dq; */ /*!re2c re2c:yyfill:enable = 0; re2c:tags = 1; re2c:YYCTYPE = \(dqchar\(dq; re2c:YYMTAGP = \(dqadd_mtag(mt, @@, yycursor);\(dq; re2c:YYMTAGN = \(dqadd_mtag(mt, @@, null);\(dq; num = [0\-9]+; @t1 num @t2 (\(dq.\(dq #t3 num #t4)* [\ex00] { ver = []; ver ~= [s2n(t1, t2)]; unfold(mt, t3, t4, ver); return true; } * { return false; } */ } void main() { Ver v; assert(parse(\(dq1\(dq, v) && v == [1]); assert(parse(\(dq1.2.3.4.5.6.7\(dq, v) && v == [1, 2, 3, 4, 5, 6, 7]); assert(!parse(\(dq1.2.\(dq, v)); } .ft P .fi .UNINDENT .UNINDENT.SS پشتیبانی از کدگذاری (Encoding support) .sp درک تفاوت بین \fBcode point\fPها و \fBcode unit\fPها ضروری است. یک code point شناسهٔ عددی یک نماد است. یک code unit کوچک‌ترین واحد ذخیره‌سازی در متن کدگذاری‌شده است. یک code point منفرد ممکن است با یک یا چند code unit نمایش داده شود. در یک کدگذاری با طول ثابت (fixed\-length)، تمام code pointها با تعداد یکسانی از code unitها نمایش داده می‌شوند. در یک کدگذاری با طول متغیر (variable\-length)، ممکن است code pointها با تعداد متفاوتی از code unitها نمایش داده شوند. توجه داشته باشید که قاعدهٔ «هر چیز» (\(dqany\(dq) \fB[^]\fP با هر code point تطابق می‌یابد، اما لزوماً با هر code unit مطابقت ندارد (تنها راه تطبیق با هر code unit صرف‌نظر از نوع کدگذاری، قاعدهٔ پیش‌فرض \fB*\fP است). تحلیل‌گر لغوی تولیدشده با جریانی از code unitها کار می‌کند: \fByych\fP یک code unit را ذخیره می‌کند و \fBYYCTYPE\fP نوع دادهٔ code unit است. از سوی دیگر، عبارات باقاعده بر حسب code pointها تعیین می‌شوند. هنگامی که re2d عبارات باقاعده را به اتوماتا کامپایل می‌کند، code pointها را به code unitها ترجمه می‌کند. این تبدیل معمولاً یک نگاشت ساده نیست: در کدگذاری‌های با طول متغیر، یک محدودهٔ منفرد از code pointها ممکن است به یک گراف پیچیده از code unitها ترجمه شود. کدگذاری‌های زیر پشتیبانی می‌شوند: .INDENT 0.0 .IP \(bu 2 \fBASCII\fP (به‌طور پیش‌فرض فعال است). این یک کدگذاری با طول ثابت با فضای کد \fB[0\-255]\fP و code pointها و code unitهای ۱\-بایتی است. .IP \(bu 2 \fBEBCDIC\fP (فعال‌شده با \fB\-\-ebcdic\fP یا \fBre2c:encoding:ebcdic\fP). این یک کدگذاری با طول ثابت با فضای کد \fB[0\-255]\fP و code pointها و code unitهای ۱\-بایتی است. .IP \(bu 2 \fBUCS2\fP (فعال‌شده با \fB\-\-ucs2\fP یا \fBre2c:encoding:ucs2\fP). این یک کدگذاری با طول ثابت با فضای کد \fB[0\-0xFFFF]\fP و code pointها و code unitهای ۲\-بایتی است. .IP \(bu 2 \fBUTF8\fP (فعال‌شده با \fB\-\-utf8\fP یا \fBre2c:encoding:utf8\fP). این یک کدگذاری یونیکد با طول متغیر است. اندازهٔ code unit برابر با ۱ بایت است. code pointها با ۱ \-\- ۴ code unit نمایش داده می‌شوند. .IP \(bu 2 \fBUTF16\fP (فعال‌شده با \fB\-\-utf16\fP یا \fBre2c:encoding:utf16\fP). این یک کدگذاری یونیکد با طول متغیر است. اندازهٔ code unit برابر با ۲ بایت است. code pointها با ۱ \-\- ۲ code unit نمایش داده می‌شوند. .IP \(bu 2 \fBUTF32\fP (فعال‌شده با \fB\-\-utf32\fP یا \fBre2c:encoding:utf32\fP). این یک کدگذاری یونیکد با طول ثابت با فضای کد \fB[0\-0x10FFFF]\fP و code pointها و code unitهای ۴\-بایتی است. .UNINDENT .sp فایل‌های ضمیمهٔ \fBinclude/unicode_blocks.re\fP، \fBinclude/unicode_categories.re\fP و \fBinclude/unicode_properties.re\fP تعاریف re2d را برای بلوک‌ها، دسته‌ها و ویژگی‌های توصیف‌شده در استاندارد یونیکد فراهم می‌کنند. .sp گزینهٔ \fB\-\-input\-encoding\fP کدگذاری فایل مبدأ را تعیین می‌کند، که می‌تواند برای فعال کردن لیترال‌های یونیکد در عبارات باقاعده استفاده شود. برای مثال \fB\-\-input\-encoding utf8\fP به re2d می‌گوید که فایل مبدأ با فرمت UTF8 است (این گزینه با \fB\-\-utf8\fP که کدگذاری متن ورودی را تنظیم می‌کند متفاوت است). گزینهٔ \fB\-\-encoding\-policy\fP نحوهٔ مدیریت جانشین‌های یونیکد (code pointها در محدودهٔ \fB[0xD800\-0xDFFF]\fP) را توسط re2d مشخص می‌کند. .sp در ادامه نمونه‌ای از یک تحلیل‌گر لغوی برای شناسه‌های یونیکد با کدگذاری UTF8 آمده است. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C // re2d $INPUT \-o $OUTPUT \-8 \-i module main; /*!include:re2c \(dqunicode_categories.re\(dq */ private int lex(const(char)* s) { const(char)* yycursor = s, yymarker; /*!re2c re2c:YYCTYPE = \(dqchar\(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; } */ } void main() { assert(lex(\(dq_Ыдентификатор\(dq) == 0); assert(lex(\(dq!!!\(dq)==1); } .ft P .fi .UNINDENT .UNINDENT .SS فایل‌های ضمیمه (Include files) .sp ابزار re2d به کاربر امکان می‌دهد فایل‌های دیگر را با استفاده از بلوکی به شکل \fB/*!include:re2c FILE */\fP یا \fB%{include FILE %}\fP، یا دستورالعمل درون‌بلوکی \fB!include FILE ;\fP ضمیمه کند، که در آن \fBFILE\fP مسیر فایل مورد نظر برای ضمیمه شدن است. re2d فایل‌های ضمیمه را در پوشهٔ فایل دربرگیرنده و در مسیرهای ضمیمه که می‌توان با گزینهٔ \fB\-I\fP تعیین کرد، جستجو می‌کند. بلوک‌ها/دستورالعمل‌های ضمیمه در re2d دقیقاً مشابه \fB#include\fP در C/C++ عمل می‌کنند: محتویات \fBFILE\fP عیناً در محل بلوک/دستورالعمل جای‌گذاری می‌شوند. فایل‌های ضمیمه ممکن است خود شامل فایل‌های ضمیمهٔ دیگری باشند. از گزینهٔ \fB\-\-depfile\fP برای ردیابی وابستگی‌های ساخت فایل خروجی به فایل‌های ضمیمه استفاده کنید. ابزار re2d برخی فایل‌های ضمیمهٔ از پیش تعریف‌شده را ارائه می‌دهد که در زیرپوشهٔ \fBinclude/\fP پروژه یافت می‌شوند. این فایل‌ها شامل تعاریفی هستند که ممکن است برای پروژه‌های دیگر نیز مفید باشند (مانند دسته‌بندی‌های یونیکد) و ساختاری شبیه به یک کتابخانهٔ استاندارد برای re2d تشکیل می‌دهند\&. در ادامه مثالی از نحوهٔ استفاده از فایل‌های ضمیمه آورده شده است. .SS فایل ضمیمهٔ ۱ (definitions.d) .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C enum Result{ OK, FAIL }; /*!re2c number = [1\-9][0\-9]*; */ .ft P .fi .UNINDENT .UNINDENT.SS فایل include ۲ (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 Result.OK; } .ft P .fi .UNINDENT .UNINDENT .SS فایل ورودی .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C // re2d $INPUT \-o $OUTPUT \-i /*!include:re2c \(dqdefinitions.d\(dq */ private Result lex(const(char)* s) { const(char)* yycursor = s, yymarker; /*!re2c re2c:YYCTYPE = \(dqchar\(dq; re2c:yyfill:enable = 0; * { return Result.FAIL; } number { return Result.OK; } !include \(dqextra_rules.re.inc\(dq; */ } void main() { assert(lex(\(dq123\(dq) == Result.OK); assert(lex(\(dq123.4567\(dq) == Result.OK); } .ft P .fi .UNINDENT .UNINDENT .SS فایل‌های سرآیند .sp ابزار re2d این امکان را فراهم می‌سازد که با استفاده از گزینهٔ \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 یک فایل سرآیند تولید شود. بلوک نخست آغاز فایل سرآیند و بلوک دوم پایان آن را مشخص می‌کند. تمام موارد مابین این بلوک‌ها توسط re2d پردازش شده و کد تولیدشده در فایلی که با گزینهٔ \fB\-\-header\fP یا پیکربندی \fBre2c:header\fP مشخص شده (یا در صورت عدم استفاده از گزینه یا پیکربندی، در \fBstdout\fP) نوشته می‌شود. فایل سرآیند تولیدشدهٔ خودکار ممکن است در مواردی نیاز باشد که از re2d برای تولید تعاریفی استفاده می‌شود که باید از سایر واحدهای ترجمه (translation units) قابل مشاهده باشند. .sp در ادامه نمونه‌ای از تولید یک فایل سرآیند آورده شده است که شامل تعریف وضعیت لکسر به همراه متغیرهای برچسب (tag variables) است (تعداد متغیرها به گرامر باقاعده بستگی داشته و برای برنامه‌نویس نامشخص است). .SS فایل ورودی .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C // re2d $INPUT \-o $OUTPUT \-i \-\-header lexer/state.d module main; import core.stdc.stddef; import lexer.state; // the module is generated by re2c /*!header:re2c:on*/ module lexer.state; struct LexerState { const(char)* str, yycursor; /*!stags:re2c format = \(dqconst(char)* @@;\(dq; */ }; /*!header:re2c:off*/ private long lex(ref LexerState yyrecord) { const(char)* t; /*!re2c re2c:api = record; re2c:YYCTYPE = \(dqchar\(dq; re2c:tags = 1; re2c:yyfill:enable = 0; re2c:header = \(dqlexer/state.d\(dq; [a]* @t [b]* { return t \- yyrecord.str; } */ } void main() { const(char)* s = \(dqab\(dq; LexerState st = {s, s /*!stags:re2c format = \(dq, null\(dq; */}; assert(lex(st) == 1); const(char)* s2 = \(dqaaabbbbbbbb\(dq; LexerState st2 = {s2, s2 /*!stags:re2c format = \(dq, null\(dq; */}; assert(lex(st2) == 3); } .ft P .fi .UNINDENT .UNINDENT .SS فایل سرآیند .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C /* Generated by re2c */ module lexer.state; struct LexerState { const(char)* str, yycursor; const(char)* yyt1; }; .ft P .fi .UNINDENT .UNINDENT.SS برنامه‌های اسکلتی (Skeleton programs) .sp با گزینهٔ \fB\-S, \-\-skeleton\fP، ابزار re2d تمام کدهای غیر re2d را نادیده گرفته و یک برنامهٔ C خودکفا تولید می‌کند که می‌تواند در ادامه کامپایل و اجرا شود. این برنامه از کد تحلیل‌گر لغوی (lexer) و داده‌های ورودی تشکیل شده است. برای هر DFA ساخته‌شده (بلوک یا شرط)، re2d یک lexer مستقل و دو فایل تولید می‌کند: یک فایل \fB\&.input\fP با رشته‌های مشتق‌شده از DFA، و یک فایل \fB\&.keys\fP با نتایج تطابق مورد انتظار. برنامه هر lexer را بر روی فایل \fB\&.input\fP مربوطه اجرا کرده و نتایج را با انتظارات مقایسه می‌کند. برنامه‌های اسکلتی به چند دلیل بسیار مفید هستند: .INDENT 0.0 .IP \(bu 2 آن‌ها می‌توانند درستی بهینه‌سازی‌های مختلف re2d را بررسی کنند (داده‌ها در ابتدای فرآیند، پیش از اعمال هرگونه تغییر و تبدیل در DFA تولید می‌شوند). .IP \(bu 2 تولید مجموعه‌ای از داده‌های ورودی با پوشش مناسب می‌تواند هم برای آزمون و هم برای بنچمارک مفید باشد. .IP \(bu 2 تولید برنامه‌های اجرایی خودکفا به کاربر امکان می‌دهد نمونه‌های آزمون کمینه (minimized test cases) دریافت کند (کد اصلی ممکن است بزرگ بوده یا وابستگی‌های زیادی داشته باشد). .UNINDENT .sp دشواریِ تولید داده‌های ورودی در این است که به‌جز در ساده‌ترین حالت‌ها، تعداد رشته‌های ورودیِ ممکن بیش از حد زیاد است (حتی اگر طول رشته محدود باشد). re2d این مشکل را با تولید رشته‌های کافی برای پوشش تقریباً تمام انتقال‌های DFA حل می‌کند. این ابزار از الگوریتم زیر استفاده می‌کند: ابتدا یک اسکلت از DFA می‌سازد. برای کدگذاری‌هایی با اندازهٔ واحد کد ۱ بایتی (مانند ASCII، UTF\-8 و EBCDIC)، این اسکلت صرفاً یک کپی دقیق از DFA اصلی است. برای کدگذاری‌هایی با واحدهای کد چندبایتی، اسکلت یک کپی از DFA با حذف برخی از انتقال‌ها است: بدین ترتیب که re2d حداکثر ۲۵۶ واحد کد را برای هر بازهٔ پیوسته و مجزا که متناظر با یک انتقال DFA است در نظر می‌گیرد. مقادیر انتخاب‌شده به‌طور یکنواخت توزیع شده‌اند و شامل مرزهای بازه نیز می‌شوند. re2d به‌جای تلاش برای پوشش تمام مسیرهای ممکن در اسکلت (که کاری ناممکن است)، مسیرهای کافی برای پوشش همهٔ انتقال‌های اسکلت را تولید می‌کند و بدین ترتیب پرش‌های شرطی مربوطه را در lexer تحریک می‌نماید. پیاده‌سازی این الگوریتم به حدود 1Gb انتقال محدود شده و مقدار ثابتی از حافظه را مصرف می‌کند (re2d داده‌ها را به‌محض تولید در فایل می‌نویسد). .SS مصورسازی و اشکال‌زدایی (Visualization and debug) .sp با گزینهٔ \fB\-D, \-\-emit\-dot\fP، ابزار re2d کدی تولید نمی‌کند؛ در عوض، DFA تولیدشده را در قالب DOT ذخیره (dump) می‌کند. می‌توان این خروجی را با استفاده از 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 ابزار re2d در اصل توسط 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. .