|
|
\_\_NOTOC\_\_ [ К основной странице курса](Страница_курса_"Методы_построения_компиляторов" "wikilink")
|
|
|
|
|
|
### Простой парсер выражений
|
|
|
|
|
|
Комплект для практического занятия [скачиваем отсюда](http://pascalabc.net/downloads/CompilerConstruction/GPPG_Pack2.zip).
|
|
|
|
|
|
Он содержит .y и .lex файлы, создающие компилятор перевода выражения со скобками в обратную польскую бесскобочную запись.
|
|
|
|
|
|
Для уяснения содержимого .y и .lex файлов необходимо иметь в виду следующее: эти файлы неразрывно связаны друг с другом, и информация, определенная в одном файле, используется в другом.
|
|
|
|
|
|
Разберемся в содержимом этих файлов и в том, как их компилировать.
|
|
|
|
|
|
- Поскольку gplex и gppg теперь работают вместе, gplex следует запускать без ключа /noparser, а gppg - с ключом /gplex
|
|
|
- **my.lex**
|
|
|
|
|
|
`{INTNUM} {return (int)Tokens.INTNUM;}`
|
|
|
|
|
|
Для каждой лексемы *обязательно* следует возвращать целое значение, характеризующее тип лексемы.
|
|
|
|
|
|
- Tokens - перечислимый тип с полями, задаваемыми в **myyacc.y**. Он формируется автоматически по записи
|
|
|
|
|
|
`%token INTNUM,REALNUM,ID`
|
|
|
|
|
|
- Приведем для примера одно из правил в **myyacc.y**:
|
|
|
|
|
|
`expr : expr PLUS T { Console.WriteLine(`“`+`”`); }`
|
|
|
` | T {}`
|
|
|
` ;`
|
|
|
|
|
|
Здесь лексема PLUS определена в файле **my.lex** Обратим также внимание на то, что правила во второй секции **myyacc.y** разделяются пустой строкой и если правило состоит более чем из одного подправила, то оно обязательно должно завершаться символом ;
|
|
|
|
|
|
- Определим лексему PLUS в файле **my.lex**:
|
|
|
|
|
|
`PLUS \+`
|
|
|
`%%`
|
|
|
`{PLUS} {return (int)Tokens.PLUS;}`
|
|
|
|
|
|
В файле **myyacc.y**:
|
|
|
|
|
|
`%token INTNUM,REALNUM,ID`
|
|
|
|
|
|
- В файле **myyacc.y**:
|
|
|
|
|
|
`F : INTNUM {Console.WriteLine($1);}`
|
|
|
|
|
|
- В файле **myyacc.y**:
|
|
|
|
|
|
`%union {`
|
|
|
` public int iVal;`
|
|
|
` public double dVal;`
|
|
|
` public string sVal;`
|
|
|
`}`
|
|
|
|
|
|
`%token `<iVal>` INTNUM`
|
|
|
|
|
|
В файле **my.lex**:
|
|
|
|
|
|
`{INTNUM} {`
|
|
|
` yylval.iVal = int.Parse(yytext); `
|
|
|
` return (int)Tokens.INTNUM;`
|
|
|
` }`
|
|
|
|
|
|
### Задания
|
|
|
|
|
|
- Разобраться в содержимом lex-файла
|
|
|
- Разобраться в содержимом и формате yacc-файла
|
|
|
- Добавить операции - /
|
|
|
- Добавить операцию % (остаток от целочисленного деления)
|
|
|
- Добавить в грамматику выражений в начале программы присваивания вида a=3;b=4; После всех присваиваний должно идти выражение. Выражение также может содержать указанные переменные: a=3;b=4;21\*a+b
|
|
|
|
|
|
<!-- -->
|
|
|
|
|
|
- Рассмотреть грамматику if then else и посмотреть на выдаваемую ошибку
|
|
|
- Рассмотреть модифицированную грамматику if then else и убедиться, что ошибки нет
|
|
|
|