RE2SWIFT(1) RE2SWIFT(1) نام (NAME) re2swift - تولید تحلیل‌گرهای لغوی سریع برای Swift خلاصه دستور (SYNOPSIS) re2swift [ OPTIONS ] [ WARNINGS ] INPUT ورودی می‌تواند یک فایل یا - برای stdin باشد. مقدمه (INTRODUCTION) ابزار re2swift به عنوان یک پیش‌پردازنده عمل می‌کند. این ابزار فایل ورودی را (که معمولاً برنامه‌ای به زبان Swift است، اما می‌تواند هر چیز دیگری نیز باشد) خوانده و به دنبال بلوک‌های کدی می‌گردد که درون نشانگرهای آغاز/پایان با ساختار ویژه محصور شده‌اند. متن خارج از این بلوک‌ها عیناً در فایل خروجی کپی می‌شود. محتوای درون بلوک‌ها توسط re2swift پردازش می‌شود؛ این ابزار آن‌ها را به کد زبان Swift ترجمه کرده و کد تولیدشده را به جای آن بلوک در خروجی قرار می‌دهد. در اینجا مثالی از یک برنامه کوچک آورده شده است که بررسی می‌کند آیا یک رشته داده‌شده حاوی یک عدد ده‌دهی است یا خیر: // re2swift $INPUT -o $OUTPUT -i func lex(_ yyinput: UnsafePointer) -> Bool { var yycursor = 0 /*!re2c re2c:yyfill:enable = 0; [1-9][0-9]* { return true } * { return false } */ } assert(lex("1234")) در خروجی، re2swift بلوک میانی را با کد تولیدشده جایگزین کرده است: /* Generated by re2swift */ // re2swift $INPUT -o $OUTPUT -i func lex(_ yyinput: UnsafePointer) -> Bool { var yycursor = 0 var yych: UInt8 = 0 var yystate: UInt = 0 yyl: while true { switch yystate { case 0: yych = yyinput[yycursor] yycursor += 1 switch yych { case 0x31...0x39: yystate = 2 continue yyl default: yystate = 1 continue yyl } case 1: return false case 2: yych = yyinput[yycursor] switch yych { case 0x30...0x39: yycursor += 1 yystate = 2 continue yyl default: yystate = 3 continue yyl } case 3: return true default: fatalError("internal lexer error") } } } assert(lex("1234")) یک برنامه re2swift از دنباله‌ای از بلوک‌ها درآمیخته با کد به زبان مقصد تشکیل می‌شود. یک بلوک ممکن است شامل تعاریف، پیکربندی‌ها، قواعد، کنش‌ها و دستورالعمل‌ها به هر ترتیبی باشد: name = regular-expression ; یک تعریف، name را به regular-expression مقید می‌سازد. نام‌ها می‌توانند شامل نویسه‌های الفبایی-عددی و زیرخط باشند. بخش regular expressions مروری کلی بر نحو re2swift برای عبارت‌های منظم ارائه می‌دهد. پس از تعریف، می‌توان از name در سایر عبارت‌های منظم و قواعد استفاده کرد. بازگشت در تعاریف نام‌گذاری‌شده مجاز نیست و هر نام باید پیش از استفاده تعریف شود. یک بلوک، تعاریف نام‌گذاری‌شده را از حوزه سراسری (global scope) به ارث می‌برد. بازتعریف نامی که در حوزه کنونی وجود دارد یک خطا محسوب می‌شود. configuration = value ; یک پیکربندی امکان تغییر رفتار re2swift و سفارشی‌سازی کد تولیدشده را فراهم می‌کند. برای مشاهده فهرست کامل پیکربندی‌های پشتیبانی‌شده توسط re2swift، بخش configurations را ببینید. بسته به یک پیکربندی خاص، value می‌تواند یک کلمه کلیدی، یک عدد صحیح غیرمنفی یا یک رشته تک‌خطی باشد که در صورت عدم تشکیل از نویسه‌های الفبایی-عددی، باید در نقل‌قول تکی یا دوگانه قرار گیرد. یک بلوک، پیکربندی‌ها را از حوزه سراسری به ارث می‌برد و می‌تواند آن‌ها را بازتعریف کرده یا موارد جدیدی بیفزاید. پیکربندی‌های تعریف‌شده درون یک بلوک، بر کل بلوک تأثیر می‌گذارند، حتی اگر در انتهای آن ظاهر شوند. regular-expression code یک قاعده، regular-expression را به کنش معنایی آن پیوند می‌دهد (یک بلوک کد درون آکوالاد، یا بلوکی از کد که با := شروع شده و در یک خط جدیدِ پس از آن با هر نویسه‌ای غیر از فضای خالی پایان می‌یابد). اگر regular-expression مطابقت پیدا کند، code مرتبط اجرا می‌شود. اگر چندین قاعده مطابقت داشته باشند، طولانی‌ترین تطابق اولویت دارد. اگر چندین قاعده با رشته یکسانی تطابق پیدا کنند، اولین قاعده اولویت دارد. دو قاعده ویژه وجود دارد: قاعده پیش‌فرض * و قاعده پایان ورودی $. قاعده پیش‌فرض همواره باید تعریف شود، صرف‌نظر از جایگاهش در بلوک دارای کمترین اولویت است، و با هر واحد کد (code unit) مطابقت می‌یابد (نه لزوماً یک نویسه معتبر، بخش encoding support را ببینید). در صورت استفاده از روش متناظر برای handling the end of input، قاعده پایان ورودی باید تعریف شود. همراه با start conditions قواعد نحو پیچیده‌تری خواهند داشت. !action code یک کنش، بلوک کدی (code) تعریف‌شده توسط کاربر را به نقطه مشخصی در ماشین حالت متناهی تولیدشده متصل می‌کند (همان‌طور که کنش‌های معنایی کد را به حالت‌های پایانی پیوند می‌دهند). برای فهرست کاملی از کنش‌های از پیش‌تعریف‌شده، بخش actions را ببینید. !directive ; یک دستورالعمل یکی از گزاره‌های ویژه از پیش‌تعریف‌شده است. هر دستورالعمل هدف منحصربه‌فردی دارد. برای جزئیات بخش directives را ببینید. بلوک‌ها (Blocks) نشانگرهای شروع و پایان بلوک یا /*!re2c و */ هستند، یا %{ و %} (از هر دو شیوه پشتیبانی می‌شود). از نسخه 2.2 به بعد، بلوک‌ها می‌توانند نام‌های اختیاری داشته باشند که امکان ارجاع به آن‌ها را در سایر بلوک‌ها فراهم می‌کند. انواع مختلفی از بلوک‌ها وجود دارند: /*!re2c[:] ... */ or %{[:] ... %} یک بلوک سراسری حاوی تعاریف، پیکربندی‌ها، قواعد و دستورالعمل‌ها است. re2swift عبارت‌های منظم مرتبط با هر قاعده را در یک اتوماتای متناهی معین کامپایل کرده، آن را به شکل پرش‌های شرطی در زبان مقصد کدگذاری می‌کند و بلوک را با کد تولیدشده جایگزین می‌سازد. نام‌ها و پیکربندی‌های تعریف‌شده در یک بلوک سراسری به حوزه سراسری اضافه می‌شوند و برای بلوک‌های پس از آن قابل مشاهده خواهند بود. در آغاز برنامه، حوزه سراسری با options خط فرمان مقداردهی اولیه می‌شود. /*!local:re2c[:] ... */ or %{local[:] ... %} یک بلوک محلی شبیه بلوک سراسری است، اما نام‌ها و پیکربندی‌های موجود در آن حوزه محلی دارند (بر سایر بلوک‌ها تأثیری نمی‌گذارند). /*!rules:re2c[:] ... */ or %{rules[:] ... %} یک بلوک قواعد مانند یک بلوک محلی است، اما خودش کدی تولید نمی‌کند و هیچ تعریفی را هم به حوزه سراسری اضافه نمی‌نماید -- هدف آن، استفاده مجدد در سایر بلوک‌ها است. این روشی برای اشتراک‌گذاری کد است (جزئیات بیشتر در بخش reusable blocks). پیش از نسخه 2.2 از re2swift، بلوک‌های قواعد نیازمند گزینه -r --reusable بودند. /*!use:re2c[:] ... */ or %{use[:] ... %} یک بلوک use که به یک بلوک قواعد از پیش تعریف‌شده ارجاع می‌دهد. اگر نام مشخص شده باشد، re2swift به دنبال بلوک قواعدی با این نام می‌گردد. در غیر این صورت، از تازه‌ترین بلوک قواعد (چه نام‌دار یا بی‌نام) استفاده می‌شود. یک بلوک use می‌تواند تعاریف، پیکربندی‌ها و قواعد مختص به خود را اضافه کند، که این موارد به بلوک قواعد ارجاع‌شده اضافه می‌شوند. پیش از نسخه 2.2 از re2swift، بلوک‌های use نیازمند گزینه -r --reusable بودند. /*!max:re2c[:[:...]] ... */ or %{max[:[:...]] ... %} بلوکی که تعریف YYMAXFILL را تولید می‌کند. یک فهرست اختیاری از نام‌های بلوک مشخص می‌کند که هنگام محاسبه مقدار YYMAXFILL کدام بلوک‌ها باید لحاظ شوند (اگر فهرست خالی باشد، تمام بلوک‌ها لحاظ می‌شوند). به طور پیش‌فرض، کد تولیدشده یک تعریف ماکرو برای C (#define YYMAXFILL ) یا یک متغیر سراسری برای Go (var YYMAXFILL int = ) است. این بخش را می‌توان با پیکربندی اختیاری format سفارشی کرد که یک رشته الگو را مشخص می‌کند که در آن @@{max} (یا به اختصار @@) با مقدار عددی YYMAXFILL جایگزین می‌شود. /*!maxnmatch:re2c[:[:...]] ... */ or %{maxnmatch[:[:...]] ... %} بلوکی که تعریف YYMAXNMATCH را تولید می‌کند (نیازمند گزینه -P --posix-captures است). یک فهرست اختیاری از نام‌های بلوک مشخص می‌کند که هنگام محاسبه مقدار YYMAXNMATCH کدام بلوک‌ها باید لحاظ شوند (اگر فهرست خالی باشد، همه بلوک‌ها لحاظ می‌شوند). به طور پیش‌فرض، کد تولیدشده یک تعریف ماکرو برای C (#define YYMAXNMATCH ) یا یک متغیر سراسری برای Go (var YYMAXNMATCH int = ) است. این بخش را می‌توان با پیکربندی اختیاری format سفارشی کرد که یک رشته الگو را مشخص می‌کند که در آن @@{max} (یا به اختصار @@) با مقدار عددی YYMAXNMATCH جایگزین می‌شود. /*!stags:re2c[:[:...]] ... */, /*!mtags:re2c[:[:...]] ... */ or %{stags[:[:...]] ... %}, %{mtags[:[:...]] ... %{ بلوک‌هایی که قطعه کدی از نوع الگو را تعیین می‌کنند که برای هر متغیر s-tag/m-tag تولیدشده توسط re2swift بسط می‌یابد. یک فهرست اختیاری از نام‌های بلوک مشخص می‌کند که هنگام محاسبه مجموعه متغیرهای برچسب کدام بلوک‌ها باید لحاظ شوند (اگر فهرست خالی باشد، همه بلوک‌ها لحاظ می‌شوند). دو پیکربندی اختیاری وجود دارد: format و separator. پیکربندی format یک رشته الگو را مشخص می‌کند که در آن @@{tag} (یا به اختصار @@) با نام هر متغیر برچسب جایگزین می‌شود. پیکربندی separator قطعه کدی را مشخص می‌کند که برای متصل کردن قطعات format تولیدشده برای متغیرهای برچسب مختلف به کار می‌رود. /*!svars:re2c[:[:...]] ... */, /*!mvars:re2c[:[:...]] ... */ or %{svars[:[:...]] ... %}, %{mvars[:[:...]] ... %{ بلوک‌هایی که قطعه کدی از نوع الگو را تعیین می‌کنند که برای هر s-tag/m-tag که یا صراحتاً توسط قواعد مشخص شده است (با گزینه --tags) یا به طور ضمنی توسط re2swift ایجاد شده است (با گزینه‌های --captvars یا --posix-captvars) بسط می‌یابد. یک فهرست اختیاری از نام‌های بلوک مشخص می‌کند که هنگام محاسبه مجموعه برچسب‌ها کدام بلوک‌ها باید لحاظ شوند (اگر فهرست خالی باشد، تمام بلوک‌ها لحاظ می‌شوند). دو پیکربندی اختیاری وجود دارد: format و separator. پیکربندی format یک رشته الگو را مشخص می‌کند که در آن @@{tag} (یا به اختصار @@) با نام هر برچسب جایگزین می‌شود. پیکربندی separator قطعه کدی را مشخص می‌کند که برای متصل کردن قطعات format تولیدشده برای برچسب‌های مختلف به کار می‌رود. /*!getstate:re2c[:[:...]] ... */ or %{getstate[:[:...]] ... %} بلوکی که یک توزیع شرطی بر روی وضعیت lexer تولید می‌کند (نیازمند گزینه --storable-state است). یک فهرست اختیاری از نام‌های بلوک مشخص می‌کند که کدام بلوک‌ها باید در توزیع وضعیت گنجانده شوند. گذار پیش‌فرض به برچسب آغازین اولین بلوک در فهرست انجام می‌شود. اگر فهرست خالی باشد، همه بلوک‌ها لحاظ می‌شوند و گذار پیش‌فرض به اولین بلوک در فایل که دارای برچسب آغازین است انجام می‌پذیرد. این نوع بلوک با گزینه --loop-switch ناسازگار است، زیرا نیازمند گذارهای بین‌بلوکی است که بدون goto یا فراخوانی‌های تابع پشتیبانی نمی‌شوند. /*!conditions:re2c[:[:...]] ... */, /*!types:re2c... */ or %{conditions[:[:...]] ... %}, %{types... %} بلوکی که شمارش شرایط (condition enumeration) را تولید می‌کند (نیازمند گزینه --conditions است). یک فهرست اختیاری از نام‌های بلوک مشخص می‌کند که هنگام محاسبه مجموعه شرایط، کدام بلوک‌ها باید لحاظ شوند (اگر فهرست خالی باشد، تمام بلوک‌ها لحاظ می‌شوند). به طور پیش‌فرض، کد تولیدشده یک شمارش YYCONDTYPE است. این بخش می‌تواند با پیکربندی‌های اختیاری format و separator سفارشی‌سازی شود. پیکربندی format یک رشته الگو را مشخص می‌کند که در آن @@{cond} (یا به اختصار @@) با نام هر شرط، و @@{num} با نمایه عددی آن شرط جایگزین می‌شود. پیکربندی separator قطعه کدی را مشخص می‌کند که برای متصل کردن قطعات format تولیدشده برای شرایط مختلف به کار می‌رود. /*!include:re2c */ or %{include %} این بلوک به فرد اجازه می‌دهد را درج کند، که باید یک مسیر فایل درون نقل‌قول دوگانه باشد. محتویات فایل به صورت عین‌به‌عین به جای این بلوک جایگزین می‌شود، درست همان‌گونه که #include در C/C++ عمل می‌کند. این بلوک می‌تواند به همراه گزینه --depfile برای تولید وابستگی‌های سیستم ساخت به فایل‌های درج‌شده استفاده شود. /*!header:re2c:on*/ or %{header:on %} این بلوک نقطه آغاز فایل سرآیند (header) را علامت‌گذاری می‌کند. همه‌چیز پس از آن تا بلوک header:off بعدی توسط re2swift پردازش شده و در فایل سرآیند مشخص‌شده با گزینه -t --type-header نوشته می‌شود. /*!header:re2c:off*/ or %{header:off %} این بلوک پایان فایل سرآیندی که با بلوک header:on*/ آغاز شده بود را علامت‌گذاری می‌کند. /*!ignore:re2c ... */ or %{ignore ... %} بلوکی که محتویات آن نادیده گرفته شده و از فایل خروجی حذف می‌شود. در اینجا فهرست کاملی از پیکربندی‌های پشتیبانی‌شده توسط re2swift آمده است: re2c:api, re2c:input همانند گزینهٔ --api است. re2c:api:sigil نشانه ("sigil") مورد استفاده برای جای‌نگهدارهای آرگومان در ساختارهای اولیهٔ API را مشخص می‌کند. مقدار پیش‌فرض @@ است. یک جای‌نگهدار با sigil شروع شده و به دنبال آن نام آرگومان درون دو آکولاد قرار می‌گیرد. برای مثال، اگر sigil روی $ تنظیم شود، جای‌نگهدارها به شکل ${name} خواهند بود. APIهای تک‌آرگومانی می‌توانند از نمادگذاری مختصر بدون نام درون آکولادها استفاده کنند. این گزینه می‌تواند با گزینه‌های مختص به هر یک از ساختارهای اولیهٔ API بازنویسی شود، مانند re2c:YYFILL@len برای YYFILL. re2c:api:style سبک API را تعیین می‌کند. مقادیر ممکن عبارتند از functions (پیش‌فرض برای C) و free-form (پیش‌فرض برای Go و Rust). در سبک functions ساختارهای اولیهٔ API همراه با فهرست آرگومان‌ها درون پرانتز به دنبال نام ساختار اولیه تولید می‌شوند. آرگومان‌ها تنها برای پارامترهای خودکار تولیدشده فراهم می‌شوند (مانند تعداد نویسه‌های ارسالی به YYFILL)، و نه برای زمینهٔ کلی تحلیل‌گر لغوی، از این رو ساختارهای اولیه بیشتر شبیه ماکروها در C/C++ یا بستارها در Go و Rust عمل می‌کنند. در سبک free-form ساختارهای اولیهٔ API شکل ثابتی ندارند: آن‌ها باید به صورت رشته‌هایی شامل قطعه‌کدهای آزاد با متغیرهای جایگزین‌شده به فرم @@{var} یا @@ تعریف شوند (که متناظر با آرگومان‌ها در سبک تابع‌گونه هستند). این پیکربندی ممکن است برای هر ساختار اولیهٔ API به صورت مجزا بازنویسی شود؛ برای نمونه پیکربندی re2c:YYFILL:naked را برای YYFILL ببینید. re2c:bit-vectors, re2c:flags:bit-vectors, re2c:flags:b همانند گزینهٔ --bit-vectors است، اما می‌تواند بر پایهٔ هر بلوک پیکربندی شود. re2c:captures, re2c:leftmost-captures همانند گزینهٔ --leftmost-captures است، اما می‌تواند بر پایهٔ هر بلوک پیکربندی شود. re2c:captvars, re2c:leftmost-captvars همانند گزینهٔ --leftmost-captvars است، اما می‌تواند بر پایهٔ هر بلوک پیکربندی شود. re2c:case-insensitive, re2c:flags:case-insensitive همانند گزینهٔ --case-insensitive است، اما می‌تواند بر پایهٔ هر بلوک پیکربندی شود. re2c:case-inverted, re2c:flags:case-inverted همانند گزینهٔ --case-inverted است، اما می‌تواند بر پایهٔ هر بلوک پیکربندی شود. re2c:case-ranges, re2c:flags:case-ranges همانند گزینهٔ --case-ranges است، اما می‌تواند بر پایهٔ هر بلوک پیکربندی شود. re2c:computed-gotos, re2c:flags:computed-gotos, re2c:flags:g همانند گزینهٔ --computed-gotos است، اما می‌تواند بر پایهٔ هر بلوک پیکربندی شود. re2c:computed-gotos:relative, re2c:cgoto:relative همانند گزینهٔ --computed-gotos-relative است، اما می‌تواند بر پایهٔ هر بلوک پیکربندی شود. re2c:computed-gotos:threshold, re2c:cgoto:threshold در صورت استفاده از goto محاسباتی، این پیکربندی آستانهٔ پیچیدگی‌ای را مشخص می‌کند که باعث تولید جدول‌های پرش به‌جای دستورهای تودرتوی if و نگاشت‌های بیتی می‌شود. مقدار پیش‌فرض 9 است. re2c:cond:abort اگر روی یک مقدار عددی صحیح مثبت تنظیم شود، حالت پیش‌فرض در هدایت‌گر وضعیتِ تولیدشده اجرای برنامه را متوقف می‌کند. re2c:cond:goto قطعه‌کدی را مشخص می‌کند که برای قواعد میان‌بر خودکار تولیدشدهٔ :=> در شرط‌ها استفاده می‌شود. پیش‌فرض goto @@; است. جای‌نگهدار @@ با نام شرط جایگزین می‌شود (پیکربندی‌های re2c:api:sigil و re2c:cond:goto@cond را ببینید). re2c:cond:goto@cond نشانهٔ مورد استفاده برای جایگزینی آرگومان در تعریف re2c:cond:goto را مشخص می‌کند. مقدار پیش‌فرض @@ است. پیکربندی عمومی‌تر re2c:api:sigil را بازنویسی می‌کند. re2c:cond:divider جداکنندهٔ بلوک‌های شرط را تعریف می‌کند. مقدار پیش‌فرض /* *********************************** */ است. جای‌نگهدارها با نام شرط جایگزین می‌شوند (پیکربندی‌های re2c:api;sigil و re2c:cond:divider@cond را ببینید). re2c:cond:divider@cond نشانهٔ مورد استفاده برای جایگزینی آرگومان در تعریف re2c:cond:divider را مشخص می‌کند. مقدار پیش‌فرض @@ است. پیکربندی عمومی‌تر re2c:api:sigil را بازنویسی می‌کند. re2c:cond:prefix, re2c:condprefix پیشوند مورد استفاده برای برچسب‌های شرط را مشخص می‌کند. پیش‌فرض yyc_ است. re2c:cond:enumprefix, re2c:condenumprefix پیشوند مورد استفاده برای شناسه‌های شرط را مشخص می‌کند. پیش‌فرض yyc است. re2c:debug-output, re2c:flags:debug-output, re2c:flags:d همانند گزینهٔ --debug-output است، اما می‌تواند بر پایهٔ هر بلوک پیکربندی شود. re2c:empty-class, re2c:flags:empty-class همانند گزینهٔ --empty-class است، اما می‌تواند بر پایهٔ هر بلوک پیکربندی شود. re2c:encoding:ebcdic, re2c:flags:ecb, re2c:flags:e همانند گزینهٔ --ebcdic است، اما می‌تواند بر پایهٔ هر بلوک پیکربندی شود. re2c:encoding:ucs2, re2c:flags:wide-chars, re2c:flags:w همانند گزینهٔ --ucs2 است، اما می‌تواند بر پایهٔ هر بلوک پیکربندی شود. re2c:encoding:utf8, re2c:flags:utf-8, re2c:flags:8 همانند گزینهٔ --utf8 است، اما می‌تواند بر پایهٔ هر بلوک پیکربندی شود. re2c:encoding:utf16, re2c:flags:utf-16, re2c:flags:x همانند گزینهٔ --utf16 است، اما می‌تواند بر پایهٔ هر بلوک پیکربندی شود. re2c:encoding:utf32, re2c:flags:unicode, re2c:flags:u همانند گزینهٔ --utf32 است، اما می‌تواند بر پایهٔ هر بلوک پیکربندی شود. re2c:encoding-policy, re2c:flags:encoding-policy همانند گزینهٔ --encoding-policy است، اما می‌تواند بر پایهٔ هر بلوک پیکربندی شود. re2c:eof نماد نگهبان مورد استفاده با قاعدهٔ پایان ورودی $ را مشخص می‌کند. مقدار پیش‌فرض -1 است (قاعدهٔ $ استفاده نمی‌شود). مقادیر ممکن دیگر شامل تمامی واحدهای کد معتبر هستند. تنها اعداد ده‌دهی شناسایی می‌شوند. re2c:header, re2c:flags:type-header, re2c:flags:t نام فایل سرآیند تولیدشده را به صورت نسبی نسبت به دایرکتوری فایل خروجی مشخص می‌کند. همانند گزینهٔ --header است با این تفاوت که مسیر فایل نسبی است. re2c:indent:string رشتهٔ مورد استفاده برای دندانه‌گذاری را مشخص می‌کند. پیش‌فرض یک نویسهٔ تب تک "\t" است. رشتهٔ دندانه‌گذاری تنها باید شامل نویسه‌های فاصلهٔ خالی باشد. برای غیرفعال کردن کامل دندانه‌گذاری، این پیکربندی را روی یک رشتهٔ خالی تنظیم کنید. re2c:indent:top حداقل مقدار دندانه‌گذاری برای استفاده را مشخص می‌کند. مقدار پیش‌فرض صفر است. این مقدار باید یک عدد صحیح غیرمنفی باشد. re2c:invert-captures همانند گزینهٔ --invert-captures است، اما می‌تواند بر پایهٔ هر بلوک پیکربندی شود. re2c:label:prefix, re2c:labelprefix پیشوند مورد استفاده برای برچسب‌های وضعیت DFA را مشخص می‌کند. پیش‌فرض yy است. re2c:label:start, re2c:startlabel تولید برچسب شروع بلوک را کنترل می‌کند. مقدار پیش‌فرض صفر است، به این معنی که برچسب شروع تنها در صورت استفاده تولید می‌شود. یک مقدار عددی صحیح بزرگ‌تر از صفر، حتی اگر برچسب شروع توسط تحلیل‌گر لغوی استفاده نشود، تولید آن را اجباری می‌کند. مقدار رشته‌ای نیز تولید برچسب شروع را اجباری کرده و نام برچسب را روی رشتهٔ مشخص‌شده تنظیم می‌کند. این پیکربندی تنها روی بلوک فعلی اعمال می‌شود (برای بلوک بعدی به مقدار پیش‌فرض بازنشانی می‌شود). re2c:label:yyFillLabel پیشوند برچسب‌های YYFILL مورد استفاده همراه با re2c:eof و در حالت وضعیت قابل‌ذخیره را مشخص می‌کند. re2c:label:yyloop نام برچسب نشان‌دهندهٔ شروع حلقهٔ تحلیل‌گر لغوی با گزینهٔ --loop-switch را مشخص می‌کند. پیش‌فرض yyloop است. re2c:label:yyNext نام برچسب اختیاری را مشخص می‌کند که بعد از سوییچ YYGETSTATE در حالت وضعیت قابل‌ذخیره می‌آید (با re2c:state:nextlabel فعال می‌شود). پیش‌فرض yyNext است. re2c:lookahead, re2c:flags:lookahead منسوخ شده است (گزینهٔ منسوخ‌شدهٔ --no-lookahead را ببینید). re2c:monadic اگر روی غیرصفر تنظیم شود، تحلیل‌گر لغوی تولیدشده از نشانه‌گذاری مونادیک استفاده خواهد کرد (این پیکربندی مختص به Haskell است). re2c:nested-ifs, re2c:flags:nested-ifs, re2c:flags:s همانند گزینهٔ --nested-ifs است، اما می‌تواند بر پایهٔ هر بلوک پیکربندی شود. re2c:posix-captures, re2c:flags:posix-captures, re2c:flags:P همانند گزینهٔ --posix-captures است، اما می‌تواند بر پایهٔ هر بلوک پیکربندی شود. re2c:posix-captvars همانند گزینهٔ --posix-captvars است، اما می‌تواند بر پایهٔ هر بلوک پیکربندی شود. re2c:tags, re2c:flags:tags, re2c:flags:T همانند گزینهٔ --tags است، اما می‌تواند بر پایهٔ هر بلوک پیکربندی شود. re2c:tags:expression عبارت مورد استفاده برای متغیرهای برچسب را مشخص می‌کند. به طور پیش‌فرض re2swift عبارت‌هایی به فرم yyt تولید می‌کند. این حالت ممکن است ناخوشایند باشد، برای مثال اگر متغیرهای برچسب به عنوان فیلدهایی در یک struct تعریف شده باشند. تمامی رخدادهای @@{tag} یا @@ با نام واقعی برچسب جایگزین می‌شوند. برای مثال، re2c:tags:expression = "s.@@"; منجر به تولید عبارت‌هایی به فرم s.yyt در کد تولیدشده می‌شود. همچنین پیکربندی re2c:api:sigil را ببینید..TP re2c:tags:negative عبارت ثابتی را مشخص می‌کند که برای مقدار منفی تگ استفاده می‌شود (معمولاً در صورتی که تگ‌ها آفست‌های عدد صحیح در رشته ورودی باشند، مقدار آن -1 است یا اگر اشاره‌گر باشند، اشاره‌گر تهی خواهد بود). re2c:tags:prefix پیشوند نام متغیرهای تگ را مشخص می‌کند. مقدار پیش‌فرض yyt است. re2c:sentinel نماد دیده‌بان (sentinel) مورد استفاده برای بررسی‌های پایان ورودی را مشخص می‌کند (زمانی که بررسی‌های محدوده با re2c:yyfill:enable = 0; غیرفعال شده باشند و re2c:eof تنظیم نشده باشد). این پیکربندی بر تولید کد تأثیری ندارد: هدف آن اطمینان از عدم وجود نماد دیده‌بان در میان یک قاعده، و تضمین اینکه تحلیل‌گر لغوی فراتر از انتهای بافر را نخواهد خواند است. مقدار پیش‌فرض -1` است (در این حالت re2swift فرض می‌کند که دیده‌بان صفر است، که رایج‌ترین حالت می‌باشد). فقط اعداد ده‌دهی شناسایی می‌شوند. re2c:state:abort اگر روی یک مقدار عدد صحیح مثبت تنظیم شود، شاخهٔ پیش‌فرض (default case) در توزیع وضعیت تولیدشده، اجرای برنامه را لغو (abort) می‌کند و یک شاخهٔ صریح -1 شامل انتقال به ابتدای بلوک خواهد بود. re2c:state:nextlabel کنترل می‌کند که آیا بعد از عبارت switch مربوط به YYGETSTATE یک برچسب yyNext قرار گیرد یا خیر (مقدار پیش‌فرض صفر است که با عدم وجود برچسب مطابقت دارد). به عنوان جایگزین می‌توان از re2c:label:start برای تولید یک برچسب شروع مشخص، یا از یک بلوک صریح getstate برای تولید ساختار switch مربوط به YYGETSTATE به صورت جداگانه از بلوک تحلیل‌گر استفاده کرد. re2c:unsafe, re2c:flags:unsafe مشابه گزینهٔ --no-unsafe است، اما می‌تواند بر پایهٔ هر بلوک پیکربندی شود. اگر روی صفر تنظیم شود، از تولید پوشش‌های (wrappers) unsafe در اطراف YYPEEK جلوگیری می‌کند. پیش‌فرض مقداری غیرصفر است (پوشش‌ها تولید می‌شوند). این پیکربندی مختص Rust است. re2c:YYBACKUP, re2c:define:YYBACKUP عنصر پایهٔ عمومی API به نام YYBACKUP را تعریف می‌کند. re2c:YYBACKUPCTX, re2c:define:YYBACKUPCTX عنصر پایهٔ عمومی API به نام YYBACKUPCTX را تعریف می‌کند. re2c:YYCONDTYPE, re2c:define:YYCONDTYPE عنصر پایهٔ API به نام YYCONDTYPE را تعریف می‌کند. re2c:YYCTYPE, re2c:define:YYCTYPE عنصر پایهٔ API به نام YYCTYPE را تعریف می‌کند. re2c:YYCTXMARKER, re2c:define:YYCTXMARKER عنصر پایهٔ API به نام YYCTXMARKER را تعریف می‌کند. re2c:YYCURSOR, re2c:define:YYCURSOR عنصر پایهٔ API به نام YYCURSOR را تعریف می‌کند. re2c:YYDEBUG, re2c:define:YYDEBUG عنصر پایهٔ API به نام YYDEBUG را تعریف می‌کند. re2c:YYFILL, re2c:define:YYFILL عنصر پایهٔ API به نام YYFILL را تعریف می‌کند. re2c:YYFILL@len, re2c:define:YYFILL@len علامت ویژه (sigil) مورد استفاده برای جایگزینی آرگومان در تعریف YYFILL را مشخص می‌کند. مقدار پیش‌فرض @@ است. پیکربندی عمومی‌تر re2c:api:sigil را لغو می‌کند. re2c:YYFILL:naked, re2c:define:YYFILL:naked پیکربندی عمومی‌تر re2c:api:style را برای YYFILL لغو می‌کند. مقدار صفر متناظر با سبک آزاد API (free-form) است. re2c:YYFN عنصر پایهٔ API به نام YYFN را تعریف می‌کند. re2c:YYINPUT عنصر پایهٔ API به نام YYINPUT را تعریف می‌کند. re2c:YYGETCOND, re2c:define:YYGETCONDITION عنصر پایهٔ API به نام YYGETCOND را تعریف می‌کند. re2c:YYGETCOND:naked, re2c:define:YYGETCONDITION:naked پیکربندی عمومی‌تر re2c:api:style را برای YYGETCOND لغو می‌کند. مقدار صفر متناظر با سبک آزاد API است. re2c:YYGETSTATE, re2c:define:YYGETSTATE عنصر پایهٔ API به نام YYGETSTATE را تعریف می‌کند. re2c:YYGETSTATE:naked, re2c:define:YYGETSTATE:naked پیکربندی عمومی‌تر re2c:api:style را برای YYGETSTATE لغو می‌کند. مقدار صفر متناظر با سبک آزاد API است. re2c:YYGETACCEPT, re2c:define:YYGETACCEPT عنصر پایهٔ API به نام YYGETACCEPT را تعریف می‌کند. re2c:YYLESSTHAN, re2c:define:YYLESSTHAN عنصر پایهٔ عمومی API به نام YYLESSTHAN را تعریف می‌کند. re2c:YYLIMIT, re2c:define:YYLIMIT عنصر پایهٔ API به نام YYLIMIT را تعریف می‌کند. re2c:YYMARKER, re2c:define:YYMARKER عنصر پایهٔ API به نام YYMARKER را تعریف می‌کند. re2c:YYMTAGN, re2c:define:YYMTAGN عنصر پایهٔ عمومی API به نام YYMTAGN را تعریف می‌کند. re2c:YYMTAGP, re2c:define:YYMTAGP عنصر پایهٔ عمومی API به نام YYMTAGP را تعریف می‌کند. re2c:YYPEEK, re2c:define:YYPEEK عنصر پایهٔ عمومی API به نام YYPEEK را تعریف می‌کند. re2c:YYRESTORE, re2c:define:YYRESTORE عنصر پایهٔ عمومی API به نام YYRESTORE را تعریف می‌کند. re2c:YYRESTORECTX, re2c:define:YYRESTORECTX عنصر پایهٔ عمومی API به نام YYRESTORECTX را تعریف می‌کند. re2c:YYRESTORETAG, re2c:define:YYRESTORETAG عنصر پایهٔ عمومی API به نام YYRESTORETAG را تعریف می‌کند. re2c:YYSETCOND, re2c:define:YYSETCONDITION عنصر پایهٔ API به نام YYSETCOND را تعریف می‌کند. re2c:YYSETCOND@cond, re2c:define:YYSETCONDITION@cond علامت ویژه (sigil) مورد استفاده برای جایگزینی آرگومان در تعریف YYSETCOND را مشخص می‌کند. مقدار پیش‌فرض @@ است. پیکربندی عمومی‌تر re2c:api:sigil را لغو می‌کند. re2c:YYSETCOND:naked, re2c:define:YYSETCONDITION:naked پیکربندی عمومی‌تر re2c:api:style را برای YYSETCOND لغو می‌کند. مقدار صفر متناظر با سبک آزاد API است. re2c:YYSETSTATE, re2c:define:YYSETSTATE عنصر پایهٔ API به نام YYSETSTATE را تعریف می‌کند. re2c:YYSETSTATE@state, re2c:define:YYSETSTATE@state علامت ویژه (sigil) مورد استفاده برای جایگزینی آرگومان در تعریف YYSETSTATE را مشخص می‌کند. مقدار پیش‌فرض @@ است. پیکربندی عمومی‌تر re2c:api:sigil را لغو می‌کند. re2c:YYSETSTATE:naked, re2c:define:YYSETSTATE:naked پیکربندی عمومی‌تر re2c:api:style را برای YYSETSTATE لغو می‌کند. مقدار صفر متناظر با سبک آزاد API است. re2c:YYSETACCEPT, re2c:define:YYSETACCEPT عنصر پایهٔ API به نام YYSETACCEPT را تعریف می‌کند. re2c:YYSKIP, re2c:define:YYSKIP عنصر پایهٔ عمومی API به نام YYSKIP را تعریف می‌کند. re2c:YYSHIFT, re2c:define:YYSHIFT عنصر پایهٔ عمومی API به نام YYSHIFT را تعریف می‌کند. re2c:YYCOPYMTAG, re2c:define:YYCOPYMTAG عنصر پایهٔ عمومی API به نام YYCOPYMTAG را تعریف می‌کند. re2c:YYCOPYSTAG, re2c:define:YYCOPYSTAG عنصر پایهٔ عمومی API به نام YYCOPYSTAG را تعریف می‌کند. re2c:YYSHIFTMTAG, re2c:define:YYSHIFTMTAG عنصر پایهٔ عمومی API به نام YYSHIFTMTAG را تعریف می‌کند. re2c:YYSHIFTSTAG, re2c:define:YYSHIFTSTAG عنصر پایهٔ عمومی API به نام YYSHIFTSTAG را تعریف می‌کند. re2c:YYSTAGN, re2c:define:YYSTAGN عنصر پایهٔ عمومی API به نام YYSTAGN را تعریف می‌کند. re2c:YYSTAGP, re2c:define:YYSTAGP عنصر پایهٔ عمومی API به نام YYSTAGP را تعریف می‌کند. re2c:yyaccept, re2c:variable:yyaccept عنصر پایهٔ API به نام yyaccept را تعریف می‌کند. re2c:yybm, re2c:variable:yybm عنصر پایهٔ API به نام yybm را تعریف می‌کند. re2c:yybm:hex, re2c:variable:yybm:hex اگر روی مقداری غیرصفر تنظیم شود، نقشه‌های بیتی (bitmaps) برای گزینهٔ --bit-vectors در قالب شانزده‌شانزدهی (hexadecimal) تولید می‌شوند. پیش‌فرض صفر است (نقشه‌های بیتی در قالب ده‌دهی هستند). re2c:yych, re2c:variable:yych عنصر پایهٔ API به نام yych را تعریف می‌کند. re2c:yych:emit, re2c:variable:yych:emit اگر روی صفر تنظیم شود، تعریف yych تولید نمی‌شود. مقدار پیش‌فرض غیرصفر است. re2c:yych:conversion, re2c:variable:yych:conversion اگر روی مقداری غیرصفر تنظیم شود، re2swift به طور خودکار هر بار که yych خوانده می‌شود، یک تبدیل به YYCTYPE تولید می‌کند. پیش‌فرض صفر است (بدون تبدیل). re2c:yych:literals, re2c:variable:yych:literals قالب لیترال‌هایی که yych با آن‌ها مطابقت داده می‌شود را مشخص می‌کند. مقادیر ممکن عبارتند از: char (لیترال‌های نویسه‌ای درون گیومه تکی؛ موارد غیرقابل چاپ از توالی‌های گریز که با بک‌اسلش شروع می‌شوند استفاده می‌کنند)، hex (اعداد صحیح شانزده‌شانزدهی) و char_or_hex (ترکیبی از هر دو؛ لیترال‌های نویسه‌ای برای نویسه‌های قابل چاپ و اعداد صحیح شانزده‌شانزدهی برای بقیه). re2c:yyctable, re2c:variable:yyctable عنصر پایهٔ API به نام yyctable را تعریف می‌کند..TP re2c:yynmatch, re2c:variable:yynmatch عنصر پایه API با نام yynmatch را تعریف می‌کند. re2c:yypmatch, re2c:variable:yypmatch عنصر پایه API با نام yypmatch را تعریف می‌کند. re2c:yytarget, re2c:variable:yytarget عنصر پایه API با نام yytarget را تعریف می‌کند. re2c:yystable, re2c:variable:yystable منسوخ شده است. re2c:yystate, re2c:variable:yystate عنصر پایه API با نام yystate را تعریف می‌کند. re2c:yyfill, re2c:variable:yyfill عنصر پایه API با نام yyfill را تعریف می‌کند. re2c:yyfill:check اگر روی صفر تنظیم شود، از تولید بررسی پیش از YYFILL برای تعداد نویسه‌های ورودی (تعریف YYLESSTHAN در API عمومی و مقایسه مبتنی بر YYLIMIT در API اشاره‌گر C) جلوگیری می‌کند. مقدار پیش‌فرض غیرصفر است (بررسی را تولید می‌کند). re2c:yyfill:enable اگر روی صفر تنظیم شود، تولید YYFILL را (همراه با بررسی آن) لغو می‌کند. این حالت باید زمانی استفاده شود که کل ورودی در یک بخش یکپارچه از حافظه جا می‌شود (نیازی به بافر کردن نیست) و بررسی‌های پایان ورودی به بررسی‌های YYFILL متکی نیستند (برای نمونه، اگر از نویسه نشانگر پایان / sentinel استفاده شود). برای اطمینان از اینکه تحلیل‌گر لغوی تولیدشده نمی‌تواند فراتر از پایان ورودی را بخواند، از هشدارها (گزینه -W) و پیکربندی re2c:sentinel استفاده کنید. مقدار پیش‌فرض غیرصفر است (YYFILL فعال است). re2c:yyfill:parameter اگر روی صفر تنظیم شود، از تولید پارامتر ارسالی به YYFILL جلوگیری می‌کند. این پارامتر حداقل تعداد نویسه‌هایی است که باید فراهم شوند. پیش‌فرض غیرصفر است (پارامتر تولید می‌شود). این پیکربندی را می‌توان با re2c:YYFILL:naked یا re2c:api:style بازنویسی کرد. re2c:yyfn:sep جداکننده مورد استفاده در عناصر YYFN را مشخص می‌کند (پیش‌فرض نقطه-ویرگول است). re2c:yyfn:throw استثناهای پرتاب‌شده توسط تابع YYFN را مشخص می‌کند (پیش‌فرض خالی است، که به معنای پرتاب نشدن هیچ استثنایی است). عبارت‌های منظم (Regular expressions) ابزار re2swift از نحو زیر برای عبارت‌های منظم استفاده می‌کند: "foo" ثابت رشته‌ای حساس به بزرگی و کوچکی حروف. 'foo' ثابت رشته‌ای غیرحساس به بزرگی و کوچکی حروف. [a-xyz], [^a-xyz] کلاس نویسه (احتمالاً نفی‌شده). . هر نویسه‌ای به جز خط جدید. R \ S تفاضل کلاس‌های نویسه R و S. R* صفر یا چند بار تکرار R. R+ یک یا چند بار تکرار R. R? R اختیاری. R{n} تکرار R دقیقاً n بار. R{n,} تکرار R حداقل n بار. R{n,m} تکرار R از n تا m بار. (R) تنها همان R؛ پرانتزها برای تغییر اولویت استفاده می‌شوند. در صورت فعال بودن استخراج تطابق فرعی، (R) بسته به گزینه --invert-captures یک گروه ضبط‌کننده یا غیرضبط‌کننده است. (!R) در صورت فعال بودن استخراج تطابق فرعی، (!R) بسته به گزینه --invert-captures یک گروه غیرضبط‌کننده یا ضبط‌کننده است. R S الحاق: R و به دنبال آن S. R | S جایگزین: R یا S. R / S پیش‌نگری: R و به دنبال آن S، اما S مصرف نمی‌شود. name عبارت منظم تعریف‌شده با نام name (یا رشته دقیق "name" در حالت سازگاری با Flex). {name} عبارت منظم تعریف‌شده با نام name در حالت سازگاری با Flex. @stag یک s-tag: آخرین موقعیت ورودی که در آن @stag تطابق می‌یابد را در متغیری به نام stag ذخیره می‌کند. #mtag یک m-tag: تمامی موقعیت‌های ورودی که در آن‌ها #mtag تطابق می‌یابد را در متغیری به نام mtag ذخیره می‌کند. $ پایان ورودی. کلاس‌های نویسه و ثابت‌های رشته‌ای می‌توانند شامل توالی‌های گریز زیر باشند: \a، \b، \f، \n، \r، \t، \v، \\، گریزهای هشت‌هشتی \ooo و گریزهای شانزده‌شانزدهی \xhh، \uhhhh و \Uhhhhhhhh..SS "کنش‌ها (Actions)" در اینجا فهرستی از کنش‌های از پیش تعریف‌شده که توسط re2swift پشتیبانی می‌شوند آمده است: !entry code کنش ورودی (Entry action) یک بلوک از code تعریف‌شده توسط کاربر را به وضعیت آغازین ماشین حالت متناهی کنونی مقید می‌کند. اگر از start conditions استفاده شود، کنش ورودی را می‌توان به‌صورت جداگانه برای هر شرط تنظیم کرد. این کنش ممکن است برای انجام مقداردهی اولیه، مانند ذخیره موقعیت آغازین یک لکسم (lexeme) استفاده شود. !pre_rule code کنش پیش‌قاعده (Pre-rule action) یک بلوک از code تعریف‌شده توسط کاربر را به ابتدای کنش‌های معنایی تمام قواعد در بلوک کنونی (یا در صورت استفاده از start conditions، به شرط کنونی) اضافه می‌کند. این کنش می‌تواند برای فاکتورگیری بخش مشترک تمام کنش‌های معنایی (مانند ذخیره موقعیت پایانی یک لکسم) استفاده شود. !post_rule code کنش پس‌قاعده (Post-rule action) یک بلوک از code تعریف‌شده توسط کاربر را به انتهای کنش‌های معنایی تمام قواعد در بلوک کنونی (یا در صورت استفاده از start conditions، به شرط کنونی) ضمیمه می‌کند. این کنش می‌تواند برای درج عبارت‌های تله (trap) که در برابر جریان کنترل ناخواسته محافظت می‌کنند، استفاده شود. رهنمودها (Directives) در اینجا فهرست کاملی از رهنمودهای پشتیبانی‌شده توسط re2swift آمده است: !use:name ; یک رهنمود درون‌بلوکیِ use که یک بلوک قواعد از پیش تعریف‌شده با name مشخص را در بلوک کنونی ادغام می‌کند. تعاریف نام‌گذاری‌شده، پیکربندی‌ها و قواعد بلوک مرجع به موارد فعلی اضافه می‌شوند. تداخلات میان قواعد و پیکربندی‌های هم‌پوشان به روش معمول حل می‌شوند: نخستین قاعده اولویت دارد، و آخرین پیکربندی بر موارد پیشین بازنویسی می‌شود. یک استثنا قواعد خاص *، $ و هستند که برای آن‌ها تعریف محلی بلوک همواره اولویت دارد. یک رهنمود use را می‌توان در هر کجای یک بلوک قرار داد، و استفاده از چندین رهنمود use مجاز است. !include file ; این رهنمود همانند بلوک include است: محتویات file را عیناً به جای رهنمود درج می‌کند. رابط برنامه (Program interface) کد تولیدشده به کمک عناصر پایه (primitives) که در مجموع به عنوان API شناخته می‌شوند، با برنامه بیرونی ارتباط برقرار می‌کند. اینکه کدام پایه‌ها باید برای یک برنامه خاص تعریف شوند به عوامل متعددی بستگی دارد، از جمله پیچیدگی عبارات باقاعده، نحوه نمایش ورودی، بافرینگ و استفاده از قابلیت‌های گوناگون. تمام پایه‌های ضروری باید توسط کاربر در قالب ماکروها، توابع، متغیرها یا هر شکل مناسب دیگری که کد تولیدشده را از نظر نحوی و معنایی صحیح سازد، تعریف شوند. re2swift تعاریف را بررسی نمی‌کند (و نمی‌تواند بررسی کند)، بنابراین اگر موردی جا افتاده باشد یا به نادرستی تعریف شده باشد، ممکن است برنامه تولیدشده با خطاهای زمان کامپایل یا زمان اجرا مواجه شود. این راهنما مثال‌هایی از تعاریف API در رایج‌ترین موارد ارائه می‌دهد. ابزار re2swift دارای سه شیوه (flavor) از API است که مجموعه اصلی پایه‌های استفاده‌شده توسط یک برنامه را مشخص می‌کنند: Simple API این حالت پیش‌فرض برای backend سوئیفت (Swift) است. این API از پایه‌های زیر تشکیل شده است: YYINPUT (که باید به‌صورت توالی از واحدهای کد، مانند یک رشته تعریف شود) و YYCURSOR، YYMARKER، YYCTXMARKER، YYLIMIT (که باید به‌صورت اندیس‌هایی در YYINPUT تعریف شوند). Record API رابط Record API در مواردی مفید است که وضعیت تحلیل‌گر لغوی باید در یک شیء ذخیره شود. این حالت با گزینه --api record یا پیکربندی re2c:api = record فعال می‌شود. این API شامل متغیر yyrecord است (این نام را می‌توان با re2c:YYRECORD بازنویسی کرد) که باید به‌صورت یک ساختار (struct) یا کلاس (class) با فیلدهای yyinput، yycursor، yymarker، yyctxmarker و yylimit تعریف شود (تنها فیلدهایی که توسط کد تولیدشده استفاده می‌شوند باید تعریف شوند، و نام‌های آن‌ها نیز قابل پیکربندی است). Generic API این منعطف‌ترین API است. این حالت با گزینه --api generic یا پیکربندی re2c:api = generic فعال می‌شود. این API شامل پایه‌های زیر برای عملیات عمومی است: YYPEEK، YYSKIP، YYBACKUP، YYBACKUPCTX، YYSTAGP، YYSTAGN، YYMTAGP، YYMTAGN، YYRESTORE، YYRESTORECTX، YYRESTORETAG، YYSHIFT، YYSHIFTSTAG، YYSHIFTMTAG، YYLESSTHAN، YYEND. برای مثال، اگر ورودی یک آرایه از بایت‌ها با پایان صفر به‌صورت buffer: [UInt8] باشد، متغیرهای cursor، limit، marker و ctxmarker از نوع Int نمایانگر موقعیت‌های ورودی باشند، و -1 نمایانگر موقعیت‌های نامعتبر باشد، یک Generic API می‌تواند به‌صورت زیر تعریف شود: /*!re2c re2c:YYPEEK = "buffer[cursor]"; re2c:YYSKIP = "cursor++"; re2c:YYBACKUP = "marker = cursor"; re2c:YYRESTORE = "cursor = marker"; re2c:YYBACKUPCTX = "ctxmarker = cursor"; re2c:YYRESTORECTX = "cursor = ctxmarker"; re2c:YYRESTORETAG = "cursor = ${tag}"; re2c:YYLESSTHAN = "limit - cursor < @@{len}"; re2c:YYEND = "limit == cursor"; re2c:YYSTAGP = "@@{tag} = cursor"; re2c:YYSTAGN = "@@{tag} = -1"; re2c:YYSHIFT = "cursor += @@{shift}"; re2c:YYSHIFTSTAG = "@@{tag} += @@{shift}"; */ در اینجا فهرست کاملی از پایه‌های API که ممکن است توسط کد تولیدشده جهت برقراری ارتباط با برنامه بیرونی استفاده شوند آمده است: YYCTYPE نوع نویسه‌های ورودی (واحدهای کد). برای کدگذاری‌های ASCII، EBCDIC و UTF-8 باید یک عدد صحیح بدون علامت ۱ بایتی باشد. برای UTF-16 یا UCS-2 باید عدد صحیح بدون علامت ۲ بایتی باشد. برای UTF-32 باید عدد صحیح بدون علامت ۴ بایتی باشد. YYCURSOR یک مقدار چپ (l-value) که موقعیت کنونی ورودی را ذخیره می‌کند (یک اشاره‌گر یا آفست صحیح در YYINPUT). در ابتدا YYCURSOR باید به نخستین نویسه ورودی اشاره کند، و سپس توسط کد تولیدشده به جلو برده می‌شود. هنگامی که قاعده‌ای مطابقت یابد، موقعیت YYCURSOR نویسه پس از آخرین نویسه تطبیق‌یافته خواهد بود. YYLIMIT یک مقدار راست (r-value) که موقعیت پایان ورودی را ذخیره می‌کند (یک اشاره‌گر یا آفست صحیح در YYINPUT). در ابتدا YYLIMIT باید به موقعیت پس از آخرین نویسه ورودی موجود اشاره کند. این مقدار توسط کد تولیدشده تغییر داده نمی‌شود. تحلیل‌گر لغوی YYCURSOR را با YYLIMIT مقایسه می‌کند تا مشخص شود آیا نویسه‌های ورودی کافی باقی مانده‌اند یا خیر. YYMARKER یک مقدار چپ (l-value) که موقعیت آخرین قاعده تطبیق‌یافته را ذخیره می‌کند (یک اشاره‌گر یا آفست صحیح در YYINPUT). این مقدار برای بازیابی موقعیت YYCURSOR در صورتی که تطبیق طولانی‌تر با شکست مواجه شود و تحلیل‌گر لغوی نیاز به بازگشت به عقب (rollback) داشته باشد، استفاده می‌شود. مقداردهی اولیه نیاز نیست. YYCTXMARKER یک مقدار چپ (l-value) که موقعیت زمینه دنباله‌دار (trailing context) را ذخیره می‌کند (یک اشاره‌گر یا آفست صحیح در YYINPUT). به مقداردهی اولیه نیازی نیست. YYCTXMARKER تنها در صورتی نیاز است که از عملگر پیش‌نگری (lookahead) / استفاده شود. YYFILL یک پایه Generic API با یک متغیر len. پایه YYFILL باید دست‌کم len نویسه ورودی بیشتر تأمین کند یا با شکست مواجه شود. اگر از re2c:eof استفاده شود، len همیشه 1 است و YYFILL باید همواره به تابع فراخواننده بازگردد؛ مقدار بازگشتی صفر نشان‌دهنده موفقیت است. اگر از re2c:eof استفاده نشود، مقدار بازگشتی YYFILL نادیده گرفته می‌شود و نباید هنگام شکست بازگشتی داشته باشد. بیشینه مقدار len برابر با YYMAXFILL است. YYFN پایه‌ای که پیش‌نمونه (prototype) تابع را در مدل کد --recursive-functions تعریف می‌کند. مقدار آن باید آرایه‌ای از یک یا چند رشته باشد، که در آن هر رشته شامل دو یا سه مؤلفه است که توسط رشته مشخص‌شده در پیکربندی re2c:fn:sep (معمولاً یک نقطه‌ویرگول) از هم جدا شده‌اند. نخستین عنصر آرایه نام تابع و نوع بازگشتی را مشخص می‌کند (برای یک تابع void خالی است). عناصر بعدی آرگومان‌های تابع را تعریف می‌کنند: اول، عبارت مربوط به آرگومان مورد استفاده در بدنه تابع (معمولاً تنها یک نام)؛ دوم، نوع آرگومان؛ سوم، یک پارامتر صوری اختیاری (پیش‌فرض آن مؤلفه اول است - معمولاً هر دو آرگومان و پارامتر شناسه یکسانی هستند). YYINPUT یک مقدار راست (r-value) که توالی نویسه‌های ورودی کنونی (رشته، بافر، و غیره) را ذخیره می‌کند. YYMAXFILL یک ثابت صحیح برابر با بیشینه مقدار آرگومان ورودی به YYFILL. این مقدار را می‌توان با یک بلوک max تولید کرد. YYLESSTHAN یک پایه Generic API با یک متغیر len. این پایه باید به‌صورت یک مقدار راست (r-value) از نوع بولی تعریف شود که اگر و تنها اگر کمتر از len نویسه ورودی باقی مانده باشد برابر با true است. YYEND یک پایه Generic API بدون متغیر. این پایه باید به‌صورت یک مقدار راست (r-value) از نوع بولی تعریف شود که اگر و تنها اگر به پایان منطقی ورودی (بدون احتساب هرگونه پدینگ یا نمادهای نگهبان/sentinel) رسیده باشیم برابر با true است. YYEND برای پیاده‌سازی نماد $ در عبارات باقاعده استفاده می‌شود. این پایه با YYLESSTHAN تفاوت دارد، که برای اطمینان از اینکه تحلیل‌گر لغوی فراتر از انتهای بافر را نخواند استفاده می‌شود. YYPEEK یک دستور اولیه (primitive) عمومی API بدون متغیر. باید به‌صورت یک r-value از نوع YYCTYPE تعریف شود که برابر با نویسه در موقعیت فعلی ورودی است. YYSKIP یک دستور اولیه عمومی API که باید موقعیت فعلی ورودی را به اندازهٔ یک واحد کد جلو ببرد. YYBACKUP یک دستور اولیه عمومی API که باید موقعیت فعلی ورودی را ذخیره کند (تا بعداً با YYRESTORE بازیابی شود). YYRESTORE یک دستور اولیه عمومی API که باید موقعیت فعلی ورودی را به مقدار ذخیره‌شده توسط YYBACKUP بازگرداند. YYBACKUPCTX یک دستور اولیه عمومی API که باید موقعیت فعلی ورودی را به‌عنوان موقعیت بافت انتهایی (trailing context) ذخیره کند (تا بعداً با YYRESTORECTX بازیابی شود). YYRESTORECTX یک دستور اولیه عمومی API که باید موقعیت بافت انتهایی ذخیره‌شده با YYBACKUPCTX را بازگرداند. YYRESTORETAG یک دستور اولیه عمومی API با یک متغیر tag که باید موقعیت بافت انتهایی را به مقدار tag بازگرداند. YYSTAGP یک دستور اولیه عمومی API با یک متغیر tag، که در آن tag می‌تواند یک اشاره‌گر یا آفست در YYINPUT باشد (برای جزئیات به بخش استخراج تطابق‌های فرعی مراجعه کنید). YYSTAGP باید tag را روی موقعیت فعلی ورودی تنظیم کند. YYSTAGN یک دستور اولیه عمومی API با یک متغیر tag، که در آن tag می‌تواند یک اشاره‌گر یا آفست در YYINPUT باشد (برای جزئیات به بخش استخراج تطابق‌های فرعی مراجعه کنید). YYSTAGN باید tag را روی مقداری تنظیم کند که نشان‌دهندهٔ موقعیت ناموجود در ورودی است. YYMTAGP یک دستور اولیه عمومی API با یک متغیر tag. YYMTAGP باید موقعیت فعلی را به تاریخچهٔ تطابق‌های فرعی tag الحاق کند (برای جزئیات به بخش استخراج تطابق‌های فرعی مراجعه کنید). YYMTAGN یک دستور اولیه عمومی API با یک متغیر tag. YYMTAGN باید مقداری را که نشان‌دهندهٔ موقعیت ناموجود در ورودی است، به تاریخچهٔ تطابق‌های فرعی tag الحاق کند (برای جزئیات به بخش استخراج تطابق‌های فرعی مراجعه کنید). YYSHIFT یک دستور اولیه عمومی API با یک متغیر shift که باید موقعیت فعلی ورودی را به اندازهٔ shift نویسه جابه‌جا کند (مقدار جابه‌جایی ممکن است منفی باشد). YYCOPYSTAG یک دستور اولیه عمومی API با دو متغیر lhs و rhs که باید متغیر s-tag سمت راست (rhs) را در متغیر s-tag سمت چپ (lhs) رونوشت کند. برای بیشتر زبان‌ها این دستور اولیه دارای یک تعریف پیش‌فرض است که lhs را برابر rhs قرار می‌دهد. YYCOPYMTAG یک دستور اولیه عمومی API با دو متغیر lhs و rhs که باید متغیر m-tag سمت راست (rhs) را در متغیر m-tag سمت چپ (lhs) رونوشت کند. برای بیشتر زبان‌ها این دستور اولیه دارای یک تعریف پیش‌فرض است که lhs را برابر rhs قرار می‌دهد. YYSHIFTSTAG یک دستور اولیه عمومی API با دو متغیر tag و shift که باید tag را به اندازهٔ shift واحد کد جابه‌جا کند (مقدار جابه‌جایی ممکن است منفی باشد). YYSHIFTMTAG یک دستور اولیه عمومی API با دو متغیر tag و shift که باید آخرین مقدار در تاریخچهٔ tag را به اندازهٔ shift واحد کد جابه‌جا کند (مقدار جابه‌جایی ممکن است منفی باشد). YYMAXNMATCH یک ثابت عدد صحیح برابر با حداکثر تعداد گروه‌های تسخیرکنندهٔ POSIX در یک قاعده. این مقدار با یک بلوک maxnmatch تولید می‌شود. YYCONDTYPE نوع نوع شمارشی شرط (condition enum). می‌تواند با بلوک conditions یا گزینهٔ --header تولید شود. YYGETACCEPT یک دستور اولیه با یک متغیر var که انتخاب‌گر عددیِ قاعدهٔ پذیرفته‌شده را ذخیره می‌کند. برای بیشتر زبان‌ها این دستور اولیه تعریفی پیش‌فرض دارد که از var می‌خواند. YYSETACCEPT یک دستور اولیه با دو متغیر: var (یک l-value که انتخاب‌گر عددی قاعدهٔ پذیرفته‌شده را ذخیره می‌کند) و val (مقدار انتخاب‌گر). برای بیشتر زبان‌ها این دستور اولیه تعریفی پیش‌فرض دارد که var را برابر val قرار می‌دهد. YYGETCOND یک r-value از نوع YYCONDTYPE که برابر با شناسهٔ شرط فعلی است. YYSETCOND یک دستور اولیه با یک متغیر cond که باید شناسهٔ شرط فعلی را روی cond تنظیم کند. YYGETSTATE یک r-value از نوع عدد صحیح که برابر با وضعیت فعلی تحلیل‌گر لغوی (lexer) است. مقدار آن باید به -1 مقداردهی اولیه شود. YYSETSTATE یک دستور اولیه با یک متغیر state که باید وضعیت فعلی تحلیل‌گر لغوی را روی state تنظیم کند. YYDEBUG این دستور اولیه فقط با گزینهٔ -d یا --debug-output تولید می‌شود. هدف آن افزودن امکان ثبت وقایع (لاگین) به کد تولیدشده است (تعریف معمول YYDEBUG یک دستور چاپ است). عبارت‌های YYDEBUG در هر وضعیت تولید می‌شوند و دو متغیر دارند: state (یا نمایهٔ وضعیت DFA یا -1) و symbol (نماد ورودی فعلی). yyaccept یک l-value از نوع عددیِ صحیح بدون علامت که شمارهٔ آخرین قاعدهٔ منطبق‌شده را ذخیره می‌کند. تعریف توسط کاربر تنها با گزینهٔ --storable-state ضروری است. yybm جدولی حاوی نقشه‌های بیتی فشرده‌شده برای حداکثر ۸ گذار (که با گزینهٔ --bitmaps استفاده می‌شود). این جدول شامل ۲۵۶ عنصر است و با واحدهای کد ۱ بایتی اندیس‌گذاری می‌شود. هر عنصر ۸ بیتی، مقادیر بولی را برای حداکثر ۸ گذار ترکیب می‌کند. بیت k-اُم از عنصر n-اُم درست (true) است اگر و تنها اگر n-اُمین واحد کد در محدودهٔ k-اُمین گذار باشد. ایدهٔ این نقشهٔ بیتی جایگزینی چندین شاخهٔ if یا حالت‌های switch با یک بررسیِ تک‌بیتی در جدول است. yych یک l-value از نوع YYCTYPE که نویسهٔ ورودی فعلی را ذخیره می‌کند. تعریف توسط کاربر تنها با گزینهٔ -f --storable-state لازم است. yyctable جدول پرش تولیدشده برای توزیع شرط اولیه (که با ترکیب گزینه‌های --conditions و --computed-gotos فعال می‌شود). yyfill یک l-value که نتیجهٔ فراخوانی YYFILL را ذخیره می‌کند (این ممکن است برای زبان‌های تابعی محض لازم باشد، جایی که YYFILL تابعی مونادیک با مقدار بازگشتی پیچیده است). yynmatch یک l-value از نوع عددیِ صحیح بدون علامت که تعداد گروه‌های تسخیرکنندهٔ POSIX را در قاعدهٔ منطبق‌شده ذخیره می‌کند. تنها با گزینهٔ -P --posix-captures استفاده می‌شود. yypmatch آرایه‌ای از l-valueها که برای نگهداری مقادیر برچسب مربوط به پرانتزهای تسخیرکننده در قاعدهٔ منطبق‌شده استفاده می‌شوند. طول آرایه باید حداقل yynmatch * 2 باشد (معمولاً YYMAXNMATCH * 2 انتخاب مناسبی است). تنها با گزینهٔ -P --posix-captures استفاده می‌شود. yystable منسوخ‌شده. yystate یک l-value که با گزینهٔ --loop-switch برای ذخیرهٔ وضعیت فعلی DFA استفاده می‌شود. yytarget جدول پرشی که حاوی مقصدهای پرش (نشانی‌های برچسب) برای تمامی گذارها از یک وضعیت است. این جدول مختص هر وضعیت به‌صورت محلی است. تولید جدول‌های yytarget با گزینهٔ --computed-gotos فعال می‌شود. برخی از گزینه‌ها دارای پیکربندی‌های متناظر هستند، برخی دیگر سراسری بوده و پس از شروع خواندن فایل ورودی توسط re2c قابل تغییر نیستند. گزینه‌های اشکال‌زدایی (دیباگ) عموماً نیازمند ساخت re2c در پیکربندی دیباگ هستند. گزینه‌های داخلی برای آزمایش الگوریتم‌های به‌کاررفته در re2c مفیدند. -? --help -h نمایش پیام راهنما. --api مشخص کردن API مورد استفاده توسط کد تولیدشده جهت برقراری ارتباط با کد تعریف‌شده توسط کاربر. گزینهٔ simple باید در موارد ساده استفاده شود؛ هنگامی که نیازی به پر کردن مجدد بافر و ذخیره‌سازی وضعیت تحلیل‌گر لغوی (lexer) نیست. گزینهٔ record باید زمانی استفاده شود که وضعیت لکسر باید در یک رکورد (struct، class و غیره) ذخیره شود. گزینهٔ generic باید در سناریوهای پیچیده‌ای به کار رود که دو API دیگر انعطاف‌پذیری کافی ندارند. --bit-vectors -b بهینه‌سازی پرش‌های شرطی با استفاده از ماسک‌های بیتی. این گزینه مستلزم --nested-ifs است. --captures, --leftmost-captures فعال‌سازی استخراج زیرتطابق با گروه‌های گیرندهٔ حریصانه‌ترینِ چپ‌ترین (leftmost greedy). نتیجه در آرایهٔ yybmatch با ظرفیت 2 * YYMAXNMATCH جمع‌آوری می‌شود، و yynmatch به تعداد گروه‌ها برای قاعدهٔ منطبق‌شده تنظیم می‌گردد. --captvars, --leftmost-captvars فعال‌سازی استخراج زیرتطابق با گروه‌های گیرندهٔ حریصانه‌ترینِ چپ‌ترین (leftmost greedy). نتیجه در متغیرهای yytl و yytr برای گروه گیرندهٔ k-اُم گردآوری می‌شود. --case-insensitive در نظر گرفتن رشته‌های دارای تک‌نقل‌قول و دونقل‌قول به صورت غیرحساس به بزرگی و کوچکی حروف. --case-inverted معکوس کردن معنای رشته‌های دارای تک‌نقل‌قول و دونقل‌قول: رشته‌های با تک‌نقل‌قول حساس به حروف و رشته‌های با دونقل‌قول غیرحساس به بزرگی و کوچکی حروف در نظر گرفته می‌شوند. --case-ranges ادغام caseهای متوالی در دستور switch به یک بازه در قالب low ... high. این نحو، یک افزونهٔ زبان C/C++ است که توسط کامپایلرهایی مانند GCC، Clang و Tcc پشتیبانی می‌شود. مزیت اصلی نسبت به استفاده از caseهای تکی، تولید کد کوچک‌تر و سرعت بالاتر در زمان تولید کد است، اگرچه برای برخی کامپایلرها مانند Tcc منجر به کاهش اندازهٔ فایل باینری نیز می‌شود. --computed-gotos -g بهینه‌سازی پرش‌های شرطی با استفاده از افزونهٔ غیراستاندارد "computed goto" (که باید توسط کامپایلر پشتیبانی شود). برنامه re2swift جدول‌های پرش را تنها در موارد پیچیده با تعداد زیادی شاخهٔ شرطی تولید می‌کند. آستانهٔ پیچیدگی با پیکربندی cgoto:threshold قابل تنظیم است. آفست‌های نسبی را می‌توان با پیکربندی cgoto:relative فعال کرد. این گزینه مستلزم --bit-vectors است. --computed-gotos-relative مشابه --computed-gotos، اما در عوض آفست‌های نسبی را برای جدول‌های پرش تولید می‌کند (که باید توسط کامپایلر پشتیبانی شود). این گزینه مستلزم --computed-gotos است. --conditions --start-conditions -c فعال‌سازی پشتیبانی از "شرایط" مشابه Flex: چندین لکسر مرتبط درون یک بلوک. این یک جایگزین برای مشخص‌کردن دستی بلوک‌های مختلف re2swift متصل‌شده با goto یا فراخوانی‌های توابع است. --depfile FILE نوشتن اطلاعات وابستگی در FILE در قالب یک قاعدهٔ Makefile به شکل : [include-file ...]. این قابلیت امکان ردیابی وابستگی‌های ساخت را در حضور بلوک‌ها/دستورهای include فراهم می‌کند، به طوری که به‌روزرسانی فایل‌های include باعث تولید مجدد فایل خروجی می‌شود. این گزینه به گزینهٔ --output وابسته است. --ebcdic --ecb -e تولید لکسری که ورودی را با کدگذاری EBCDIC می‌خواند. برنامه re2swift فرض می‌کند که محدودهٔ نویسه‌ها 0 -- 0xFF و اندازهٔ نویسه ۱ بایت است. --empty-class تعیین نحوهٔ رفتار re2swift با کلاس‌های نویسهٔ خالی. با مقدار match-empty (پیش‌فرض) کلاس خالی با ورودی خالی تطابق می‌یابد (که غیرمنطقی است، اما برای سازگاری با نسخه‌های قبلی حفظ شده است). با match-none تطبیق کلاس خالی همیشه با شکست مواجه می‌شود. با error کلاس خالی یک خطای کامپایل ایجاد می‌کند. --encoding-policy تعیین نحوهٔ رفتار re2swift با جانشین‌های یونیکد (surrogates). با مقدار fail برنامه re2swift با مواجهه با یک جانشین، با خطا متوقف می‌شود. با substitute برنامه re2swift بدون هشدار جانشین‌ها را با کدپوینت خطای 0xFFFD جایگزین می‌کند. با ignore (پیش‌فرض) re2swift با جانشین‌ها مانند کدپوینت‌های معمولی رفتار می‌کند. استاندارد یونیکد بیان می‌کند که جانشین‌های مستقل نامعتبر هستند، اما کتابخانه‌ها و برنامه‌های دنیای واقعی رفتارهای متفاوتی دارند. --flex-syntax -F پشتیبانی جزئی از نحو Flex: در این حالت تعاریف نام‌گذاری‌شده نیازی به علامت مساوی و سمی‌کولنِ پایانی ندارند، و در صورت استفاده باید درون آکوالاد قرار گیرند. نام‌های بدون آکوالاد به عنوان رشته‌های محصور در دونقل‌قول در نظر گرفته می‌شوند. --goto-label استفاده از مدل کد "goto/label": کدگذاری DFA در قالب بلوک‌های کد برچسب‌دار متصل‌شده با انتقال‌های goto میان بلوک‌ها. این گزینه تنها برای زبان‌هایی پشتیبانی می‌شود که دستور goto دارند. --header --type-header -t HEADER تولید یک فایل HEADER. محتوای فایل را می‌توان با استفاده از بلوک‌های ویژهٔ header:on و header:off تعیین کرد. در صورت استفاده از شرایط، شمارشگر مربوط به شرایط (enum) به طور خودکار به انتهای فایل سرایندِ تولیدشده اضافه خواهد شد (مگر اینکه یک بلوک صریح conditions وجود داشته باشد). -I PATH افزودن PATH به فهرست مسیرهایی که هنگام جستجوی فایل‌های include استفاده می‌شوند. این گزینه در ترکیب با بلوک یا دستور include مفید است. برنامه re2swift فایل FILE را در دایرکتوری فایل والد و در مسیرهای include تعیین‌شده با گزینهٔ -I جستجو می‌کند. --input نام مستعار منسوخ‌شده برای --api. گزینهٔ default متناظر با simple است (در واقع برای اکثر بک‌اندها پیش‌فرض است، اما نه برای همه). گزینهٔ custom متناظر با generic است. --input-encoding مشخص کردن نحوهٔ تجزیهٔ عبارت‌های منظم توسط re2swift. با مقدار ascii (پیش‌فرض) re2swift ورودی را به عنوان کدگذاری ASCII در نظر می‌گیرد: هر توالی از واحدهای کد، توالی از نویسه‌های مستقل ۱ بایتی است. با utf8 برنامه re2swift ورودی را به عنوان کدگذاری UTF-8 در نظر گرفته و نویسه‌های چندبایتی را تشخیص می‌دهد. --invert-captures معکوس کردن معنای گروه‌های گیرنده و غیرگیرنده. به صورت پیش‌فرض (...) گیرنده و (! ...) غیرگیرنده است. با این گزینه (! ...) گیرنده و (...) غیرگیرنده خواهد بود. --lang مشخص کردن زبان مقصد. زبان‌های پشتیبانی‌شده عبارتند از C، D، Go، Haskell، Java، JS، OCaml، Python، Rust، Swift، V، Zig (زبان‌های بیشتر را می‌توان از طریق فایل‌های نحوِ تعریف‌شده توسط کاربر اضافه کرد؛ گزینهٔ --syntax را ببینید). گزینهٔ none پیکربندی‌های پیش‌فرض نحو را غیرفعال می‌کند تا زبان مقصد تعریف‌نشده باقی بماند. --location-format تعیین قالب مکان در پیام‌ها. با gnu مکان‌ها به صورت 'filename:line:column: ...' چاپ می‌شوند. با msvc مکان‌ها به صورت 'filename(line,column) ...' چاپ می‌شوند. پیش‌فرض gnu است. --loop-switch استفاده از مدل کد "loop/switch": کدگذاری DFA در قالب یک حلقه روی دستور switch، که در آن وضعیت‌های جداگانه همان caseهای switch هستند. وضعیت در یک متغیر yystate ذخیره می‌شود. انتقال‌های بین وضعیت‌ها، yystate را به برچسب case وضعیت مقصد به‌روزرسانی کرده و اجرا را به ابتدای حلقه ادامه می‌دهند. --nested-ifs -s استفاده از دستورات تو‌در‌توی if به جای دستورات switch در پرش‌های شرطی. این کار معمولاً در کامپایلرهای غیربهینه‌ساز منجر به کدی کارآمدتر می‌شود. --no-debug-info -i عدم درج دستورهای خط (line directives) در خروجی. این قابلیت زمانی که کد تولیدشده در یک سیستم کنترل نسخه نگهداری می‌شود مفید است (برای جلوگیری از diffهای حجیم خودکار روی تغییرات کوچک). --no-generation-date جلوگیری از چاپ تاریخ در فایل تولیدشده. --no-version جلوگیری از چاپ نسخه در فایل تولیدشده. --no-unsafe عدم تولید بسته‌بند unsafe روی YYPEEK (این گزینه مختص Rust است). به دلایل کارایی، YYPEEK باید از بررسی محدوده (bounds-checking) خودداری کند، زیرا لکسر پیش از این بررسی‌های پایان ورودی را به روشی کارآمدتر انجام می‌دهد. کاربر ممکن است تعریفی امن از YYPEEK ارائه دهد، یا تعریفی که تنها در بیلد انتشار (release) ناامن باشد، که در این حالت گزینهٔ --no-unsafe به جلوگیری از هشدارهای مربوط به بلوک‌های unsafe زاید کمک می‌کند. --output -o OUTPUT مشخص کردن فایل OUTPUT. --posix-captures, -P فعال‌سازی استخراج زیرتطابق با گروه‌های گیرندهٔ سبک POSIX. نتیجه در آرایهٔ yybmatch با ظرفیت 2 * YYMAXNMATCH گردآوری شده، و yynmatch به تعداد گروه‌ها برای قاعدهٔ منطبق تنظیم می‌شود. --posix-captvars فعال‌سازی استخراج زیرتطابق با گروه‌های گیرندهٔ سبک POSIX. نتیجه در متغیرهای yytl و yytr برای گروه گیرندهٔ k-اُم گردآوری می‌شود. --recursive-functions استفاده از مدل کد مبتنی بر توابع هم‌بازگشتی (co-recursive)، که در آن هر وضعیت DFA یک تابع مجزاست که می‌تواند سایر توابع وضعیت یا خودش را فراخوانی کند. --reusable -r از نگارش 2.2 منسوخ شده است (بلوک‌های با قابلیت استفاده مجدد اکنون به طور پیش‌فرض مجاز هستند). --skeleton -S نادیده گرفتن کد واسط تعریف‌شده توسط کاربر و تولید یک برنامهٔ خودکفای "اسکلت" (skeleton). علاوه بر این، تولید فایل‌های ورودی با رشته‌های مشتق‌شده از گرامر منظم و نتایج تطابق فشرده‌شده که برای اعتبارسنجی رفتار برنامهٔ "اسکلت" روی تمام ورودی‌ها به کار می‌روند. این گزینه برای یافتن باگ‌ها در بهینه‌سازی‌ها و تولید کد مفید است. این گزینه تنها برای C پشتیبانی می‌شود..TP --storable-state -f تولید یک تحلیل‌گر لغوی که می‌تواند وضعیت درونی خود را ذخیره کند. این ویژگی در تحلیل‌گرهای لغوی مبتنی بر مدل push مفید است که در هنگام عدم وجود ورودی کافی توسط برنامه‌ای بیرونی متوقف شده و پس از در دسترس قرار گرفتن ورودی بیشتر، اجرای آن‌ها از سر گرفته می‌شود. در این حالت، کاربران باید علاوه بر این، دستورات اولیهٔ YYGETSTATE و YYSETSTATE را تعریف کنند، و متغیرهای yych، yyaccept و state باید بخشی از وضعیت ذخیره‌شدهٔ تحلیل‌گر لغوی باشند. --syntax FILE بارگذاری پیکربندی‌ها از FILE مشخص‌شده و اعمال آن‌ها روی فایل نحو پیش‌فرض. توجه داشته باشید که FILE می‌تواند تنها چند پیکربندی را تعریف کند (اگر برای اصلاح فایل نحو پیش‌فرض استفاده شود)، یا یک بک‌اند زبان کاملاً جدید را تعریف نماید (در حالت دوم توصیه می‌شود از گزینهٔ --lang none استفاده شود). --tags -T فعال‌سازی استخراج تطابق‌های فرعی با برچسب‌ها. --ucs2 --wide-chars -w تولید یک تحلیل‌گر لغوی که ورودی با کدگذاری UCS2 را می‌خواند. re2swift فرض می‌کند که دامنهٔ نویسه‌ها 0 -- 0xFFFF و اندازهٔ نویسه ۲ بایت است. این گزینه مستلزم --nested-ifs است. --utf8 --utf-8 -8 تولید یک تحلیل‌گر لغوی که ورودی با کدگذاری UTF-8 را می‌خواند. re2swift فرض می‌کند که دامنهٔ نویسه‌ها 0 -- 0x10FFFF و اندازهٔ نویسه ۱ بایت است. --utf16 --utf-16 -x تولید یک تحلیل‌گر لغوی که ورودی با کدگذاری UTF16 را می‌خواند. re2swift فرض می‌کند که دامنهٔ نویسه‌ها 0 -- 0x10FFFF و اندازهٔ نویسه ۲ بایت است. این گزینه مستلزم --nested-ifs است. --utf32 --unicode -u تولید یک تحلیل‌گر لغوی که ورودی با کدگذاری UTF32 را می‌خواند. re2swift فرض می‌کند که دامنهٔ نویسه‌ها 0 -- 0x10FFFF و اندازهٔ نویسه ۴ بایت است. این گزینه مستلزم --nested-ifs است. --verbose چاپ یک پیام کوتاه در صورت موفقیت. --vernum -V نمایش اطلاعات نسخه در قالب MMmmpp (نسخه اصلی، فرعی، وصله). --version -v نمایش اطلاعات نسخه. --single-pass -1 منسوخ شده است. کاری انجام نمی‌دهد (حالت تک‌گذره در حال حاضر پیش‌فرض است). --debug-output -d درج فراخوانی‌های YYDEBUG در کد تولیدشده. این قابلیت برای ردگیری اجرای تحلیل‌گر لغوی مفید است. --dump-adfa گزینهٔ اشکال‌زدایی: خروجی دادن DFA پس از تونل‌زنی (به قالب .dot). --dump-cfg گزینهٔ اشکال‌زدایی: خروجی دادن گراف جریان کنترل متغیرهای برچسب (به قالب .dot). --dump-closure-stats گزینهٔ اشکال‌زدایی: خروجی دادن آمار تعداد وضعیت‌ها در بستار. --dump-dfa-det گزینهٔ اشکال‌زدایی: خروجی دادن DFA بلافاصله پس از قطعی‌سازی (به قالب .dot). --dump-dfa-min گزینهٔ اشکال‌زدایی: خروجی دادن DFA پس از کمینه‌سازی (به قالب .dot). --dump-dfa-tagopt گزینهٔ اشکال‌زدایی: خروجی دادن DFA پس از بهینه‌سازی‌های برچسب (به قالب .dot). --dump-dfa-tree گزینهٔ اشکال‌زدایی: خروجی دادن DFA در حال ساخت با وضعیت‌هایی که به صورت درخت‌های تاریخچهٔ برچسب نمایش داده شده‌اند (به قالب .dot). --dump-dfa-raw گزینهٔ اشکال‌زدایی: خروجی دادن DFA در حال ساخت با مجموعه‌وضعیت‌های بسط‌یافته (به قالب .dot). --dump-interf گزینهٔ اشکال‌زدایی: خروجی دادن جدول تداخل حاصل از تحلیل زنده‌بودنِ متغیرهای برچسب. --dump-nfa گزینهٔ اشکال‌زدایی: خروجی دادن NFA (به قالب .dot). --emit-dot -D به جای خروجی معمول، گراف تحلیل‌گر لغوی را در قالب .dot تولید می‌کند. خروجی را می‌توان با کمک Graphviz به یک تصویر تبدیل کرد (مانند dot -Tpng -odfa.png dfa.dot). --dfa-minimization گزینهٔ داخلی: الگوریتم کمینه‌سازی DFA مورد استفاده توسط re2swift. گزینهٔ moore الگوریتم مور است (که پیش‌فرض است). گزینهٔ table الگوریتم "پر کردن جدول" است. هر دو الگوریتم باید صرف‌نظر از نام‌گذاری مجدد وضعیت‌ها، DFA یکسانی تولید کنند؛ پر کردن جدول ساده‌تر و بسیار کندتر است و به عنوان پیاده‌سازی مرجع عمل می‌کند. --eager-skip گزینهٔ داخلی: وادار کردن تحلیل‌گر لغوی تولیدشده به پیش بردن مشتاقانهٔ موقعیت ورودی -- بلافاصله پس از خواندن نماد ورودی. این گزینه رفتار پیش‌فرض را تغییر می‌دهد که در آن موقعیت ورودی به صورت تنبلانه -- پس از گذار به وضعیت بعدی -- به جلو برده می‌شود. --no-lookahead گزینهٔ داخلی، منسوخ شده. در گذشته برای فعال‌سازی الگوریتم TDFA(0) به کار می‌رفت. بر خلاف TDFA(1)، الگوریتم TDFA(0) از پیش‌نگری یک‌نمادی استفاده نمی‌کند. این الگوریتم عملیات ثبات‌ها را به جای گذارهای خروجی، روی گذارهای ورودی اعمال می‌کند. ارزیابی‌ها نشان دادند که الگوریتم TDFA(0) کارایی کمتری نسبت به TDFA(1) دارد. --no-optimize-tags گزینهٔ داخلی: غیرفعال کردن بهینه‌سازی متغیرهای برچسب (مفید برای اشکال‌زدایی). --posix-closure گزینهٔ داخلی: تعیین الگوریتم کوتاه‌ترین مسیر مورد استفاده برای ساخت بستار اپسیلون با معناشناسی رفع ابهام POSIX؛ مقدار gor1 (پیش‌فرض) نشان‌دهندهٔ الگوریتم گلدبرگ-رادزیک (Goldberg-Radzik) است و gtop نشان‌دهندهٔ الگوریتم "ترتیب توپولوژیکی سراسری" می‌باشد. --posix-prectable گزینهٔ داخلی: تعیین الگوریتم مورد استفاده برای محاسبهٔ جدول اولویت POSIX. الگوریتم complex جدول اولویت را در یک پیمایش از درخت تاریخچهٔ برچسب محاسبه می‌کند و دارای پیچیدگی درجه دو بر حسب تعداد وضعیت‌های TNFA است؛ این حالت پیش‌فرض است. الگوریتم naive در بدترین حالت دارای پیچیدگی درجه سه بر حسب تعداد وضعیت‌های TNFA است، اما بسیار ساده‌تر از complex بوده و ممکن است در موارد غیرپاتولوژیک کمی سریع‌تر باشد. --stadfa گزینهٔ داخلی، منسوخ شده. در گذشته برای فعال‌سازی الگوریتم staDFA به کار می‌رفت؛ تفاوت این الگوریتم با TDFA در این است که عملیات ثبات‌ها به جای قرارگیری روی گذارها، در وضعیت‌ها قرار می‌گیرند. ارزیابی‌ها نشان دادند که الگوریتم staDFA کارایی کمتری نسبت به TDFA دارد. --fixed-tags گزینهٔ داخلی: مشخص می‌کند که آیا بهینه‌سازی برچسب‌های ثابت باید روی همهٔ برچسب‌ها اعمال شود (all)، روی هیچ‌کدام (none)، یا فقط روی آن‌هایی که در الحاق سطح بالا قرار دارند (toplevel). مقدار پیش‌فرض all است. برچسب‌های "ثابت" برچسب‌هایی هستند که در فاصله‌ای معین نسبت به برچسبی دیگر (موسوم به "پایه") قرار دارند. در چنین حالتی تنها برچسب پایه نیاز به ردیابی دارد، و مقدار برچسب ثابت را می‌توان از حاصل جمع مقدار برچسب پایه با یک آفست ایستا محاسبه کرد. برای برچسب‌هایی که درون ساختار انتخاب (alternative) یا تکرار قرار دارند، بررسی این موضوع نیز لازم است که آیا برچسب پایه مقداری معادل عدم تطابق دارد یا خیر (در این صورت برچسب ثابت نیز باید بدون در نظر گرفتن آفست، روی عدم تطابق تنظیم شود). برای برچسب‌های واقع در الحاق سطح بالا، این بررسی لازم نیست زیرا آن‌ها همیشه مطابقت دارند. هشدارها را می‌توان به‌صورت جداگانه فعال یا غیرفعال کرد و یا به یک خطا تبدیل نمود. -W فعال‌سازی تمام هشدارها. -Werror تبدیل هشدارها به خطا. توجه داشته باشید که این گزینه به‌تنهایی هیچ هشداری را فعال نمی‌کند؛ بلکه تنها بر هشدارهایی تأثیر می‌گذارد که تاکنون فعال شده‌اند یا بعداً فعال خواهند شد. -W فعال‌سازی warning. -Wno- غیرفعال‌سازی warning. -Werror- فعال‌سازی warning و در نظر گرفتن آن به‌عنوان خطا (شامل -W نیز می‌شود). -Wno-error- این warning خاص را به‌عنوان خطا در نظر نگیر. این گزینه خودِ هشدار را غیرفعال نمی‌کند. -Wcondition-order هشدار در صورتی که برنامه تولیدشده فرضیات ضمنی درباره شماره‌گذاری شرط‌ها داشته باشد. کاربر باید از گزینه --header یا بلوک conditions برای تولید نگاشت نام‌های شرط به اعداد استفاده کند و سپس نام‌های شرط تولیدشده به‌صورت خودکار را به کار ببرد. -Wempty-character-class هشدار در صورتی که یک عبارت باقاعده شامل یک کلاس نویسه خالی باشد. تلاش برای تطبیق یک کلاس نویسه خالی بی‌معنی است: این تطبیق همیشه باید با شکست مواجه شود. با این حال، به دلایل سازگاری با گذشته، re2swift کلاس‌های نویسه خالی را مجاز دانسته و با آن‌ها مانند رشته‌های خالی رفتار می‌کند. از گزینه --empty-class برای تغییر رفتار پیش‌فرض استفاده کنید. -Wmatch-empty-string هشدار در صورتی که یک قاعده تهی‌پذیر باشد (با یک رشته خالی تطبیق یابد). اگر تحلیل‌گر لغوی در یک حلقه اجرا شود و تطبیق خالی ناخواسته باشد، تحلیل‌گر لغوی ممکن است به‌طور غیرمنتظره در یک حلقه بی‌پایان گیر کند. -Wswapped-range هشدار در صورتی که کران پایین یک بازه بزرگ‌تر از کران بالای آن باشد. رفتار پیش‌فرض جابه‌جا کردن بی‌سروصدای کران‌های بازه است. -Wundefined-control-flow هشدار در صورتی که برخی از رشته‌های ورودی باعث ایجاد جریان کنترل تعریف‌نشده در تحلیل‌گر لغوی شوند (الگوهای ناقص گزارش می‌شوند). این یک اشتباه رایج و خطرناک است. این مشکل را می‌توان به‌سادگی با افزودن قاعده پیش‌فرض * رفع کرد که کمترین اولویت را دارد، با هر واحد کد تطبیق می‌یابد، و همیشه یک واحد کد منفرد را مصرف می‌کند. -Wunreachable-rules هشدار درباره قواعدی که توسط قواعد دیگر تحت‌الشعاع قرار گرفته‌اند و هرگز تطبیق نخواهند یافت. -Wdeprecated-eof_rule هشدار درباره قواعد مستقل پایان ورودی $ که با تغییرات آینده شکسته خواهند شد و نیاز به اصلاح دارند. در حال حاضر این قواعد هنگام تداخل با قواعد دیگر تقدم دارند، اما پس از معرفی نماد تعمیم‌یافته پایان ورودی $، ترتیب تقدم تغییر خواهد کرد و این قواعد توسط سایر قواعد تحت‌الشعاع قرار خواهند گرفت. -Wuseless-escape هشدار در صورتی که نمادی گریزدهی شده باشد که نباید می‌شد. به‌طور پیش‌فرض، re2swift چنین گریزهایی را نادیده می‌گیرد، اما این مورد ممکن است نشان‌دهنده یک غلط تایپی یا خطایی در توالی گریز باشد. -Wnondeterministic-tags هشدار در صورتی که یک برچسب دارای درجه n-ام از غیرقطعی بودن باشد، جایی که n بزرگ‌تر از ۱ است. -Wsentinel-in-midrule هشدار در صورتی که نماد دیده‌بان در میانه یک قاعده رخ دهد --- این امر ممکن است باعث خواندن فراتر از انتهای بافر، خرابی‌ها یا خراب شدن حافظه در تحلیل‌گر لغوی تولیدشده شود. این هشدار تنها در صورتی کاربرد دارد که از روش دیده‌بان برای بررسی پایان ورودی استفاده شود. در صورت استفاده از پیکربندی re2c:sentinel، این هشدار به خطا تبدیل می‌شود. -Wundefined-syntax-config هشدار در صورتی که فایل نحو مشخص‌شده با گزینه --syntax فاقد تعاریف برخی از پیکربندی‌ها باشد. این به نگهداری فایل‌های نحو تعریف‌شده توسط کاربر کمک می‌کند: اگر نسخه جدیدی پیکربندی‌هایی را اضافه کند، فایل نحو قدیمی هشداری صادر خواهد کرد و کاربر مطلع خواهد شد. اگر برخی از پیکربندی‌ها استفاده نمی‌شوند و نیازی به تعریف ندارند، باید به‌صراحت روی تنظیم شوند. فایل‌های نحو (Syntax files) پشتیبانی از زبان‌های مختلف در re2c بر پایه ایده فایل‌های نحو استوار است. یک فایل نحو، فایلی پیکربندی است که نحو زبان مقصد را تعریف می‌کند -- نه کل زبان، بلکه بخش کوچکی از آن را که توسط کد تولیدشده استفاده می‌شود. فایل‌های نحو re2c را بسیار انعطاف‌پذیر می‌کنند، اما نباید به‌عنوان جایگزینی برای پیکربندی‌های re2c: استفاده شوند: هدف آن‌ها تعریف نحو زبان مقصد است، نه سفارشی‌سازی یک تحلیل‌گر لغوی خاص. همه زبان‌های پشتیبانی‌شده دارای فایل‌های نحو پیش‌فرضی هستند که بخشی از توزیع به شمار می‌روند (زیردایرکتوری include/syntax را ببینید)؛ آن‌ها همچنین در باینری re2swift تعبیه شده‌اند. کاربران می‌توانند یک فایل نحو سفارشی ارائه دهند که چند پیکربندی را برای یکی از زبان‌های پشتیبانی‌شده بازنویسی می‌کند، یا می‌توانند تمام پیکربندی‌ها را از نو تعریف کنند (در این صورت باید از گزینه --lang none استفاده شود). فایل‌های نحو حاوی پیکربندی‌هایی از چهار نوع مختلف هستند: فهرست ویژگی‌ها، پیکربندی‌های زبان، پیکربندی‌های درجا و الگوهای کد. فهرست ویژگی‌ها (Feature lists) چند پیکربندی فهرستی، ویژگی‌های گوناگون پشتیبانی‌شده توسط یک بک‌اند معین را تعریف می‌کنند، به‌گونه‌ای که re2swift در صورت تلاش کاربر برای فعال‌سازی یک ویژگی پشتیبانی‌نشده، خطای واضحی صادر کند: supported_apis فهرستی از APIهای پشتیبانی‌شده با عناصر ممکنِ simple، record و generic. supported_api_styles فهرستی از شیوه‌های API پشتیبانی‌شده با عناصر ممکنِ functions و free-form. supported_code_models فهرستی از مدل‌های کد پشتیبانی‌شده با عناصر ممکنِ goto-label، loop-switch و recursive-functions. supported_targets فهرستی از مقصدهای تولید کد پشتیبانی‌شده با عناصر ممکنِ code، dot و skeleton. supported_features فهرستی از ویژگی‌های پشتیبانی‌شده با عناصر ممکنِ nested-ifs، bitmaps، computed-gotos، case-ranges، monadic، unsafe، tags، captures و captvars. پیکربندی‌های زبان (Language configurations) چند پیکربندی بولی ویژگی‌هایی از زبان مقصد را توصیف می‌کنند که بر تجزیه‌کننده و تولیدکننده کد re2swift تأثیر می‌گذارند: semicolons غیرصفر اگر زبان پس از دستورها از نقطه‌ویرگول استفاده کند. backtick_quoted_strings غیرصفر اگر زبان دارای رشته‌های احاطه‌شده با بک‌تیک باشد. single_quoted_strings غیرصفر اگر زبان دارای رشته‌های احاطه‌شده با تک‌نقل‌قول باشد. indentation_sensitive غیرصفر اگر زبان به تورفتگی حساس باشد. wrap_blocks_in_braces غیرصفر اگر دستورهای مرکب باید در آکوالد قرار گیرند. پیکربندی‌های درجا (Inplace configurations) فایل‌های نحو مقادیر اولیه تمام پیکربندی‌های re2c: را تعریف می‌کنند، زیرا ممکن است برای زبان‌های مختلف متفاوت باشند. برای مشاهده فهرست کامل تمام پیکربندی‌های درجا و معنای آن‌ها به بخش پیکربندی‌ها مراجعه کنید. الگوهای کد (Code templates) الگوهای کد نحو زبان مقصد را تعریف می‌کنند. آن‌ها در یک زبان ویژه‌دامنه ساده با گرامر صوری زیر نوشته می‌شوند: code-template :: name '=' code-exprs ';' | CODE_TEMPLATE ';' | '' ';' code-exprs :: | code-exprs code-expr code-expr :: STRING | VARIABLE | optional | list optional :: '(' CONDITIONAL '?' code-exprs ')' | '(' CONDITIONAL '?' code-exprs ':' code-exprs ')' list :: '[' VARIABLE ':' code-exprs ']' | '[' VARIABLE '{' NUMBER '}' ':' code-exprs ']' | '[' VARIABLE '{' NUMBER ',' NUMBER '}' ':' code-exprs ']' یک الگوی کد توالی‌ای از رشته‌های لفظی، متغیرها، عناصر اختیاری و فهرست‌ها، یا ارجاعی به الگوی کد دیگر، یا مقدار ویژه است. متغیرها جای‌بان‌هایی هستند که در مرحله تولید کد جایگزین می‌شوند. متغیرهای فهرستی خاص هستند: هنگام بسط الگوهای فهرستی، re2swift عبارت‌های سمت راست دونقطه را چند بار تکرار می‌کند، و هر بار رخدادهای متغیر فهرست را با مقداری مخصوص به این تکرار جایگزین می‌سازد. فهرست‌ها دارای کران‌های اختیاری هستند (مقادیر منفی از انتها شمرده می‌شوند، مثلاً -1 به معنای آخرین عنصر است). نام‌های شرطی با یک نقطه شروع می‌شوند. هم شرط‌ها و هم متغیرها می‌توانند محلی (مخصوص به الگوی کد داده‌شده) یا سراسری (مجاز در تمام الگوهای کد) باشند. هنگامی که re2swift فایل نحو را می‌خواند، بررسی می‌کند که هر الگوی کد تنها از متغیرها و شرط‌هایی استفاده کند که در آن مجاز هستند. به‌عنوان مثال، الگوی کد زیر ساختار if-then-else را برای یک زبان C-مانند تعریف می‌کند: code:if_then_else = [branch{0}: topindent "if " cond " {" nl indent [stmt: stmt] dedent] [branch{1:-1}: topindent "} else" (.cond ? " if " cond) " {" nl indent [stmt: stmt] dedent] topindent "}" nl; در اینجا branch یک متغیر فهرستی است: branch{0} به شاخه نخست بسط می‌یابد (که ویژه است، زیرا بخش else ندارد)، و branch{1:-1} به تمام شاخه‌های باقی‌مانده (در صورت وجود) بسط پیدا می‌کند. stmt نیز یک متغیر فهرستی است: [stmt: stmt] یک فهرست تو‌در‌تو است که به فهرستی از دستورها در بدنه شاخه جاری بسط می‌یابد. topindent، indent، dedent و nl متغیرهای سراسری هستند، و .cond یک شرط محلی است (معنای آن‌ها در ادامه شرح داده شده است). این الگوی کد می‌تواند کد زیر را تولید کند: if x { // do something } else if y { // do something else } else { // don't do anything } در ادامه فهرستی از تمام الگوهای کد پشتیبانی‌شده توسط re2swift به همراه متغیرها و شرط‌های محلی آن‌ها آورده شده است. توجه داشته باشید که یک تعریف خاص می‌تواند از متغیرها و شرط‌های محلی استفاده کند، اما ملزم به انجام آن نیست. هر الگوی کد بدون استفاده باید روی تنظیم شود. code:var_local اعلان یا تعریف یک متغیر محلی. متغیرهای پشتیبانی‌شده: type (نوع متغیر)، name (نام آن) و init (مقدار اولیه، در صورت وجود). شرط‌ها: .init (اگر مقداردهی اولیه وجود داشته باشد، true). code:var_global مشابه code:var_local، با این تفاوت که در سطح بالا (top-level) استفاده می‌شود. code:const_local تعریف یک مقدار ثابت محلی. متغیرهای پشتیبانی‌شده: type (نوع مقدار ثابت)، name (نام آن) و init (مقدار اولیه). code:const_global مشابه code:const_local، با این تفاوت که در سطح بالا (top-level) استفاده می‌شود. code:array_local تعریف یک آرایه محلی (جدول). متغیرهای پشتیبانی‌شده: type (نوع عناصر آرایه)، name (نام آرایه)، size (اندازه آن)، row (یک متغیر فهرستی که به خودی خود کدی تولید نمی‌کند، اما عبارت فهرست را به تعداد سطرهای جدول بسط می‌دهد) و elem (یک متغیر فهرستی که به تمام عناصر جدول در سطر فعلی بسط می‌یابد -- برای قرارگیری به‌صورت تودرتو در فهرست row در نظر گرفته شده است). شرط پشتیبانی‌شده: .const (اگر آرایه تغییرناپذیر باشد، true). code:array_global مشابه code:array_local، با این تفاوت که در سطح بالا (top-level) استفاده می‌شود. code:array_elem ارجاع به عنصری از یک آرایه (جدول). متغیرهای پشتیبانی‌شده: array (نام آرایه) و index (اندیس عنصر). code:enum تعریف یک نوع شمارشی (ممکن است با استفاده از یک ساختار زبانی ویژه برای شمارش‌ها، یا صرفاً به‌صورت چند مقدار ثابت مستقل تعریف شود). متغیرهای پشتیبانی‌شده عبارتند از type (نوع شمارشی تعریف‌شده توسط کاربر یا نوع ثابت‌ها)، elem (متغیر فهرستی که به نام هر عضو بسط می‌یابد) و init (مقداردهی اولیه برای هر عضو). شرط‌ها: .init (اگر مقداردهی اولیه وجود داشته باشد، true). code:enum_elem عنصر نوع شمارشی (عضوی از یک نوع شمارشی تعریف‌شده توسط کاربر یا نام یک مقدار ثابت، بسته به نحوه تعریف code:enum). متغیرهای پشتیبانی‌شده عبارتند از name (نام عنصر) و type (نوع آن). code:assign دستور انتساب. متغیرهای پشتیبانی‌شده عبارتند از lhs (سمت چپ) و rhs (سمت راست). code:type_int نوع عدد صحیح علامت‌دار (signed integer). code:type_uint نوع عدد صحیح بدون علامت (unsigned integer). code:type_yybm نوع عناصر موجود در جدول yybm. code:type_yytarget نوع عناصر موجود در جدول yytarget. code:type_yyctable نوع عناصر موجود در جدول yyctable. code:cmp_eq عملگر "equals" (مساوی). code:cmp_ne عملگر "not equals" (نامساوی). code:cmp_lt عملگر "less than" (کوچک‌تر). code:cmp_gt عملگر "greater than" (بزرگ‌تر). code:cmp_le عملگر "less or equal" (کوچک‌تر یا مساوی). code:cmp_ge عملگر "greater or equal" (بزرگ‌تر یا مساوی). code:if_then_else دستور If-then-else با یک یا چند شاخه. متغیرهای پشتیبانی‌شده: branch (یک متغیر فهرستی که به خودی خود کدی تولید نمی‌کند، اما عبارت فهرست را به تعداد شاخه‌ها بسط می‌دهد)، cond (شرط شاخه فعلی) و stmt (یک متغیر فهرستی که به تمام دستورهای موجود در شاخه فعلی بسط می‌یابد). شرط‌ها: .cond (اگر شاخه فعلی دارای شرط باشد، true)، .many (اگر بیش از یک شاخه وجود داشته باشد، true). code:if_then_else_oneline حالت خاصی از code:if_then_else برای زمانی که تمام شاخه‌ها دستورهای تک‌خطی دارند. اگر این مورد باشد، به جای آن از code:if_then_else استفاده می‌شود. code:switch یک دستور switch با یک یا چند حالت (case). متغیرهای پشتیبانی‌شده: expr (عبارتی که روی آن switch انجام می‌شود) و case (یک متغیر فهرستی که به تمام گروه‌های case همراه با بلوک‌های کدشان بسط می‌یابد). code:switch_cases گروهی از حالت‌های switch که به یک بلوک کد واحد نگاشت می‌شوند. متغیرهای پشتیبانی‌شده عبارتند از case (یک متغیر فهرستی که به تمام حالت‌های این گروه بسط می‌یابد) و stmt (یک متغیر فهرستی که به تمام دستورهای موجود در بلوک کد بسط می‌یابد). code:switch_cases_oneline حالت خاصی از code:switch_cases برای زمانی که بلوک کد شامل یک دستور تک‌خطی است. اگر این مورد باشد، به جای آن از code:switch_cases استفاده می‌شود. code:switch_case_range یک حالت switch تکی که محدوده‌ای از مقادیر را پوشش می‌دهد (که ممکن است شامل یک مقدار واحد باشد). متغیر پشتیبانی‌شده: val (یک متغیر فهرستی که به تمام مقادیر موجود در محدوده بسط می‌یابد). شرط‌های پشتیبانی‌شده: .many (اگر بیش از یک مقدار در محدوده وجود داشته باشد، true) و .char_literals (اگر این یک switch روی نویسه‌های حرفی باشد، true -- برخی زبان‌ها نحو ویژه‌ای برای این حالت ارائه می‌دهند). code:switch_case_default حالت پیش‌فرض (default) در switch. code:loop حلقه‌ای که برای همیشه اجرا می‌شود (مگر اینکه از داخل بدنه حلقه متوقف شود). متغیرهای پشتیبانی‌شده: label (برچسب حلقه)، stmt (یک متغیر فهرستی که به تمام دستورهای بدنه حلقه بسط می‌یابد). code:continue دستور continue. متغیرهای پشتیبانی‌شده: label (برچسبی که اجرا باید از آن ادامه یابد). code:goto دستور goto. متغیرهای پشتیبانی‌شده: label (برچسب مقصد پرش). code:cgoto دستور goto محاسباتی (computed goto). متغیرهای پشتیبانی‌شده: array (جدول حاوی اطلاعات goto محاسباتی)، index (اندیس عنصر در جدول) و base (برچسب پایه، تنها در صورتی استفاده می‌شود که .cgoto.relative برابر با true باشد). code:cgoto:data عبارت مقداردهی اولیه برای یک عنصر واحد در جدول goto محاسباتی. متغیرهای پشتیبانی‌شده: label (برچسبی که برای مقداردهی اولیه عنصر فعلی استفاده می‌شود)، type (نوع پایه‌ای عناصر موجود در جدول) و base (برچسب پایه - تنها در صورتی استفاده می‌شود که .cgoto.relative برابر با true باشد). code:fndecl اعلان تابع. متغیرهای پشتیبانی‌شده: name (نام تابع)، type (نوع بازگشتی)، throw (استثناهای پرتاب‌شده توسط این تابع، به پیکربندی re2c:yyfn:throw نگاشت می‌شود)، arg (یک متغیر فهرستی که به خودی خود کدی تولید نمی‌کند، اما عبارت فهرست را به تعداد آرگومان‌های تابع بسط می‌دهد)، argname (نام آرگومان فعلی)، argtype (نوع آرگومان فعلی). شرط: .type (اگر این یک تابع غیر void باشد، true). code:fndef مشابه code:fndecl، اما برای تعریف تابع استفاده می‌شود، بنابراین یک متغیر فهرستی اضافی stmt دارد که به تمام دستورهای درون بدنه تابع بسط می‌یابد. code:fncall دستور فراخوانی تابع. متغیرهای پشتیبانی‌شده: name (نام تابع)، retval (مقدار سمت چپ یا l-value که مقدار بازگشتی در آن ذخیره می‌شود، در صورت وجود) و arg (یک متغیر فهرستی که به تمام آرگومان‌های تابع بسط می‌یابد). شرط‌ها: .args (اگر تابع دارای آرگومان باشد، true) و .retval (اگر مقدار بازگشتی نیاز به ذخیره شدن داشته باشد، true). code:tailcall دستور فراخوانی دمدمی (tail call). متغیرهای پشتیبانی‌شده: name (نام تابع) و arg (یک متغیر فهرستی که به تمام آرگومان‌های تابع بسط می‌یابد). شرط‌ها: .args (اگر تابع دارای آرگومان باشد، true) و .retval (اگر این یک تابع غیر void باشد، true). code:recursive_functions بدنه برنامه با مدل کد --recursive-functions. متغیرهای پشتیبانی‌شده: fn (یک متغیر فهرستی که به خودی خود هیچ کدی تولید نمی‌کند، اما عبارت فهرست را به تعداد توابع بسط می‌دهد)، fndecl (اعلان تابع فعلی) و fndef (تعریف تابع فعلی). code:fingerprint اثر انگشت (fingerprint) در بالای فایل خروجی تولیدشده. متغیرهای پشتیبانی‌شده: ver (نسخه re2swift که برای تولید این فایل استفاده شده است) و date (تاریخ تولید). code:line_info قالب دستورالعمل‌های خط (اگر روی تنظیم شده باشد، هیچ دستورالعملی تولید نمی‌شود). متغیرهای پشتیبانی‌شده: line (شماره خط) و file (نام فایل). code:abort دستوری که اجرای برنامه را بی‌درنگ متوقف (abort) می‌کند. code:yydebug دستور YYDEBUG، احتمالاً اختصاصی‌شده برای APIهای مختلف. متغیرهای پشتیبانی‌شده: YYDEBUG، yyrecord، yych (به پیکربندی‌های re2c: متناظر نگاشت می‌شوند)، state (شماره وضعیت DFA)..TP code:yypeek دستور YYPEEK، که ممکن است برای APIهای مختلف سفارشی‌سازی شده باشد. متغیرهای پشتیبانی‌شده: YYPEEK، YYCTYPE، YYINPUT، YYCURSOR، yyrecord، yych (نگاشت به پیکربندی‌های متناظر re2c:). شرط‌ها: .cast (درست اگر re2c:yych:conversion روی مقداری غیر از صفر تنظیم شده باشد). code:yyskip دستور YYSKIP، که ممکن است برای APIهای مختلف سفارشی‌سازی شده باشد. متغیرهای پشتیبانی‌شده: YYSKIP، YYCURSOR، yyrecord (نگاشت به پیکربندی‌های متناظر re2c:). code:yybackup دستور YYBACKUP، که ممکن است برای APIهای مختلف سفارشی‌سازی شده باشد. متغیرهای پشتیبانی‌شده: YYBACKUP، YYCURSOR، YYMARKER، yyrecord (نگاشت به پیکربندی‌های متناظر re2c:). code:yybackupctx دستور YYBACKUPCTX، که ممکن است برای APIهای مختلف سفارشی‌سازی شده باشد. متغیرهای پشتیبانی‌شده: YYBACKUPCTX، YYCURSOR، YYCTXMARKER، yyrecord (نگاشت به پیکربندی‌های متناظر re2c:). code:yyskip_yypeek دستور ترکیبی code:yyskip و code:yypeek (به‌طور پیش‌فرض code:yyskip و به دنبال آن code:yypeek). code:yypeek_yyskip دستور ترکیبی code:yypeek و code:yyskip (به‌طور پیش‌فرض code:yypeek و به دنبال آن code:yyskip). code:yyskip_yybackup دستور ترکیبی code:yyskip و code:yybackup (به‌طور پیش‌فرض code:yyskip و به دنبال آن code:yybackup). code:yybackup_yyskip دستور ترکیبی code:yybackup و code:yyskip (به‌طور پیش‌فرض code:yybackup و به دنبال آن code:yyskip). code:yybackup_yypeek دستور ترکیبی code:yybackup و code:yypeek (به‌طور پیش‌فرض code:yybackup و به دنبال آن code:yypeek). code:yyskip_yybackup_yypeek دستور ترکیبی code:yyskip، code:yybackup و code:yypeek (به‌طور پیش‌فرض ``code:yyskip`` و به دنبال آن code:yybackup و سپس code:yypeek). code:yybackup_yypeek_yyskip دستور ترکیبی code:yybackup، code:yypeek و code:yyskip (به‌طور پیش‌فرض ``code:yybackup`` و به دنبال آن code:yypeek و سپس code:yyskip). code:yyrestore دستور YYRESTORE، که ممکن است برای APIهای مختلف سفارشی‌سازی شده باشد. متغیرهای پشتیبانی‌شده: YYRESTORE، YYCURSOR، YYMARKER، yyrecord (نگاشت به پیکربندی‌های متناظر re2c:). code:yyrestorectx دستور YYRESTORECTX، که ممکن است برای APIهای مختلف سفارشی‌سازی شده باشد. متغیرهای پشتیبانی‌شده: YYRESTORECTX، YYCURSOR، YYCTXMARKER، yyrecord (نگاشت به پیکربندی‌های متناظر re2c:). code:yyrestoretag دستور YYRESTORETAG، که ممکن است برای APIهای مختلف سفارشی‌سازی شده باشد. متغیرهای پشتیبانی‌شده: YYRESTORETAG، YYCURSOR، yyrecord (نگاشت به پیکربندی‌های متناظر re2c:)، tag (نام متغیر برچسب که برای بازیابی موقعیت استفاده می‌شود). code:yyshift دستور YYSHIFT، که ممکن است برای APIهای مختلف سفارشی‌سازی شده باشد. متغیرهای پشتیبانی‌شده: YYSHIFT، YYCURSOR، yyrecord (نگاشت به پیکربندی‌های متناظر re2c:)، offset (تعداد واحدهای کد برای انتقال موقعیت فعلی). code:yyshiftstag دستور YYSHIFTSTAG، که ممکن است برای APIهای مختلف سفارشی‌سازی شده باشد. متغیرهای پشتیبانی‌شده: YYSHIFTSTAG، yyrecord، negative (نگاشت به پیکربندی‌های متناظر re2c:)، tag (متغیر برچسب که باید منتقل شود)، offset (تعداد واحدهای کد برای انتقال). شرط‌ها: .nested (درست اگر این یک برچسب تو‌در‌تو باشد -- در این حالت ممکن است مقدار آن برابر با re2c:tags:negative باشد، که نباید منتقل شود). code:yyshiftmtag دستور YYSHIFTMTAG، که ممکن است برای APIهای مختلف سفارشی‌سازی شده باشد. متغیرهای پشتیبانی‌شده: YYSHIFTMTAG (نگاشت به پیکربندی متناظر re2c:)، tag (متغیر برچسب که باید منتقل شود)، offset (تعداد واحدهای کد برای انتقال). code:yystagp دستور YYSTAGP، که ممکن است برای APIهای مختلف سفارشی‌سازی شده باشد. متغیرهای پشتیبانی‌شده: YYSTAGP، YYCURSOR، yyrecord (نگاشت به پیکربندی‌های متناظر re2c:)، tag (متغیر برچسب که باید به‌روزرسانی شود). code:yymtagp دستور YYMTAGP، که ممکن است برای APIهای مختلف سفارشی‌سازی شده باشد. متغیرهای پشتیبانی‌شده: YYMTAGP (نگاشت به پیکربندی متناظر re2c:)، tag (متغیر برچسب که باید به‌روزرسانی شود). code:yystagn دستور YYSTAGN، که ممکن است برای APIهای مختلف سفارشی‌سازی شده باشد. متغیرهای پشتیبانی‌شده: YYSTAGN، negative، yyrecord (نگاشت به پیکربندی‌های متناظر re2c:)، tag (متغیر برچسب که باید به‌روزرسانی شود). code:yymtagn دستور YYMTAGN، که ممکن است برای APIهای مختلف سفارشی‌سازی شده باشد. متغیرهای پشتیبانی‌شده: YYMTAGN (نگاشت به پیکربندی متناظر re2c:)، tag (متغیر برچسب که باید به‌روزرسانی شود). code:yycopystag دستور YYCOPYSTAG، که ممکن است برای APIهای مختلف سفارشی‌سازی شده باشد. متغیرهای پشتیبانی‌شده: YYCOPYSTAG، yyrecord (نگاشت به پیکربندی‌های متناظر re2c:)، lhs، rhs (متغیرهای برچسب سمت چپ و راست عملیات رونوشت). code:yycopymtag دستور YYCOPYMTAG، که ممکن است برای APIهای مختلف سفارشی‌سازی شده باشد. متغیرهای پشتیبانی‌شده: YYCOPYMTAG، yyrecord (نگاشت به پیکربندی‌های متناظر re2c:)، lhs، rhs (متغیرهای برچسب سمت چپ و راست عملیات رونوشت). code:yygetaccept دستور YYGETACCEPT، که ممکن است برای APIهای مختلف سفارشی‌سازی شده باشد. متغیرهای پشتیبانی‌شده: YYGETACCEPT، yyrecord (نگاشت به پیکربندی‌های متناظر re2c:)، var (نگاشت به پیکربندی re2c:yyaccept). code:yysetaccept دستور YYSETACCEPT، که ممکن است برای APIهای مختلف سفارشی‌سازی شده باشد. متغیرهای پشتیبانی‌شده: YYSETACCEPT، yyrecord (نگاشت به پیکربندی‌های متناظر re2c:)، var (نگاشت به پیکربندی re2c:yyaccept) و val (مقدار عددی قاعده پذیرفته‌شده). code:yygetcond دستور YYGETCOND، که ممکن است برای APIهای مختلف سفارشی‌سازی شده باشد. متغیرهای پشتیبانی‌شده: YYGETCOND، yyrecord (نگاشت به پیکربندی‌های متناظر re2c:)، var (نگاشت به پیکربندی re2c:yycond). code:yysetcond دستور YYSETCOND، که ممکن است برای APIهای مختلف سفارشی‌سازی شده باشد. متغیرهای پشتیبانی‌شده: YYSETCOND، yyrecord (نگاشت به پیکربندی‌های متناظر re2c:)، var (نگاشت به پیکربندی re2c:yycond) و val (شناسه عددی شرط). code:yygetstate دستور YYGETSTATE، که ممکن است برای APIهای مختلف سفارشی‌سازی شده باشد. متغیرهای پشتیبانی‌شده: YYGETSTATE، yyrecord (نگاشت به پیکربندی‌های متناظر re2c:)، var (نگاشت به پیکربندی re2c:yystate). code:yysetstate دستور YYSETSTATE، که ممکن است برای APIهای مختلف سفارشی‌سازی شده باشد. متغیرهای پشتیبانی‌شده: YYSETSTATE، yyrecord (نگاشت به پیکربندی‌های متناظر re2c:)، var (نگاشت به پیکربندی re2c:yystate) و val (شماره وضعیت). code:yylessthan دستور YYLESSTHAN، که ممکن است برای APIهای مختلف سفارشی‌سازی شده باشد. متغیرهای پشتیبانی‌شده: YYLESSTHAN، YYCURSOR، YYLIMIT، yyrecord (نگاشت به پیکربندی‌های متناظر re2c:)، need (تعداد واحدهای کد برای مقایسه در برابر آن). شرط: .many (درست اگر مقدار need بیشتر از یک باشد). code:yyend عبارت YYEND، که ممکن است برای APIهای مختلف سفارشی‌سازی شده باشد. متغیرهای پشتیبانی‌شده: YYEND، YYCURSOR، YYLIMIT. code:yybm_filter شرطی که برای پالایش مقادیر yych که توسط جدول yybm پوشش داده نشده‌اند استفاده می‌شود (همراه با گزینه --bitmaps به کار می‌رود). متغیر پشتیبانی‌شده: yych (نگاشت به پیکربندی re2c:yych). code:yybm_match قالب بررسی جدول yybm (تولید‌شده با گزینه --bitmaps). متغیرهای پشتیبانی‌شده: yybm، yych (نگاشت به پیکربندی‌های متناظر re2c:)، offset (آفست در جدول yybm که باید به yych افزوده شود) و mask (ماسک بیتی که باید روی ورودی جدول اعمال شود تا مقدار بولی مورد نیاز برای بررسی به دست آید) code:yytarget_filter شرطی که برای پالایش مقادیر yych که توسط جدول yytarget پوشش داده نشده‌اند استفاده می‌شود (همراه با گزینه --computed-gotos به کار می‌رود). متغیر پشتیبانی‌شده: yych (نگاشت به پیکربندی re2c:yych). در اینجا فهرستی از تمام متغیرهای سراسری مجاز در فایل‌های نحو آورده شده است: nl یک خط جدید. indent متغیری که هیچ کدی تولید نمی‌کند، اما اثر جانبی افزایش سطح تورفتگی را به همراه دارد..TP dedent متغیری که کدی تولید نمی‌کند، اما دارای اثر جانبی کاهش سطح تورفتگی است. topindent رشتهٔ تورفتگی برای دستور جاری. سطح تورفتگی توسط تولیدکنندهٔ کد ردیابی شده و به‌طور خودکار به‌روزرسانی می‌شود. در اینجا فهرستی از تمام شرط‌های سراسری مجاز در فایل‌های نحو آمده است: .api.simple درست است اگر از API ساده استفاده شود (--api simple یا re2c:api = simple). .api.generic درست است اگر از API عمومی استفاده شود (--api generic یا re2c:api = generic). .api.record درست است اگر از API رکورد استفاده شود (--api record یا re2c:api = record). .api_style.functions درست است اگر از سبک API تابع‌گونه استفاده شود (re2c:api-style = functions). .api_style.freeform درست است اگر از سبک API با فرم آزاد استفاده شود (re2c:api-style = free-form). .case_ranges درست است اگر ویژگی بازه‌های case فعال باشد (--case-ranges یا re2c:case-ranges = 1). .cgoto.relative درست است اگر شکل نسبی goto محاسباتی استفاده شود (--computed-gotos-relative یا re2c:cgoto:relative = 1). .code_model.goto_label درست است اگر مدل کد مبتنی بر goto/label استفاده شود (--goto-label). .code_model.loop_switch درست است اگر مدل کد مبتنی بر loop/switch استفاده شود (--loop-switch). .code_model.recursive_functions درست است اگر مدل کد مبتنی بر توابع بازگشتی استفاده شود (--recursive-function). .date درست است اگر اثرانگشت تولیدشده باید شامل تاریخ تولید باشد. .loop_label درست است اگر حلقه‌های تولیدشده توسط re2swift باید برچسب داشته باشند (re2c:label:yyloop روی یک رشتهٔ غیرخالی تنظیم شده باشد). .monadic درست است اگر کد تولیدشده باید به‌صورت مونادیک باشد (re2c:monadic = 1). این مورد تنها برای زبان‌های تابعی خالص کاربرد دارد. .start_conditions درست است اگر شرایط شروع فعال باشند (--start-conditions). .storable_state درست است اگر وضعیت قابل ذخیره‌سازی فعال باشد (--storable-state). .unsafe درست است اگر re2swift برای تولید کد سریع‌تر باید از بلوک‌های "unsafe" استفاده کند (--unsafe، re2c:unsafe = 1). این مورد تنها برای زبان‌هایی که دارای ویژگی "unsafe" هستند کاربرد دارد. .version درست است اگر اثرانگشت تولیدشده باید شامل نسخهٔ re2swift باشد. .yyfill.enable درست است اگر YYFILL فعال باشد (re2c:yyfill:enable = 1). .yyfn.throw درست است اگر پیکربندی re2c:yyfn:throw با یک رشتهٔ غیرخالی تعریف شده باشد. مدیریت پایان ورودی (HANDLING THE END OF INPUT) یکی از مشکلات اصلی برای تحلیل‌گر واژگانی (lexer)، دانستن زمان توقف است. چند شرط برای خاتمه وجود دارد: • تحلیل‌گر واژگانی ممکن است با قاعده‌ای تطابق یابد (شامل قاعدهٔ پیش‌فرض *) و به یک وضعیت پایانی برسد • تحلیل‌گر واژگانی ممکن است در تطبیق با هر قاعده‌ای ناموفق باشد و به یک وضعیت پیش‌فرض برسد • تحلیل‌گر واژگانی ممکن است به پایان ورودی برسد دو شرط نخست، تحلیل‌گر واژگانی را به شیوه‌ای «طبیعی» خاتمه می‌دهند: تحلیل‌گر به وضعیتی بدون گذارهای خروجی می‌رسد و تطبیق به‌طور خودکار متوقف می‌شود. شرط سوم، پایان ورودی، متفاوت است: این حالت ممکن است در هر وضعیتی رخ دهد و تحلیل‌گر واژگانی باید قادر به مدیریت آن باشد. بررسی پایان ورودی، روند کار عادی تحلیل‌گر واژگانی را دچار وقفه کرده و شاخه‌های شرطی را به برنامهٔ تولیدشده می‌افزاید؛ بنابراین لازم است تعداد چنین بررسی‌هایی به حداقل برسد. re2swift از چند روش مختلف برای مدیریت پایان ورودی پشتیبانی می‌کند. انتخاب روش مورد استفاده به پیچیدگی عبارات منظم، نیاز به بافرسازی، ملاحظات کارایی و سایر عوامل بستگی دارد. در ادامه فهرستی از این روش‌ها آمده است: • نویسهٔ نگهبان (Sentinel). این روش نیاز به بررسی‌های پایان ورودی را به‌کلی برطرف می‌کند. این روش ساده و کارآمد است، اما محدود به مواردی است که یک نویسهٔ «نگهبان» طبیعی وجود داشته باشد که هرگز در ورودی معتبر رخ ندهد. این نویسه ممکن است همچنان در ورودی نامعتبر رخ دهد، اما نباید توسط عبارات منظم مجاز دانسته شود، مگر شاید به عنوان آخرین نویسهٔ یک قاعده. نویسهٔ نگهبان به انتهای ورودی ضمیمه شده و به عنوان یک سیگنال توقف عمل می‌کند: زمانی که تحلیل‌گر واژگانی این نویسه را بخواند، یا یک خطای نحوی است یا پایان ورودی. در هر دو حالت، تحلیل‌گر واژگانی باید متوقف شود. این روش زمانی استفاده می‌شود که YYFILL با re2c:yyfill:enable = 0; غیرفعال شده و re2c:eof مقدار پیش‌فرض -1 را داشته باشد. • نویسهٔ نگهبان به همراه بررسی کران‌ها (Sentinel with bounds checks). این روش همگانی (generic) است: امکان پردازش هر ورودی را بدون محدودیت روی عبارات منظم فراهم می‌کند. ایدهٔ کار کاهش تعداد بررسی‌های پایان ورودی با انجام آن‌ها تنها روی نویسه‌هایی خاص است. مشابه روش «نگهبان»، یکی از نویسه‌ها به عنوان «نگهبان» انتخاب شده و به انتهای ورودی ضمیمه می‌شود. با این حال، هیچ محدودیتی در مورد محل وقوع نویسهٔ نگهبان وجود ندارد (در واقع هر نویسه‌ای می‌تواند به عنوان نگهبان انتخاب شود). زمانی که تحلیل‌گر واژگانی این نویسه را می‌خواند، علاوه بر آن یک بررسی کران انجام می‌دهد. اگر موقعیت فعلی در محدودهٔ مجاز باشد، تحلیل‌گر واژگانی تطبیق را از سر گرفته و با نویسهٔ نگهبان مانند یک نویسهٔ معمولی رفتار می‌کند. در غیر این صورت، YYFILL را فراخوانی می‌کند (مگر اینکه غیرفعال شده باشد). اگر ورودی بیشتری ارائه شود، تحلیل‌گر واژگانی نویسهٔ پایانی را مجدداً تطبیق داده و به‌گونه‌ای ادامه می‌دهد که گویی نگهبان اصلاً وجود نداشته است. در غیر این صورت، باید پایان واقعی ورودی باشد و تحلیل‌گر واژگانی متوقف می‌شود. این روش زمانی استفاده می‌شود که re2c:eof مقداری غیرمنفی داشته باشد (باید روی مقدار عددیِ نویسهٔ نگهبان تنظیم شود). استفاده از YYFILL اختیاری است. • بررسی کران‌ها به همراه لایه‌گذاری (Bounds checks with padding). این روش همگانی است و ممکن است از روش «نگهبان به همراه بررسی کران‌ها» سریع‌تر باشد، اما پیچیده‌تر نیز هست. ایدهٔ کار این است که وضعیت‌های DFA به مؤلفه‌های قویاً همبند (SCCها) افراز شوند و برای هر SCC یک بررسی منفرد به اندازهٔ کافی نویسه تولید شود تا طولانی‌ترین مسیر بدون حلقه در این SCC را پوشش دهد. این کار تعداد بررسی‌ها را کاهش می‌دهد، اما مشکلی با تکواژهای (lexemes) کوتاه در انتهای ورودی ایجاد می‌کند، زیرا بررسی به نویسه‌های کافی برای پوشش طولانی‌ترین تکواژ نیاز دارد. این مشکل را می‌توان با لایه‌گذاری ورودی با چند نویسهٔ ساختگی که پسوند معتبری برای یک تکواژ تشکیل نمی‌دهند (تا تحلیل‌گر واژگانی نتواند با آن‌ها تطبیق یابد) برطرف کرد. طول لایه‌گذاری باید YYMAXFILL باشد که با یک بلوک max تولید می‌شود. اگر ورودی کافی وجود نداشته باشد، تحلیل‌گر واژگانی YYFILL را فراخوانی می‌کند که باید حداقل تعداد نویسه‌های لازم را تأمین کند یا بازنگردد. این روش در صورتی به کار می‌رود که YYFILL فعال باشد و re2c:eof برابر -1 باشد (این پیکربندی پیش‌فرض است). • بررسی‌های سفارشی (Custom checks). رابط Generic API به کاربر اجازه می‌دهد عملیات پایه‌ای مانند خواندن یک نویسه را رونویسی کند، که امکان گنجاندن بررسی‌های پایان ورودی را به عنوان بخشی از آن‌ها فراهم می‌سازد. این رویکرد خطازاست و باید با احتیاط استفاده شود. برای استفاده از یک روش سفارشی، API عمومی را با --api custom یا re2c:api = custom; فعال کرده و بررسی‌های پیش‌فرض کران‌ها را با re2c:yyfill:enable = 0; یا re2c:yyfill:check = 0; غیرفعال کنید. زیربخش‌های زیر شامل مثالی از هر روش هستند..SS نگهبان (Sentinel) این مثال از یک نویسه نگهبان (sentinel character) برای مدیریت پایان ورودی استفاده می‌کند. این برنامه واژه‌های جداشده با فاصله را در یک رشته پایان‌یافته با null شمارش می‌کند. نویسه نگهبان null است: آخرین نویسه از هر رشته ورودی است، و در هیچ‌یک از قواعد در میانه یک لکسم (lexeme) مجاز دانسته نشده است (به‌ویژه، در بازه‌های نویسه‌ای که نادیده‌گرفتن آن آسان است گنجانده نشده است). اگر یک null در میانه رشته رخ دهد، یک خطای نحو (syntax error) است و لکسر با قاعده پیش‌فرض * تطابق می‌یابد، اما داده‌ای فراتر از پایان ورودی را نخواهد خواند و دچار فروپاشی (crash) نخواهد شد (از هشدار -Wsentinel-in-midrule و پیکربندی re2c:sentinel برای راستی‌آزمایی این مورد استفاده کنید). پیکربندی re2c:yyfill:enable = 0; از تولید بررسی‌های محدوده (bounds checks) و فراخوانی‌های YYFILL جلوگیری می‌کند. // re2swift $INPUT -o $OUTPUT // Expects a null-terminated string. func lex(_ yyinput: UnsafePointer) -> Int? { var yycursor = 0, count = 0 loop: while true { /*!re2c re2c:yyfill:enable = 0; [a-z]+ { count += 1 continue loop } [ ]+ { continue loop } [\x00] { return count } * { return nil } */ } } func test(_ str: StaticString, _ expect: Int?) { assert(lex(str.utf8Start) == expect) } test("", 0) test("one two three", 3) test("f0ur", nil) نگهبان با بررسی‌های محدوده (Sentinel with bounds checks) این مثال از نویسه نگهبان همراه با بررسی‌های محدوده برای مدیریت پایان ورودی استفاده می‌کند (این روش در نسخه 1.2 اضافه شد). این برنامه رشته‌های محصور در تک‌نقل‌قول (single-quoted) که با فاصله از هم جدا شده‌اند را می‌شمارد. نویسه نگهبان null است که با پیکربندی re2c:eof = 0; تعیین می‌شود. همانند روش sentinel، نویسه null آخرین نویسه هر رشته ورودی است، اما در میانه یک قاعده نیز مجاز است (برای مثال، 'aaa\0aa'\0 ورودی معتبری است، اما 'aaa\0 یک خطای نحوی است). بررسی‌های محدوده در هر حالتی که یک نویسه ورودی را تطبیق می‌دهد تولید می‌شوند، اما دامنه آن‌ها به شاخه‌ای که null را مدیریت می‌کند محدود است. بررسی‌های محدوده با API عمومی به صورت YYLIMIT <= YYCURSOR یا YYLESSTHAN(1) هستند. اگر شرط بررسی برقرار (true) باشد، لکسر به پایان ورودی رسیده است و باید متوقف شود (از آنجا که ورودی در یک بافر جای می‌گیرد، YYFILL با re2c:yyfill:enable = 0; غیرفعال شده است؛ برای مشاهده مثالی که از YYFILL استفاده می‌کند، به بخش YYFILL with sentinel مراجعه کنید). رسیدن به پایان ورودی سه حالت را پیش می‌آورد: اگر لکسر در حالت اولیه باشد، با قاعده پایان ورودی $ مطابقت می‌یابد؛ در غیر این صورت ممکن است به یک قاعده تطبیق‌یافته قبلی (از جمله قاعده پیش‌فرض *) بازگردد یا به یک حالت پیش‌فرض برود، که موجب هشدار -Wundefined-control-flow می‌شود. // re2swift $INPUT -o $OUTPUT // Expects a null-terminated string. func lex(_ yyinput: UnsafePointer, _ length: Int) -> Int? { var yycursor = 0, yylimit = length, yymarker = 0 var count = 0 loop: while true { /*!re2c re2c:eof = 0; re2c:yyfill:enable = 0; str = ['] ([^'\\] | [\\][^])* [']; str { count += 1 continue loop } [ ]+ { continue loop } * { return nil } $ { return count } */ } } func test(_ str: StaticString, _ expect: Int?) { assert(lex(str.utf8Start, str.utf8CodeUnitCount) == expect) } test("", 0); test("'qu\0tes' 'are' 'fine: \\'' ", 3); test("'unterminated\\'", nil); بررسی‌های محدوده با پدینگ (Bounds checks with padding) این مثال از بررسی‌های محدوده به همراه پدینگ (padding) برای مدیریت پایان ورودی استفاده می‌کند (این روش به‌طور پیش‌فرض فعال است). این برنامه رشته‌های محصور در تک‌نقل‌قول که با فاصله جدا شده‌اند را می‌شمارد. یک پدینگ متشکل از نویسه‌های null به تعداد YYMAXFILL به انتهای ورودی افزوده شده است، که در آن مقدار YYMAXFILL به‌طور خودکار توسط یک بلوک max تولید می‌شود. الزامی به استفاده از null برای پدینگ وجود ندارد --- تا زمانی که نویسه‌ها پسوند معتبری برای یک لکسم تشکیل ندهند، می‌توان از هر نویسه‌ای استفاده کرد (در این مثال، پدینگ نباید شامل تک‌نقل‌قول باشد، چرا که ممکن است با پسوند یک رشته محصور در تک‌نقل‌قول اشتباه گرفته شود). یک قاعده توقف ("stop") وجود دارد که با نخستین نویسه پدینگ (null) تطبیق یافته و لکسر را خاتمه می‌دهد (توجه داشته باشید که بررسی می‌کند آیا null در ابتدای پدینگ قرار دارد یا خیر، در غیر این صورت یک خطای نحوی است). بررسی‌های محدوده تنها در برخی از حالت‌ها تولید می‌شوند که توسط مؤلفه‌های قویاً همبند خودکار (اتوماتون) زیرین تعیین می‌گردند. بررسی‌ها با API عمومی به صورت (YYLIMIT - YYCURSOR) < n یا YYLESSTHAN(n) هستند، که در آن n حداقل تعداد نویسه‌های مورد نیاز برای ادامه کار لکسر است (این همچنین بدان معناست که بررسی محدوده بعدی حداکثر در n نویسه دیگر رخ خواهد داد). اگر شرط بررسی برقرار باشد، لکسر به پایان ورودی رسیده است و YYFILL(n) را فراخوانی می‌کند که یا باید حداقل n نویسه ورودی را فراهم کند یا بازگشتی نداشته باشد. در این مثال YYFILL همیشه ناموفق است و لکسر را با یک خطا متوقف می‌کند (که مشکلی نیست، زیرا ورودی درون یک بافر جا می‌شود). برای مثالی که بافر ورودی را با استفاده از YYFILL دوباره پر می‌کند، به بخش YYFILL with padding مراجعه کنید. // re2swift $INPUT -o $OUTPUT /*!max:re2c*/ func lex(_ str: UnsafeBufferPointer) -> Int? { let length = str.count // Make a copy of the string with YYMAXFILL zeroes at the end. let yyinput = ContiguousArray(str) + repeatElement(0, count: yymaxfill) var yycursor = 0, yylimit = length + yymaxfill var count = 0 loop: while true { /*!re2c re2c:YYFILL = "return nil"; str = ['] ([^'\\] | [\\][^])* [']; str { count += 1 continue loop } [\x00] { // Check that it's the sentinel, not some unexpected null. if yycursor - 1 == length { return count } else { return nil } } [ ]+ { continue loop } * { return nil } */ } } func test(_ str: StaticString, _ expect: Int?) { str.withUTF8Buffer { assert(lex($0) == expect) } } test("", 0) test("'qu\0tes' 'are' 'fine: \\'' ", 3) test("'unterminated\\'", nil) test("'unexpected \0 null\\'", nil) این مثال از یک روش سفارشی مدیریت پایان ورودی (end-of-input) بر پایهٔ API عمومی (generic API) استفاده می‌کند. برنامه رشته‌های محصور در نقل‌قول تکی (single-quoted) را که با فاصله از هم جدا شده‌اند می‌شمارد. این برنامه مشابه مثال sentinel است، با این تفاوت که ورودی با نویسهٔ تهی پایان نیافته است (null-terminated نیست). برای جبران نبود نویسهٔ نگهبان (sentinel) در انتهای ورودی، YYPEEK بازتعریف شده است تا پیش از خواندن نویسهٔ بعدی ورودی، یک بررسی محدوده (bounds check) انجام دهد. این روش ناکارآمد است زیرا بررسی‌ها بسیار مکرر انجام می‌شوند. اگر شرط بررسی برقرار نباشد، YYPEEK نویسهٔ واقعی را برمی‌گرداند؛ در غیر این صورت یک نویسهٔ نگهبان ساختگی بازمی‌گرداند. // re2swift $INPUT -o $OUTPUT import Foundation func lex(_ str: Data) -> Int? { var cursor = 0, limit = str.count var count = 0 loop: while true { /*!re2c re2c:api = generic; re2c:yyfill:enable = 0; re2c:YYSKIP = "cursor += 1"; re2c:YYPEEK = "cursor < limit ? str[cursor] : 0"; // fake null [a-z]+ { count += 1 continue loop } [\x00] { return count } [ ]+ { continue loop } * { return nil} */ } } func test(_ str: String, _ expect: Int?) { // For the sake of example create a string without terminating null. assert(lex(Data(str.utf8)) == expect) } test("", 0) test("one two three ", 3) test("f0ur", nil) پر کردن مجدد بافر (BUFFER REFILLING) نیاز به بافرسازی زمانی رخ می‌دهد که ورودی را نتوان به‌طور یک‌جا در حافظه نگاشت کرد: یا بیش از حد بزرگ است، یا به صورت جریانی دریافت می‌شود (مانند خواندن از یک سوکت). تکنیک معمول در چنین مواردی، تخصیص یک بافر حافظه با اندازهٔ ثابت و پردازش ورودی در تکه‌هایی (chunks) است که در بافر جا می‌شوند. هنگامی که تکهٔ فعلی پردازش شد، به بیرون منتقل شده و داده‌های جدید وارد می‌شوند. در عمل این موضوع تا حدی پیچیده‌تر است، زیرا وضعیت تحلیل‌گر لغوی (lexer) تنها از یک موقعیت ورودی تشکیل نشده، بلکه شامل مجموعه‌ای از موقعیت‌های مرتبط است: • مکان‌نما (cursor): نویسهٔ بعدی ورودی برای خواندن (YYCURSOR در API اشاره‌گر C یا YYSKIP/YYPEEK در generic API) • حد (limit): موقعیتِ پس از آخرین نویسهٔ موجود ورودی (YYLIMIT در API اشاره‌گر C، یا مدیریت‌شده به‌طور ضمنی توسط YYLESSTHAN در generic API) • نشانه‌گر (marker): موقعیت تازه‌ترین تطابق، در صورت وجود (YYMARKER در API پیش‌فرض یا YYBACKUP/YYRESTORE در generic API) • توکن (token): ابتدای لکسم (lexeme) فعلی (در re2swift API ضمنی است، چرا که برای عملکرد عادی لکسر نیازی به آن نیست و می‌تواند توسط کاربر تعریف و به‌روزرسانی شود) • نشانه‌گر زمینه (context marker): موقعیت زمینهٔ انتهایی (YYCTXMARKER در API اشاره‌گر C یا YYBACKUPCTX/YYRESTORECTX در generic API) • متغیرهای برچسب (tag variables): موقعیت‌های زیرتطابق (تعریف‌شده با بلوک‌های stags و mtags و توابع اولیهٔ generic API شامل YYSTAGP/YYSTAGN/YYMTAGP/YYMTAGN) همهٔ این موارد در هر حالتی به کار نمی‌روند، اما در صورت استفاده، باید توسط YYFILL به‌روزرسانی شوند. تمام موقعیت‌های فعال در بازهٔ بین token و cursor قرار دارند؛ بنابراین هر چیزی میان ابتدای بافر و token را می‌توان دور ریخت، بازهٔ token تا limit باید به ابتدای بافر منتقل شود، و فضای خالی انتهای بافر باید با داده‌های جدید پر شود. برای جلوگیری از فراخوانی‌های مکرر YYFILL، بهتر است تا حد امکان نویسه‌های ورودی بیشتری پر شود (حتی اگر نویسه‌های کمتری برای از سرگیری لکسر کافی باشد). جزئیات پیاده‌سازی YYFILL بسته به روش مدیریت EOF مورداستفاده کمی متفاوت است: حالت قاعدهٔ EOF تا حدی ساده‌تر از حالت بررسی محدوده همراه با لایه‌گذاری (padding) است. همچنین توجه داشته باشید که اگر گزینهٔ -f --storable-state استفاده شود، YYFILL معناشناسی کمی متفاوتی خواهد داشت (که در بخش مربوط به وضعیت قابل ذخیره شرح داده شده است). YYFILL با نویسهٔ نگهبان (YYFILL with sentinel) اگر از قاعدهٔ EOF استفاده شود، YYFILL یک سازوکار اولیّهٔ شبه‌تابع است که هیچ آرگومانی نمی‌پذیرد و مقداری بازمی‌گرداند که با صفر مقایسه می‌شود. فراخوانی YYFILL با شرط YYLIMIT <= YYCURSOR در API اشاره‌گر C و YYLESSTHAN() در generic API تحریک می‌شود. یک مقدار بازگشتی غیرصفر به این معنی است که YYFILL شکست خورده است. یک فراخوانی موفق YYFILL باید حداقل یک نویسه را تامین کرده و موقعیت‌های ورودی را بر این اساس تنظیم کند. Limit همیشه باید روی یک واحد پس از آخرین موقعیت ورودی در بافر تنظیم شود، و نویسهٔ موجود در موقعیت limit باید نماد نگهبان تعیین‌شده توسط پیکربندی re2c:eof باشد. تصاویر زیر مکان‌های نسبی موقعیت‌های ورودی در بافر را قبل و بعد از فراخوانی YYFILL نشان می‌دهند (نماد نگهبان با # مشخص شده است، و تصویر دوم حالتی را نشان می‌دهد که ورودی کافی برای پر کردن کل بافر وجود ندارد). <-- 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 در اینجا مثالی از برنامه‌ای آورده شده است که فایل ورودی input.txt را در تکه‌های ۴۰۹۶ بایتی می‌خواند و از قاعدهٔ EOF استفاده می‌کند. // re2swift $INPUT -o $OUTPUT import Foundation struct Input { static let bufferSize = 4095 var file: FileHandle var yyinput = ContiguousArray(repeating: 0, count: Self.bufferSize + 1) var yylimit = Self.bufferSize var yycursor = Self.bufferSize var yymarker = Self.bufferSize var token = -1 var eof = false } extension Input { mutating func lex() -> Int? { var count = 0 loop: while true { self.token = self.yycursor /*!re2c re2c:api = record; re2c:eof = 0; re2c:yyrecord = "self"; re2c:YYFILL = "self.fill() == .ok"; str = ['] ([^'\\] | [\\][^])* [']; str { count += 1 continue loop } [ ]+ { continue loop } $ { return count } * { return nil } */ } } mutating func fill() -> FillStatus { guard !self.eof else { return .eof } let shift = self.token let used = self.yylimit - self.token let free = Self.bufferSize - used // Error: Lexeme too long. In the real world we can reallocate a larger buffer. if self.token < 1 { return .longLexeme } // Shift buffer contents, discarding everything up to the current lexeme. self.yyinput.replaceSubrange(.. <-- 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 -> در اینجا مثالی از برنامه‌ای آمده است که فایل ورودی input.txt را در قطعات ۴۰۹۶ بایتی می‌خواند و از بررسی محدوده‌ها (bounds-checking) به همراه لایه‌گذاری استفاده می‌کند. // re2swift $INPUT -o $OUTPUT import Foundation /*!max:re2c*/ struct Input { static let bufferSize = 4096 - yymaxfill var file: FileHandle var yyinput = ContiguousArray(repeating: 0, count: Self.bufferSize + yymaxfill) var yylimit = Self.bufferSize var yycursor = Self.bufferSize var token = -1 var eof = false } extension Input { mutating func lex() -> Int? { var count = 0 loop: while true { self.token = self.yycursor /*!re2c re2c:api = record; re2c:yyrecord = "self"; re2c:YYFILL = "if self.fill(@@) != .ok { return nil }"; str = ['] ([^'\\] | [\\][^])* [']; [\x00] { // Check that it is the sentinel, not some unexpected null. return self.token == self.yylimit - yymaxfill ? count : nil; } str { count += 1 continue loop } [ ]+ { continue loop } * { return nil } */ } } mutating func fill(_ need: Int) -> FillStatus { guard !self.eof else { return .eof } let shift = self.token let used = self.yylimit - self.token let free = Self.bufferSize - used // Error: Lexeme too long. In the real world we can reallocate a larger buffer. if self.token < need { return .longLexeme } // Shift buffer contents, discarding everything up to the current lexeme. self.yyinput.replaceSubrange(.. add zero padding // so that the lexer can access characters at the end of buffer. self.yylimit += read if read < free { self.eof = true self.yyinput.withUnsafeMutableBytes { _ = memset($0.baseAddress! + self.yylimit, 0, yymaxfill) } self.yylimit += yymaxfill } return .ok } enum FillStatus { case ok, eof, longLexeme } } let fileName = "input" let content = "'qu\0tes' 'are' 'fine: \\'' "; // Prepare input file: a few times the size of the buffer, // containing strings with zeroes and escaped quotes. guard FileManager.default.createFile( atPath: fileName, contents: Data(String(repeating: content, count: Input.bufferSize).utf8) ) else { fatalError("failed to write file \"\(fileName)\"") } // Number of quoted strings written to file let count = 3 * Input.bufferSize // Initialize lexer state // This immediately triggers YYFILL, as the check `in.yycursor < in.yylimit` fails. guard let file = FileHandle(forReadingAtPath: fileName) else { throw NSError(domain: NSCocoaErrorDomain, code: CocoaError.fileReadNoSuchFile.rawValue) } var `in` = Input(file: file) // Run the lexer assert(`in`.lex() == count) // Cleanup: remove input file try file.close() try FileManager.default.removeItem(atPath: fileName) بلوک‌های چندگانه (Multiple blocks) گاهی اوقات لازم است چندین تحلیل‌گر لغوی (lexer) مرتبط با یکدیگر داشته باشیم (برای مثال، اگر یک ماشین حالت سطح بالا وجود داشته باشد که بین حالت‌های مختلف لکسر گذار انجام می‌دهد). این کار می‌تواند با استفاده از چندین بلوک به‌هم‌پیوستهٔ re2swift پیاده‌سازی شود. گزینهٔ دیگر استفاده از شرایط شروع (start conditions) است. پیاده‌سازی اتصالات بین بلوک‌ها به زبان مقصد بستگی دارد. در زبان‌هایی که دستور goto دارند (مانند C/C++ و Go) می‌توان همهٔ بلوک‌ها را در یک تابع قرار داد، به طوری که پیشوند هر یک از آن‌ها یک برچسب باشد. گذار از یک بلوک به بلوک دیگر یک goto ساده است. در زبان‌هایی که goto ندارند (مانند Rust)، لازم است از یک حلقه به همراه switch روی متغیر حالت استفاده شود، مشابه حلقه/switch مربوط به yystate که توسط re2swift تولید می‌شود؛ یا اینکه هر بلوک درون یک تابع قرار گرفته و از فراخوانی توابع استفاده گردد. مثال زیر از چندین بلوک برای تجزیهٔ اعداد دودویی (binary)، هشت‌هشتی (octal)، ده‌دهی (decimal) و شانزده‌شانزدهی (hexadecimal) استفاده می‌کند. هر مبنا بلوک مخصوص به خود را دارد. بلوک اولیه مبنا را تعیین کرده و کنترل را به سایر بلوک‌ها هدایت می‌کند. پیکربندی‌های مشترک در یک بلوک مجزا در ابتدای برنامه تعریف شده‌اند؛ این پیکربندی‌ها توسط سایر بلوک‌ها به ارث برده می‌شوند. // re2swift $INPUT -o $OUTPUT func parseUInt32(_ yyinput: UnsafePointer) -> UInt32? { var yycursor = 0, yymarker = 0 /*!re2c re2c:yyfill:enable = 0; "0b" / [01] { return parseBin() } "0" { return parseOct() } "" / [1-9] { return parseDec() } "0x" / [0-9a-fA-F] { return parseHex() } * { return nil } */ func add(_ accum: inout UInt64, _ charOrigin: UnicodeScalar, _ base: UInt64, _ offset: UInt64 = 0) { let digit = yyinput[yycursor - 1] - UInt8(ascii: charOrigin) accum = min(accum * base + UInt64(digit) + offset, UInt64(UInt32.max) + 1) } func parseBin() -> UInt32? { var accum: UInt64 = 0 parse: while true { /*!re2c [01] { add(&accum, "0", 2); continue parse } * { return UInt32(exactly: accum) } */ } } func parseOct() -> UInt32? { var accum: UInt64 = 0 parse: while true { /*!re2c [0-7] { add(&accum, "0", 8); continue parse } * { return UInt32(exactly: accum) } */ } } func parseDec() -> UInt32? { var accum: UInt64 = 0 parse: while true { /*!re2c [0-9] { add(&accum, "0", 10); continue parse } * { return UInt32(exactly: accum) } */ } } func parseHex() -> UInt32? { var accum: UInt64 = 0 parse: while true { /*!re2c [0-9] { add(&accum, "0", 16); continue parse } [a-f] { add(&accum, "a", 16, 10); continue parse } [A-F] { add(&accum, "A", 16, 10); continue parse } * { return UInt32(exactly: accum) } */ } } } assert(parseUInt32("") == nil) assert(parseUInt32("1234567890") == 1234567890) assert(parseUInt32("0b1101") == 13) assert(parseUInt32("0x7Fe") == 2046) assert(parseUInt32("0644") == 420) assert(parseUInt32("9999999999") == nil) شرایط شروع (Start conditions) شرایط شروع با گزینهٔ --start-conditions فعال می‌شوند. آن‌ها روشی برای کدگذاری چندین خودکارهٔ (اتوماتای) به‌هم‌پیوسته درون یک بلوک re2swift یکسان فراهم می‌کنند. هر شرط متناظر با یک خودکارهٔ منفرد است و یک نام یکتا دارد که توسط کاربر مشخص می‌شود، و همچنین یک شمارهٔ داخلی یکتا که توسط re2swift تعریف می‌گردد. این شماره‌ها برای جابه‌جایی میان شرایط به کار می‌روند: کد تولیدشده از پیش‌ساخته‌های YYGETCOND و YYSETCOND برای دریافت شرط کنونی یا تنظیم آن به شمارهٔ داده‌شده استفاده می‌کند. برای تولید شناسه‌های عددی شرایط، از بلوک conditions، گزینهٔ --header یا پیکربندی re2c:header استفاده کنید. پیکربندی re2c:cond:enumprefix پیشوند شناسه‌های تولیدشده را مشخص می‌کند. در حالت شرط، هر قاعده باید دارای پیشوندی از فهرستی از نام‌های شرایط جداشده با کاما درون قلاب‌های شکسته، یا نویسهٔ عام <*> برای نشان دادن همهٔ شرایط باشد. نحو قواعد به‌صورت زیر گسترش می‌یابد: < condition-list > regular-expression code قاعده‌ای که در هر شرط موجود در condition-list ادغام می‌شود. این قاعده با regular-expression مطابقت می‌یابد و code مرتبط را اجرا می‌کند. < condition-list > regular-expression => condition code قاعده‌ای که در هر شرط موجود در condition-list ادغام می‌شود. این قاعده با regular-expression مطابقت می‌یابد، شرط کنونی را به condition تنظیم می‌کند و code مرتبط را اجرا می‌کند. < condition-list > regular-expression :=> condition قاعده‌ای که در هر شرط موجود در condition-list ادغام می‌شود. این قاعده با regular-expression مطابقت می‌یابد و بلافاصله به condition گذار می‌کند (هیچ عمل معنایی وجود ندارد). < condition-list > !action code قاعده‌ای که code را به مکان تعیین‌شده توسط action در هر شرط موجود در condition-list پیوند می‌دهد (برای انواع مختلف کنش‌ها به بخش actions مراجعه کنید). code قاعده‌ای که code را به ابتدای کنش‌های معناییِ تمام قواعد برای هر شرط در condition-list اضافه می‌کند. این نحو منسوخ شده است و در عوض باید از کنش !pre_rule استفاده شود (دقیقاً همان کار را انجام می‌دهد). < > code قاعده‌ای که یک شرط ورودی ویژه با شمارهٔ صفر و نام "0" ایجاد می‌کند که قبل از پرش به سایر شرایط، code را اجرا می‌کند. این نحو منسوخ شده است و باید به جای آن از کنش !entry استفاده شود (کنترل دقیق‌تری فراهم می‌کند، زیرا کد می‌تواند بر مبنای هر شرط مشخص شود و می‌توان مستقیماً بدون گذر از توزیع شرط، به شروع شرط پرش کرد). < > => condition code مشابه قاعدهٔ قبلی، با این تفاوت که condition بعدی را تعیین می‌کند. < > :=> condition مشابه قاعدهٔ قبلی، با این تفاوت که هیچ کد مرتبطی ندارد و بلافاصله به condition پرش می‌کند. کدی که re2swift برای شرایط تولید می‌کند بستگی به این دارد که re2swift از روش goto/label استفاده می‌کند یا روش loop/switch برای کدگذاری خودکاره‌ها. در زبان‌هایی که دستور goto دارند (مانند C/C++ و Go)، شرایط به‌طور طبیعی به‌صورت بلوک‌هایی از کد با پیشوند برچسب‌هایی به فرم yyc_ پیاده‌سازی می‌شوند، که در آن cond نام یک شرط است (پیشوند برچسب را می‌توان با re2c:cond:prefix تغییر داد). گذارها بین شرایط با استفاده از goto و برچسب‌های شرایط پیاده‌سازی می‌شوند. پیش از همهٔ شرایط، re2swift یک switch اولیه روی YYGETSTATE تولید می‌کند که به وضعیت شروع شرط کنونی پرش می‌کند. قواعد میان‌بُر :=> از switch اولیه گذر کرده و مستقیماً به شرط مشخص‌شده پرش می‌کنند (می‌توان از re2c:cond:goto برای تغییر رفتار پیش‌فرض استفاده کرد). قواعد دارای کنش‌های معنایی به‌طور خودکار به شرط بعدی پرش نمی‌کنند؛ این کار باید توسط کد کنش تعریف‌شده توسط کاربر انجام شود. در زبان‌هایی که goto ندارند (مانند Rust)، re2swift از متغیر yystate برای ذخیرهٔ شماره‌های شرایط استفادهٔ مجدد می‌کند. هر شرط یک شناسهٔ عددی برابر با شمارهٔ وضعیت آغازین خود دریافت می‌کند، و یک switch بین شرایط هیچ تفاوتی با یک switch بین وضعیت‌های DFA یک شرط منفرد ندارد. نیازی به یک switch شرط اولیهٔ مجزا نیست. (از آنجا که رویکرد مشابهی برای پیاده‌سازی وضعیت‌های قابل ذخیره استفاده می‌شود، در صورتی که هم از وضعیت‌های قابل ذخیره و هم از شرایط استفاده شود، YYGETCOND/YYSETCOND زائد خواهند بود). برنامهٔ زیر از شرایط شروع برای تجزیهٔ اعداد دودویی، هشت‌هشتی، ده‌دهی و شانزده‌شانزدهی استفاده می‌کند. یک بلوک منفرد وجود دارد که در آن هر مبنا شرط مخصوص به خود را دارد، و شرط اولیه به همهٔ آن‌ها متصل است. متغیر تعریف‌شده توسط کاربر cond شمارهٔ شرط کنونی را ذخیره می‌کند؛ این متغیر با شمارهٔ شرط اولیه‌ای که توسط بلوک conditions تولید شده است مقداردهی اولیه می‌شود. // re2swift $INPUT -o $OUTPUT -c /*!conditions:re2c*/ func parseUInt32(_ yyinput: UnsafePointer) -> UInt32? { var yycursor = 0, yymarker = 0, yycond = yycinit var accum: UInt64 = 0 loop: while true { /*!re2c re2c:yyfill:enable = 0; '0b' / [01] :=> bin "0" :=> oct "" / [1-9] :=> dec '0x' / [0-9a-fA-F] :=> hex [01] { add("0", 2); continue loop } [0-7] { add("0", 8); continue loop } [0-9] { add("0", 10); continue loop } [0-9] { add("0", 16); continue loop } [a-f] { add("a", 16, 10); continue loop } [A-F] { add("A", 16, 10); continue loop } "\x00" { return UInt32(exactly: accum) } <*> * { return nil } */ } func add(_ charOrigin: UnicodeScalar, _ base: UInt64, _ offset: UInt64 = 0) { let digit = yyinput[yycursor - 1] - UInt8(ascii: charOrigin) accum = min(accum * base + UInt64(digit) + offset, UInt64(UInt32.max) + 1) } } assert(parseUInt32("") == nil) assert(parseUInt32("1234567890") == 1234567890) assert(parseUInt32("0b1101") == 13) assert(parseUInt32("0x7Fe") == 2046) assert(parseUInt32("0644") == 420) assert(parseUInt32("9999999999") == nil) با گزینهٔ --storable-state، ابزار re2swift تحلیل‌گر لغوی (lexer) تولید می‌کند که می‌تواند وضعیت فعلی خود را ذخیره کرده، به فراخواننده بازگردد، و بعداً عملیات را دقیقاً از همان‌جایی که رها کرده بود از سر بگیرد. حالت پیش‌فرضِ کارکرد در re2swift مدل "pull" (کِششی) است، که در آن تحلیل‌گر لغوی هر زمان که به ورودی بیشتری نیاز داشته باشد آن را «می‌کِشد». این ممکن است در مواردی که ورودی به صورت تکه‌تکه در دسترس قرار می‌گیرد غیرقابل‌قبول باشد (به عنوان مثال، اگر تحلیل‌گر لغوی توسط تجزیه‌کننده (parser) فراخوانی شود، یا اگر برنامهٔ تحلیل‌گر لغوی از طریق پروتکل سوکت با برنامهٔ دیگری ارتباط برقرار کند که باید پیش از ارسال پیام بعدی منتظر پاسخ از تحلیل‌گر لغوی بماند). ویژگی وضعیت قابل ذخیره‌سازی دقیقاً برای چنین مواردی در نظر گرفته شده است: این ویژگی امکان تولید تحلیل‌گرهای لغوی را فراهم می‌کند که در یک مدل "push" (رانشی) کار می‌کنند. هنگامی که تحلیل‌گر لغوی به ورودی بیشتری نیاز دارد، وضعیت خود را ذخیره کرده و به فراخواننده بازمی‌گردد. بعداً، زمانی که ورودی بیشتری در دسترس قرار گرفت، فراخواننده تحلیل‌گر لغوی را دقیقاً از همان نقطه‌ای که متوقف شده بود از سر می‌گیرد. در مقایسه با مدل "pull"، چند تغییر لازم است: • تعریف دستورهای اولیهٔ YYSETSTATE() و YYGETSTATE(state). • تعریف متغیرهای yych، yyaccept (در صورت استفاده) و state به عنوان بخشی از وضعیت پایدار (persistent) تحلیل‌گر لغوی. متغیر state باید با -1 مقداردهی اولیه شود. • دستور YYFILL باید به جای تلاش برای تأمین ورودی بیشتر، به برنامهٔ بیرونی بازگردد. کد بازگشتی باید نشان دهد که تحلیل‌گر لغوی به ورودی بیشتری نیاز دارد. • برنامهٔ بیرونی باید موقعیت‌هایی را که تحلیل‌گر لغوی به ورودی بیشتری نیاز دارد تشخیص داده و واکنش مناسب نشان دهد. • استفادهٔ اختیاری از بلوک getstate برای تولید سوییچِ YYGETSTATE جدا از تحلیل‌گر لغوی اصلی. این مورد فقط برای زبان‌هایی کار می‌کند که دارای goto هستند (نه در حالت --loop-switch). • استفاده از re2c:eof و روش sentinel with bounds checks برای مدیریت پایان ورودی. روش مبتنی بر لایه‌گذاری (padding) ممکن است کار نکند زیرا مشخص نیست چه زمانی باید لایه‌گذاری اضافه شود: پایان فعلی ورودی ممکن است پایان نهایی ورودی نباشد، و اضافه کردن زودهنگام لایه‌گذاری ممکن است نشانهٔ لغویِ حریصانه‌ای (greedy lexeme) را که تا حدی خوانده شده قطع کند. علاوه بر این، به دلیل منطق سطح‌بالای برنامه، دریافت ورودی بیشتر ممکن است به پردازش نشانهٔ لغوی در انتهای بافر بستگی داشته باشد (که از قبل به دلیل شرایط پایان ورودی مسدود شده است). در اینجا مثالی از یک تحلیل‌گر لغوی با مدل "push" آورده شده است که خواندن بسته‌ها از یک سوکت را شبیه‌سازی می‌کند. تحلیل‌گر لغوی تا زمان رسیدن به پایان ورودی تکرار می‌شود و به تابع فراخواننده بازمی‌گردد. تابع فراخواننده با «ارسال» بستهٔ بعدی ورودی بیشتری فراهم کرده و تحلیل لغوی را از سر می‌گیرد. این فرایند زمانی که تمام بسته‌ها ارسال شدند، یا زمانی که خطایی رخ دهد، متوقف می‌شود. // re2swift $INPUT -o $OUTPUT -f import Foundation func log(_ items: Any..., separator: String = " ", terminator: String = "\n") { #if DEBUG var stderr = FileHandle.standardError print(items, separator: separator, terminator: terminator, to: &stderr) #endif } extension FileHandle: TextOutputStream { public func write(_ string: String) { self.write(Data(string.utf8)) } } struct State { // Use a small buffer to cover the case when a lexeme doesn't fit, // in a real world use case use a larger buffer. static let bufferSize = 10 let file: FileHandle // Extra '\0' byte on buffer acts as terminator. var yyinput = ContiguousArray(repeating: 0, count: Self.bufferSize + 1) var yylimit = Self.bufferSize var yycursor = Self.bufferSize var yymarker = Self.bufferSize var token = Self.bufferSize var yystate = -1 } extension State { mutating func lex(recv: inout Int) -> Status { var yych: UInt8 = 0 lex: while true { self.token = self.yycursor /*!re2c re2c:api = record; re2c:eof = 0; re2c:variable:yyrecord = "self"; re2c:YYFILL = "return .waiting"; packet = [a-z]+[;]; * { return .badPacket } $ { return .end } packet { recv += 1 continue lex } */ } } mutating func fill() -> Status { let used = self.yylimit - self.token let free = Self.bufferSize - used // Error: No space. In the real world we can reallocate a larger buffer. if free < 1 { return .bigPacket } // Shift buffer contents, discarding everything up to the current lexeme. let shift = self.token self.yyinput.replaceSubrange(.. State.Status { // Create a "socket" (open the same file for reading and writing). let fname: String = "pipe" guard FileManager.default.createFile(atPath: fname, contents: nil), let fw = FileHandle(forWritingAtPath: fname) else { fatalError("cannot open '\(fname)'") } guard let fr = FileHandle(forReadingAtPath: fname) else { fatalError("cannot read file '\(fname)'") } defer { // Cleanup: remove input file. do { try fw.close() try fr.close() try FileManager.default.removeItem(atPath: fname) } catch { fatalError("error on file cleanup: \(error.localizedDescription)") } } var state = State(file: fr) // 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. var send = 0, recv = 0 while true { switch state.lex(recv: &recv) { case .end: log("done: got \(recv)") assert(recv == send) return .end case .waiting: log("waiting...") if send < packets.count { log("sent packet \(send)") packets[send].withUTF8Buffer { do { try fw.write(contentsOf: $0) } catch { fatalError("cannot write to \(fname): \(error.localizedDescription)") } } send += 1 } let status = state.fill() state.yyinput.withUnsafeBytes { let buf = $0.bindMemory(to: CChar.self) log("queue: '\(String(utf8String: buf.baseAddress!) ?? "")'") } if status == .bigPacket { log("error: packet too big") return .bigPacket } assert(status == .ready) case .badPacket: log("error: ill-formed packet") return .badPacket default: fatalError("unreachable") } } } assert(test([]) == .end) assert(test([ "zero;", "one;", "two;", "three;", "four;" ]) == .end) assert(test([ "zer0;" ]) == .badPacket) assert(test([ "looooooooooong;" ]) == .bigPacket) log("all tests completed successfully") بلوک‌های چندبار مصرف به شکل /*!rules:re2c[:] ... */ یا %{rules[:] ... %} را می‌توان به هر تعداد دفعات دوباره استفاده کرد و با سایر بلوک‌های re2swift ترکیب نمود. مقدار اختیاری است. یک بلوک قواعد را می‌توان در یک بلوک یا دستورالعمل use به کار برد. کد یک بلوک قواعد در هر نقطه از استفاده تولید می‌شود. بلوک‌های use با /*!use:re2c[:] ... */ یا %{use[:] ... %} تعریف می‌شوند. مقدار اختیاری است: اگر مشخص نشده باشد، بلوک قواعد مرتبط، جدیدترین بلوک موجود خواهد بود (چه نام‌گذاری شده و چه بدون نام). یک بلوک use می‌تواند تعاریف نام‌گذاری‌شده، پیکربندی‌ها و قواعد خاص خودش را بیفزاید. یک مورد کاربرد مهم برای بلوک‌های use، تحلیل‌گر لغوی (lexer) است که از چندین کدگذاری ورودی مختلف پشتیبانی می‌کند: یک بلوک قواعد یکسان، چندین بار همراه با پیکربندی‌های مختص هر کدگذاری استفاده می‌شود (مثال زیر را ببینید). دستورالعمل استفاده درون‌بلوکی !use:; می‌تواند از داخل یک بلوک re2swift به کار رود. این دستورالعمل، بلوک ارجاع‌شده را با بلوک فعلی ادغام می‌کند. اگر برخی از قواعد و پیکربندی‌های ادغام‌شده با موارد تعریف‌شده قبلی هم‌پوشانی داشته باشند، تداخل‌ها به شیوه معمول حل می‌شوند: نخستین قاعده تقدم دارد، و جدیدترین پیکربندی جایگزین موارد پیشین می‌شود. یک استثنا، قواعد ویژه *، $ و (در حالت شرط) هستند که برای آن‌ها تعریف محلی بلوک، هرگونه تعریف به ارث‌رسیده را لغو می‌کند. دستورالعمل use امکان ترکیب بلوک‌های مختلف re2swift را با یکدیگر در یک بلوک فراهم می‌سازد (مثال زیر را ببینید). بلوک‌های نام‌گذاری‌شده و دستورالعمل استفاده درون‌بلوکی در نسخه 2.2 برنامه re2swift اضافه شدند. از آن نسخه به بعد، بلوک‌های چندبار مصرف به‌طور پیش‌فرض مجاز هستند (نیازی به گزینه خاصی نیست). پیش از نسخه 2.2، حالت استفاده مجدد با گزینه -r --reusable فعال می‌شد. پیش از نسخه 1.2 بلوک‌های چندبار مصرف نمی‌توانستند با بلوک‌های عادی ترکیب شوند. مثالی از یک دستورالعمل !use // re2swift $INPUT -o $OUTPUT // This example shows how to combine reusable re2c blocks: two blocks // ('colors' and 'fish') are merged into one. The 'salmon' rule occurs // in both blocks; the 'fish' block takes priority because it is used // earlier. Default rule * occurs in all three blocks; the local (not // inherited) definition takes priority. /*!rules:re2c:colors * { fatalError("unreachable") } "red" | "salmon" | "magenta" { return .color } */ /*!rules:re2c:fish * { fatalError("unreachable") } "haddock" | "salmon" | "eel" { return .fish } */ func lex(_ yyinput: UnsafePointer) -> What { var yycursor = 0, yymarker = 0 /*!re2c re2c:yyfill:enable = 0; !use:fish; !use:colors; * { return .dunno } // Overrides inherited '*' rules */ } enum What { case color, fish, dunno } assert(lex("salmon") == .fish) assert(lex("what?") == .dunno) مثالی از یک بلوک /*!use:re2c ... */ // re2swift $INPUT -o $OUTPUT --input-encoding utf8 // 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; "∀x ∃y" { return true } * { return false } */ func lexUTF8(_ yyinput: [UInt8]) -> Bool { var yycursor = 0, yymarker = 0 /*!use:re2c re2c:YYCTYPE = UInt8; re2c:encoding:utf8 = 1; */ } func lexUTF32(_ yyinput: [UInt32]) -> Bool { var yycursor = 0, yymarker = 0 /*!use:re2c re2c:YYCTYPE = UInt32; re2c:encoding:utf32 = 1; */ } assert(lexUTF8([ 0xe2, 0x88, 0x80, 0x78, 0x20, 0xe2, 0x88, 0x83, 0x79 ])) // UTF-8 assert(lexUTF32([ 0x00002200, 0x00000078, 0x00000020, 0x00002203, 0x00000079 ])) // UTF-32 استخراج زیرتطابق (Submatch extraction) برنامه re2swift دو گزینه برای استخراج زیرتطابق دارد. Tags گزینه اول استفاده از برچسب‌ها (tags) مستقل به شکل @stag یا #mtag است، که در آن stag و mtag نام‌های اختیاری تعریف‌شده توسط کاربر هستند. برچسب‌ها با گزینه -T --tags یا پیکربندی re2c:tags = 1 فعال می‌شوند. برچسب‌ها از لحاظ معنایی نشانگر موقعیت هستند: می‌توانند در هر کجای یک عبارت منظم درج شوند و به موقعیت متناظر (یا موقعیت‌های چندگانه) در رشته ورودی متصل گردند. برچسب‌های S به آخرین موقعیت منطبق متصل می‌شوند و برچسب‌های m به فهرستی از موقعیت‌ها متصل می‌گردند (ممکن است در زیرعبارت‌های تکرار استفاده شوند، جایی که یک موقعیت واحد در عبارت منظم با چندین موقعیت در رشته ورودی متناظر است). تمام برچسب‌ها باید توسط کاربر، یا به‌صورت دستی یا با کمک بلوک‌های svars و mvars، تعریف شوند. اگر بیش از یک روش برای تطبیق برچسب‌ها با ورودی وجود داشته باشد، ابهام با استفاده از راهبرد ابهام‌زدایی چپ‌ترین حریصانه (leftmost greedy) برطرف می‌شود. Captures گزینه دوم استفاده از گروه‌های گیرانداز (capturing groups) است. آن‌ها با گزینه --captures یا پیکربندی re2c:captures = 1 فعال می‌شوند. دو گونه برای سیاست‌های مختلف رفع ابهام وجود دارد؛ --leftmost-captures (پیش‌فرض) برای سیاست چپ‌ترین حریصانه، و --posix-captures برای سیاست طولانی‌ترین تطابق POSIX است. در این حالت همه زیرعبارت‌های داخل پرانتز به عنوان گروه‌های گیرانداز در نظر گرفته می‌شوند و می‌توان از علامت تعجب برای مشخص کردن گروه‌های غیرگیرانداز استفاده کرد: (! ... ). با گزینه --invert-captures یا پیکربندی re2c:invert-captures = 1، معنای علامت تعجب معکوس می‌شود. تعداد گروه‌ها برای قاعده منطبق در متغیر yynmatch ذخیره می‌شود (کل عبارت منظم، گروه شماره صفر است)، و نتایج زیرتطابق در آرایه yypmatch ذخیره می‌گردند. هم yynmatch و هم yypmatch باید توسط کاربر تعریف شوند و اندازه yypmatch باید حداقل [yynmatch * 2] باشد. از بلوک maxnmatch برای تعریف YYMAXNMATCH استفاده کنید، ثابتی که برابر با بیشینه مقدار yynmatch در میان همه قواعد است. Captvars روش دیگر برای استفاده از گروه‌های گیرانداز، گزینه --captvars یا پیکربندی re2c:captvars = 1 است. تنها تفاوت با --captures در نحوه ذخیره‌سازی نتایج زیرتطابق توسط کد تولیدشده است: به‌جای yynmatch و yypmatch، برنامه re2swift متغیرهای yytl و yytr را برای k-امین گروه گیرانداز تولید می‌کند (کاربر باید این متغیرها را با استفاده از یک بلوک svars اعلان کند). گیراندازی با متغیرها از دو سیاست رفع ابهام پشتیبانی می‌کند: --leftmost-captvars یا re2c:leftmost-captvars = 1 برای سیاست چپ‌ترین حریصانه (حالت پیش‌فرض) و --posix-captvars یا re2c:posix-captvars برای سیاست طولانی‌ترین تطابق POSIX. در لایه‌های زیرین، تمام این گزینه‌ها به برچسب‌ها و اتوماتای متناهی معین برچسب‌دار با پیش‌نگری (Tagged Deterministic Finite Automata with Lookahead یا TDFA) تبدیل می‌شوند. ایده اصلی TDFA به حداقل رساندن سربار استخراج زیرتطابق است. در حالت حداقلی، اگر هیچ برچسب یا گروه گیراندازی در یک عبارت منظم وجود نداشته باشد، TDFA صرفاً یک DFA معمولی است. اگر تعداد برچسب‌ها در حد اعتدال باشد، سربار به‌ندرت محسوس است. اتوماتای TDFA تولیدشده از تعدادی متغیر برچسب استفاده می‌کند که مستقیماً به برچسب‌ها نگاشت نمی‌شوند: یک متغیر واحد ممکن است برای برچسب‌های متفاوتی به کار رود، و یک برچسب ممکن است به چندین متغیر برای نگهداری تمام مقادیر ممکن خود نیاز داشته باشد. در نهایت، ابهام رفع شده و به ازای هر برچسب تنها یک متغیر نهایی باقی می‌ماند. متغیرهای برچسب باید با استفاده از بلوک‌های stags یا mtags تعریف شوند. اگر وضعیت لکسر ذخیره شود، متغیرهای برچسب نیز باید بخشی از آن باشند. آن‌ها همچنین باید توسط YYFILL به‌روزرسانی شوند. برچسب‌های S از عملیات زیر پشتیبانی می‌کنند: • ذخیره موقعیت ورودی در یک برچسب s: دستور t = YYCURSOR با API اشاره‌گر C یا عملیات تعریف‌شده توسط کاربر YYSTAGP(t) با API عمومی • ذخیره مقدار پیش‌فرض در یک برچسب s: دستور t = NULL با API اشاره‌گر C یا عملیات تعریف‌شده توسط کاربر YYSTAGN(t) با API عمومی • کپی یک برچسب s به دیگری: t1 = t2 برچسب‌های M از عملیات زیر پشتیبانی می‌کنند: • الحاق موقعیت ورودی به یک برچسب m: عملیات تعریف‌شده توسط کاربر YYMTAGP(t) هم با API پیش‌فرض و هم با API عمومی • الحاق مقدار پیش‌فرض به یک برچسب m: عملیات تعریف‌شده توسط کاربر YYMTAGN(t) هم با API پیش‌فرض و هم با API عمومی • کپی یک برچسب m به دیگری: t1 = t2 برچسب‌های S را می‌توان به صورت مقادیر اسکالر (اشاره‌گرها یا آفست‌ها) پیاده‌سازی کرد. برچسب‌های M به نمایش پیچیده‌تری نیاز دارند، چرا که باید دنباله‌ای از مقادیر برچسب را ذخیره کنند. ساده‌ترین و ناکارآمدترین نمایش یک برچسب m، یک فهرست (آرایه، بردار) از مقادیر برچسب است؛ نمایش کارآمدتر، ذخیره تمام برچسب‌های m در یک درخت پیشوندی است که به صورت آرایه‌ای از گره‌های (v, p) نمایش داده می‌شود، که در آن v مقدار برچسب و p اشاره‌گری به گره والد است. در اینجا یک مثال ساده از استفاده از برچسب‌های s برای تجزیه نسخه‌بندی معنایی متشکل از سه مؤلفه عددی آورده شده است: major، minor، patch (مورد آخر اختیاری است). برای یک مثال پیچیده‌تر که از YYFILL استفاده می‌کند، به بخش زیر مراجعه کنید. // re2swift $INPUT -o $OUTPUT struct SemVer: Equatable { var major: Int, minor: Int, patch: Int } func lex(_ yyinput: UnsafePointer) -> SemVer? { let tagNone = -1 var yycursor = 0, yymarker = 0 // Final tag variables available in semantic action. /*!svars:re2c format = "var @@ = tagNone\n"; */ // Intermediate tag variables used by the lexer (must be autogenerated). /*!stags:re2c format = 'var @@ = tagNone\n'; */ /*!re2c re2c:yyfill:enable = 0; re2c:tags = 1; num = [0-9]+; @t1 num @t2 "." @t3 num @t4 ("." @t5 num)? [\x00] { let s2n = { (range: Range) in range.reduce(0) { accum, idx in accum * 10 + Int(yyinput[idx] - UInt8(ascii: "0")) } } return SemVer( major: s2n(t1..(repeating: 0, count: Self.bufferSize + 1) var yylimit = Self.bufferSize var yycursor = Self.bufferSize var yymarker = Self.bufferSize var token = Self.bufferSize // Intermediate tag variables must be part of the lexer state passed to YYFILL. // They don't correspond to tags and should be autogenerated by re2c. /*!stags:re2c format = " var @@ = Self.tagNone\n"; */ var eof = false let file: FileHandle } extension Input { mutating func lex() -> [SemVer]? { var semVers = [SemVer]() semVers.reserveCapacity(Self.bufferSize) // Final tag variables available in semantic action. /*!svars:re2c format = " var @@: Int\n"; */ parse: while true { self.token = self.yycursor /*!re2c re2c:api = record; re2c:eof = 0; re2c:tags = 1; re2c:yyrecord = "self"; re2c:YYFILL = "self.fill() == .ok"; num = [0-9]+; num @t1 "." @t2 num @t3 ("." @t4 num)? [\n] { semVers.append(SemVer( major: self.s2n(self.token..) -> Int { self.yyinput[range].reduce(0) { accum, digit in accum * 10 + Int(digit - UInt8(ascii: "0")) } } mutating func fill() -> FillStatus { guard !self.eof else { return .eof } let shift = self.token let used = self.yylimit - self.token let free = Self.bufferSize - used // Error: Lexeme too long. In the real world we could reallocate a larger buffer. guard self.token >= 1 else { return .longLexeme } // Shift buffer contents, discarding everything up to the current token. self.yyinput.replaceSubrange(..) -> SemVer? { let tagNone = -1 var yycursor = 0, yymarker = 0 // Final tag variables available in semantic action. /*!svars:re2c format = " var @@: Int\n"; */ // Intermediate tag variables used by the lexer (must be autogenerated). /*!stags:re2c format = " var @@ = tagNone\n"; */ /*!re2c re2c:yyfill:enable = 0; re2c:captvars = 1; num = [0-9]+; (num) "." (num) ("." num)? [\x00] { let _ = yytl0; _ = yytr0 // Some variables are unused. return SemVer( major: s2n(yytl1..) -> Int { range.reduce(0) { accum, idx in accum * 10 + Int(yyinput[idx] - UInt8(ascii: "0")) } } } assert(lex("23.34") == SemVer(major: 23, minor: 34, patch: 0)) assert(lex("1.2.999") == SemVer(major: 1, minor: 2, patch: 999)) assert(lex("1.a") == nil) در اینجا مثالی از به‌کارگیری برچسب‌های m برای تجزیه یک نسخه با تعداد متغیری از مؤلفه‌ها آورده شده است. متغیرهای برچسب در یک ترای (trie) ذخیره می‌شوند. // re2swift $INPUT -o $OUTPUT import Foundation // Unbounded number of version components. struct Ver: Equatable { let components: [Int] } func parse(_ yyinput: UnsafePointer) -> Ver? { let tagNone = -1 var yycursor = 0, yymarker = 0 var mTagPool = [MTag]() // Final tag variables available in semantic action. /*!svars:re2c format = " let @@: Int\n"; */ /*!mvars:re2c format = " let @@: MTag?\n"; */ // Intermediate tag variables used by the lexer (must be autogenerated). /*!stags:re2c format = " var @@ = tagNone\n"; */ /*!mtags:re2c format = " var @@: MTag? = nil\n"; */ /*!re2c re2c:tags = 1; re2c:yyfill:enable = 0; re2c:YYSTAGP = "@@ = yycursor"; re2c:YYSTAGN = "@@ = tagNone"; re2c:YYMTAGP = "@@ = add(tag: @@, value: yycursor)"; re2c:YYMTAGN = "@@ = add(tag: @@, value: tagNone)"; num = [0-9]+; @t1 num @t2 ("." #t3 num #t4)* [\x00] { var components = [s2n(t1..) -> Int { range.reduce(0) { accum, idx in accum * 10 + Int(yyinput[idx] - UInt8(ascii: "0")) } } // Append a single value to an m-tag history. func add(tag prevTag: MTag?, value: Int) -> MTag { let tag = MTag(prev: prevTag, element: value) mTagPool.append(tag) return tag } } // 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). class MTag { weak var prev: MTag? // Link of predecessor node or root (nil) var elem: Int // Tag value init(prev: MTag?, element: Int) { self.prev = prev self.elem = element } } assert(parse("1") == Ver(components: [1])) assert(parse("1.2.3.4.5.6.7") == Ver(components: [1, 2, 3, 4, 5, 6, 7])) assert(parse("1.2.") == nil) درک تفاوت میان نقطه‌کدها (code points) و واحدهای کد (code units) ضروری است. یک نقطه‌کد، یک شناسه عددی برای یک نماد است. یک واحد کد، کوچک‌ترین واحد ذخیره‌سازی در متن کدگذاری‌شده است. یک نقطه‌کد منفرد ممکن است با یک یا چند واحد کد نمایش داده شود. در یک کدگذاری با طول ثابت (fixed-length)، تمام نقطه‌کدها با تعداد یکسانی از واحدهای کد نمایش داده می‌شوند. در یک کدگذاری با طول متغیر (variable-length)، نقطه‌کدها ممکن است با تعداد متفاوتی از واحدهای کد نمایش یابند. توجه داشته باشید که قاعده «هر چیز» ("any") یعنی [^] با هر نقطه‌کدی مطابقت دارد، اما لزوماً با هر واحد کدی مطابقت ندارد (تنها راه برای تطبیق با هر واحد کد بدون در نظر گرفتن نوع کدگذاری، قاعده پیش‌فرض * است). تحلیل‌گر لغوی (lexer) تولیدشده با جریانی از واحدهای کد کار می‌کند: yych یک واحد کد را ذخیره می‌کند و YYCTYPE نوع واحد کد است. از سوی دیگر، عبارات باقاعده بر حسب نقطه‌کدها مشخص می‌شوند. هنگامی که re2swift عبارات باقاعده را به اتوماتا کامپایل می‌کند، نقطه‌کدها را به واحدهای کد ترجمه می‌نماید. این تبدیل عموماً یک نگاشت ساده نیست: در کدگذاری‌های با طول متغیر، یک محدوده نقطه‌کد منفرد ممکن است به یک گراف پیچیده از واحدهای کد تبدیل شود. کدگذاری‌های زیر پشتیبانی می‌شوند: • ASCII (به‌طور پیش‌فرض فعال است). یک کدگذاری با طول ثابت با فضای کد [0-255] و نقطه‌کدها و واحدهای کد ۱ بایتی است. • EBCDIC (با --ebcdic یا re2c:encoding:ebcdic فعال می‌شود). یک کدگذاری با طول ثابت با فضای کد [0-255] و نقطه‌کدها و واحدهای کد ۱ بایتی است. • UCS2 (با --ucs2 یا re2c:encoding:ucs2 فعال می‌شود). یک کدگذاری با طول ثابت با فضای کد [0-0xFFFF] و نقطه‌کدها و واحدهای کد ۲ بایتی است. • UTF8 (با --utf8 یا re2c:encoding:utf8 فعال می‌شود). یک کدگذاری یونی‌کد با طول متغیر است. اندازه هر واحد کد ۱ بایت است. نقطه‌کدها با ۱ تا ۴ واحد کد نمایش داده می‌شوند. • UTF16 (با --utf16 یا re2c:encoding:utf16 فعال می‌شود). یک کدگذاری یونی‌کد با طول متغیر است. اندازه هر واحد کد ۲ بایت است. نقطه‌کدها با ۱ تا ۲ واحد کد نمایش داده می‌شوند. • UTF32 (با --utf32 یا re2c:encoding:utf32 فعال می‌شود). یک کدگذاری یونی‌کد با طول ثابت با فضای کد [0-0x10FFFF] و نقطه‌کدها و واحدهای کد ۴ بایتی است. فایل‌های include شامل include/unicode_blocks.re، include/unicode_categories.re و include/unicode_properties.re تعاریف re2swift را برای بلوک‌ها، دسته‌بندی‌ها و ویژگی‌های شرح‌داده‌شده در استاندارد Unicode فراهم می‌کنند. گزینه --input-encoding کدگذاری فایل مبدأ را مشخص می‌کند که می‌تواند برای فعال‌سازی لیترال‌های یونی‌کد در عبارات باقاعده به کار رود. برای مثال --input-encoding utf8 به re2swift اعلام می‌کند که فایل مبدأ با فرمت UTF8 است (با --utf8 که کدگذاری متن ورودی را تعیین می‌کند تفاوت دارد). گزینه --encoding-policy روشی را تعیین می‌کند که re2swift با جانشین‌های یونی‌کد (نقطه‌کدهای موجود در محدوده [0xD800-0xDFFF]) رفتار می‌کند. در زیر نمونه‌ای از یک تحلیل‌گر لغوی برای شناسه‌های یونی‌کد با کدگذاری UTF8 آورده شده است. // re2swift $INPUT -o $OUTPUT -8 -i /*!include:re2c "unicode_categories.re" */ func lex(_ yyinput: UnsafePointer) -> Bool { var yycursor = 0, yymarker = 0 /*!re2c re2c:yyfill:enable = 0; // Simplified "Unicode Identifier and Pattern Syntax" // (see https://unicode.org/reports/tr31) id_start = L | Nl | [$_]; id_continue = id_start | Mn | Mc | Nd | Pc | [\u200D\u05F3]; identifier = id_start id_continue*; identifier { return true } * { return false } */ } assert(lex("_Ыдентификатор")) assert(lex("識別子")) assert(!lex("+")) فایل‌های ضمیمه (Include files) برنامه re2swift اجازه می‌دهد تا فایل‌های دیگر را با استفاده از بلوکی به قالب /*!include:re2c FILE */ یا %{include FILE %}، یا یک دستورالعمل درون‌بلوکیِ !include FILE ; ضمیمه کنید، که در آن FILE مسیر فایلی است که باید اضافه شود. re2swift فایل‌های include را در دایرکتوری فایلی که شامل این دستور است و همچنین در مکان‌های include که با گزینه -I مشخص می‌شوند جستجو می‌کند. بلوک‌ها/دستورالعمل‌های include در re2swift مشابه #include در C/C++ عمل می‌کنند: محتوای FILE عیناً در جای بلوک/دستورالعمل جای‌گذاری می‌شود. فایل‌های include ممکن است خودشان نیز شامل موارد include دیگری باشند. برای ردگیری وابستگی‌های ساخت فایل خروجی به فایل‌های include، از گزینه --depfile استفاده کنید. برنامه re2swift تعدادی فایل include از پیش تعریف‌شده ارائه می‌دهد که در زیردایرکتوری include/ پروژه یافت می‌شوند. این فایل‌ها حاوی تعاریفی هستند که ممکن است برای پروژه‌های دیگر مفید باشند (مانند دسته‌بندی‌های Unicode) و ساختاری شبیه به یک کتابخانه استاندارد برای re2swift تشکیل می‌دهند. در زیر مثالی از نحوه استفاده از فایل‌های include آورده شده است. فایل ضمیمه ۱ (definitions.swift) enum Result { case ok, fail } /*!re2c number = [1-9][0-9]*; */ // floating-point numbers frac = [0-9]* "." [0-9]+ | [0-9]+ "."; exp = 'e' [+-]? [0-9]+; float = frac exp? | [0-9]+ exp; float { return .ok } فایل ورودی (Input file) // re2swift $INPUT -o $OUTPUT -i /*!include:re2c "definitions.swift" */ func lex(_ yyinput: UnsafePointer) -> Result { var yycursor = 0, yymarker = 0 /*!re2c re2c:yyfill:enable = 0; * { return .fail } number { return .ok } !include "extra_rules.re.inc"; */ } assert(lex("123") == .ok) assert(lex("123.4567") == .ok) فایل‌های سرآیند (Header files) ابزار re2swift به شما اجازه می‌دهد با استفاده از گزینهٔ --header یا پیکربندی re2c:header و جفت‌بلوک‌هایی به شکل /*!header:re2c:on*/ و /*!header:re2c:off*/، یا %{header:on%} و %{header:off%}، از روی فایل ورودی .re یک فایل سرآیند تولید کنید. بلوک نخست، آغاز فایل سرآیند و بلوک دوم، پایان آن را مشخص می‌کند. تمامی محتوای میان این بلوک‌ها توسط re2swift پردازش شده و کد تولیدشده در فایلی که با گزینهٔ --header یا پیکربندی re2c:header مشخص شده نوشته می‌شود (یا در صورت عدم استفاده از گزینه یا پیکربندی، در stdout نوشته خواهد شد). فایل سرآیند تولیدشدهٔ خودکار ممکن است در مواردی نیاز باشد که re2swift برای تولید تعاریفی به کار می‌رود که باید از سایر واحدهای ترجمه (translation units) قابل مشاهده باشند. در ادامه مثالی از تولید یک فایل سرآیند آورده شده است که شامل تعریف وضعیت لکسر به همراه متغیرهای برچسب (tag variables) است (تعداد متغیرها به گرامر منظم بستگی دارد و برای برنامه‌نویس مشخص نیست). فایل ورودی (Input file) // re2swift $INPUT -o $OUTPUT -i --header lexer/state.swift /*!header:re2c:on*/ struct LexerState { var yyinput: UnsafePointer var yycursor: Int /*!stags:re2c format = "var @@ = -1"; */ init(str: UnsafePointer, cur: Int = 0) { self.yyinput = str self.yycursor = cur } } /*!header:re2c:off*/ extension LexerState { mutating func lex() -> Int { let t: Int /*!re2c re2c:header = "lexer/state.swift"; re2c:api = record; re2c:tags = 1; re2c:yyfill:enable = 0; re2c:yyrecord = "self"; [a]* @t [b]* { return t } */ } } @main struct Program { static func main() { let str: StaticString = "ab" var state = LexerState(str: str.utf8Start) assert(state.lex() == 1) } } فایل سرآیند (Header file) /* Generated by re2swift */ struct LexerState { var yyinput: UnsafePointer var yycursor: Int var yyt1 = -1 init(str: UnsafePointer, cur: Int = 0) { self.yyinput = str self.yycursor = cur } } با گزینهٔ -S, --skeleton، ابزار re2swift تمام کدهای غیر re2swift را نادیده می‌گیرد و یک برنامهٔ C خودکفا تولید می‌کند که می‌تواند در ادامه کامپایل و اجرا شود. این برنامه از کد تحلیل‌گر لغوی (lexer) و داده‌های ورودی تشکیل شده است. به ازای هر DFA ساخته‌شده (بلوک یا شرط)، re2swift یک تحلیل‌گر لغوی مستقل و دو فایل تولید می‌کند: یک فایل .input با رشته‌های مشتق‌شده از DFA و یک فایل .keys با نتایج تطابق مورد انتظار. برنامه هر تحلیل‌گر لغوی را روی فایل .input متناظر اجرا کرده و نتایج را با موارد مورد انتظار مقایسه می‌کند. برنامه‌های اسکلتی به چند دلیل بسیار مفید هستند: • آن‌ها می‌توانند درستی بهینه‌سازی‌های گوناگون re2swift را بررسی کنند (داده‌ها در مراحل اولیهٔ فرایند، پیش از اعمال هرگونه تبدیل روی DFA تولید می‌شوند). • تولید مجموعه‌ای از داده‌های ورودی با پوشش مناسب می‌تواند هم برای آزمایش و هم برای ارزیابی کارایی (benchmarking) مفید باشد. • تولید برنامه‌های اجرایی خودکفا به شخص اجازه می‌دهد موارد آزمون کمینه‌شده (minimized test cases) به دست آورد (کد اصلی ممکن است بزرگ باشد یا وابستگی‌های زیادی داشته باشد). دشواریِ تولید داده‌های ورودی در این است که به‌جز در ساده‌ترین حالت‌ها، تعداد رشته‌های ورودیِ ممکن بیش از حد زیاد است (حتی اگر طول رشته محدود باشد). re2swift این دشواری را با تولید رشته‌های کافی برای پوشش تقریباً تمامی گذارهای DFA حل می‌کند. این ابزار از الگوریتم زیر استفاده می‌کند: ابتدا اسکلتی از DFA را می‌سازد. برای کدگذاری‌هایی با اندازه واحد کد 1-بایتی (مانند ASCII، UTF-8 و EBCDIC) اسکلت صرفاً یک رونوشت دقیق از DFA اصلی است. برای کدگذاری‌هایی با واحدهای کد چندبایتی، اسکلت رونوشتی از DFA با حذف برخی گذارها است: بدین صورت که re2swift حداکثر ۲۵۶ واحد کد را برای هر بازهٔ پیوسته و مجزا که با یک گذار DFA مطابقت دارد برمی‌گزیند. مقادیر انتخاب‌شده به‌طور یکنواخت توزیع شده‌اند و شامل کران‌های بازه نیز می‌شوند. re2swift به‌جای تلاش برای پوشش تمام مسیرهای ممکن در اسکلت (که کاری نشدنی است)، مسیرهای کافی برای پوشش همهٔ گذارهای اسکلت تولید می‌کند تا بدین ترتیب پرش‌های شرطی متناظر در تحلیل‌گر لغوی فعال شوند. پیاده‌سازی این الگوریتم به حدود 1 گیگابایت گذار محدود شده است و مقدار ثابتی حافظه مصرف می‌کند (re2swift به‌محض تولید داده‌ها، آن‌ها را در فایل می‌نویسد). مصورسازی و اشکال‌زدایی (Visualization and debug) با گزینهٔ -D, --emit-dot، ابزار re2swift هیچ کدی تولید نمی‌کند؛ در عوض، DFA تولیدشده را در قالب DOT ذخیره (dump) می‌کند. می‌توان این خروجی را با استفاده از Graphviz یا کتابخانه‌ای دیگر به تصویری از DFA تبدیل کرد. توجه داشته باشید که این گزینه، DFA نهایی را پس از گذراندن شماری از بهینه‌سازی‌ها و تبدیل‌ها نشان می‌دهد. مراحل اولیه را می‌توان با گزینه‌های اشکال‌زدایی گوناگون مانند --dump-nfa، --dump-dfa-raw و غیره ذخیره کرد (فهرست کامل گزینه‌ها را ببینید). همچنین ببینید (SEE ALSO) می‌توانید اطلاعات بیشتری دربارهٔ re2c در وبگاه رسمی بیابید: http://re2c.org. برنامه‌های مشابه عبارتند از flex(1)، lex(1)، quex(http://quex.sourceforge.net). نویسندگان (AUTHORS) re2swift در ابتدا توسط Peter Bumbulis (peter@csg.uwaterloo.ca) در سال ۱۹۹۳ نوشته شد. Marcus Boerger و Dan Nuffer چندین سال وقت صرف کردند تا ایدهٔ اصلی را به یک تولیدکنندهٔ کد آمادهٔ استفاده در محیط عملیاتی تبدیل کنند. از آن زمان، این پروژه توسط داوطلبان متعددی نگهداری و توسعه داده شده است، به‌ویژه: Brian Young (bayoung@acm.org)، Marcus Boerger، Dan Nuffer (nuffer@users.sourceforge.net)، Ulya Trofimovich (skvadrik@gmail.com)، Serghei Iakovlev، Sergei Trofimovich، Petr Skocik، ligfx raekye و PolarGoose. RE2SWIFT(1)