.\" 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 "RE2RUST" 1 "" "" "" .SH "نام (NAME)" re2rust \- ساخت تحلیل‌گرهای لغوی سریع برای Rust .SH "خلاصه دستور (SYNOPSIS)" .sp re2rust \fB[ OPTIONS ]\fP \fB[ WARNINGS ]\fP \fBINPUT\fP .sp ورودی می‌تواند یک فایل یا \fB\-\fP برای stdin باشد. .SH "مقدمه (INTRODUCTION)" .sp ابزار re2rust به‌عنوان یک پیش‌پردازنده عمل می‌کند. این ابزار فایل ورودی را (که معمولاً برنامه‌ای به زبان Rust است، اما می‌تواند هر چیز دیگری باشد) می‌خواند و به دنبال بلوک‌هایی از کد می‌گردد که در نشانگرهای آغاز/پایان با ساختار ویژه محصور شده‌اند. متن‌های خارج از این بلوک‌ها عیناً به فایل خروجی منتقل می‌شوند. محتویات این بلوک‌ها توسط re2rust پردازش می‌شود؛ re2rust آن‌ها را به کد Rust ترجمه کرده و کد تولیدشده را به جای آن بلوک قرار می‌دهد. .sp در ادامه مثالی از یک برنامه کوچک آورده شده است که بررسی می‌کند آیا یک رشته داده‌شده حاوی یک عدد ده‌دهی (decimal) است یا خیر: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C // re2rust $INPUT \-o $OUTPUT \-\-no\-unsafe \-\-api simple fn lex(yyinput: &[u8]) \-> bool { let mut yycursor = 0; /*!re2c re2c:YYCTYPE = u8; re2c:yyfill:enable = 0; [1\-9][0\-9]* { return true; } * { return false; } */ } fn main() { assert!(lex(b\(dq1234\e0\(dq)); } .ft P .fi .UNINDENT .UNINDENT .sp در خروجی، re2rust بلوک میانی را با کد تولیدشده جایگزین کرده است: .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C /* Generated by re2rust */ // re2rust $INPUT \-o $OUTPUT \-\-no\-unsafe \-\-api simple fn lex(yyinput: &[u8]) \-> bool { let mut yycursor = 0; { #[allow(unused_assignments)] let mut yych : u8 = 0; let mut yystate : usize = 0; \(aqyyl: loop { match yystate { 0 => { yych = yyinput[yycursor]; yycursor += 1; match yych { 0x31 ..= 0x39 => { yystate = 2; continue \(aqyyl; } _ => { yystate = 1; continue \(aqyyl; } } } 1 => { return false; }, 2 => { yych = yyinput[yycursor]; match yych { 0x30 ..= 0x39 => { yycursor += 1; yystate = 2; continue \(aqyyl; } _ => { yystate = 3; continue \(aqyyl; } } } 3 => { return true; }, _ => panic!(\(dqinternal lexer error\(dq), } } } } fn main() { assert!(lex(b\(dq1234\e0\(dq)); } .ft P .fi .UNINDENT .UNINDENT.SH "مبانی (BASICS)" .sp یک برنامه re2rust از دنباله‌ای از \fIبلوک‌ها\fP آمیخته با کد در زبان مقصد تشکیل شده است. یک بلوک می‌تواند شامل \fIتعاریف\fP، \fIپیکربندی‌ها\fP، \fIقواعد\fP، \fIکنش‌ها\fP و \fIدستورالعمل‌ها\fP به هر ترتیبی باشد: .INDENT 0.0 .TP .B \fBname = regular\-expression ;\fP یک \fIتعریف\fP، \fBname\fP را به \fBregular\-expression\fP مقید می‌کند\&. نام‌ها می‌توانند شامل نویسه‌های الفبایی\-عددی و زیرخط باشند. بخش \fI\%عبارات باقاعده\fP مروری کلی بر نحو عبارات باقاعده در re2rust ارائه می‌دهد. پس از تعریف، \fBname\fP می‌تواند در سایر عبارات باقاعده و قواعد استفاده شود. بازگشت در تعاریف نام‌گذاری‌شده مجاز نیست و هر نام باید پیش از استفاده تعریف شده باشد. یک بلوک، تعاریف نام‌گذاری‌شده را از حوزه سراسری به ارث می‌برد. تعریف مجدد نامی که در حوزه فعلی وجود دارد، خطا است. .TP .B \fBconfiguration = value ;\fP یک \fIپیکربندی\fP امکان تغییر رفتار re2rust و سفارشی‌سازی کد تولیدشده را فراهم می‌سازد. برای فهرست کاملی از پیکربندی‌های پشتیبانی‌شده توسط re2rust بخش \fI\%پیکربندی‌ها\fP را ببینید. بسته به هر پیکربندی خاص، \fBvalue\fP می‌تواند یک کلمه کلیدی، یک عدد صحیح غیرمنفی یا یک رشته تک‌خطی باشد که باید درون علامت‌های نقل‌قول تکی یا دوتایی قرار گیرد، مگر اینکه فقط از نویسه‌های الفبایی\-عددی تشکیل شده باشد. یک بلوک، پیکربندی‌ها را از حوزه سراسری به ارث می‌برد و می‌تواند آن‌ها را بازتعریف کرده یا موارد جدیدی اضافه کند. پیکربندی‌های تعریف‌شده درون یک بلوک، بر کل بلوک تأثیر می‌گذارند، حتی اگر در انتهای آن قرار گرفته باشند. .TP .B \fBregular\-expression code\fP یک \fIقاعده\fP، \fBregular\-expression\fP را به کنش معنایی آن مقید می‌کند (یک بلوک کد درون آکوالاد، یا یک بلوک کد که با \fB:=\fP آغاز شده و به یک خط جدید ختم می‌شود که پس از آن هر نویسه غیرفضای‌خالی بیاید). اگر \fBregular\-expression\fP تطبیق یابد، \fBcode\fP مربوطه اجرا می‌شود. اگر چندین قاعده مطابقت داشته باشند، طولانی‌ترین تطبیق اولویت دارد. اگر چندین قاعده با یک رشته تطابق داشته باشند، اولین قاعده اولویت دارد. دو قاعده ویژه وجود دارد: قاعده پیش‌فرض \fB*\fP و قاعده پایان ورودی \fB$\fP\&. قاعده پیش‌فرض همواره باید تعریف شود، صرف‌نظر از جایگاهش در بلوک کمترین اولویت را دارد و با هر واحد کد تطبیق می‌یابد (نه لزوماً یک نویسه معتبر، بخش \fI\%پشتیبانی از کدگذاری\fP را ببینید). قاعده پایان ورودی باید در صورتی تعریف شود که روش متناظر برای \fI\%مدیریت پایان ورودی\fP استفاده شده باشد. با \fI\%شرایط شروع\fP، قواعد نحو پیچیده‌تری خواهند داشت. .TP .B \fB!action code\fP یک \fIکنش\fP، یک بلوک \fBcode\fP تعریف‌شده توسط کاربر را به مکانی خاص در ماشین حالت متناهی تولیدشده مقید می‌سازد (همان‌گونه که کنش‌های معنایی کد را به حالت‌های پایانی پیوند می‌دهند). برای فهرست کاملی از کنش‌های از پیش‌تعریف‌شده، بخش \fI\%کنش‌ها\fP را ببینید. .TP .B \fB!directive ;\fP یک \fIدستورالعمل\fP یکی از عبارت‌های ویژه از پیش‌تعریف‌شده است. هر دستورالعمل هدف منحصر‌به‌فردی دارد. برای جزئیات بخش \fI\%دستورالعمل‌ها\fP را ببینید. .UNINDENT .SS "بلوک‌ها (Blocks)" .sp نشانگرهای آغاز و پایان بلوک یا \fB/*!re2c\fP و \fB*/\fP هستند، یا \fB%{\fP و \fB%}\fP (از هر دو سبک پشتیبانی می‌شود). از نسخه 2.2 بلوک‌ها می‌توانند نام‌های اختیاری داشته باشند که امکان ارجاع به آن‌ها را در سایر بلوک‌ها فراهم می‌کند. انواع مختلفی از بلوک‌ها وجود دارند: .INDENT 0.0 .TP .B \fB/*!re2c[:] ... */\fP یا \fB%{[:] ... %}\fP یک \fIبلوک سراسری\fP شامل تعاریف، پیکربندی‌ها، قواعد و دستورالعمل‌ها است. re2rust عبارات باقاعده مرتبط با هر قاعده را در یک اتوماتون متناهی قطعی کامپایل کرده، آن را به شکل پرش‌های شرطی در زبان مقصد کدگذاری می‌کند و بلوک را با کد تولیدشده جایگزین می‌سازد. نام‌ها و پیکربندی‌های تعریف‌شده در یک بلوک سراسری به حوزه سراسری اضافه شده و برای بلوک‌های پس از آن قابل مشاهده می‌شوند. در ابتدای برنامه، حوزه سراسری با \fI\%گزینه‌های\fP خط فرمان مقداردهی اولیه می‌شود. .TP .B \fB/*!local:re2c[:] ... */\fP یا \fB%{local[:] ... %}\fP یک \fIبلوک محلی\fP مانند یک بلوک سراسری است، با این تفاوت که نام‌ها و پیکربندی‌های درون آن دارای حوزه محلی هستند (بر سایر بلوک‌ها تأثیر نمی‌گذارند). .TP .B \fB/*!rules:re2c[:] ... */\fP یا \fB%{rules[:] ... %}\fP یک \fIبلوک قواعد\fP شبیه به یک بلوک محلی است، اما به‌خودی‌خود هیچ کدی تولید نمی‌کند و هیچ تعریفی را به حوزه سراسری اضافه نمی‌نماید \-\- هدف آن استفاده مجدد در سایر بلوک‌ها است. این روشی برای اشتراک‌گذاری کد است (جزئیات بیشتر در بخش \fI\%بلوک‌های قابل استفاده مجدد\fP). پیش از نسخه 2.2 re2rust، بلوک‌های قواعد به گزینه \fB\-r \-\-reusable\fP نیاز داشتند. .TP .B \fB/*!use:re2c[:] ... */\fP یا \fB%{use[:] ... %}\fP یک بلوک استفاده که به یک بلوک قواعدِ از پیش‌تعریف‌شده ارجاع می‌دهد. اگر نام مشخص شده باشد، re2rust به دنبال یک بلوک قواعد با این نام می‌گردد. در غیر این صورت، از جدیدترین بلوک قواعد استفاده می‌شود (خواه نام‌گذاری‌شده باشد یا بدون نام). یک بلوک استفاده می‌تواند تعاریف، پیکربندی‌ها و قواعد خاص خود را بیفزاید که به موارد موجود در بلوک قواعد ارجاع‌شده اضافه می‌شوند. پیش از نسخه 2.2 re2rust، بلوک‌های استفاده به گزینه \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 تولیدشده توسط re2rust بسط می‌یابد\&. یک فهرست اختیاری از نام‌های بلوک مشخص می‌کند که هنگام محاسبه مجموعه متغیرهای برچسب، کدام بلوک‌ها باید لحاظ شوند (اگر فهرست خالی باشد، همه بلوک‌ها لحاظ می‌شوند). دو پیکربندی اختیاری وجود دارد: \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) یا به‌طور ضمنی توسط re2rust تولید شده باشد (با گزینه‌های \fB\-\-captvars\fP یا \fB\-\-posix\-captvars\fP) بسط می‌یابد. یک فهرست اختیاری از نام‌های بلوک مشخص می‌کند که هنگام محاسبه مجموعه برچسب‌ها، کدام بلوک‌ها باید لحاظ شوند (اگر فهرست خالی باشد، همه بلوک‌ها لحاظ می‌شوند). دو پیکربندی اختیاری وجود دارد: \fBformat\fP و \fBseparator\fP\&. پیکربندی \fBformat\fP یک رشته الگو را مشخص می‌کند که در آن \fB@@{tag}\fP (یا به‌اختصار \fB@@\fP) با نام هر برچسب جایگزین می‌شود. پیکربندی \fBseparator\fP قطعه‌کدی را مشخص می‌کند که برای پیوند دادن قطعات تولیدشده \fBformat\fP برای برچسب‌های مختلف به کار می‌رود. .TP .B \fB/*!getstate:re2c[:[:...]] ... */\fP یا \fB%{getstate[:[:...]] ... %}\fP بلوکی که توزیع شرطی را بر اساس وضعیت تحلیل‌گر واژگانی تولید می‌کند (به گزینه \fB\-\-storable\-state\fP نیاز دارد). یک فهرست اختیاری از نام‌های بلوک مشخص می‌کند که کدام بلوک‌ها باید در توزیع وضعیت لحاظ شوند. انتقال پیش‌فرض به برچسب شروع اولین بلوک در فهرست می‌رود. اگر فهرست خالی باشد، تمام بلوک‌ها لحاظ می‌شوند و انتقال پیش‌فرض به اولین بلوک در فایلی می‌رود که برچسب شروع دارد. این نوع بلوک با گزینه \fB\-\-loop\-switch\fP ناسازگار است، زیرا نیازمند انتقال‌های بین‌بلوکی است که بدون \fBgoto\fP یا فراخوانی توابع پشتیبانی نمی‌شوند. .TP .B \fB/*!conditions:re2c[:[:...]] ... */\fP, \fB/*!types:re2c... */\fP یا \fB%{conditions[:[:...]] ... %}\fP, \fB%{types... %}\fP بلوکی که شمارش شرایط را تولید می‌کند (به گزینه \fB\-\-conditions\fP نیاز دارد). یک فهرست اختیاری از نام‌های بلوک مشخص می‌کند که هنگام محاسبه مجموعه شرایط، کدام بلوک‌ها باید لحاظ شوند (اگر فهرست خالی باشد، همه بلوک‌ها لحاظ می‌شوند). به‌طور پیش‌فرض کد تولیدشده یک نوع شمارشی \fBYYCONDTYPE\fP است\&. این مقدار می‌تواند با پیکربندی‌های اختیاری \fBformat\fP و \fBseparator\fP سفارشی‌سازی شود. پیکربندی \fBformat\fP یک رشته الگو را مشخص می‌کند که در آن \fB@@{cond}\fP (یا به‌اختصار \fB@@\fP) با نام هر شرط، و \fB@@{num}\fP با اندیس عددی آن شرط جایگزین می‌شود. پیکربندی \fBseparator\fP قطعه‌کدی را مشخص می‌کند که برای پیوند دادن قطعات تولیدشده \fBformat\fP برای شرایط مختلف به کار می‌رود. .TP .B \fB/*!include:re2c */\fP یا \fB%{include %}\fP این بلوک امکان درج \fB\fP را فراهم می‌کند، که باید یک مسیر فایل درون علامت‌های نقل‌قول دوتایی باشد. محتویات فایل دقیقاً به جای بلوک جایگزین می‌شود، درست مانند نحوه کارکرد \fB#include\fP در C/C++. این بلوک می‌تواند همراه با گزینه \fB\-\-depfile\fP برای تولید وابستگی‌های سامانه ساخت بر روی فایل‌های گنجانده‌شده استفاده شود. .TP .B \fB/*!header:re2c:on*/\fP یا \fB%{header:on %}\fP این بلوک آغاز فایل سرآیند را مشخص می‌کند. تمام موارد پس از آن و تا بلوک \fBheader:off\fP بعدی توسط re2rust پردازش شده و در فایل سرآیند مشخص‌شده با گزینه \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 در اینجا فهرست کاملی از پیکربندی‌های پشتیبانی‌شده توسط re2rust آمده است: .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 است. یک جای‌نگهدار با sigil آغاز شده و به دنبال آن نام آرگومان در آکولاد می‌آید. برای نمونه، اگر sigil روی \fB$\fP تنظیم شود، جای‌نگهدارها به شکل \fB${name}\fP خواهند بود. رابط‌های برنامه‌نویسی تک‌آرگومانی ممکن است از نشانه‌گذاری خلاصه بدون نام در آکولاد استفاده کنند. این گزینه می‌تواند با گزینه‌های مربوط به هر یک از عناصر پایهٔ API بازنویسی (override) شود، مانند \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)، نه برای زمینهٔ کلی تحلیل‌گر واژگانی (lexer context)، بنابراین عناصر پایه بیشتر شبیه ماکروها در C/C++ یا بستارها (closures) در Go و Rust عمل می‌کنند. در سبک free\-form، عناصر پایهٔ API شکل ثابتی ندارند: آن‌ها باید به‌صورت رشته‌هایی حاوی قطعه‌کدهای آزاد با متغیرهای درون‌یابی‌شده به شکل \fB@@{var}\fP یا \fB@@\fP تعریف شوند (که با آرگومان‌ها در سبک تابع‌گونه مطابقت دارند). این پیکربندی ممکن است برای هر یک از عناصر پایهٔ API بازنویسی (override) شود، برای نمونه به پیکربندی \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 محاسباتی استفاده شود، این پیکربندی آستانهٔ پیچیدگی را مشخص می‌کند که تولید جدول‌های پرش (jump tables) را به جای دستورهای \fBif\fP تو در تو و نگاشت‌های بیتی (bitmaps) فعال می‌کند. مقدار پیش‌فرض \fB9\fP است. .TP .B \fBre2c:cond:abort\fP اگر روی یک مقدار عددی صحیح و مثبت تنظیم شود، حالت پیش‌فرض (default case) در توزیع شرطیِ تولیدشده، اجرای برنامه را متوقف می‌کند. .TP .B \fBre2c:cond:goto\fP قطعه‌کدی را مشخص می‌کند که برای قواعد میان‌بُر خودکار تولیدشدهٔ \fB:=>\fP در شرایط استفاده می‌شود. پیش‌فرض \fBgoto @@;\fP است. جای‌نگهدار \fB@@\fP با نام شرط جایگزین می‌شود (به پیکربندی‌های \fBre2c:api:sigil\fP و \fBre2c:cond:goto@cond\fP مراجعه کنید). .TP .B \fBre2c:cond:goto@cond\fP نشانگر (sigil) مورد استفاده برای جایگزینی آرگومان را در تعریف \fBre2c:cond:goto\fP مشخص می‌کند. مقدار پیش‌فرض \fB@@\fP است. پیکربندی عمومی‌تر \fBre2c:api:sigil\fP را بازنویسی (override) می‌کند. .TP .B \fBre2c:cond:divider\fP جداکننده را برای بلوک‌های شرط تعریف می‌کند. مقدار پیش‌فرض \fB/* *********************************** */\fP است. جای‌نگهدارها با نام شرط جایگزین می‌شوند (به \fBre2c:api;sigil\fP و \fBre2c:cond:divider@cond\fP مراجعه کنید). .TP .B \fBre2c:cond:divider@cond\fP نشانگر (sigil) مورد استفاده برای جایگزینی آرگومان را در تعریف \fBre2c:cond:divider\fP مشخص می‌کند. پیش‌فرض \fB@@\fP است. پیکربندی عمومی‌تر \fBre2c:api:sigil\fP را بازنویسی (override) می‌کند. .TP .B \fBre2c:cond:prefix\fP, \fBre2c:condprefix\fP پیشوند مورد استفاده برای برچسب‌های شرط را مشخص می‌کند. پیش‌فرض \fByyc_\fP است. .TP .B \fBre2c:cond:enumprefix\fP, \fBre2c:condenumprefix\fP پیشوند مورد استفاده برای شناسه‌های شرط را مشخص می‌کند. پیش‌فرض \fByyc\fP است. .TP .B \fBre2c:debug\-output\fP, \fBre2c:flags:debug\-output\fP, \fBre2c:flags:d\fP مشابه گزینهٔ \fB\-\-debug\-output\fP، اما می‌تواند بر پایهٔ هر بلوک پیکربندی شود. .TP .B \fBre2c:empty\-class\fP, \fBre2c:flags:empty\-class\fP مشابه گزینهٔ \fB\-\-empty\-class\fP، اما می‌تواند بر پایهٔ هر بلوک پیکربندی شود. .TP .B \fBre2c:encoding:ebcdic\fP, \fBre2c:flags:ecb\fP, \fBre2c:flags:e\fP مشابه گزینهٔ \fB\-\-ebcdic\fP، اما می‌تواند بر پایهٔ هر بلوک پیکربندی شود. .TP .B \fBre2c:encoding:ucs2\fP, \fBre2c:flags:wide\-chars\fP, \fBre2c:flags:w\fP مشابه گزینهٔ \fB\-\-ucs2\fP، اما می‌تواند بر پایهٔ هر بلوک پیکربندی شود. .TP .B \fBre2c:encoding:utf8\fP, \fBre2c:flags:utf\-8\fP, \fBre2c:flags:8\fP مشابه گزینهٔ \fB\-\-utf8\fP، اما می‌تواند بر پایهٔ هر بلوک پیکربندی شود. .TP .B \fBre2c:encoding:utf16\fP, \fBre2c:flags:utf\-16\fP, \fBre2c:flags:x\fP مشابه گزینهٔ \fB\-\-utf16\fP، اما می‌تواند بر پایهٔ هر بلوک پیکربندی شود. .TP .B \fBre2c:encoding:utf32\fP, \fBre2c:flags:unicode\fP, \fBre2c:flags:u\fP مشابه گزینهٔ \fB\-\-utf32\fP، اما می‌تواند بر پایهٔ هر بلوک پیکربندی شود. .TP .B \fBre2c:encoding\-policy\fP, \fBre2c:flags:encoding\-policy\fP مشابه گزینهٔ \fB\-\-encoding\-policy\fP، اما می‌تواند بر پایهٔ هر بلوک پیکربندی شود. .TP .B \fBre2c:eof\fP نماد نگهبان (sentinel symbol) مورد استفاده با قاعدهٔ پایان ورودی \fB$\fP را مشخص می‌کند. مقدار پیش‌فرض \fB\-1\fP است (از قاعدهٔ \fB$\fP استفاده نمی‌شود). سایر مقادیر ممکن شامل تمامی واحدهای کد معتبر است. تنها اعداد دهدهی شناسایی می‌شوند. .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 نام برچسب اختیاری‌ای را که پس از گزینشگر (switch) \fBYYGETSTATE\fP در حالت وضعیت ذخیره‌پذیر می‌آید (فعال‌شده با \fBre2c:state:nextlabel\fP) مشخص می‌کند. پیش‌فرض \fByyNext\fP است. .TP .B \fBre2c:lookahead\fP, \fBre2c:flags:lookahead\fP منسوخ‌شده (گزینهٔ منسوخ‌شدهٔ \fB\-\-no\-lookahead\fP را ببینید). .TP .B \fBre2c:monadic\fP اگر روی مقداری غیر از صفر تنظیم شود، تحلیل‌گر واژگانی تولیدشده از نشانه‌گذاری مونادیک (monadic notation) استفاده خواهد کرد (این پیکربندی مختص Haskell است)..TP .B \fBre2c:nested\-ifs\fP, \fBre2c:flags:nested\-ifs\fP, \fBre2c:flags:s\fP مشابه گزینهٔ \fB\-\-nested\-ifs\fP، اما می‌تواند بر پایهٔ هر بلوک پیکربندی شود. .TP .B \fBre2c:posix\-captures\fP, \fBre2c:flags:posix\-captures\fP, \fBre2c:flags:P\fP مشابه گزینهٔ \fB\-\-posix\-captures\fP، اما می‌تواند بر پایهٔ هر بلوک پیکربندی شود. .TP .B \fBre2c:posix\-captvars\fP مشابه گزینهٔ \fB\-\-posix\-captvars\fP، اما می‌تواند بر پایهٔ هر بلوک پیکربندی شود. .TP .B \fBre2c:tags\fP, \fBre2c:flags:tags\fP, \fBre2c:flags:T\fP مشابه گزینهٔ \fB\-\-tags\fP، اما می‌تواند بر پایهٔ هر بلوک پیکربندی شود. .TP .B \fBre2c:tags:expression\fP عبارت مورد استفاده برای متغیرهای برچسب را مشخص می‌کند. به‌طور پیش‌فرض re2rust عبارت‌هایی به شکل \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 است). .TP .B \fBre2c:tags:prefix\fP پیشوند نام متغیرهای برچسب را مشخص می‌کند. مقدار پیش‌فرض \fByyt\fP\& است. .TP .B \fBre2c:sentinel\fP نماد دیده‌بان (sentinel) مورد استفاده برای بررسی‌های پایان ورودی را مشخص می‌کند (زمانی که بررسی‌های محدوده با \fBre2c:yyfill:enable = 0;\fP غیرفعال شده باشند و \fBre2c:eof\fP تنظیم نشده باشد). این پیکربندی بر تولید کد تأثیری ندارد: هدف آن این است که تأیید کند نماد دیده‌بان در میانهٔ یک قاعده مجاز نیست، و اطمینان حاصل شود که تحلیل‌گر لغوی فراتر از انتهای بافر را نخواهد خواند. مقدار پیش‌فرض \fI\-1\(ga\fP است (در این حالت re2rust فرض می‌کند که دیده‌بان صفر است که رایج‌ترین حالت است). تنها اعداد ده‌دهی شناخته می‌شوند. .TP .B \fBre2c:state:abort\fP اگر روی یک مقدار عددی صحیح مثبت تنظیم شود، حالت پیش‌فرض (default case) در توزیع وضعیت (state dispatch) تولیدشده، اجرای برنامه را لغو (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، اما می‌تواند بر پایهٔ هر بلوک پیکربندی شود. اگر روی صفر تنظیم شود، از تولید بسته‌بندی‌های (wrappers) \fBunsafe\fP در اطراف \fBYYPEEK\fP\& جلوگیری می‌کند. مقدار پیش‌فرض غیرصفر است (بسته‌بندی‌ها تولید می‌شوند). این پیکربندی مختص به Rust است. .TP .B \fBre2c:YYBACKUP\fP, \fBre2c:define:YYBACKUP\fP عنصر پایهٔ عمومی API به نام \fBYYBACKUP\fP\& را تعریف می‌کند. .TP .B \fBre2c:YYBACKUPCTX\fP, \fBre2c:define:YYBACKUPCTX\fP عنصر پایهٔ عمومی API به نام \fBYYBACKUPCTX\fP\& را تعریف می‌کند. .TP .B \fBre2c:YYCONDTYPE\fP, \fBre2c:define:YYCONDTYPE\fP عنصر پایهٔ API به نام \fBYYCONDTYPE\fP\& را تعریف می‌کند. .TP .B \fBre2c:YYCTYPE\fP, \fBre2c:define:YYCTYPE\fP عنصر پایهٔ API به نام \fBYYCTYPE\fP\& را تعریف می‌کند. .TP .B \fBre2c:YYCTXMARKER\fP, \fBre2c:define:YYCTXMARKER\fP عنصر پایهٔ API به نام \fBYYCTXMARKER\fP\& را تعریف می‌کند. .TP .B \fBre2c:YYCURSOR\fP, \fBre2c:define:YYCURSOR\fP عنصر پایهٔ API به نام \fBYYCURSOR\fP\& را تعریف می‌کند. .TP .B \fBre2c:YYDEBUG\fP, \fBre2c:define:YYDEBUG\fP عنصر پایهٔ API به نام \fBYYDEBUG\fP\& را تعریف می‌کند. .TP .B \fBre2c:YYFILL\fP, \fBre2c:define:YYFILL\fP عنصر پایهٔ API به نام \fBYYFILL\fP\& را تعریف می‌کند. .TP .B \fBre2c:YYFILL@len\fP, \fBre2c:define:YYFILL@len\fP نشانهٔ (sigil) مورد استفاده برای جایگزینی آرگومان را در تعریف \fBYYFILL\fP مشخص می‌کند. مقدار پیش‌فرض \fB@@\fP\& است. پیکربندی عمومی‌تر \fBre2c:api:sigil\fP را بازنویسی می‌کند. .TP .B \fBre2c:YYFILL:naked\fP, \fBre2c:define:YYFILL:naked\fP پیکربندی عمومی‌تر \fBre2c:api:style\fP را برای \fBYYFILL\fP\& بازنویسی می‌کند. مقدار صفر متناظر با سبک آزاد API (free\-form) است. .TP .B \fBre2c:YYFN\fP عنصر پایهٔ API به نام \fBYYFN\fP\& را تعریف می‌کند. .TP .B \fBre2c:YYINPUT\fP عنصر پایهٔ API به نام \fBYYINPUT\fP\& را تعریف می‌کند. .TP .B \fBre2c:YYGETCOND\fP, \fBre2c:define:YYGETCONDITION\fP عنصر پایهٔ API به نام \fBYYGETCOND\fP\& را تعریف می‌کند. .TP .B \fBre2c:YYGETCOND:naked\fP, \fBre2c:define:YYGETCONDITION:naked\fP پیکربندی عمومی‌تر \fBre2c:api:style\fP را برای \fBYYGETCOND\fP\& بازنویسی می‌کند. مقدار صفر متناظر با سبک آزاد API (free\-form) است. .TP .B \fBre2c:YYGETSTATE\fP, \fBre2c:define:YYGETSTATE\fP عنصر پایهٔ API به نام \fBYYGETSTATE\fP\& را تعریف می‌کند. .TP .B \fBre2c:YYGETSTATE:naked\fP, \fBre2c:define:YYGETSTATE:naked\fP پیکربندی عمومی‌تر \fBre2c:api:style\fP را برای \fBYYGETSTATE\fP\& بازنویسی می‌کند. مقدار صفر متناظر با سبک آزاد API (free\-form) است. .TP .B \fBre2c:YYGETACCEPT\fP, \fBre2c:define:YYGETACCEPT\fP عنصر پایهٔ API به نام \fBYYGETACCEPT\fP\& را تعریف می‌کند. .TP .B \fBre2c:YYLESSTHAN\fP, \fBre2c:define:YYLESSTHAN\fP عنصر پایهٔ عمومی API به نام \fBYYLESSTHAN\fP\& را تعریف می‌کند. .TP .B \fBre2c:YYLIMIT\fP, \fBre2c:define:YYLIMIT\fP عنصر پایهٔ API به نام \fBYYLIMIT\fP\& را تعریف می‌کند. .TP .B \fBre2c:YYMARKER\fP, \fBre2c:define:YYMARKER\fP عنصر پایهٔ API به نام \fBYYMARKER\fP\& را تعریف می‌کند. .TP .B \fBre2c:YYMTAGN\fP, \fBre2c:define:YYMTAGN\fP عنصر پایهٔ عمومی API به نام \fBYYMTAGN\fP\& را تعریف می‌کند. .TP .B \fBre2c:YYMTAGP\fP, \fBre2c:define:YYMTAGP\fP عنصر پایهٔ عمومی API به نام \fBYYMTAGP\fP\& را تعریف می‌کند. .TP .B \fBre2c:YYPEEK\fP, \fBre2c:define:YYPEEK\fP عنصر پایهٔ عمومی API به نام \fBYYPEEK\fP\& را تعریف می‌کند. .TP .B \fBre2c:YYRESTORE\fP, \fBre2c:define:YYRESTORE\fP عنصر پایهٔ عمومی API به نام \fBYYRESTORE\fP\& را تعریف می‌کند. .TP .B \fBre2c:YYRESTORECTX\fP, \fBre2c:define:YYRESTORECTX\fP عنصر پایهٔ عمومی API به نام \fBYYRESTORECTX\fP\& را تعریف می‌کند. .TP .B \fBre2c:YYRESTORETAG\fP, \fBre2c:define:YYRESTORETAG\fP عنصر پایهٔ عمومی API به نام \fBYYRESTORETAG\fP\& را تعریف می‌کند. .TP .B \fBre2c:YYSETCOND\fP, \fBre2c:define:YYSETCONDITION\fP عنصر پایهٔ API به نام \fBYYSETCOND\fP\& را تعریف می‌کند. .TP .B \fBre2c:YYSETCOND@cond\fP, \fBre2c:define:YYSETCONDITION@cond\fP نشانهٔ (sigil) مورد استفاده برای جایگزینی آرگومان را در تعریف \fBYYSETCOND\fP مشخص می‌کند. مقدار پیش‌فرض \fB@@\fP\& است. پیکربندی عمومی‌تر \fBre2c:api:sigil\fP را بازنویسی می‌کند. .TP .B \fBre2c:YYSETCOND:naked\fP, \fBre2c:define:YYSETCONDITION:naked\fP پیکربندی عمومی‌تر \fBre2c:api:style\fP را برای \fBYYSETCOND\fP\& بازنویسی می‌کند. مقدار صفر متناظر با سبک آزاد API (free\-form) است. .TP .B \fBre2c:YYSETSTATE\fP, \fBre2c:define:YYSETSTATE\fP عنصر پایهٔ API به نام \fBYYSETSTATE\fP\& را تعریف می‌کند. .TP .B \fBre2c:YYSETSTATE@state\fP, \fBre2c:define:YYSETSTATE@state\fP نشانهٔ (sigil) مورد استفاده برای جایگزینی آرگومان را در تعریف \fBYYSETSTATE\fP مشخص می‌کند. مقدار پیش‌فرض \fB@@\fP\& است. پیکربندی عمومی‌تر \fBre2c:api:sigil\fP را بازنویسی می‌کند. .TP .B \fBre2c:YYSETSTATE:naked\fP, \fBre2c:define:YYSETSTATE:naked\fP پیکربندی عمومی‌تر \fBre2c:api:style\fP را برای \fBYYSETSTATE\fP\& بازنویسی می‌کند. مقدار صفر متناظر با سبک آزاد API (free\-form) است. .TP .B \fBre2c:YYSETACCEPT\fP, \fBre2c:define:YYSETACCEPT\fP عنصر پایهٔ API به نام \fBYYSETACCEPT\fP\& را تعریف می‌کند. .TP .B \fBre2c:YYSKIP\fP, \fBre2c:define:YYSKIP\fP عنصر پایهٔ عمومی API به نام \fBYYSKIP\fP\& را تعریف می‌کند. .TP .B \fBre2c:YYSHIFT\fP, \fBre2c:define:YYSHIFT\fP عنصر پایهٔ عمومی API به نام \fBYYSHIFT\fP\& را تعریف می‌کند. .TP .B \fBre2c:YYCOPYMTAG\fP, \fBre2c:define:YYCOPYMTAG\fP عنصر پایهٔ عمومی API به نام \fBYYCOPYMTAG\fP\& را تعریف می‌کند. .TP .B \fBre2c:YYCOPYSTAG\fP, \fBre2c:define:YYCOPYSTAG\fP عنصر پایهٔ عمومی API به نام \fBYYCOPYSTAG\fP\& را تعریف می‌کند..TP .B \fBre2c:YYSHIFTMTAG\fP, \fBre2c:define:YYSHIFTMTAG\fP عنصر اولیهٔ 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 اگر روی مقداری غیرصفر تنظیم شود، نگاشت‌های بیتی برای گزینهٔ \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 اگر روی غیرصفر تنظیم شود، re2rust در هر بار خواندن \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 نباشد (برای نمونه در صورت استفاده از یک نویسهٔ نگهبان). از هشدارها (گزینهٔ \fB\-W\fP) و پیکربندی \fBre2c:sentinel\fP برای اطمینان از این‌که تحلیل‌گر لغوی تولیدشده نمی‌تواند فراتر از انتهای ورودی را بخواند استفاده کنید. مقدار پیش‌فرض غیرصفر است (\fBYYFILL\fP فعال است). .TP .B \fBre2c:yyfill:parameter\fP اگر روی صفر تنظیم شود، از تولید پارامتر ارسالی به \fBYYFILL\fP جلوگیری می‌کند. این پارامتر حداقل تعداد نویسه‌هایی است که باید فراهم شوند. مقدار پیش‌فرض غیرصفر است (پارامتر تولید می‌شود). این پیکربندی را می‌توان با استفاده از \fBre2c:YYFILL:naked\fP یا \fBre2c:api:style\fP بازنویسی کرد. .TP .B \fBre2c:yyfn:sep\fP جداکنندهٔ استفاده‌شده در عناصر \fBYYFN\fP را مشخص می‌کند (پیش‌فرض نقطه‌ویرگول است). .TP .B \fBre2c:yyfn:throw\fP استثناهای پرتاب‌شده توسط تابع \fBYYFN\fP را مشخص می‌کند (پیش‌فرض خالی است، که به معنی عدم وجود استثنا است). .UNINDENT.SS "عبارت‌های منظم (Regular expressions)" .sp ابزار re2rust از نحو زیر برای عبارت‌های منظم استفاده می‌کند: .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؛ پرانتزها برای تغییر اولویت (حق تقدم) استفاده می‌شوند. اگر استخراج تطابق‌های فرعی فعال باشد، \fB(R)\fP بسته به گزینه \fB\-\-invert\-captures\fP یک گروه گیرنده (capturing) یا غیرگیرنده (non\-capturing) خواهد بود. .TP .B \fB(!R)\fP اگر استخراج تطابق‌های فرعی فعال باشد، \fB(!R)\fP بسته به گزینه \fB\-\-invert\-captures\fP یک گروه غیرگیرنده یا گیرنده خواهد بود. .TP .B \fBR S\fP الحاق: \fBR\fP و به دنبال آن \fBS\fP\&. .TP .B \fBR | S\fP انتخاب جایگزین: \fBR یا S\fP\&. .TP .B \fBR / S\fP پیش‌نگری (Lookahead): \fBR\fP و به دنبال آن \fBS\fP، اما \fBS\fP مصرف نمی‌شود. .TP .B \fBname\fP عبارت منظم تعریف‌شده با نام \fBname\fP (یا رشته صریح \fB\(dqname\(dq\fP در حالت سازگاری با Flex). .TP .B \fB{name}\fP عبارت منظم تعریف‌شده با نام \fBname\fP در حالت سازگاری با Flex. .TP .B \fB@stag\fP یک \fIs\-tag\fP: آخرین موقعیت ورودی را که در آن \fB@stag\fP مطابقت یافته است، در متغیری به نام \fBstag\fP ذخیره می‌کند. .TP .B \fB#mtag\fP یک \fIm\-tag\fP: تمام موقعیت‌های ورودی را که در آن‌ها \fB#mtag\fP مطابقت یافته است، در متغیری به نام \fBmtag\fP ذخیره می‌کند. .TP .B \fB$\fP پایان ورودی. .UNINDENT .sp کلاس‌های نویسه و رشته‌های صریح می‌توانند شامل دنباله‌های گریز زیر باشند: \fB\ea\fP، \fB\eb\fP، \fB\ef\fP، \fB\en\fP، \fB\er\fP، \fB\et\fP، \fB\ev\fP، \fB\e\e\fP، گریزهای هشت‌هشتی \fB\eooo\fP و گریزهای شانزده‌شانزدهی \fB\exhh\fP، \fB\euhhhh\fP و \fB\eUhhhhhhhh\fP\&. .SS "کنش‌ها (Actions)" .sp در اینجا فهرستی از کنش‌های از پیش تعریف‌شده که توسط re2rust پشتیبانی می‌شوند آمده است: .INDENT 0.0 .TP .B \fB!entry code\fP کنش ورود، بلوک \fBcode\fP تعریف‌شده توسط کاربر را به وضعیت آغازین ماشین حالت متناهی جاری مقید می‌کند. اگر از \fI\%شرایط شروع\fP (\fIstart conditions\fP) استفاده شود، کنش ورود را می‌توان برای هر شرط به‌صورت جداگانه تنظیم کرد. این کنش می‌تواند برای انجام مقداردهی اولیه استفاده شود، مثلاً برای ذخیره موقعیت شروع یک جزء واژگانی (lexeme). .TP .B \fB!pre_rule code\fP کنش پیش‌قاعده، بلوک \fBcode\fP تعریف‌شده توسط کاربر را به ابتدای کنش‌های معنایی تمام قواعد در بلوک جاری (یا شرط، در صورت استفاده از \fI\%شرایط شروع\fP) اضافه می‌کند. این کنش می‌تواند برای مجزا کردن بخش مشترک تمام کنش‌های معنایی به کار رود (مانند ذخیره موقعیت پایانی یک جزء واژگانی). .TP .B \fB!post_rule code\fP کنش پس‌قاعده، بلوک \fBcode\fP تعریف‌شده توسط کاربر را به انتهای کنش‌های معنایی تمام قواعد در بلوک جاری (یا شرط، در صورت استفاده از \fI\%شرایط شروع\fP) ضمیمه می‌کند. این کنش ممکن است برای تولید دستورات تله (trap statements) جهت جلوگیری از انحراف جریان کنترل ناخواسته به کار رود. .UNINDENT.SS "رهنمودها (Directives)" .sp در اینجا فهرست کاملی از رهنمودهای پشتیبانی‌شده توسط re2rust آمده است: .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\& شناخته می‌شوند با برنامه بیرونی ارتباط برقرار می‌کند. اینکه کدام پایه‌ها باید برای یک برنامه خاص تعریف شوند به عوامل متعددی بستگی دارد، از جمله پیچیدگی عبارات باقاعده، نحوه نمایش ورودی، بافرینگ و استفاده از قابلیت‌های گوناگون. تمام پایه‌های ضروری باید توسط کاربر در قالب ماکروها، توابع، متغیرها یا هر شکل مناسب دیگری تعریف شوند که کد تولیدشده را از نظر نحوی و معنایی درست سازد. re2rust تعاریف را بررسی نمی‌کند (و نمی‌تواند بررسی کند)، بنابراین اگر موردی جا افتاده باشد یا به نادرستی تعریف شده باشد، ممکن است برنامه تولیدشده با خطاهای زمان کامپایل یا زمان اجرا مواجه شود. این راهنما نمونه‌هایی از تعاریف API را در رایج‌ترین موارد ارائه می‌دهد. .sp ابزار re2rust دارای سه شیوه API است که مجموعه اصلی پایه‌های استفاده‌شده توسط یک برنامه را مشخص می‌کنند: .INDENT 0.0 .TP .B \fBSimple API\fP (\fIدر نسخه 4.0 افزوده شد\fP) این یک API پایه‌ای است که می‌تواند با گزینه \fB\-\-api simple\fP یا پیکربندی \fBre2c:api = simple\fP فعال شود. این رابط شامل پایه‌های زیر است: \fBYYINPUT\fP (که باید به‌صورت توالی‌ای از واحدهای کد، مانند یک رشته، تعریف شود) و \fBYYCURSOR\fP، \fBYYMARKER\fP، \fBYYCTXMARKER\fP، \fBYYLIMIT\fP (که باید به‌عنوان شاخص‌هایی در \fBYYINPUT\fP تعریف شوند). .nf .fi .sp .TP .B \fBRecord API\fP (\fIدر نسخه 4.0 افزوده شد\fP) رابط Record API در مواردی مفید است که وضعیت تحلیل‌گر واژگانی (lexer) باید در یک struct ذخیره شود. این رابط با گزینه \fB\-\-api record\fP یا پیکربندی \fBre2c:api = record\fP فعال می‌شود. این API شامل یک متغیر \fByyrecord\fP است (نام آن با \fBre2c:yyrecord\fP قابل بازنویسی است) که باید به‌صورت یک struct با فیلدهای \fByyinput\fP، \fByycursor\fP، \fByymarker\fP، \fByyctxmarker\fP و \fByylimit\fP تعریف شود (تنها فیلدهایی که توسط کد تولیدشده استفاده می‌شوند نیاز به تعریف دارند و نام آن‌ها قابل پیکربندی است). .nf .fi .sp .TP .B \fBGeneric API\fP این انعطاف‌پذیرترین API و رابط پیش‌فرض برای backend زبان Rust است. این API شامل پایه‌هایی برای عملیات‌های عمومی است: \fBYYPEEK\fP، \fBYYSKIP\fP، \fBYYBACKUP\fP، \fBYYBACKUPCTX\fP، \fBYYSTAGP\fP، \fBYYSTAGN\fP، \fBYYMTAGP\fP، \fBYYMTAGN\fP، \fBYYRESTORE\fP، \fBYYRESTORECTX\fP، \fBYYRESTORETAG\fP، \fBYYSHIFT\fP، \fBYYSHIFTSTAG\fP، \fBYYSHIFTMTAG\fP، \fBYYLESSTHAN\fP، \fBYYEND\fP\&. به عنوان مثال، اگر ورودی یک برش بایتی \fBbuffer: &[u8]\fP باشد، متغیرهای \fBcursor\fP، \fBlimit\fP، \fBmarker\fP و \fBctxmarker\fP از نوع \fBusize\fP نشان‌دهنده موقعیت‌های ورودی باشند، و یک ثابت \fBNONE\fP نشان‌دهنده موقعیت نامعتبر باشد، آن‌گاه Generic API را می‌توان به‌صورت زیر تعریف کرد: .INDENT 7.0 .INDENT 3.5 .sp .nf .ft C /*!re2c re2c:YYPEEK = \(dq*buffer.get_unchecked(cursor)\(dq; re2c:YYSKIP = \(dqcursor += 1;\(dq; re2c:YYBACKUP = \(dqmarker = cursor;\(dq; re2c:YYRESTORE = \(dqcursor = marker;\(dq; re2c:YYBACKUPCTX = \(dqctxmarker = cursor;\(dq; re2c:YYRESTORECTX = \(dqcursor = ctxmarker;\(dq; re2c:YYRESTORETAG = \(dqcursor = @@{tag};\(dq; re2c:YYLESSTHAN = \(dqlimit \- cursor < @@{len}\(dq; re2c:YYEND = \(dqlimit == cursor\(dq; re2c:YYSTAGP = \(dq@@{tag} = cursor;\(dq; re2c:YYSTAGN = \(dq@@{tag} = NONE;\(dq; re2c:YYSHIFT = \(dqcursor = (cursor as isize + @@{shift}) as usize;\(dq; re2c:YYSHIFTSTAG = \(dq@@{tag} = (@@{tag} as isize + @@{shift}) as usize;\(dq; */ .ft P .fi .UNINDENT .UNINDENT .UNINDENT .sp در اینجا فهرست کاملی از پایه‌های API آمده است که ممکن است توسط کد تولیدشده برای برقراری ارتباط با برنامه بیرونی استفاده شوند. .INDENT 0.0 .TP .B \fBYYCTYPE\fP نوع نویسه‌های ورودی (واحدهای کد). برای کدگذاری‌های ASCII، EBCDIC و UTF\-8 باید یک عدد صحیح بدون علامت ۱ بایتی باشد. برای UTF\-16 یا UCS\-2 باید یک عدد صحیح بدون علامت ۲ بایتی باشد. برای UTF\-32 باید یک عدد صحیح بدون علامت ۴ بایتی باشد. .TP .B \fBYYCURSOR\fP یک مقدار l\-value که موقعیت فعلی ورودی را ذخیره می‌کند (یک اشاره‌گر یا آفست عددی در \fBYYINPUT\fP). در ابتدا \fBYYCURSOR\fP باید به نخستین نویسه ورودی اشاره کند، و سپس توسط کد تولیدشده به جلو برده می‌شود. هنگامی که یک قاعده مطابقت می‌یابد، موقعیت \fBYYCURSOR\fP پس از آخرین نویسه منطبق‌شده خواهد بود. .TP .B \fBYYLIMIT\fP یک مقدار r\-value که موقعیت انتهای ورودی را ذخیره می‌کند (یک اشاره‌گر یا آفست عددی در \fBYYINPUT\fP). در ابتدا \fBYYLIMIT\fP باید به موقعیت پس از آخرین نویسه در دسترس ورودی اشاره کند. این مقدار توسط کد تولیدشده تغییر داده نمی‌شود. تحلیل‌گر واژگانی \fBYYCURSOR\fP را با \fBYYLIMIT\fP مقایسه می‌کند تا تشخیص دهد آیا به اندازه کافی نویسه ورودی باقی مانده است یا خیر. .TP .B \fBYYMARKER\fP یک مقدار l\-value که موقعیت آخرین قاعده منطبق‌شده را ذخیره می‌کند (یک اشاره‌گر یا آفست عددی در \fBYYINPUT\fP). از این مقدار برای بازگرداندن موقعیت \fBYYCURSOR\fP در صورتی که تطابق طولانی‌تر شکست بخورد و تحلیل‌گر واژگانی نیاز به بازگشت به عقب (rollback) داشته باشد استفاده می‌شود. به مقداردهی اولیه نیازی نیست. .TP .B \fBYYCTXMARKER\fP یک مقدار l\-value که موقعیت بافت پسین (trailing context) را ذخیره می‌کند (یک اشاره‌گر یا آفست عددی در \fBYYINPUT\fP). به هیچ مقداردهی اولیه‌ای نیاز نیست. \fBYYCTXMARKER\fP تنها در صورتی نیاز است که عملگر پیش‌نگری \fB/\fP استفاده شده باشد. .TP .B \fBYYFILL\fP یک پایه Generic 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 یک پایه Generic API با یک متغیر \fBlen\fP\&. این پایه باید به‌عنوان یک مقدار r\-value از نوع بولی تعریف شود که مقدار آن برابر با \fBtrue\fP است اگر و تنها اگر کمتر از \fBlen\fP نویسه ورودی باقی مانده باشد. .TP .B \fBYYEND\fP یک پایه Generic API بدون متغیر. باید به‌عنوان یک مقدار r\-value از نوع بولی تعریف شود که مقدار آن برابر با \fBtrue\fP است اگر و تنها اگر به پایان \fIمنطقی\fP ورودی رسیده باشیم (بدون احتساب هرگونه نویسه لایه‌گذاری یا نماد نگهبان). \fBYYEND\fP برای پیاده‌سازی نماد \fB$\fP در عبارات باقاعده به کار می‌رود. این پایه با \fBYYLESSTHAN\fP متفاوت است که برای اطمینان از اینکه تحلیل‌گر واژگانی فراتر از انتهای بافر را نمی‌خواند استفاده می‌شود..TP .B \fBYYPEEK\fP یک جزء اولیه (primitive) عمومی API بدون متغیر. باید به‌صورت یک r\-value از نوع \fBYYCTYPE\fP تعریف شود که برابر با نویسه در موقعیت فعلی ورودی است. .TP .B \fBYYSKIP\fP یک جزء اولیه (primitive) عمومی API که باید موقعیت فعلی ورودی را یک واحد کد (code unit) به جلو ببرد. .TP .B \fBYYBACKUP\fP یک جزء اولیه (primitive) عمومی API که باید موقعیت فعلی ورودی را ذخیره کند (تا بعداً با \fBYYRESTORE\fP بازیابی شود). .TP .B \fBYYRESTORE\fP یک جزء اولیه (primitive) عمومی API که باید موقعیت فعلی ورودی را به مقدار ذخیره‌شده توسط \fBYYBACKUP\fP\& بازگرداند. .TP .B \fBYYBACKUPCTX\fP یک جزء اولیه (primitive) عمومی API که باید موقعیت فعلی ورودی را به‌عنوان موقعیت بافت پسین (trailing context) ذخیره کند (تا بعداً با \fBYYRESTORECTX\fP بازیابی شود). .TP .B \fBYYRESTORECTX\fP یک جزء اولیه (primitive) عمومی API که باید موقعیت بافت پسین ذخیره‌شده با \fBYYBACKUPCTX\fP\& را بازیابی کند. .TP .B \fBYYRESTORETAG\fP یک جزء اولیه (primitive) عمومی API با یک متغیر \fBtag\fP که باید موقعیت بافت پسین را به مقدار \fBtag\fP\& بازگرداند. .TP .B \fBYYSTAGP\fP یک جزء اولیه (primitive) عمومی API با یک متغیر \fBtag\fP، که در آن \fBtag\fP می‌تواند یک اشاره‌گر یا آفست در \fBYYINPUT\fP باشد (برای جزئیات به بخش استخراج تطابق‌های فرعی مراجعه کنید). \fBYYSTAGP\fP باید \fBtag\fP را روی موقعیت فعلی ورودی تنظیم کند. .TP .B \fBYYSTAGN\fP یک جزء اولیه (primitive) عمومی API با یک متغیر \fBtag\fP، که در آن \fBtag\fP می‌تواند یک اشاره‌گر یا آفست در \fBYYINPUT\fP باشد (برای جزئیات به بخش استخراج تطابق‌های فرعی مراجعه کنید). \fBYYSTAGN\fP باید \fBtag\fP را روی مقداری تنظیم کند که نشان‌دهندهٔ موقعیت ورودی ناموجود است. .TP .B \fBYYMTAGP\fP یک جزء اولیه (primitive) عمومی API با یک متغیر \fBtag\fP\&. \fBYYMTAGP\fP باید موقعیت فعلی را به تاریخچهٔ تطابق‌های فرعی \fBtag\fP اضافه کند (برای جزئیات به بخش استخراج تطابق‌های فرعی مراجعه کنید). .TP .B \fBYYMTAGN\fP یک جزء اولیه (primitive) عمومی API با یک متغیر \fBtag\fP\&. \fBYYMTAGN\fP باید مقداری را که نشان‌دهندهٔ موقعیت ورودی ناموجود است به تاریخچهٔ تطابق‌های فرعی \fBtag\fP اضافه کند (برای جزئیات به بخش استخراج تطابق‌های فرعی مراجعه کنید). .TP .B \fBYYSHIFT\fP یک جزء اولیه (primitive) عمومی API با یک متغیر \fBshift\fP که باید موقعیت فعلی ورودی را به اندازهٔ \fBshift\fP نویسه انتقال دهد (مقدار انتقال ممکن است منفی باشد). .TP .B \fBYYCOPYSTAG\fP یک جزء اولیه (primitive) عمومی API با دو متغیر \fBlhs\fP و \fBrhs\fP که باید متغیر s\-tag سمت راست (\fBrhs\fP) را در متغیر s\-tag سمت چپ (\fBlhs\fP) کپی کند. برای بیشتر زبان‌ها این جزء اولیه دارای یک تعریف پیش‌فرض است که \fBlhs\fP را به \fBrhs\fP انتساب می‌دهد. .TP .B \fBYYCOPYMTAG\fP یک جزء اولیه (primitive) عمومی API با دو متغیر \fBlhs\fP و \fBrhs\fP که باید متغیر m\-tag سمت راست (\fBrhs\fP) را در متغیر m\-tag سمت چپ (\fBlhs\fP) کپی کند. برای بیشتر زبان‌ها این جزء اولیه دارای یک تعریف پیش‌فرض است که \fBlhs\fP را به \fBrhs\fP انتساب می‌دهد. .TP .B \fBYYSHIFTSTAG\fP یک جزء اولیه (primitive) عمومی API با دو متغیر \fBtag\fP و \fBshift\fP که باید \fBtag\fP را به اندازهٔ \fBshift\fP واحد کد (code unit) انتقال دهد (مقدار انتقال ممکن است منفی باشد). .TP .B \fBYYSHIFTMTAG\fP یک جزء اولیه (primitive) عمومی API با دو متغیر \fBtag\fP و \fBshift\fP که باید آخرین مقدار در تاریخچهٔ \fBtag\fP را به اندازهٔ \fBshift\fP واحد کد انتقال دهد (مقدار انتقال ممکن است منفی باشد). .TP .B \fBYYMAXNMATCH\fP یک ثابت عدد صحیح برابر با حداکثر تعداد گروه‌های تطابق POSIX در یک قاعده. این مقدار با یک بلوک \fBmaxnmatch\fP تولید می‌شود. .TP .B \fBYYCONDTYPE\fP نوع شمارش شرط (condition enum). می‌توان آن را با بلوک \fBconditions\fP یا گزینهٔ \fB\-\-header\fP تولید کرد. .TP .B \fBYYGETACCEPT\fP یک جزء اولیه (primitive) با یک متغیر \fBvar\fP که انتخاب‌کنندهٔ عددی قاعدهٔ پذیرفته‌شده را ذخیره می‌کند. برای بیشتر زبان‌ها این جزء اولیه دارای یک تعریف پیش‌فرض است که از \fBvar\fP\& می‌خواند. .TP .B \fBYYSETACCEPT\fP یک جزء اولیه (primitive) با دو متغیر: \fBvar\fP (یک l\-value که انتخاب‌کنندهٔ عددی قاعدهٔ پذیرفته‌شده را ذخیره می‌کند) و \fBval\fP (مقدار انتخاب‌کننده). برای بیشتر زبان‌ها این جزء اولیه دارای تعریفی پیش‌فرض است که \fBvar\fP را به \fBval\fP\& انتساب می‌دهد. .TP .B \fBYYGETCOND\fP یک r\-value از نوع \fBYYCONDTYPE\fP که برابر با شناسهٔ شرط فعلی است. .TP .B \fBYYSETCOND\fP یک جزء اولیه (primitive) با یک متغیر \fBcond\fP که باید شناسهٔ شرط فعلی را روی \fBcond\fP\& تنظیم کند. .TP .B \fBYYGETSTATE\fP یک r\-value از نوع عدد صحیح که برابر با وضعیت فعلی تحلیل‌گر لغوی است. مقدار اولیهٔ آن باید \fB\-1\fP\& باشد. .TP .B \fBYYSETSTATE\fP یک جزء اولیه (primitive) با یک متغیر \fBstate\fP که باید وضعیت فعلی تحلیل‌گر لغوی را روی \fBstate\fP\& تنظیم کند. .TP .B \fBYYDEBUG\fP این جزء اولیه فقط با گزینهٔ \fB\-d\fP، \fB\-\-debug\-output\fP تولید می‌شود. هدف آن افزودن ثبت وقایع (logging) به کد تولید‌شده است (تعریف متداول \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 جدول پرش تولید‌شده برای ارسال (dispatch) شرط اولیه (با ترکیب گزینه‌های \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 بهینه‌سازی پرش‌های شرطی با استفاده از ماسک‌های بیتی. این گزینه مستلزم \fB\-\-nested\-ifs\fP است. .TP .B \fB\-\-captures\fP, \fB\-\-leftmost\-captures\fP فعال‌سازی استخراج زیرتطبیق (submatch) با گروه‌های گیرانداز حریصانهٔ چپ‌ترین. نتیجه در یک آرایهٔ \fByybmatch\fP با ظرفیت \fB2 * YYMAXNMATCH\fP جمع‌آوری می‌شود، و \fByynmatch\fP به تعداد گروه‌ها برای قاعدهٔ تطبیق‌یافته تنظیم می‌گردد. .TP .B \fB\-\-captvars\fP, \fB\-\-leftmost\-captvars\fP فعال‌سازی استخراج زیرتطبیق با گروه‌های گیرانداز حریصانهٔ چپ‌ترین. نتیجه برای \fBk\fP\-امین گروه گیرانداز در متغیرهای \fByytl\fP و \fByytr\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 منجر به اندازهٔ باینری کوچک‌تر نیز می‌شود. .TP .B \fB\-\-computed\-gotos \-g\fP بهینه‌سازی پرش‌های شرطی با استفاده از افزونهٔ غیراستاندارد \(dqcomputed goto\(dq (که باید توسط کامپایلر پشتیبانی شود). re2rust جدول‌های پرش را تنها در موارد پیچیده با شاخه‌های شرطی فراوان تولید می‌کند. آستانهٔ پیچیدگی می‌تواند با پیکربندی \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 فعال‌سازی پشتیبانی از \(dqشرط‌ها\(dq مشابه Flex: چندین تحلیل‌گر لغوی مرتبط درون یک بلوک. این گزینه جایگزینی برای مشخص کردن دستی بلوک‌های مختلف re2rust است که با \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 می‌خواند. re2rust فرض می‌کند که بازهٔ نویسه‌ها 0 \-\- 0xFF و اندازهٔ هر نویسه ۱ بایت است. .TP .B \fB\-\-empty\-class \fP تعریف نحوهٔ برخورد re2rust با کلاس‌های نویسهٔ خالی. با \fBmatch\-empty\fP (پیش‌فرض)، کلاس خالی با ورودی خالی تطبیق می‌یابد (که غیرمنطقی است، اما با نسخه‌های پیشین سازگار است). با \fBmatch\-none\fP کلاس خالی همیشه در تطبیق ناموفق است. با \fBerror\fP، کلاس خالی یک خطای کامپایل ایجاد می‌کند. .TP .B \fB\-\-encoding\-policy \fP تعریف نحوهٔ برخورد re2rust با جانشین‌های یونیکد (surrogates). با \fBfail\fP هنگام مواجهه با جانشین، re2rust با خطا متوقف می‌شود. با \fBsubstitute\fP، re2rust به‌طور بی‌صدا جانشین‌ها را با نقطهٔ کد خطای 0xFFFD جایگزین می‌کند. با \fBignore\fP (پیش‌فرض)، re2rust با جانشین‌ها مانند نقاط کد عادی رفتار می‌کند. استاندارد یونیکد بیان می‌کند که جانشین‌های مستقل نامعتبر هستند، اما کتابخانه‌ها و برنامه‌های دنیای واقعی رفتارهای متفاوتی دارند. .TP .B \fB\-\-flex\-syntax \-F\fP پشتیبانی جزئی از نحو Flex: در این حالت تعاریف نام‌دار نیازی به علامت مساوی و سمی‌کالن پایانی ندارند، و در هنگام استفاده باید با آکوالاد محصور شوند. با نام‌های بدون آکوالاد مانند رشته‌های محصور در نقل‌قول دوتایی برخورد می‌شود. .TP .B \fB\-\-goto\-label\fP استفاده از مدل کد \(dqgoto/label\(dq: کدگذاری DFA در قالب بلوک‌های کد برچسب‌دار متصل‌شده با انتقال‌های \fBgoto\fP بین بلوک‌ها. این ویژگی تنها برای زبان‌هایی که دارای دستور \fBgoto\fP هستند پشتیبانی می‌شود. .TP .B \fB\-\-header \-\-type\-header \-t HEADER\fP تولید یک فایل \fBHEADER\fP. محتوای فایل را می‌توان با استفاده از بلوک‌های ویژهٔ \fBheader:on\fP و \fBheader:off\fP مشخص کرد. در صورت استفاده از شرط‌ها، یک شمارش (enum) شرط به‌طور خودکار به هدر تولیدشده افزوده می‌شود (مگر اینکه یک بلوک صریح \fBconditions\fP وجود داشته باشد). .TP .B \fB\-I PATH\fP افزودن \fBPATH\fP به فهرست مکان‌هایی که هنگام جستجوی فایل‌های include استفاده می‌شوند. این گزینه در ترکیب با بلوک یا دستورالعمل \fBinclude\fP کاربردی است. re2rust به دنبال \fBFILE\fP در دایرکتوری فایل والد و در مکان‌های include مشخص‌شده با گزینهٔ \fB\-I\fP می‌گردد. .TP .B \fB\-\-input \fP نام مستعار منسوخ‌شده برای \fB\-\-api\fP\&. گزینهٔ \fBdefault\fP معادل \fBsimple\fP است (در واقع برای بیشتر بک‌اندها پیش‌فرض است، اما نه برای همه). گزینهٔ \fBcustom\fP معادل \fBgeneric\fP است. .TP .B \fB\-\-input\-encoding \fP مشخص کردن روش تجزیهٔ عبارت‌های باقاعده توسط re2rust. با \fBascii\fP (پیش‌فرض) re2rust با ورودی مانند کدگذاری ASCII رفتار می‌کند: هر دنباله‌ای از واحدهای کد، دنباله‌ای از نویسه‌های تک‌بایتی مستقل است. با \fButf8\fP، re2rust با ورودی مانند کدگذاری UTF8 رفتار کرده و نویسه‌های چندبایتی را تشخیص می‌دهد. .TP .B \fB\-\-invert\-captures\fP معکوس کردن معنای گروه‌های گیرانداز و غیرگیرانداز. به‌طور پیش‌فرض \fB(...)\fP گیرانداز و \fB(! ...)\fP غیرگیرانداز است. با این گزینه، \fB(! ...)\fP گیرانداز و \fB(...)\fP غیرگیرانداز خواهد بود. .TP .B \fB\-\-lang \fP مشخص کردن زبان مقصد. زبان‌های پشتیبانی‌شده عبارتند از C، D، Go، Haskell، Java، JS، OCaml، Python، Rust، Swift، V، Zig (زبان‌های بیشتری می‌توانند از طریق فایل‌های نحو تعریف‌شده توسط کاربر افزوده شوند؛ گزینهٔ \fB\-\-syntax\fP را ببینید). گزینهٔ \fBnone\fP پیکربندی‌های پیش‌فرض نحو را غیرفعال می‌کند، به‌گونه‌ای که زبان مقصد تعریف‌نشده باقی می‌ماند. .TP .B \fB\-\-location\-format \fP مشخص کردن قالب مکان در پیام‌ها. با \fBgnu\fP مکان‌ها به‌صورت \(aqfilename:line:column: ...\(aq چاپ می‌شوند. با \fBmsvc\fP مکان‌ها به‌صورت \(aqfilename(line,column) ...\(aq چاپ می‌شوند. پیش‌فرض \fBgnu\fP است. .TP .B \fB\-\-loop\-switch\fP استفاده از مدل کد \(dqloop/switch\(dq: کدگذاری DFA در قالب یک حلقه بر روی یک دستور switch، که در آن هر وضعیت مجزا یک 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 دستورالعمل‌های خط در خروجی درج نشوند. این گزینه ممکن است هنگامی که کد تولیدشده در یک سامانهٔ کنترل نسخه ذخیره می‌شود مفید باشد (برای جلوگیری از تفاوت‌های بزرگ تولیدشده بر اثر تغییرات جزئی). .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 باید از بررسی مرزها اجتناب کند، زیرا تحلیل‌گر لغوی پیشاپیش بررسی‌های پایان ورودی را به روش کارآمدتری انجام داده است. کاربر می‌تواند یک تعریف امن برای \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 استفاده از مدل کدی مبتنی بر توابع هم‌بازگشتی، که در آن هر وضعیت DFA یک تابع جداگانه است که می‌تواند توابع وضعیت‌های دیگر یا خودش را فراخوانی کند. .TP .B \fB\-\-reusable \-r\fP از نسخهٔ 2.2 منسوخ شده است (بلوک‌های با قابلیت استفادهٔ مجدد اکنون به‌طور پیش‌فرض مجاز هستند). .TP .B \fB\-\-skeleton \-S\fP نادیده‌گرفتن کد رابط تعریف‌شده توسط کاربر و تولید یک برنامهٔ \(dqاسکلت\(dq خودکفا. علاوه بر این، تولید فایل‌های ورودی با رشته‌های به‌دست‌آمده از دستور زبان باقاعده و نتایج تطبیق فشرده‌شده که برای تأیید رفتار \(dqاسکلت\(dq روی تمام ورودی‌ها به کار می‌روند. این گزینه برای یافتن باگ‌ها در بهینه‌سازی‌ها و تولید کد مفید است. این گزینه فقط برای C پشتیبانی می‌شود. .TP .B \fB\-\-storable\-state \-f\fP تولید یک تحلیل‌گر لغوی که می‌تواند وضعیت درونی خود را ذخیره کند. این مورد در تحلیل‌گرهای لغوی مدل push مفید است که وقتی ورودی کافی وجود ندارد توسط یک برنامهٔ بیرونی متوقف شده و سپس هنگام دردسترس قرار گرفتن ورودی بیشتر، از سر گرفته می‌شوند. در این حالت، کاربران باید علاوه بر این، توابع اولیهٔ \fBYYGETSTATE\fP و \fBYYSETSTATE\fP را تعریف کنند و متغیرهای \fByych\fP، \fByyaccept\fP و \fBstate\fP باید بخشی از وضعیت ذخیره‌شدهٔ تحلیل‌گر لغوی باشند. .TP .B \fB\-\-syntax FILE\fP بارگذاری پیکربندی‌ها از \fBFILE\fP مشخص‌شده و اعمال آن‌ها بر روی فایل نحو (syntax) پیش‌فرض. توجه داشته باشید که \fBFILE\fP می‌تواند تنها چند پیکربندی را تعریف کند (اگر برای اصلاح فایل نحو پیش‌فرض استفاده شود)، یا می‌تواند یک بک‌اند زبان کاملاً جدید را تعریف کند (در حالت دوم توصیه می‌شود از گزینهٔ \fB\-\-lang none\fP استفاده کنید). .TP .B \fB\-\-tags \-T\fP فعال‌سازی استخراج زیرتطبیق با برچسب‌ها (tags). .TP .B \fB\-\-ucs2 \-\-wide\-chars \-w\fP تولید تحلیل‌گر لغوی که ورودی با کدگذاری UCS2 را می‌خواند. re2rust فرض می‌کند که محدودهٔ نویسه‌ها 0 \-\- 0xFFFF و اندازهٔ هر نویسه ۲ بایت است. این گزینه مستلزم \fB\-\-nested\-ifs\fP است\&. .TP .B \fB\-\-utf8 \-\-utf\-8 \-8\fP تولید تحلیل‌گر لغوی که ورودی را با کدگذاری UTF\-8 می‌خواند. re2rust فرض می‌کند که محدودهٔ نویسه‌ها 0 \-\- 0x10FFFF و اندازهٔ هر نویسه ۱ بایت است. .TP .B \fB\-\-utf16 \-\-utf\-16 \-x\fP تولید تحلیل‌گر لغوی که ورودی با کدگذاری UTF16 را می‌خواند. re2rust فرض می‌کند که محدودهٔ نویسه‌ها 0 \-\- 0x10FFFF و اندازهٔ هر نویسه ۲ بایت است. این گزینه مستلزم \fB\-\-nested\-ifs\fP است\&. .TP .B \fB\-\-utf32 \-\-unicode \-u\fP تولید تحلیل‌گر لغوی که ورودی با کدگذاری UTF32 را می‌خواند. re2rust فرض می‌کند که محدودهٔ نویسه‌ها 0 \-\- 0x10FFFF و اندازهٔ هر نویسه ۴ بایت است. این گزینه مستلزم \fB\-\-nested\-ifs\fP است\&. .TP .B \fB\-\-verbose\fP چاپ یک پیام کوتاه در صورت موفقیت. .TP .B \fB\-\-vernum \-V\fP نمایش اطلاعات نسخه در قالب \fBMMmmpp\fP (اصلی، فرعی، وصله). .TP .B \fB\-\-version \-v\fP نمایش اطلاعات نسخه. .TP .B \fB\-\-single\-pass \-1\fP منسوخ شده است. کاری انجام نمی‌دهد (تک‌گذره اکنون پیش‌فرض است). .UNINDENT .INDENT 0.0 .TP .B \fB\-\-debug\-output \-d\fP درج فراخوانی‌های \fBYYDEBUG\fP در کد تولیدشده. این گزینه برای ردگیری اجرای تحلیل‌گر لغوی مفید است. .TP .B \fB\-\-dump\-adfa\fP گزینهٔ اشکال‌زدایی: خروجی دادن DFA پس از تونل‌زنی (در قالب ‎.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 به جای خروجی عادی، گراف تحلیل‌گر لغوی را در قالب ‎.dot تولید می‌کند. خروجی می‌تواند با کمک Graphviz به یک تصویر تبدیل شود (مثلاً چیزی مانند \fBdot \-Tpng \-odfa.png dfa.dot\fP). .UNINDENT .INDENT 0.0 .TP .B \fB\-\-dfa\-minimization \fP گزینهٔ داخلی: الگوریتم کمینه‌سازی DFA که توسط re2rust استفاده می‌شود\&. گزینهٔ \fBmoore\fP الگوریتم مور (پیش‌فرض) است. گزینهٔ \fBtable\fP الگوریتم \(dqپر کردن جدول\(dq است. هر دو الگوریتم باید به جز برچسب‌گذاری مجدد وضعیت‌ها، DFA یکسانی تولید کنند؛ روش پر کردن جدول ساده‌تر و بسیار کندتر بوده و به عنوان یک پیاده‌سازی مرجع عمل می‌کند. .TP .B \fB\-\-eager\-skip\fP گزینهٔ داخلی: وادار کردن تحلیل‌گر لغوی تولیدشده به پیش بردن موقعیت ورودی به صورت مشتاقانه \-\- بلافاصله پس از خواندن نماد ورودی. این گزینه رفتار پیش‌فرض را که در آن موقعیت ورودی به صورت تنبلانه \-\- پس از گذار به وضعیت بعدی \-\- به جلو برده می‌شود، تغییر می‌دهد. .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 گزینهٔ داخلی: تعیین الگوریتم کوتاه‌ترین مسیر مورد استفاده برای ساخت بستار اپسیلون با معناشناسی رفع ابهام 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 گزینهٔ داخلی: تعیین اینکه آیا بهینه‌سازی برچسب ثابت باید روی همهٔ برچسب‌ها اعمال شود (\fBall\fP)، روی هیچ‌کدام (\fBnone\fP)، یا فقط روی آن‌هایی که در الحاق سطح بالا قرار دارند (\fBtoplevel\fP). پیش‌فرض \fBall\fP است\&. برچسب‌های \(dqثابت\(dq آن‌هایی هستند که در فاصلهٔ ثابتی از یک برچسب دیگر (به نام \(dqپایه\(dq) قرار دارند. در چنین مواردی فقط برچسب پایه نیاز به ردگیری دارد و مقدار برچسب ثابت می‌تواند برابر با مقدار برچسب پایه به‌علاوهٔ یک فاصلهٔ ایستا محاسبه شود. برای برچسب‌هایی که در گزینش یا تکرار قرار دارند، همچنین لازم است بررسی شود که آیا برچسب پایه دارای مقدار عدم تطابق است یا خیر (در این صورت برچسب ثابت نیز بدون در نظر گرفتن فاصله، باید برابر با عدم تطابق تنظیم شود). برای برچسب‌های موجود در الحاق سطح بالا نیازی به این بررسی نیست، زیرا آن‌ها همیشه مطابقت دارند. .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 هشدار در صورتی که یک عبارت باقاعده شامل یک ردهٔ نویسه‌ای خالی باشد. تلاش برای تطبیق یک ردهٔ نویسه‌ای خالی هیچ مفهومی ندارد: همیشه باید ناموفق باشد. با این حال، به دلایل سازگاری با گذشته، re2rust رده‌های نویسه‌ای خالی را مجاز دانسته و با آن‌ها مانند رشته‌های خالی رفتار می‌کند. برای تغییر رفتار پیش‌فرض از گزینهٔ \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 هشدار در صورتی که یک نماد حاوی گریز باشد در حالی که نباید باشد. به‌طور پیش‌فرض، re2rust چنین گریزهایی را نادیده می‌گیرد، اما این مورد می‌تواند بیانگر یک اشتباه تایپی یا خطا در دنبالهٔ گریز باشد. .TP .B \fB\-Wnondeterministic\-tags\fP هشدار در صورتی که یک برچسب دارای درجهٔ \fBn\fP\-ام از عدم قطعیت باشد، به‌طوری که \fBn\fP بزرگ‌تر از ۱ است. .TP .B \fB\-Wsentinel\-in\-midrule\fP هشدار در صورتی که نماد نگهبان در وسط یک قاعده رخ دهد \-\-\- این اتفاق ممکن است باعث خواندن فراتر از انتهای بافر، خرابی برنامه یا آسیب به حافظه در تحلیل‌گر لغوی تولیدشده شود. این هشدار تنها در صورتی قابل اعمال است که از روش نگهبان برای بررسی پایان ورودی استفاده شود. اگر از پیکربندی \fBre2c:sentinel\fP استفاده شود، به یک خطا تبدیل می‌گردد. .TP .B \fB\-Wundefined\-syntax\-config\fP هشدار در صورتی که فایل نحو مشخص‌شده با گزینهٔ \fB\-\-syntax\fP فاقد تعاریف برخی از پیکربندی‌ها باشد. این به نگهداری فایل‌های نحوِ تعریف‌شده توسط کاربر کمک می‌کند: اگر در نسخهٔ جدیدی پیکربندی‌هایی اضافه شود، فایل نحو قدیمی هشدار خواهد داد و به کاربر اطلاع داده می‌شود. اگر برخی پیکربندی‌ها بلااستفاده هستند و نیازی به تعریف ندارند، باید به‌صراحت روی \fB\fP تنظیم شوند. .UNINDENT.SS فایل‌های نحو (Syntax files) .sp پشتیبانی از زبان‌های گوناگون در re2c بر پایه ایده \fIفایل‌های نحو\fP (\fIsyntax files\fP)\& بنا شده است. یک فایل نحو، یک فایل پیکربندی است که نحو زبان مقصد را تعریف می‌کند \-\- نه کل زبان، بلکه بخش کوچکی از آن را که توسط کد تولیدشده استفاده می‌شود. فایل‌های نحو انعطاف‌پذیری بالایی به re2c می‌بخشند، اما نباید به عنوان جایگزینی برای پیکربندی‌های \fBre2c:\fP استفاده شوند: هدف آن‌ها تعریف نحو زبان مقصد است، نه شخصی‌سازی یک تحلیل‌گر لغوی (lexer) خاص. تمام زبان‌های پشتیبانی‌شده دارای فایل‌های نحو پیش‌فرضی هستند که بخشی از توزیع به شمار می‌روند (زیردایرکتوری \fBinclude/syntax\fP را ببینید)؛ آن‌ها همچنین در باینری re2rust گنجانده شده‌اند. کاربران می‌توانند یک فایل نحو سفارشی ارائه دهند که چند پیکربندی را برای یکی از زبان‌های پشتیبانی‌شده بازنویسی می‌کند، یا می‌توانند همه پیکربندی‌ها را مجدداً تعریف کنند (در این حالت باید از گزینه \fB\-\-lang none\fP استفاده شود). فایل‌های نحو شامل پیکربندی‌هایی در چهار دسته مختلف هستند: فهرست ویژگی‌ها، پیکربندی‌های زبان، پیکربندی‌های درجا و الگوهای کد. .sp \fBفهرست‌های ویژگی (Feature lists)\fP .INDENT 0.0 .INDENT 3.5 چند پیکربندی فهرستی، ویژگی‌های گوناگون پشتیبانی‌شده توسط یک بک‌اند معین را تعریف می‌کنند، تا در صورتی که کاربر تلاش کند ویژگی پشتیبانی‌نشده‌ای را فعال کند، re2rust بتواند خطای واضحی بدهد: .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 فهرستی از مقاصد تولید کد (codegen) پشتیبانی‌شده با عناصر ممکن \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 چند پیکربندی بولی ویژگی‌هایی از زبان مقصد را توصیف می‌کنند که بر تجزیه‌کننده و تولیدکننده کد re2rust تأثیر می‌گذارند: .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 یک الگوی کد دنباله‌ای از رشته‌های لفظی (string literals)، متغیرها، عناصر اختیاری و فهرست‌ها، یا ارجاعی به یک الگوی کد دیگر، یا مقدار ویژه \fB\fP\& است. متغیرها جایگزین‌هایی (placeholders) هستند که در فاز تولید کد جایگزین می‌شوند. متغیرهای فهرستی خاص هستند: هنگام بسط الگوهای فهرستی، re2rust عبارت‌های سمت راست دو‌نقطه را چند بار تکرار می‌کند، و هر بار رخدادهای متغیر فهرست را با مقداری مخصوص به این تکرار جایگزین می‌نماید. فهرست‌ها دارای کران‌های اختیاری هستند (مقادیر منفی از انتها شمرده می‌شوند، برای نمونه \fB\-1\fP به معنای آخرین عنصر است). نام‌های شرطی با یک نقطه شروع می‌شوند. هم شرط‌ها و هم متغیرها می‌توانند محلی (مخصوص الگوی کد داده‌شده) یا سراسری (مجاز در تمام الگوهای کد) باشند. هنگامی که re2rust فایل نحو را می‌خواند، بررسی می‌کند که هر الگوی کد فقط از متغیرها و شرط‌هایی استفاده کند که در آن مجاز هستند. .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 در اینجا فهرستی از تمام الگوهای کد پشتیبانی‌شده توسط re2rust به همراه متغیرها و شرط‌های محلی آن‌ها آورده شده است. توجه داشته باشید که یک تعریف خاص می‌تواند، اما لزومی ندارد که از متغیرها و شرط‌های محلی استفاده کند. هر الگوی کد استفاده‌نشده باید بر روی \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 تعریف یک شمارش (ممکن است با ساختار زبانیِ ویژه‌ای برای شمارش‌ها تعریف شود، یا صرفاً به صورت چند مقدار ثابت مستقل). متغیرهای پشتیبانی‌شده عبارتند از \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 نوع عدد صحیح علامت‌دار. .TP .B \fBcode:type_uint\fP نوع عدد صحیح بدون علامت. .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. .TP .B \fBcode:cmp_ne\fP عملگر \(dqنابرابر با\(dq. .TP .B \fBcode:cmp_lt\fP عملگر \(dqکوچک‌تر از\(dq. .TP .B \fBcode:cmp_gt\fP عملگر \(dqبزرگ‌تر از\(dq. .TP .B \fBcode:cmp_le\fP عملگر \(dqکوچک‌تر یا مساوی\(dq. .TP .B \fBcode:cmp_ge\fP عملگر \(dqبزرگ‌تر یا مساوی\(dq. .TP .B \fBcode:if_then_else\fP دستور if\-then\-else با یک یا چند شاخه. متغیرهای پشتیبانی‌شده: \fBbranch\fP (یک متغیر فهرستی که خود کدی تولید نمی‌کند، اما عبارت فهرست را به تعداد شاخه‌ها بسط می‌دهد)، \fBcond\fP (شرط شاخه فعلی) و \fBstmt\fP (یک متغیر فهرستی که به تمام دستورات موجود در شاخه فعلی گسترش می‌یابد). شرایط: \fB\&.cond\fP (درست در صورتی که شاخه فعلی دارای شرط باشد)، \fB\&.many\fP (درست در صورتی که بیش از یک شاخه وجود داشته باشد). .TP .B \fBcode:if_then_else_oneline\fP شکل خاصی از \fBcode:if_then_else\fP برای حالتی که تمام شاخه‌ها دارای دستورات تک‌خطی هستند. اگر این مقدار \fB\fP باشد، به جای آن از \fBcode:if_then_else\fP استفاده می‌شود. .TP .B \fBcode:switch\fP یک دستور switch با یک یا چند حالت (case). متغیرهای پشتیبانی‌شده: \fBexpr\fP (عبارتِ مورد ارزیابی در switch) و \fBcase\fP (یک متغیر فهرستی که به تمام گروه‌های case به همراه بلوک‌های کدشان گسترش می‌یابد). .TP .B \fBcode:switch_cases\fP گروهی از موارد (cases) در دستور 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). متغیرهای پشتیبانی‌شده: \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 (درست در صورتی که این تابع از نوع non\-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 (درست در صورتی که این تابع non\-void باشد). .TP .B \fBcode:recursive_functions\fP بدنه برنامه همراه با مدل کد \fB\-\-recursive\-functions\fP. متغیرهای پشتیبانی‌شده: \fBfn\fP (یک متغیر فهرستی که خود کدی تولید نمی‌کند، اما عبارت فهرست را به تعداد توابع بسط می‌دهد)، \fBfndecl\fP (اعلان تابع فعلی) و \fBfndef\fP (تعریف تابع فعلی)..TP .B \fBcode:fingerprint\fP اثرانگشت در بالای فایل خروجی تولیدشده. متغیرهای پشتیبانی‌شده: \fBver\fP (نسخهٔ re2rust که برای تولید استفاده شده است) و \fBdate\fP (تاریخ تولید). .TP .B \fBcode:line_info\fP قالب دستورالعمل‌های خط (اگر روی \fB\fP تنظیم شود، هیچ دستورالعملی تولید نمی‌شود). متغیرهای پشتیبانی‌شده: \fBline\fP (شمارهٔ خط) و \fBfile\fP (نام فایل). .TP .B \fBcode:abort\fP دستوری که اجرای برنامه را متوقف (abort) می‌کند. .TP .B \fBcode:yydebug\fP دستور \fBYYDEBUG\fP، احتمالاً سفارشی‌شده برای APIهای مختلف. متغیرهای پشتیبانی‌شده: \fBYYDEBUG\fP، \fByyrecord\fP، \fByych\fP (نگاشت به پیکربندی‌های متناظر \fBre2c:\fP)، \fBstate\fP (شمارهٔ حالت DFA). .TP .B \fBcode:yypeek\fP دستور \fBYYPEEK\fP، احتمالاً سفارشی‌شده برای APIهای مختلف. متغیرهای پشتیبانی‌شده: \fBYYPEEK\fP، \fBYYCTYPE\fP، \fBYYINPUT\fP، \fBYYCURSOR\fP، \fByyrecord\fP، \fByych\fP (نگاشت به پیکربندی‌های متناظر \fBre2c:\fP). شرط‌ها: \fB\&.cast\fP (درست در صورتی که \fBre2c:yych:conversion\fP روی غیرصفر تنظیم شده باشد). .TP .B \fBcode:yyskip\fP دستور \fBYYSKIP\fP، احتمالاً سفارشی‌شده برای APIهای مختلف. متغیرهای پشتیبانی‌شده: \fBYYSKIP\fP، \fBYYCURSOR\fP، \fByyrecord\fP (نگاشت به پیکربندی‌های متناظر \fBre2c:\fP). .TP .B \fBcode:yybackup\fP دستور \fBYYBACKUP\fP، احتمالاً سفارشی‌شده برای APIهای مختلف. متغیرهای پشتیبانی‌شده: \fBYYBACKUP\fP، \fBYYCURSOR\fP، \fBYYMARKER\fP، \fByyrecord\fP (نگاشت به پیکربندی‌های متناظر \fBre2c:\fP). .TP .B \fBcode:yybackupctx\fP دستور \fBYYBACKUPCTX\fP، احتمالاً سفارشی‌شده برای APIهای مختلف. متغیرهای پشتیبانی‌شده: \fBYYBACKUPCTX\fP، \fBYYCURSOR\fP، \fBYYCTXMARKER\fP، \fByyrecord\fP (نگاشت به پیکربندی‌های متناظر \fBre2c:\fP). .TP .B \fBcode:yyskip_yypeek\fP دستور ترکیبی \fBcode:yyskip\fP و \fBcode:yypeek\fP (پیش‌فرض \fBcode:yyskip\fP و به دنبال آن \fBcode:yypeek\fP است). .TP .B \fBcode:yypeek_yyskip\fP دستور ترکیبی \fBcode:yypeek\fP و \fBcode:yyskip\fP (پیش‌فرض \fBcode:yypeek\fP و به دنبال آن \fBcode:yyskip\fP است). .TP .B \fBcode:yyskip_yybackup\fP دستور ترکیبی \fBcode:yyskip\fP و \fBcode:yybackup\fP (پیش‌فرض \fBcode:yyskip\fP و به دنبال آن \fBcode:yybackup\fP است). .TP .B \fBcode:yybackup_yyskip\fP دستور ترکیبی \fBcode:yybackup\fP و \fBcode:yyskip\fP (پیش‌فرض \fBcode:yybackup\fP و به دنبال آن \fBcode:yyskip\fP است). .TP .B \fBcode:yybackup_yypeek\fP دستور ترکیبی \fBcode:yybackup\fP و \fBcode:yypeek\fP (پیش‌فرض \fBcode:yybackup\fP و به دنبال آن \fBcode:yypeek\fP است). .TP .B \fBcode:yyskip_yybackup_yypeek\fP دستور ترکیبی \fBcode:yyskip\fP، \fBcode:yybackup\fP و \fBcode:yypeek\fP (پیش‌فرض \(ga\(gacode:yyskip\(ga\(ga و به دنبال آن \fBcode:yybackup\fP و به دنبال آن \fBcode:yypeek\fP است). .TP .B \fBcode:yybackup_yypeek_yyskip\fP دستور ترکیبی \fBcode:yybackup\fP، \fBcode:yypeek\fP و \fBcode:yyskip\fP (پیش‌فرض \(ga\(gacode:yybackup\(ga\(ga و به دنبال آن \fBcode:yypeek\fP و به دنبال آن \fBcode:yyskip\fP است). .TP .B \fBcode:yyrestore\fP دستور \fBYYRESTORE\fP، احتمالاً سفارشی‌شده برای APIهای مختلف. متغیرهای پشتیبانی‌شده: \fBYYRESTORE\fP، \fBYYCURSOR\fP، \fBYYMARKER\fP، \fByyrecord\fP (نگاشت به پیکربندی‌های متناظر \fBre2c:\fP). .TP .B \fBcode:yyrestorectx\fP دستور \fBYYRESTORECTX\fP، احتمالاً سفارشی‌شده برای APIهای مختلف. متغیرهای پشتیبانی‌شده: \fBYYRESTORECTX\fP، \fBYYCURSOR\fP، \fBYYCTXMARKER\fP، \fByyrecord\fP (نگاشت به پیکربندی‌های متناظر \fBre2c:\fP). .TP .B \fBcode:yyrestoretag\fP دستور \fBYYRESTORETAG\fP، احتمالاً سفارشی‌شده برای APIهای مختلف. متغیرهای پشتیبانی‌شده: \fBYYRESTORETAG\fP، \fBYYCURSOR\fP، \fByyrecord\fP (نگاشت به پیکربندی‌های متناظر \fBre2c:\fP)، \fBtag\fP (نام متغیر برچسب استفاده‌شده برای بازیابی موقعیت). .TP .B \fBcode:yyshift\fP دستور \fBYYSHIFT\fP، احتمالاً سفارشی‌شده برای APIهای مختلف. متغیرهای پشتیبانی‌شده: \fBYYSHIFT\fP، \fBYYCURSOR\fP، \fByyrecord\fP (نگاشت به پیکربندی‌های متناظر \fBre2c:\fP)، \fBoffset\fP (تعداد واحدهای کد برای انتقال موقعیت فعلی). .TP .B \fBcode:yyshiftstag\fP دستور \fBYYSHIFTSTAG\fP، احتمالاً سفارشی‌شده برای APIهای مختلف. متغیرهای پشتیبانی‌شده: \fBYYSHIFTSTAG\fP، \fByyrecord\fP، \fBnegative\fP (نگاشت به پیکربندی‌های متناظر \fBre2c:\fP)، \fBtag\fP (متغیر برچسبی که باید جابه‌جا شود)، \fBoffset\fP (تعداد واحدهای کد برای انتقال). شرط‌ها: \fB\&.nested\fP (درست در صورتی که این یک برچسب تو‌در‌تو باشد \-\- در این حالت ممکن است مقدار آن برابر با \fBre2c:tags:negative\fP باشد، که نباید منتقل شود). .TP .B \fBcode:yyshiftmtag\fP دستور \fBYYSHIFTMTAG\fP، احتمالاً سفارشی‌شده برای APIهای مختلف. متغیرهای پشتیبانی‌شده: \fBYYSHIFTMTAG\fP (نگاشت به پیکربندی متناظر \fBre2c:\fP)، \fBtag\fP (متغیر برچسبی که باید جابه‌جا شود)، \fBoffset\fP (تعداد واحدهای کد برای انتقال). .TP .B \fBcode:yystagp\fP دستور \fBYYSTAGP\fP، احتمالاً سفارشی‌شده برای APIهای مختلف. متغیرهای پشتیبانی‌شده: \fBYYSTAGP\fP، \fBYYCURSOR\fP، \fByyrecord\fP (نگاشت به پیکربندی‌های متناظر \fBre2c:\fP)، \fBtag\fP (متغیر برچسبی که باید به‌روزرسانی شود). .TP .B \fBcode:yymtagp\fP دستور \fBYYMTAGP\fP، احتمالاً سفارشی‌شده برای APIهای مختلف. متغیرهای پشتیبانی‌شده: \fBYYMTAGP\fP (نگاشت به پیکربندی متناظر \fBre2c:\fP)، \fBtag\fP (متغیر برچسبی که باید به‌روزرسانی شود). .TP .B \fBcode:yystagn\fP دستور \fBYYSTAGN\fP، احتمالاً سفارشی‌شده برای APIهای مختلف. متغیرهای پشتیبانی‌شده: \fBYYSTAGN\fP، \fBnegative\fP، \fByyrecord\fP (نگاشت به پیکربندی‌های متناظر \fBre2c:\fP)، \fBtag\fP (متغیر برچسبی که باید به‌روزرسانی شود). .TP .B \fBcode:yymtagn\fP دستور \fBYYMTAGN\fP، احتمالاً سفارشی‌شده برای APIهای مختلف. متغیرهای پشتیبانی‌شده: \fBYYMTAGN\fP (نگاشت به پیکربندی متناظر \fBre2c:\fP)، \fBtag\fP (متغیر برچسبی که باید به‌روزرسانی شود). .TP .B \fBcode:yycopystag\fP دستور \fBYYCOPYSTAG\fP، احتمالاً سفارشی‌شده برای APIهای مختلف. متغیرهای پشتیبانی‌شده: \fBYYCOPYSTAG\fP، \fByyrecord\fP (نگاشت به پیکربندی‌های متناظر \fBre2c:\fP)، \fBlhs\fP، \fBrhs\fP (متغیرهای برچسب سمت چپ و راست عملیات کپی). .TP .B \fBcode:yycopymtag\fP دستور \fBYYCOPYMTAG\fP، احتمالاً سفارشی‌شده برای APIهای مختلف. متغیرهای پشتیبانی‌شده: \fBYYCOPYMTAG\fP، \fByyrecord\fP (نگاشت به پیکربندی‌های متناظر \fBre2c:\fP)، \fBlhs\fP، \fBrhs\fP (متغیرهای برچسب سمت چپ و راست عملیات کپی). .TP .B \fBcode:yygetaccept\fP دستور \fBYYGETACCEPT\fP، احتمالاً سفارشی‌شده برای APIهای مختلف. متغیرهای پشتیبانی‌شده: \fBYYGETACCEPT\fP، \fByyrecord\fP (نگاشت به پیکربندی‌های متناظر \fBre2c:\fP)، \fBvar\fP (نگاشت به پیکربندی \fBre2c:yyaccept\fP). .TP .B \fBcode:yysetaccept\fP دستور \fBYYSETACCEPT\fP، احتمالاً سفارشی‌شده برای APIهای مختلف. متغیرهای پشتیبانی‌شده: \fBYYSETACCEPT\fP، \fByyrecord\fP (نگاشت به پیکربندی‌های متناظر \fBre2c:\fP)، \fBvar\fP (نگاشت به پیکربندی \fBre2c:yyaccept\fP) و \fBval\fP (مقدار عددی قاعدهٔ پذیرفته‌شده). .TP .B \fBcode:yygetcond\fP دستور \fBYYGETCOND\fP، احتمالاً سفارشی‌شده برای APIهای مختلف. متغیرهای پشتیبانی‌شده: \fBYYGETCOND\fP، \fByyrecord\fP (نگاشت به پیکربندی‌های متناظر \fBre2c:\fP)، \fBvar\fP (نگاشت به پیکربندی \fBre2c:yycond\fP). .TP .B \fBcode:yysetcond\fP دستور \fBYYSETCOND\fP، احتمالاً سفارشی‌شده برای APIهای مختلف. متغیرهای پشتیبانی‌شده: \fBYYSETCOND\fP، \fByyrecord\fP (نگاشت به پیکربندی‌های متناظر \fBre2c:\fP)، \fBvar\fP (نگاشت به پیکربندی \fBre2c:yycond\fP) و \fBval\fP (شناسهٔ عددی شرط). .TP .B \fBcode:yygetstate\fP دستور \fBYYGETSTATE\fP، احتمالاً سفارشی‌شده برای APIهای مختلف. متغیرهای پشتیبانی‌شده: \fBYYGETSTATE\fP، \fByyrecord\fP (نگاشت به پیکربندی‌های متناظر \fBre2c:\fP)، \fBvar\fP (نگاشت به پیکربندی \fBre2c:yystate\fP). .TP .B \fBcode:yysetstate\fP دستور \fBYYSETSTATE\fP، احتمالاً سفارشی‌شده برای APIهای مختلف. متغیرهای پشتیبانی‌شده: \fBYYSETSTATE\fP، \fByyrecord\fP (نگاشت به پیکربندی‌های متناظر \fBre2c:\fP)، \fBvar\fP (نگاشت به پیکربندی \fBre2c:yystate\fP) و \fBval\fP (شمارهٔ حالت). .TP .B \fBcode:yylessthan\fP دستور \fBYYLESSTHAN\fP، احتمالاً سفارشی‌شده برای APIهای مختلف. متغیرهای پشتیبانی‌شده: \fBYYLESSTHAN\fP، \fBYYCURSOR\fP، \fBYYLIMIT\fP، \fByyrecord\fP (نگاشت به پیکربندی‌های متناظر \fBre2c:\fP)، \fBneed\fP (تعداد واحدهای کد برای بررسی در برابر آن). شرط: \fB\&.many\fP (درست در صورتی که مقدار \fBneed\fP بیشتر از یک باشد)..TP .B \fBcode:yyend\fP عبارت \fBYYEND\fP، احتمالاً تخصیص‌یافته برای APIهای گوناگون. متغیرهای پشتیبانی‌شده: \fBYYEND\fP، \fBYYCURSOR\fP، \fBYYLIMIT\fP\&. .TP .B \fBcode:yybm_filter\fP شرطی که برای فیلتر کردن مقادیر \fByych\fP که توسط جدول \fByybm\fP پوشش داده نشده‌اند به کار می‌رود (همراه با گزینهٔ \fB\-\-bitmaps\fP استفاده می‌شود). متغیر پشتیبانی‌شده: \fByych\fP (به پیکربندی \fBre2c:yych\fP نگاشت می‌شود). .TP .B \fBcode:yybm_match\fP قالب بررسی جدول \fByybm\fP (تولیدشده با گزینهٔ \fB\-\-bitmaps\fP). متغیرهای پشتیبانی‌شده: \fByybm\fP، \fByych\fP (به پیکربندی‌های متناظر \fBre2c:\fP نگاشت می‌شوند)، \fBoffset\fP (آفست در جدول \fByybm\fP که باید به \fByych\fP افزوده شود) و \fBmask\fP (ماسک بیتی که باید روی مدخل جدول اعمال شود تا مقدار بولی مورد نیاز برای بررسی به دست آید) .TP .B \fBcode:yytarget_filter\fP شرطی که برای فیلتر کردن مقادیر \fByych\fP که توسط جدول \fByytarget\fP پوشش داده نشده‌اند به کار می‌رود (همراه با گزینهٔ \fB\-\-computed\-gotos\fP استفاده می‌شود). متغیر پشتیبانی‌شده: \fByych\fP (به پیکربندی \fBre2c:yych\fP نگاشت می‌شود). .UNINDENT .sp در اینجا فهرستی از تمام متغیرهای سراسری مجاز در فایل‌های نحو آمده است: .INDENT 0.0 .TP .B \fBnl\fP یک خط جدید. .TP .B \fBindent\fP متغیری که هیچ کدی تولید نمی‌کند، اما اثر جانبی افزایش سطح تورفتگی را دارد. .TP .B \fBdedent\fP متغیری که هیچ کدی تولید نمی‌کند، اما اثر جانبی کاهش سطح تورفتگی را دارد. .TP .B \fBtopindent\fP رشتهٔ تورفتگی برای دستور فعلی. سطح تورفتگی توسط مولد کد ردیابی شده و به‌طور خودکار به‌روزرسانی می‌شود. .UNINDENT .sp در اینجا فهرستی از تمام شرط‌های سراسری مجاز در فایل‌های نحو آمده است: .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 آزاد استفاده شود (\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 درست است اگر اثرانگشت تولیدشده باید حاوی تاریخ تولید باشد. .TP .B \fB\&.loop_label\fP درست است اگر حلقه‌های تولیدشده توسط re2rust باید دارای برچسب باشند (\fBre2c:label:yyloop\fP روی یک رشتهٔ غیرخالی تنظیم شده باشد). .TP .B \fB\&.monadic\fP درست است اگر کد تولیدشده باید به شیوهٔ مونادیک باشد (\fBre2c:monadic = 1\fP). این مورد تنها برای زبان‌های تابعی محض کاربرد دارد. .TP .B \fB\&.start_conditions\fP درست است اگر شرایط شروع فعال باشند (\fB\-\-start\-conditions\fP). .TP .B \fB\&.storable_state\fP درست است اگر وضعیت قابل ذخیره‌سازی فعال باشد (\fB\-\-storable\-state\fP). .TP .B \fB\&.unsafe\fP درست است اگر re2rust باید از بلوک‌های \(dqunsafe\(dq برای تولید کد سریع‌تر استفاده کند (\fB\-\-unsafe\fP، \fBre2c:unsafe = 1\fP). این مورد تنها برای زبان‌هایی مرتبط است که ویژگی \(dqunsafe\(dq را دارند. .TP .B \fB\&.version\fP درست است اگر اثرانگشت تولیدشده باید شامل نسخهٔ re2rust باشد. .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 دو شرط اول، تحلیل‌گر لغوی را به روشی \(dqطبیعی\(dq خاتمه می‌دهند: تحلیل‌گر به وضعیتی بدون گذارهای خروجی می‌رسد و تطابق به‌طور خودکار متوقف می‌شود. شرط سوم، یعنی پایان ورودی، متفاوت است: ممکن است در هر وضعیتی رخ دهد و تحلیل‌گر لغوی باید قادر به مدیریت آن باشد. بررسی پایان ورودی، جریان کار عادی تحلیل‌گر لغوی را مختل کرده و شاخه‌های شرطی را به برنامهٔ تولیدشده اضافه می‌کند؛ بنابراین به حداقل رساندن تعداد چنین بررسی‌هایی ضروری است. \fBre2rust\fP از چند روش مختلف برای مدیریت پایان ورودی پشتیبانی می‌کند. اینکه از کدام روش استفاده شود به پیچیدگی عبارات منظم، نیاز به بافرسازی، ملاحظات کارایی و سایر عوامل بستگی دارد. در اینجا فهرستی از روش‌ها آمده است: .INDENT 0.0 .IP \(bu 2 \fBدیده‌بان (Sentinel).\fP این روش نیاز به بررسی‌های پایان ورودی را به‌طور کلی حذف می‌کند. این شیوه ساده و کارآمد است، اما محدود به حالتی است که یک نویسهٔ \(dqدیده‌بان\(dq طبیعی وجود داشته باشد که هرگز در ورودی معتبر رخ ندهد. این نویسه همچنان ممکن است در ورودی نامعتبر رخ دهد، اما نباید توسط عبارات منظم مجاز شناخته شود، مگر شاید به عنوان آخرین نویسهٔ یک قاعده. نویسهٔ دیده‌بان به انتهای ورودی الحاق شده و به عنوان سیگنال توقف عمل می‌کند: زمانی که تحلیل‌گر لغوی این نویسه را می‌خواند، یا خطای نحوی رخ داده یا پایان ورودی است. در هر دو حالت، تحلیل‌گر لغوی باید متوقف شود. این روش در صورتی استفاده می‌شود که \fBYYFILL\fP با \fBre2c:yyfill:enable = 0;\fP غیرفعال شده باشد و \fBre2c:eof\fP مقدار پیش‌فرض \fB\-1\fP را داشته باشد\&. .nf .fi .sp .IP \(bu 2 \fBدیده‌بان با بررسی کرانه‌ها (Sentinel with bounds checks).\fP این روش عمومی است: اجازه می‌دهد هر ورودی بدون محدودیت روی عبارات منظم مدیریت شود. ایده این است که با انجام بررسی‌های پایان ورودی تنها روی نویسه‌هایی خاص، تعداد آن‌ها کاهش یابد. مشابه روش \(dqدیده‌بان\(dq، یکی از نویسه‌ها به عنوان \(dqدیده‌بان\(dq انتخاب شده و به انتهای ورودی الحاق می‌گردد. با این حال، هیچ محدودیتی در محل وقوع دیده‌بان وجود ندارد (در واقع، هر نویسه‌ای می‌تواند به عنوان دیده‌بان انتخاب شود). هنگامی که تحلیل‌گر لغوی این نویسه را می‌خواند، علاوه بر آن یک بررسی کرانه‌ها را انجام می‌دهد. اگر موقعیت فعلی در محدودهٔ مجاز باشد، تحلیل‌گر لغوی تطابق را از سر گرفته و با دیده‌بان مانند یک نویسهٔ معمولی رفتار می‌کند. در غیر این صورت، \fBYYFILL\fP را فراخوانی می‌کند (مگر اینکه غیرفعال شده باشد). اگر ورودی بیشتری ارائه شود، تحلیل‌گر لغوی نویسهٔ آخر را دوباره تطبیق داده و به گونه‌ای ادامه می‌دهد که گویی دیده‌بان در آنجا نبوده است. در غیر این صورت، باید پایان واقعی ورودی باشد و تحلیل‌گر لغوی متوقف می‌شود. این روش زمانی استفاده می‌شود که \fBre2c:eof\fP مقداری غیرمنفی داشته باشد (باید روی مقدار عددی دیده‌بان تنظیم شود). استفاده از \fBYYFILL\fP اختیاری است. .nf .fi .sp .IP \(bu 2 \fBبررسی کرانه‌ها با پدینگ (Bounds checks with padding).\fP این روش عمومی است و ممکن است سریع‌تر از روش \(dqدیده‌بان با بررسی کرانه‌ها\(dq باشد، اما پیچیده‌تر نیز هست. ایده این است که وضعیت‌های DFA به مؤلفه‌های قویاً همبند (SCCها) افراز شوند و برای هر SCC یک بررسی منفرد برای نویسه‌های کافی جهت پوشش طولانی‌ترین مسیر بدون حلقه در آن SCC ایجاد گردد. این کار تعداد بررسی‌ها را کاهش می‌دهد، اما مشکلی در مورد لکسم‌های (lexeme) کوتاه در انتهای ورودی وجود دارد، زیرا بررسی نیازمند نویسه‌های کافی برای پوشش طولانی‌ترین لکسم است. این مشکل می‌تواند با پدینگ (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) امکان بازنویسی عملیات پایه مانند خواندن نویسه را فراهم می‌کند، که گنجاندن بررسی‌های پایان ورودی را به عنوان بخشی از آن‌ها ممکن می‌سازد. این رویکرد مستعد خطا است و باید با احتیاط استفاده شود. برای استفاده از یک روش سفارشی، رابط عمومی را با \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\-terminated) شمارش می‌کند. نگهبان، null است: این آخرین کاراکتر هر رشته ورودی است و توسط هیچ‌یک از قواعد در میانه‌ی یک نشانه (lexeme) مجاز دانسته نمی‌شود (به‌ویژه، در بازه‌های نویسه‌ای که نادیده‌گرفتن آن آسان است گنجانده نشده است). اگر یک null در میانه‌ی یک رشته رخ دهد، این یک خطای نحو است و تحلیل‌گر لغوی قاعده پیش‌فرض \fB*\fP را مطابقت می‌دهد، اما فراتر از پایان ورودی را نخواهد خواند و دچار فروپاشی (crash) نخواهد شد (از هشدار \fI\%\-Wsentinel\-in\-midrule\fP و پیکربندی \fBre2c:sentinel\fP برای بررسی این موضوع استفاده کنید). پیکربندی \fBre2c:yyfill:enable = 0;\fP از تولید بررسی‌های مرزی و فراخوانی‌های \fBYYFILL\fP جلوگیری می‌کند. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C // re2rust $INPUT \-o $OUTPUT \-\-api simple fn lex(yyinput: &[u8]) \-> isize { // The input must be null\-terminated, otherwise the function has UB. assert_eq!(yyinput.last(), Some(&0)); let mut yycursor = 0; let mut count = 0; \(aqlex: loop { /*!re2c re2c:YYCTYPE = u8; re2c:yyfill:enable = 0; * { return \-1; } [\ex00] { return count; } [a\-z]+ { count += 1; continue \(aqlex; } [ ]+ { continue \(aqlex; } */} } fn main() { assert_eq!(lex(b\(dq\ex00\(dq), 0); assert_eq!(lex(b\(dqone two three\ex00\(dq), 3); assert_eq!(lex(b\(dqf0ur\ex00\(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 // re2rust $INPUT \-o $OUTPUT \-\-api simple fn lex(yyinput: &[u8]) \-> isize { // The input must be null\-terminated, otherwise the function has UB. assert_eq!(yyinput.last(), Some(&0)); let (mut yycursor, mut yymarker) = (0, 0); let yylimit = yyinput.len() \- 1; // null\-terminator not included let mut count = 0; \(aqlex: loop { /*!re2c re2c:YYCTYPE = u8; re2c:yyfill:enable = 0; re2c:eof = 0; str = [\(aq] ([^\(aq\e\e] | [\e\e][^])* [\(aq]; * { return \-1; } $ { return count; } str { count += 1; continue \(aqlex; } [ ]+ { continue \(aqlex; } */} } fn main() { assert_eq!(lex(b\(dq\e0\(dq), 0); assert_eq!(lex(b\(dq\(aqqu\e0tes\(aq \(aqare\(aq \(aqfine: \e\e\(aq\(aq \e0\(dq), 3); assert_eq!(lex(b\(dq\(aqunterminated\e\e\(aq\e0\(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) مطابقت می‌یابد و لکسر (lexer) را متوقف می‌کند (توجه داشته باشید که این قاعده بررسی می‌کند آیا null در ابتدای پدینگ قرار دارد یا خیر، در غیر این صورت یک خطای نحوی رخ می‌دهد). بررسی‌های مرز تنها در وضعیت‌های خاصی تولید می‌شوند که توسط مؤلفه‌های قویاً همبند خودکارِ پایه تعیین شده‌اند. این بررسی‌ها دارای قالب \fB(YYLIMIT \- YYCURSOR) < n\fP یا \fBYYLESSTHAN(n)\fP در API عمومی هستند، که در آن \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 // re2rust $INPUT \-o $OUTPUT \-\-api simple /*!max:re2c*/ fn lex(s: &[u8]) \-> isize { let mut count = 0; let mut yycursor = 0; let yylimit = s.len() + YYMAXFILL; // Copy string to a buffer and add YYMAXFILL zero padding. let mut yyinput = Vec::with_capacity(yylimit); yyinput.extend_from_slice(s); yyinput.extend([0 as u8; YYMAXFILL]); \(aqlex: loop { /*!re2c re2c:YYCTYPE = u8; re2c:YYFILL = \(dqreturn \-1;\(dq; str = [\(aq] ([^\(aq\e\e] | [\e\e][^])* [\(aq]; [\ex00] { // Check that it is the sentinel, not some unexpected null. return if yycursor == s.len() + 1 { count } else { \-1 } } str { count += 1; continue \(aqlex; } [ ]+ { continue \(aqlex; } * { return \-1; } */} } fn main() { assert_eq!(lex(b\(dq\(dq), 0); assert_eq!(lex(b\(dq\(aqqu\e0tes\(aq \(aqare\(aq \(aqfine: \e\e\(aq\(aq \(dq), 3); assert_eq!(lex(b\(dq\(aqunterminated\e\e\(aq\(dq), \-1); assert_eq!(lex(b\(dq\(aqunexpected \e0 null\(dq), \-1); } .ft P .fi .UNINDENT .UNINDENT .SS "بررسی‌های سفارشی (Custom checks)" .sp این مثال از یک روش سفارشی برای مدیریت انتهای ورودی بر پایهٔ generic API استفاده می‌کند. این برنامه رشته‌های محصور در علامت نقل‌قول تکی که با فاصله جدا شده‌اند را شمارش می‌کند. این مثال مشابه با مثال \fI\%sentinel\fP است، با این تفاوت که ورودی به null ختم نمی‌شود. برای جبران نبودِ نویسهٔ نگهبان در انتهای ورودی، \fBYYPEEK\fP بازتعریف شده است تا پیش از خواندن نویسهٔ بعدی ورودی، یک بررسی مرز انجام دهد. این روش ناکارآمد است زیرا بررسی‌ها به‌طور مکرر انجام می‌شوند. اگر شرط بررسی ناموفق باشد، \fBYYPEEK\fP نویسهٔ واقعی را برمی‌گرداند، در غیر این صورت یک نویسهٔ نگهبان ساختگی را برمی‌گرداند. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C // re2rust $INPUT \-o $OUTPUT // Expect a string without terminating null. fn lex(s: &[u8]) \-> isize { let mut count = 0; let mut cur = 0; let lim = s.len(); \(aqlex: loop {/*!re2c re2c:YYCTYPE = u8; re2c:YYPEEK = \(dqif cur < lim {*s.get_unchecked(cur)} else {0}\(dq; re2c:YYSKIP = \(dqcur += 1;\(dq; re2c:yyfill:enable = 0; * { return \-1; } [\ex00] { return count; } [a\-z]+ { count += 1; continue \(aqlex; } [ ]+ { continue \(aqlex; } */} } fn main() { assert_eq!(lex(b\(dq\(dq), 0); assert_eq!(lex(b\(dqone two three \(dq), 3); assert_eq!(lex(b\(dqf0ur\(dq), \-1); } .ft P .fi .UNINDENT .UNINDENT.SH "پر کردن مجدد بافر (BUFFER REFILLING)" .sp نیاز به بافربندی زمانی رخ می‌دهد که ورودی را نتوان به طور یک‌جا در حافظه نگاشت کرد: یا داده بسیار حجیم است، یا به صورت جریانی (مانند خواندن از یک سوکت) دریافت می‌شود. روش معمول در چنین مواردی تخصیص یک بافر حافظه با اندازهٔ ثابت و پردازش ورودی در تکه‌هایی (chunks) است که در این بافر جا می‌گیرند. هنگامی که تکهٔ جاری پردازش شد، به بیرون منتقل شده و داده‌های جدید وارد می‌شوند. در عمل این روند تا حدی پیچیده‌تر است، زیرا وضعیت تحلیل‌گر واژگانی (lexer) تنها از یک موقعیت ورودی تشکیل نشده، بلکه مجموعه‌ای از موقعیت‌های مرتبط با یکدیگر است: .INDENT 0.0 .IP \(bu 2 مکان‌نما (cursor): نویسهٔ ورودی بعدی که باید خوانده شود (\fBYYCURSOR\fP در C pointer API یا \fBYYSKIP\fP/\fBYYPEEK\fP در generic API) .IP \(bu 2 حد (limit): موقعیتِ پس از آخرین نویسهٔ موجود ورودی (\fBYYLIMIT\fP در C pointer API، که به صورت ضمنی توسط \fBYYLESSTHAN\fP در generic API مدیریت می‌شود) .IP \(bu 2 نشانه‌گذار (marker): موقعیت تازه‌ترین تطابق، در صورت وجود (\fBYYMARKER\fP در API پیش‌فرض یا \fBYYBACKUP\fP/\fBYYRESTORE\fP در generic API) .IP \(bu 2 توکن (token): ابتدای لکسم (lexeme) فعلی (در re2rust API به صورت ضمنی است، زیرا برای عملکرد عادی لکسر نیازی به آن نیست و می‌تواند توسط کاربر تعریف و به‌روزرسانی شود) .IP \(bu 2 نشانه‌گذار زمینه (context marker): موقعیت زمینهٔ انتهایی (\fBYYCTXMARKER\fP در C pointer API یا \fBYYBACKUPCTX\fP/\fBYYRESTORECTX\fP در generic API) .IP \(bu 2 متغیرهای برچسب (tag variables): موقعیت‌های زیرتطابق (تعریف‌شده با بلوک‌های \fBstags\fP و \fBmtags\fP و عملگرهای اولیهٔ generic API شامل \fBYYSTAGP\fP/\fBYYSTAGN\fP/\fBYYMTAGP\fP/\fBYYMTAGN\fP) .UNINDENT .sp تمام این موارد در هر حالتی استفاده نمی‌شوند، اما در صورت استفاده، باید توسط \fBYYFILL\fP به‌روزرسانی گردند\&. تمام موقعیت‌های فعال در بخش بین token و cursor قرار دارند؛ بنابراین هر داده‌ای بین ابتدای بافر و token را می‌توان دور ریخت، بخش بین token تا limit باید به ابتدای بافر منتقل شود، و فضای خالی ایجادشده در انتهای بافر با داده‌های جدید پر شود. برای جلوگیری از فراخوانی‌های مکرر \fBYYFILL\fP بهتر است تا حد امکان نویسه‌های ورودی بیشتری پر شود (حتی اگر نویسه‌های کمتری برای ادامهٔ کار لکسر کافی باشد). جزئیات پیاده‌سازی \fBYYFILL\fP بسته به روش مدیریت EOF کمی متفاوت است: حالت قاعدهٔ EOF تا حدی ساده‌تر از حالت بررسی مرزها همراه با فاصله‌گذاری (padding) است. همچنین توجه داشته باشید که در صورت استفاده از گزینهٔ \fB\-f \-\-storable\-state\fP، سازوکار \fBYYFILL\fP معنای اندکی متفاوت خواهد داشت (که در بخش مربوط به وضعیت قابل ذخیره‌سازی شرح داده شده است). .SS "YYFILL با نشانه (YYFILL with sentinel)" .sp اگر از قاعدهٔ EOF استفاده شود، \fBYYFILL\fP یک عملگر اولیه مانند تابع است که هیچ آرگومانی نمی‌پذیرد و مقداری برمی‌گرداند که با صفر مقایسه می‌شود. فراخوانی \fBYYFILL\fP توسط شرط \fBYYLIMIT <= YYCURSOR\fP در C pointer API و \fBYYLESSTHAN()\fP در generic API فعال می‌شود. مقدار بازگشتی غیرصفر به این معنی است که \fBYYFILL\fP با شکست مواجه شده است. یک فراخوانی موفق \fBYYFILL\fP باید حداقل یک نویسه فراهم کرده و موقعیت‌های ورودی را بر همان اساس تنظیم کند. حد (limit) باید همیشه یک موقعیت بعد از آخرین ورودی در بافر تنظیم شود، و نویسهٔ موجود در موقعیت limit باید نماد نگهبان (sentinel) مشخص‌شده با پیکربندی \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 // re2rust $INPUT \-o $OUTPUT use std::fs::File; use std::io::{Read, Write}; const BUFSIZE: usize = 4096; struct State { file: File, yyinput: [u8; BUFSIZE], yylimit: usize, yycursor: usize, yymarker: usize, token: usize, eof: bool, } #[derive(PartialEq)] enum Fill { Ok, Eof, LongLexeme } fn fill(st: &mut State) \-> Fill { if st.eof { return Fill::Eof; } // Error: lexeme too long. In real life could reallocate a larger buffer. if st.token < 1 { return Fill::LongLexeme; } // Shift buffer contents (discard everything up to the current token). st.yyinput.copy_within(st.token..st.yylimit, 0); st.yylimit \-= st.token; st.yycursor \-= st.token; st.yymarker = st.yymarker.overflowing_sub(st.token).0; // may underflow if marker is unused st.token = 0; // Fill free space at the end of buffer with new data from file. match st.file.read(&mut st.yyinput[st.yylimit..BUFSIZE \- 1]) { // \-1 for sentinel Ok(n) => { st.yylimit += n; st.eof = n == 0; // end of file st.yyinput[st.yylimit] = 0; // append sentinel } Err(why) => panic!(\(dqcannot read from file: {}\(dq, why) } return Fill::Ok; } fn lex(yyrecord: &mut State) \-> isize { let mut count: isize = 0; \(aqlex: loop { yyrecord.token = yyrecord.yycursor; /*!re2c re2c:api = record; re2c:YYCTYPE = u8; re2c:YYFILL = \(dqfill(yyrecord) == Fill::Ok\(dq; re2c:eof = 0; str = [\(aq] ([^\(aq\e\e] | [\e\e][^])* [\(aq]; * { return \-1; } $ { return count; } str { count += 1; continue \(aqlex; } [ ]+ { continue \(aqlex; } */} } fn main() { let fname = \(dqinput\(dq; let content = b\(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. match File::create(fname) { Err(why) => panic!(\(dqcannot open {}: {}\(dq, fname, why), Ok(mut file) => match file.write_all(&content.repeat(BUFSIZE)) { Err(why) => panic!(\(dqcannot write to {}: {}\(dq, fname, why), Ok(_) => {} } }; let count = 3 * BUFSIZE; // number of quoted strings written to file // Reopen input file for reading. let file = match File::open(fname) { Err(why) => panic!(\(dqcannot read file {}: {}\(dq, fname, why), Ok(file) => file, }; // Initialize lexer state: all offsets are at the end of buffer. let yylimit = BUFSIZE \- 1; let mut st = State { file: file, // Sentinel (at \(gayylimit\(ga offset) is set to null, which triggers YYFILL. yyinput: [0; BUFSIZE], yylimit: yylimit, yycursor: yylimit, yymarker: yylimit, token: yylimit, eof: false, }; // Run the lexer. assert_eq!(lex(&mut st), count as isize); // Cleanup: remove input file. match std::fs::remove_file(fname) { Err(why) => panic!(\(dqcannot remove {}: {}\(dq, fname, why), Ok(_) => {} } } .ft P .fi .UNINDENT .UNINDENT.SS "YYFILL با لایه‌گذاری (YYFILL with padding)" .sp در حالت پیش‌فرض (زمانی که از قاعدهٔ EOF استفاده نمی‌شود)، \fBYYFILL\fP یک سازوکار پایه‌ای (primitive) تابع‌مانند است که یک آرگومان می‌پذیرد و هیچ مقداری را بازنمی‌گرداند. فراخوانی \fBYYFILL\fP با شرط \fB(YYLIMIT \- YYCURSOR) < n\fP در API اشاره‌گر C و \fBYYLESSTHAN(n)\fP در API عمومی راه‌اندازی می‌شود. آرگومان ارائه‌شده به \fBYYFILL\fP کمینه تعداد نویسه‌هایی است که باید تأمین شوند. اگر نتواند این کار را انجام دهد، \fBYYFILL\fP نباید کنترل را به لکسر بازگرداند (به همین دلیل بهتر است به صورت ماکرویی پیاده‌سازی شود که در صورت شکست، از تابع فراخواننده خارج شود). در صورت فراخوانی موفقیت‌آمیز \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 را در قطعات ۴۰۹۶ بایتی می‌خواند و از بررسی حدود به همراه لایه‌گذاری استفاده می‌کند. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C // re2rust $INPUT \-o $OUTPUT use std::fs::File; use std::io::{Read, Write}; /*!max:re2c*/ const BUFSIZE: usize = 4096; struct State { file: File, yyinput: [u8; BUFSIZE], yylimit: usize, yycursor: usize, yymarker: usize, token: usize, eof: bool, } #[derive(PartialEq)] enum Fill { Ok, Eof, LongLexeme } fn fill(st: &mut State, need: usize) \-> Fill { if st.eof { return Fill::Eof; } // Error: lexeme too long. In real life can reallocate a larger buffer. if st.token < need { return Fill::LongLexeme; } // Shift buffer contents (discard everything up to the current token). st.yyinput.copy_within(st.token..st.yylimit, 0); st.yylimit \-= st.token; st.yycursor \-= st.token; st.yymarker = st.yymarker.overflowing_sub(st.token).0; // underflows if marker is unused st.token = 0; // Fill free space at the end of buffer with new data from file. let n = match st.file.read(&mut st.yyinput[st.yylimit..BUFSIZE \- YYMAXFILL]) { Ok(n) => n, Err(why) => panic!(\(dqcannot read from file: {}\(dq, why) }; st.yylimit += n; // If read zero characters, this is end of input => add zero padding // so that the lexer can access characters at the end of buffer. if n == 0 { st.eof = true; for i in 0..YYMAXFILL { st.yyinput[st.yylimit + i] = 0; } st.yylimit += YYMAXFILL; } return Fill::Ok; } fn lex(yyrecord: &mut State) \-> isize { let mut count: isize = 0; \(aqlex: loop { yyrecord.token = yyrecord.yycursor; /*!re2c re2c:api = record; re2c:YYCTYPE = u8; re2c:YYFILL = \(dqif fill(yyrecord, @@) != Fill::Ok { return \-1; }\(dq; str = [\(aq] ([^\(aq\e\e] | [\e\e][^])* [\(aq]; [\ex00] { // Check that it is the sentinel, not some unexpected null. return if yyrecord.token == yyrecord.yylimit \- YYMAXFILL { count } else { \-1 } } str { count += 1; continue \(aqlex; } [ ]+ { continue \(aqlex; } * { return \-1; } */} } fn main() { let fname = \(dqinput\(dq; let content = b\(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. match File::create(fname) { Err(why) => panic!(\(dqcannot open {}: {}\(dq, fname, why), Ok(mut file) => match file.write_all(&content.repeat(BUFSIZE)) { Err(why) => panic!(\(dqcannot write to {}: {}\(dq, fname, why), Ok(_) => {} } }; let count = 3 * BUFSIZE; // number of quoted strings written to file // Reopen input file for reading. let file = match File::open(fname) { Err(why) => panic!(\(dqcannot read file {}: {}\(dq, fname, why), Ok(file) => file, }; // Initialize lexer state: all offsets are at the end of buffer. // This immediately triggers YYFILL, as the YYLESSTHAN condition is true. let yylimit = BUFSIZE \- YYMAXFILL; let mut st = State { file: file, yyinput: [0; BUFSIZE], yylimit: yylimit, yycursor: yylimit, yymarker: yylimit, token: yylimit, eof: false, }; // Run the lexer. assert_eq!(lex(&mut st), count as isize); // Cleanup: remove input file. match std::fs::remove_file(fname) { Err(why) => panic!(\(dqcannot remove {}: {}\(dq, fname, why), Ok(_) => {} } } .ft P .fi .UNINDENT .UNINDENT.SH "ویژگی‌ها (FEATURES)" .SS "چندین بلوک (Multiple blocks)" .sp گاهی اوقات لازم است چندین تحلیل‌گر لغویِ (lexer) مرتبط با یکدیگر داشته باشیم (برای نمونه، زمانی که یک ماشین وضعیت سطح بالا وجود دارد که بین حالت‌های مختلف تحلیل‌گر جابه‌جا می‌شود). این کار می‌تواند با استفاده از چندین بلوک متصل re2rust پیاده‌سازی شود. گزینهٔ دیگر استفاده از \fI\%start conditions\fP است\&. .sp پیاده‌سازی ارتباط بین بلوک‌ها به زبان مقصد بستگی دارد. در زبان‌هایی که دستور \fBgoto\fP دارند (مانند C/C++ و Go)، می‌توان همهٔ بلوک‌ها را در یک تابع قرار داد و پیش از هر بلوک یک برچسب (label) تعریف کرد. انتقال از یک بلوک به بلوک دیگر با یک \fBgoto\fP ساده انجام می‌شود\&. در زبان‌هایی که فاقد \fBgoto\fP هستند (مانند Rust)، استفاده از یک حلقه همراه با switch روی یک متغیر وضعیت ضروری است؛ مشابه حلقه/switch متغیر \fByystate\fP که توسط re2rust تولید می‌شود، و یا اینکه هر بلوک درون یک تابع محصور شده و از فراخوانی توابع استفاده شود. .sp مثال زیر از چندین بلوک برای تجزیهٔ اعداد دودویی (binary)، هشت‌هشتی (octal)، ده‌دهی (decimal) و شانزده‌شانزدهی (hexadecimal) استفاده می‌کند. هر مبنا بلوک مخصوص به خود را دارد. بلوک اولیه مبنا را تعیین کرده و به بلوک‌های دیگر هدایت می‌کند. پیکربندی‌های مشترک در بلوکی جداگانه در ابتدای برنامه تعریف شده‌اند؛ این تنظیمات توسط بلوک‌های دیگر به ارث برده می‌شوند. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C // re2rust $INPUT \-o $OUTPUT // Store u32 number in u64 during parsing to simplify overflow handling. struct State<\(aqa> { yyinput: &\(aqa [u8], yycursor: usize, yymarker: usize, num: u64, } /*!re2c // Common re2c definitions shared between all functions. re2c:api = record; re2c:yyrecord = st; re2c:yyfill:enable = 0; re2c:YYCTYPE = u8; */ const ERROR: u64 = std::u32::MAX as u64 + 1; // overflow macro_rules! maybe { // Convert the number from u64 to optional u32. ($n:expr) => { if $n < ERROR { Some($n as u32) } else { None } } } // Add digit with the given base, checking for overflow. fn add(st: &mut State, offs: u8, base: u64) { let digit = unsafe { st.yyinput.get_unchecked(st.yycursor \- 1) } \- offs; st.num = std::cmp::min(st.num * base + digit as u64, ERROR); } fn parse_u32(s: & [u8]) \-> Option { assert_eq!(s.last(), Some(&0)); // expect null\-terminated input let mut st = State {yyinput: s, yycursor: 0, yymarker: 0, num: 0}; /*!re2c \(aq0b\(aq / [01] { return parse_bin(&mut st); } \(dq0\(dq { return parse_oct(&mut st); } \(dq\(dq / [1\-9] { return parse_dec(&mut st); } \(aq0x\(aq / [0\-9a\-fA\-F] { return parse_hex(&mut st); } * { return None; } */ } fn parse_bin(st: &mut State) \-> Option { \(aqbin: loop {/*!re2c [01] { add(st, 48, 2); continue \(aqbin; } * { return maybe!(st.num); } */} } fn parse_oct(st: &mut State) \-> Option { \(aqoct: loop {/*!re2c [0\-7] { add(st, 48, 8); continue \(aqoct; } * { return maybe!(st.num); } */} } fn parse_dec(st: &mut State) \-> Option { \(aqdec: loop {/*!re2c [0\-9] { add(st, 48, 10); continue \(aqdec; } * { return maybe!(st.num); } */} } fn parse_hex(st: &mut State) \-> Option { \(aqhex: loop {/*!re2c [0\-9] { add(st, 48, 16); continue \(aqhex; } [a\-f] { add(st, 87, 16); continue \(aqhex; } [A\-F] { add(st, 55, 16); continue \(aqhex; } * { return maybe!(st.num); } */} } fn main() { assert_eq!(parse_u32(b\(dq\e0\(dq), None); assert_eq!(parse_u32(b\(dq1234567890\e0\(dq), Some(1234567890)); assert_eq!(parse_u32(b\(dq0b1101\e0\(dq), Some(13)); assert_eq!(parse_u32(b\(dq0x7Fe\e0\(dq), Some(2046)); assert_eq!(parse_u32(b\(dq0644\e0\(dq), Some(420)); assert_eq!(parse_u32(b\(dq9999999999\e0\(dq), None); } .ft P .fi .UNINDENT .UNINDENT.SS "شرایط شروع (Start conditions)" .sp شرایط شروع با گزینهٔ \fB\-\-start\-conditions\fP فعال می‌شوند. آن‌ها روشی را برای کدگذاری چندین خودکارهٔ (اتوماتای) مرتبط با یکدیگر در یک بلوک re2rust فراهم می‌کنند. .sp هر شرط متناظر با یک خودکارهٔ واحد است و نام یکتایی دارد که توسط کاربر مشخص می‌شود و شمارهٔ داخلی یکتایی دارد که توسط re2rust\& تعریف می‌شود. این شماره‌ها برای جابه‌جایی میان شرایط به کار می‌روند: کد تولید‌شده از اولیه‌های \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 استفاده شود (این اکشن امکان کنترل دقیق‌تری را فراهم می‌سازد، زیرا کد می‌تواند به ازای هر شرط مشخص شود و می‌توان مستقیماً بدون گذر از توزیع شرایط (condition dispatch) به شروع شرط پرش کرد). .TP .B \fB< > => condition code\fP مشابه قاعدهٔ قبلی، با این تفاوت که \fBcondition\fP بعدی را تعیین می‌کند. .TP .B \fB< > :=> condition\fP مشابه قاعدهٔ قبلی، با این تفاوت که کد مرتبطی ندارد و بلافاصله به \fBcondition\fP پرش می‌کند. .UNINDENT .UNINDENT .UNINDENT .sp کدی که re2rust برای شرایط تولید می‌کند بستگی به این دارد که re2rust از رویکرد goto/label یا رویکرد loop/switch برای کدگذاری خودکاره‌ها استفاده کند. .sp در زبان‌هایی که دارای دستور \fBgoto\fP هستند (مانند C/C++ و Go)، شرایط به‌طور طبیعی به‌صورت بلوک‌هایی از کد با برچسب‌هایی به شکل \fByyc_\fP پیاده‌سازی می‌شوند، که در آن \fBcond\fP نام شرط است (پیشوند برچسب را می‌توان با \fBre2c:cond:prefix\fP تغییر داد). انتقال‌ها بین شرایط با استفاده از \fBgoto\fP و برچسب‌های شرط پیاده‌سازی می‌شوند. پیش از همهٔ شرایط، re2rust یک switch اولیه بر روی \fBYYGETSTATE\fP تولید می‌کند که به وضعیت شروع شرط فعلی پرش می‌کند. قواعد میان‌بر \fB:=>\fP از switch اولیه عبور کرده و مستقیماً به شرط مشخص‌شده پرش می‌کنند (از \fBre2c:cond:goto\fP می‌توان برای تغییر رفتار پیش‌فرض استفاده کرد). قواعد دارای عمل‌های معنایی به‌طور خودکار به شرط بعدی پرش نمی‌کنند؛ این کار باید توسط کد عمل تعریف‌شده توسط کاربر انجام شود. .sp در زبان‌هایی که فاقد \fBgoto\fP هستند (مانند Rust)، re2rust متغیر \fByystate\fP را برای ذخیرهٔ شماره‌های شرط بازاستفاده می‌کند. هر شرط یک شناسهٔ عددی برابر با شمارهٔ وضعیت شروع خود دریافت می‌کند، و جابه‌جایی میان شرایط تفاوتی با جابه‌جایی میان وضعیت‌های DFA در یک شرط واحد ندارد. نیازی به یک switch اولیهٔ جداگانه برای شرایط نیست. (از آنجا که رویکرد یکسانی برای پیاده‌سازی وضعیت‌های قابل ذخیره استفاده می‌شود، در صورت استفادهٔ هم‌زمان از وضعیت‌های قابل ذخیره و شرایط، \fBYYGETCOND\fP/\fBYYSETCOND\fP زائد خواهند بود). .sp برنامهٔ زیر از شرایط شروع برای تجزیهٔ اعداد دودویی (باینری)، هشت‌هشتی (اوکتال)، ده‌دهی (دسیمال) و شانزده‌شانزدهی (هگزادسیمال) استفاده می‌کند. یک بلوک واحد وجود دارد که در آن هر مبنا شرط مخصوص به خود را دارد و شرط اولیه به همهٔ آن‌ها متصل است. متغیر تعریف‌شده توسط کاربر \fBcond\fP شمارهٔ شرط فعلی را ذخیره می‌کند؛ این متغیر با شمارهٔ شرط اولیه که توسط بلوک \fBconditions\fP تولید شده است مقداردهی اولیه می‌شود. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C // re2rust $INPUT \-o $OUTPUT \-c \-\-api simple /*!conditions:re2c*/ const ERROR: u64 = std::u32::MAX as u64 + 1; // overflow // Add digit with the given base, checking for overflow. fn add(num: &mut u64, str: &[u8], cur: usize, offs: u8, base: u64) { let digit = unsafe { str.get_unchecked(cur \- 1) } \- offs; *num = std::cmp::min(*num * base + digit as u64, ERROR); } fn parse_u32(yyinput: &[u8]) \-> Option { assert_eq!(yyinput.last(), Some(&0)); // expect null\-terminated input let (mut yycursor, mut yymarker) = (0, 0); let mut yycond = YYC_INIT; let mut num = 0u64; // Store number in u64 to simplify overflow checks. \(aqlex: loop { /*!re2c re2c:YYCTYPE = u8; re2c:yyfill:enable = 0; \(aq0b\(aq / [01] :=> BIN \(dq0\(dq :=> OCT \(dq\(dq / [1\-9] :=> DEC \(aq0x\(aq / [0\-9a\-fA\-F] :=> HEX * { return None; } [01] { add(&mut num, yyinput, yycursor, 48, 2); continue \(aqlex; } [0\-7] { add(&mut num, yyinput, yycursor, 48, 8); continue \(aqlex; } [0\-9] { add(&mut num, yyinput, yycursor, 48, 10); continue \(aqlex; } [0\-9] { add(&mut num, yyinput, yycursor, 48, 16); continue \(aqlex; } [a\-f] { add(&mut num, yyinput, yycursor, 87, 16); continue \(aqlex; } [A\-F] { add(&mut num, yyinput, yycursor, 55, 16); continue \(aqlex; } * { return if num < ERROR { Some(num as u32) } else { None }; } */} } fn main() { assert_eq!(parse_u32(b\(dq\e0\(dq), None); assert_eq!(parse_u32(b\(dq1234567890\e0\(dq), Some(1234567890)); assert_eq!(parse_u32(b\(dq0b1101\e0\(dq), Some(13)); assert_eq!(parse_u32(b\(dq0x7Fe\e0\(dq), Some(2046)); assert_eq!(parse_u32(b\(dq0644\e0\(dq), Some(420)); assert_eq!(parse_u32(b\(dq9999999999\e0\(dq), None); } .ft P .fi .UNINDENT .UNINDENT.SS "وضعیت ذخیره‌پذیر (Storable state)" .sp با گزینهٔ \fB\-\-storable\-state\fP، ابزار re2rust تحلیل‌گری لغوی تولید می‌کند که می‌تواند وضعیت فعلی خود را ذخیره کرده، به فراخوان بازگردد و بعداً عملیات را دقیقاً از همان جایی که متوقف شده بود از سر بگیرد. حالت پیش‌فرض عملکرد در re2rust یک مدل «کِششی» (\(dqpull\(dq) است که در آن، تحلیل‌گر لغوی هر زمان که به ورودی بیشتری نیاز داشته باشد آن را دریافت می‌کند. این امر ممکن است در مواردی که ورودی به صورت تکه‌تکه در دسترس قرار می‌گیرد غیرقابل‌قبول باشد (برای نمونه، اگر تحلیل‌گر لغوی توسط تجزیه‌کننده فراخوانی شود، یا اگر برنامهٔ تحلیل‌گر لغوی از طریق یک پروتکل سوکت با برنامهٔ دیگری ارتباط برقرار کند که باید پیش از ارسال پیام بعدی منتظر پاسخی از تحلیل‌گر لغوی بماند). قابلیت وضعیت ذخیره‌پذیر دقیقاً برای چنین مواردی در نظر گرفته شده است: این ویژگی امکان تولید تحلیل‌گرهای لغوی را فراهم می‌کند که در یک مدل «فشاری» (\(dqpush\(dq) کار می‌کنند. هنگامی که تحلیل‌گر لغوی به ورودی بیشتری نیاز پیدا کند، وضعیت خود را ذخیره کرده و به فراخوان بازمی‌گردد. سپس، هنگامی که ورودی بیشتری در دسترس قرار گیرد، فراخوان تحلیل‌گر لغوی را دقیقاً از جایی که متوقف شده بود ادامه می‌دهد. در مقایسه با مدل «کِششی» (\(dqpull\(dq)، چند تغییر لازم است: .INDENT 0.0 .IP \(bu 2 تعریف عملگرهای پایه‌ای \fBYYSETSTATE()\fP و \fBYYGETSTATE(state)\fP. .IP \(bu 2 تعریف متغیرهای \fByych\fP، \fByyaccept\fP (در صورت استفاده) و \fBstate\fP به عنوان بخشی از وضعیت ماندگار تحلیل‌گر لغوی. متغیر \fBstate\fP باید با \fB\-1\fP مقداردهی اولیه شود. .IP \(bu 2 دستور \fBYYFILL\fP باید به جای تلاش برای تأمین ورودی بیشتر، به برنامهٔ بیرونی بازگردد. کد بازگشتی باید نشان دهد که تحلیل‌گر لغوی به ورودی بیشتری نیاز دارد. .IP \(bu 2 برنامهٔ بیرونی باید شرایطی را که تحلیل‌گر لغوی به ورودی بیشتری نیاز دارد تشخیص داده و واکنش مناسب نشان دهد. .IP \(bu 2 استفادهٔ اختیاری از بلوک \fBgetstate\fP برای تولید سوئیچ \fBYYGETSTATE\fP جدا از تحلیل‌گر لغوی اصلی. این مورد تنها برای زبان‌هایی کار می‌کند که دارای \fBgoto\fP هستند (نه در حالت \fB\-\-loop\-switch\fP). .IP \(bu 2 استفاده از \fBre2c:eof\fP و روش \fI\%sentinel with bounds checks\fP برای مدیریت پایان ورودی. روش مبتنی بر لایه‌گذاری (padding) ممکن است کار نکند، چرا که زمان اضافه کردن لایه‌گذاری مشخص نیست: پایان فعلی ورودی ممکن است پایان نهایی ورودی نباشد، و افزودن بیش از حد زودهنگام لایه‌گذاری ممکن است یک نشانهٔ (lexeme) حریصانه را که تا حدی خوانده شده قطع کند. علاوه بر این، به دلیل منطق سطح‌بالای برنامه، دریافت ورودی بیشتر ممکن است به پردازش نشانه در انتهای بافر وابسته باشد (که از قبل به دلیل شرط پایان ورودی مسدود شده است). .UNINDENT .sp در اینجا مثالی از یک تحلیل‌گر لغوی با مدل «فشاری» (\(dqpush\(dq) آورده شده است که خواندن بسته‌ها از یک سوکت را شبیه‌سازی می‌کند. تحلیل‌گر لغوی حلقه می‌زند تا زمانی که به پایان ورودی برسد و به تابع فراخوان بازگردد. تابع فراخوان با «ارسال» بستهٔ بعدی ورودی بیشتری را فراهم کرده و تحلیل لغوی را از سر می‌گیرد. این فرایند زمانی متوقف می‌شود که تمام بسته‌ها ارسال شده باشند یا خطایی رخ دهد. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C // re2rust $INPUT \-o $OUTPUT \-f use std::fs::File; use std::io::{Read, Write}; const DEBUG: bool = false; macro_rules! log { ($($fmt:expr)? $(, $args:expr)*) => { if DEBUG { println!($($fmt)? $(, $args)*) } } } // Use a small buffer to cover the case when a lexeme doesn\(aqt fit. // In real world use a larger buffer. const BUFSIZE: usize = 10; struct State { file: File, yyinput: [u8; BUFSIZE], yylimit: usize, yycursor: usize, yymarker: usize, token: usize, yystate: isize, } #[derive(Debug, PartialEq)] enum Status {End, Ready, Waiting, BadPacket, BigPacket} fn fill(st: &mut State) \-> Status { // Error: lexeme too long. In real life can reallocate a larger buffer. if st.token < 1 { return Status::BigPacket; } // Shift buffer contents (discard everything up to the current lexeme). st.yyinput.copy_within(st.token..st.yylimit, 0); st.yylimit \-= st.token; st.yycursor \-= st.token; st.yymarker = st.yymarker.overflowing_sub(st.token).0; // underflows if marker is unused st.token = 0; // Fill free space at the end of buffer with new data. match st.file.read(&mut st.yyinput[st.yylimit..BUFSIZE \- 1]) { // \-1 for sentinel Ok(n) => { st.yylimit += n; st.yyinput[st.yylimit] = 0; // append sentinel symbol }, Err(why) => panic!(\(dqcannot read from file: {}\(dq, why) } return Status::Ready; } fn lex(yyrecord: &mut State, recv: &mut usize) \-> Status { let mut yych; \(aqlex: loop { yyrecord.token = yyrecord.yycursor; /*!re2c re2c:api = record; re2c:eof = 0; re2c:YYCTYPE = \(dqu8\(dq; re2c:YYFILL = \(dqreturn Status::Waiting;\(dq; packet = [a\-z]+[;]; * { return Status::BadPacket; } $ { return Status::End; } packet { *recv += 1; continue \(aqlex; } */} } fn test(packets: Vec<&[u8]>, expect: Status) { // Create a pipe (open the same file for reading and writing). let fname = \(dqpipe\(dq; let mut fw: File = match File::create(fname) { Err(why) => panic!(\(dqcannot open {}: {}\(dq, fname, why), Ok(file) => file, }; let fr: File = match File::open(fname) { Err(why) => panic!(\(dqcannot read file {}: {}\(dq, fname, why), Ok(file) => file, }; // Initialize lexer state: \(gastate\(ga value is \-1, all offsets are at the end // of buffer, the character at \(gayylimit\(ga offset is the sentinel (null). let yylimit = BUFSIZE \- 1; let mut state = State { file: fr, // Sentinel (at \(gayylimit\(ga offset) is set to null, which triggers YYFILL. yyinput: [0; BUFSIZE], yylimit: yylimit, yycursor: yylimit, yymarker: yylimit, token: yylimit, 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. let mut status; let mut send = 0; let mut recv = 0; loop { status = lex(&mut state, &mut recv); if status == Status::End { log!(\(dqdone: got {} packets\(dq, recv); break; } else if status == Status::Waiting { log!(\(dqwaiting...\(dq); if send < packets.len() { log!(\(dqsent packet {}\(dq, send); match fw.write_all(packets[send]) { Err(why) => panic!(\(dqcannot write to {}: {}\(dq, fname, why), Ok(_) => send += 1, } } status = fill(&mut state); log!(\(dqqueue: \(aq{}\(aq\(dq, String::from_utf8_lossy(&state.yyinput)); if status == Status::BigPacket { log!(\(dqerror: packet too big\(dq); break; } assert_eq!(status, Status::Ready); } else { assert_eq!(status, Status::BadPacket); log!(\(dqerror: ill\-formed packet\(dq); break; } } // Check results. assert_eq!(status, expect); if status == Status::End { assert_eq!(recv, send); } // Cleanup: remove input file. match std::fs::remove_file(fname) { Err(why) => panic!(\(dqcannot remove {}: {}\(dq, fname, why), Ok(_) => {} } } fn main() { test(vec![], Status::End); test(vec![b\(dqzero;\(dq, b\(dqone;\(dq, b\(dqtwo;\(dq, b\(dqthree;\(dq, b\(dqfour;\(dq], Status::End); test(vec![b\(dqzer0;\(dq], Status::BadPacket); test(vec![b\(dqgoooooooooogle;\(dq], Status::BigPacket); } .ft P .fi .UNINDENT .UNINDENT.SS بلوک‌های با قابلیت استفاده مجدد .sp بلوک‌های با قابلیت استفاده مجدد به شکل \fB/*!rules:re2c[:] ... */\fP یا \fB%{rules[:] ... %}\fP می‌توانند به هر تعداد بار مجدداً استفاده شده و با دیگر بلوک‌های re2rust ترکیب شوند. بخش \fB\fP اختیاری است. یک بلوک rules می‌تواند در یک بلوک یا دستورالعمل \fBuse\fP به کار رود. کد مربوط به یک بلوک rules در هر نقطه از استفاده تولید می‌شود. .sp بلوک‌های use با \fB/*!use:re2c[:] ... */\fP یا \fB%{use[:] ... %}\fP\& تعریف می‌شوند. بخش \fB\fP اختیاری است: اگر مشخص نشود، بلوک rules مرتبط، جدیدترین بلوک خواهد بود (خواه نام‌دار باشد یا بی‌نام). یک بلوک use می‌تواند تعاریف نام‌دار، پیکربندی‌ها و قواعد مختص به خود را اضافه کند. یک مورد کاربرد مهم برای بلوک‌های use، تحلیل‌گر لغوی (lexer) با پشتیبانی از چندین کدگذاری ورودی است: همان بلوک rules چندین بار با پیکربندی‌های خاص هر کدگذاری مجدداً استفاده می‌شود (مثال زیر را ببینید). .sp دستورالعمل درون‌بلوکی \fB!use:;\fP می‌تواند از داخل یک بلوک re2rust استفاده شود. این دستور، بلوک ارجاع‌شده‌ی \fB\fP را با بلوک فعلی ادغام می‌کند. اگر برخی از قواعد و پیکربندی‌های ادغام‌شده با موارد تعریف‌شده‌ی پیشین هم‌پوشانی داشته باشند، تداخل‌ها به شیوه معمول حل می‌شوند: نخستین قاعده اولویت دارد و آخرین پیکربندی بر موارد پیشین اعمال می‌شود. یک استثنا، قواعد ویژه \fB*\fP، \fB$\fP و (در حالت شرطی) \fB\fP هستند که برای آن‌ها تعریف محلی بلوک بر هر تعریف به ارث‌رسیده‌ای ارجحیت دارد. دستورالعمل use امکان ترکیب بلوک‌های مختلف re2rust را در یک بلوک فراهم می‌سازد (مثال زیر را ببینید). .sp بلوک‌های نام‌دار و دستورالعمل درون‌بلوکی use در نگارش 2.2 به re2rust اضافه شدند. از آن نگارش به بعد، بلوک‌های با قابلیت استفاده مجدد به‌طور پیش‌فرض مجاز هستند (به گزینه خاصی نیاز نیست). پیش از نگارش 2.2، حالت استفاده مجدد با گزینه \fB\-r \-\-reusable\fP فعال می‌شد. پیش از نگارش 1.2، بلوک‌های با قابلیت استفاده مجدد نمی‌توانستند با بلوک‌های عادی ترکیب شوند. .SS مثالی از دستورالعمل \fB!use\fP .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C // re2rust $INPUT \-o $OUTPUT \-\-api simple // 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. #[derive(Debug, PartialEq)] enum Ans { Color, Fish, Dunno } /*!rules:re2c:colors * { panic!(\(dqah\(dq); } \(dqred\(dq | \(dqsalmon\(dq | \(dqmagenta\(dq { return Ans::Color; } */ /*!rules:re2c:fish * { panic!(\(dqoh\(dq); } \(dqhaddock\(dq | \(dqsalmon\(dq | \(dqeel\(dq { return Ans::Fish; } */ fn lex(yyinput: &[u8]) \-> Ans { assert!(yyinput.len() > 0); // expect nonempty input let (mut yycursor, mut yymarker) = (0, 0); /*!re2c re2c:yyfill:enable = 0; re2c:YYCTYPE = u8; !use:fish; !use:colors; * { return Ans::Dunno; } // overrides inherited \(aq*\(aq rules */ } fn main() { assert_eq!(lex(b\(dqsalmon\(dq), Ans::Fish); assert_eq!(lex(b\(dqwhat?\(dq), Ans::Dunno); } .ft P .fi .UNINDENT .UNINDENT.SS نمونه‌ای از یک بلوک \fB/*!use:re2c ... */\fP .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C // re2rust $INPUT \-o $OUTPUT \-\-input\-encoding utf8 \-\-api simple // 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 Some(yycursor); } * { return None; } */ fn lex_utf8(yyinput: &[u8]) \-> Option { assert!(yyinput.len() > 0); // expect nonempty input let (mut yycursor, mut yymarker) = (0, 0); /*!use:re2c re2c:encoding:utf8 = 1; re2c:YYCTYPE = u8; */ } fn lex_utf32(yyinput: &[u32]) \-> Option { assert!(yyinput.len() > 0); // expect nonempty input let (mut yycursor, mut yymarker) = (0, 0); /*!use:re2c re2c:encoding:utf32 = 1; re2c:YYCTYPE = u32; */ } fn main() { let s8 = vec![0xe2, 0x88, 0x80, 0x78, 0x20, 0xe2, 0x88, 0x83, 0x79]; assert_eq!(lex_utf8(&s8), Some(s8.len())); let s32 = vec![0x2200, 0x78, 0x20, 0x2203, 0x79]; assert_eq!(lex_utf32(&s32), Some(s32.len())); } .ft P .fi .UNINDENT .UNINDENT .SS استخراج زیرتطبیق (Submatch extraction) .sp ابزار re2rust دو گزینه برای استخراج زیرتطبیق دارد. .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 فعال می‌شوند. از نظر معنایی، برچسب‌ها نشانگرهای موقعیت هستند: آنها را می‌توان در هر کجای یک عبارت باقاعده درج کرد، و به موقعیت مربوطه (یا چندین موقعیت) در رشته ورودی متصل می‌شوند. \fIبرچسب‌های s (یا S\-tags)\fP به آخرین موقعیت تطبیق‌یافته متصل می‌شوند، و \fIبرچسب‌های m (یا m\-tags)\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 است. در این حالت، تمام زیرعبارت‌های درون پرانتز به عنوان گروه‌های گیرانداز در نظر گرفته می‌شوند، و می‌توان از علامت تعجب برای مشخص کردن گروه‌های غیرگیرانداز استفاده کرد: \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 باشد\&. برای تعریف \fBYYMAXNMATCH\fP از بلوک \fBmaxnmatch\fP استفاده کنید، ثابتی که برابر با بیشینه مقدار \fByynmatch\fP در میان تمام قواعد است. .TP .B \fBCaptvars\fP روش دیگر برای استفاده از گروه‌های گیرانداز، گزینه \fB\-\-captvars\fP یا پیکربندی \fBre2c:captvars = 1\fP است. تنها تفاوت با \fB\-\-captures\fP در نحوه ذخیره‌سازی نتایج زیرتطبیق توسط کد تولیدشده است: به جای \fByynmatch\fP و \fByypmatch\fP، ابزار re2rust متغیرهای \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 به حداقل رساندن بار اضافی (overhead) در استخراج زیرتطبیق است. در حالت نهایی، اگر هیچ برچسب یا گیراندازی در یک عبارت باقاعده وجود نداشته باشد، TDFA صرفاً یک DFA معمولی است. اگر تعداد برچسب‌ها متعادل باشد، بار اضافی به سختی قابل توجه خواهد بود. اتوماتای TDFA تولیدشده از تعدادی \fIمتغیر برچسب (tag variables)\fP استفاده می‌کند که مستقیماً به برچسب‌ها نگاشت نمی‌شوند: ممکن است یک متغیر واحد برای برچسب‌های متفاوتی استفاده شود، و یک برچسب ممکن است به چندین متغیر برای نگهداری تمام مقادیر ممکن خود نیاز داشته باشد. در نهایت ابهام رفع می‌شود، و برای هر برچسب تنها یک متغیر نهایی باقی می‌ماند. متغیرهای برچسب باید با استفاده از بلوک‌های \fBstags\fP یا \fBmtags\fP تعریف شوند. اگر وضعیت تحلیل‌گر لغوی ذخیره می‌شود، متغیرهای برچسب باید بخشی از آن باشند. آنها همچنین باید توسط \fBYYFILL\fP به‌روزرسانی شوند\&. .sp برچسب‌های S\-tag از عملیات‌های زیر پشتیبانی می‌کنند: .INDENT 0.0 .IP \(bu 2 ذخیره موقعیت ورودی در یک s\-tag: مقدار \fBt = YYCURSOR\fP با API اشاره‌گر C یا یک عملیات تعریف‌شده توسط کاربر \fBYYSTAGP(t)\fP با API عمومی (generic) .IP \(bu 2 ذخیره مقدار پیش‌فرض در یک s\-tag: مقدار \fBt = NULL\fP با API اشاره‌گر C یا یک عملیات تعریف‌شده توسط کاربر \fBYYSTAGN(t)\fP با API عمومی (generic) .IP \(bu 2 رونوشت از یک s\-tag به دیگری: \fBt1 = t2\fP .UNINDENT .sp برچسب‌های M\-tag از عملیات‌های زیر پشتیبانی می‌کنند: .INDENT 0.0 .IP \(bu 2 الحاق موقعیت ورودی به یک m\-tag: یک عملیات تعریف‌شده توسط کاربر \fBYYMTAGP(t)\fP با هر دو API پیش‌فرض و عمومی (generic) .IP \(bu 2 الحاق مقدار پیش‌فرض به یک m\-tag: یک عملیات تعریف‌شده توسط کاربر \fBYYMTAGN(t)\fP با هر دو API پیش‌فرض و عمومی (generic) .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ها برای تجزیه نسخه‌بندی معنایی متشکل از سه بخش عددی آورده شده است: major، minor و patch (بخش آخر اختیاری است). برای نمونه‌ای پیچیده‌تر که از \fBYYFILL\fP استفاده می‌کند، بخش‌های زیر را ببینید\&. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C // re2rust $INPUT \-o $OUTPUT \-\-api simple #[derive(Debug, PartialEq)] struct SemVer(u32, u32, u32); // version: (major, minor, patch) const NONE: usize = std::usize::MAX; fn s2n(str: &[u8]) \-> u32 { // convert a pre\-parsed string to a number let mut n = 0; for i in str { n = n * 10 + *i as u32 \- 48; } return n; } fn parse(yyinput: &[u8]) \-> Option { assert_eq!(yyinput.last(), Some(&0)); // expect null\-terminated input let (mut yycursor, mut yymarker) = (0, 0); // Final tag variables available in semantic action. /*!svars:re2c format = \(aq#[allow(unused_mut)]\enlet mut @@;\en\(aq; */ // Intermediate tag variables used by the lexer (must be autogenerated). /*!stags:re2c format = \(aqlet mut @@ = NONE;\(aq; */ /*!re2c re2c:YYCTYPE = u8; re2c:yyfill:enable = 0; re2c:tags = 1; num = [0\-9]+; @t1 num @t2 \(dq.\(dq @t3 num @t4 (\(dq.\(dq @t5 num)? [\ex00] { let major = s2n(&yyinput[t1..t2]); let minor = s2n(&yyinput[t3..t4]); let patch = if t5 != NONE {s2n(&yyinput[t5..yycursor \- 1])} else {0}; return Some(SemVer(major, minor, patch)); } * { return None; } */ } fn main() { assert_eq!(parse(b\(dq23.34\e0\(dq), Some(SemVer(23, 34, 0))); assert_eq!(parse(b\(dq1.2.99999\e0\(dq), Some(SemVer(1, 2, 99999))); assert_eq!(parse(b\(dq1.a\e0\(dq), None); } .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 // re2rust $INPUT \-o $OUTPUT use std::fs::File; use std::io::{Read, Write}; const BUFSIZE: usize = 4096; const NONE: usize = usize::MAX; struct State { file: File, yyinput: [u8; BUFSIZE], yylimit: usize, yycursor: usize, yymarker: usize, token: usize, // 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 = \(dq@@: usize,\en\(dq; */ eof: bool, } #[derive(PartialEq)] enum Fill { Ok, Eof, LongLexeme } #[derive(Debug, PartialEq)] struct SemVer(u32, u32, u32); // version: (major, minor, patch) fn s2n(str: &[u8]) \-> u32 { // convert a pre\-parsed string to a number let mut n = 0; for i in str { n = n * 10 + *i as u32 \- 48; } return n; } macro_rules! shift { // ignore overflow, marker and tags may not be set yet ($x:expr, $y:expr) => { $x = $x.overflowing_sub($y).0 } } fn fill(st: &mut State) \-> Fill { if st.eof { return Fill::Eof; } // Error: lexeme too long. In real life could reallocate a larger buffer. if st.token < 1 { return Fill::LongLexeme; } // Shift buffer contents (discard everything up to the current token). st.yyinput.copy_within(st.token..st.yylimit, 0); st.yylimit \-= st.token; st.yycursor \-= st.token; shift!(st.yymarker, st.token); // Tag variables need to be shifted like other input positions. The check // for NONE is only needed if some tags are nested inside of alternative or // repetition, so that they can have NONE value. /*!stags:re2c format = \(dqif st.@@ != NONE { shift!(st.@@, st.token); }\en\(dq; */ st.token = 0; // Fill free space at the end of buffer with new data from file. match st.file.read(&mut st.yyinput[st.yylimit..BUFSIZE \- 1]) { Ok(n) => { st.yylimit += n; st.eof = n == 0; st.yyinput[st.yylimit] = 0; } Err(why) => panic!(\(dqcannot read from file: {}\(dq, why) } return Fill::Ok; } fn parse(st: &mut State) \-> Option> { let mut vers = Vec::new(); // Final tag variables available in semantic action. /*!svars:re2c format = \(aqlet mut @@;\en\(aq; */ \(aqparse: loop { st.token = st.yycursor; /*!re2c re2c:api = record; re2c:eof = 0; re2c:tags = 1; re2c:yyrecord = st; re2c:YYCTYPE = u8; re2c:YYFILL = \(dqfill(st) == Fill::Ok\(dq; num = [0\-9]+; num @t1 \(dq.\(dq @t2 num @t3 (\(dq.\(dq @t4 num)? [\en] { let major = s2n(&st.yyinput[st.token..t1]); let minor = s2n(&st.yyinput[t2..t3]); let patch = if t4 != NONE {s2n(&st.yyinput[t4..st.yycursor \- 1])} else {0}; vers.push(SemVer(major, minor, patch)); continue \(aqparse; } $ { return Some(vers); } * { return None; } */ } } fn main() { let fname = \(dqinput\(dq; let verstr = b\(dq1.22.333\en\(dq; let expect = (0..BUFSIZE).map(|_| SemVer(1, 22, 333)).collect(); // Prepare input file (make sure it exceeds buffer size). match File::create(fname) { Err(why) => panic!(\(dqcannot open {}: {}\(dq, fname, why), Ok(mut file) => match file.write_all(&verstr.repeat(BUFSIZE)) { Err(why) => panic!(\(dqcannot write to {}: {}\(dq, fname, why), Ok(_) => {} } }; // Reopen input file for reading. let file = match File::open(fname) { Err(why) => panic!(\(dqcannot read file {}: {}\(dq, fname, why), Ok(file) => file, }; // Initialize lexer state. let yylimit = BUFSIZE \- 1; let mut st = State { file: file, yyinput: [0; BUFSIZE], // sentinel is set to zero, which triggers YYFILL yylimit: yylimit, yycursor: yylimit, yymarker: yylimit, token: yylimit, /*!stags:re2c format = \(dq@@: NONE,\en\(dq; */ eof: false, }; // Run the lexer and check results. assert_eq!(parse(&mut st), Some(expect)); // Cleanup: remove input file. match std::fs::remove_file(fname) { Err(why) => panic!(\(dqcannot remove {}: {}\(dq, fname, why), Ok(_) => {} } } .ft P .fi .UNINDENT .UNINDENT .sp در ادامه مثالی از به‌کارگیری گروه‌های تسخیر (capturing groups) برای تجزیهٔ نسخه‌بندی‌های معنایی آورده شده است. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C // re2rust $INPUT \-o $OUTPUT \-\-api simple #[derive(Debug, PartialEq)] struct SemVer(u32, u32, u32); // version: (major, minor, patch) const NONE: usize = std::usize::MAX; fn s2n(str: &[u8]) \-> u32 { // convert a pre\-parsed string to a number let mut n = 0; for i in str { n = n * 10 + *i as u32 \- 48; } return n; } fn parse(yyinput: &[u8]) \-> Option { assert_eq!(yyinput.last(), Some(&0)); // expect null\-terminated input let (mut yycursor, mut yymarker) = (0, 0); // Final tag variables available in semantic action. /*!stags:re2c format = \(aqlet mut @@ = NONE;\(aq; */ // Intermediate tag variables used by the lexer (must be autogenerated). /*!svars:re2c format = \(aq#[allow(unused_mut)]\enlet mut @@;\en\(aq; */ /*!re2c re2c:YYCTYPE = u8; re2c:yyfill:enable = 0; re2c:captvars = 1; num = [0\-9]+; (num) \(dq.\(dq (num) (\(dq.\(dq num)? [\ex00] { assert!(yytl0 == 0 && yytr0 == yyinput.len()); let major = s2n(&yyinput[yytl1..yytr1]); let minor = s2n(&yyinput[yytl2..yytr2]); let patch = if yytl3 == NONE {0} else {s2n(&yyinput[yytl3 + 1..yytr3])}; return Some(SemVer(major, minor, patch)); } * { return None; } */ } fn main() { assert_eq!(parse(b\(dq23.34\e0\(dq), Some(SemVer(23, 34, 0))); assert_eq!(parse(b\(dq1.2.99999\e0\(dq), Some(SemVer(1, 2, 99999))); assert_eq!(parse(b\(dq1.a\e0\(dq), None); } .ft P .fi .UNINDENT .UNINDENT.sp در اینجا مثالی از به‌کارگیری m\-tagها برای تجزیهٔ یک نگارش با تعداد متغیری از مؤلفه‌ها آورده شده است. متغیرهای برچسب در یک trie ذخیره می‌شوند. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C // re2rust $INPUT \-o $OUTPUT \-\-api simple const NONE: usize = std::usize::MAX; const MTAG_ROOT: usize = NONE \- 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). type MtagTrie = Vec::; struct MtagElem { elem: usize, // tag value pred: usize, // index of the predecessor node or root } // Append a single value to an m\-tag history. fn add_mtag(trie: &mut MtagTrie, mtag: usize, value: usize) \-> usize { trie.push(MtagElem{elem: value, pred: mtag}); return trie.len() \- 1; } // Recursively unwind tag histories and collect version components. fn unwind(trie: &MtagTrie, x: usize, y: usize, str: &[u8], ver: &mut Ver) { // Reached the root of the m\-tag tree, stop recursion. if x == MTAG_ROOT && y == MTAG_ROOT { return; } // Unwind history further. unwind(trie, trie[x].pred, trie[y].pred, str, ver); // Get tag values. Tag histories must have equal length. assert!(x != MTAG_ROOT && y != MTAG_ROOT); let (ex, ey) = (trie[x].elem, trie[y].elem); if ex != NONE && ey != NONE { // Both tags are valid string indices, extract component. ver.push(s2n(&str[ex..ey])); } else { // Both tags are NONE (this corresponds to zero repetitions). assert!(ex == NONE && ey == NONE); } } type Ver = Vec::; // unbounded number of version components fn s2n(str: &[u8]) \-> u32 { // convert a pre\-parsed string to a number let mut n = 0; for i in str { n = n * 10 + *i as u32 \- 48; } return n; } fn parse(yyinput: &[u8]) \-> Option { assert_eq!(yyinput.last(), Some(&0)); // expect null\-terminated input let (mut yycursor, mut yymarker) = (0, 0); let mut mt: MtagTrie = Vec::new(); // Final tag variables available in semantic action. /*!svars:re2c format = \(aqlet @@;\en\(aq; */ /*!mvars:re2c format = \(aqlet @@;\en\(aq; */ // Intermediate tag variables used by the lexer (must be autogenerated). /*!stags:re2c format = \(aqlet mut @@ = NONE;\(aq; */ /*!mtags:re2c format = \(aqlet mut @@ = MTAG_ROOT;\(aq; */ /*!re2c re2c:YYCTYPE = u8; re2c:YYMTAGP = \(dq@@ = add_mtag(&mut mt, @@, yycursor);\(dq; re2c:YYMTAGN = \(dq@@ = add_mtag(&mut mt, @@, NONE);\(dq; re2c:yyfill:enable = 0; re2c:tags = 1; num = [0\-9]+; @t1 num @t2 (\(dq.\(dq #t3 num #t4)* [\ex00] { let mut ver: Ver = Vec::new(); ver.push(s2n(&yyinput[t1..t2])); unwind(&mt, t3, t4, yyinput, &mut ver); return Some(ver); } * { return None; } */ } fn main() { assert_eq!(parse(b\(dq1\e0\(dq), Some(vec![1])); assert_eq!(parse(b\(dq1.2.3.4.5.6.7\e0\(dq), Some(vec![1, 2, 3, 4, 5, 6, 7])); assert_eq!(parse(b\(dq1.2.\e0\(dq), None); } .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ها تعریف می‌شوند. هنگامی که re2rust عبارت‌های منظم را به ماشین‌های خودکار (automata) کامپایل می‌کند، 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 تعاریف re2rust را برای بلوک‌ها، دسته‌ها و ویژگی‌های شرح‌داده‌شده در استاندارد Unicode ارائه می‌دهند. .sp گزینهٔ \fB\-\-input\-encoding\fP کدگذاری فایل منبع را مشخص می‌کند که می‌تواند برای فعال کردن لیترال‌های یونیکد در عبارت‌های منظم به کار رود. برای مثال \fB\-\-input\-encoding utf8\fP به re2rust اعلام می‌کند که فایل منبع با قالب UTF8 است (با \fB\-\-utf8\fP که کدگذاری متن ورودی را مشخص می‌کند تفاوت دارد). گزینهٔ \fB\-\-encoding\-policy\fP شیوهٔ مدیریت نویسه‌های جانشین یونیکد (Unicode surrogates؛ code pointها در بازهٔ \fB[0xD800\-0xDFFF]\fP) توسط re2rust را تعیین می‌کند. .sp در زیر نمونه‌ای از یک تحلیل‌گر لغوی برای شناسه‌های یونیکد کدگذاری‌شده با UTF8 آمده است. .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C // re2rust $INPUT \-o $OUTPUT \-\-utf8 \-\-api simple /*!include:re2c \(dqunicode_categories.re\(dq */ fn lex(yyinput: &[u8]) \-> bool { assert_eq!(yyinput.last(), Some(&0)); // expect null\-terminated input let (mut yycursor, mut yymarker) = (0, 0); /*!re2c re2c:YYCTYPE = u8; 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 true; } * { return false; } */ } fn main() { assert!(lex(\(dq_Ыдентификатор\e0\(dq.as_bytes())); } .ft P .fi .UNINDENT .UNINDENT.SS فایل‌های ضمیمه (Include files) .sp ابزار re2rust به شما امکان می‌دهد تا فایل‌های دیگر را با استفاده از بلوکی به قالب \fB/*!include:re2c FILE */\fP یا \fB%{include FILE %}\fP، یا یک دستور درون‌بلوکی \fB!include FILE ;\fP ضمیمه کنید، که در آن \fBFILE\fP مسیر فایل مورد نظر برای ضمیمه شدن است. re2rust فایل‌های include را در دایرکتوری فایلی که عمل ضمیمه‌سازی را انجام می‌دهد و همچنین در مکان‌های include که با گزینهٔ \fB\-I\fP مشخص می‌شوند، جستجو می‌کند. بلوک‌ها/دستورهای include در re2rust دقیقاً مانند \fB#include\fP در C/C++ عمل می‌کنند: محتوای \fBFILE\fP عیناً در محل بلوک/دستور جای‌گذاری می‌شود. فایل‌های include ممکن است خود دارای includeهای بیشتری باشند. برای ردیابی وابستگی‌های ساخت فایل خروجی به فایل‌های include، از گزینهٔ \fB\-\-depfile\fP استفاده کنید. ابزار re2rust تعدادی فایل include از پیش تعریف‌شده ارائه می‌دهد که در زیردایرکتوری \fBinclude/\fP پروژه قابل دسترسی هستند. این فایل‌ها شامل تعاریفی هستند که ممکن است برای پروژه‌های دیگر مفید باشند (مانند دسته‌بندی‌های یونیکد) و چیزی شبیه به یک کتابخانهٔ استاندارد برای re2rust\& تشکیل می‌دهند. در ادامه مثالی از به‌کارگیری فایل‌های include آورده شده است. .SS فایل ضمیمه ۱ (definitions.rs) .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C #[derive(Debug, PartialEq)] enum Num { Int, Float, NaN } /*!re2c number = [1\-9][0\-9]*; */ .ft P .fi .UNINDENT .UNINDENT .SS فایل ضمیمه ۲ (extra_rules.re.inc) .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C // floating\-point numbers frac = [0\-9]* \(dq.\(dq [0\-9]+ | [0\-9]+ \(dq.\(dq; exp = \(aqe\(aq [+\-]? [0\-9]+; float = frac exp? | [0\-9]+ exp; float { return Num::Float; } .ft P .fi .UNINDENT .UNINDENT .SS فایل ورودی (Input file) .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C // re2rust $INPUT \-o $OUTPUT \-\-api simple /*!include:re2c \(dqdefinitions.rs\(dq */ fn lex(yyinput: &[u8]) \-> Num { assert_eq!(yyinput.last(), Some(&0)); // expect null\-terminated input let mut yycursor = 0; let mut yymarker = 0; /*!re2c re2c:yyfill:enable = 0; re2c:YYCTYPE = u8; * { return Num::NaN; } number { return Num::Int; } !include \(dqextra_rules.re.inc\(dq; */ } fn main() { assert_eq!(lex(b\(dq123\e0\(dq), Num::Int); assert_eq!(lex(b\(dq123.4567\e0\(dq), Num::Float); } .ft P .fi .UNINDENT .UNINDENT.SS "فایل‌های سرآیند (Header files)" .sp ابزار re2rust این امکان را فراهم می‌کند که با استفاده از گزینهٔ \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 فایل سرآیند تولید شود\&. نخستین بلوک نشان‌دهندهٔ آغاز فایل سرآیند و دومین بلوک نشان‌دهندهٔ پایان آن است. هر آنچه میان این بلوک‌ها قرار گیرد توسط re2rust پردازش شده و کد تولیدشده در فایلی که با گزینهٔ \fB\-\-header\fP یا پیکربندی \fBre2c:header\fP مشخص شده است (یا در صورت عدم استفاده از گزینه یا پیکربندی، در \fBstdout\fP) نوشته می‌شود. فایل سرآیند خودکار تولیدشده ممکن است در مواردی نیاز باشد که از re2rust برای تولید تعاریفی استفاده می‌شود که باید از سایر واحدهای ترجمه (translation units) قابل مشاهده باشند. .sp در اینجا مثالی از تولید یک فایل سرآیند آورده شده است که شامل تعریف وضعیت تحلیل‌گر لغوی (lexer state) با متغیرهای برچسب (tag variables) است (تعداد متغیرها به گرامر منظم وابسته است و برای برنامه‌نویس مشخص نیست). .SS "فایل ورودی (Input file)" .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C // re2rust $INPUT \-o $OUTPUT \-\-header lexer/state.rs mod lexer; use lexer::state::State; // the module is generated by re2c /*!header:re2c:on*/ pub struct State<\(aqa> { pub yyinput: &\(aqa [u8], pub yycursor: usize, /*!stags:re2c format = \(dqpub @@: usize,\(dq; */ } /*!header:re2c:off*/ fn lex(yyrecord: &mut State) \-> usize { assert_eq!(yyrecord.yyinput.last(), Some(&0)); // expect null\-terminated input let t: usize; /*!re2c re2c:header = \(dqlexer/state.rs\(dq; re2c:yyfill:enable = 0; re2c:api = record; re2c:YYCTYPE = \(dqu8\(dq; re2c:tags = 1; [a]* @t [b]* { return t; } */ } fn main() { let mut st = State { yyinput: b\(dqab\e0\(dq, yycursor: 0, /*!stags:re2c format = \(dq@@: 0,\(dq; */ }; assert_eq!(lex(&mut st), 1); } .ft P .fi .UNINDENT .UNINDENT .SS "فایل سرآیند (Header file)" .INDENT 0.0 .INDENT 3.5 .sp .nf .ft C /* Generated by re2c */ pub struct State<\(aqa> { pub yyinput: &\(aqa [u8], pub yycursor: usize, pub yyt1: usize, } .ft P .fi .UNINDENT .UNINDENT.SS "برنامه‌های اسکلت (Skeleton programs)" .sp با گزینهٔ \fB\-S, \-\-skeleton\fP، ابزار re2rust تمامی کدهای غیر re2rust را نادیده گرفته و یک برنامهٔ مستقل به زبان C تولید می‌کند که می‌تواند در ادامه کامپایل و اجرا شود. این برنامه از کد تحلیل‌گر لغوی و داده‌های ورودی تشکیل شده است. به ازای هر DFA ساخته‌شده (بلوک یا شرط)، re2rust یک تحلیل‌گر لغوی مستقل و دو فایل تولید می‌کند: یک فایل \fB\&.input\fP حاوی رشته‌های مشتق‌شده از DFA، و یک فایل \fB\&.keys\fP حاوی نتایج تطابق مورد انتظار. این برنامه هر تحلیل‌گر لغوی را روی فایل \fB\&.input\fP متناظر اجرا کرده و نتایج را با مقادیر مورد انتظار مقایسه می‌کند. برنامه‌های اسکلت به دلایل متعددی بسیار مفید هستند: .INDENT 0.0 .IP \(bu 2 می‌توانند درستی بهینه‌سازی‌های گوناگون re2rust را بررسی کنند (داده‌ها در مراحل ابتدایی فرآیند و پیش از اعمال هرگونه تبدیل روی DFA تولید می‌شوند). .IP \(bu 2 تولید مجموعه‌ای از داده‌های ورودی با پوشش مناسب می‌تواند هم برای آزمودن و هم برای محک‌زنی مفید باشد. .IP \(bu 2 تولید برنامه‌های اجرایی مستقل این امکان را فراهم می‌سازد که به نمونه‌های آزمون کمینه (minimized test cases) دسترسی پیدا کرد (چرا که کد اصلی ممکن است حجیم بوده یا وابستگی‌های فراوانی داشته باشد). .UNINDENT .sp دشواری تولید داده‌های ورودی در این است که به جز در ساده‌ترین حالات، تعداد رشته‌های ورودی ممکن بیش از حد زیاد است (حتی اگر طول رشته محدود باشد). re2rust این مشکل را با تولید رشته‌های کافی برای پوشش تقریباً تمامی گذارهای DFA حل می‌کند. این ابزار از الگوریتم زیر استفاده می‌کند: نخست، یک اسکلت از DFA می‌سازد. برای رمزگذاری‌هایی با اندازهٔ واحد کد ۱ بایتی (مانند ASCII، UTF\-8 و EBCDIC)، این اسکلت صرفاً یک رونوشت دقیق از DFA اصلی است. برای رمزگذاری‌هایی با واحدهای کد چندبایتی، اسکلت یک رونوشت از DFA است که برخی از گذارها در آن حذف شده‌اند؛ بدین صورت که re2rust برای هر بازهٔ پیوسته و مجزا که با یک گذار DFA مطابقت دارد، حداکثر ۲۵۶ واحد کد را برمی‌گزیند. مقادیر انتخاب‌شده به طور یکنواخت توزیع شده و شامل کران‌های بازه نیز هستند. re2rust به جای تلاش برای پوشش دادن همهٔ مسیرهای ممکن در اسکلت (که کاری ناممکن است)، به اندازهٔ کافی مسیر تولید می‌کند تا تمامی گذارهای اسکلت را پوشش دهد، و بدین ترتیب پرش‌های شرطی متناظر را در تحلیل‌گر لغوی فعال می‌سازد. پیاده‌سازی این الگوریتم به حدود ۱ گیگابایت گذار محدود شده و مقدار ثابتی از حافظه را مصرف می‌کند (re2rust داده‌ها را به محض تولید، در فایل می‌نویسد). .SS "بصری‌سازی و اشکال‌زدایی (Visualization and debug)" .sp با گزینهٔ \fB\-D, \-\-emit\-dot\fP، ابزار re2rust هیچ کدی تولید نمی‌کند؛ در عوض، 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 ابزار re2rust در ابتدا توسط 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. .