I-convert ang mga regular na expression sa isang non-deterministic state machine. Leksikal na pagsusuri

Kailangan ng isang non-deterministic na makina ng estado M = (Q, T, D, q 0 , F) bumuo ng isang deterministikong may hangganan na makina ng estado M = (Q", T, D", q" 0 , F"). Ang paunang estado para sa automat na nasa ilalim ng konstruksiyon ay ang ε-pagsasara ng paunang estado ng paunang automat. ε-closure - isang set ng mga estado na maaabot mula sa isang ibinigay na isa sa pamamagitan ng mga transition kasama ang ε. Dagdag pa, habang may mga estado kung saan ang mga transition ay hindi pa nagagawa (ang mga transition ay ginawa sa pamamagitan ng mga simbolo, ang mga transition na kung saan ay nasa orihinal na automat), para sa bawat simbolo, ang ε-pagsasara ng hanay ng mga estado na maaabot mula sa itinuturing na estado sa pamamagitan ng paglipat sa pamamagitan ng itinuturing na simbolo ay kinakalkula. Kung ang estado na tumutugma sa nahanap na hanay ay umiiral na, pagkatapos ay isang paglipat ay idinagdag doon. Kung hindi, idaragdag ang bagong natanggap na estado.

Halimbawa

Pagsisimula

Ang mga estado na naaayon sa ε-pagsasara ng paunang estado ay minarkahan. Ang mga estadong ito ay tumutugma sa estado A hinaharap DKA.


Unang pag-ulit

May mga transition mula sa ε-closure hanggang sa NCA states 3 at 10 (ayon sa a at c, ayon sa pagkakabanggit). Para sa state 3, ang ε-closure ay ang set ng states (3, 4, 6), para sa state 10 - (10). Italaga natin ang mga bagong estado ng DFA na naaayon sa mga set na ito bilang B at C.

estado ng DKASet ng mga estado ng NFA
a b c
A{1, 2, 9} B - C
B{3, 4, 6} - - -
C{10} - - -


Pangalawang pag-ulit

Mula sa hanay ng mga estado ng NFA (3, 4, 6) na tumutugma sa estado ng DFA B mayroong dalawang paglipat - sa estado 5 (sa pamamagitan ng b) at 7 (ni c). Ang kanilang ε-closures ay nagsalubong, ngunit ang mga set mismo ay naiiba, kaya sila ay itinalaga ng dalawang bagong DFA states - D at E. Mula sa mga estado ng NFA na naaayon sa estado ng DFA C, walang mga transition.

estado ng DKASet ng mga estado ng NFAJumpable na mga character
a b c
A{1, 2, 9} B - C
B{3, 4, 6} - DE
C{10} - - -
D{2, 5, 8, 9} - - -
E{2, 7, 8, 9} - - -


Pangatlong pag-ulit

Mula sa mga hanay ng mga estado ng NFA na naaayon sa mga estado ng DFA D at E ginagawa ang mga paglipat sa mga hanay ng mga estado na naaayon sa mga umiiral na estado (mula sa hanay (2, 5, 8, 9) na tumutugma sa estado D, sa a paglipat sa estado 3 na kabilang sa set (3, 4, 6) na tumutugma sa estado ng DFA B, sa c- paglipat sa estado 10 na naaayon sa estado C; katulad din para sa set na tumutugma sa estado ng DFA E). Ang proseso ng pagbuo ng talahanayan ng mga estado at mga paglipat ng DFA ay nakumpleto.

estado ng DKASet ng mga estado ng NFAJumpable na mga character
a b c
A{1, 2, 9} B - C
B{3, 4, 6} - DE
C{10} - - -
D{2, 5, 8, 9} B - C
E{2, 7, 8, 9} B - C


Resulta:

Pagbuo ng isang right-linear na grammar mula sa isang may hangganan na automat

Ang bawat estado ay nauugnay sa isang hindi terminal. Kung mayroong paglipat ng estado X sa isang estado Y sa a, magdagdag ng panuntunan XaY. Para sa mga huling estado, magdagdag ng mga panuntunan X→ e. Para sa ε-transition - XY.

Halimbawa 1 (deterministic state machine)

  • A → a b | c C
  • B → b D | c E
  • C → e
  • D → a b | c C
  • E → a b | c C

Halimbawa 2 (non-deterministic state machine)

  • 1 → 2 | 9
  • 2 → a 3
  • 3 → 4 | 6
  • 4 → b 5
  • 5 → 8
  • 6 → c 7
  • 7 → 8
  • 8 → 2 | 9
  • 9 → c 10
  • 10 → ε

Konstruksyon ng DFA sa pamamagitan ng RV

Magkaroon tayo ng isang regular na expression r. Batay sa regular na expression na ito, kinakailangan na bumuo ng isang deterministikong finite automat D ganyan L(D) = L(r).

Regular na pagbabago sa expression

Magdagdag tayo ng simbolo dito, ibig sabihin ang dulo ng RV - "#". Bilang resulta, nakakakuha kami ng isang regular na expression ( r)#.

Paggawa ng puno

Isipin natin ang isang regular na expression bilang isang puno, ang mga dahon nito ay ang mga terminal na character, at ang mga panloob na node ay ang mga operasyon ng concatenation ".", unyon "∪" at pag-ulit "*". Nagtatalaga kami ng natatanging numero sa bawat dahon ng puno (maliban sa ε-dahon) at tinutukoy ito, sa isang banda, bilang posisyon sa puno at, sa kabilang banda, bilang posisyon ng simbolo na tumutugma sa dahon.

Pagkalkula ng mga function na nullable, firstpos, lastpos

Ngayon, binabagtas ang puno T mula sa ibaba hanggang sa itaas mula kaliwa hanggang kanan, kinakalkula namin ang tatlong function: nullable, firstpos, at lastpos. Mga pag-andar nullable, firstpos at lastpos tinukoy sa mga node ng puno. Ang halaga ng lahat ng mga function maliban nullable, ay ang hanay ng mga posisyon. Function firstpos(n) para sa bawat node n ng regex syntax tree ay nagbibigay ng hanay ng mga posisyon na tumutugma sa mga unang character sa mga substring na nabuo ng subexpression na nagtatapos sa n. Gayundin, lastpos(n) ay nagbibigay ng hanay ng mga posisyon na tumutugma sa mga huling character sa mga substring na nabuo ng mga subexpression na may tuktok n. Para sa mga node n, na ang mga subtree (iyon ay, isang puno na ang node n ay isang ugat) ay maaaring makabuo ng isang walang laman na salita, tinutukoy namin nullable(n) = totoo, at para sa iba pang mga node mali. Talahanayan upang kalkulahin nullable, firstpos, lastpos:

buhol n nullable(n) firstpos(n) lastpos(n)
ε totoo
i ≠ ε mali {i} {i}
ikaw ∪ vnullable(u) o nullable(v) firstpos(u) ∪ firstpos(v) lastpos(u) ∪ lastpos(v)
ikaw . vnullable(u) at nullable(v) kung nullable(u) pagkatapos firstpos(u) ∪ firstpos(v) iba pa firstpos(u) kung nullable(v) pagkatapos lastpos(u) ∪ lastpos(v) iba pa lastpos(v)
v*totoo firstpos(v) lastpos(v)

Mga followpos ng gusali

Function followpos kinakalkula sa pamamagitan ng nullable, firstpos at lastpos. Function followpos tinukoy sa maraming posisyon. Ibig sabihin followpos ay isang hanay ng mga posisyon. Kung ang i- posisyon, pagkatapos followpos(i) maraming posisyon j parang may string... cd... kasama sa wikang inilarawan ng RW, tulad na i tumutugma sa entry na ito c, a j- pagpasok d. Function followpos ay maaari ding kalkulahin sa isang traversal ng puno ayon sa sumusunod na dalawang panuntunan

  1. Hayaan n- panloob na node na may "." (pagsasama-sama); a, b- kanyang mga inapo. Pagkatapos para sa bawat posisyon i kasama sa lastpos(a followpos(i) isang grupo ng firstpos(b).
  2. Hayaan n- panloob na node na may "*" na operasyon (iteration), a- ang kanyang inapo. Pagkatapos para sa bawat posisyon i kasama sa lastpos(a), idagdag sa hanay ng mga halaga followpos(i) isang grupo ng firstpos(a).

Halimbawa

I-compute ang halaga ng function followpos para sa regular na pagpapahayag ( a(b|c))*c.

PosisyonIbig sabihin followpos
1: (a (b|c))*c {2, 3}
2: (a(b |c))*c {1, 4}
3: (a(b|c ))*c {1, 4}
4: (a(b|c))*c {5}

Pagbuo ng isang DFA

Ang DFA ay isang set ng mga estado at isang set ng mga transition sa pagitan nila. Ang estado ng DFA ay isang hanay ng mga posisyon. Ang pagtatayo ng isang DFA ay binubuo sa unti-unting pagdaragdag ng mga kinakailangang estado dito at ang pagtatayo ng mga paglipat para sa kanila. Sa una, mayroong isang estado firstpos(ugat) (ugat- ang ugat ng puno), na walang mga transition. Ang paglipat ay isinasagawa ng mga character mula sa regular na expression. Ang bawat karakter ay tumutugma sa isang hanay ng mga posisyon ( p i). Pinagkakaisa ang lahat followpos(x) ay ang estado kung saan kinakailangang puntahan, kung saan ang x ay isang posisyon na naroroon kapwa sa mga posisyon ng estado at kabilang sa mga posisyon ng simbolo mula sa RE, kung saan ginawa ang paglipat. Kung walang ganoong estado, dapat itong idagdag. Dapat na ulitin ang proseso hanggang sa mabuo ang lahat ng transition para sa lahat ng estado. Ang lahat ng mga estado na naglalaman ng posisyon ng # simbolo na idinagdag sa dulo ng RE ay idineklara na pinal.

DFA na nakuha mula sa RV ( a(b|c))*c

Halimbawa

Bumuo ng DFA sa pamamagitan ng regular na expression ( a(b|c))*c.

estado ng DKASimbolo
a(1)b(2)c(3, 4)
A(1, 4)B(2, 3) - C(5)
B(2, 3) - A(1, 4)A(1, 4)
C(5) - - -

Pagbuo ng isang DFA na may pinakamababang bilang ng mga estado

Ang isang DFA na may pinakamababang bilang ng mga estado ay binuo para sa isang tinukoy na DFA sa lahat ng dako, ibig sabihin. ganyan . Para sa anumang DFA, mayroong isang katumbas na DFA na tinukoy sa lahat ng dako.

Pagbuo ng isang DFA na tinukoy sa lahat ng dako

Magpakilala ng bagong estado at tumukoy ng bagong hanay ng mga estado .

Tukuyin natin ang isang bagong function ng transition tulad nito:

Pagbuo ng partition (pormal)

Buuin natin ang paunang partisyon P hanay ng mga estado sa dalawang pangkat: mga huling estado F at iba pa S/F, ibig sabihin. P = {F, Q\F}.

Ilapat sa bawat pangkat GP sumusunod na pamamaraan. basagin G sa mga subgroup upang ang mga estado s at t mula sa G napunta sa parehong grupo kung at kung para lamang sa bawat input na simbolo a estado s at t may mga transition a sa mga estado mula sa parehong grupo sa P.

Ang mga resultang subgroup ay idinagdag sa bagong partition P bago.

Tanggapin P = P bago at ulitin ang pagtatayo ng partisyon hanggang sa pag-stabilize, ibig sabihin, hanggang sa tumigil ang pagbabago ng partisyon.

Pagbuo ng partition (algorithm)

Upang makabuo ng isang partisyon, mayroong sumusunod na algorithm. Bumubuo kami ng isang talahanayan ng paglipat para sa orihinal na automat, bumuo ng isang paunang partisyon.

Nagtatalaga kami ng identifier sa bawat grupo mula sa partition (para sa unang partition, halimbawa, 0 at 1).

Ang bawat estado (bawat hilera ng talahanayan) ay itinalaga ng isang string ng form na "a.bcd...xyz", kung saan ang identifier ng pangkat kung saan ang estado ay kabilang sa [unang column (kung saan tayo nagmula), ang pangalawa. column (kung saan tayo pupunta sa pamamagitan ng unang character), ..., ang huling column (kung saan tayo pupunta ng huling character)].

Bumubuo kami ng mga bagong grupo ayon sa pagkakataon ng mga string, ibig sabihin, upang ang mga estado na may parehong nakatalagang mga string ay mahulog sa isang grupo.

Pagkatapos, isang bagong pag-ulit. Nagtatalaga kami ng mga bagong identifier sa mga resultang grupo, halimbawa (0, 1, ..., n). At inuulit namin ang pagtatayo ng partisyon hanggang sa pag-stabilize.

Tandaan na kapag mayroon na lamang isang estado na natitira sa grupo, sa mga susunod na yugto ng pagbuo ng partition, hindi mo na maisusulat ang string ng mga identifier para sa estado na ito, dahil ang string na ito ay magiging kakaiba sa anumang kaso dahil sa unang character ng ang tali. Sa madaling salita, kapag naghahati, walang mangyayari sa isang grupo mula sa isang estado - ito ay ililipat sa isang bagong hati.

Konstruksyon ng pinababang automat

Ang bawat isa sa mga resultang grupo ay nagiging estado ng isang bagong DFA. Kung ang pangkat ay naglalaman ng paunang (panghuling) estado ng orihinal na automat, ang pangkat na ito ay magiging paunang (ayon sa pagkakabanggit pangwakas) na estado ng bagong DFA. Ang mga paglipat ay binuo sa isang malinaw na paraan: ang isang paglipat sa isang estado mula sa isang pangkat ay itinuturing na isang paglipat sa isang pangkat.

Dala namin ang makina. Inalis muna namin ang hindi bumubuo (sterile, "patay"), pagkatapos hindi maabot na mga estado (ibinigay ang mga kahulugan para sa mga simbolo, ngunit sa isang malinaw na paraan ay inililipat sila sa mga estado ng automat).

Sa pangkalahatan, ang pag-alis ng mga patay na estado ay gagawing NFA ang isang DFA, dahil sa isang DFA ang lahat ng mga transition ay dapat tukuyin. Gayunpaman, sa Dragon Book, ang naturang paglihis mula sa pormal na kahulugan ay itinuturing pa ring katanggap-tanggap.

Halimbawa

Upang bumuo ng isang DFA na may pinakamababang bilang ng mga estado para sa isang DFA ng sumusunod na form:

  • Paunang hati: (C) ( pangwakas na estado), (A, B, D, E) ( lahat ng iba pang estado).
  • (C)( walang pagbabago), (A, D, E), (B), ( dahil dumadaan kami mula sa A, D, E kasama ang a, c hanggang B at C, ayon sa pagkakabanggit).
  • Wala na tayong magagawa pa.

Hayaang tumutugma ang pangkat (C) sa estado C, pangkat (A, D, E) sa estado A, at pangkat (B) sa estado B. Pagkatapos ay kumuha kami ng DFA na may pinakamababang bilang ng mga estado:

Halimbawa (algorithm para sa pagbuo ng partition)

Isang talahanayan ng paglipat para sa isang tinukoy sa lahat ng dako (idinagdag ang estado Z) DFA na tumutugma sa RV (ab|ε)a*|abb|b*a. Mula sa mga tanong sa pagsusulit noong 2012.

abako 0ako 1
→A*BC0.01 0.12
B*DE0.00 1.01
CFC1.01
D*DZ0.01 0.04
E*DZ0.00 1.03
F*ZZ0.11
ZZZ1.11

Mga Pag-ulit:

  • I 0: ABCDEF(0), CZ(1).
  • I 1: AD(0), BE(1), C(2), F(3), Z(4).
  • I 2: A, B, C, D, E, F, Z.

Resulta: ang makina ay mayroon nang pinakamababang bilang ng mga estado :-)

DFA na nagpapahintulot sa pagkumpleto ng wika

Ang algorithm para sa pagbuo ng isang DFA na tumatanggap ng pandagdag ng wikang L (L̅) ay binubuo ng dalawang hakbang:

  • Pagbuo ng kumpletong DFA
  • Konstruksyon ng nais na automat mula dito

Sa katunayan, walang ganap na DFA. Sa ilalim ng buong DKA ilang naiintindihan ng mga guro ang automat, sa talahanayan ng paglipat kung saan walang mga walang laman na cell. Gayunpaman, ayon sa kahulugan ng DFA - δ: Q × Σ → Q - hindi maaaring magkaroon ng walang laman na mga cell sa anumang kaso. Ang automat "na may mga walang laman na cell", gayunpaman, ay nakakatugon sa kahulugan ng NFA. Sa kurso ng paglutas, hindi karaniwan na makakuha lamang ng ganoong NFA, na kulang lamang sa mga transition bago ang DFA.

Upang mapunan ito, sapat na upang magdagdag ng isang bagong estado X, at "sa halip na" hindi umiiral na mga transition ay nagdaragdag ng mga transition sa bagong estadong ito. Huwag kalimutang magdagdag ng mga transition mula sa X sa X. Madaling makita na kung saan ang orihinal na automat ay hindi tumanggap ng ilang kadena dahil sa kawalan ng isang paglipat, ang bagong automat ay mapupunta sa estado X at mabitin dito. Dahil ang bagong estado ay hindi isang accepting (final) na estado, hindi rin tatanggapin ng bagong automat ang chain na ito.

Ngayon, upang mabuo ang nais na automat, kinakailangan lamang na baguhin ang mga tungkulin ng pagtanggap at hindi pagtanggap na mga estado. Sa madaling salita, F" = Q \ F.

Pagbuo ng LL(k) analyzer

Pagbabago ng gramatika

Hindi lahat ng grammar ay LL(k)-parsable. Ang isang grammar na walang konteksto ay kabilang sa klase ng LL(1) kung wala itong FIRST-FIRST na mga salungatan (ang kaliwang recursion ay isang espesyal na kaso ng naturang salungatan) at FIRST-FOLLOW.

Minsan posibleng ibahin ang anyo ng mga di-LL(1) na gramatika upang maging LL(1) ang mga ito. Ang ilan (mas tiyak, ang mga isinasaalang-alang sa kurso) mga pagbabago ay ibinigay sa ibaba.

Pag-alis ng kaliwang recursion

Ipagpalagay na mayroon kaming isang tuntunin ng form (simula dito sa seksyong ito, malalaking titik - mga simbolo na hindi terminal, maliit na titik - chain ng anumang mga character):

  • A→A a| A b| … | A k | m | n | … | z

Hindi ito pumapayag sa hindi malabo na pagsusuri, kaya dapat itong i-convert.

Madaling ipakita na ang panuntunang ito ay katumbas ng sumusunod na pares ng mga panuntunan:

  • A → m b | n b | … | z B
  • B → a b | b b | … | k b | ε

Kaliwang factorization

Ang kakanyahan ng pamamaraang ito ay ang pag-aalis ng kalabuan sa pagpili ng mga patakaran para sa kaliwang karakter. Upang gawin ito, ang isang karaniwang kaliwang prefix ay matatagpuan at kung ano ang maaaring sumunod dito ay kinuha sa isang bagong panuntunan (maliit na titik - chain ng anumang mga character)

Halimbawa
  • A → a c | a df | a dg | b

Pinalitan sa

  • A → a b | b
  • B → c | d f | d g

na nagiging

  • A → a b | b
  • B → c | d Sa
  • C → f | g

Halimbawa ng Grammar Conversion

G= ((S, A, B), (a, b, c), P, S)

  • S→SAbB | a
  • A→ab | aa | ε
  • B → c | ε

Pag-alis ng kaliwang recursion para sa S:

  • S → aS 1
  • S 1 → AbBS 1 | ε

Kaliwang factorization para sa A:

  • A → aA 1 | ε
  • A 1 → b | a

Panghuling gramatika:

  • S → aS 1
  • S 1 → AbBS 1 | ε
  • A → aA 1 | ε
  • A 1 → b | a
  • B → c | ε

Building MUNA at SUNDIN

FIRST(α), kung saan ang α ∈ (N ∪ T)* ay ang set ng mga terminal kung saan maaaring magsimula ang α. Kung α ⇒ ε, pagkatapos ay ε ∈ FIRST(α). Alinsunod dito, ang halaga ng FOLLOW( A) para sa hindi terminal A- maraming mga terminal na maaaring lumitaw kaagad pagkatapos A sa ilang sentimental na anyo. Kung ang A maaaring ang pinaka-rightmost character sa ilang sentential form, kung gayon ang huling $ token ay kabilang din sa FOLLOW( A)

UNANG pagkalkula

Para sa mga terminal
  • Para sa anumang terminal x, xT, UNA( x) = {x}
Para sa mga hindi terminal
  • Kung ang X ay isang non-terminal, pagkatapos ay inilalagay namin ang FIRST( X) = {∅}
  • Kung may tuntunin ang gramatika X→ ε, pagkatapos ay idagdag ang ε sa FIRST( X)
  • Para sa bawat hindi terminal X at para sa bawat tuntunin ng hinuha XY 1 …Y k idagdag sa FIRST( X) ang UNANG hanay ng lahat ng mga simbolo sa kanang bahagi ng panuntunan hanggang sa una kung saan hindi nagmula ang ε, kasama ang
Para sa mga kadena
  • Para sa string ng character X 1 …X k FIRST ay ang unyon ng UNANG mga character na kasama sa string hanggang sa una, na mayroong ε ∉ FIRST, kasama ito.
Halimbawa
  • S → aS 1
  • S 1 → AbBS 1 | ε
  • A → aA 1 | ε
  • A 1 → b | a
  • B → c | ε

UNANG hindi terminal sa pagkakasunud-sunod ng paglutas ng dependency:

  • UNANG(S) = (a)
  • UNANG(A) = (a, ε)
  • UNANG(A 1) = (b, a)
  • UNANG(B) = (c, ε)
  • UNANG(S 1) = (a, b, ε)

UNANG para sa mga panuntunan sa hinuha:

  • UNANG(aS 1) = (a)
  • UNANG(AbBS 1) = (a, b)
  • UNANG(ε) = (ε)
  • UNANG(aA 1) = (a)
  • UNANG(a) = (a)
  • UNANG(b) = (b)
  • UNANG(c) = (c)

SUNDIN ang pagkalkula

Pag-compute ng FOLLOW function para sa character X:

  • Hayaan ang SUNOD(X) = (∅)
  • Kung ang X ay isang grammar axiom, pagkatapos ay idagdag ang marker na $ sa SUNDIN
  • Para sa lahat ng panuntunan ng form A → αXβ idagdag ang FIRST(β)\(ε) sa FOLLOW(X) (X ay maaaring sundan ng mga character na nagsisimula sa β)
  • Para sa lahat ng panuntunan ng form A → αX at A → αXβ, ε ∈ FIRST(β), idagdag ang FOLLOW(A) sa FOLLOW(X) (iyon ay, X ay maaaring sundan ng lahat ng character na maaaring sumunod sa A, kung nasa ang inference rule, ang X ay maaaring nasa dulong kanan)
  • Ulitin ang nakaraang dalawang talata hangga't posible na magdagdag ng mga character sa set
Halimbawa
  • S → aS 1
  • S 1 → AbBS 1 | ε
  • A → aA 1 | ε
  • A 1 → b | a
  • B → c | ε

Resulta:

  • SUNDIN (S) = ($)
  • SUNDIN(S 1) = ($) (S 1 ay ang pinakakanang karakter sa panuntunan S → aS 1)
  • SUNDIN(A) = (b) (A sa panuntunan S 1 → AbBS 1 ay sinusundan ng b)
  • FOLLOW(A 1) = (b) (A 1 ay ang pinaka-kanang character sa rule A → aA 1 , kaya idinaragdag ang FOLLOW(A) sa FOLLOW(A 1))
  • SUNDIN(B) = (a, b, $) (idagdag ang UNANG(S 1)\(ε) (sumusunod mula sa panuntunan S 1 → AbBS 1), SUNDIN(S 1) (dahil mayroong S 1 → ε))

Pag-compile ng table

mesa M para sa isang non-terminal-terminal na pares (sa cell M[A, a]) ay tumutukoy sa panuntunan kung saan dapat bawasan ang input na salita. Ang talahanayan ay pinupunan bilang mga sumusunod: para sa bawat panuntunan ng inference ng isang ibinigay na grammar A → α (kung saan ang α ay nauunawaan bilang isang chain sa kanang bahagi ng panuntunan), ang mga sumusunod na aksyon ay isinasagawa:

  1. Para sa bawat terminal a∈ FIRST(α) magdagdag ng panuntunan Aα sa M[A, a]
  2. Kung ε ∈ FIRST(α), para sa bawat isa b∈ SUNDIN( A) idagdag Aα sa M[A, b]
  3. ε ∈ FIRST(α) at ​​$ ∈ FOLLOW( A), idagdag Aα sa M[A, $]
  4. Ang lahat ng mga walang laman na cell ay isang error sa input na salita

Halimbawa

Bumuo ng talahanayan para sa gramatika

  • S → aS 1
  • S 1 → AbBS 1 | ε
  • A → aA 1 | ε
  • A 1 → b | a
  • B → c | ε

Resulta:

abc $
S S → aS 1 (Unang tuntunin, hinuha S → aS 1 , a ∈ UNANG(aS 1)) pagkakamali (Ikaapat na panuntunan) pagkakamali (Ikaapat na panuntunan) pagkakamali (Ikaapat na panuntunan)
S1 S 1 → AbBS 1 (Unang panuntunan, output S 1 → AbBS 1 , a ∈ FIRST(AbBS 1)) S 1 → AbBS 1 (Unang panuntunan, output S 1 → AbBS 1 , b ∈ FIRST(AbBS 1)) pagkakamali (Ikaapat na panuntunan) S 1 → ε (Ikatlong tuntunin, hinuha S 1 → ε, ε ∈ UNA(ε), $ ∈ SUNDIN(S 1))
A A → aA 1 (Unang tuntunin, output A → aA 1 , a ∈ FIRST(aA 1)) A→ε (Ikalawang tuntunin, output A 1 → ε, b ∈ SUNDIN(A 1)) pagkakamali (Ikaapat na panuntunan) pagkakamali (Ikaapat na panuntunan)
A 1 A 1 → a (Unang tuntunin, output A 1 → a, a ∈ FIRST(a)) A 1 → b (Unang panuntunan, output A 1 → b, b ∈ UNANG(b)) pagkakamali (Ikaapat na panuntunan) pagkakamali (Ikaapat na panuntunan)
B B→ε B→ε (Ikalawang tuntunin, hinuha B → ε, a ∈ SUNDIN(B)) B → c (Unang panuntunan, output B → c, c ∈ FIRST(c)) B→ε (Ikatlong panuntunan, hinuha B → ε, $ ∈ SUNDIN(B))

Pag-parse ng string

Ang proseso ng pag-parse ng isang string ay medyo simple. Ang kakanyahan nito ay ang mga sumusunod: sa bawat hakbang, binabasa ang tuktok na simbolo v c input chain.

  • Kung ang v- simbolo ng terminal
    • Kung ang v sumasabay sa kasama, tapos pareho silang nawasak, may shift
    • Kung ang v hindi tumutugma sa kasama, pagkatapos ay may senyales na error sa pag-parse
  • Kung ang v- simbolo na hindi terminal, c babalik sa simula ng linya sa halip na v ang kanang bahagi ng panuntunan, na kinuha mula sa cell ng talahanayan, ay ibinalik sa stack M[v, c]

Ang proseso ay nagtatapos kapag ang string at ang stack ay umabot na sa dulong marker (#).

Halimbawa

I-parse natin ang string na "aabbaabcb":

salansanlinyaaksyon
S# a abbaabcb$S → aS 1
a S1#a abbaabcb$shift
S1# a bbaabcb$S 1 → AbBS 1
A bbs 1#a bbaabcb$A → aA 1
a A 1 bBS 1 #a bbaabcb$shift
A 1 bbs 1#b baabcb$A 1 → b
b bbs 1#b baabcb$shift
b B.S. 1#b aabcb$shift
B S1#a abcb$B→ε
S1# a abcb$S 1 → AbBS 1
A bbs 1#a abcb$A → aA 1
A bbs 1#a abcb$A → aA 1
a A 1 bBS 1 #a abcb$shift
A 1 bbs 1#a bcb$A 1 → a
a bbs 1#a bcb$shift
b B.S. 1#b cb$shift
B S1#c b$B → c
c S1#c b$shift
S1# b$ S 1 → AbBS 1
A bbs 1#b$ A→ε
b B.S. 1#b$ shift
B S1#$ B→ε
S1# $ S 1 → ε
# $ handa na

Pagbuo ng LR(k) analyzer

Pag-compute ng k sa LR(k)

Walang algorithm na magpapahintulot, sa pangkalahatang kaso, na kalkulahin ang k para sa isang arbitraryong gramatika. Karaniwang sulit na subukang bumuo ng LR(1) parser. Kung mayroon itong hindi hihigit sa isang operasyon bawat set (Shift, Bawasan, o Tanggapin), kung gayon ang grammar ay LR(0). Kung, gayunpaman, ang isang salungatan at banggaan ay naganap sa pagbuo ng isang LR(1) parser, kung gayon ang grammar na ito ay hindi LR(1) at ito ay sulit na subukang bumuo ng LR(2). Kung nabigo itong itayo, pagkatapos ay LR(3) at iba pa.

Pagkumpleto ng gramatika

Magdagdag tayo ng bagong panuntunan S" → S, at gawin ang S" na axiom ng grammar. Ang karagdagang panuntunang ito ay kinakailangan upang matukoy kung kailan magwawakas ang analyzer at pinapayagan ang input chain. Ang pagpasok ay nagaganap kung at kung posible lamang na magsagawa ng convolution ayon sa panuntunan S → S".

Pagbuo ng isang kanonikal na sistema ng mga hanay ng mga tinatanggap na LR(1)-mga sitwasyon

Sa simula, mayroong isang set I 0 na may pagsasaayos ng analyzer S" → .S, $. Pagkatapos, ang pagsasara ng operasyon ay inilapat sa pagsasaayos na ito hanggang, bilang resulta ng aplikasyon nito, walang mga bagong pagsasaayos na idinagdag. Susunod , ang mga transition sa mga bagong set ay ginagawa sa pamamagitan ng paglilipat ng punto ng isang character pakanan (ang mga paglukso ay ginawa ng character na pagkatapos ng tuldok bago ang pagtalon at bago ito pagkatapos ng pagtalon), at ang mga pagsasaayos na nakuha mula sa mga umiiral na. sa paraang ito ay idinaragdag sa mga set na ito. Ang pagsasara ng operasyon ay inilalapat din sa kanila, at ang buong proseso ay paulit-ulit hanggang sa wala nang mga bagong hanay na lilitaw.

Halimbawa

Bumuo ng isang kanonikal na sistema ng mga hanay ng mga tinatanggap na LR(1)-mga sitwasyon para sa tinukoy na grammar:

  • S" → S
  • S → ABA
  • A → Aa | ε
  • B → cBc | d

Desisyon:

  • Bumuo kami ng pagsasara para sa configuration S" → .S, $:
    • S → .ABA,$
  • Para sa mga resultang configuration (S → .ABA, $) bumuo din kami ng pagsasara:
    • A → .Aa, c
    • A → .Aa, d
    • A → .,c
    • A → ., d
  • Para sa mga resultang pagsasaayos (A → .Aa, c; A → .Aa, d) gumagawa din kami ng pagsasara:
    • A → .Aa, a
    • A → ., a
  • Wala nang mga pagsasaayos sa I 0 na estado ang maaaring itayo - ang pagsasara ay binuo
  • Mula sa I 0, maaari kang gumawa ng mga paglipat sa kahabaan ng S at A at makakuha ng isang hanay ng mga pagsasaayos I 1 at I 2, na binubuo ng mga sumusunod na elemento:
    • I 1 = (S" → S., $)
    • I 2 = (S → A.BA, $; A → A.a, c; A → A.a, d; A → A.a, a)
  • I 1 ay hindi nangangailangan ng pagsasara
  • Buuin natin ang pagsasara I 2:
    • B → .cBc, a
    • B → .cBc, $
    • B → .d, a
    • B → .d, $
  • Ang lahat ng iba pang mga set ay itinayo nang katulad.

Pagbuo ng parser table

Ang huling hakbang sa pagbuo ng LR(1) parser ay pagbuo ng mga talahanayan aksyon at pumunta sa. mesa aksyon binuo para sa mga character ng input string, ibig sabihin, para sa mga terminal at end-of-line marker $, table pumunta sa ay binuo para sa mga simbolo ng grammar, ibig sabihin, para sa mga terminal at hindi terminal.

Pagbuo ng Goto Table

Ipinapakita ng talahanayan ng Goto kung aling estado ang pupuntahan kapag nakatagpo ang susunod na simbolo ng grammar. Samakatuwid, kung sa canonical system ng mga hanay mayroong isang paglipat mula sa ako i sa Ij sa pamamagitan ng simbolo A, pagkatapos ay sa Goto( ako i, A) inilalagay namin ang estado ako j. Matapos punan ang talahanayan, ipinapalagay namin na sa lahat ng walang laman na mga cell Goto( ako i, A) = Error

Pagbuo ng talahanayan ng Mga Pagkilos

  • Kung mayroong paglipat sa terminal a mula sa estado I i patungo sa estado I j , pagkatapos ay Aksyon(I i , a) = Shift(I j)
  • Kung A ≠ S" at mayroong configuration A → α., a, pagkatapos Action(I i , a) = Reduce(A → α)
  • Para sa isang estado I i na may configuration S" → S., $, Action(I i , $) = Tanggapin
  • Para sa lahat ng walang laman na mga cell Action(I i , a) = Error

Halimbawa

Bumuo ng Action at Goto na mga talahanayan para sa grammar

  • S" → S
  • S → ABA
  • A → Aa | ε
  • B → cBc | d

Desisyon:

aksyonpumunta sa
acd$ SS"ABacd
ako 0Bawasan(A → ε)Bawasan(A → ε)Bawasan(A → ε) ako 1 ako 2
ako 1 tanggapin
ako 2Shift(I 6)Shift(I 4)Shift(I 5) ako 3ako 6ako 4ako 5
ako 3Bawasan(A → ε) Bawasan(A → ε) ako 13
ako 4 Shift(I 8)Shift(I 9) ako 7 ako 8ako 9
ako 5Bawasan(B → d) Bawasan(B → d)
ako 6Bawasan(A → Aa)Bawasan(A → Aa)Bawasan(A → Aa)
ako 7 Shift(I 10) ako 10
ako 8 Shift(I 8)Shift(I 9) ako 11 ako 8ako 9
ako 9 Bawasan(B → d)
ako 10Bawasan(B → cBc) Bawasan(B → cBc)
ako 11 Shift(I 12) ako 12
ako 12 Bawasan(B → cBc)
ako 13Shift(I 14) Bawasan(S → ABA) ako 14
ako 14Bawasan(A → Aa) Bawasan(A → Aa)

Pag-parse ng chain

Sa bawat hakbang, binabasa ang nangungunang karakter v mula sa stack ng analyzer at kunin ang huling character c input chain.

Kung nasa talahanayan ng mga aksyon sa intersection v at c matatagpuan:

  • shift( ako k), pagkatapos ay ilagay sa stack kasama at pagkatapos ako k. Kung saan c tinanggal mula sa string.
  • Bawasan( Au), pagkatapos ay ang lahat ng terminal at non-terminal na simbolo na bumubuo sa chain ay iki-clear mula sa tuktok ng stack u, pagkatapos ay tumingin ang estado ako m natitira sa tuktok. Ayon sa transition table sa intersection ako m at A hanapin ang susunod na estado ako s. Pagkatapos ay itinulak ang A sa stack, at pagkatapos ako s. Ang linya ay nananatiling hindi nagbabago.
  • Tanggapin, pagkatapos ay kumpleto na ang pag-parse
  • ang kawalan ng laman ay isang pagkakamali

Halimbawa

Buuin natin ang pag-parse ng string aaaccdcc:

salansanLinyaAksyon
ako 0 a aaccdcc$Bawasan(A → ε), pumunta sa I 2
ako 0 A ako 2 a aaccdcc$Shift(I 6)
I 0 A I 2 a ako 6 a accdcc$Bawasan(A → Aa), pumunta sa I 2
ako 0 A ako 2 a accdcc$Shift(I 6)
I 0 A I 2 a ako 6 a ccdcc$Bawasan(A → Aa), pumunta sa I 2
ako 0 A ako 2 a ccdcc$Shift(I 6)
I 0 A I 2 a ako 6 c cdcc$Bawasan(A → Aa), pumunta sa I 2
ako 0 A ako 2 c cdcc$Shift(I 4)
I 0 A I 2 s ako 4 c dcc$Shift(I 8)
I 0 A I 2 c I 4 c ako 8 d cc$Shift(I 9)
I 0 A I 2 c I 4 c I 8 d ako 9 c c$Bawasan(B → d), pumunta sa I 11
I 0 A I 2 c I 4 c I 8 B ako 11 c c$Shift(I 12)
I 0 A I 2 c I 4 c I 8 B I 11 c ako 12 c$ Bawasan(B → cBc), pumunta sa I 7
I 0 A I 2 c I 4 B ako 7 c$ Shift(I 10)
I 0 A I 2 c I 4 B I 7 c ako 10 $ Bawasan(B → cBc), pumunta sa I 3
I 0 A I 2 B ako 3 $ Bawasan(A → ε), pumunta sa I 13
I 0 A I 2 B I 3 A ako 13 $ Bawasan(S → ABA), pumunta sa I 1
ako 0 S ako 1 $ tanggapin

Pagsasalin ng mga arithmetic expression (Seti-Ullman algorithm)

Tandaan. Ang code ay nabuo ng doggy style na mala- Motorola, i.e.

Op Arg1, Arg2

ibig sabihin

Arg2 = Arg1 Op Arg2

Paggawa ng puno

Ang puno ay itinayo gaya ng dati para sa isang aritmetika na expression: Sa ugat, ang operasyon na may pinakamababang priyoridad, na sinusundan ng mga pagpapatakbo na may bahagyang mas mataas na priyoridad, at iba pa. Ang mga panaklong ay may pinakamataas na precedence. Kung mayroong ilang mga operasyon na may parehong priyoridad - a op b op c, pagkatapos ay ang puno ay binuo bilang para sa expression (a op b) op c.

Halimbawa

Bumuo ng isang puno para sa expression na a + b / (d + a − b × c / d − e) + c × d

Desisyon: Sinusulat namin ang expression sa form

((a) + ((b) / ((((d) + (a)) − ((b) × (c)) / (d)) − (e)))) + ((c) × ( d))

Pagkatapos sa ugat ng bawat subtree ay magkakaroon ng operasyon, at ang mga expression sa mga bracket sa kaliwa at kanan nito ay ang mga subtree nito. Halimbawa, para sa subexpression ((b) × (c)) / (d), ang operasyong “/” ay nasa ugat ng kaukulang subtree, at ang mga subexpression ((b) × (c)) at (d ) ang magiging mga subtree nito.

Layout ng puno (pagkalkula ng bilang ng mga rehistro)

  • Kung ang vertex ay ang kaliwang dahon (iyon ay, isang variable), pagkatapos ay markahan namin ito ng zero.
  • Kung ang tuktok ay ang tamang dahon, pagkatapos ay markahan namin ito ng isa
  • Kung markahan namin ang parehong mga subtree nito para sa ilang vertex, markahan namin ito bilang mga sumusunod:
    • Kung ang kaliwa at kanang subtree ay may label na magkakaibang numero, piliin ang pinakamalaki sa kanila
    • Kung ang kaliwa at kanang mga subtree ay may label na may parehong mga numero, ang subtree na ito ay bibigyan ng isang numero na mas malaki kaysa sa isa na may label sa mga subtree.
mga marka ng dahonLayout ng puno na may magkaparehong mga subtreeAng kaliwang subtree ay may label na may malaking numeroAng kanang subtree ay may label na may malaking numero
tama - pareho parang ninuno.
  • Kung ang label umalis inapo higit pa mga label tama, pagkatapos tama bata ay itinalagang rehistro isa pa kaysa sa ninuno, at umalis - pareho parang ninuno.
  • Ang code ay nabuo sa pamamagitan ng pagtawid sa puno mula sa ibaba hanggang sa itaas tulad ng sumusunod:

    1. Walang nabuong code para sa vertex na may label na 0

    2. Kung ang itaas ay sheet X na may label na 1 at irehistro ang R i, pagkatapos ay ang code

    MOVE X, Ri

    3. Kung ang tuktok ay panloob na may register R i at ang kaliwang anak nito ay sheet X na may label na 0, pagkatapos ay tumutugma ito sa code

    <Код правого поддерева>OpX, Ri

    4. Kung ang mga subtrees ng isang vertex na may register R i- hindi dahon at ang label ng kanang vertex ay mas malaki kaysa o katumbas ng label ng kaliwa (na may rehistrong Rj, j = i + 1), pagkatapos ay tumutugma ang code sa vertex

    <Код tama subtree><Код umalis mga subtree > Op Rj, Ri

    5. Kung ang mga subtrees ng vertex na may register R i- hindi mga dahon at ang label ng kanang vertex (kung saan ang rehistro ng Rj, j = i + 1) ay mas mababa sa label ng kaliwa, pagkatapos ay tumutugma ang code sa vertex

    Ang pamamahagi ng rehistro ay ipinapakita sa graph sa kanan. Binuo na code:

    ILIPAT ang d, R0 ;R0 = d ILIPAT c, R1 ;R1 = c MUL b, R1 ;R1 = (b × c) DIV R1, R0 ;R0 = (b × c) / d IGALAW a, R1 ;R1 = a ADD d, R1 ;R1 = a + d SUB R1, R0 ;R0 = (a + d) − ((b × c) / d) MOVE e, R1 ;R1 = e SUB R0, R1 ;R1 = ((a + d) − ((b × c) / d)) − e MOVE R1, R0;R0 = ((a + d) − ((b × c) / d)) − e DIV b, R0 ;R0 = b / (((a + d) − ((b × c) / d)) − e) ADD a, R0 ;R0 = a + (b / (((a + d) − ((b × c) / d )) − e)) MOVE d, R1 ;R1 = d MUL c, R1 ;R1 = c × d ADD R0, R1 ;R1 = (a + (b / (((a + d)) − ((b × c) ) / d)) − e))) + (c × d) MOVE R1, R0;R0 = (a + (b / (((a + d)) − ((b × c) / d)) − e) )) + (c × d)

    Pagsasalin ng mga lohikal na expression

    Ipinapakita ng seksyong ito kung paano bumuo ng code para sa tamad na pagsusuri ng mga boolean na expression. Bilang resulta ng algorithm, ang isang piraso ng code ay nakuha, na, gamit ang TST, BNE, BEQ operations, kinakalkula ang isang lohikal na expression sa pamamagitan ng paglipat sa isa sa mga label: TRUELAB o FALSELAB.

    Paggawa ng puno

    Ang puno ng isang lohikal na expression ay sumasalamin sa pagkakasunud-sunod kung saan ito sinusuri ayon sa nangunguna sa mga operasyon, iyon ay, upang suriin ang halaga ng isang tree node (na kung saan ay ang pagpapatakbo ng dalawang operand na mga subtree ng node), kailangan nating unang kalkulahin ang mga halaga ng mga subtree nito.

    Priyoridad ng Operasyon: Ang NOT operator ang may pinakamataas na precedence, na sinusundan ng AND at pagkatapos ay OR. Kung ang iba pang mga lohikal na operasyon ay ginagamit sa expression, kung gayon ang mga ito ay dapat na ipahayag sa pamamagitan ng tatlong ito sa isang tiyak na paraan (kadalasan, walang iba pang mga operasyon at expression ng conversion ay hindi kinakailangan). Ang pagkakaugnay para sa mga operasyon ng parehong priyoridad ay mula kaliwa hanggang kanan, ibig sabihin, ang A at B at C ay itinuturing bilang (A at B) at C

    Halimbawa

    Bumuo ng isang puno para sa lohikal na expression na hindi A o B at C at (B o hindi C).

    Desisyon: tingnan ang diagram sa kanan.

    Para sa bawat tuktok ng puno, 4 na katangian ang kinakalkula:

    • Numero ng node
    • Ang label na dadaanan kung mali ang expression sa node (false label, fl)
    • Ang label na tatahakin kung totoo ang expression sa node (true label, tl)
    • Label-sign (sign) (para sa higit pang mga detalye, tingnan sa ibaba)

    Ang mga vertice ay binibilang sa random na pagkakasunud-sunod, ang tanging kundisyon ay ang pagiging natatangi ng mga numero ng node.

    Ang layout ng puno ay ginagawa tulad ng sumusunod:

    • Tinutukoy ng fl ang bilang ng vertex kung saan ginawa ang transition o falselab kung false ang vertex na ito
    • Ipinapahiwatig ng tl ang bilang ng vertex kung saan ginawa ang transition o truelab kung totoo ang vertex na ito

    Tinutukoy ng sign kung saan maaaring wakasan ang pagsusuri ng kasalukuyang subtree.

    Para sa ugat ng puno, fl=falselab, tl=truelab, sign=false.

    kaya:

    Halimbawa

    Markahan ang puno na binuo para sa lohikal na expression na hindi A o B at C at (B o hindi C).

    Pagbuo ng code

    Mga utos ng makina na ginamit sa nabuong code:

    • TST - pagsuri sa argumento para sa katotohanan at pagtatakda ng bandila kung mali ang argumento
    • BNE - tumalon sa label kung ang bandila ay hindi nakatakda, ibig sabihin, ang kundisyon ay nasuri sa TST totoo
    • BEQ - tumalon sa label kung ang bandila ay nakatakda, ibig sabihin, ang kundisyon ay nasuri sa TST mali

    Ang code ay binuo tulad ng sumusunod:

    • ang puno ay tinatahak mula sa ugat, para sa AT at O, ang kaliwang subtree ay unang tinatahak, pagkatapos ay ang kanan
    • para sa bawat vertex na dumaan, ang numero nito (label) ay naka-print
    • para sa sheet A(number, tl, fl, sign) TST A ay naka-print
      • kung sign == true, naka-print ang BNE tl
      • kung sign == false, ang BEQ fl ay naka-print

    Halimbawa

    Para sa expression sa itaas, ang sumusunod na code ay bubuo:

    1:2:4: TST A BEQ TRUELAB 3:5:7: TST B BEQ FALSELAB 8: TST C BEQ FALSELAB 6:9: TST B BNE TRUELAB 10:11: TST C BNE FALSELAB TRUELAB: FALSELAB:

    Sample na paraan ng pagtutugma

    Ang ideya ng pamamaraan ay para sa parehong seksyon ng programa, ang code ay maaaring mabuo sa iba't ibang paraan, at, bilang isang resulta, ang pag-optimize ay maaaring makamit para sa isa o ibang parameter.

    Pagbubuo ng problema

    Mayroong maraming mga sample, ang bawat isa ay tinukoy ng isang piraso ng intermediate na representasyon kung saan ito naaangkop, ang timbang at ang nabuong code. Mayroong isang intermediate representation tree, na isang fragment ng programa kung saan kinakailangan upang makabuo ng code. Ang layunin ay bumuo ng gayong takip ng intermediate representation tree na may mga sample upang ang kabuuang bigat ng mga sample ay minimal.

    Ang mga pattern ay mga tagubilin sa pagpupulong at ang mga puno ng parse na tumutugma sa kanila. Para sa bawat sample, ang oras ng pagpapatupad nito (sa mga cycle) ay kilala. Sa kanilang tulong, bubuo kami ng pinakamainam (sa mga tuntunin ng oras ng pagpapatupad) na code.

    Mga halimbawang halimbawa

    Pagbuo ng isang intermediate na representasyon

    Una, bumuo kami ng parse tree para sa buong expression.

    Pagbuo ng coverage

    Ngayon para sa bawat vertex (dumaan namin ang mga ito sa pagkakasunud-sunod mula sa mga dahon hanggang sa ugat), bubuo kami ng pinakamainam na code para sa subtree nito. Upang gawin ito, dumaan lang kami sa lahat ng mga sample na naaangkop sa isang naibigay na vertex. Ang oras ng pagpapatupad kapag gumagamit ng isang partikular na pattern ay ang kabuuan ng oras na kinakailangan upang suriin ang mga argumento nito (at alam na natin ang pinakamainam na code para sa pag-compute ng mga ito salamat sa tree traversal order) at ang oras ng pagpapatupad ng pattern mismo. Sa lahat ng mga opsyon na nakuha, pipiliin namin ang pinakamahusay - ito ang magiging pinakamainam na code para sa subtree ng vertex na ito. Sa ugat ng puno, nakukuha namin ang pinakamainam na code para sa buong expression.

    Pagbuo ng code

    Hindi kinakailangang isulat ang code para sa lahat ng vertices - sapat na upang isulat ang minimum na kinakailangang oras at ang sample na kailangan mong gamitin. Ang lahat ng iba pa mula dito ay madaling naibalik.

    Mayroon kaming walang katapusang bilang ng mga rehistro sa mga problemang ito, kaya sa bawat oras na maaari kang gumamit ng bago.

    Konstruksyon ng RV ayon sa DKA

    Konstruksyon ng NFA ayon sa right-linear grammar

    Grammar Casting

    Upang ma-convert ang isang arbitrary na COP-grammar sa pinababang anyo, dapat mong gawin ang mga sumusunod na hakbang:

    • alisin ang lahat ng baog na mga character;
    • alisin ang lahat ng hindi maabot na mga character;

    Pag-alis ng mga walang kwentang character

    pasukan: COP-grammar G = (T, N, P, S).

    Output: Isang COP-grammar G' = (T, N', P', S) na walang mga baog na simbolo, kung saan L(G) = L(G').

    Paraan:

    Recursively build sets N 0 , N 1 , ...

    1. N 0 = ∅, i = 1.
    2. N i = (A | (A → α) ∈ P at α ∈ (N i - 1 ∪ T)*) ∪ N i-1 .
    3. Kung N i ≠ N i - 1, pagkatapos ay i = i + 1 at pumunta sa hakbang 2, kung hindi N’ = N i ; Ang P' ay binubuo ng mga panuntunan ng set P na naglalaman lamang ng mga simbolo mula sa N' ∪ T; G' = (T, N', P', S).

    Kahulugan: ang isang simbolong x ∈ (T ∪ N) ay sinasabing hindi maabot sa isang gramatika G = (T, N, P, S) kung ito ay hindi lilitaw sa anumang pangungusap na anyo ng gramatika na ito.

    Halimbawa

    Alisin ang mga walang kwentang character mula sa grammar G((A, B, C, D, E, F, S), (a, b, c, d, e, f, g), P, S)

    • S → AcDe | CaDbCe | Saca | aCb | dFg
    • A → SeAd | cSA
    • B → CaBd | aDBc | BSC | bfg
    • C→Ebd | Seb | aAc | cfF
    • D→fCE | ac | dEdAS | ε
    • E→ESacD | aec | eFF

    Desisyon

    • N 0 = ∅
    • N 1 = (B (B → bfg) , D (D → ac) , E (E → aec) )
    • N 2 = (B, D, E, C (C → Ebd) )
    • N 3 = (B, D, E, C, S (S → aCb) )
    • N 4 \u003d (B, D, E, C, S) \u003d N 3

    G"((B, C, D, E, S), (a, b, c, d, e, f, g), P", S)

    • S → CaDbCe | Saca | aCb
    • B → CaBd | aDBc | BSC | bfg
    • C→Ebd | Si Seb
    • D→fCE | ac | ε
    • E→ESacD | aec

    Pag-alis ng mga hindi maabot na character

    pasukan: COP grammar G = (T, N, P, S)

    Output: Isang COP-grammar G' = (T', N', P', S) na naglalaman ng walang hindi maabot na mga simbolo, kung saan L(G) = L(G').

    Paraan:

    1. V 0 = (S); ako = 1.
    2. V i = (x | x ∈ (T ∪ N), (A → αxβ) ∈ P at A ∈ V i - 1 ) ∪ V i-1 .
    3. Kung V i ≠ V i - 1 , pagkatapos ay i = i + 1 at pumunta sa hakbang 2, kung hindi N’ = V i ∩ N; T' = V i ∩ T; Ang P' ay binubuo ng mga tuntunin ng set P na naglalaman lamang ng mga simbolo mula sa V i ; G' = (T', N', P', S).

    Kahulugan: Ang isang COP-grammar G ay sinasabing mababawasan kung hindi ito naglalaman ng mga hindi matamo at sterile na mga simbolo.

    Halimbawa

    Alisin ang mga hindi maabot na character mula sa grammar G"((B, C, D, E, S), (a, b, c, d, e, f, g), P", S)

    • S → CaDbCe | Saca | aCb
    • B → CaBd | aDBc | BSC | bfg
    • C→Ebd | Si Seb
    • D→fCE | ac | ε
    • E→ESacD | aec

    Desisyon

    • V 0 = (S)
    • V 1 = (S, C (S → CaDbCe) , D (S → CaDbCe) , a (S → CaDbCe) , b (S → CaDbCe) , e (S → CaDbCe) )
    • V 2 = (S, C, D, a, b, e, E (C → Ebd) , d (C → Ebd) , f (D → fCE) )
    • V 3 = (S, C, D, E, a, b, d, e, f, c (E → ESacD) )
    • V 4 \u003d (S, C, D, E, a, b, d, e, f, c) \u003d V 3

    G""((C, D, E, S), (a, b, c, d, e, f), P"", S)

    • S → CaDbCe | Saca | aCb
    • C→Ebd | Si Seb
    • D→fCE | ac | ε
    • E→ESacD | aec
    sa pamamagitan ng kabuuang bilang ng mga character ng alpabeto ng mga simbolo at mga palatandaan ng mga operasyon at mga bracket sa record r .

    Batayan. Automata para sa mga expression ng haba 1: at ipinapakita sa sumusunod na figure.


    kanin. 5.1.

    Tandaan na mayroon ang bawat isa sa tatlong automata na ito hanay ng mga huling estado ay binubuo ng isang estado.

    hakbang ng induction. Ipagpalagay natin ngayon na para sa bawat isa regular na pagpapahayag haba<= k построен соответствующий НКА, причем у него единственное заключительное состояние. Рассмотрим произвольное regular na pagpapahayag r ng haba k+1 . Depende sa huling operasyon, maaari itong magkaroon ng isa sa tatlong anyo: (r 1 + r 2), (r 1 r 2) o (r 1) * . Hayaan at maging mga NFA na kinikilala ang mga wika L r1 at L r2 , ayon sa pagkakabanggit. Nang walang pagkawala ng pangkalahatan, ipagpalagay namin na mayroon silang iba't ibang mga estado: .

    Pagkatapos ang NFA , na ang diagram ay ipinapakita sa Fig. 5.2, kinikilala ang wika.


    kanin. 5.2.

    Ang makinang ito ay may hanay ng mga estado, kung saan ang q 0 ay isang bagong paunang estado, ang q f ay isang bagong (natatanging!) pangwakas na estado, at ang programa ay kinabibilangan ng mga programang automat M 1 at M 2 at apat na bagong transition command: . Malinaw, ang wikang kinikilala ng NFA M ay kinabibilangan ng lahat ng mga salita mula sa L ( M 1 ) at mula sa L ( M 2 ) . Sa kabilang banda, ang bawat salita ay tumatagal ng q 0 hanggang q f , at pagkatapos ng unang hakbang ang landas na dinadala nito ay dumadaan sa q 0 1 o q 0 2 . Dahil ang mga estado M 1 at M 2 ay hindi nagsalubong, kung gayon sa unang kaso ang landas na ito ay maaaring makarating sa q f lamang sa pamamagitan ng isang -transition mula sa q f 1 at pagkatapos . Katulad nito, sa pangalawang kaso.

    Para sa expression, ang diagram ng NFA na kumikilala sa wikang L r ay ipinapakita sa sumusunod na figure.


    kanin. 5.3.

    Ang makinang ito ay may hanay ng mga estado , paunang estado q 0 = q 0 1, panghuling estado q f =q f 2, at kasama sa programa ang mga programang automat M 1 at M 2 at isang bagong utos - paglipat mula sa huling estado M 1 hanggang sa paunang estado M 2, i.e. . Dito rin malinaw na ang anumang landas mula q 0 = q 0 1 hanggang q f = q f 2 ay dumadaan sa isang -transition mula q f 1 hanggang q 0 2 . Samakatuwid, ang anumang salitang pinahihintulutan ng M ay isang pagsasama-sama ng ilang salita mula sa L M1 ) na may ilang salita mula sa L M2 ) , at anumang pagsasama-sama ng mga naturang salita ay pinapayagan. Samakatuwid, kinikilala ng NFA M ang wika .

    Hayaan ang r = r 1 * . Ang diagram ng NFA na kumikilala sa wikang L r =L r1* = L M1 * ay ipinapakita sa fig. 5.3.


    kanin. 5.3.

    Ang makinang ito ay may hanay ng mga estado, kung saan ang q 0 ay isang bagong panimulang estado, ang q f ay isang bagong (natatanging!) pangwakas na estado, at kasama sa programa ang automaton program M 1 at apat na bagong transition command: . Malinaw, . Para sa isang walang laman na salita w, ayon sa kahulugan ng pag-ulit para sa ilang k >= 1 ang salitang w ay maaaring hatiin sa k subwords: w=w 1 w 2 ... w k at iyon na. Para sa bawat i= 1,... ,k ang salitang w i ay nagmamapa ng q 0 1 hanggang q f 1 . Pagkatapos para sa salitang w sa diagram M mayroong isang landas

    Kaya naman, . Sa kabaligtaran, kung ang ilang salita ay nagsasalin ng q 0 sa q f , kung gayon ito ay umiiral o ito ay dinadala ng landas q 0 1 sa pamamagitan ng -transition, kalaunan mula sa q f 1 ng -transition ay nagtatapos sa q f . Samakatuwid, tulad ng isang salita.

    Mula sa Theorems 4.2 at 5.1 direkta naming nakuha

    Corollary 5.1. Para sa lahat regular na pagpapahayag ang isa ay mahusay na makakagawa ng isang deterministikong finite automat na kumikilala sa wikang kinakatawan ng expression na ito.

    Ang pahayag na ito ay isang halimbawa synthesis theorems: ayon sa paglalarawan ng gawain (wika bilang regular na pagpapahayag) isang programa (DFA) na nagsasagawa nito ay epektibong binuo. Totoo rin ang kabaligtaran - teorama ng pagsusuri.

    Teorama 5.2. Para sa bawat deterministic (o non-deterministic) na may hangganang automat, maaaring bumuo ang isa regular na pagpapahayag, na kumakatawan sa wikang kinikilala ng automat na ito.

    Ang patunay ng theorem na ito ay medyo teknikal at lampas sa saklaw ng aming kurso.

    Kaya, maaari nating tapusin na ang klase ng mga limitadong wika ng automata ay nag-tutugma sa klase mga regular na wika. Sa mga sumusunod, tatawagin lang natin ito klase ng mga wikang automata.

    Ang automaton M r na itinayo sa patunay ng Theorem 5.1

    Pangunahing Kahulugan Ang mga regular na expression sa alpabeto Σ at ang mga regular na set na tinutukoy nila ay recursively tinukoy bilang mga sumusunod: 1) isang regular na expression na nagsasaad ng isang regular na set; 2) e ay isang regular na expression na nagsasaad ng isang regular na set (e); 3) kung ang isang Σ, kung gayon ang a ay isang regular na expression na nagsasaad ng regular na set (a); 4) kung ang p at q ay mga regular na expression na nagsasaad ng mga regular na set na P at Q, kung gayon ang a) (p+q) ay isang regular na expression na nagsasaad ng P Q; b) ang pq ay isang regular na expression na nagsasaad ng PQ; c) ang p* ay isang regular na expression na nagsasaad ng P*; 5) walang iba ang isang regular na expression.

    Pangunahing kahulugan Pag-priyoridad: * (iteration) – pinakamataas na priyoridad; pagsasama-sama; + (unyon). Kaya 0 + 10* = (0 + (1 (0*))). Mga halimbawa: 1. 01 ay nangangahulugang (01); 2. 0* - (0*); 3. (0+1)* - (0, 1)*; 4. (0+1)* 011 - nangangahulugang ang hanay ng lahat ng mga string na binubuo ng 0 at 1 at nagtatapos sa string na 011; 5. Ang ibig sabihin ng (a+b) (a+b+0+1)* ay ang set ng lahat ng string (0, 1, a, b)* na nagsisimula sa a o b.

    Ang mga pangunahing kahulugan ng Lemma: 1) α + β = β + α 2) * = e 3) α + (β + γ) = (α + β) + γ 4) α(βγ) = (αβ)γ 5 ) α( β + γ) = αβ + αγ 6) (α + β)γ = αγ + βγ 7) αe = eα = α 8) α = 9) α+α* = α* 10) (α*)* = α* 11) α+α = α 12) α+ = α

    Ang komunikasyon ng RT at RM RM ay mga wikang nabuo ng RT. Halimbawa: x = a+b, y = c+d, x X = (a, b), y Y = (c, d), x + y X Y = (a, b, c, d). Pagsasama-sama: xy XY = (ac, ad, bc, bd). k(u+o)t (k)(u, o)(t) = (balyena, pusa) o ng Lemmas No. 5 at No. 6 k(u+o)m = whale + pusa (balyena, pusa) . Pag-ulit: x = a, x* X* = (e, a, aaa, …), ibig sabihin, x* = e + xxx + …

    Relasyon ng RT at RM Pag-ulit ng pagkakadugtong at unyon: (xy)* = e + xyxyxy + ... (x + y)* = e + (x + y)(x + y) + ... = = e + xx + xy + yx + yy + xxx + … Halimbawa: 0 + 1(0+1)* (0) ((1) (0, 1)*) = (0, 1, 10, 11, 100, 101, 110, 111…). Ang unyon ay commutative: x + y = y + x Ang concatenation ay hindi: xy ≠ yx

    Relasyon sa pagitan ng RT at PM na Priyoridad na mga halimbawa: x + yz (x, yz), (x + y)z (xz, yz), x + y* (e, x, y, yyy, yyyy, …), (x + y)* (e, x, y, xx, xy, yx, yy, xxx, …), (xy)* (e, xyxy, …), xy* (x, xyy, xyyy, …). Mga bagong lemma: a* + e = a*; (a + e)* = a*; a*a* = a*; e* = e; atbp.

    Mga regular na sistema ng equation Equation na may regular na coefficient X = a. Ang X + b ay may solusyon (pinakamaliit na fixed point) a*b: aa*b + b = (aa* + e)b = a*b System of equation na may regular na coefficient: X 1 = α 10 + α 11 X 1 + α 12 X 2 + … + α 1 n. Xn X 2 \u003d α 20 + α 21 X 1 + α 22 X 2 + ... + α 2 n. Xn ………………………. . Xn = αn 0 + αn 1 X 1 + αn 2 X 2 + … + αnn. Xn Hindi Alam – Δ = (X 1, X 2, …, Xn).

    Mga regular na sistema ng mga equation Algoritmo ng solusyon (Paraang Gauss): Hakbang 1. Itakda ang i = 1. Hakbang 2. Kung i = n, pumunta sa hakbang 4. Kung hindi, isulat ang mga equation para sa Xi sa anyong Xi = αXi + β (β = β 0 + βi +1 Xi+1 + … + βn.Xn). Pagkatapos, sa kanang bahagi para sa mga equation na Xi+1, …, Xn, pinapalitan namin ang Xi ng regular na expression na α*β. Hakbang 3. Dagdagan ang i ng 1 at bumalik sa hakbang 2. Hakbang 4. Isulat ang equation para sa Xn bilang Xn = αXn + β. Pumunta sa hakbang 5 (na may i = n). Hakbang 5. Ang equation para sa Xi ay Xi = αXi + β. Isulat sa output Xi = α*β, sa mga equation para sa Xi– 1, …, X 1 na pinapalitan ang α*β sa halip na Xi. Hakbang 6. Kung i = 1, huminto, kung hindi ay bawasan ang i ng 1 at bumalik sa hakbang 5.

    Pagbabago ng DFA sa RW Para sa DFA M = (Q, Σ, δ, q 0, F) bumubuo kami ng isang sistema na may mga regular na coefficient kung saan Δ = Q: 1. itinakda namin ang αij: = ; 2. kung δ(Xi, a) = Xj, a Σ, pagkatapos ay αij: = αij + a; 3. kung Xi F o δ(Xi,) = HALT, pagkatapos ay αi 0: = e. Pagkatapos malutas ang nais na RV ay magiging X 1 = q 0.

    Pag-convert ng DFA sa RW Halimbawa: para sa isang fixed-point na numero, makuha natin ang system q 0 = + q 0 + sq 1 + pq 2 + dq 3 + q 4 q 1 = + q 0 + q 1 + pq 2 + dq 3 + q 4 q 2 = + q 0 + q 1 + q 2 + q 3 + dq 4 q 3 = e + q 0 + q 1 + q 2 + dq 3 + pq 4 = e + q 0 + q 1 + q 2 + q 3 + dq 4 Dito: s ang tanda ng numero, s = "+" + "-"; p – decimal point, p = "."; d - mga numero, d = "0" + "1" + ... + "9".

    Solusyon sa conversion ng DFA sa RW: q 0 = *(sq 1 + pq 2 + dq 3 + q 4 +) = sq 1 + pq 2 + dq 3 q 1 = + q 0 + q 1 + pq 2 + dq 3 + q 4 = pq 2 + dq 3, q ​​​​2 = + q 0 + q 1 + q 2 + q 3 + dq 4 = dq 4, q 3 = e + q 0 + q 1 + q 2 + dq 3 + pq 4 = dq 3 + pq 4 + e, q 4 = e + q 0 + q 1 + q 2 + q 3 + dq 4 = dq 4 + e. Mula sa ikatlong equation: q 3 \u003d dq 3 + pq 4 + e \u003d d * (pq 4 + e). Mula sa ikaapat na equation: q 4 = dq 4 + e = d*.

    I-convert ang DFA sa RW Reverse: q 3 = d*(pq 4 + e) ​​​​= d*(pd* + e), q 2 = dq 4 = dd*, q 1 = pq 2 + dq 3 = pdd* + dd *(pd* + e), q 0 = sq 1 + pq 2 + dq 3 = s(pdd* + dd*(pd* + e)) + pdd* + dd*(pd* + e). Kaya, ang DFA na ito ay tumutugma sa RE s(pdd* + dd*(pd* + e)) + pdd* + dd*(pd* + e). Upang pasimplehin: s(pdd* + dd*(pd* + e)) + pdd* + dd*(pd* + e) ​​​​= = spdd* + sdd*(pd* + e) ​​​​+ pdd* + dd*(pd* + e) ​​= (s + e)(pdd* + dd*(pd* + e)) Para sa mas maikling notasyon, maaari mong gamitin ang positive iteration aa* = a*a = a+: (s + e )(pdd* + dd* (pd* + e)) = (s + e)(pd+ + d+pd* + d+)

    Transpormasyon ng DFA sa RT Pagma-map sa graph ng transisyon ng DFA function sa mga pangunahing operasyon ng regular na expression: q 0 a b a q 1 q 2 q 1 q 0 a+b a b ab q 2 a*

    Pag-convert ng DFA sa RT Mas kumplikadong kumbinasyon ng mga operasyon: q 0 a q 1 b b b q 0 a q 2 q 1 (a + e)b c b q 0 q 2 ab(cab)* q 0 (a + b)* q 0 a q 1 aa* = a+ q 0 a q 1 a b a a a (ab)+ q 2 b q 1 c e + (a + b)c*

    Conversion ng DFA sa RW Para sa RW (s + e)(pd+ + d+(pd* + e)): q 0 p q 2 d s p q 1 d d q 3 d p q 4 d q 5 d

    Real Time Programming Regular Expressions: Binuo sa maraming programming language (PHP, Java. Script, …); Ipinatupad bilang mga plug-in (halimbawa, ang klase ng Regex para sa .NET platform). Mga pagkakaiba sa anyo ng pagsulat: x? = x + e x(1, 3) = x + xxx atbp.

    RT Programming Regex Class Constructs (System.Text.Regular.Expressions): Interpretasyon ng Pagkakasunud-sunod ng Pagtakas ng Character b Kapag ginamit sa mga square bracket, tumutugma sa character na "←" (u 0008) t, r, n, a, f, v Tab (u 0009), pagbabalik ng karwahe (u 000 D), bagong linya (u 000 A), atbp. c. X Control character (hal. c. C ay Ctrl+C, u 0003) e Escape (u 001 B) ooo Octal ASCII character xhh Hex ASCII character uhhhh Unicode character Ang sumusunod na character ay hindi isang espesyal na PB character. Ang lahat ng mga espesyal na character ay dapat na i-escape gamit ang character na ito. Halimbawa (sa halimbawa, ang pattern at ang search string ay ibinigay, ang mga tugma na makikita sa string ay may salungguhit): @"rnw+" – "rn. Mayroong n dalawang string dito" .

    Programming RT Mga subset ng mga character. Anumang karakter maliban sa dulo ng string (n) Anumang karakter mula sa hanay [^xxx] Anumang karakter maliban sa mga karakter mula sa hanay Anumang karakter mula sa hanay ] Pagbawas ng isang hanay o hanay mula sa isa pang p(pangalan) Anumang karakter na tinukoy ayon sa kategoryang Unicode na pinangalanang pangalan P (pangalan) Anumang karakter maliban sa mga tinukoy ng kategoryang Unicode na pinangalanang pangalan w Set ng mga character na ginagamit kapag tinutukoy ang mga identifier W Set ng mga character na hindi ginagamit kapag tinutukoy ang mga identifier s Mga Puwang S Lahat maliban sa mga puwang d Digit D Hindi digit Mga Halimbawa : @". +" – "rn. Mayroong n dalawang linya dito"; @"+" - "0xabcfx"; @"[^fx]+" – "0 xabcfx"; @"+" - "0xabcfx"; @"[^a-f]+" – "0 xabcfx"; @"]+" – "0xabcfx"; @"p(Lu)" - "Mga Ilaw ng Lungsod"; // Lu - malalaking titik @"P(Lu)" - "Lungsod"; @"p(Is. Cyrillic)" - "ha. OS"; // Ay. Cyrillic - mga titik na Ruso

    PB Programming Anchor ^, A Sa simula ng string $, Z Sa dulo ng string o hanggang sa "n" sa dulo ng string z Sa dulo ng string G Kung saan natapos ang nakaraang tugma b Word boundary B Anumang posisyong wala sa hangganan ng salita Mga Halimbawa: @ "G(d)" - "(1)(3)(5)(9)"; // tatlong tugma (1), (2) at (3) @"bnS*ionb" – "donasyon ng bansa"; @"Bendw*b" – "end sends endure lender".

    Programming RT Operations (quantifiers) *, *? Pag-ulit +, +? Positibong pag-ulit? , ? ? Zero o isang tugma (n), (n)? Eksaktong n tumutugma sa (n, ), (n, )? Hindi bababa sa n tugma (n, m), (n, m)? Mula sa n hanggang m na mga tugma Mga Halimbawa (ang mga unang quantifier ay matakaw, naghahanap ng maraming elemento hangga't maaari, ang mga pangalawa ay tamad, naghahanap ng kaunting elemento hangga't maaari): @"d(3, )" – "888 -5555"; @"^d(3)" - "913 -913"; @"-d(3)$" - "913 -913"; @"5+? 5" - "888 -5555"; // tatlong tugma - 55, 55 at 55 @"5+5" - "888 -5555".

    RT Programming Grouping () Awtomatikong itinalaga ng pangkat ang isang numero (?:) Huwag i-save ang grupo (?) o (? "pangalan") Kung may nakitang tugma, lumikha ng pinangalanang grupo (?) o Tanggalin ang dating tinukoy na grupo at (? Ang "pangalan-pangalan") ay nag-iimbak sa bagong pangkat ng substring sa pagitan ng dating tinukoy na grupo at ng bagong pangkat (? imnsx:) Ino-on o i-off ang alinman sa limang (? -imnsx:) posibleng opsyon sa grupo: i - case walang nararamdaman; s ay isang linya (pagkatapos ay ". " ay anumang karakter); m – multiline mode (“^” , “$” – simula at dulo ng bawat linya); n - huwag kumuha ng mga hindi pinangalanang grupo; x - ibukod ang mga hindi nakatakas na puwang mula sa pattern at isama ang mga komento pagkatapos ng tanda ng numero (#) (?=) Zero-length positive lookahead assertion

    RE Programming (? !) Negative lookahead assertion of zero length (?) Non-returning (greedy) part of expression Mga Halimbawa: @"(an)+" – "bananas annals"; @"an+" – "bananas annals"; // ihambing, tatlong tugma - an, an at ann @"(? i: an)+" - "ba. NAnas annals"; @"+(? =d)" – "abc xyz 12 555 w"; @"(?

    Src="https://website/presentation/-112203859_437213351/image-24.jpg" alt="(!LANG:Programming RT Reference number Group reference k Pinangalanang group reference Mga Halimbawa: @"> Программирование РВ Ссылки число Ссылка на группу k Ссылка на именованную группу Примеры: @"(w)1" – "deep"; @"(? w)k " – "deep". Конструкции изменения | Альтернатива (соответствует операции объединения) (? (выражение)да|нет) Сопоставляется с частью «да» , если выражение соответствует; в противном случае сопоставляется с необязательной частью «нет» (? (имя)да|нет), Сопоставляется с частью «да» , если названное имя (? (число)да|нет) захвата имеет соответствие; в противном случае сопоставляется с необязательной частью «нет» Пример: @"th(e|is|at)" – "this is the day";!}

    RT Programming Substitutions $number Pinapalitan ang bahagi ng string na nauugnay sa grupo ng tinukoy na numero $(name) Pinapalitan ang bahagi ng string na naaayon sa grupo na may tinukoy na pangalan $$ Substitutes $ $& Palitan ng kopya ng buong tugma $` Palitan ang text ng input string hanggang sa tumugma sa $" Palitan ang text ng input line pagkatapos ng tugma $+ Palitan ang huling nakunan na grupo $_ Palitan ang buong linya Mga komento (? #) Inline na komento # Komento sa dulo ng linya

    Mga Resulta ng RT Programming ng Regex: Regex Matches() Match. Collection Match Groups() Group. Collection Group Captures() Capture. Collection Captures()

    Halimbawa ng RT Programming sa C++ CLI (Visual C++/CLR/CLR Console Application): int main() ( Regex ^r = gcnew Regex(L"((\d)+)+"); Match ^m = r-> Match (L"123 456"); int na tugma. Bilang = 0; habang (m->Tagumpay) ( Console: : Sumulat. Linya(L"Match(0)", ++match. Bilang); para sa (int i = 1; i Groups->Count; i++) ( Group ^g = m->Groups[i]; Console: : Write. Line(L" Group (0) = "(1)"", i, g-> Value ); for (int j = 0; j Captures->Count; j++) ( Capture ^c = g->Captures[j]; Console: : Write.Line(L" Capture(0) = "(1)" , posisyon = (2), haba = (3)", j, c, c->Index, c->Length); ) ) m = m->Next. Match(); ) return 0; ) System: : Text : : Regular. mga ekspresyon

    Pagsasama ng mga aksyon at paghahanap ng mga error Paglilimita sa bilang ng mga makabuluhang digit sa isang numero: (s + e)(pd+ + d+(pd* + e)) s = +|p = . d = ds + e = s? = (+|-)? pd* + e = (pd*)? =(.d*)? @"(+|-)? (. d+|d+(. d*)?)" o @"^(+|-)? (. d+|d+(. d*)?)$" Regex r = bagong Regex (@"^(+|-)? (. (? "digit"d)+|(? "digit"d)+(. (? "digit"d)*)?)$"); Tugma ang m = r. Tugma("+1. 23456789"); if (m. Tagumpay) ( Group g = m. Groups["digit"]; if (g. Captures. Count

    Paganahin ang Mga Aksyon at Paghahanap ng Mga Error Pagtukoy sa Posisyon ng Error: Regex r = new Regex(@"(+|-)? (. (? "digit"d)+|(? "digit"d)+(. (? " digit "d )*)?)"); string str = "+1.2345!678"; Tugma ang m = r. Tugma(str); if (m. Success) ( Group g = m. Groups["digit"]; if (g. Captures. Count 0) Console. Write. Line("Error sa posisyon 1: hindi inaasahang character "(0)"", str ); else if (m.Length

    Paganahin ang mga aksyon at paghahanap ng mga error Pagtukoy sa posisyon ng error: 1. ang unang posisyon ng input string (1), kung ang unang tugma ay hindi magsisimula sa posisyon Index = 0; 2. ang posisyon kasunod ng huling tugma (tugma. Haba + 1), kung hindi ito tumutugma sa huling posisyon ng input string; 3. ang posisyon ng unang pahinga sa pagitan ng mga laban (tugma[i]. Index + tugma[i]. Haba + 1), kung ang karakter na sumusunod sa nakaraang tugma ay hindi ang unang karakter ng susunod na laban.

    index) break; index = m[i]. Index + m[i]. haba; ) Console. magsulat. Line("Error sa posisyon (0) "(1)"", index + 1, str); ) "abc. xyz. pqr" ay tama; + abc. xyz. pqr" - error sa posisyon 1 ("+"); "abc. xyz. pqr!" – error sa posisyon 12 (“!”); "abc. xyz!. pqr" - error sa posisyon 8 ("!").

    Pagsasama ng mga aksyon at paghahanap para sa mga error Ngunit! "abc. xyz. +pqr" - error sa posisyon 8 (". "). Bagong pattern na variant: @"w+(. w+)*(. (? !$))? " Validation: "abc. xyz. +pqr" - error sa posisyon 9 ("+"); "abc. xyz. pqr. "- isang error sa posisyon 12 (". ").

    Mga balanseng kahulugan: "(? "x")" ay nagdaragdag ng isang elemento sa koleksyon na pinangalanang "x"; Ang "(? "-x")" ay nag-aalis ng isang elemento mula sa koleksyon na "x"; Sinusuri ng "(? (x)(? !))" na walang natitirang elemento sa koleksyon na "x". Wika L, na naglalarawan sa mga nested na pahayag ng wikang Pascal na "simulan ang wakas; ': @"^s*((? "nagsisimula+)+(? "-nagsisimula"nagtatapos*; s*)+)*(? (nagsisimula)(? !))$".

    Ang DFA ay isang espesyal na kaso ng NFA. Sa kanya:

      walang estado na may ε-transition;

      para sa bawat estado na S at input na simbolo a, mayroong hindi hihigit sa isang arko na papalabas mula sa S at may label na a.

    Ang isang DFA ay mayroon lamang maximum na isang transition para sa anumang input na simbolo mula sa bawat estado. Kung ang isang talahanayan ay ginagamit upang kumatawan sa DFA transition function, ang bawat entry ay maglalaman lamang ng isang estado. Kaya, madaling suriin kung pinapayagan ng isang ibinigay na DFA ang isang partikular na row, dahil iisa lang ang path mula sa start state, na may label na may row na ito.

    Ang Figure 3 ay nagpapakita ng isang DFA transition graph na nagbibigay-daan para sa parehong wika (a|b) * a(a|b)(a|b) bilang ang NFA sa Figure 1.

    Figure 3. Isang DFA na nagbibigay-daan sa string (a|b) * a(a|b)(a|b).

    Isang deterministikong finite automat M na tumatanggap ng isang partikular na wika:

    M = ((1, 2, 3, 4, 5, 6, 7, 8), (a, b), D, 1, (3, 5, 6, 8))

    Ang transition function D ay tinukoy bilang mga sumusunod:

    Pagbuo ng nc mula sa isang regular na expression

    1. Para sa ε, ang NFA ay may sumusunod na anyo (0 ang inisyal na estado, 1 ang huling estado):

    2. Para sa isang kasama sa ibinigay na wika ng NFA:

    3. Hayaang maging mga NFA ang N(s) at N(t) para sa mga regular na expression na s at t.

      Para sa regular na expression na s|t, ang pinagsama-samang NFA ay may sumusunod na anyo:

    b. Para sa regular na expression st NFA:

    kasama. Para sa expression na s*, ang NFA ay may anyo:

    d. Para sa expression sa (mga) bracket, ang (mga) NFA ay ginagamit tulad ng sa talata a.

    Ang bawat bagong estado ay tumatanggap ng isang indibidwal na pangalan. Ang pagtatayo ng NFA N(r) ay may mga sumusunod na katangian:

      Ang N(r) ay may bilang ng mga estado na hindi lalampas sa bilang ng mga simbolo nang higit sa 2 beses.

      Ang N(r) ay may eksaktong isang inisyal at isang huling estado. Ang huling estado ay walang papalabas na mga transition.

      Ang bawat estado N(r) ay may alinman sa 1 transition para sa isang simbolo mula sa alpabeto (), o hindi hihigit sa 2 papalabas na ε-transition.

    Convert na to dka.

    Ang NFA sa Figure 1 ay may 2 transition mula sa state 0 para sa simbolo a: states 0 at 1. Ang nasabing transition ay malabo, tulad ng transition sa ε. Ang pagmomodelo ng mga naturang NSC sa tulong ng isang computer program ay mas mahirap. Ang kahulugan ng admissibility ay nagsasaad na dapat mayroong ilang landas mula sa paunang estado hanggang sa huling estado, ngunit kapag mayroong maraming mga landas para sa parehong input string, lahat ng mga ito ay dapat isaalang-alang upang makahanap ng isang landas patungo sa huling estado o upang malaman. na walang ganoong landas.

    Sa talahanayan ng paglipat ng NFA, ang bawat entry ay tumutugma sa isang hanay ng mga estado, at sa talahanayan ng paglipat ng DFA - isa lamang. Ang esensya ng pagbabago ay ang bawat estado ng DFA ay tumutugma sa hanay ng mga estado ng NFA. Ginagamit ng DFA ang mga estado nito upang subaybayan ang lahat ng posibleng estado na maaaring mapuntahan ng NFA pagkatapos basahin ang susunod na simbolo ng input. Ibig sabihin, pagkatapos basahin ang input stream, ang DFA ay nasa isang estado na kumakatawan sa isang partikular na hanay ng mga estado ng NFA na maaabot mula sa una sa kahabaan ng path na tumutugma sa input string. Ang bilang ng mga naturang estado ng DFA ay maaaring lumampas nang malaki sa bilang ng mga estado ng NFA (exponential dependence), ngunit sa pagsasagawa ito ay napakabihirang, at kung minsan ay may mas kaunting mga estado sa DFA kaysa sa NFA.

    Isaalang-alang natin ang gayong pagbabago gamit ang isang partikular na halimbawa. Ang Figure 4 ay nagpapakita ng isa pang NFA na nagpapahintulot sa wika (a|b) * a(a|b)(a|b) (tulad ng sa Figures 1 at 3).

    Figure 4. NFA na nagpapahintulot sa wika (a|b) * a(a|b)(a|b)

    Ang paglipat mula sa estado 13 hanggang sa estado 14 na inilalarawan sa figure ay maaaring kinakatawan ng katulad ng paglipat mula sa estado 8 hanggang sa estado 13.

    Bumuo tayo ng isang DFA para sa ibinigay na wika. Ang panimulang estado ng katumbas na DFA ay ang estado A =(0, 1, 2, 4, 7), iyon ay, ang mga estado na maaaring maabot mula 0 hanggang ε.

    Ang input character na alpabeto ay (a, b). Mula sa paunang estado A, maaaring kalkulahin ng isa ang estado na maaabot na may kinalaman sa a. Tawagin natin itong estadong B = (1, 2, 3, 4, 6, 7, 8, 9, 11, 13, 14).

    Sa mga estado sa A, ang estado 4 lang ang may transisyon sa b patungo sa estado 5, kaya ang DFA ay may paglipat sa b mula A patungo sa estado C = (1, 2, 4, 5, 6, 7).

    Kung ipagpapatuloy namin ang prosesong ito sa mga estado B at C, ang lahat ng hanay ng mga estado ng NFA ay lalagyan ng label. Kaya, magkakaroon tayo ng mga hanay ng mga estado:

    A = (0, 1, 2, 4, 7)

    B = (1, 2, 3, 4, 6, 7, 8, 9, 11, 13, 14)

    C = (1, 2, 4, 5, 6, 7)

    D = (10, 12, 13, 14)

    Ang estado A ay inisyal, at ang mga estadong B, D, E ay pinal.

    Ang kumpletong talahanayan ng paglipat ay ipinapakita sa ibaba.

    Ipinapakita ng Figure 5 sa ibaba ang DFA mismo para sa wikang ito.

    Figure 5. Isang DFA na tumatanggap ng wika (a|b) * a(a|b)(a|b)

    Listahan ng ginamit na panitikan:

      Pentus A. E., Pentus M. R. – Teorya ng mga pormal na wika

      A. Aho, R. Seti, D. Ullman - Mga Compiler: mga prinsipyo, teknolohiya, tool.

    Pagbuo ng deterministikong finite automat mula sa isang regular na expression

    Ipakita natin ngayon ang isang algorithm para sa pagbuo ng isang deterministikong finite automat mula sa isang regular na expression na nagpapahintulot sa parehong wika [?].

    Hayaang maibigay ang isang regular na expression na r sa alpabeto T. Magdagdag ng isang end marker sa regular na expression na r: (r)#. Ang ganitong regular na expression ay tatawaging nakumpleto. Sa kurso ng trabaho nito, gagamitin ng algorithm ang nakumpletong regular na expression.

    Ang algorithm ay gagana sa syntax tree para sa nakumpletong regular na expression (r)#, ang bawat dahon nito ay minarkahan ng simbolo , at bawat isa. panloob na tuktok ay minarkahan ng tanda ng isa sa mga operasyon: (concatenation),| (unyon), * (pag-ulit).

    Ang bawat dahon ng puno (maliban sa mga e-dahon) ay bibigyan ng isang natatanging numero, na tinatawag na posisyon, at gagamitin namin ito, sa isang banda, upang sumangguni sa isang dahon sa puno, at, sa kabilang banda, upang sumangguni sa simbolo na katumbas ng dahong ito. Tandaan na kung ang isang character ay ginamit nang maraming beses sa isang regular na expression, mayroon itong maraming mga posisyon.

    Baguhin natin ang punong T mula sa ibaba hanggang sa itaas mula kaliwa hanggang kanan at kalkulahin ang apat na function: nullable, firstpos, lastpos at followpos. Ang unang tatlong function - nullable, firstpos at lastpos - ay tinukoy sa mga node ng tree, at ang followpos ay tinukoy sa set ng mga posisyon. Ang halaga ng lahat ng mga function maliban sa nullable ay ang hanay ng mga posisyon. Ang followpos function ay kinakalkula sa pamamagitan ng iba pang tatlong function.

    Ang function na firstpos(n) para sa bawat node n ng regular expression syntax tree ay nagbibigay ng hanay ng mga posisyon na tumutugma sa mga unang character sa mga substring, na nabuo ng subexpression na may vertex sa n. Katulad nito, binibigyan ng lastpos(n) ang hanay ng mga posisyon na tumutugma sa mga huling character sa mga substring nabuo ng mga subexpression na may vertex n. Para sa isang node n na ang mga subtree (iyon ay, mga puno na ang root node n ay) ay maaaring makagawa ng null na salita, tukuyin ang nullable(n)=true, at para sa natitirang mga node nullable(n)=false.

    Ang talahanayan para sa pagkalkula ng nullable, firstpos, at lastpos function ay ipinapakita sa fig. 3.11.

    Halimbawa 3.7.Sa fig. Ipinapakita ng 3.12 ang syntax tree para sa nakumpletong regular na expression (a|b) * abb# na may resulta ng pagsusuri sa mga function ng firstpos at lastpos. Sa kaliwa ng bawat node ay ang halaga ng firstpos, sa kanan ng node ay ang halaga ng lastpos. Tandaan na ang mga function na ito ay maaaring kalkulahin sa isang tree traversal.

    Kung ang i ay isang posisyon, kung gayon ang followpos(i) ay ang hanay ng mga posisyon j na mayroong ilang string... cd ... na nagaganap sa wikang inilarawan ng regular na expression na ang posisyong i ay tumutugma sa paglitaw ng c at posisyon. j ay entry d.

    kanin. 3.11.

    kanin. 3.12.

    Ang followpos function ay maaari ding kalkulahin sa isang bottom-up traversal ng puno ayon sa dalawang panuntunang ito.

    1. Hayaan ang n ay isang panloob na node na may isang operasyon (concatenation), ang u at v ay ang mga inapo nito. Pagkatapos para sa bawat posisyon na kasama ko sa lastpos(u), idinaragdag namin sa set ng mga value ng followpos(i) ang set firstpos(v).

    2. Hayaang n maging isang panloob na node na may operasyon * (iteration), u - ang inapo nito. Pagkatapos para sa bawat posisyon na kasama ko sa lastpos(u), idinaragdag namin sa set ng mga value ng followpos(i) ang set firstpos(u).

    Halimbawa 3.8. Ang resulta ng pagsusuri ng followpos function para sa regular na expression mula sa nakaraang halimbawa ay ipinapakita sa fig. 3.13.

    Algorithm 3.3. Direktang pagbuo ng isang DFA mula sa isang regular na expression.

    Pagpasok. Regular na expression r sa alpabeto T.

    Output. DFA M = (Q, T, D, q 0 , F) na ang L(M) = L(r).

    Pamamaraan. Ang mga estado ng DFA ay tumutugma sa mga hanay ng mga posisyon.

    Sa una, ang Q at D ay walang laman. Sundin ang mga hakbang 1-6:

    (1) Bumuo ng syntax tree para sa augmented na regular na expression (r)#.