Задание 3.
Выполним (используя лексер предыдущей лабораторной работы) логический парсер в соответствии с грамматикой из 5-6 лабораторных работ. (см. рисунок 3)
Рисунок 4 – Результат работы лексического анализатора
Рисунок 5 – Результат работы лексического анализатора 2
Листинг for_parser_simple.y:
%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int yylex(void);
void yyerror(const char *s);
extern FILE* yyin;
extern int yylineno;
extern char* yytext;
int debug = 0;
%}
%token FOR DO LPAREN RPAREN SEMICOLON ASSIGN
%token IDENTIFIER ROMAN COMP COMMENT
%token LT GT EQ // <, >, =
%%
program:
statements
;
statements:
/* empty */
| statements statement
;
statement:
for_stmt SEMICOLON
| comment SEMICOLON
| error SEMICOLON { yyerrok; }
;
for_stmt:
FOR LPAREN init SEMICOLON cond SEMICOLON inc RPAREN DO
{ printf("Found FOR loop\n"); }
;
init:
/* empty */ { printf("No init\n"); }
| IDENTIFIER ASSIGN expr { printf("Init: %s := ...\n", yytext); }
;
cond:
/* empty */ { printf("No cond\n"); }
| expr LT expr { printf("Cond: <\n"); }
| expr GT expr { printf("Cond: >\n"); }
| expr EQ expr { printf("Cond: =\n"); }
;
inc:
/* empty */ { printf("No inc\n"); }
| IDENTIFIER ASSIGN expr { printf("Inc: %s := ...\n", yytext); }
;
expr:
IDENTIFIER { printf("ID: %s\n", yytext); }
| ROMAN { printf("Roman: %s\n", yytext); }
;
comment:
COMMENT { printf("Comment\n"); }
;
%%
void yyerror(const char *s) {
fprintf(stderr, "Line %d: Error at '%s': %s\n", yylineno, yytext, s);
}
int main(int argc, char **argv) {
printf("=== Simple FOR parser ===\n");
if (argc > 1) {
yyin = fopen(argv[1], "r");
if (!yyin) {
fprintf(stderr, "Can't open %s\n", argv[1]);
return 1;
}
printf("Parsing file: %s\n", argv[1]);
}
return yyparse();
}
Листинг for_lexer.lex:
%{
#include "for_parser_simple.tab.h"
int yylineno = 1;
%}
%%
"for" { printf("Token: FOR\n"); return FOR; }
"do" { printf("Token: DO\n"); return DO; }
":=" { printf("Token: ASSIGN\n"); return ASSIGN; }
"<" { printf("Token: LT\n"); return LT; }
">" { printf("Token: GT\n"); return GT; }
"=" { printf("Token: EQ\n"); return EQ; }
"(" { printf("Token: LPAREN\n"); return LPAREN; }
")" { printf("Token: RPAREN\n"); return RPAREN; }
";" { printf("Token: SEMICOLON\n"); return SEMICOLON; }
/* Римские числа ДОЛЖНЫ идти ПЕРЕД идентификаторами! */
[IVXivx]+ {
printf("Token: ROMAN (%s)\n", yytext);
return ROMAN;
}
[a-zA-Z_][a-zA-Z0-9_]* {
printf("Token: IDENTIFIER (%s)\n", yytext);
return IDENTIFIER;
}
\{[^}]*\} {
printf("Token: COMMENT\n");
return COMMENT;
}
[ \t\n]+ /* skip whitespace */
. { printf("Unknown: %c\n", yytext[0]); }
%%
int yywrap() { return 1; }
