Π§ΠΈΡ‚Π°ΠΉΡ‚Π΅ ΠΊΠ½ΠΈΠ³ΠΈ ΠΎΠ½Π»Π°ΠΉΠ½ Π½Π° Bookidrom.ru! БСсплатныС ΠΊΠ½ΠΈΠ³ΠΈ Π² ΠΎΠ΄Π½ΠΎΠΌ ΠΊΠ»ΠΈΠΊΠ΅

Π§ΠΈΡ‚Π°Ρ‚ΡŒ ΠΎΠ½Π»Π°ΠΉΠ½ Β«UNIX β€” ΡƒΠ½ΠΈΠ²Π΅Ρ€ΡΠ°Π»ΡŒΠ½Π°Ρ срСда программирования». Π‘Ρ‚Ρ€Π°Π½ΠΈΡ†Π° 65

Автор Π‘Ρ€Π°ΠΉΠ°Π½ ΠšΠ΅Ρ€Π½ΠΈΠ³Π°Π½

ΠžΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ %prec "Π³ΠΎΠ²ΠΎΡ€ΠΈΡ‚", Ρ‡Ρ‚ΠΎ символ ΡƒΠ½Π°Ρ€Π½ΠΎΠ³ΠΎ минуса (Ρ‚.Π΅. Π·Π½Π°ΠΊ "-" ΠΏΠ΅Ρ€Π΅Π΄ Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ΠΌ) ΠΈΠΌΠ΅Π΅Ρ‚ Ρ‚ΠΎΡ‚ ΠΆΠ΅ ΠΏΡ€ΠΈΠΎΡ€ΠΈΡ‚Π΅Ρ‚, Ρ‡Ρ‚ΠΎ ΠΈ UNARYMINUS (Π½Π°ΠΈΠ²Ρ‹ΡΡˆΠΈΠΉ); дСйствиС Π·Π°ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ Π² ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΈ Π·Π½Π°ΠΊΠ°. ΠŸΡ€ΠΈΠΎΡ€ΠΈΡ‚Π΅Ρ‚ минуса ΠΌΠ΅ΠΆΠ΄Ρƒ двумя выраТСниями устанавливаСтся ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ.

Π£ΠΏΡ€Π°ΠΆΠ½Π΅Π½ΠΈΠ΅ 8.2

Π”ΠΎΠ±Π°Π²ΡŒΡ‚Π΅ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ % (взятиС остатка) ΠΈ ΡƒΠ½Π°Ρ€Π½Ρ‹ΠΉ плюс ΠΊ hoc1. РСкомСндация: ΠΎΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ΡΡŒ ΠΊ справочному руководству ΠΏΠΎ frexp(3).

НСкоторыС замСчания ΠΎΡ‚Π½ΠΎΡΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ make

Обидно, Ρ‡Ρ‚ΠΎ приходится Π²Π²ΠΎΠ΄ΠΈΡ‚ΡŒ Π΄Π²Π΅ ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ для компиляции hoc1. Π₯отя, ΠΊΠΎΠ½Π΅Ρ‡Π½ΠΎ, Π½Π΅Ρ‚Ρ€ΡƒΠ΄Π½ΠΎ ΡΠΎΡΡ‚Π°Π²ΠΈΡ‚ΡŒ ΠΊΠΎΠΌΠ°Π½Π΄Π½Ρ‹ΠΉ Ρ„Π°ΠΉΠ» для Ρ‚Π°ΠΊΠΎΠ³ΠΎ задания, Π½ΠΎ Π΅ΡΡ‚ΡŒ Π»ΡƒΡ‡ΡˆΠΈΠΉ способ, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ ΠΏΠΎΠ·Π΄Π½Π΅Π΅ ΠΌΠΎΠΆΠ½ΠΎ Ρ€Π°ΡΠΏΡ€ΠΎΡΡ‚Ρ€Π°Π½ΠΈΡ‚ΡŒ Π½Π° Ρ‚ΠΎΡ‚ случай, ΠΊΠΎΠ³Π΄Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° состоит ΠΈΠ· Π½Π΅ΡΠΊΠΎΠ»ΡŒΠΊΠΈΡ… исходных Ρ„Π°ΠΉΠ»ΠΎΠ². ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° make Ρ‡ΠΈΡ‚Π°Π΅Ρ‚ описания взаимозависимости ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ² ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ ΠΈ позволяСт ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ Π΅Π΅ Π΄Π΅ΠΉΡΡ‚Π²ΡƒΡŽΡ‰ΡƒΡŽ Π²Π΅Ρ€ΡΠΈΡŽ. Она провСряСт врСмя послСднСй ΠΌΠΎΠ΄ΠΈΡ„ΠΈΠΊΠ°Ρ†ΠΈΠΈ ΠΊΠ°ΠΆΠ΄ΠΎΠ³ΠΎ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°, выясняСт ΠΌΠΈΠ½ΠΈΠΌΠ°Π»ΡŒΠ½Ρ‹ΠΉ объСм пСрСкомпиляции, ΠΊΠΎΡ‚ΠΎΡ€ΡƒΡŽ Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ Π²Ρ‹ΠΏΠΎΠ»Π½ΠΈΡ‚ΡŒ для получСния Π½ΠΎΠ²ΠΎΠΉ Π΄Π΅ΠΉΡΡ‚Π²ΡƒΡŽΡ‰Π΅ΠΉ вСрсии, ΠΈ Π·Π°Ρ‚Π΅ΠΌ запускаСт процСсс. ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° make разбираСтся Π² Π·Π°ΠΏΡƒΡ‚Π°Π½Π½Ρ‹Ρ… ΠΌΠ½ΠΎΠ³ΠΎΡˆΠ°Π³ΠΎΠ²Ρ‹Ρ… процСссах, Π² частности Π² yacc, поэтому Π΅ΠΉ ΠΌΠΎΠΆΠ½ΠΎ Π΄Π°Π²Π°Ρ‚ΡŒ задания, Π½Π΅ уточняя ΠΎΡ‚Π΄Π΅Π»ΡŒΠ½Ρ‹Π΅ шаги.

ОсобСнно ΠΏΠΎΠ»Π΅Π·Π½ΠΎ ΠΎΠ±Ρ€Π°Ρ‰Π°Ρ‚ΡŒΡΡ ΠΊ make, ΠΊΠΎΠ³Π΄Π° создаваСмая ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° Π½Π°ΡΡ‚ΠΎΠ»ΡŒΠΊΠΎ Π²Π΅Π»ΠΈΠΊΠ°, Ρ‡Ρ‚ΠΎ "располагаСтся" Π² Π½Π΅ΡΠΊΠΎΠ»ΡŒΠΊΠΈΡ… исходных Ρ„Π°ΠΉΠ»Π°Ρ…. Однако ΠΎΠ½Π° ΡƒΠ΄ΠΎΠ±Π½Π° ΠΈ для Ρ‚Π°ΠΊΠΈΡ… ΠΌΠ°Π»Ρ‹Ρ… ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌ, ΠΊΠ°ΠΊ hoc1. НиТС ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Π½Ρ‹ описания ΠΊΠΎΠΌΠ°Π½Π΄ для make, рассчитанныС Π½Π° hoc1, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ make ΠΏΡ€Π΅Π΄ΠΏΠΎΠ»Π°Π³Π°Π΅Ρ‚ Π½Π°ΠΉΡ‚ΠΈ Π² Ρ„Π°ΠΉΠ»Π΅ с ΠΈΠΌΠ΅Π½Π΅ΠΌ makefile.

$ cat makefile

hoc1: hoc.o

cc hoc.o -o hoc1

$

Π—Π΄Π΅ΡΡŒ сообщаСтся, Ρ‡Ρ‚ΠΎ hoc1 зависит ΠΎΡ‚ hoc.o ΠΈ Ρ‡Ρ‚ΠΎ hoc1 создаСтся ΠΈΠ· hoc.o с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΊΠΎΠΌΠ°Π½Π΄Ρ‹ сс, которая запускаСт компилятор Π‘ΠΈ, помСщая Π²Ρ‹Ρ…ΠΎΠ΄Π½ΠΎΠΉ ΠΏΠΎΡ‚ΠΎΠΊ Π² Ρ„Π°ΠΉΠ» hoc1. ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° make ΡƒΠΆΠ΅ "Π·Π½Π°Π΅Ρ‚", ΠΊΠ°ΠΊ ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Ρ‚ΡŒ Π²Ρ…ΠΎΠ΄Π½ΠΎΠΉ Ρ„Π°ΠΉΠ» для yacc hoc.y Π² Π²Ρ‹Ρ…ΠΎΠ΄Π½ΠΎΠΉ Ρ„Π°ΠΉΠ» hoc.o:

$ make ΠŸΡ€ΠΎΠ΄Π΅Π»Π°Π΅ΠΌ ΠΏΠ΅Ρ€Π²Ρ‹ΠΉ Ρ€Π°Π· ΠΏΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠ΅ hoc1 с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ make

yacc hoc.y

сс -с y.tab.c

rm y.tab.c

mv y.tab.o hoc.ΠΎ

сс hoc.о -о hoc1

$ make ΠŸΠΎΠΏΡ€ΠΎΠ±ΡƒΠ΅ΠΌ Π΅Ρ‰Π΅ Ρ€Π°Π·

'hoc1' is up to date make ΠΏΠΎΠ½ΠΈΠΌΠ°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ это Π½Π΅ Π½ΡƒΠΆΠ½ΠΎ

$

8.2 Π­Ρ‚Π°ΠΏ 2: ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅ ΠΈ восстановлСниС послС ошибки

Π‘Π»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠΉ шаг ΠΏΠ΅Ρ€Π΅Ρ…ΠΎΠ΄ ΠΎΡ‚ hoc1 ΠΊ hoc2, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ сводится ΠΊ Ρ€Π°ΡΡˆΠΈΡ€Π΅Π½ΠΈΡŽ памяти (Π² памяти хранится 26 ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Ρ… с ΠΈΠΌΠ΅Π½Π°ΠΌΠΈ ΠΎΡ‚ Π° Π΄ΠΎ z). Π­Ρ‚ΠΎ довольно нСслоТный ΠΈ вСсьма ΠΏΠΎΠ»Π΅Π·Π½Ρ‹ΠΉ ΠΏΡ€ΠΎΠΌΠ΅ΠΆΡƒΡ‚ΠΎΡ‡Π½Ρ‹ΠΉ этап. ΠœΡ‹ Ρ‚Π°ΠΊΠΆΠ΅ Π²Π²Π΅Π΄Π΅ΠΌ здСсь процСсс ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ ошибок. Если Π²Ρ‹ ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΈΡ‚Π΅ hoc1, Ρ‚ΠΎ ΡƒΠ±Π΅Π΄ΠΈΡ‚Π΅ΡΡŒ, Ρ‡Ρ‚ΠΎ Ρ€Π΅Π°ΠΊΡ†ΠΈΠ΅ΠΉ Π½Π° синтаксичСскиС ошибки ΡΠ²Π»ΡΡŽΡ‚ΡΡ Π²Ρ‹Π²ΠΎΠ΄ сообщСния ΠΈ ΠΏΡ€Π΅ΠΊΡ€Π°Ρ‰Π΅Π½ΠΈΠ΅ Ρ€Π°Π±ΠΎΡ‚Ρ‹. ПовСдСниС ΠΆΠ΅ hoc1 Π² случаС арифмСтичСских ошибок Ρ‚ΠΈΠΏΠ° дСлСния Π½Π° Π½ΡƒΠ»ΡŒ достойно всячСского порицания:

$ hoc1

1/0

Floating exception - core dump

$

Для Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ Π½ΠΎΠ²Ρ‹Ρ… возмоТностСй Ρ‚Ρ€Π΅Π±ΡƒΡŽΡ‚ΡΡ лишь нСбольшиС измСнСния: ΠΏΡ€ΠΈΠ±Π»ΠΈΠ·ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ 35 строк тСкста. ЛСксичСский Π°Π½Π°Π»ΠΈΠ·Π°Ρ‚ΠΎΡ€ yylex Π΄ΠΎΠ»ΠΆΠ΅Π½ Ρ€Π°ΡΠΏΠΎΠ·Π½Π°Π²Π°Ρ‚ΡŒ Π±ΡƒΠΊΠ²Ρ‹ ΠΊΠ°ΠΊ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Π΅, Π° Π³Ρ€Π°ΠΌΠΌΠ°Ρ‚ΠΈΠΊΠ° ΡΠΎΠ΄Π΅Ρ€ΠΆΠ°Ρ‚ΡŒ ΠΏΡ€Π°Π²ΠΈΠ»Π° Π²Ρ‹Π²ΠΎΠ΄Π° Π²ΠΈΠ΄Π°

expr: VAR

 | VAR '=' expr

Π’Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ ΡΠΎΠ΄Π΅Ρ€ΠΆΠ°Ρ‚ΡŒ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ присваивания; Ρ€Π°Π·Ρ€Π΅ΡˆΠ΅Π½Ρ‹ Ρ‚Π°ΠΊΠΆΠ΅ ΠΌΠ½ΠΎΠ³ΠΎΠΊΡ€Π°Ρ‚Π½Ρ‹Π΅ присваивания Ρ‚ΠΈΠΏΠ°

x = y = z = 0

ΠŸΡ€ΠΎΡΡ‚Π΅ΠΉΡˆΠΈΠΉ способ хранСния Π·Π½Π°Ρ‡Π΅Π½ΠΈΠΉ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Ρ… ΡΠΎΠ·Π΄Π°Ρ‚ΡŒ массив ΠΈΠ· 26 элСмСнтов; ΠΎΠ΄Π½ΠΎΠ±ΡƒΠΊΠ²Π΅Π½Π½ΡƒΡŽ ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π² качСствС индСкса массива. Однако Ссли Π°Π½Π°Π»ΠΈΠ·Π°Ρ‚ΠΎΡ€Ρƒ прСдстоит ΠΎΠ±Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Ρ‚ΡŒ ΠΈ ΠΈΠΌΠ΅Π½Π° ΠΏΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Ρ‹Ρ…, ΠΈ значСния Π² ΠΎΠ΄Π½ΠΎΠΌ стСкС, Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΡΠΎΠΎΠ±Ρ‰ΠΈΡ‚ΡŒ yacc, Ρ‡Ρ‚ΠΎ элСмСнт стСка являСтся объСдинСниСм double ΠΈ int, Π° Π½Π΅ просто элСмСнтом Ρ‚ΠΈΠΏΠ° double. Π­Ρ‚ΠΎ дСлаСтся с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ описания %union. Описания #define ΠΈΠ»ΠΈ typedef подходят для опрСдСлСния стСка ΠΈΠ· Π±Π°Π·ΠΎΠ²Ρ‹Ρ… Ρ‚ΠΈΠΏΠΎΠ² ΠΊΠ°ΠΊ double, Π½ΠΎ для Ρ‚ΠΈΠΏΠΎΠ² объСдинСния трСбуСтся описаниС %union, ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ yacc осущСствляСт ΠΊΠΎΠ½Ρ‚Ρ€ΠΎΠ»ΡŒ Ρ‚ΠΈΠΏΠΎΠ² Π² выраТСниях Π²ΠΈΠ΄Π° $$ = $2.

НиТС ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Π½Π° Ρ‡Π°ΡΡ‚ΡŒ опрСдСлСния Π³Ρ€Π°ΠΌΠΌΠ°Ρ‚ΠΈΠΊΠΈ hoc.y для ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ hoc2:

$ cat hoc.y

%{

double mem[26]; /* memory for variables 'a'..'z' */

%}

%union {     /* stack type */

 double val; /* actual value */

 int index;  /* index into mem[] */

}

%token <val> NUMBER

%token <index> VAR

%type <val> expr

%right '='

%left '+'

%left '*' '/'

%left UNARYMINUS

%%

list: /* nothing */

 | list '\n'

 | list expr '\n' { printf ("\t%.8g\n", $2); }

 | list error '\n' { yyerrok; }

 ;

expr: NUMBER

 | VAR { $$ = mem[$1]; }

 | VAR '=' expr { $$ = mem[$1] = $3; }

 | expr '+' expr { $$ = $1 + $3; }

 | expr '-' expr { $$ = $1 - $3; }

 | expr '*' expr { $$ = $1 * $3; }

 | expr '/' expr {

  if ($3 == 0.0)

  execerror("division by zero", "");

  $$ = $1 / $3;

 }

 | '(' expr ')' { $$ = $2; }

 | '-' expr %prec UNARYMINUS { $$ = -$2; }

 ;

%%

/* end of grammar */

...

Из описания %union слСдуСт, Ρ‡Ρ‚ΠΎ элСмСнты стСка содСрТат ΠΈΠ»ΠΈ число с Π΄Π²ΠΎΠΉΠ½ΠΎΠΉ Ρ‚ΠΎΡ‡Π½ΠΎΡΡ‚ΡŒΡŽ (ΠΎΠ±Ρ‹Ρ‡Π½Ρ‹ΠΉ случай), ΠΈΠ»ΠΈ Ρ†Π΅Π»ΠΎΠ΅, ΡΠ²Π»ΡΡŽΡ‰Π΅Π΅ΡΡ индСксом Π² массивС mem. Π’ описании %token Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ указываСтся Ρ‚ΠΈΠΏ значСния. Π’ описании %type Π΅ΡΡ‚ΡŒ свСдСния ΠΎ Ρ‚ΠΎΠΌ, Ρ‡Ρ‚ΠΎ Π²Ρ‹Ρ€Π°ΠΆ являСтся элСмСнтом объСдинСния <val>, Ρ‚.Π΅. double. Π˜Π½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡ ΠΎ Ρ‚ΠΈΠΏΠ΅ позволяСт yacc ΠΎΠ±Ρ€Π°Ρ‰Π°Ρ‚ΡŒΡΡ ΠΊ Π½ΡƒΠΆΠ½ΠΎΠΌΡƒ элСмСнту объСдинСния. ΠžΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ Π²Π½ΠΈΠΌΠ°Π½ΠΈΠ΅: "=" прСдставляСт собой ΠΏΡ€Π°Π²ΠΎΠ°ΡΡΠΎΡ†ΠΈΠ°Ρ‚ΠΈΠ²Π½ΡƒΡŽ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΡŽ, Ρ‚ΠΎΠ³Π΄Π° ΠΊΠ°ΠΊ Π΄Ρ€ΡƒΠ³ΠΈΠ΅ ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ β€” лСвоассоциативныС.

ΠžΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° ошибок происходит Π² нСсколько этапов. ΠŸΡ€Π΅ΠΆΠ΄Π΅ всСго производится ΠΏΡ€ΠΎΠ²Π΅Ρ€ΠΊΠ° Π½Π° Π½ΡƒΠ»Π΅Π²ΠΎΠΉ Π΄Π΅Π»ΠΈΡ‚Π΅Π»ΡŒ: Ссли Π΄Π΅Π»ΠΈΡ‚Π΅Π»ΡŒ Ρ€Π°Π²Π΅Π½ Π½ΡƒΠ»ΡŽ, вызываСтся ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Π° ΠΎΠ±Ρ€Π°Π±ΠΎΡ‚ΠΊΠΈ ошибок execerror. Π’Ρ‚ΠΎΡ€ΠΎΠΉ этап Π·Π°ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ Π² ΠΏΠ΅Ρ€Π΅Ρ…Π²Π°Ρ‚Π΅ сигнала "ΠΏΠ΅Ρ€Π΅ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ вСщСствСнного" ("floating point exception"), ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ Π²ΠΎΠ·Π½ΠΈΠΊΠ°Π΅Ρ‚ ΠΏΡ€ΠΈ ΠΏΠ΅Ρ€Π΅ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠΈ вСщСствСнного числа. Π‘ΠΈΠ³Π½Π°Π» устанавливаСтся Π² Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ main. ПослСдний шаг восстановлСния послС ошибки Π·Π°ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ Π² Π΄ΠΎΠ±Π°Π²Π»Π΅Π½ΠΈΠΈ ΠΊ Π³Ρ€Π°ΠΌΠΌΠ°Ρ‚ΠΈΠΊΠ΅ ΠΏΡ€Π°Π²ΠΈΠ»Π° Π²Ρ‹Π²ΠΎΠ΄Π° для ошибки. Π’ Π³Ρ€Π°ΠΌΠΌΠ°Ρ‚ΠΈΠΊΠ΅ yacc слово error Π·Π°Ρ€Π΅Π·Π΅Ρ€Π²ΠΈΡ€ΠΎΠ²Π°Π½ΠΎ; ΠΎΠ½ΠΎ Π΄Π°Π΅Ρ‚ Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ Π°Π½Π°Π»ΠΈΠ·Π°Ρ‚ΠΎΡ€Ρƒ ΠΎΡΠΎΠ·Π½Π°Ρ‚ΡŒ ΡΠΈΠ½Ρ‚Π°ΠΊΡΠΈΡ‡Π΅ΡΠΊΡƒΡŽ ΠΎΡˆΠΈΠ±ΠΊΡƒ ΠΈ Π²ΠΎΡΡΡ‚Π°Π½ΠΎΠ²ΠΈΡ‚ΡŒΡΡ послС Π½Π΅Π΅. Если ΠΏΡ€ΠΎΠΈΠ·ΠΎΠΉΠ΄Π΅Ρ‚ ошибка, yacc Π² ΠΊΠΎΠ½Ρ†Π΅ ΠΊΠΎΠ½Ρ†ΠΎΠ² ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ это ΠΏΡ€Π°Π²ΠΈΠ»ΠΎ, распознаСт ΠΎΡˆΠΈΠ±ΠΊΡƒ ΠΊΠ°ΠΊ грамматичСски "ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΡƒΡŽ" ΠΊΠΎΠ½ΡΡ‚Ρ€ΡƒΠΊΡ†ΠΈΡŽ ΠΈ, Ρ‚Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ, восстановится. ДСйствиС yyerrok Π·Π°ΠΊΠ»ΡŽΡ‡Π°Π΅Ρ‚ΡΡ Π² установкС ΠΏΡ€ΠΈΠ·Π½Π°ΠΊΠ° Π² Π°Π½Π°Π»ΠΈΠ·Π°Ρ‚ΠΎΡ€Π΅, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΉ позволяСт Π²Π΅Ρ€Π½ΡƒΡ‚ΡŒΡΡ Π΅ΠΌΡƒ Π½Π°Π·Π°Π΄ Π² состояниС осмыслСнного Ρ€Π°Π·Π±ΠΎΡ€Π°. ВосстановлСниС послС ошибки слоТная ΠΏΡ€ΠΎΠ±Π»Π΅ΠΌΠ° для всСх Π°Π½Π°Π»ΠΈΠ·Π°Ρ‚ΠΎΡ€ΠΎΠ². ΠœΡ‹ ΠΏΠΎΠΊΠ°Π·Π°Π»ΠΈ Π²Π°ΠΌ здСсь лишь самыС элСмСнтарныС ΠΏΡ€ΠΈΠ΅ΠΌΡ‹ ΠΈ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΎΠ±ΠΎΠ·Π½Π°Ρ‡ΠΈΠ»ΠΈ возмоТности yacc.

Π’ Π³Ρ€Π°ΠΌΠΌΠ°Ρ‚ΠΈΠΊΠ΅ hoс2 ΠΏΡ€ΠΎΠΈΠ·ΠΎΡˆΠ»ΠΈ Π½Π΅Π·Π½Π°Ρ‡ΠΈΡ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ измСнСния. НиТС ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Π½Π° функция main, дополнСнная ΠΎΠ±Ρ€Π°Ρ‰Π΅Π½ΠΈΠ΅ΠΌ ΠΊ setjmp. Оно позволяСт Π·Π°ΠΏΠΎΠΌΠ½ΠΈΡ‚ΡŒ Ρ‚ΠΎ Π½ΠΎΡ€ΠΌΠ°Π»ΡŒΠ½ΠΎΠ΅ состояниС, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ Π±ΡƒΠ΄Π΅Ρ‚ использовано ΠΏΡ€ΠΈ восстановлСнии послС ошибки. Π’ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ execerror происходит ΡΠΎΠΎΡ‚Π²Π΅Ρ‚ΡΡ‚Π²ΡƒΡŽΡ‰Π΅Π΅ ΠΎΠ±Ρ€Π°Ρ‰Π΅Π½ΠΈΠ΅ ΠΊ longjmp. (ОписаниС setjmp ΠΈ longjmp см. Π² Ρ€Π°Π·Π΄. 7.5.)

...

#include <stdio.h>

#include <ctype.h>

char *progname;

int lineno = 1;


#include <signal.h>

#include <setjmp.h>

jmp_buf begin;


main(argc, argv) /* hoc2 */

 char *argv[];

{

 int fpecatch();

 progname = argv[0];

 setjmp(begin);

 signal(SIGFPE, fpecatch);

 yyparse();

}


execerror(s, t) /* recover from run-time error */

 char *s, *t;

{

 warning(s, t);

 longjmp(begin, 0);

}


fpecatch() /* catch floating point exceptions */

{

 execerror("floating point exception", (char*)0);

}

Π’ цСлях ΠΎΡ‚Π»Π°Π΄ΠΊΠΈ ΠΌΡ‹ сочли ΡƒΠ΄ΠΎΠ±Π½Ρ‹ΠΌ, Ρ‡Ρ‚ΠΎΠ±Ρ‹ функция execerror Π²Ρ‹Π·Ρ‹Π²Π°Π»Π° abort (см. справочноС руководство ΠΏΠΎ abort(3)), Ρ‡Ρ‚ΠΎ ΠΏΡ€ΠΈΠ²Π΅Π΄Π΅Ρ‚ ΠΊ распСчаткС содСрТимого памяти, ΠΊΠΎΡ‚ΠΎΡ€ΡƒΡŽ Π·Π°Ρ‚Π΅ΠΌ смогут ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ adb ΠΈ sdb. Когда Ρ€Π°Π·Ρ€Π°Π±ΠΎΡ‚ΠΊΠ° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ ΠΏΠΎΠ»Π½ΠΎΡΡ‚ΡŒΡŽ Π·Π°Π²Π΅Ρ€ΡˆΠΈΡ‚ΡΡ, ΠΎΠ±Ρ€Π°Ρ‰Π΅Π½ΠΈΠ΅ ΠΊ abort Π±ΡƒΠ΄Π΅Ρ‚ Π·Π°ΠΌΠ΅Π½Π΅Π½ΠΎ Π½Π° longjmp.

Π’ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ΅ hoc2 лСксичСский Π°Π½Π°Π»ΠΈΠ·Π°Ρ‚ΠΎΡ€ нСсколько ΠΈΠ½ΠΎΠΉ. Π’ Π½Π΅ΠΌ ΡƒΡ‡Ρ‚Π΅Π½ΠΎ Ρ€Π°Π·Π»ΠΈΡ‡ΠΈΠ΅ строчных ΠΈ прописных Π±ΡƒΠΊΠ², Π° ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Ρ‚Π΅ΠΏΠ΅Ρ€ΡŒ yyval являСтся объСдинСниСм, Π½ΡƒΠΆΠ½ΠΎ Π²Ρ‹Π±Ρ€Π°Ρ‚ΡŒ подходящий элСмСнт ΠΏΠ΅Ρ€Π΅Π΄ Π²Ρ‹Ρ…ΠΎΠ΄ΠΎΠΌ ΠΈΠ· yylex. НиТС ΠΏΠΎΠΊΠ°Π·Π°Π½Ρ‹ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½Π½Ρ‹Π΅ Ρ„Ρ€Π°Π³ΠΌΠ΅Π½Ρ‚Ρ‹:

yylex() /* hoc2 */

{

 ...

 if (с == '.' || isdigit(c)) { /* number */

  ungetc(c, stdin);

  scanf("%lf", &yylval.val);

  return NUMBER;

 }

 if (islower(c)) {

  yylval.index = с - 'a'; /* ASCII only */

  return VAR;

 }

...

Π•Ρ‰Π΅ Ρ€Π°Π· ΠΎΡ‚ΠΌΠ΅Ρ‚ΠΈΠΌ, Ρ‡Ρ‚ΠΎ Ρ‚ΠΈΠΏ лСксСмы (Ρ‚.Π΅. NUMBER) Π½Π΅ совпадаСт с Π΅Π΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ΠΌ (Π½Π°ΠΏΡ€ΠΈΠΌΠ΅Ρ€, 3.1416).