| BT_LANGUAGE(1) | btparse | BT_LANGUAGE(1) |
نام (NAME)
bt_language - زبان دادههای BibTeX، همانطور که توسط btparse شناخته میشود
خلاصه دستور (SYNOPSIS)
# Lexical grammar, mode 1: top-level
AT \@
NEWLINE \n
COMMENT \%~[\n]*\n
WHITESPACE [\ \r\t]+
JUNK ~[\@\n\ \r\t]+
# Lexical grammar, mode 2: in-entry
NEWLINE \n
COMMENT \%~[\n]*\n
WHITESPACE [\ \r\t]+
NUMBER [0-9]+
NAME [a-z0-9\!\$\&\*\+\-\.\/\:\;\<\>\?\[\]\^\_\`\|]+
LBRACE \{
RBRACE \}
LPAREN \(
RPAREN \)
EQUALS =
HASH \#
COMMA ,
QUOTE \"
# Lexical grammar, mode 3: strings
# (very hairy -- see text)
# Syntactic grammar:
bibfile : ( entry )*
entry : AT NAME body
body : STRING # for comment entries
| ENTRY_OPEN contents ENTRY_CLOSE
contents : ( NAME | NUMBER ) COMMA fields # for regular entries
| fields # for macro definition entries
| value # for preamble entries
fields : field { COMMA fields }
|
field : NAME EQUALS value
value : simple_value ( HASH simple_value )*
simple_value : STRING
| NUMBER
| NAME
یکی از مشکلات BibTeX این است که هیچ مشخصات رسمی برای این زبان وجود ندارد. این بدان معناست که کاربرانی که زوایای مبهم و پیچیدهٔ این زبان را بررسی میکنند تا حد زیادی به حال خود رها شدهاند، و برنامهنویسانی که تجزیهکنندههای خود را پیادهسازی میکنند کاملاً متکی به خود هستند---مگر از طریق مشاهدهٔ رفتار پیادهسازی اصلی.
سایر پیادهسازان تجزیهکننده (بهویژه Nelson Beebe از پروژهٔ مشهور "bibclean") زحمت توضیح زبانی را که توسط تجزیهکنندهشان پذیرفته میشود متقبل شدهاند، و با همان رویکرد، موارد زیر ارائه شده است.
اگر با ظرایف و پیچیدگیهای زبانهای منظم (regular) و مستقل از متن (context-free) آشنایی ندارید، درک این مطلب برایتان آسان نخواهد بود. این متن مقدمهای بر زبان BibTeX نیست؛ برای یادگیری خود زبان داده، هر کتاب LaTeX مناسبتر خواهد بود.
گرامر واژگانی (LEXICAL GRAMMAR)
پویشگر واژگانی سه حالت متمایز دارد: top-level، in-entry، و string. به طور تقریبی، top-level حالت اولیه است؛ با دیدن یک "@" در top-level وارد حالت in-entry میشویم؛ و با دیدن "}" یا ")" که پایانبخش مدخل است، به top-level برمیگردیم. با دیدن یک """ یا "{" که جداکنندهٔ مدخل نباشد از حالت in-entry وارد حالت string میشویم. توجه داشته باشید که زبان واژگانی هم غیرمنظم است (زیرا آکولادها باید متوازن باشند) و هم وابسته به متن (چون "{" بسته به زمینهٔ نحوی خود میتواند معانی متفاوتی داشته باشد). با این وجود، ما از عبارتهای باقاعده برای توصیف عناصر واژگانی استفاده خواهیم کرد، زیرا آنها نقطهٔ شروع مورد استفاده توسط خود پویشگر واژگانی هستند. بقیهٔ گرامر واژگانی به طور غیررسمی در متن توضیح داده خواهد شد.
از top-level، توکنهای زیر طبق عبارتهای باقاعده در سمت راست شناسایی میشوند:
AT \@ NEWLINE \n COMMENT \%~[\n]*\n WHITESPACE [\ \r\t]+ JUNK ~[\@\n\ \r\t]+
(توجه داشته باشید که این نحو عبارت باقاعدهٔ PCCTS است که باید برای کاربران سایر موتورهای regex تا حد زیادی آشنا باشد. یک ویژگی نامتعارف این است که یک کلاس نویسه به صورت "~[...]" منفی میشود به جای "[^...]".)
با دیدن "at" در top-level، وارد حالت in-entry میشویم. فاصلههای خالی، نویسههای زائد (junk)، خطوط جدید، و کامنتها همگی نادیده گرفته میشوند، که دو مورد آخر شمارندهٔ خط را افزایش میدهند. (Junk به طور صریح شناسایی میشود تا طرح «کامنت ضمنی» "bibtex" امکانپذیر باشد.)
از حالت in-entry، خطوط جدید، کامنت و فاصلههای خالی دقیقاً همانند حالت top-level شناسایی میشوند. علاوه بر این، توکنهای زیر نیز شناسایی میگردند:
NUMBER [0-9]+
NAME [a-z0-9\!\$\&\*\+\-\.\/\:\;\<\>\?\[\]\^\_\`\|]+
LBRACE \{
RBRACE \}
LPAREN \(
RPAREN \)
EQUALS =
HASH \#
COMMA ,
QUOTE \"
در این مرحله، پویشگر واژگانی به شکل مشکوکی بیشتر شبیه یک گرامر مستقل از متن به نظر میرسد تا مجموعهای از عبارتهای باقاعدهٔ مستقل. با این حال، حفظ این پیچیدگی در پویشگر ضروری است زیرا برخی نویسهها (بهویژه "{" و "(") بسته به توکنهایی که پیش از آنها در جریان ورودی آمدهاند، معانی واژگانی بسیار متفاوتی دارند.
بهویژه، اگر "{" و "(" پس از یک توکن "at" و یک توکن "name" بیایند، به عنوان «آغازگر مدخل» (entry openers) در نظر گرفته میشوند، مگر اینکه مقدار توکن "name" برابر با "comment" باشد. (به تغییر وضعیت از top-level به in-entry بین این دو توکن توجه کنید.) در مورد @comment، جداکننده به عنوان شروع یک رشته در نظر گرفته میشود و ما وارد حالت string میشویم. در غیر این صورت، جداکننده ذخیره میشود و هنگامی که "}" یا ")" متناظر با آن را میبینیم، به عنوان یک «پایانبخش مدخل» (entry closer) در نظر گرفته میشود. (آکولادها در اینجا خودبهخود متوازن میشوند زیرا تحلیلگر واژگانی رشته شمارش عمق آکولادها را بر عهده دارد.)
در هر جای دیگری، "{" به عنوان آغاز یک رشته در نظر گرفته شده و وارد حالت string میشویم. """ صرفنظر از متن و زمینه، همیشه یک رشته را آغاز میکند. سایر توکنها ("name"، "number"، "equals"، "hash"، و "comma") بدون قید و شرط شناسایی میشوند.
توجه داشته باشید که "name" یک توکن فراگیر است که برای نوع مدخلها (entry types)، کلیدهای ارجاع (citation keys)، نامهای فیلد، و نامهای ماکرو استفاده میشود؛ از آنجا که BibTeX قواعد اندکی متفاوت (و تا حد زیادی ثبتنشده در مستندات) برای این عناصر مختلف دارد، برای درست کار کردنِ امور، اندکی ترفند لازم است. به عنوان نقطهٔ شروع، تعریف BibTeX را از آنچه برای یک کلید مدخل مجاز است در نظر بگیرید: دنبالهای از هر نویسهای بهجز
" # % ' ( ) , = { }
بهعلاوهٔ فاصله. این طرح چند مشکل دارد. نخست، بدون تعیین مجموعه نویسهای که این «۱۰ نویسهٔ جادویی» از آن برگزیده شدهاند، دانستن اینکه دقیقاً چه چیزهایی مجاز هستند کمی دشوار است. دوم، مجاز دانستن نویسههای "@" میتواند به نحوی گیجکننده در BibTeX منجر شود (این موضوع BibTeX را گیج نمیکند، اما ممکن است خوانندهٔ انسانی را سردرگم کند). در نهایت، مجاز شمردن نویسههای خاصی که برای TeX ویژه هستند به این معناست که BibTeX میتواند کد نامعتبر TeX تولید کند: قرار دادن یک بکاسلش ("\") یا مدک ("~") را در یک کلید ارجاع امتحان کنید. (این استثنای اخیر تا حدودی مختص کاربرد «تولید کد (La)TeX از پایگاه دادهٔ BibTeX» است، اما چون این کاربرد، کاربرد اصلی پایگاههای دادهٔ BibTeX است، بنابراین حداقل در ابتدا، کاربرد اصلی btparse نیز خواهد بود. بدین ترتیب، توجه به این مشکل منطقی است.)
بنابراین در btparse، یک name به عنوان هر دنبالهای از حروف، ارقام، زیرخطها، و نویسههای زیر تعریف میشود:
! $ & * + - . / : ; < > ? [ ] ^ _ ` |
این فهرست از طریق حذف «۱۰ نویسهٔ جادویی» BibTeX از مجموعه نویسههای ASCII هفت بیتی قابل چاپ (۳۲-۱۲۶)، و سپس حذف بیشترِ "@"، "\" و "~" به دست آمده است. این بدان معناست که btparse برخی از کلیدهای مدخل عجیبتر را که BibTeX میپذیرد، مانند "\foo@bar"، غیرمجاز میداند، اما همچنان رشتهای با ارقام آغازین را مجاز میشمارد. در واقع، از تعریف بالا چنین به نظر میرسد که btparse رشتهای متشکل از تماماً ارقام را به عنوان یک «name» میپذیرد؛ با این حال چنین نیست، زیرا پویشگر واژگانی چنین رشتهٔ رقمی را ابتدا به عنوان یک number شناسایی میکند. در اینجا دو مشکل وجود دارد: کلیدهای مدخل BibTeX در واقع ممکن است کاملاً عددی باشند، و نامهای فیلد ممکن است با یک رقم شروع نشوند. (این دو مورد از تفاوتهای نه چندان واضح در نحوهٔ مدیریت کلیدها و نامهای فیلد توسط BibTeX هستند.) ترفندهای استفاده شده برای مقابله با این مشکلات به جای پویشگر واژگانی، در تجزیهکننده پیادهسازی شدهاند، بنابراین در «SYNTACTIC GRAMMAR» در ادامه توضیح داده شدهاند.
تحلیلگر واژگانی رشته توکنهای "lbrace"، "rbrace"، "lparen"، و "rparen" را به منظور شمارش عمق آکولاد یا پرانتز شناسایی میکند. این کار ضروری است تا بداند چه زمانی رشتهای را که با آکولاد یا پرانتز محدود شده است بپذیرد. (توجه داشته باشید که رشتهٔ محدودشده با پرانتز فقط بعد از @comment مجاز است---این یک ساختار معمول در BibTeX نیست.) علاوه بر این، هر نویسهٔ فاصلهٔ خالی غیر از فاصلهٔ معمولی (خط جدید، carriage-return، و tab) را به یک تکفاصله تبدیل میکند. (توالی فاصلههای خالی فشرده نمیشوند؛ این در حوزهٔ پسپردازش رشته است که کاملاً از پویشگر یا تجزیهکننده مجزا است.) در نهایت، """ را برای مشخص کردن مرز رشتههای محصور در علامت نقلقول میپذیرد. جدا از این محدودیتها، تحلیلگر واژگانی رشته هر چیزی را تا رسیدن به جداکنندهٔ پایان رشته میپذیرد..SH "گرامر نحوی (SYNTACTIC GRAMMAR)" (زبانی که در اینجا برای توصیف گرامر به کار رفته، «فرم باکوس-نائور گسترشیافته» (EBNF) مورد استفاده توسط PCCTS است. پایانهها با رشتههای حروف بزرگ و ناپایانهها با رشتههای حروف کوچک نشان داده شدهاند؛ نام پایانهها همان نامهای ارائهشده در گرامر واژگانی بالا هستند. "( foo )*" به معنای صفر یا چند بار تکرار قاعدهٔ تولید "foo" است و "{ foo }" به معنای یک "foo" اختیاری است.)
یک فایل صرفاً دنبالهای از صفر یا چند مدخل است:
bibfile : ( entry )*
یک مدخل شامل یک علامت اتساین (@)، یک نام («نوع مدخل»)، و بدنهٔ مدخل است:
entry : AT NAME body
بدنه یا یک رشته است (این حالت تنها در صورتی بررسی میشود که نوع مدخل "comment" باشد) یا محتویات مدخل:
body : STRING # for comment entries
| ENTRY_OPEN contents ENTRY_CLOSE
("ENTRY_OPEN" و "ENTRY_CLOSE" بسته به آنچه در ورودی برای یک مدخل خاص دیده میشود، یا "{" و "}" هستند و یا "(" و ")".)
سه قاعدهٔ تولید ممکن برای ناپایانهٔ "contents" وجود دارد. تنها یکی از آنها بسته به فرانوست (metatype) مدخل (که خود به نوع مدخل بستگی دارد)، برای هر مدخل معین اعمال میشود. در حال حاضر، btparse از چهار فرانوست مدخل پشتیبانی میکند: comment، preamble، macro definition، و regular. دو مورد نخست متناظر با مدخلهای @comment و @preamble هستند؛ "macro definition" برای مدخلهای @string است؛ و "regular" برای تمامی انواع دیگر مدخلها به کار میرود. (این کتابخانه در آینده برای پشتیبانی از انواع مدخل @modify و @alias، و فرانوستهای متناظر "modify" و "alias"، پس از انتشار BibTeX 1.0 و مشخص شدن ساختار نحوی دقیق آن، گسترش خواهد یافت.) مفهوم «فرانوست» از این جهت ضروری است که تمامی انواع مدخلی که بهطور خاص شناخته نشدهاند در فرانوست "regular" قرار گیرند. همچنین این مزیت را دارد که دیگر نیازی به اجرای مداوم "strcmp" روی نوع مدخل نباشد.
contents : ( NAME | NUMBER ) COMMA fields # for regular entries
| fields # for macro definition entries
| value # for preamble entries
توجه داشته باشید که کلید مدخل صرفاً یک "NAME" نیست، بلکه "( NAME | NUMBER)" است. این امر بدان جهت ضروری است که BibTeX کلیدهای مدخل تمامرقمی را مجاز میداند، اما پویشگر واژگانی btparse چنین رشتههای رقمی را به عنوان توکنهای "NUMBER" تشخیص میدهد.
"fields" فهرستی از فیلدها است که با کاما از هم جدا شدهاند، به همراه یک کامای پایانی اختیاری:
fields : field { COMMA fields }
|
یک "field" یک مقداردهی تکی "field = value" است:
field : NAME EQUALS value
توجه داشته باشید که "NAME" در اینجا نسخهای محدود شده از توکن "name" است که در «دستور زبان واژگانی» در بالا شرح داده شد. هر توکن "name" توسط تجزیهکننده پذیرفته میشود، اما بلافاصله بررسی میگردد تا اطمینان حاصل شود که با رقم شروع نمیشود؛ در صورت شروع با رقم، یک خطای نحوی مصنوعی ایجاد میشود. (این کار برای سازگاری با BibTeX است که اجازه نمیدهد نام فیلدها با یک رقم آغاز شوند.)
یک "value" مجموعهای از مقادیر ساده است که با نویسههای '#' به یکدیگر متصل شدهاند:
value : simple_value ( HASH simple_value )*
یک مقدار ساده (simple value) یک رشته، عدد، یا نام (برای فراخوانیهای ماکرو) است:
simple_value : STRING
| NUMBER
| NAME
btparse
نویسنده (AUTHOR)
Greg Ward <gward@python.net>
| 2025-07-14 | btparse, version 0.91 |