ພາສາອັງກິດພາສາຝຣັ່ງແອສປາໂຍນ

OnWorks favicon

peg - ອອນລາຍໃນຄລາວ

ດໍາເນີນການ peg ໃນ OnWorks ຜູ້ໃຫ້ບໍລິການໂຮດຕິ້ງຟຣີຜ່ານ Ubuntu Online, Fedora Online, Windows online emulator ຫຼື MAC OS online emulator

ນີ້ແມ່ນຄໍາສັ່ງ peg ທີ່ສາມາດດໍາເນີນການໄດ້ໃນ OnWorks ຜູ້ໃຫ້ບໍລິການໂຮດຕິ້ງຟຣີໂດຍໃຊ້ຫນຶ່ງໃນຫຼາຍໆບ່ອນເຮັດວຽກອອນໄລນ໌ຂອງພວກເຮົາເຊັ່ນ Ubuntu Online, Fedora Online, Windows online emulator ຫຼື MAC OS online emulator

ໂຄງການ:

NAME


peg, ຂາ - parser generator

ສະຫຼຸບສັງລວມ


peg [-hvV - ຜົນ​ຜະ​ລິດ​] [ຊື່​ເອ​ກະ​ສານ ... ]
ຂາ [-hvV - ຜົນ​ຜະ​ລິດ​] [ຊື່​ເອ​ກະ​ສານ ... ]

ລາຍລະອຽດ


peg ແລະ ຂາ ແມ່ນເຄື່ອງມືສໍາລັບການສ້າງ parsers recursive-descent: ໂຄງການທີ່ປະຕິບັດ
ຮູບແບບທີ່ກົງກັນກັບຂໍ້ຄວາມ. ພວກເຂົາເຈົ້າປະມວນຜົນ Grammar ການສະແດງອອກ (PEG) [Ford 2004] ກັບ
ຜະລິດໂຄງການທີ່ຮັບຮູ້ປະໂຫຍກທາງກົດໝາຍຂອງໄວຍາກອນນັ້ນ. peg ປະມວນຜົນ PEGs
ຂຽນໂດຍໃຊ້ syntax ຕົ້ນສະບັບທີ່ອະທິບາຍໂດຍ Ford; ຂາ ປະມວນຜົນ PEGs ທີ່ຂຽນໂດຍໃຊ້
syntax ແລະສົນທິສັນຍາທີ່ແຕກຕ່າງກັນເລັກນ້ອຍທີ່ມີຈຸດປະສົງເພື່ອເຮັດໃຫ້ມັນເປັນທີ່ຫນ້າສົນໃຈ
ການທົດແທນສໍາລັບຕົວວິເຄາະທີ່ສ້າງຂຶ້ນດ້ວຍ lex(1) ແລະ yacc(1). ບໍ່​ມັກ lex ແລະ yacc, peg ແລະ ຂາ
ສະ​ຫນັບ​ສະ​ຫນູນ backtracking ບໍ່​ຈໍາ​ກັດ​, ສະ​ຫນອງ​ທາງ​ເລືອກ​ຕາມ​ຄໍາ​ສັ່ງ​ເປັນ​ວິ​ທີ​ການ​ສໍາ​ລັບ​ການ disambiguation​, ແລະ​
ສາມາດສົມທົບການສະແກນ (ການວິເຄາະ lexical) ແລະ parsing (ການວິເຄາະ syntactic) ເປັນອັນດຽວ
ກິດຈະກໍາ.

peg ອ່ານທີ່ລະບຸໄວ້ ຊື່​ເອ​ກະ​ສານs, ຫຼືມາດຕະຖານ input ຖ້າບໍ່ມີ ຊື່​ເອ​ກະ​ສານs ແມ່ນໃຫ້, ສໍາລັບ a
ໄວຍະກອນອະທິບາຍຕົວວິເຄາະເພື່ອສ້າງ. peg ຫຼັງຈາກນັ້ນສ້າງໄຟລ໌ແຫຼ່ງ C ທີ່
ກໍານົດຫນ້າທີ່ yyparse(). ໄຟລ໌ແຫຼ່ງ C ນີ້ສາມາດຖືກລວມເຂົ້າໃນ, ຫຼືລວບລວມແລະຫຼັງຈາກນັ້ນ
ເຊື່ອມໂຍງກັບ, ໂຄງການລູກຄ້າ. ແຕ່ລະຄັ້ງທີ່ໂຄງການລູກຄ້າໂທຫາ yyparse() parser
ບໍລິໂພກຂໍ້ຄວາມທີ່ປ້ອນເຂົ້າຕາມກົດລະບຽບການວິເຄາະ, ເລີ່ມຕົ້ນຈາກກົດລະບຽບທໍາອິດໃນ
ໄວຍາກອນ. yyparse() ສົ່ງຄືນຄ່າທີ່ບໍ່ແມ່ນສູນ ຖ້າການປ້ອນຂໍ້ມູນສາມາດຖືກວິເຄາະຕາມ
ໄວຍາກອນ; ມັນຈະສົ່ງຄ່າສູນຖ້າການປ້ອນຂໍ້ມູນບໍ່ສາມາດວິເຄາະໄດ້.

ຄຳນຳໜ້າ 'yy' ຫຼື 'YY' ແມ່ນນຳໜ້າກັບສັນຍາລັກທີ່ເຫັນໄດ້ຈາກພາຍນອກທັງໝົດໃນເຄື່ອງທີ່ສ້າງຂຶ້ນ.
parser. ນີ້ມີຈຸດປະສົງເພື່ອຫຼຸດຜ່ອນຄວາມສ່ຽງຂອງມົນລະພິດ namespace ໃນໂຄງການລູກຄ້າ.
(ທາງເລືອກຂອງ 'yy' ແມ່ນປະຫວັດສາດ; ເບິ່ງ lex(1) ແລະ yacc(1), ສໍາລັບການຍົກຕົວຢ່າງ.

OPTIONS


peg ແລະ ຂາ ໃຫ້​ທາງ​ເລືອກ​ດັ່ງ​ຕໍ່​ໄປ​ນີ້​:

-h ພິມບົດສະຫຼຸບຂອງທາງເລືອກທີ່ມີຢູ່ແລະຫຼັງຈາກນັ້ນອອກ.

- ຜົນຜະລິດ
ຂຽນ parser ທີ່ສ້າງຂຶ້ນໃສ່ໄຟລ໌ output ແທນທີ່ຈະເປັນຜົນຜະລິດມາດຕະຖານ.

-v ຂຽນຂໍ້ມູນ verbose ກັບຄວາມຜິດພາດມາດຕະຖານໃນຂະນະທີ່ເຮັດວຽກ.

-V ຂຽນຂໍ້ມູນສະບັບເປັນຄວາມຜິດພາດມາດຕະຖານຫຼັງຈາກນັ້ນອອກ.

A SIMPLE EXAMPLE


ຕໍ່ໄປນີ້ peg input ກໍານົດໄວຍະກອນທີ່ມີກົດລະບຽບດຽວ (ເອີ້ນວ່າ 'ເລີ່ມຕົ້ນ') ນັ້ນແມ່ນ
ພໍໃຈເມື່ອການປ້ອນຂໍ້ມູນມີສະຕຣິງ "ຊື່ຜູ້ໃຊ້".

ເລີ່ມ <- "ຊື່ຜູ້ໃຊ້"

(ເຄື່ອງໝາຍວົງຢືມແມ່ນ ບໍ່ ສ່ວນຫນຶ່ງຂອງຂໍ້ຄວາມທີ່ກົງກັນ; ພວກເຂົາຮັບໃຊ້ເພື່ອຊີ້ບອກຕົວຫນັງສື
string to be matched.) ໃນຄໍາສັບຕ່າງໆອື່ນໆ, yyparse() ໃນແຫຼ່ງ C ທີ່ຜະລິດຈະກັບຄືນມາ
ບໍ່ແມ່ນສູນເທົ່ານັ້ນຖ້າແປດຕົວອັກສອນຕໍ່ໄປອ່ານຈາກການປ້ອນຂໍ້ມູນສະກົດຄຳວ່າ "ຊື່ຜູ້ໃຊ້".
ຖ້າການປ້ອນຂໍ້ມູນມີອັນອື່ນ, yyparse() ສົ່ງຄ່າສູນ ແລະບໍ່ມີການປ້ອນຂໍ້ມູນໃດໆ
ບໍລິໂພກ. (ໂທຕໍ່ມາ yyparse() ຍັງຈະສົ່ງຄ່າສູນ, ເນື່ອງຈາກຕົວວິເຄາະແມ່ນ
ສະກັດຢ່າງມີປະສິດທິພາບຊອກຫາສາຍ "ຊື່ຜູ້ໃຊ້".) ເພື່ອຮັບປະກັນຄວາມຄືບຫນ້າພວກເຮົາສາມາດເພີ່ມ
ປະໂຫຍກທາງເລືອກກັບກົດລະບຽບ 'ເລີ່ມຕົ້ນ' ທີ່ຈະກົງກັບຕົວອັກສອນດຽວຖ້າ "ຊື່ຜູ້ໃຊ້"
ບໍ່ພົບ.

ເລີ່ມ <- "ຊື່ຜູ້ໃຊ້"
/.

yyparse() ຕອນນີ້ສົ່ງຄ່າທີ່ບໍ່ແມ່ນສູນສະເໝີ (ຍົກເວັ້ນໃນຕອນທ້າຍຂອງການປ້ອນຂໍ້ມູນ). ເຮັດ
ບາງສິ່ງບາງຢ່າງທີ່ເປັນປະໂຫຍດທີ່ພວກເຮົາສາມາດເພີ່ມການປະຕິບັດກັບກົດລະບຽບ. ການປະຕິບັດເຫຼົ່ານີ້ແມ່ນປະຕິບັດຫຼັງຈາກ a
ການ​ແຂ່ງ​ຂັນ​ທີ່​ສົມ​ບູນ​ແມ່ນ​ໄດ້​ພົບ​ເຫັນ (ເລີ່ມ​ຈາກ​ກົດ​ລະ​ບຽບ​ທໍາ​ອິດ​) ແລະ​ໄດ້​ຮັບ​ການ​ຄັດ​ເລືອກ​ຕາມ​
'ເສັ້ນທາງ' ປະຕິບັດຜ່ານໄວຍະກອນເພື່ອໃຫ້ກົງກັບວັດສະດຸປ້ອນ. (ນັກພາສາສາດຈະເອີ້ນເສັ້ນທາງນີ້ວ່າ a
'ເຄື່ອງໝາຍວະລີ'.)

ເລີ່ມ <- "ຊື່ຜູ້ໃຊ້" { printf("%s\n", getlogin()); }
/ < . > { putchar(yytext[0]); }

ແຖວທຳອິດແນະນຳໃຫ້ນັກວິເຄາະພິມຊື່ເຂົ້າສູ່ລະບົບຂອງຜູ້ໃຊ້ທຸກຄັ້ງທີ່ມັນເຫັນ
"ຊື່ຜູ້ໃຊ້" ໃນການປ້ອນຂໍ້ມູນ. ຖ້າການຈັບຄູ່ນັ້ນລົ້ມເຫລວ, ແຖວທີສອງຈະບອກຕົວວິເຄາະໃຫ້ສະທ້ອນ
ຕົວອັກສອນຕໍ່ໄປກ່ຽວກັບການປ້ອນຂໍ້ມູນມາດຕະຖານຜົນຜະລິດ. ຕອນນີ້ຕົວວິເຄາະຂອງພວກເຮົາກຳລັງປະຕິບັດໄດ້ທີ່ເປັນປະໂຫຍດ
ເຮັດ​ວຽກ​: ມັນ​ຈະ​ສໍາ​ເນົາ​ເອົາ​ການ​ປ້ອນ​ຂໍ້​ມູນ​ກັບ​ຜົນ​ຜະ​ລິດ​, ທົດ​ແທນ​ການ​ເກີດ​ທັງ​ຫມົດ​ຂອງ "ຊື່​ຜູ້​ໃຊ້​" ກັບ​.
ຊື່ບັນຊີຂອງຜູ້ໃຊ້.

ໃຫ້ສັງເກດວົງເລັບມຸມ ('<' ແລະ '>') ທີ່ຖືກເພີ່ມໃສ່ທາງເລືອກທີສອງ. ເຫຼົ່ານີ້
ບໍ່ມີຜົນຕໍ່ຄວາມຫມາຍຂອງກົດລະບຽບ, ແຕ່ໃຫ້ບໍລິການເພື່ອຈໍາກັດຂໍ້ຄວາມທີ່ມີໃຫ້
ການປະຕິບັດຕໍ່ໄປນີ້ຢູ່ໃນຕົວແປ yytext.

ຖ້າໄວຍະກອນຂ້າງເທິງແມ່ນຖືກຈັດໃສ່ໃນໄຟລ໌ username.peg, ແລ່ນຄໍາສັ່ງ

peg -o username.c username.peg

ຈະບັນທຶກ parser ທີ່ສອດຄ້ອງກັນຢູ່ໃນໄຟລ໌ ຊື່ຜູ້ໃຊ້.c. ເພື່ອສ້າງໂຄງການທີ່ສົມບູນ
parser ນີ້ສາມາດໄດ້ຮັບການລວມເຂົ້າໂດຍໂຄງການ C ດັ່ງຕໍ່ໄປນີ້.

#ລວມທັງ /* printf(), putchar() */
#ລວມທັງ /* getlogin() */

#include "username.c" /* yyparse() */

int ຕົ້ນຕໍ ()
{
ໃນຂະນະທີ່ (yyparse()) /* ເຮັດເລື້ມຄືນຈົນກ່ວາ EOF */
;
return 0
}

PEG ໄວຍະກອນ


ໄວຍາກອນປະກອບດ້ວຍຊຸດຂອງກົດລະບຽບທີ່ມີຊື່.

ຊື່ <- ຮູບແບບ

ໄດ້ ຮູບແບບ ມີໜຶ່ງ ຫຼືຫຼາຍອົງປະກອບຕໍ່ໄປນີ້.

ຊື່ ອົງປະກອບຢືນສໍາລັບຮູບແບບທັງຫມົດໃນກົດລະບຽບທີ່ມີໃຫ້ ຊື່.

"ລັກສະນະ"
ຕົວອັກສອນ ຫຼືສະຕຣິງທີ່ຕິດຢູ່ໃນວົງຢືມຄູ່ແມ່ນກົງກັນຕາມຕົວອັກສອນ. ANSI C
ລໍາດັບ escape ແມ່ນຮັບຮູ້ພາຍໃນ ລັກສະນະ.

'ລັກສະນະ'
ຕົວອັກສອນ ຫຼືສະຕຣິງທີ່ຕິດຢູ່ໃນວົງຢືມດຽວແມ່ນກົງກັນຕາມຕົວອັກສອນ, ດັ່ງຂ້າງເທິງ.

[ລັກສະນະ]
ຊຸດຕົວລະຄອນທີ່ປິດຢູ່ໃນວົງເລັບສີ່ຫຼ່ຽມກົງກັບຕົວອັກສອນດຽວຈາກ
ທີ່ກໍານົດໄວ້, ມີຕົວອັກສອນ escape ຮັບຮູ້ເປັນຂ້າງເທິງ. ຖ້າຊຸດເລີ່ມຕົ້ນດ້ວຍ
uparrow (^) ຫຼັງຈາກນັ້ນຊຸດຈະຖືກລົບອອກ (ອົງປະກອບທີ່ກົງກັບຕົວອັກສອນໃດນຶ່ງ ບໍ່ ໃນ
ຕັ້ງ). ຄູ່ຂອງຕົວອັກສອນທີ່ແຍກອອກດ້ວຍ dash (-) ເປັນຕົວແທນຂອງຂອບເຂດຂອງ
ຕົວອັກສອນຈາກຕົວທຳອິດຫາຕົວທີສອງ, ລວມທັງຕົວລະຄອນ. ຕົວອັກສອນຕົວໜັງສືອັນດຽວ
ຫຼືຂີດກ້ອງແມ່ນຖືກຈັບຄູ່ໂດຍຊຸດຕໍ່ໄປນີ້.

[a-zA-Z_]

ເຊັ່ນດຽວກັນ, ຕໍ່ໄປນີ້ກົງກັບຕົວອັກສອນທີ່ບໍ່ແມ່ນຕົວເລກດຽວ.

[^0-9]

. ຈຸດກົງກັບຕົວອັກສອນໃດນຶ່ງ. ໃຫ້ສັງເກດວ່າເວລາດຽວທີ່ລົ້ມເຫລວນີ້ແມ່ນໃນຕອນທ້າຍຂອງ
ໄຟລ໌, ບ່ອນທີ່ບໍ່ມີຕົວອັກສອນທີ່ຈະກົງກັນ.

( ຮູບແບບ )
ວົງເລັບຖືກໃຊ້ສໍາລັບການຈັດກຸ່ມ (ການດັດແກ້ກ່ອນຫນ້າຂອງຕົວປະຕິບັດການ
ອະທິບາຍຂ້າງລຸ່ມນີ້).

{ ການປະຕິບັດ }
ວົງເລັບ curly ອ້ອມຮອບການກະທໍາ. ການປະຕິບັດແມ່ນລະຫັດແຫຼ່ງ C ທີ່ບໍ່ຄາດຄິດທີ່ຈະເປັນ
ປະຕິບັດໃນຕອນທ້າຍຂອງການຈັບຄູ່. ວົງເລັບໃດໆພາຍໃນການປະຕິບັດຕ້ອງຖືກຕ້ອງ
ຮັງ. ຂໍ້​ຄວາມ​ທີ່​ປ້ອນ​ຂໍ້​ມູນ​ໃດ​ຫນຶ່ງ​ທີ່​ຖືກ​ຈັບ​ຄູ່​ກ່ອນ​ການ​ດໍາ​ເນີນ​ການ​ແລະ delimited ໂດຍ​ມຸມ​
ວົງເລັບ (ເບິ່ງຂ້າງລຸ່ມນີ້) ແມ່ນມີຢູ່ໃນການປະຕິບັດເປັນເນື້ອໃນຂອງ
array ຕົວອັກສອນ yytext. ຄວາມຍາວຂອງ (ຈໍານວນຕົວອັກສອນໃນ) yytext is
ມີຢູ່ໃນຕົວແປ yyeng. (ຊື່ຕົວແປເຫຼົ່ານີ້ແມ່ນປະຫວັດສາດ; ເບິ່ງ
lex(1).

< ວົງເລັບມຸມເປີດກົງກັນສະເໝີ (ບໍ່ໃຊ້ການປ້ອນຂໍ້ມູນ) ແລະເຮັດໃຫ້ເກີດການແຍກວິເຄາະ
ເພື່ອເລີ່ມຕົ້ນການສະສົມຂໍ້ຄວາມທີ່ກົງກັນ. ຂໍ້​ຄວາມ​ນີ້​ຈະ​ຖືກ​ເຮັດ​ໃຫ້​ມີ​ການ​ປະ​ຕິ​ບັດ​ໃນ​
ຕົວແປ yytext.

> ວົງເລັບມຸມປິດກົງກັນສະເໝີ (ບໍ່ໃຊ້ການປ້ອນຂໍ້ມູນ) ແລະເຮັດໃຫ້ຕົວວິເຄາະ
ເພື່ອຢຸດການສະສົມຂໍ້ຄວາມສໍາລັບ yytext.

ຂ້າງ​ເທິງ elements ສາມາດຖືກສ້າງເປັນທາງເລືອກ ແລະ/ຫຼືເຮັດຊ້ຳໄດ້ດ້ວຍຄຳຕໍ່ທ້າຍຕໍ່ໄປນີ້:

element ?
ອົງປະກອບແມ່ນທາງເລືອກ. ຖ້າມີຢູ່ໃນວັດສະດຸປ້ອນ, ມັນຖືກບໍລິໂພກແລະກົງກັນ
ສໍາເລັດ. ຖ້າບໍ່ມີຢູ່ໃນການປ້ອນຂໍ້ມູນ, ບໍ່ມີຂໍ້ຄວາມຖືກບໍລິໂພກ ແລະການແຂ່ງຂັນສຳເລັດ
ຢ່າງໃດກໍ່ຕາມ.

element +
ອົງປະກອບແມ່ນເຮັດຊ້ໍາໄດ້. ຖ້າ​ຫາກ​ວ່າ​ມີ​ຢູ່​ໃນ​ການ​ປ້ອນ​ຂໍ້​ມູນ​, ຫນຶ່ງ​ຫຼື​ຫຼາຍ​ການ​ເກີດ​ຂຶ້ນ​ຂອງ​
element ຖືກບໍລິໂພກແລະການແຂ່ງຂັນປະສົບຜົນສໍາເລັດ. ຖ້າບໍ່ມີການປະກົດຕົວຂອງ element ມີ
ປະກົດຢູ່ໃນວັດສະດຸປ້ອນ, ການແຂ່ງຂັນລົ້ມເຫລວ.

element *
ອົງປະກອບແມ່ນທາງເລືອກແລະເຮັດຊ້ໍາໄດ້. ຖ້າມີຢູ່ໃນວັດສະດຸປ້ອນ, ໜຶ່ງ ຫຼືຫຼາຍກວ່ານັ້ນ
ການປະກົດຕົວຂອງ element ຖືກບໍລິໂພກແລະການແຂ່ງຂັນປະສົບຜົນສໍາເລັດ. ຖ້າບໍ່ມີການປະກົດຕົວຂອງ
element ມີຢູ່ໃນວັດສະດຸປ້ອນ, ການແຂ່ງຂັນປະສົບຜົນສໍາເລັດຢ່າງໃດກໍ່ຕາມ.

ອົງປະກອບຂ້າງເທິງນີ້ແລະຄໍາຕໍ່ທ້າຍສາມາດຖືກປ່ຽນເປັນ predicates (ທີ່ກົງກັນເອງ
ປ້ອນ​ຂໍ້​ຄວາມ​ແລະ​ຕໍ່​ມາ​ສໍາ​ເລັດ​ຫຼື​ລົ້ມ​ເຫຼວ​ ໂດຍບໍ່ມີການ ການບໍລິໂພກວັດສະດຸປ້ອນນັ້ນ) ກັບ
ຄຳນຳໜ້າຕໍ່ໄປນີ້:

& element
predicate ສົບຜົນສໍາເລັດພຽງແຕ່ຖ້າຫາກວ່າ element ສາມາດຈັບຄູ່ໄດ້. ພິມຂໍ້ຄວາມຖືກສະແກນໃນຂະນະທີ່
ການຈັບຄູ່ element ບໍ່ໄດ້ບໍລິໂພກຈາກການປ້ອນຂໍ້ມູນ ແລະຍັງມີຢູ່
ການ​ຈັບ​ຄູ່​ຕໍ່​ມາ​.

! element
predicate ສົບຜົນສໍາເລັດພຽງແຕ່ຖ້າຫາກວ່າ element ບໍ່ສາມາດຈັບຄູ່ກັນໄດ້. ພິມຂໍ້ຄວາມຖືກສະແກນໃນຂະນະທີ່
ການຈັບຄູ່ element ບໍ່ໄດ້ບໍລິໂພກຈາກການປ້ອນຂໍ້ມູນ ແລະຍັງມີຢູ່
ການ​ຈັບ​ຄູ່​ຕໍ່​ມາ​. ເປັນ idiom ທີ່ນິຍົມແມ່ນ

!.

ເຊິ່ງກົງກັບຈຸດສິ້ນສຸດຂອງໄຟລ໌, ຫຼັງຈາກຕົວອັກສອນສຸດທ້າຍຂອງການປ້ອນຂໍ້ມູນແລ້ວ
ຖືກບໍລິໂພກ.

ແບບຟອມພິເສດຂອງ '&' ແມ່ນໃຫ້:

&{ ການສະແດງອອກ }
ໃນນີ້ predicate ງ່າຍດາຍ C ການສະແດງອອກ (ບໍ່ ຖະແຫຼງການ) ຖືກປະເມີນທັນທີ
ເມື່ອ parser ມາຮອດ predicate. ຖ້າ ການສະແດງອອກ ໃຫ້ຜົນທີ່ບໍ່ແມ່ນສູນ (ຄວາມຈິງ)
'ການຈັບຄູ່' ປະສົບຜົນສໍາເລັດແລະຕົວວິເຄາະສືບຕໍ່ກັບອົງປະກອບຕໍ່ໄປໃນຮູບແບບ.
ຖ້າ ການສະແດງອອກ yields zero (false) the 'match' fails and the parser back up to
ຊອກຫາຕົວແຍກທາງເລືອກຂອງການປ້ອນຂໍ້ມູນ.

ອົງປະກອບຈໍານວນຫນຶ່ງ (ມີຫຼືບໍ່ມີຄໍານໍາຫນ້າແລະ suffixes) ສາມາດຖືກລວມເຂົ້າກັນເປັນ a ລໍາດັບ
ໂດຍ​ການ​ຂຽນ​ໃຫ້​ເຂົາ​ເຈົ້າ​ຫນຶ່ງ​ຫຼັງ​ຈາກ​ນັ້ນ​. ລໍາດັບທັງຫມົດກົງກັນພຽງແຕ່ຖ້າແຕ່ລະຄົນ
ອົງປະກອບພາຍໃນມັນກົງກັນ, ຈາກຊ້າຍຫາຂວາ.

ລໍາດັບສາມາດຖືກແຍກອອກເປັນທາງເລືອກທີ່ບໍ່ເຂົ້າກັນໂດຍຕົວປະຕິບັດການສະຫຼັບ '/'.

ລຳດັບ-1 / ລຳດັບ-2 / ... / ລຳດັບ-N
ແຕ່ລະລໍາດັບແມ່ນພະຍາຍາມເຮັດຈົນກ່ວາຫນຶ່ງຂອງພວກເຂົາກົງກັນ, ໃນເວລານັ້ນກົງກັນ
ສໍາລັບຮູບແບບໂດຍລວມສໍາເລັດ. ຖ້າບໍ່ມີ ລຳ ດັບໃດກົງກັນ, ກົງກັນ
ຂອງຮູບແບບໂດຍລວມລົ້ມເຫລວ.

ສຸດທ້າຍ, ສັນຍາລັກປອນ (#) ແນະນໍາຄໍາຄິດຄໍາເຫັນ (ຍົກເລີກ) ທີ່ສືບຕໍ່ໄປຈົນເຖິງທີ່ສຸດ
ຂອງສາຍ.

ເພື່ອສະຫຼຸບຂ້າງເທິງ, parser ພະຍາຍາມຈັບຄູ່ຂໍ້ຄວາມທີ່ປ້ອນເຂົ້າກັບຮູບແບບໃດນຶ່ງ
ປະກອບມີຕົວຫນັງສື, ຊື່ (ເປັນຕົວແທນຂອງກົດລະບຽບອື່ນໆ), ແລະຕົວປະຕິບັດການຕ່າງໆ (ຂຽນເປັນ
prefixes, suffixes, juxtaposition for sequencing and and infix alternation operator) ທີ່
ປັບປຸງແກ້ໄຂວິທີການຈັບຄູ່ອົງປະກອບພາຍໃນຮູບແບບ. ການແຂ່ງຂັນແມ່ນເຮັດຈາກຊ້າຍຫາ
ສິດ, 'descending' ເຂົ້າໄປໃນກົດລະບຽບຍ່ອຍທີ່ມີຊື່ຍ້ອນວ່າເຂົາເຈົ້າໄດ້ພົບ. ຖ້າຂະບວນການຈັບຄູ່
ລົ້ມເຫລວ, parser 'back track' ('rewinding' input ຢ່າງເຫມາະສົມໃນຂະບວນການ) ເພື່ອ
ຊອກຫາທາງເລືອກທີ່ໃກ້ທີ່ສຸດ 'ເສັ້ນທາງ' ຜ່ານໄວຍາກອນ. ໃນຄໍາສັບຕ່າງໆອື່ນໆ, parser
ດໍາເນີນການຄົ້ນຫາຄວາມເລິກຄັ້ງທໍາອິດ, ຊ້າຍຫາຂວາສໍາລັບເສັ້ນທາງທີ່ປະສົບຜົນສໍາເລັດທໍາອິດທີ່ກົງກັນ
ໂດຍຜ່ານກົດລະບຽບ. ຖ້າພົບເຫັນ, ການປະຕິບັດຕາມເສັ້ນທາງທີ່ປະສົບຜົນສໍາເລັດຈະຖືກປະຕິບັດ (ໃນ
ຄໍາ​ສັ່ງ​ທີ່​ເຂົາ​ເຈົ້າ​ໄດ້​ພົບ).

ໃຫ້ສັງເກດວ່າ predicates ໄດ້ຖືກປະເມີນ ທັນທີ ໃນລະຫວ່າງການຄົ້ນຫາການແຂ່ງຂັນທີ່ປະສົບຜົນສໍາເລັດ,
ນັບຕັ້ງແຕ່ພວກເຂົາປະກອບສ່ວນກັບຄວາມສໍາເລັດຫຼືຄວາມລົ້ມເຫລວຂອງການຄົ້ນຫາ. ການກະທໍາ, ຢ່າງໃດກໍຕາມ, ແມ່ນ
ການປະເມີນພຽງແຕ່ຫຼັງຈາກການແຂ່ງຂັນທີ່ປະສົບຜົນສໍາເລັດໄດ້ຖືກພົບເຫັນ.

PEG ໄວຍະກອນ FOR PEG ໄວຍະກອນ


ໄວຍາກອນສໍາລັບ peg ໄວຍະກອນແມ່ນສະແດງໃຫ້ເຫັນຂ້າງລຸ່ມນີ້. ນີ້ຈະສະແດງໃຫ້ເຫັນທັງສອງຢ່າງແລະເປັນທາງການ
ຄຳອະທິບາຍຂ້າງເທິງ.

ໄວຍະກອນ <- Spacing Definition+ EndOfFile

ຄໍານິຍາມ <- Identifier LEFTARROW Expression
ການສະແດງອອກ <- ລໍາດັບ ( SLASH Sequence )*
ລຳດັບ <- ຄຳນຳໜ້າ*
ຄຳນຳໜ້າ <- ແລະ ຄຳສັ່ງ
/ ( ແລະ | ບໍ່ແມ່ນ )? ຕໍ່ທ້າຍ
Suffix <- ຫຼັກ ( QUERY / STAR / PLUS )?
ຫຼັກ <- ຕົວລະບຸ !LEFTARROW
/ ເປີດການສະແດງອອກ CLOSE
/ ຕົວໜັງສື
/ ຫ້ອງຮຽນ
/ DOT
/ ປະຕິບັດ
/ ເລີ່ມຕົ້ນ
/ ສິ້ນສຸດ

ຕົວລະບຸ <- < IdentStart IdentCont* > Spacing
IdentStart <- [a-zA-Z_]
IdentCont <- IdentStart / [0-9]
ຕົວໜັງສື <-[']< ( !['] Char )* > ['] ຍະຫວ່າງ
/ ["]< ( !["] Char )* > ["] ໄລຍະຫ່າງ
ຫ້ອງຮຽນ <- '[' < ( !']' Range )* > ']' ໄລຍະຫ່າງ
ຊ່ວງ <- Char '-' Char / Char
Char <- '\\' [abefnrtv'"\[\]\\]
/ '\\' [0-3][0-7][0-7]
/ '\\' [0-7][0-7]?
/ '\\' '-'
/ !'\\'.
ໄລຍະຫ່າງທາງຊ້າຍ <- '<-'
SLASH <- '/' ໄລຍະຫ່າງ
ແລະ <- '&' ໄລຍະຫ່າງ
ບໍ່ແມ່ນ <- '!' ໄລຍະຫ່າງ
ຄໍາຖາມ <- '?' ໄລຍະຫ່າງ
STAR <- '*' ໄລຍະຫ່າງ
ບວກ <- '+' ໄລຍະຫ່າງ
ເປີດ <- '(' ໄລຍະຫ່າງ
ປິດ <- ')' ໄລຍະຫ່າງ
DOT <- '.' ໄລຍະຫ່າງ
ຍະຫວ່າງ <- (ຍະຫວ່າງ / ຄຳເຫັນ)*
ຄຳເຫັນ <- '#' ( !EndOfLine . )* EndOfLine
Space <- ' ' / '\t' / EndOfLine
EndOfLine <- '\r\n' / '\n' / '\r'
EndOfFile <- !.
ການປະຕິບັດ <- '{' < [^}]* > '}' ໄລຍະຫ່າງ
BEGIN <- '<' ໄລຍະຫ່າງ
END <- '>' ໄລຍະຫ່າງ

LEG ໄວຍະກອນ


ຂາ ແມ່ນການປ່ຽນແປງຂອງ peg ທີ່ເພີ່ມຄຸນສົມບັດບາງຢ່າງຂອງ lex(1) ແລະ yacc(1). ມັນແຕກຕ່າງຈາກ
peg ໃນວິທີການດັ່ງຕໍ່ໄປນີ້.

%{ ຂໍ້​ຄວາມ... %}
ພາກສ່ວນການປະກາດສາມາດປາກົດຢູ່ທຸກບ່ອນທີ່ຄາດການກໍານົດກົດລະບຽບ. ໄດ້
ຂໍ້ຄວາມ ລະຫວ່າງຕົວຂັ້ນ '%{' ແລະ '%}' ແມ່ນສຳເນົາຄຳສັບໃສ່ C ທີ່ສ້າງຂຶ້ນ.
ລະຫັດວິເຄາະ ກ່ອນທີ່ຈະ ລະຫັດທີ່ປະຕິບັດຕົວວິເຄາະຕົວມັນເອງ.

ຊື່ = ຮູບແບບ
ໂຕປະຕິບັດການ 'ມອບໝາຍ' ແທນຕົວປະຕິບັດການລູກສອນຊ້າຍ '<-'.

ຊື່ກົດລະບຽບ
Hyphens ສາມາດປາກົດເປັນຕົວອັກສອນໃນຊື່ຂອງກົດລະບຽບ. ແຕ່ລະຂີດຖືກປ່ຽນເປັນ
ຂີດກ້ອງໃນລະຫັດແຫຼ່ງ C ທີ່ສ້າງຂຶ້ນ. ຂີດດຽວ '-' ແມ່ນ ກ
ຊື່​ກົດ​ຫມາຍ​.

- = [ \t\n\r]*
ເລກ = [0-9]+ -
ຊື່ = [a-zA-Z_][a-zA_Z_0-9]* -
l-paren = '(' -
r-paren = ')' -

ຕົວຢ່າງນີ້ສະແດງໃຫ້ເຫັນວ່າຊ່ອງຫວ່າງທີ່ຖືກລະເລີຍສາມາດເຫັນໄດ້ຊັດເຈນໃນເວລາອ່ານໄວຍາກອນ
ແລະຍັງ unobtrusive ໃນເວລາທີ່ວາງໄວ້ຢ່າງເສລີໃນຕອນທ້າຍຂອງທຸກກົດລະບຽບທີ່ກ່ຽວຂ້ອງກັບ
ອົງປະກອບ lexical.

seq-1 | seq-2
ຕົວປະຕິບັດການສະຫຼັບແມ່ນແຖບຕັ້ງ '|' ແທນທີ່ຈະເປັນຕົວຫຍໍ້ໜ້າ '/'. ໄດ້
peg ກົດລະບຽບ

ຊື່ <- sequence-1
/ sequence-2
/ sequence-3

ດັ່ງນັ້ນຈຶ່ງຂຽນ

name = sequence-1
| ລຳດັບ-2
| ລຳດັບ-3
;

in ຂາ (ມີເຄື່ອງໝາຍຈຸດສຸດທ້າຍເປັນທາງເລືອກ, ດັ່ງທີ່ອະທິບາຍຕໍ່ໄປ).

exp ~ { ການປະຕິບັດ }
ຕົວປະຕິບັດການ postfix ~{ ການປະຕິບັດ } ສາມາດຖືກວາງໄວ້ຫຼັງຈາກການສະແດງອອກໃດໆແລະຈະປະຕິບັດຕົວ
ເຊັ່ນ​ດຽວ​ກັນ​ກັບ​ການ​ປະ​ຕິ​ບັດ​ຕາມ​ປົກ​ກະ​ຕິ (ລະ​ຫັດ C ທີ່​ຕົນ​ເອງ​) ເວັ້ນ​ເສຍ​ແຕ່​ວ່າ​ມັນ​ຖືກ​ຮຽກ​ຮ້ອງ​ພຽງ​ແຕ່​ໃນ​ເວ​ລາ​ທີ່​ exp
ລົ້ມເຫລວ. ມັນຜູກມັດຫນ້ອຍກ່ວາຕົວປະຕິບັດການອື່ນໆຍົກເວັ້ນສະຫຼັບແລະ
sequencing, ແລະມີຈຸດປະສົງເພື່ອເຮັດໃຫ້ການຈັດການຄວາມຜິດພາດແລະລະຫັດການຟື້ນຕົວງ່າຍຂຶ້ນ
ຂຽນ. ໃຫ້ສັງເກດວ່າ yytext ແລະ yyeng ບໍ່ມີຢູ່ໃນການປະຕິບັດເຫຼົ່ານີ້, ແຕ່ວ່າ
ຕົວປ່ຽນຕົວຊີ້ yy ສາມາດໃຊ້ໄດ້ເພື່ອໃຫ້ລະຫັດເຂົ້າເຖິງໃດໆທີ່ຜູ້ໃຊ້ກໍານົດ
ສະມາຊິກຂອງສະຖານະຕົວວິເຄາະ (ເບິ່ງ "ປັບແຕ່ງຕົວວິເຄາະ" ຂ້າງລຸ່ມນີ້). ໃຫ້ສັງເກດວ່າ
exp ສະເຫມີເປັນການສະແດງອອກດຽວ; ເພື່ອຮຽກຮ້ອງການກະ ທຳ ຂໍ້ຜິດພາດ ສຳ ລັບຄວາມລົ້ມເຫຼວພາຍໃນ
ລໍາດັບ, ວົງເລັບຕ້ອງຖືກນໍາໃຊ້ເພື່ອຈັດກຸ່ມລໍາດັບເປັນອັນດຽວ
ການສະແດງອອກ.

rule = e1 e2 e3 ~{ error("e[12] ok; e3 has failed"); }
| ...

rule = (e1 e2 e3) ~{ error("ຫນຶ່ງໃນ e[123] ລົ້ມເຫລວ"); }
| ...

ຮູບແບບ ;
ເຄື່ອງໝາຍວັກຕອນເຄິ່ງຈໍ້າສອງເມັດສາມາດປິດເປັນທາງເລືອກໄດ້ ຮູບແບບ.

%% ຂໍ້​ຄວາມ...
ອັດຕາສ່ວນສອງເທົ່າ '%%' ສິ້ນສຸດກົດລະບຽບ (ແລະການປະກາດ) ພາກສ່ວນຂອງ
ໄວຍາກອນ. ທັງໝົດ ຂໍ້ຄວາມ ຕໍ່​ໄປ​ນີ້ '%%' ຖືກ​ຄັດ​ລອກ​ຄໍາ​ເວົ້າ​ທີ່​ຈະ​ສ້າງ​ລະ​ຫັດ parser C
ຫຼັງຈາກ ລະຫັດການປະຕິບັດຕົວວິເຄາະ.

$$ = ມູນຄ່າ
ກົດລະບຽບຍ່ອຍສາມາດສົ່ງຄືນຄວາມຫມາຍໄດ້ ມູນຄ່າ ຈາກການປະຕິບັດໂດຍການມອບຫມາຍໃຫ້
pseudo-variable '$$'. ຄ່າ semantic ທັງໝົດຕ້ອງມີປະເພດດຽວກັນ (ເຊິ່ງເປັນຄ່າເລີ່ມຕົ້ນ
ກັບ 'int'). ປະເພດນີ້ສາມາດປ່ຽນແປງໄດ້ໂດຍການກໍານົດ YYSTYPE ໃນສ່ວນການປະກາດ.

ຕົວລະບຸ:ຊື່
ຄ່າ semantic ກັບຄືນມາ (ໂດຍການມອບຫມາຍໃຫ້ '$$') ຈາກກົດລະບຽບຍ່ອຍ ຊື່ is
ທີ່ກ່ຽວຂ້ອງກັບ ຕົວລະບຸ ແລະສາມາດຖືກກ່າວເຖິງໃນການປະຕິບັດຕໍ່ໄປ.

ຕົວ​ຢ່າງ​ຂອງ​ເຄື່ອງ​ຄິດ​ເລກ​ຢູ່​ຂ້າງ​ລຸ່ມ​ນີ້​ສະ​ແດງ​ໃຫ້​ເຫັນ​ການ​ນໍາ​ໃຊ້ '$$' ແລະ ':'.

LEG ຕົວຢ່າງ: A ໂຕະ ເຄື່ອງຄິດໄລ່


ສ່ວນຂະຫຍາຍໃນ ຂາ ອະທິບາຍຂ້າງເທິງນີ້ອະນຸຍາດໃຫ້ຕົວວິເຄາະທີ່ເປັນປະໂຫຍດ ແລະຜູ້ປະເມີນ (ລວມທັງ
ປະກາດ, ກົດລະບຽບໄວຍາກອນ, ແລະສະຫນັບສະຫນູນຫນ້າທີ່ C ເຊັ່ນ 'ຕົ້ນຕໍ') ທີ່ຈະຮັກສາໄວ້ພາຍໃນ.
ໄຟລ໌ແຫຼ່ງດຽວ. ເພື່ອ​ສະ​ແດງ​ໃຫ້​ເຫັນ​ນີ້​ພວກ​ເຮົາ​ສະ​ແດງ​ໃຫ້​ເຫັນ​ການ​ຄິດ​ໄລ່ desk ງ່າຍ​ດາຍ​ສະ​ຫນັບ​ສະ​ຫນູນ​
ສີ່ຕົວປະຕິບັດການເລກຄະນິດສາດທົ່ວໄປ ແລະຕົວແປທີ່ມີຊື່. ຜົນໄດ້ຮັບລະດັບປານກາງຂອງ
ການປະເມີນເລກຄະນິດຈະຖືກສະສົມຢູ່ໃນ stack implicit ໂດຍການສົ່ງຄືນໃຫ້ເຂົາເຈົ້າເປັນ
ຄ່າ semantic ຈາກກົດລະບຽບຍ່ອຍ.

%{
#ລວມທັງ /* printf() */
#ລວມທັງ /* atoi() */
int vars[26];
%}

Stmt = - e:Expr EOL { printf("%d\n", e); }
| ( !EOL . )* EOL { printf("error\n"); }

Expr = i:ID ASSIGN s:Sum { $$ = vars[i] = s; }
| s:ລວມ { $$ = s; }

ລວມ = l:ຜະລິດຕະພັນ
(ບວກ r:ຜະລິດຕະພັນ { l += r; }
| MINUS r:ຜະລິດຕະພັນ { l -= r; }
)* { $$ = l; }

ຜະລິດຕະພັນ = l:ມູນຄ່າ
(TIMES r:ຄ່າ { l *= r; }
| DIVIDE r:ຄ່າ { l /= r; }
)* { $$ = l; }

ຄ່າ = i:NUMBER { $$ = atoi(yytext); }
| i:ID !ASSIGN { $$ = vars[i]; }
| ເປີດ i:Expr ປິດ { $$ = i; }

NUMBER = < [0-9]+ > - { $$ = atoi(yytext); }
ID = < [az] > - { $$ = yytext[0] - 'a'; }
ມອບໝາຍ = '=' -
ບວກ = '+' -
MINUS = '-' -
TIMES = '*' -
DIVIDE = '/' -
ເປີດ = '(' -
CLOSE = ')' -

- = [ \t ]*
EOL = '\n' | '\r\n' | '\r' | ';'

%%

int ຕົ້ນຕໍ ()
{
ໃນຂະນະທີ່ (yyparse())
;
return 0
}

LEG ໄວຍະກອນ FOR LEG ໄວຍະກອນ


ໄວຍາກອນສໍາລັບ ຂາ ໄວຍະກອນແມ່ນສະແດງໃຫ້ເຫັນຂ້າງລຸ່ມນີ້. ນີ້ຈະສະແດງໃຫ້ເຫັນທັງສອງຢ່າງແລະເປັນທາງການ
ຄຳອະທິບາຍຂ້າງເທິງ.

ໄວຍະກອນ = -
(ປະກາດ | ຄໍານິຍາມ)+
trailer? ທ້າຍຂອງໄຟລ໌

ປະກາດ = '%{' < ( !'%}' . )* > RPERCENT

trailer = '%%' < .* >

ຄໍານິຍາມ = ຕົວລະບຸ EQUAL expression SEMICOLON?

expression = ລຳດັບ (ລຳດັບ BAR)*

ລໍາດັບ = ຄວາມຜິດພາດ+

error = ຄໍານໍາຫນ້າ ( TILDE action )?

ຄໍານໍາຫນ້າ = ແລະການປະຕິບັດ
| (ແລະ | ບໍ່ແມ່ນ)? ຕໍ່ທ້າຍ

suffix = ປະຖົມ ( QUERY | STAR | PLUS )?

primary = ຕົວລະບຸຕົວລະບຸ COLON !EQUAL
| ຕົວລະບຸ !EQUAL
| ເປີດສະແດງອອກ CLOSE
| ຕົວໜັງສື
| ຫ້ອງຮຽນ
| DOT
| ການກະທຳ
| ເລີ່ມຕົ້ນ
| ສິ້ນສຸດ

ຕົວລະບຸ = < [-a-zA-Z_][-a-zA-Z_0-9]* > -

ລິດ = [']< ( ![']char )* > [']-
| ["]< ( !["] char )* > ["] -

class = '[' < ( !']' range )* > ']' -

range = char '-' char | char

char = '\\' [abefnrtv'"\[\]\\]
| '\\' [0-3][0-7][0-7]
| '\\' [0-7][0-7]?
| !'\\' .

action = '{' < braces* > '}' -

braces = '{' braces* '}'
| !'}' .

EQUAL = '=' -
COLON = ':' -
SEMICOLON = ';' -
BAR = '|' -
ແລະ = '&' -
ບໍ່ແມ່ນ = '!' -
QUERY = '?' -
ດາວ = '*' -
ບວກ = '+' -
ເປີດ = '(' -
CLOSE = ')' -
DOT = '.' -
BEGIN = '<' -
END = '>' -
TILDE = '~' -
RPERCENT = '%}' -

- = (ຊ່ອງ | ຄໍາເຫັນ)*
ຊ່ອງ = ' ' | '\t' | ປາຍສາຍ
comment = '#' ( !end-of-line . )* end-of-line
end-of-line = '\r\n' | '\n' | '\r'
end-of-file = !.

ປັບແຕ່ງ ການ PARSER


ສັນຍາລັກຕໍ່ໄປນີ້ສາມາດຖືກກໍານົດຄືນໃຫມ່ໃນພາກສ່ວນການປະກາດເພື່ອດັດແກ້ທີ່ສ້າງຂຶ້ນ
ລະຫັດວິເຄາະ.

YYSTYPE
ປະເພດມູນຄ່າ semantic. ຕົວແປ pseudo-variable '$$' ແລະຕົວລະບຸ 'ຜູກມັດ' ກັບ
ຜົນໄດ້ຮັບກົດລະບຽບກັບຕົວປະຕິບັດການຈໍ້າສອງເມັດ ':' ທັງຫມົດຄວນຈະຖືກພິຈາລະນາວ່າເປັນການປະກາດ
ທີ່​ຈະ​ມີ​ປະ​ເພດ​ນີ້​. ຄ່າເລີ່ມຕົ້ນແມ່ນ 'int'.

YYPARSE
ຊື່ຂອງຈຸດເຂົ້າຫຼັກໄປຫາຕົວວິເຄາະ. ຄ່າເລີ່ມຕົ້ນແມ່ນ 'yyparse'.

YYPARSEFROM
ຊື່ຂອງທາງເລືອກທີ່ປ້ອນໄປຫາຕົວວິເຄາະ. ຟັງຊັນນີ້ຄາດຫວັງວ່າຫນຶ່ງ
argument: ຟັງຊັນທີ່ສອດຄ້ອງກັບກົດລະບຽບທີ່ຊອກຫາການຈັບຄູ່
ຄວນເລີ່ມຕົ້ນ. ຄ່າເລີ່ມຕົ້ນແມ່ນ 'yyparsefrom'. ໃຫ້ສັງເກດວ່າ yyparse() ຖືກກໍານົດເປັນ

int yyparse() { return yyparsefrom(yy_foo); }

ບ່ອນທີ່ 'foo' ແມ່ນຊື່ຂອງກົດລະບຽບທໍາອິດໃນໄວຍາກອນ.

YY_INPUT(buff, ຜົນ, ຂະໜາດສູງສຸດ)
ມະຫາພາກນີ້ຖືກເອີ້ນໂດຍຕົວແຍກວິເຄາະເພື່ອໃຫ້ໄດ້ຂໍ້ຄວາມທີ່ປ້ອນເຂົ້າຫຼາຍຂຶ້ນ. buff ຊີ້ໃຫ້ເຫັນເຖິງ
ພື້ນທີ່ຂອງຄວາມຊົງຈໍາທີ່ສາມາດຖືໄດ້ຫຼາຍທີ່ສຸດ ຂະໜາດສູງສຸດ ຕົວລະຄອນ. ມະຫາພາກຄວນສຳເນົາ
ປ້ອນຂໍ້ຄວາມໃສ່ buff ແລະຫຼັງຈາກນັ້ນກໍານົດຕົວແປຈໍານວນເຕັມ ຜົນ ເພື່ອຊີ້ບອກ
ສຳເນົາຕົວອັກສອນ. ຖ້າບໍ່ມີການປ້ອນຂໍ້ມູນເພີ່ມເຕີມ, macro ຄວນ
ມອບໝາຍ 0 ໃຫ້ ຜົນ. ໂດຍຄ່າເລີ່ມຕົ້ນ, ມະຫາພາກ YY_INPUT ຖືກກຳນົດໄວ້ດັ່ງນີ້.

#ກຳນົດ YY_INPUT(buf, ຜົນໄດ້ຮັບ, max_size) \
{ \
int yyc= getchar(); \
ຜົນໄດ້ຮັບ = (EOF == yyc) ? 0 : (*(buf)= yyc, 1); \
}

ໃຫ້ສັງເກດວ່າຖ້າ YY_CTX_LOCAL ຖືກກໍານົດ (ເບິ່ງຂ້າງລຸ່ມນີ້) ຫຼັງຈາກນັ້ນ, ການໂຕ້ຖຽງທໍາອິດເພີ່ມເຕີມ,
ປະກອບດ້ວຍບໍລິບົດການວິເຄາະ, ຖືກສົ່ງກັບ YY_INPUT.

YY_DEBUG
ຖ້າສັນຍາລັກນີ້ຖືກກໍານົດ, ລະຫັດເພີ່ມເຕີມຈະຖືກລວມຢູ່ໃນຕົວວິເຄາະ
ພິມຂໍ້ມູນ arcane ຈໍານວນຫຼວງຫຼາຍໃຫ້ກັບຄວາມຜິດພາດມາດຕະຖານໃນຂະນະທີ່ເຄື່ອງວິເຄາະ
ກຳ ລັງແລ່ນ.

YY_BEGIN
ມະຫາພາກນີ້ຖືກຮຽກຮ້ອງເພື່ອໝາຍຈຸດເລີ່ມຕົ້ນຂອງຂໍ້ຄວາມທີ່ປ້ອນເຂົ້າທີ່ຈະສາມາດໃຊ້ໄດ້
ໃນການປະຕິບັດເປັນ 'yytext'. ນີ້ເທົ່າກັບການປະກົດຕົວຂອງ '<' ໃນໄວຍະກອນ.
ສິ່ງເຫຼົ່ານີ້ຖືກປ່ຽນເປັນ predicates ທີ່ຄາດວ່າຈະປະສົບຜົນສໍາເລັດ. ຄ່າເລີ່ມຕົ້ນ
ຄໍານິຍາມ

#define YY_BEGIN (yybegin= yypos, 1)

ດັ່ງນັ້ນຈຶ່ງຊ່ວຍປະຢັດຕໍາແຫນ່ງ input ໃນປັດຈຸບັນແລະກັບຄືນ 1 ('true') ເປັນຜົນມາຈາກ
ຄາດ.

YY_END ມະຫາພາກນີ້ກົງກັບ '>' ໃນໄວຍະກອນ. ອີກເທື່ອຫນຶ່ງ, ມັນເປັນ predicate ດັ່ງນັ້ນ
ຄໍານິຍາມເລີ່ມຕົ້ນຈະບັນທຶກຕໍາແຫນ່ງປ້ອນຂໍ້ມູນກ່ອນທີ່ຈະ 'ສໍາເລັດ'.

#define YY_END (yyend= yypos, 1)

YY_PARSE(T)
ມະຫາພາກນີ້ປະກາດຈຸດເຂົ້າຕົວວິເຄາະ (yyparse ແລະ yyparsefrom) ເປັນປະເພດ.
T. ຄໍານິຍາມເລີ່ມຕົ້ນ

#ກຳນົດ YY_PARSE(T) T

ໃບ yyparse() ແລະ yyparsefrom() ດ້ວຍການເບິ່ງເຫັນທົ່ວໂລກ. ຖ້າພວກເຂົາບໍ່ຄວນເປັນ
ເຫັນໄດ້ຈາກພາຍນອກໃນໄຟລ໌ແຫຼ່ງອື່ນໆ, ມະຫາພາກນີ້ສາມາດຖືກກຳນົດຄືນໃໝ່ເພື່ອປະກາດ
ເຂົາເຈົ້າ 'static'.

#define YY_PARSE(T) static T

YY_CTX_LOCAL
ຖ້າສັນຍາລັກນີ້ຖືກກໍານົດໃນລະຫວ່າງການລວບລວມຕົວແຍກທີ່ສ້າງຂຶ້ນຫຼັງຈາກນັ້ນທົ່ວໂລກ
ສະຖານະຕົວວິເຄາະຈະຖືກເກັບໄວ້ໃນໂຄງສ້າງຂອງປະເພດ 'yycontext' ເຊິ່ງສາມາດປະກາດໄດ້
ເປັນຕົວແປທ້ອງຖິ່ນ. ນີ້ອະນຸຍາດໃຫ້ຫຼາຍໆຕົວຢ່າງຂອງ parsers ຢູ່ຮ່ວມກັນແລະ
ປອດໄພກະດ້າງ. ຟັງຊັນການແຍກ yyparse() ຈະຖືກປະກາດວ່າຄາດວ່າຈະມີຄັ້ງທໍາອິດ
ການໂຕ້ຖຽງຂອງປະເພດ 'yycontext *', ຕົວຢ່າງຂອງໂຄງສ້າງທີ່ຖືທົ່ວໂລກ
ລັດສໍາລັບຕົວວິເຄາະ. ຕົວຢ່າງນີ້ຕ້ອງໄດ້ຮັບການຈັດສັນແລະເລີ່ມຕົ້ນເປັນສູນໂດຍ
ລູກຄ້າ. ຕົວຢ່າງເລັກນ້ອຍແຕ່ຄົບຖ້ວນສົມບູນມີດັ່ງນີ້.

#ລວມ

#ກຳນົດ YY_CTX_LOCAL

#include "the-generated-parser.peg.c"

int ຕົ້ນຕໍ ()
{
yycontext ctx;
memset(&ctx, 0, sizeof(yycontext));
ໃນຂະນະທີ່ (yyparse(&ctx));
return 0
}

ໃຫ້ສັງເກດວ່າຖ້າສັນຍາລັກນີ້ບໍ່ໄດ້ຖືກ ກຳ ນົດຫຼັງຈາກນັ້ນຕົວວິເຄາະທີ່ລວບລວມຈະຄົງທີ່
ຈັດສັນລັດທົ່ວໂລກຂອງຕົນ ແລະຈະບໍ່ເປັນຄືນມາ ຫຼືປອດໄພ. ຫມາຍເຫດຍັງ
ວ່າໂຄງສ້າງ yycontext parser ຖືກເລີ່ມຕົ້ນໂດຍອັດຕະໂນມັດໃນຄັ້ງທໍາອິດ
yyparse() ເອີ້ນວ່າ; ໂຄງ​ປະ​ກອບ​ການ​ນີ້​ ຕ້ອງ ດັ່ງນັ້ນຈຶ່ງຖືກເລີ່ມຕົ້ນຢ່າງຖືກຕ້ອງເປັນສູນ
ກ່ອນທີ່ຈະໂທຫາຄັ້ງທໍາອິດ yyparse,

YY_CTX_MEMBERS
ຖ້າ YY_CTX_LOCAL ຖືກກໍານົດ (ເບິ່ງຂ້າງເທິງ) ຫຼັງຈາກນັ້ນ macro YY_CTX_MEMBERS ສາມາດຖືກກໍານົດ.
ເພື່ອຂະຫຍາຍໄປຫາການປະກາດພາກສະຫນາມສະມາຊິກເພີ່ມເຕີມທີ່ລູກຄ້າຕ້ອງການ
ລວມຢູ່ໃນການປະກາດປະເພດໂຄງສ້າງ 'yycontext'. ເຫຼົ່ານີ້ເພີ່ມເຕີມ
ສະມາຊິກຈະຖືກລະເລີຍໂດຍຕົວແຍກວິເຄາະທີ່ສ້າງຂຶ້ນ. ຕົວຢ່າງຂອງ 'yycontext'
ທີ່​ກ່ຽວ​ຂ້ອງ​ກັບ parser ທີ່​ໃຊ້​ໃນ​ປັດ​ຈຸ​ບັນ​ແມ່ນ​ມີ​ຢູ່​ພາຍ​ໃນ​ການ​ປະ​ຕິ​ບັດ​ເປັນ​
ຕົວປ່ຽນຕົວຊີ້ yy.

YY_BUFFER_SIZE
ຂະຫນາດເບື້ອງຕົ້ນຂອງຂໍ້ຄວາມ buffer, ໃນ bytes. ຄ່າເລີ່ມຕົ້ນແມ່ນ 1024 ແລະ buffer
ຂະ​ຫນາດ​ແມ່ນ​ເພີ່ມ​ຂຶ້ນ​ສອງ​ເທົ່າ​ທຸກ​ຄັ້ງ​ທີ່​ຕ້ອງ​ການ​ເພື່ອ​ຕອບ​ສະ​ຫນອງ​ຄວາມ​ຕ້ອງ​ການ​ໃນ​ລະ​ຫວ່າງ​ການ​ວິ​ເຄາະ​. ຄໍາຮ້ອງສະຫມັກ
ທີ່ໂດຍທົ່ວໄປແລ້ວ parses ສາຍຍາວຫຼາຍສາມາດເພີ່ມອັນນີ້ເພື່ອຫຼີກເວັ້ນການທີ່ບໍ່ຈໍາເປັນ
ການຈັດສັນພູມຕ້ານທານ.

YY_STACK_SIZE
ຂະໜາດເບື້ອງຕົ້ນຂອງຕົວແປ ແລະ stacks ການປະຕິບັດ. ຄ່າເລີ່ມຕົ້ນແມ່ນ 128, ເຊິ່ງແມ່ນ
ເພີ່ມຂຶ້ນສອງເທົ່າທຸກຄັ້ງທີ່ຕ້ອງການເພື່ອຕອບສະໜອງຄວາມຕ້ອງການໃນລະຫວ່າງການວິເຄາະ. ຄໍາຮ້ອງສະຫມັກທີ່ມີ
ການໂທເລິກຊ້ອນກັບຕົວແປທ້ອງຖິ່ນຫຼາຍອັນ, ຫຼືວ່າປະຕິບັດຫຼາຍຢ່າງຫຼັງຈາກ a
ການແຂ່ງຂັນທີ່ປະສົບຜົນສໍາເລັດອັນດຽວ, ສາມາດເພີ່ມທະວີການນີ້ເພື່ອຫຼີກເວັ້ນການ buffer ທີ່ບໍ່ຈໍາເປັນ
ການຈັດສັນ.

YY_MALLOC(YY, ຫລືຂະຫຍາຍໂຕ)
ໜ່ວຍຄວາມຈຳສຳລັບບ່ອນເກັບຂໍ້ມູນທີ່ກ່ຽວຂ້ອງກັບຕົວແຍກວິເຄາະທັງໝົດ. ຕົວກໍານົດການແມ່ນ
ໂຄງສ້າງ yy ປະຈຸບັນແລະຈໍານວນຂອງ bytes ທີ່ຈະຈັດສັນ. ຄ່າເລີ່ມຕົ້ນ
ຄໍານິຍາມແມ່ນ: malloc(ຫລືຂະຫຍາຍໂຕ)

YY_REALLOC(YY, PTR, ຫລືຂະຫຍາຍໂຕ)
ຕົວຈັດແບ່ງໜ່ວຍຄວາມຈຳສຳລັບການເກັບຮັກສາແບບໄດນາມິກ (ເຊັ່ນ: ຂໍ້ຄວາມ buffers ແລະ
stacks ຕົວປ່ຽນແປງ). ພາລາມິເຕີແມ່ນໂຄງສ້າງ yycontext ໃນປັດຈຸບັນ, the
ການ​ຈັດ​ສັນ​ທີ່​ຈັດ​ສັນ​ໃນ​ເມື່ອ​ກ່ອນ​, ແລະ​ຈໍາ​ນວນ​ຂອງ​ໄບ​ຕ​໌​ທີ່​ຈະ​ເກັບ​ຮັກ​ສາ​ໄວ້​
ເຕີບໃຫຍ່. ຄໍານິຍາມເລີ່ມຕົ້ນແມ່ນ: realloc(PTR, ຫລືຂະຫຍາຍໂຕ)

YY_FREE(YY, PTR)
ຕົວແທນຈໍາຫນ່າຍຫນ່ວຍຄວາມຈໍາ. ພາລາມິເຕີແມ່ນໂຄງສ້າງ yycontext ໃນປັດຈຸບັນແລະ
ການ​ເກັບ​ຮັກ​ສາ​ທີ່​ຈະ​ຈັດ​ສັນ​. ຄໍານິຍາມໃນຕອນຕົ້ນແມ່ນ: free(PTR)

YYRELEASE
ຊື່ຂອງຟັງຊັນທີ່ປ່ອຍຊັບພະຍາກອນທັງຫມົດທີ່ຖືໂດຍໂຄງສ້າງ yycontext.
ຄ່າເລີ່ມຕົ້ນແມ່ນ 'yyrelease'.

ຕົວແປຕໍ່ໄປນີ້ສາມາດຖືກອ້າງເຖິງພາຍໃນການປະຕິບັດ.

char *yybuf
ຕົວແປນີ້ຊີ້ໃຫ້ເຫັນເຖິງການປ້ອນຂໍ້ມູນຂອງ parser buffer ທີ່ໃຊ້ເພື່ອເກັບຮັກສາຂໍ້ຄວາມປ້ອນຂໍ້ມູນທີ່ມີ
ຍັງບໍ່ທັນຖືກຈັບຄູ່.

int yypos
ນີ້ແມ່ນການຊົດເຊີຍ (ໃນ yybuf) ຂອງຕົວອັກສອນຕໍ່ໄປທີ່ຈະຈັບຄູ່ແລະບໍລິໂພກ.

char * yytext
ຂໍ້ຄວາມທີ່ກົງກັນຫຼ້າສຸດທີ່ຂັ້ນດ້ວຍ '<' ແລະ '>' ຖືກເກັບໄວ້ໃນຕົວແປນີ້.

int yyeng
ຕົວແປນີ້ຊີ້ບອກຈໍານວນຕົວອັກສອນໃນ 'yytext'.

ເນື້ອໃນ yy *ປີ
ຕົວແປນີ້ຊີ້ໃຫ້ເຫັນເຖິງຕົວຢ່າງຂອງ 'yycontext' ທີ່ກ່ຽວຂ້ອງກັບ
parser ທີ່ໃຊ້ໃນປັດຈຸບັນ.

ໂປຣແກຣມທີ່ຕ້ອງການປ່ອຍຊັບພະຍາກອນທັງໝົດທີ່ກ່ຽວຂ້ອງກັບຕົວວິເຄາະສາມາດນຳໃຊ້ໄດ້
ຫນ້າ​ທີ່​ດັ່ງ​ຕໍ່​ໄປ​ນີ້​.

yyrelease(yyrelease*yy)
ສົ່ງຄືນພື້ນທີ່ເກັບຂໍ້ມູນທີ່ຈັດສັນໂດຍຕົວວິເຄາະທັງໝົດທີ່ກ່ຽວຂ້ອງກັບ yy ກັບລະບົບ. ການເກັບຮັກສາ
ຈະຖືກຈັດສັນຄືນໃໝ່ໃນການໂທຄັ້ງຕໍ່ໄປ yyparse,

ໃຫ້ສັງເກດວ່າບ່ອນເກັບມ້ຽນສໍາລັບໂຄງສ້າງ yycontext ຕົວມັນເອງບໍ່ເຄີຍຖືກຈັດສັນຫຼືຍຶດຄືນ
ໂດຍທາງອ້ອມ. ຄໍາຮ້ອງສະຫມັກຕ້ອງຈັດສັນໂຄງສ້າງເຫຼົ່ານີ້ໃນການເກັບຮັກສາອັດຕະໂນມັດ, ຫຼືການນໍາໃຊ້
ໂທກ() ແລະ ຟຣີ() ເພື່ອຄຸ້ມຄອງພວກມັນຢ່າງຈະແຈ້ງ. ຕົວຢ່າງໃນພາກຕໍ່ໄປນີ້
ສະແດງໃຫ້ເຫັນວິທີການຫນຶ່ງໃນການຄຸ້ມຄອງຊັບພະຍາກອນ.

LEG ຕົວຢ່າງ: ຂະຫຍາຍ ການ PARSER'S CONTEXT


ໄດ້ yy ຕົວແປທີ່ສົ່ງຕໍ່ກັບການກະທຳປະກອບມີສະຖານະຂອງຕົວວິເຄາະບວກກັບສິ່ງເພີ່ມເຕີມ
ຊ່ອງຂໍ້ມູນທີ່ກຳນົດໂດຍ YY_CTX_MEMBERS. ຊ່ອງຂໍ້ມູນເຫຼົ່ານີ້ສາມາດຖືກນໍາໃຊ້ເພື່ອເກັບຮັກສາຄໍາຮ້ອງສະຫມັກສະເພາະ
ຂໍ້​ມູນ​ທີ່​ເປັນ​ທົ່ວ​ໂລກ​ກັບ​ການ​ໂທ​ສະ​ເພາະ​ຂອງ​ yyparse(). ເປັນເລື່ອງເລັກໆນ້ອຍໆແຕ່ສົມບູນ ຂາ
ຕົວຢ່າງຕໍ່ໄປນີ້ທີ່ໂຄງສ້າງ yycontext ຖືກຂະຫຍາຍດ້ວຍ a ນັບ ຂອງຈໍານວນຂອງ
ຕົວອັກສອນແຖວໃໝ່ທີ່ເຫັນໃນການປ້ອນຂໍ້ມູນມາເຖິງຕອນນັ້ນ (ໄວຍະກອນນັ້ນຈະບໍລິໂພກ ແລະ ບໍ່ສົນໃຈ
ການປ້ອນຂໍ້ມູນທັງໝົດ). ຜູ້ໂທຂອງ yyparse() ໃຊ້ ນັບ ເພື່ອພິມຈໍານວນຂອງສາຍຂອງ
ວັດສະດຸປ້ອນທີ່ຖືກອ່ານ.

%{
#ກຳນົດ YY_CTX_LOCAL 1
#ກຳນົດ YY_CTX_MEMBERS \
int ນັບ;
%}

Char = ('\n' | '\r\n' | '\r') { yy->count++ }
| .

%%

#ລວມ
#ລວມທັງ

int ຕົ້ນຕໍ ()
{
/* ສ້າງບໍລິບົດ parser ທ້ອງຖິ່ນໃນການເກັບຮັກສາອັດຕະໂນມັດ */
yy ສະພາບການ yy;
/* ບໍລິບົດ *ຕ້ອງ* ເລີ່ມຕົ້ນເປັນສູນກ່ອນນຳໃຊ້ຄັ້ງທຳອິດ*/
memset(&yy, 0, sizeof(yy));

ໃນຂະນະທີ່ (yyparse(&yy))
;
printf("%d ແຖວໃໝ່\n", yy.count);

/* ປ່ອຍຊັບພະຍາກອນທັງໝົດທີ່ກ່ຽວຂ້ອງກັບບໍລິບົດ */
yyrelease(&yy);

return 0
}

ທິດສະດີວິທະຍາ


peg ແລະ ຂາ ເຕືອນກ່ຽວກັບເງື່ອນໄຂຕໍ່ໄປນີ້ໃນຂະນະທີ່ປ່ຽນໄວຍາກອນເປັນ parser.

syntax ຄວາມຜິດພາດ
ໄວຍະກອນການປ້ອນຂໍ້ມູນບໍ່ຖືກຕ້ອງໃນບາງທາງ. ຂໍ້​ຄວາມ​ຜິດ​ພາດ​ຈະ​ປະ​ກອບ​ມີ​
ຂໍ້​ຄວາມ​ກ່ຽວ​ກັບ​ການ​ທີ່​ຈະ​ຖືກ​ຈັບ​ຄູ່ (ມັກ​ຈະ​ສໍາ​ຮອງ​ຂໍ້​ມູນ​ຈໍາ​ນວນ​ຫຼາຍ​ຈາກ​ສະ​ຖານ​ທີ່​ຕົວ​ຈິງ​ຂອງ​
ຂໍ້ຜິດພາດ) ແລະຕົວເລກແຖວຂອງຕົວອັກສອນທີ່ພິຈາລະນາຫຼ້າສຸດ (ເຊິ່ງແມ່ນ
ເລື້ອຍໆສະຖານທີ່ທີ່ແທ້ຈິງຂອງບັນຫາ).

ກົດລະບຽບ 'ຟູ' ໃຫມ່ ແຕ່ ບໍ່ ກໍານົດໄວ້
ໄວຍາກອນຫມາຍເຖິງກົດລະບຽບທີ່ມີຊື່ວ່າ 'foo' ແຕ່ບໍ່ມີຄໍານິຍາມສໍາລັບມັນ.
ການພະຍາຍາມໃຊ້ຕົວແຍກວິເຄາະທີ່ສ້າງຂຶ້ນນັ້ນອາດຈະເຮັດໃຫ້ເກີດຄວາມຜິດພາດຈາກຕົວເຊື່ອມຕໍ່
ເນື່ອງຈາກສັນຍາລັກທີ່ບໍ່ໄດ້ກໍານົດທີ່ກ່ຽວຂ້ອງກັບກົດລະບຽບທີ່ຂາດຫາຍໄປ.

ກົດລະບຽບ 'ຟູ' ກໍານົດໄວ້ ແຕ່ ບໍ່ ໃຫມ່
ໄວຍາກອນໄດ້ກໍານົດກົດລະບຽບທີ່ມີຊື່ວ່າ 'foo' ແລະຫຼັງຈາກນັ້ນບໍ່ສົນໃຈມັນ. ລະຫັດທີ່ກ່ຽວຂ້ອງ
ກັບກົດລະບຽບແມ່ນລວມຢູ່ໃນຕົວແຍກວິເຄາະທີ່ສ້າງຂຶ້ນເຊິ່ງຈະຢູ່ໃນທຸກໆດ້ານ
ມີສຸຂະພາບດີ.

ເປັນໄປໄດ້ infinite ໄວ້ ການເອີ້ນຄືນ in ກົດລະບຽບ 'ຟູ'
ມີຢ່າງຫນ້ອຍຫນຶ່ງເສັ້ນທາງຜ່ານໄວຍາກອນທີ່ນໍາພາຈາກກົດລະບຽບ 'foo'.
ກັບຄືນໄປບ່ອນ (ການຮຽກຮ້ອງ recursive ຂອງ) ກົດລະບຽບດຽວກັນໂດຍບໍ່ມີການບໍລິໂພກການປ້ອນຂໍ້ມູນໃດໆ.

recursion ຊ້າຍ, ໂດຍສະເພາະທີ່ພົບເຫັນຢູ່ໃນເອກະສານມາດຕະຖານ, ມັກຈະ 'ໂດຍກົງ' ແລະ
ຫມາຍເຖິງການຊໍ້າຊາກເລັກນ້ອຍ.

# (6.7.6)
direct-abstract-declarator =
LPAREN abstract-declarator RPAREN
| direct-abstract-declarator? LBRACKET assign-expr? RBRACKET
| direct-abstract-declarator? RBRACKET ດາວ LBRACKET
| direct-abstract-declarator? LPAREN param-type-list? RPAREN

recursion ສາມາດໄດ້ຮັບການກໍາຈັດໄດ້ຢ່າງງ່າຍດາຍໂດຍການແປງພາກສ່ວນຂອງຮູບແບບດັ່ງຕໍ່ໄປນີ້
recursion ເຂົ້າໄປໃນ suffix ຊ້ໍາ.

# (6.7.6)
direct-abstract-declarator =
direct-abstract-declarator-head?
direct-abstract-declarator-tail*

direct-abstract-declarator-head =
LPAREN abstract-declarator RPAREN

direct-abstract-declarator-tail =
LBRACKET assign-expr? RBRACKET
| RBRACKET ດາວ LBRACKET
| LPAREN param-type-list? RPAREN

ຂໍ້ຄວນລະວັງ


ຕົວແຍກວິເຄາະທີ່ຍອມຮັບການປ້ອນຂໍ້ມູນຫວ່າງເປົ່າຈະ ສະເຫມີໄປ ສໍາເລັດ. ພິຈາລະນາຕົວຢ່າງຕໍ່ໄປນີ້,
ບໍ່ແມ່ນຄວາມຜິດປົກກະຕິຂອງຄວາມພະຍາຍາມທໍາອິດທີ່ຈະຂຽນຕົວວິເຄາະທີ່ອີງໃສ່ PEG:

ໂຄງ​ການ = ການ​ສະ​ແດງ​ອອກ *
ການສະແດງອອກ = "ອັນໃດກໍໄດ້"
%%
int ຕົ້ນຕໍ () {
ໃນຂະນະທີ່ (yyparse())
puts("ຄວາມ​ສໍາ​ເລັດ!");
return 0
}

ໂປຣແກມນີ້ loops ຕະຫຼອດໄປ, ບໍ່ວ່າມີ input ໃດ (ຖ້າມີ) ຢູ່ໃນ stdin. ຫຼາຍ
ການ​ແກ້​ໄຂ​ແມ່ນ​ເປັນ​ໄປ​ໄດ້​, ທີ່​ງ່າຍ​ທີ່​ສຸດ​ທີ່​ຈະ​ຮຽກ​ຮ້ອງ​ໃຫ້​ມີ​ການ parser ສະ​ເຫມີ​ກິນ​ບາງ​ສ່ວນ​
ການປ້ອນຂໍ້ມູນທີ່ບໍ່ຫວ່າງເປົ່າ. ການປ່ຽນແປງແຖວທໍາອິດເປັນ

ໂປຣແກມ = Expression+

ສໍາເລັດນີ້. ຖ້າ parser ຄາດວ່າຈະໃຊ້ການປ້ອນຂໍ້ມູນທັງຫມົດ, ຫຼັງຈາກນັ້ນຢ່າງຈະແຈ້ງ
ການຮຽກຮ້ອງໃຫ້ມີການສິ້ນສຸດຂອງໄຟລ໌ແມ່ນຍັງແນະນໍາໃຫ້ສູງ:

ໂປຣແກມ = Expression+ !.

ອັນນີ້ໃຊ້ໄດ້ເພາະວ່າຕົວວິເຄາະພຽງແຕ່ບໍ່ສາມາດຈັບຄູ່ ("!" predicate) ຕົວອັກສອນໃດໆທັງໝົດ
("." expression) ເມື່ອມັນພະຍາຍາມອ່ານເກີນຈຸດສິ້ນສຸດຂອງການປ້ອນຂໍ້ມູນ.

ໃຊ້ peg ອອນໄລນ໌ໂດຍໃຊ້ບໍລິການ onworks.net


ເຊີບເວີ ແລະສະຖານີເຮັດວຽກຟຣີ

ດາວໂຫຼດແອັບ Windows ແລະ Linux

Linux ຄຳ ສັ່ງ

  • 1
    4ti2-ປົກກະຕິ
    4ti2-ປົກກະຕິ
    4ti2 - ຊຸດຊອບແວສໍາລັບ algebraic,
    ບັນຫາເລຂາຄະນິດ ແລະ combinatorial ກ່ຽວກັບ
    ຊ່ອງຫວ່າງ...
    ແລ່ນ 4ti2-normalform
  • 2
    4ti2-ຜົນຜະລິດ
    4ti2-ຜົນຜະລິດ
    4ti2 - ຊຸດຊອບແວສໍາລັບ algebraic,
    ບັນຫາເລຂາຄະນິດ ແລະ combinatorial ກ່ຽວກັບ
    ຊ່ອງຫວ່າງ...
    ແລ່ນ 4ti2-output
  • 3
    cpuburn
    cpuburn
    cpuburn, burnBX, burnK6, burnK7,
    burnMMX, burnP5, burnP6 - ການເກັບກໍາ
    ໂປລແກລມທີ່ຈະໂຫຼດໜັກໃສ່ CPU...
    ແລ່ນ cpuburn
  • 4
    cpufreq-aperf
    cpufreq-aperf
    cpufreq-aperf - ຄິດໄລ່ຄ່າສະເລ່ຍ
    ຄວາມຖີ່ໃນໄລຍະເວລາ SYNTAX:
    cpufreq-aperf [ຕົວເລືອກ] DESCRIPTION: ເປີດ
    ໂປເຊດເຊີຫລ້າສຸດມີສອງ MSR
    ລົງທະບຽນ r...
    ແລ່ນ cpufreq-aperf
  • 5
    gbgrid
    gbgrid
    gbgrid - ຜະລິດຕາຂ່າຍໄຟຟ້າຂອງຂໍ້ມູນ ...
    ແລ່ນ gbgrid
  • 6
    gbhill
    gbhill
    gbhill - Hill ສູງສຸດ Likelihhod
    ການ​ຄາດ​ຄະ​ເນ ...
    ແລ່ນ gbhill
  • ເພີ່ມເຕີມ »

Ad