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

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

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

$ cat hoc.y

%{

#define YYSTYPE double /* data type of yacc stack */

%}

%token NUMBER

%left '+' /* left associative, same precedence */

%left '*' '/' /* left assoc., higher precedence */

%%

list: /* nothing */

 | list '\n'

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

 ;

expr: NUMBER { $$ = $1; }

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

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

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

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

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

 ;

%%

/* end of grammar */

...

Π’Ρ‹ Π²ΠΈΠ΄ΠΈΡ‚Π΅, ΠΊΠ°ΠΊ ΠΌΠ½ΠΎΠ³ΠΎ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΠΈ Π·Π°ΠΊΠ»ΡŽΡ‡Π΅Π½ΠΎ Π² этих Π½Π΅ΡΠΊΠΎΠ»ΡŒΠΊΠΈΡ… строках. ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΌΡ‹ Π½Π΅ ΠΌΠΎΠΆΠ΅ΠΌ Π²Π°ΠΌ здСсь всС ΠΎΠ±ΡŠΡΡΠ½ΠΈΡ‚ΡŒ, Π² частности, ΠΊΠ°ΠΊ Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ синтаксичСский Π°Π½Π°Π»ΠΈΠ·Π°Ρ‚ΠΎΡ€, ΠΎΠ±Ρ€Π°Ρ‚ΠΈΡ‚Π΅ΡΡŒ ΠΊ справочному руководству ΠΏΠΎ yacc.

ΠΠ»ΡŒΡ‚Π΅Ρ€Π½Π°Ρ‚ΠΈΠ²Π½Ρ‹Π΅ ΠΏΡ€Π°Π²ΠΈΠ»Π° Ρ€Π°Π·Π΄Π΅Π»Π΅Π½Ρ‹ символом '|'. Π‘ ΠΊΠ°ΠΆΠ΄Ρ‹ΠΌ грамматичСским ΠΏΡ€Π°Π²ΠΈΠ»ΠΎΠΌ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ связано ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π½ΠΎΠ΅ дСйствиС, ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠ΅ выполняСтся, ΠΊΠΎΠ³Π΄Π° экзСмпляр этого ΠΏΡ€Π°Π²ΠΈΠ»Π° распознаСтся Π²ΠΎ Π²Ρ…ΠΎΠ΄Π½ΠΎΠΌ ΠΏΠΎΡ‚ΠΎΠΊΠ΅. ДСйствиС описываСтся ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΡŒΡŽ ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ΠΎΠ² Π‘ΠΈ, Π·Π°ΠΊΠ»ΡŽΡ‡Π΅Π½Π½ΠΎΠΉ Π² Ρ„ΠΈΠ³ΡƒΡ€Π½Ρ‹Π΅ скобки. Π’Π½ΡƒΡ‚Ρ€ΠΈ ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ $n (Ρ‚.Π΅. $1, $2 ΠΈ Ρ‚.Π΄.) опрСдСляСт Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅, Π²Ρ‹Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Π΅ΠΌΠΎΠ΅ n-ΠΌ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠΌ ΠΏΡ€Π°Π²ΠΈΠ»Π°, Π° $$ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅, Π²Ρ‹Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Π΅ΠΌΠΎΠ΅ всСми ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚Π°ΠΌΠΈ ΠΏΡ€Π°Π²ΠΈΠ»Π° Π² Ρ†Π΅Π»ΠΎΠΌ. Π’Π°ΠΊ, Π² ΠΏΡ€Π°Π²ΠΈΠ»Π΅

expr: NUMBER { $$ = $1; }

$1 β€” Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅, Π²Ρ‹Ρ€Π°Π±Π°Ρ‚Ρ‹Π²Π°Π΅ΠΌΠΎΠ΅ ΠΏΡ€ΠΈ распознавании NUMBER, ΠΈ ΠΎΠ½ΠΎ ΠΆΠ΅ являСтся Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚ΠΈΡ€ΡƒΡŽΡ‰ΠΈΠΌ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ΠΌ expr. Π’ Π΄Π°Π½Π½ΠΎΠΌ случаС присваиваниС $$ = $1 ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ ΠΎΠΏΡƒΡ‰Π΅Π½ΠΎ, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ $$ всСгда ΠΏΡ€ΠΈΠ½ΠΈΠΌΠ°Π΅Ρ‚ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ $1 (Ссли Π½Π΅ устанавливаСтся явно ΠΊΠ°ΠΊΠΈΠΌ Π»ΠΈΠ±ΠΎ ΠΈΠ½Ρ‹ΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ). Π’ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΉ строкС с ΠΏΡ€Π°Π²ΠΈΠ»ΠΎΠΌ

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

Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚ΠΈΡ€ΡƒΡŽΡ‰Π΅Π΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ expr являСтся суммой Π΄Π²ΡƒΡ… ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ΠΎΠ², Ρ‚ΠΎΠΆΠ΅ expr. ΠžΡ‚ΠΌΠ΅Ρ‚ΠΈΠΌ, Ρ‡Ρ‚ΠΎ $2 соотвСтствуСт '+' Ρ‚.Π΅. ΠΊΠ°ΠΆΠ΄Ρ‹ΠΉ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ‚ ΠΏΡ€ΠΎΠ½ΡƒΠΌΠ΅Ρ€ΠΎΠ²Π°Π½.

Π‘Ρ‚Ρ€ΠΎΠΊΠΎΠΉ Π²Ρ‹ΡˆΠ΅ Π²Ρ‹Ρ€Π°ΠΆΠ΅Π½ΠΈΠ΅, Π·Π° ΠΊΠΎΡ‚ΠΎΡ€Ρ‹ΠΌ слСдуСт символ ΠΏΠ΅Ρ€Π΅Π²ΠΎΠ΄Π° строки ('\n'), распознаСтся ΠΊΠ°ΠΊ список, ΠΈ пСчатаСтся Π΅Π³ΠΎ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅. Если Π·Π° Ρ‚Π°ΠΊΠΎΠΉ конструкциСй слСдуСт ΠΊΠΎΠ½Π΅Ρ† Π²Ρ…ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΏΠΎΡ‚ΠΎΠΊΠ°, процСсс Ρ€Π°Π·Π±ΠΎΡ€Π° Π·Π°Π²Π΅Ρ€ΡˆΠ°Π΅Ρ‚ΡΡ ΠΏΡ€Π°Π²ΠΈΠ»ΡŒΠ½ΠΎ. Бписок ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ пустой строкой; Ρ‚Π°ΠΊ ΡƒΡ‡ΠΈΡ‚Ρ‹Π²Π°ΡŽΡ‚ΡΡ пустыС Π²Ρ…ΠΎΠ΄Π½Ρ‹Π΅ строки.

Π€ΠΎΡ€ΠΌΠ°Ρ‚ Π²Ρ…ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΏΠΎΡ‚ΠΎΠΊΠ° для yacc β€” ΠΏΡ€ΠΎΠΈΠ·Π²ΠΎΠ»ΡŒΠ½Ρ‹ΠΉ. Наш Ρ„ΠΎΡ€ΠΌΠ°Ρ‚ рСкомСндуСтся ΠΊΠ°ΠΊ стандартный.

Π’ этой Ρ€Π΅Π°Π»ΠΈΠ·Π°Ρ†ΠΈΠΈ процСсс распознавания ΠΈΠ»ΠΈ Ρ€Π°Π·Π±ΠΎΡ€Π° Π²Ρ…ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΏΠΎΡ‚ΠΎΠΊΠ° ΠΏΡ€ΠΈΠ²ΠΎΠ΄ΠΈΡ‚ ΠΊ Π½Π΅ΠΌΠ΅Π΄Π»Π΅Π½Π½ΠΎΠΌΡƒ Π²Ρ‹Ρ‡ΠΈΡΠ»Π΅Π½ΠΈΡŽ выраТСния. Π’ Π±ΠΎΠ»Π΅Π΅ слоТных Ρ€Π΅ΡˆΠ΅Π½ΠΈΡΡ… (Π²ΠΊΠ»ΡŽΡ‡Π°Ρ hoc4 ΠΈ Π΅Π³ΠΎ ΠΏΠΎΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΠ΅ вСрсии) процСсс Ρ€Π°Π·Π±ΠΎΡ€Π° ΠΏΠΎΡ€ΠΎΠΆΠ΄Π°Π΅Ρ‚ ΠΊΠΎΠ΄ для дальнСйшСго выполнСния.

Наглядно ΠΏΡ€Π΅Π΄ΡΡ‚Π°Π²ΠΈΡ‚ΡŒ Ρ€Π°Π·Π±ΠΎΡ€ Π²Π°ΠΌ ΠΏΠΎΠΌΠΎΠΆΠ΅Ρ‚ рис. 8.1, Π³Π΄Π΅ ΠΈΠ·ΠΎΠ±Ρ€Π°ΠΆΠ΅Π½ΠΎ Π΄Π΅Ρ€Π΅Π²ΠΎ Ρ€Π°Π·Π±ΠΎΡ€Π°. ΠšΡ€ΠΎΠΌΠ΅ Ρ‚ΠΎΠ³ΠΎ, Π²Ρ‹ Π΄ΠΎΠ»ΠΆΠ½Ρ‹ Π·Π½Π°Ρ‚ΡŒ, ΠΊΠ°ΠΊ Π²Ρ‹Ρ‡ΠΈΡΠ»ΡΡŽΡ‚ΡΡ значСния ΠΈ ΠΊΠ°ΠΊ ΠΎΠ½ΠΈ Ρ€Π°ΡΠΏΡ€ΠΎΡΡ‚Ρ€Π°Π½ΡΡŽΡ‚ΡΡ ΠΎΡ‚ Π»ΠΈΡΡ‚ΡŒΠ΅Π² ΠΊ ΠΊΠΎΡ€Π½ΡŽ Π΄Π΅Ρ€Π΅Π²Π°.


Рис. 8.1: Π”Π΅Ρ€Π΅Π²ΠΎ Ρ€Π°Π·Π±ΠΎΡ€Π° для 2 + 3*4


РСально значСния Π½Π΅ ΠΏΠΎΠ»Π½ΠΎΡΡ‚ΡŒΡŽ Ρ€Π°Π·ΠΎΠ±Ρ€Π°Π½Π½Ρ‹Ρ… ΠΏΡ€Π°Π²ΠΈΠ» хранятся Π² стСкС ΠΈ Ρ‡Π΅Ρ€Π΅Π· стСк ΠΏΠ΅Ρ€Π΅Π΄Π°ΡŽΡ‚ΡΡ ΠΎΡ‚ ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΏΡ€Π°Π²ΠΈΠ»Π° ΠΊ ΡΠ»Π΅Π΄ΡƒΡŽΡ‰Π΅ΠΌΡƒ. ΠžΠ±Ρ‹Ρ‡Π½ΠΎ Π΄Π°Π½Π½Ρ‹Π΅ Π² стСкС ΠΈΠΌΠ΅ΡŽΡ‚ Ρ†Π΅Π»Ρ‹ΠΉ Ρ‚ΠΈΠΏ, Π½ΠΎ ΠΏΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ ΠΌΡ‹ Π² своСй Ρ€Π°Π±ΠΎΡ‚Π΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅ΠΌ числа с ΠΏΠ»Π°Π²Π°ΡŽΡ‰Π΅ΠΉ Ρ‚ΠΎΡ‡ΠΊΠΎΠΉ, Π½Π΅ΠΎΠ±Ρ…ΠΎΠ΄ΠΈΠΌΠΎ ΠΏΠ΅Ρ€Π΅ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΠΈΡ‚ΡŒ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΏΠΎ ΡƒΠΌΠΎΠ»Ρ‡Π°Π½ΠΈΡŽ. ΠžΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅

#define YYSTYPE double

устанавливаСт Π΄Π²ΠΎΠΉΠ½ΡƒΡŽ Ρ‚ΠΎΡ‡Π½ΠΎΡΡ‚ΡŒ для Ρ‚ΠΈΠΏΠ° Π΄Π°Π½Π½Ρ‹Ρ… стСка.

Π’Π΅ΠΏΠ΅Ρ€ΡŒ ΠΏΠ΅Ρ€Π΅ΠΉΠ΄Π΅ΠΌ ΠΊ описанию синтаксичСских классов, распознаваСмых лСксичСским Π°Π½Π°Π»ΠΈΠ·Π°Ρ‚ΠΎΡ€ΠΎΠΌ, Ссли Ρ‚ΠΎΠ»ΡŒΠΊΠΎ ΠΎΠ½ΠΈ Π½Π΅ ΡΠ²Π»ΡΡŽΡ‚ΡΡ Π»ΠΈΡ‚Π΅Ρ€Π°Π»Π°ΠΌΠΈ, состоящими ΠΈΠ· ΠΎΠ΄Π½ΠΎΠ³ΠΎ символа Π²ΠΈΠ΄Π° '+' ΠΈ '-'. ОписаниС %token спСцифицируСт ΠΎΠ΄Π½ΠΈ ΠΈΠ»ΠΈ нСсколько Ρ‚Π°ΠΊΠΈΡ… ΠΎΠ±ΡŠΠ΅ΠΊΡ‚ΠΎΠ². ΠŸΡ€ΠΈ нСобходимости ΠΌΠΎΠΆΠ½ΠΎ Π·Π°Π΄Π°Ρ‚ΡŒ Π»Π΅Π²ΡƒΡŽ ΠΈΠ»ΠΈ ΠΏΡ€Π°Π²ΡƒΡŽ Π°ΡΡΠΎΡ†ΠΈΠ°Ρ‚ΠΈΠ²Π½ΠΎΡΡ‚ΡŒ, ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΡ %left ΠΈΠ»ΠΈ %right вмСсто %token.

(ЛСвая Π°ΡΡΠΎΡ†ΠΈΠ°Ρ‚ΠΈΠ²Π½ΠΎΡΡ‚ΡŒ ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚, Ρ‡Ρ‚ΠΎ a-b-с Π±ΡƒΠ΄Π΅Ρ‚ Ρ€Π°Π·Π±ΠΈΡ€Π°Ρ‚ΡŒΡΡ ΠΊΠ°ΠΊ (Π° - b) - с, Π° Π½Π΅ Π° - (b - с).) ΠŸΡ€ΠΈΠΎΡ€ΠΈΡ‚Π΅Ρ‚ устанавливаСтся порядком появлСния ΠΎΠΏΠ΅Ρ€Π°Ρ†ΠΈΠΈ: лСксСмы ΠΈΠ· ΠΎΠ΄Π½ΠΎΠ³ΠΎ опрСдСлСния ΠΈΠΌΠ΅ΡŽΡ‚ ΠΎΠ΄ΠΈΠ½ ΠΈ Ρ‚ΠΎΡ‚ ΠΆΠ΅ ΠΏΡ€ΠΈΠΎΡ€ΠΈΡ‚Π΅Ρ‚, Π° лСксСмы, спСцифицированныС ΠΏΠΎΠ·Π΄Π½Π΅Π΅, β€” Π±ΠΎΠ»Π΅Π΅ высокий. Π’Π°ΠΊΠΈΠΌ ΠΎΠ±Ρ€Π°Π·ΠΎΠΌ, Π² Π³Ρ€Π°ΠΌΠΌΠ°Ρ‚ΠΈΠΊΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ Π±Ρ‹Ρ‚ΡŒ Π½Π΅ΠΎΠ΄Π½ΠΎΠ·Π½Π°Ρ‡Π½ΠΎΡΡ‚ΡŒ (Ρ‚.Π΅. для Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… Π²Ρ…ΠΎΠ΄Π½Ρ‹Ρ… ΠΏΠΎΡ‚ΠΎΠΊΠΎΠ² сущСствуСт нСсколько способов Ρ€Π°Π·Π±ΠΎΡ€Π°), Π½ΠΎ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½Π°Ρ информация Π² опрСдСлСниях Ρ€Π°Π·Ρ€Π΅ΡˆΠ°Π΅Ρ‚ эту Π½Π΅ΠΎΠ΄Π½ΠΎΠ·Π½Π°Ρ‡Π½ΠΎΡΡ‚ΡŒ.

Π’Ρ‚ΠΎΡ€ΡƒΡŽ ΠΏΠΎΠ»ΠΎΠ²ΠΈΠ½Ρƒ Ρ„Π°ΠΉΠ»Π° hoc.y ΡΠΎΡΡ‚Π°Π²Π»ΡΡŽΡ‚ ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Ρ‹:

/* ΠŸΡ€ΠΎΠ΄ΠΎΠ»ΠΆΠ΅Π½ΠΈΠ΅ hoc.y */

#include <stdio.h>

#include <ctype.h>


char *progname; /* for error messages */

int lineno = 1;


main(argc, argv) /* hoc1 */

char *argv[];

{

 progname = argv[0];

 yyparse();

}

Ѐункция main обращаСтся ΠΊ yyparse для Ρ€Π°Π·Π±ΠΎΡ€Π° Π²Ρ…ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΏΠΎΡ‚ΠΎΠΊΠ°. ΠŸΠ΅Ρ€Π΅Ρ…ΠΎΠ΄ Π² Ρ†ΠΈΠΊΠ»Π΅ ΠΎΡ‚ ΠΎΠ΄Π½ΠΎΠ³ΠΎ выраТСния ΠΊ Π΄Ρ€ΡƒΠ³ΠΎΠΌΡƒ происходит Π² Ρ€Π°ΠΌΠΊΠ°Ρ… Π³Ρ€Π°ΠΌΠΌΠ°Ρ‚ΠΈΠΊΠΈ с ΠΏΠΎΠΌΠΎΡ‰ΡŒΡŽ ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒΠ½ΠΎΡΡ‚ΠΈ ΠΏΡ€Π°Π²ΠΈΠ» Π²Ρ‹Π²ΠΎΠ΄Π° для списка. ΠŸΡ€ΠΈΠ΅ΠΌΠ»Π΅ΠΌΠΎ Ρ‚Π°ΠΊΠΆΠ΅ ΠΎΠ±Ρ€Π°Ρ‰Π°Ρ‚ΡŒΡΡ Π² Ρ†ΠΈΠΊΠ»Π΅ ΠΊ yyparse ΠΈΠ· Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ main, Ссли дСйствия для списка ΠΏΡ€Π΅Π΄ΠΏΠΎΠ»Π°Π³Π°ΡŽΡ‚ ΠΏΠ΅Ρ‡Π°Ρ‚ΡŒ значСния ΠΈ Π½Π΅ΠΌΠ΅Π΄Π»Π΅Π½Π½Ρ‹ΠΉ Π²ΠΎΠ·Π²Ρ€Π°Ρ‚.

Ѐункция yyparse Π² свою ΠΎΡ‡Π΅Ρ€Π΅Π΄ΡŒ ΠΌΠ½ΠΎΠ³ΠΎΠΊΡ€Π°Ρ‚Π½ΠΎ обращаСтся Π·Π° лСксСмами ΠΈΠ· Π²Ρ…ΠΎΠ΄Π½ΠΎΠ³ΠΎ ΠΏΠΎΡ‚ΠΎΠΊΠ° ΠΊ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ yylex. Наша функция yylex проста: Π² Π΅Π΅ Π·Π°Π΄Π°Ρ‡ΠΈ входят пропуск ΠΏΡ€ΠΎΠ±Π΅Π»ΠΎΠ² ΠΈ символов табуляции, ΠΏΡ€Π΅ΠΎΠ±Ρ€Π°Π·ΠΎΠ²Π°Π½ΠΈΠ΅ Ρ†ΠΈΡ„Ρ€ΠΎΠ²Ρ‹Ρ… строк Π² числовоС Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅ ΠΈ подсчСт Π²Ρ…ΠΎΠ΄Π½Ρ‹Ρ… строк для Π²Ρ‹Π²ΠΎΠ΄Π° сообщСний ΠΎΠ± ΠΎΡˆΠΈΠ±ΠΊΠ°Ρ…. ΠŸΠΎΡΠΊΠΎΠ»ΡŒΠΊΡƒ Π³Ρ€Π°ΠΌΠΌΠ°Ρ‚ΠΈΠΊΠ° допускаСт Ρ‚ΠΎΠ»ΡŒΠΊΠΎ +, -, *, /, (, ) ΠΈ \n, ΠΏΡ€ΠΈ появлСнии любого Π΄Ρ€ΡƒΠ³ΠΎΠ³ΠΎ символа yyparse Π²Ρ‹Π΄Π°Π΅Ρ‚ сообщСниС ΠΎΠ± ошибкС. ΠŸΠΎΠ»ΡƒΡ‡Π΅Π½ΠΈΠ΅ 0 ΠΎΠ·Π½Π°Ρ‡Π°Π΅Ρ‚ для yyparse "ΠΊΠΎΠ½Π΅Ρ† Ρ„Π°ΠΉΠ»Π°".

/* ΠŸΡ€ΠΎΠ΄ΠΎΠ»ΠΆΠ΅Π½ΠΈΠ΅ hoc.y */


yylex() /* hoc1 */

{

 int с;

 while ((c=getchar()) == ' ' || с == '\t')

  ;

 if (c == EOF)

  return 0;

 if (c == '.' || isdigit(c)) {

  /* number */

  ungetc(c, stdin);

  scanf("%lf", &yylval);

  return NUMBER;

 }

 if (c == '\n')

  lineno++;

 return с;

}

ΠŸΠ΅Ρ€Π΅ΠΌΠ΅Π½Π½Π°Ρ yylval ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ для связи ΠΌΠ΅ΠΆΠ΄Ρƒ синтаксичСским ΠΈ лСксичСским Π°Π½Π°Π»ΠΈΠ·Π°Ρ‚ΠΎΡ€Π°ΠΌΠΈ; ΠΎΠ½Π° ΠΎΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½Π° Π² yyparse ΠΈ ΠΈΠΌΠ΅Π΅Ρ‚ Ρ‚ΠΎΡ‚ ΠΆΠ΅ Ρ‚ΠΈΠΏ, Ρ‡Ρ‚ΠΎ стСк yacc. Ѐункция yylex Π²ΠΎΠ·Π²Ρ€Π°Ρ‰Π°Π΅Ρ‚ Ρ‚ΠΈΠΏ лСксСмы, Ρ€Π°Π²Π½ΠΎ ΠΊΠ°ΠΊ ΠΈ Π΅Π΅ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΎΠ½Π°Π»ΡŒΠ½ΠΎΠ΅ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅, ΠΈ ΠΏΡ€ΠΈΡ€Π°Π²Π½ΠΈΠ²Π°Π΅Ρ‚ yylval Π·Π½Π°Ρ‡Π΅Π½ΠΈΡŽ лСксСмы (Ссли ΠΎΠ½ΠΎ Π΅ΡΡ‚ΡŒ). НапримСр, число с ΠΏΠ»Π°Π²Π°ΡŽΡ‰Π΅ΠΉ Ρ‚ΠΎΡ‡ΠΊΠΎΠΉ ΠΈΠΌΠ΅Π΅Ρ‚ Ρ‚ΠΈΠΏ NUMBER ΠΈ Π·Π½Π°Ρ‡Π΅Π½ΠΈΠ΅, скаТСм, 12.34. Для Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Ρ… лСксСм, ΠΏΡ€Π΅ΠΆΠ΄Π΅ всСго состоящих ΠΈΠ· ΠΎΠ΄Π½ΠΎΠ³ΠΎ символа, Ρ‚Π°ΠΊΠΈΡ…, ΠΊΠ°ΠΊ '+' ΠΈΠ»ΠΈ '\n', Π² Π³Ρ€Π°ΠΌΠΌΠ°Ρ‚ΠΈΠΊΠ΅ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΡƒΠ΅Ρ‚ΡΡ Ρ‚ΠΎΠ»ΡŒΠΊΠΎ Ρ‚ΠΈΠΏ. Π’ этом случаС yylval Π½Π΅ Π½ΡƒΠΆΠ½ΠΎ ΠΎΠΏΡ€Π΅Π΄Π΅Π»ΡΡ‚ΡŒ.

ΠžΠΏΡ€Π΅Π΄Π΅Π»Π΅Π½ΠΈΠ΅ %token NUMBER ΠΈΠ· Π²Ρ…ΠΎΠ΄Π½ΠΎΠ³ΠΎ Ρ„Π°ΠΉΠ»Π° для yacc прСобразуСтся Π² ΠΎΠΏΠ΅Ρ€Π°Ρ‚ΠΎΡ€ #define Π² Π²Ρ‹Ρ…ΠΎΠ΄Π½ΠΎΠΌ Ρ„Π°ΠΉΠ»Π΅ y.tab.c, поэтому NUMBER ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚ΡŒ Π² качСствС константы Π² любом мСстС Π‘ΠΈ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹. Yacc Π²Ρ‹Π±ΠΈΡ€Π°Π΅Ρ‚ Ρ‚Π°ΠΊΠΈΠ΅ значСния, ΠΊΠΎΡ‚ΠΎΡ€Ρ‹Π΅ Π½Π΅ Π±ΡƒΠ΄ΡƒΡ‚ ΡΠΌΠ΅ΡˆΠΈΠ²Π°Ρ‚ΡŒΡΡ с символами ASCII.

ΠŸΡ€ΠΈ Π½Π°Π»ΠΈΡ‡ΠΈΠΈ синтаксичСской ошибки yyparse обращаСтся ΠΊ yyerror со строкой, содСрТащСй Π·Π°Π³Π°Π΄ΠΎΡ‡Π½ΠΎΠ΅ сообщСниС: "syntax error" ("синтаксичСская ошибка"). ΠŸΡ€Π΅Π΄ΠΏΠΎΠ»Π°Π³Π°Π΅Ρ‚ΡΡ, Ρ‡Ρ‚ΠΎ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΡŽ yyerror прСдоставляСт ΠΏΠΎΠ»ΡŒΠ·ΠΎΠ²Π°Ρ‚Π΅Π»ΡŒ: Π² нашСй Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ строка просто пСрСдаСтся Π΄Ρ€ΡƒΠ³ΠΎΠΉ Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ β€” warning, которая Π²Ρ‹Π΄Π°Π΅Ρ‚ Π½Π΅ΠΊΠΎΡ‚ΠΎΡ€ΡƒΡŽ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½ΡƒΡŽ ΠΈΠ½Ρ„ΠΎΡ€ΠΌΠ°Ρ†ΠΈΡŽ. Π’ ΠΏΠΎΡΠ»Π΅Π΄ΡƒΡŽΡ‰ΠΈΡ… вСрсиях hoc функция warning Π±ΡƒΠ΄Π΅Ρ‚ ΠΏΡ€ΠΈΠΌΠ΅Π½ΡΡ‚ΡŒΡΡ нСпосрСдствСнно.

yyerror(s) /* called for yacc syntax error */

 char *s;

{

 warning(s, (char*)0);

}


warning(s, t) /* print warning message */

 char *s, *t;

{

 fprintf(stderr, "%s: %s", progname, s);

 if (t)

  fprintf(stderr, " %s", t);

 fprintf(stderr, " near line %d\n", lineno);

}

Π­Ρ‚ΠΈΠΌ Π·Π°Π²Π΅Ρ€ΡˆΠ°ΡŽΡ‚ΡΡ ΠΏΡ€ΠΎΡ†Π΅Π΄ΡƒΡ€Ρ‹ Ρ„Π°ΠΉΠ»Π° hoc.y. Врансляция ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ для yacc происходит Π² Π΄Π²Π° этапа:

$ yacc hoc.y         Π’Ρ‹Ρ…ΠΎΠ΄Π½ΠΎΠΉ ΠΏΠΎΡ‚ΠΎΠΊ ΠΏΠΎΠΏΠ°Π΄Π°Π΅Ρ‚ Π² y.tab.c

$ сс y.tab.c -ΠΎ hoc1 ВыполняСмая ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° ΠΏΠΎΠΏΠ°Π΄Π°Π΅Ρ‚ Π² hoc1

$ hoc1

2/3

 0.66666667

-3-4

hoc1: syntax error near line 1

$

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

Π˜ΡΡΠ»Π΅Π΄ΡƒΠΉΡ‚Π΅ структуру Ρ„Π°ΠΉΠ»Π° y.tab.c (для hoc1 это составляСт ΠΎΠΊΠΎΠ»ΠΎ 300 строк тСкста).

ВнСсСниС ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠΉ β€” ΡƒΠ½Π°Ρ€Π½Ρ‹ΠΉ минус

Π Π°Π½Π΅Π΅ ΠΌΡ‹ ΡƒΡ‚Π²Π΅Ρ€ΠΆΠ΄Π°Π»ΠΈ, Ρ‡Ρ‚ΠΎ, работая с yacc, Π»Π΅Π³ΠΊΠΎ ΠΌΠ΅Π½ΡΡ‚ΡŒ язык. Π’ качСствС ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π° Π΄ΠΎΠ±Π°Π²ΠΈΠΌ ΠΊ hoc1 ΡƒΠ½Π°Ρ€Π½Ρ‹ΠΉ минус, Ρ‡Ρ‚ΠΎΠ±Ρ‹ выраТСния Ρ‚ΠΈΠΏΠ°

-3-4

Π²Ρ‹Ρ‡ΠΈΡΠ»ΡΠ»ΠΈΡΡŒ, Π° Π½Π΅ ΠΎΡ‚Π²Π΅Ρ€Π³Π°Π»ΠΈΡΡŒ ΠΊΠ°ΠΊ синтаксичСскиС ошибки. ВсСго Π΄Π²Π΅ строки Π½ΡƒΠΆΠ½ΠΎ Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡ‚Π΅Π»ΡŒΠ½ΠΎ Π²ΠΊΠ»ΡŽΡ‡ΠΈΡ‚ΡŒ Π² hoc.y. ДобавляСтся новая лСксСма UNARYMINUS Π² Ρ‚Ρƒ Ρ‡Π°ΡΡ‚ΡŒ Π³Ρ€Π°ΠΌΠΌΠ°Ρ‚ΠΈΠΊΠΈ, Π³Π΄Π΅ Π·Π°Π΄Π°ΡŽΡ‚ΡΡ ΠΏΡ€ΠΈΠΎΡ€ΠΈΡ‚Π΅Ρ‚Ρ‹, Ρ‡Ρ‚ΠΎΠ±Ρ‹ ΡƒΠ½Π°Ρ€Π½Ρ‹ΠΉ минус ΠΈΠΌΠ΅Π» Π½Π°ΠΈΠ²Ρ‹ΡΡˆΠΈΠΉ ΠΏΡ€ΠΈΠΎΡ€ΠΈΡ‚Π΅Ρ‚:

%left '+' '-'

%left '*' '/'

%left UNARYMINUS /* новая лСксСма */

Π“Ρ€Π°ΠΌΠΌΠ°Ρ‚ΠΈΠΊΠ° увСличиваСтся Π½Π° ΠΎΠ΄Π½ΠΎ ΠΏΡ€Π°Π²ΠΈΠ»ΠΎ для expr:

expr: NUMBER ($$= $1;}

 | '-' expr %prec UNARYMINUS {$$=- $2} /* Π½ΠΎΠ²ΠΎΠ΅ */

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