cradle-compiler
/
program.pl
187 строк · 2.4 Кб
1#! /usr/bin/perl
2
3## Basic single-char syntax analyzer
4
5use strict;
6use warnings;
7
8my $look;
9
10# entry point
11sub main {
12&init();
13&expression();
14# if ($look ne "\r\n") {
15# &expected("New line");
16# }
17}
18
19sub init {
20&get_char();
21}
22
23## Lexer
24
25# Следующий символ
26sub get_char {
27$look = getc STDIN;
28}
29
30# Идентификатор
31sub get_name {
32if (!&is_alpha($look)) {
33&expected("Name");
34}
35
36my $result = uc $look;
37&get_char();
38$result;
39}
40
41# Число
42sub get_num {
43if (!&is_digit($look)) {
44&expected("Integer");
45}
46
47my $result = uc $look;
48&get_char();
49$result;
50}
51
52## Правила грамматики
53
54sub ident {
55my $name = &get_name();
56if ($look eq "(") {
57&match("(");
58&match(")");
59&emitln("BSR ${name}");
60} else {
61&emitln("MOVE " . &get_name() . "(PC),D0");
62}
63}
64
65sub factor {
66if ($look eq "(") {
67&match("(");
68&expression();
69&match(")");
70} elsif (&is_alpha($look)) {
71&ident();
72} else {
73&emitln("MOVE #" . &get_num() . ",D0");
74}
75}
76
77sub term {
78&factor();
79while ($look =~ /[*\/]/) {
80&emitln("MOVE D0,-(SP)");
81if ($look eq "*") {
82&multiply();
83} elsif ($look eq "/") {
84÷();
85} else {
86&expected("Mulop");
87}
88}
89}
90
91sub expression {
92if (&is_addop($look)) {
93&emitln("CLR D0"); # - вставить 0 в начало выражения для эмуляции унарных + -
94} else {
95&term();
96}
97
98while (&is_addop($look)) {
99&emitln("MOVE D0,-(SP)");
100if ($look eq "+") {
101&add();
102} elsif ($look eq "-") {
103&subtract();
104} else {
105&expected("Addop");
106}
107}
108}
109
110sub add {
111&match("+");
112&term();
113&emitln("ADD (SP)+,D0");
114}
115
116sub subtract {
117&match("-");
118&term();
119&emitln("SUB (SP)+,D0");
120&emitln("NEG D0");
121}
122
123sub multiply {
124&match("*");
125&factor();
126&emitln("MULS (SP)+,D0");
127}
128
129sub divide {
130&match("/");
131&factor();
132&emitln("MOVE (SP)+,D1");
133&emitln("DIVS D1,D0");
134}
135
136## Обработка ошибок
137
138sub expected {
139&abort("$_[0] Expected");
140}
141
142sub abort {
143&error($_[0]);
144exit 1;
145}
146
147sub error {
148print "\n[ERROR] $_[0].\n";
149}
150
151## private
152
153# Проверка обязательного символа
154sub match {
155my $x = $_[0];
156if ($look eq $x) {
157&get_char();
158} else {
159&expected("'${x}'");
160}
161}
162
163sub is_alpha {
164$_[0] =~ m/[A-Z]/i;
165}
166
167sub is_digit {
168$_[0] =~ /[0-9]/i;
169}
170
171sub is_addop {
172$_[0] =~ /[+-]/
173}
174
175# Возврат сформированной команды
176sub emit {
177print "\t $_[0]";
178}
179
180sub emitln {
181print "\t $_[0]\n";
182}
183
184## Script body
185
186main();
1871;
188