├── .gitignore
├── LICENSE
├── Makefile
├── README.md
├── src
├── ast_eeyore.cpp
├── ast_eeyore.h
├── ast_sysy.cpp
├── ast_sysy.h
├── ast_tigger.cpp
├── ast_tigger.h
├── eeyore.l
├── eeyore.y
├── lexer.l
├── main.cpp
├── parser.y
├── tigger.l
└── tigger.y
├── test.c
└── test.sh
/.gitignore:
--------------------------------------------------------------------------------
1 | *.DS_Store
2 | /build
3 | /.vscode
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 | Preamble
9 |
10 | The GNU General Public License is a free, copyleft license for
11 | software and other kinds of works.
12 |
13 | The licenses for most software and other practical works are designed
14 | to take away your freedom to share and change the works. By contrast,
15 | the GNU General Public License is intended to guarantee your freedom to
16 | share and change all versions of a program--to make sure it remains free
17 | software for all its users. We, the Free Software Foundation, use the
18 | GNU General Public License for most of our software; it applies also to
19 | any other work released this way by its authors. You can apply it to
20 | your programs, too.
21 |
22 | When we speak of free software, we are referring to freedom, not
23 | price. Our General Public Licenses are designed to make sure that you
24 | have the freedom to distribute copies of free software (and charge for
25 | them if you wish), that you receive source code or can get it if you
26 | want it, that you can change the software or use pieces of it in new
27 | free programs, and that you know you can do these things.
28 |
29 | To protect your rights, we need to prevent others from denying you
30 | these rights or asking you to surrender the rights. Therefore, you have
31 | certain responsibilities if you distribute copies of the software, or if
32 | you modify it: responsibilities to respect the freedom of others.
33 |
34 | For example, if you distribute copies of such a program, whether
35 | gratis or for a fee, you must pass on to the recipients the same
36 | freedoms that you received. You must make sure that they, too, receive
37 | or can get the source code. And you must show them these terms so they
38 | know their rights.
39 |
40 | Developers that use the GNU GPL protect your rights with two steps:
41 | (1) assert copyright on the software, and (2) offer you this License
42 | giving you legal permission to copy, distribute and/or modify it.
43 |
44 | For the developers' and authors' protection, the GPL clearly explains
45 | that there is no warranty for this free software. For both users' and
46 | authors' sake, the GPL requires that modified versions be marked as
47 | changed, so that their problems will not be attributed erroneously to
48 | authors of previous versions.
49 |
50 | Some devices are designed to deny users access to install or run
51 | modified versions of the software inside them, although the manufacturer
52 | can do so. This is fundamentally incompatible with the aim of
53 | protecting users' freedom to change the software. The systematic
54 | pattern of such abuse occurs in the area of products for individuals to
55 | use, which is precisely where it is most unacceptable. Therefore, we
56 | have designed this version of the GPL to prohibit the practice for those
57 | products. If such problems arise substantially in other domains, we
58 | stand ready to extend this provision to those domains in future versions
59 | of the GPL, as needed to protect the freedom of users.
60 |
61 | Finally, every program is threatened constantly by software patents.
62 | States should not allow patents to restrict development and use of
63 | software on general-purpose computers, but in those that do, we wish to
64 | avoid the special danger that patents applied to a free program could
65 | make it effectively proprietary. To prevent this, the GPL assures that
66 | patents cannot be used to render the program non-free.
67 |
68 | The precise terms and conditions for copying, distribution and
69 | modification follow.
70 |
71 | TERMS AND CONDITIONS
72 |
73 | 0. Definitions.
74 |
75 | "This License" refers to version 3 of the GNU General Public License.
76 |
77 | "Copyright" also means copyright-like laws that apply to other kinds of
78 | works, such as semiconductor masks.
79 |
80 | "The Program" refers to any copyrightable work licensed under this
81 | License. Each licensee is addressed as "you". "Licensees" and
82 | "recipients" may be individuals or organizations.
83 |
84 | To "modify" a work means to copy from or adapt all or part of the work
85 | in a fashion requiring copyright permission, other than the making of an
86 | exact copy. The resulting work is called a "modified version" of the
87 | earlier work or a work "based on" the earlier work.
88 |
89 | A "covered work" means either the unmodified Program or a work based
90 | on the Program.
91 |
92 | To "propagate" a work means to do anything with it that, without
93 | permission, would make you directly or secondarily liable for
94 | infringement under applicable copyright law, except executing it on a
95 | computer or modifying a private copy. Propagation includes copying,
96 | distribution (with or without modification), making available to the
97 | public, and in some countries other activities as well.
98 |
99 | To "convey" a work means any kind of propagation that enables other
100 | parties to make or receive copies. Mere interaction with a user through
101 | a computer network, with no transfer of a copy, is not conveying.
102 |
103 | An interactive user interface displays "Appropriate Legal Notices"
104 | to the extent that it includes a convenient and prominently visible
105 | feature that (1) displays an appropriate copyright notice, and (2)
106 | tells the user that there is no warranty for the work (except to the
107 | extent that warranties are provided), that licensees may convey the
108 | work under this License, and how to view a copy of this License. If
109 | the interface presents a list of user commands or options, such as a
110 | menu, a prominent item in the list meets this criterion.
111 |
112 | 1. Source Code.
113 |
114 | The "source code" for a work means the preferred form of the work
115 | for making modifications to it. "Object code" means any non-source
116 | form of a work.
117 |
118 | A "Standard Interface" means an interface that either is an official
119 | standard defined by a recognized standards body, or, in the case of
120 | interfaces specified for a particular programming language, one that
121 | is widely used among developers working in that language.
122 |
123 | The "System Libraries" of an executable work include anything, other
124 | than the work as a whole, that (a) is included in the normal form of
125 | packaging a Major Component, but which is not part of that Major
126 | Component, and (b) serves only to enable use of the work with that
127 | Major Component, or to implement a Standard Interface for which an
128 | implementation is available to the public in source code form. A
129 | "Major Component", in this context, means a major essential component
130 | (kernel, window system, and so on) of the specific operating system
131 | (if any) on which the executable work runs, or a compiler used to
132 | produce the work, or an object code interpreter used to run it.
133 |
134 | The "Corresponding Source" for a work in object code form means all
135 | the source code needed to generate, install, and (for an executable
136 | work) run the object code and to modify the work, including scripts to
137 | control those activities. However, it does not include the work's
138 | System Libraries, or general-purpose tools or generally available free
139 | programs which are used unmodified in performing those activities but
140 | which are not part of the work. For example, Corresponding Source
141 | includes interface definition files associated with source files for
142 | the work, and the source code for shared libraries and dynamically
143 | linked subprograms that the work is specifically designed to require,
144 | such as by intimate data communication or control flow between those
145 | subprograms and other parts of the work.
146 |
147 | The Corresponding Source need not include anything that users
148 | can regenerate automatically from other parts of the Corresponding
149 | Source.
150 |
151 | The Corresponding Source for a work in source code form is that
152 | same work.
153 |
154 | 2. Basic Permissions.
155 |
156 | All rights granted under this License are granted for the term of
157 | copyright on the Program, and are irrevocable provided the stated
158 | conditions are met. This License explicitly affirms your unlimited
159 | permission to run the unmodified Program. The output from running a
160 | covered work is covered by this License only if the output, given its
161 | content, constitutes a covered work. This License acknowledges your
162 | rights of fair use or other equivalent, as provided by copyright law.
163 |
164 | You may make, run and propagate covered works that you do not
165 | convey, without conditions so long as your license otherwise remains
166 | in force. You may convey covered works to others for the sole purpose
167 | of having them make modifications exclusively for you, or provide you
168 | with facilities for running those works, provided that you comply with
169 | the terms of this License in conveying all material for which you do
170 | not control copyright. Those thus making or running the covered works
171 | for you must do so exclusively on your behalf, under your direction
172 | and control, on terms that prohibit them from making any copies of
173 | your copyrighted material outside their relationship with you.
174 |
175 | Conveying under any other circumstances is permitted solely under
176 | the conditions stated below. Sublicensing is not allowed; section 10
177 | makes it unnecessary.
178 |
179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
180 |
181 | No covered work shall be deemed part of an effective technological
182 | measure under any applicable law fulfilling obligations under article
183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or
184 | similar laws prohibiting or restricting circumvention of such
185 | measures.
186 |
187 | When you convey a covered work, you waive any legal power to forbid
188 | circumvention of technological measures to the extent such circumvention
189 | is effected by exercising rights under this License with respect to
190 | the covered work, and you disclaim any intention to limit operation or
191 | modification of the work as a means of enforcing, against the work's
192 | users, your or third parties' legal rights to forbid circumvention of
193 | technological measures.
194 |
195 | 4. Conveying Verbatim Copies.
196 |
197 | You may convey verbatim copies of the Program's source code as you
198 | receive it, in any medium, provided that you conspicuously and
199 | appropriately publish on each copy an appropriate copyright notice;
200 | keep intact all notices stating that this License and any
201 | non-permissive terms added in accord with section 7 apply to the code;
202 | keep intact all notices of the absence of any warranty; and give all
203 | recipients a copy of this License along with the Program.
204 |
205 | You may charge any price or no price for each copy that you convey,
206 | and you may offer support or warranty protection for a fee.
207 |
208 | 5. Conveying Modified Source Versions.
209 |
210 | You may convey a work based on the Program, or the modifications to
211 | produce it from the Program, in the form of source code under the
212 | terms of section 4, provided that you also meet all of these conditions:
213 |
214 | a) The work must carry prominent notices stating that you modified
215 | it, and giving a relevant date.
216 |
217 | b) The work must carry prominent notices stating that it is
218 | released under this License and any conditions added under section
219 | 7. This requirement modifies the requirement in section 4 to
220 | "keep intact all notices".
221 |
222 | c) You must license the entire work, as a whole, under this
223 | License to anyone who comes into possession of a copy. This
224 | License will therefore apply, along with any applicable section 7
225 | additional terms, to the whole of the work, and all its parts,
226 | regardless of how they are packaged. This License gives no
227 | permission to license the work in any other way, but it does not
228 | invalidate such permission if you have separately received it.
229 |
230 | d) If the work has interactive user interfaces, each must display
231 | Appropriate Legal Notices; however, if the Program has interactive
232 | interfaces that do not display Appropriate Legal Notices, your
233 | work need not make them do so.
234 |
235 | A compilation of a covered work with other separate and independent
236 | works, which are not by their nature extensions of the covered work,
237 | and which are not combined with it such as to form a larger program,
238 | in or on a volume of a storage or distribution medium, is called an
239 | "aggregate" if the compilation and its resulting copyright are not
240 | used to limit the access or legal rights of the compilation's users
241 | beyond what the individual works permit. Inclusion of a covered work
242 | in an aggregate does not cause this License to apply to the other
243 | parts of the aggregate.
244 |
245 | 6. Conveying Non-Source Forms.
246 |
247 | You may convey a covered work in object code form under the terms
248 | of sections 4 and 5, provided that you also convey the
249 | machine-readable Corresponding Source under the terms of this License,
250 | in one of these ways:
251 |
252 | a) Convey the object code in, or embodied in, a physical product
253 | (including a physical distribution medium), accompanied by the
254 | Corresponding Source fixed on a durable physical medium
255 | customarily used for software interchange.
256 |
257 | b) Convey the object code in, or embodied in, a physical product
258 | (including a physical distribution medium), accompanied by a
259 | written offer, valid for at least three years and valid for as
260 | long as you offer spare parts or customer support for that product
261 | model, to give anyone who possesses the object code either (1) a
262 | copy of the Corresponding Source for all the software in the
263 | product that is covered by this License, on a durable physical
264 | medium customarily used for software interchange, for a price no
265 | more than your reasonable cost of physically performing this
266 | conveying of source, or (2) access to copy the
267 | Corresponding Source from a network server at no charge.
268 |
269 | c) Convey individual copies of the object code with a copy of the
270 | written offer to provide the Corresponding Source. This
271 | alternative is allowed only occasionally and noncommercially, and
272 | only if you received the object code with such an offer, in accord
273 | with subsection 6b.
274 |
275 | d) Convey the object code by offering access from a designated
276 | place (gratis or for a charge), and offer equivalent access to the
277 | Corresponding Source in the same way through the same place at no
278 | further charge. You need not require recipients to copy the
279 | Corresponding Source along with the object code. If the place to
280 | copy the object code is a network server, the Corresponding Source
281 | may be on a different server (operated by you or a third party)
282 | that supports equivalent copying facilities, provided you maintain
283 | clear directions next to the object code saying where to find the
284 | Corresponding Source. Regardless of what server hosts the
285 | Corresponding Source, you remain obligated to ensure that it is
286 | available for as long as needed to satisfy these requirements.
287 |
288 | e) Convey the object code using peer-to-peer transmission, provided
289 | you inform other peers where the object code and Corresponding
290 | Source of the work are being offered to the general public at no
291 | charge under subsection 6d.
292 |
293 | A separable portion of the object code, whose source code is excluded
294 | from the Corresponding Source as a System Library, need not be
295 | included in conveying the object code work.
296 |
297 | A "User Product" is either (1) a "consumer product", which means any
298 | tangible personal property which is normally used for personal, family,
299 | or household purposes, or (2) anything designed or sold for incorporation
300 | into a dwelling. In determining whether a product is a consumer product,
301 | doubtful cases shall be resolved in favor of coverage. For a particular
302 | product received by a particular user, "normally used" refers to a
303 | typical or common use of that class of product, regardless of the status
304 | of the particular user or of the way in which the particular user
305 | actually uses, or expects or is expected to use, the product. A product
306 | is a consumer product regardless of whether the product has substantial
307 | commercial, industrial or non-consumer uses, unless such uses represent
308 | the only significant mode of use of the product.
309 |
310 | "Installation Information" for a User Product means any methods,
311 | procedures, authorization keys, or other information required to install
312 | and execute modified versions of a covered work in that User Product from
313 | a modified version of its Corresponding Source. The information must
314 | suffice to ensure that the continued functioning of the modified object
315 | code is in no case prevented or interfered with solely because
316 | modification has been made.
317 |
318 | If you convey an object code work under this section in, or with, or
319 | specifically for use in, a User Product, and the conveying occurs as
320 | part of a transaction in which the right of possession and use of the
321 | User Product is transferred to the recipient in perpetuity or for a
322 | fixed term (regardless of how the transaction is characterized), the
323 | Corresponding Source conveyed under this section must be accompanied
324 | by the Installation Information. But this requirement does not apply
325 | if neither you nor any third party retains the ability to install
326 | modified object code on the User Product (for example, the work has
327 | been installed in ROM).
328 |
329 | The requirement to provide Installation Information does not include a
330 | requirement to continue to provide support service, warranty, or updates
331 | for a work that has been modified or installed by the recipient, or for
332 | the User Product in which it has been modified or installed. Access to a
333 | network may be denied when the modification itself materially and
334 | adversely affects the operation of the network or violates the rules and
335 | protocols for communication across the network.
336 |
337 | Corresponding Source conveyed, and Installation Information provided,
338 | in accord with this section must be in a format that is publicly
339 | documented (and with an implementation available to the public in
340 | source code form), and must require no special password or key for
341 | unpacking, reading or copying.
342 |
343 | 7. Additional Terms.
344 |
345 | "Additional permissions" are terms that supplement the terms of this
346 | License by making exceptions from one or more of its conditions.
347 | Additional permissions that are applicable to the entire Program shall
348 | be treated as though they were included in this License, to the extent
349 | that they are valid under applicable law. If additional permissions
350 | apply only to part of the Program, that part may be used separately
351 | under those permissions, but the entire Program remains governed by
352 | this License without regard to the additional permissions.
353 |
354 | When you convey a copy of a covered work, you may at your option
355 | remove any additional permissions from that copy, or from any part of
356 | it. (Additional permissions may be written to require their own
357 | removal in certain cases when you modify the work.) You may place
358 | additional permissions on material, added by you to a covered work,
359 | for which you have or can give appropriate copyright permission.
360 |
361 | Notwithstanding any other provision of this License, for material you
362 | add to a covered work, you may (if authorized by the copyright holders of
363 | that material) supplement the terms of this License with terms:
364 |
365 | a) Disclaiming warranty or limiting liability differently from the
366 | terms of sections 15 and 16 of this License; or
367 |
368 | b) Requiring preservation of specified reasonable legal notices or
369 | author attributions in that material or in the Appropriate Legal
370 | Notices displayed by works containing it; or
371 |
372 | c) Prohibiting misrepresentation of the origin of that material, or
373 | requiring that modified versions of such material be marked in
374 | reasonable ways as different from the original version; or
375 |
376 | d) Limiting the use for publicity purposes of names of licensors or
377 | authors of the material; or
378 |
379 | e) Declining to grant rights under trademark law for use of some
380 | trade names, trademarks, or service marks; or
381 |
382 | f) Requiring indemnification of licensors and authors of that
383 | material by anyone who conveys the material (or modified versions of
384 | it) with contractual assumptions of liability to the recipient, for
385 | any liability that these contractual assumptions directly impose on
386 | those licensors and authors.
387 |
388 | All other non-permissive additional terms are considered "further
389 | restrictions" within the meaning of section 10. If the Program as you
390 | received it, or any part of it, contains a notice stating that it is
391 | governed by this License along with a term that is a further
392 | restriction, you may remove that term. If a license document contains
393 | a further restriction but permits relicensing or conveying under this
394 | License, you may add to a covered work material governed by the terms
395 | of that license document, provided that the further restriction does
396 | not survive such relicensing or conveying.
397 |
398 | If you add terms to a covered work in accord with this section, you
399 | must place, in the relevant source files, a statement of the
400 | additional terms that apply to those files, or a notice indicating
401 | where to find the applicable terms.
402 |
403 | Additional terms, permissive or non-permissive, may be stated in the
404 | form of a separately written license, or stated as exceptions;
405 | the above requirements apply either way.
406 |
407 | 8. Termination.
408 |
409 | You may not propagate or modify a covered work except as expressly
410 | provided under this License. Any attempt otherwise to propagate or
411 | modify it is void, and will automatically terminate your rights under
412 | this License (including any patent licenses granted under the third
413 | paragraph of section 11).
414 |
415 | However, if you cease all violation of this License, then your
416 | license from a particular copyright holder is reinstated (a)
417 | provisionally, unless and until the copyright holder explicitly and
418 | finally terminates your license, and (b) permanently, if the copyright
419 | holder fails to notify you of the violation by some reasonable means
420 | prior to 60 days after the cessation.
421 |
422 | Moreover, your license from a particular copyright holder is
423 | reinstated permanently if the copyright holder notifies you of the
424 | violation by some reasonable means, this is the first time you have
425 | received notice of violation of this License (for any work) from that
426 | copyright holder, and you cure the violation prior to 30 days after
427 | your receipt of the notice.
428 |
429 | Termination of your rights under this section does not terminate the
430 | licenses of parties who have received copies or rights from you under
431 | this License. If your rights have been terminated and not permanently
432 | reinstated, you do not qualify to receive new licenses for the same
433 | material under section 10.
434 |
435 | 9. Acceptance Not Required for Having Copies.
436 |
437 | You are not required to accept this License in order to receive or
438 | run a copy of the Program. Ancillary propagation of a covered work
439 | occurring solely as a consequence of using peer-to-peer transmission
440 | to receive a copy likewise does not require acceptance. However,
441 | nothing other than this License grants you permission to propagate or
442 | modify any covered work. These actions infringe copyright if you do
443 | not accept this License. Therefore, by modifying or propagating a
444 | covered work, you indicate your acceptance of this License to do so.
445 |
446 | 10. Automatic Licensing of Downstream Recipients.
447 |
448 | Each time you convey a covered work, the recipient automatically
449 | receives a license from the original licensors, to run, modify and
450 | propagate that work, subject to this License. You are not responsible
451 | for enforcing compliance by third parties with this License.
452 |
453 | An "entity transaction" is a transaction transferring control of an
454 | organization, or substantially all assets of one, or subdividing an
455 | organization, or merging organizations. If propagation of a covered
456 | work results from an entity transaction, each party to that
457 | transaction who receives a copy of the work also receives whatever
458 | licenses to the work the party's predecessor in interest had or could
459 | give under the previous paragraph, plus a right to possession of the
460 | Corresponding Source of the work from the predecessor in interest, if
461 | the predecessor has it or can get it with reasonable efforts.
462 |
463 | You may not impose any further restrictions on the exercise of the
464 | rights granted or affirmed under this License. For example, you may
465 | not impose a license fee, royalty, or other charge for exercise of
466 | rights granted under this License, and you may not initiate litigation
467 | (including a cross-claim or counterclaim in a lawsuit) alleging that
468 | any patent claim is infringed by making, using, selling, offering for
469 | sale, or importing the Program or any portion of it.
470 |
471 | 11. Patents.
472 |
473 | A "contributor" is a copyright holder who authorizes use under this
474 | License of the Program or a work on which the Program is based. The
475 | work thus licensed is called the contributor's "contributor version".
476 |
477 | A contributor's "essential patent claims" are all patent claims
478 | owned or controlled by the contributor, whether already acquired or
479 | hereafter acquired, that would be infringed by some manner, permitted
480 | by this License, of making, using, or selling its contributor version,
481 | but do not include claims that would be infringed only as a
482 | consequence of further modification of the contributor version. For
483 | purposes of this definition, "control" includes the right to grant
484 | patent sublicenses in a manner consistent with the requirements of
485 | this License.
486 |
487 | Each contributor grants you a non-exclusive, worldwide, royalty-free
488 | patent license under the contributor's essential patent claims, to
489 | make, use, sell, offer for sale, import and otherwise run, modify and
490 | propagate the contents of its contributor version.
491 |
492 | In the following three paragraphs, a "patent license" is any express
493 | agreement or commitment, however denominated, not to enforce a patent
494 | (such as an express permission to practice a patent or covenant not to
495 | sue for patent infringement). To "grant" such a patent license to a
496 | party means to make such an agreement or commitment not to enforce a
497 | patent against the party.
498 |
499 | If you convey a covered work, knowingly relying on a patent license,
500 | and the Corresponding Source of the work is not available for anyone
501 | to copy, free of charge and under the terms of this License, through a
502 | publicly available network server or other readily accessible means,
503 | then you must either (1) cause the Corresponding Source to be so
504 | available, or (2) arrange to deprive yourself of the benefit of the
505 | patent license for this particular work, or (3) arrange, in a manner
506 | consistent with the requirements of this License, to extend the patent
507 | license to downstream recipients. "Knowingly relying" means you have
508 | actual knowledge that, but for the patent license, your conveying the
509 | covered work in a country, or your recipient's use of the covered work
510 | in a country, would infringe one or more identifiable patents in that
511 | country that you have reason to believe are valid.
512 |
513 | If, pursuant to or in connection with a single transaction or
514 | arrangement, you convey, or propagate by procuring conveyance of, a
515 | covered work, and grant a patent license to some of the parties
516 | receiving the covered work authorizing them to use, propagate, modify
517 | or convey a specific copy of the covered work, then the patent license
518 | you grant is automatically extended to all recipients of the covered
519 | work and works based on it.
520 |
521 | A patent license is "discriminatory" if it does not include within
522 | the scope of its coverage, prohibits the exercise of, or is
523 | conditioned on the non-exercise of one or more of the rights that are
524 | specifically granted under this License. You may not convey a covered
525 | work if you are a party to an arrangement with a third party that is
526 | in the business of distributing software, under which you make payment
527 | to the third party based on the extent of your activity of conveying
528 | the work, and under which the third party grants, to any of the
529 | parties who would receive the covered work from you, a discriminatory
530 | patent license (a) in connection with copies of the covered work
531 | conveyed by you (or copies made from those copies), or (b) primarily
532 | for and in connection with specific products or compilations that
533 | contain the covered work, unless you entered into that arrangement,
534 | or that patent license was granted, prior to 28 March 2007.
535 |
536 | Nothing in this License shall be construed as excluding or limiting
537 | any implied license or other defenses to infringement that may
538 | otherwise be available to you under applicable patent law.
539 |
540 | 12. No Surrender of Others' Freedom.
541 |
542 | If conditions are imposed on you (whether by court order, agreement or
543 | otherwise) that contradict the conditions of this License, they do not
544 | excuse you from the conditions of this License. If you cannot convey a
545 | covered work so as to satisfy simultaneously your obligations under this
546 | License and any other pertinent obligations, then as a consequence you may
547 | not convey it at all. For example, if you agree to terms that obligate you
548 | to collect a royalty for further conveying from those to whom you convey
549 | the Program, the only way you could satisfy both those terms and this
550 | License would be to refrain entirely from conveying the Program.
551 |
552 | 13. Use with the GNU Affero General Public License.
553 |
554 | Notwithstanding any other provision of this License, you have
555 | permission to link or combine any covered work with a work licensed
556 | under version 3 of the GNU Affero General Public License into a single
557 | combined work, and to convey the resulting work. The terms of this
558 | License will continue to apply to the part which is the covered work,
559 | but the special requirements of the GNU Affero General Public License,
560 | section 13, concerning interaction through a network will apply to the
561 | combination as such.
562 |
563 | 14. Revised Versions of this License.
564 |
565 | The Free Software Foundation may publish revised and/or new versions of
566 | the GNU General Public License from time to time. Such new versions will
567 | be similar in spirit to the present version, but may differ in detail to
568 | address new problems or concerns.
569 |
570 | Each version is given a distinguishing version number. If the
571 | Program specifies that a certain numbered version of the GNU General
572 | Public License "or any later version" applies to it, you have the
573 | option of following the terms and conditions either of that numbered
574 | version or of any later version published by the Free Software
575 | Foundation. If the Program does not specify a version number of the
576 | GNU General Public License, you may choose any version ever published
577 | by the Free Software Foundation.
578 |
579 | If the Program specifies that a proxy can decide which future
580 | versions of the GNU General Public License can be used, that proxy's
581 | public statement of acceptance of a version permanently authorizes you
582 | to choose that version for the Program.
583 |
584 | Later license versions may give you additional or different
585 | permissions. However, no additional obligations are imposed on any
586 | author or copyright holder as a result of your choosing to follow a
587 | later version.
588 |
589 | 15. Disclaimer of Warranty.
590 |
591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
599 |
600 | 16. Limitation of Liability.
601 |
602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
610 | SUCH DAMAGES.
611 |
612 | 17. Interpretation of Sections 15 and 16.
613 |
614 | If the disclaimer of warranty and limitation of liability provided
615 | above cannot be given local legal effect according to their terms,
616 | reviewing courts shall apply local law that most closely approximates
617 | an absolute waiver of all civil liability in connection with the
618 | Program, unless a warranty or assumption of liability accompanies a
619 | copy of the Program in return for a fee.
620 |
621 | END OF TERMS AND CONDITIONS
622 |
623 | How to Apply These Terms to Your New Programs
624 |
625 | If you develop a new program, and you want it to be of the greatest
626 | possible use to the public, the best way to achieve this is to make it
627 | free software which everyone can redistribute and change under these terms.
628 |
629 | To do so, attach the following notices to the program. It is safest
630 | to attach them to the start of each source file to most effectively
631 | state the exclusion of warranty; and each file should have at least
632 | the "copyright" line and a pointer to where the full notice is found.
633 |
634 |
635 | Copyright (C)
636 |
637 | This program is free software: you can redistribute it and/or modify
638 | it under the terms of the GNU General Public License as published by
639 | the Free Software Foundation, either version 3 of the License, or
640 | (at your option) any later version.
641 |
642 | This program is distributed in the hope that it will be useful,
643 | but WITHOUT ANY WARRANTY; without even the implied warranty of
644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
645 | GNU General Public License for more details.
646 |
647 | You should have received a copy of the GNU General Public License
648 | along with this program. If not, see .
649 |
650 | Also add information on how to contact you by electronic and paper mail.
651 |
652 | If the program does terminal interaction, make it output a short
653 | notice like this when it starts in an interactive mode:
654 |
655 | Copyright (C)
656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
657 | This is free software, and you are welcome to redistribute it
658 | under certain conditions; type `show c' for details.
659 |
660 | The hypothetical commands `show w' and `show c' should show the appropriate
661 | parts of the General Public License. Of course, your program's commands
662 | might be different; for a GUI interface, you would use an "about box".
663 |
664 | You should also get your employer (if you work as a programmer) or school,
665 | if any, to sign a "copyright disclaimer" for the program, if necessary.
666 | For more information on this, and how to apply and follow the GNU GPL, see
667 | .
668 |
669 | The GNU General Public License does not permit incorporating your program
670 | into proprietary programs. If your program is a subroutine library, you
671 | may consider it more useful to permit linking proprietary applications with
672 | the library. If this is what you want to do, use the GNU Lesser General
673 | Public License instead of this License. But first, please read
674 | .
675 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | # Based on https://matansilver.com/2017/08/29/universal-makefile/
2 | # Modified by MaxXing
3 |
4 | # Flags
5 | CFLAGS := -Wall -std=c11
6 | CXXFLAGS := -Wall -Wno-register -std=c++17
7 | FFLAGS :=
8 | BFLAGS := -d
9 | LDFLAGS :=
10 |
11 | # Debug flags
12 | DEBUG ?= 0
13 | ifeq ($(DEBUG), 0)
14 | CFLAGS += -g -O0
15 | CXXFLAGS += -g -O0
16 | else
17 | CFLAGS += -O2
18 | CXXFLAGS += -O2
19 | endif
20 |
21 | # Compilers
22 | CC := gcc
23 | CXX := g++
24 | FLEX := flex
25 | BISON := bison
26 |
27 | # Directories
28 | TOP_DIR := $(shell pwd)
29 | TARGET_EXEC := compiler
30 | BUILD_DIR ?= $(TOP_DIR)/build
31 | SRC_DIR := $(TOP_DIR)/src
32 |
33 | # Source files & target files
34 | FB_SRCS := $(patsubst $(SRC_DIR)/%.l, $(BUILD_DIR)/%.lex.cpp, $(shell find $(SRC_DIR) -name *.l))
35 | FB_SRCS += $(patsubst $(SRC_DIR)/%.y, $(BUILD_DIR)/%.tab.cpp, $(shell find $(SRC_DIR) -name *.y))
36 | SRCS := $(FB_SRCS) $(shell find $(SRC_DIR) -name *.c -or -name *.cpp -or -name *.cc)
37 | OBJS := $(patsubst $(BUILD_DIR)/%.c, $(BUILD_DIR)/%.c.o, $(SRCS))
38 | OBJS := $(patsubst $(BUILD_DIR)/%.cpp, $(BUILD_DIR)/%.cpp.o, $(OBJS))
39 | OBJS := $(patsubst $(BUILD_DIR)/%.cc, $(BUILD_DIR)/%.cc.o, $(OBJS))
40 | OBJS := $(patsubst $(SRC_DIR)/%.c, $(BUILD_DIR)/%.c.o, $(OBJS))
41 | OBJS := $(patsubst $(SRC_DIR)/%.cpp, $(BUILD_DIR)/%.cpp.o, $(OBJS))
42 | OBJS := $(patsubst $(SRC_DIR)/%.cc, $(BUILD_DIR)/%.cc.o, $(OBJS))
43 |
44 | # Header directories & dependencies
45 | INC_DIRS := $(shell find $(SRC_DIR) -type d)
46 | INC_DIRS += $(INC_DIRS:$(SRC_DIR)%=$(BUILD_DIR)%)
47 | INC_FLAGS := $(addprefix -I, $(INC_DIRS))
48 | DEPS := $(OBJS:.o=.d)
49 | CPPFLAGS = $(INC_FLAGS) -MMD -MP
50 |
51 |
52 | # Main target
53 | $(BUILD_DIR)/$(TARGET_EXEC): $(FB_SRCS) $(OBJS)
54 | $(CXX) $(LDFLAGS) $(OBJS) -o $@
55 |
56 | # C source
57 | $(BUILD_DIR)/%.c.o: $(SRC_DIR)/%.c
58 | mkdir -p $(dir $@)
59 | $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
60 |
61 | # C++ source
62 | define cxx_recipe
63 | mkdir -p $(dir $@)
64 | $(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $@
65 | endef
66 | $(BUILD_DIR)/%.cpp.o: $(SRC_DIR)/%.cpp; $(cxx_recipe)
67 | $(BUILD_DIR)/%.cpp.o: $(BUILD_DIR)/%.cpp; $(cxx_recipe)
68 | $(BUILD_DIR)/%.cc.o: $(SRC_DIR)/%.cc; $(cxx_recipe)
69 |
70 | # Flex
71 | $(BUILD_DIR)/%.lex.cpp: $(SRC_DIR)/%.l
72 | mkdir -p $(dir $@)
73 | $(FLEX) $(FFLAGS) -o $@ $<
74 |
75 | # Bison
76 | $(BUILD_DIR)/%.tab.cpp: $(SRC_DIR)/%.y
77 | mkdir -p $(dir $@)
78 | $(BISON) $(BFLAGS) -o $@ $<
79 |
80 |
81 | .PHONY: clean
82 |
83 | clean:
84 | -rm -rf $(BUILD_DIR)
85 |
86 | -include $(DEPS)
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/0x2d/mycompiler/fae0817009f5a141d94fb5b7fa3705dc955e0f79/README.md
--------------------------------------------------------------------------------
/src/ast_eeyore.cpp:
--------------------------------------------------------------------------------
1 | #include"ast_eeyore.h"
2 | #include
3 | #include
4 | #include"eeyore.tab.hpp"
5 |
6 | extern FILE *eeyorein;
7 | extern FILE *eeyoreout;
8 |
9 | std::vectorglobal_table;
10 | std::vectorfunctions;
11 | FUNC *func_ptr = nullptr;
12 | AST *root_eeyore;
13 | int param_i = 0;
14 |
15 | static void irgen(AST *th);
16 | static void irgen_decl(AST *th);
17 | static void irgen_func(AST *th);
18 | static void irgen_exp(AST *th);
19 |
20 | ENTRY *findvar(class FUNC *func, std::string id){
21 | if(func){
22 | for(int i=0;itable.size();i++){
23 | if(func->table[i]->id == id){
24 | return func->table[i];
25 | }
26 | }
27 | }
28 | for(int i=0;iid == id){
30 | return global_table[i];
31 | }
32 | }
33 | return nullptr;
34 | }
35 |
36 | FUNC *findfunc(std::string id){
37 | for(int i=0;iid == id){
39 | return functions[i];
40 | }
41 | }
42 | return nullptr;
43 | }
44 |
45 | static void irgen_exp(AST *th){
46 | if(th->son[0]->type == _RETURN && th->son.size() == 1){
47 | //"return";
48 | fprintf(eeyoreout," return\n");
49 | } else if(th->son[0]->type == _RETURN && th->son.size() == 2){
50 | //"return" RightValue
51 | if(th->son[1]->son[0]->type == _NUM){
52 | fprintf(eeyoreout," a0 = %d\n", th->son[1]->son[0]->val);
53 | } else{
54 | int s = th->son[1]->son[0]->entry->stack;
55 | if(th->son[1]->son[0]->entry->global){
56 | fprintf(eeyoreout," load v%d a0\n",s);
57 | } else{
58 | fprintf(eeyoreout," load %d a0\n",s);
59 | }
60 | }
61 | fprintf(eeyoreout," return\n");
62 | } else if(th->son[0]->type == _SYMBOL && th->son.size() == 2 && th->son[1]->type == _RightValue){
63 | //SYMBOL "=" RightValue
64 | if(th->son[1]->son[0]->type == _NUM){
65 | fprintf(eeyoreout," t1 = %d\n",th->son[1]->son[0]->val);
66 | } else{
67 | ENTRY *temp = th->son[1]->son[0]->entry;
68 | if(temp->global){
69 | if(temp->array){
70 | fprintf(eeyoreout," loadaddr v%d t1\n",temp->stack);
71 | }else{
72 | fprintf(eeyoreout," load v%d t1\n",temp->stack);
73 | }
74 | } else{
75 | if(temp->array){
76 | fprintf(eeyoreout," loadaddr %d t1\n",temp->stack);
77 | }else{
78 | fprintf(eeyoreout," load %d t1\n",temp->stack);
79 | }
80 | }
81 | }
82 | ENTRY *val1 = th->son[0]->entry;
83 | if(val1->global){
84 | fprintf(eeyoreout," loadaddr v%d t0\n",val1->stack);
85 | fprintf(eeyoreout," t0[0] = t1\n");
86 | } else{
87 | fprintf(eeyoreout," store t1 %d\n",val1->stack);
88 | }
89 | } else if(th->son[0]->type == _SYMBOL && th->son.size() == 3 && th->son[1]->type == _OP){
90 | //SYMBOL "=" OP RightValue
91 | if(th->son[2]->son[0]->type == _NUM){
92 | fprintf(eeyoreout," t1 = %d\n",th->son[2]->son[0]->val);
93 | } else{
94 | ENTRY *temp = th->son[2]->son[0]->entry;
95 | if(temp->global){
96 | if(temp->array){
97 | fprintf(eeyoreout," loadaddr v%d t1\n",temp->stack);
98 | }else{
99 | fprintf(eeyoreout," load v%d t1\n",temp->stack);
100 | }
101 | } else{
102 | if(temp->array){
103 | fprintf(eeyoreout," loadaddr %d t1\n",temp->stack);
104 | }else{
105 | fprintf(eeyoreout," load %d t1\n",temp->stack);
106 | }
107 | }
108 | }
109 | ENTRY *val1 = th->son[0]->entry;
110 | if(val1->global){
111 | fprintf(eeyoreout," loadaddr v%d t0\n",val1->stack);
112 | fprintf(eeyoreout," t0[0] = %s t1\n",th->son[1]->op.c_str());
113 | } else{
114 | fprintf(eeyoreout," t0 = %s t1\n",th->son[1]->op.c_str());
115 | fprintf(eeyoreout," store t0 %d\n",val1->stack);
116 | }
117 | } else if(th->son[0]->type == _SYMBOL && th->son.size() == 4 && th->son[2]->type == _BinOp){
118 | //SYMBOL "=" RightValue BinOp RightValue
119 | if(th->son[1]->son[0]->type == _NUM){
120 | fprintf(eeyoreout," t1 = %d\n",th->son[1]->son[0]->val);
121 | } else{
122 | ENTRY *temp = th->son[1]->son[0]->entry;
123 | if(temp->global){
124 | if(temp->array){
125 | fprintf(eeyoreout," loadaddr v%d t1\n",temp->stack);
126 | }else{
127 | fprintf(eeyoreout," load v%d t1\n",temp->stack);
128 | }
129 | } else{
130 | if(temp->array){
131 | fprintf(eeyoreout," loadaddr %d t1\n",temp->stack);
132 | }else{
133 | fprintf(eeyoreout," load %d t1\n",temp->stack);
134 | }
135 | }
136 | }
137 | std::string val3;
138 | if(th->son[3]->son[0]->type == _NUM){
139 | val3 = std::to_string(th->son[3]->son[0]->val);
140 | } else{
141 | ENTRY *temp = th->son[3]->son[0]->entry;
142 | if(temp->global){
143 | if(temp->array){
144 | fprintf(eeyoreout," loadaddr v%d t2\n",temp->stack);
145 | }else{
146 | fprintf(eeyoreout," load v%d t2\n",temp->stack);
147 | }
148 | } else{
149 | if(temp->array){
150 | fprintf(eeyoreout," loadaddr %d t2\n",temp->stack);
151 | }else{
152 | fprintf(eeyoreout," load %d t2\n",temp->stack);
153 | }
154 | }
155 | val3 = "t2";
156 | }
157 | ENTRY *val1 = th->son[0]->entry;
158 | if(val1->global){
159 | fprintf(eeyoreout," loadaddr v%d t0\n",val1->stack);
160 | fprintf(eeyoreout," t3 = t1 %s %s\n",th->son[2]->op.c_str(),val3.c_str());
161 | fprintf(eeyoreout," t0[0] = t3\n");
162 | } else{
163 | fprintf(eeyoreout," t0 = t1 %s %s\n",th->son[2]->op.c_str(),val3.c_str());
164 | fprintf(eeyoreout," store t0 %d\n",val1->stack);
165 | }
166 | } else if(th->son[0]->type == _SYMBOL && th->son.size() == 3 && th->son[1]->type == _RightValue){
167 | //SYMBOL "[" RightValue "]" "=" RightValue
168 | int val2 = th->son[1]->son[0]->val;
169 | if(th->son[2]->son[0]->type == _NUM){
170 | fprintf(eeyoreout," t1 = %d\n",th->son[2]->son[0]->val);
171 | } else{
172 | ENTRY *temp = th->son[2]->son[0]->entry;
173 | if(temp->global){
174 | if(temp->array){
175 | fprintf(eeyoreout," loadaddr v%d t1\n",temp->stack);
176 | }else{
177 | fprintf(eeyoreout," load v%d t1\n",temp->stack);
178 | }
179 | } else{
180 | if(temp->array){
181 | fprintf(eeyoreout," loadaddr %d t1\n",temp->stack);
182 | }else{
183 | fprintf(eeyoreout," load %d t1\n",temp->stack);
184 | }
185 | }
186 | }
187 | ENTRY *val1 = th->son[0]->entry;
188 | if(val1->global){
189 | fprintf(eeyoreout," loadaddr v%d t0\n",val1->stack);
190 | fprintf(eeyoreout," t0[%d] = t1\n",val2);
191 | } else{
192 | if(val1->array){
193 | fprintf(eeyoreout," loadaddr %d t0\n",val1->stack);
194 | } else{
195 | fprintf(eeyoreout," load %d t0\n",val1->stack);
196 | }
197 | fprintf(eeyoreout," t0[%d] = t1\n",val2);
198 | }
199 | } else if(th->son[0]->type == _SYMBOL && th->son.size() == 3 && th->son[1]->type == _SYMBOL){
200 | //SYMBOL "=" SYMBOL "[" RightValue "]"
201 | int val3 = th->son[2]->son[0]->val;
202 | ENTRY *temp = th->son[1]->entry;
203 | if(temp->global){
204 | fprintf(eeyoreout," loadaddr v%d t1\n",temp->stack);
205 | } else{
206 | if(temp->array){
207 | fprintf(eeyoreout," loadaddr %d t1\n",temp->stack);
208 | } else{
209 | fprintf(eeyoreout," load %d t1\n",temp->stack);
210 | }
211 | }
212 | ENTRY *val1 = th->son[0]->entry;
213 | if(val1->global){
214 | fprintf(eeyoreout," loadaddr v%d t0\n",val1->stack);
215 | fprintf(eeyoreout," t2 = t1[%d]\n",val3);
216 | fprintf(eeyoreout," t0[0] = t2\n");
217 | } else{
218 | fprintf(eeyoreout," t0 = t1[%d]\n",val3);
219 | fprintf(eeyoreout," store t0 %d\n",val1->stack);
220 | }
221 | } else if(th->son[0]->type == _IF){
222 | //"if" RightValue LOGICOP RightValue "goto" LABEL
223 | if(th->son[1]->son[0]->type == _NUM){
224 | fprintf(eeyoreout," t0 = %d\n",th->son[1]->son[0]->val);
225 | } else{
226 | int s = th->son[1]->son[0]->entry->stack;
227 | if(th->son[1]->son[0]->entry->global){
228 | fprintf(eeyoreout," load v%d t0\n",s);
229 | } else{
230 | fprintf(eeyoreout," load %d t0\n",s);
231 | }
232 | }
233 | if(th->son[3]->son[0]->type == _NUM){
234 | fprintf(eeyoreout," t1 = %d\n",th->son[3]->son[0]->val);
235 | } else{
236 | int s = th->son[3]->son[0]->entry->stack;
237 | if(th->son[3]->son[0]->entry->global){
238 | fprintf(eeyoreout," load v%d t1\n",s);
239 | } else{
240 | fprintf(eeyoreout," load %d t1\n",s);
241 | }
242 | }
243 | fprintf(eeyoreout," if t0 %s t1 goto %s\n",th->son[2]->op.c_str(),th->son[5]->id.c_str());
244 | } else if(th->son[0]->type == _GOTO){
245 | //"goto" LABEL
246 | fprintf(eeyoreout," goto %s\n",th->son[1]->id.c_str());
247 | } else if(th->son[0]->type == _LABEL){
248 | //LABEL ":"
249 | fprintf(eeyoreout,"%s:\n",th->son[0]->id.c_str());
250 | } else if(th->son[0]->type == _PARAM){
251 | //"param" RightValue
252 | if(th->son[1]->son[0]->type == _NUM){
253 | fprintf(eeyoreout," a%d = %d\n", param_i,th->son[1]->son[0]->val);
254 | } else{
255 | int s = th->son[1]->son[0]->entry->stack;
256 | if(th->son[1]->son[0]->entry->global){
257 | if(th->son[1]->son[0]->entry->array){
258 | fprintf(eeyoreout," loadaddr v%d a%d\n",s,param_i);
259 | } else{
260 | fprintf(eeyoreout," load v%d a%d\n",s,param_i);
261 | }
262 | } else{
263 | if(th->son[1]->son[0]->entry->array){
264 | fprintf(eeyoreout," loadaddr %d a%d\n",s,param_i);
265 | } else{
266 | fprintf(eeyoreout," load %d a%d\n",s,param_i);
267 | }
268 | }
269 | }
270 | param_i++;
271 | } else if(th->son[0]->type == _CALL){
272 | //"call" FUNCTION
273 | fprintf(eeyoreout," call %s\n",th->son[1]->id.c_str());
274 | param_i = 0;
275 | } else if(th->son[1]->type == _CALL){
276 | //SYMBOL "=" "call" FUNCTION
277 | fprintf(eeyoreout," call %s\n",th->son[2]->id.c_str());
278 | param_i = 0;
279 | ENTRY *val1 = th->son[0]->entry;
280 | if(val1->global){
281 | fprintf(eeyoreout," loadaddr v%d t0\n",val1->stack);
282 | fprintf(eeyoreout," t0[0] = a0\n");
283 | } else{
284 | fprintf(eeyoreout," store a0 %d\n",val1->stack);
285 | }
286 | }
287 | }
288 |
289 | static void irgen_func(AST *th){
290 | func_ptr = findfunc(th->son[0]->son[0]->id);
291 | fprintf(eeyoreout,"%s [%d] [%d]\n",func_ptr->id.c_str(),func_ptr->pnum,func_ptr->stack_size);
292 | for(int i=0;ipnum;i++){
293 | fprintf(eeyoreout," store a%d %d\n",i,i);
294 | }
295 | if(func_ptr->id == "f_main"){
296 | for(int i=0;iisinit){
298 | fprintf(eeyoreout," loadaddr v%d t0\n",global_table[i]->stack);
299 | for(int j=0;jsize;j+=4){
300 | fprintf(eeyoreout," t1 = %d\n",global_table[i]->init[j/4]);
301 | fprintf(eeyoreout," t0[%d] = t1\n", j);
302 | }
303 | }
304 | }
305 | }
306 | for(int i=0;ison[1]->son.size();i++){
307 | if(th->son[1]->son[i]->son[0]->type == _Expression){
308 | irgen_exp(th->son[1]->son[i]->son[0]);
309 | } else{
310 | irgen_decl(th->son[1]->son[i]->son[0]);
311 | }
312 | }
313 | fprintf(eeyoreout,"end %s\n",func_ptr->id.c_str());
314 | }
315 |
316 | static void irgen_decl(AST *th){
317 | if(!func_ptr){
318 | if(th->son.size() == 1){
319 | fprintf(eeyoreout,"v%d = %d\n",th->son[0]->entry->stack, th->son[0]->entry->val);
320 | } else{
321 | fprintf(eeyoreout,"v%d = malloc %d\n",th->son[1]->entry->stack,th->son[0]->val);
322 | }
323 | }
324 | }
325 |
326 | static void irgen(AST *th){
327 | func_ptr = nullptr;
328 | for(int i=0;ison.size();i++){
329 | if(th->son[i]->type == _Declaration){
330 | irgen_decl(th->son[i]);
331 | } else if(th->son[i]->type == _Initialization){
332 | ;
333 | } else if(th->son[i]->type == _FunctionDef){
334 | irgen_func(th->son[i]);
335 | }
336 | }
337 | }
338 |
339 | void codegen_tigger(char *input_file_path, char *output_file_path){
340 | FILE *input_file = fopen(input_file_path,"r");
341 | FILE *output_file = fopen(output_file_path,"w");
342 | eeyorein = input_file;
343 | eeyoreout = output_file;
344 |
345 | eeyoreparse();
346 | irgen(root_eeyore);
347 |
348 | fclose(input_file);
349 | fclose(output_file);
350 | eeyorein = stdin;
351 | eeyoreout = stdout;
352 | }
353 |
--------------------------------------------------------------------------------
/src/ast_eeyore.h:
--------------------------------------------------------------------------------
1 | #ifndef AST_EEYORE_H
2 | #define AST_EEYORE_H
3 |
4 | #include
5 | #include
6 |
7 | enum TYPE {
8 | _IF, _RETURN, _VAR, _NUM, _SYMBOL, _END, _FUNCTION, _LOGICOP, _OP, _GOTO, _LABEL, _PARAM, _CALL,
9 | _Program, _Declaration, _Initialization, _FunctionDef, _FunctionHeader, _Statements, _FunctionEnd,
10 | _Statement, _Expression, _RightValue, _BinOp
11 | };
12 |
13 | class ENTRY;
14 | class FUNC;
15 |
16 | class AST{
17 | public:
18 | AST() = default;
19 | AST(TYPE t):type(t){}
20 |
21 | std::vector son;
22 | TYPE type;
23 | std::string op;
24 | int val;
25 | std::string id;
26 | ENTRY *entry;
27 | };
28 |
29 | class ENTRY{
30 | public:
31 | ENTRY() = default;
32 | ENTRY(std::string i):id(i){
33 | this->reg = -1;
34 | this->isinit = false;
35 | this->global = false;
36 | this->array = false;
37 | }
38 |
39 | std::string id;
40 | bool global;
41 | bool array;
42 | int reg;
43 | int stack;
44 | int size;
45 | //用于初始化
46 | int val;
47 | int *init;
48 | bool isinit;
49 | };
50 |
51 | class FUNC{
52 | public:
53 | FUNC() = default;
54 | FUNC(std::string i, int p):id(i),pnum(p){
55 | this->stack_size = 0;
56 | }
57 |
58 | std::string id;
59 | int pnum;
60 | std::vectortable;
61 | int stack_size;
62 | };
63 |
64 | #endif
65 |
--------------------------------------------------------------------------------
/src/ast_sysy.cpp:
--------------------------------------------------------------------------------
1 | #include"ast_sysy.h"
2 | #include
3 | #include
4 | #include
5 | #include"parser.tab.hpp"
6 |
7 | extern FILE *sysyin;
8 | extern FILE *sysyout;
9 |
10 | AST *root_sysy;
11 | TABLE *root_symtable;
12 | std::vector symtable_vector;
13 | TABLE * symtable_ptr;
14 | int T_i = 0; //var
15 | int t_i = 0; //temp var
16 | int p_i = 0; //func var
17 | int indent = 0; //global indent
18 | int label = 0; //global label
19 | int symtable_i = 1; //下一个要打开的符号表编号
20 | int label_in_global; //最内层代码块的进入标号
21 | int label_out_global;
22 | bool wait_for_pointer = false; //用于判断对于数组的引用是否生成指针
23 |
24 | static void irgen(AST *th);
25 | static void irgen_Decl(AST *th);
26 | static void irgen_FuncDef(AST *th);
27 | static void irgen_Block(AST *th);
28 | static void irgen_Stmt(AST *th);
29 | static void irgen_ConstInitVal(AST *th, int addr, int layer, ENTRY_VAL *e);
30 | static void irgen_InitVal(AST *th, int addr, int layer, ENTRY_VAL *e);
31 | static std::string irgen_AddExp(AST *th);
32 | static std::string irgen_MulExp(AST *th);
33 | static std::string irgen_UnaryExp(AST *th);
34 | static std::string irgen_LVal(AST *th, bool isleft);
35 | static void irgen_LOrExp(AST *th, int label_true, int label_false);
36 | static void irgen_LAndExp(AST *th, int label_false);
37 | static std::string irgen_EqExp(AST *th);
38 | static std::string irgen_RelExp(AST *th);
39 |
40 | bool TABLE::Find(bool isVal, std::string id, bool recursive){
41 | if(isVal){
42 | for(int i=0;ival.size();i++){
43 | if(id == this->val[i]->id){
44 | return true;
45 | }
46 | }
47 | if(recursive){
48 | if(this != root_symtable){
49 | return this->father->Find(isVal,id,recursive);
50 | }
51 | }
52 | } else{
53 | for(int i=0;ifunc.size();i++){
54 | if(id == this->func[i]->id){
55 | return true;
56 | }
57 | }
58 | }
59 | return false;
60 | }
61 |
62 | ENTRY * TABLE::FindAndReturn(bool isVal, std::string id){
63 | if(isVal){
64 | for(int i=0;ival.size();i++){
65 | if(id == this->val[i]->id){
66 | return this->val[i];
67 | }
68 | }
69 | if(this != root_symtable){
70 | return this->father->FindAndReturn(isVal,id);
71 | }
72 | } else{
73 | for(int i=0;ifunc.size();i++){
74 | if(id == this->func[i]->id){
75 | return this->func[i];
76 | }
77 | }
78 | }
79 | }
80 |
81 | static void print_indent(){
82 | for(int indent_temp=0;indent_tempval.size();i++){
89 | if(table->val[i]->isParam){
90 | table->val[i]->eeyore_id = "p"+std::to_string(p_i);
91 | p_i++;
92 | } else{
93 | table->val[i]->eeyore_id = "T"+std::to_string(T_i);
94 | T_i++;
95 | if(table->val[i]->isArray){
96 | print_indent();
97 | fprintf(sysyout,"var %d %s\n", table->val[i]->size, table->val[i]->eeyore_id.c_str());
98 | } else{
99 | print_indent();
100 | fprintf(sysyout,"var %s\n", table->val[i]->eeyore_id.c_str());
101 | }
102 | }
103 | }
104 | if(table != root_symtable){
105 | for(int i=0;ison.size();i++){
106 | print_decl(table->son[i],0);
107 | }
108 | }
109 | int t_i_temp = t_i;
110 | for(int i=0;ison.size() == 1){
120 | return ((ENTRY_VAL *)th->son[0]->entry)->eeyore_id;
121 | } else{
122 | std::string val1, val2, val3;
123 | ENTRY_VAL *entry_temp = (ENTRY_VAL *)th->son[0]->entry;
124 | int size_temp = entry_temp->size;
125 | val1 = "t"+std::to_string(t_i);
126 | t_i++;
127 | if(th->son.size() > 2){
128 | val3 = "t"+std::to_string(t_i);
129 | t_i++;
130 | }
131 | for(int i=1;ison.size();i++){
132 | size_temp /= entry_temp->shape[i-1];
133 | val2 = irgen_AddExp(th->son[i]->son[0]);
134 | if(i==1){
135 | print_indent();
136 | fprintf(sysyout,"%s = %s * %d\n",val1.c_str(),val2.c_str(),size_temp);
137 | } else{
138 | print_indent();
139 | fprintf(sysyout,"%s = %s * %d\n",val3.c_str(),val2.c_str(),size_temp);
140 | print_indent();
141 | fprintf(sysyout,"%s = %s + %s\n",val1.c_str(),val1.c_str(),val3.c_str());
142 | }
143 | }
144 | print_indent();
145 | fprintf(sysyout,"%s = %s + %s\n",val1.c_str(),entry_temp->eeyore_id.c_str(),val1.c_str());
146 | if(wait_for_pointer){
147 | return val1;
148 | }
149 | if(isleft){
150 | return val1+"[0]";
151 | } else{
152 | print_indent();
153 | fprintf(sysyout,"%s = %s[0]\n",val1.c_str(),val1.c_str());
154 | return val1;
155 | }
156 | }
157 | }
158 |
159 | static std::string irgen_UnaryExp(AST *th){
160 | std::string val1, val2;
161 | if(th->son[0]->type == _PrimaryExp){
162 | AST *ptr = th->son[0]; //PrimaryExp
163 | if(ptr->son[0]->type == _INT_CONST){
164 | val1 = std::to_string(ptr->son[0]->val);
165 | } else if(ptr->son[0]->type == _LVal){
166 | val1 = irgen_LVal(ptr->son[0],false);
167 | } else{
168 | val1 = irgen_AddExp(ptr->son[0]->son[0]);
169 | }
170 | } else if(th->son[0]->type == _UnaryOp){
171 | if(th->son[0]->son[0]->op != '+'){
172 | val1 = "t"+std::to_string(t_i);
173 | t_i++;
174 | val2 = irgen_UnaryExp(th->son[1]);
175 | print_indent();
176 | fprintf(sysyout,"%s = %c %s\n",val1.c_str(),th->son[0]->son[0]->op,val2.c_str());
177 | } else{
178 | val1 = irgen_UnaryExp(th->son[1]);
179 | }
180 | } else if(th->son[0]->type == _IDENT){
181 | if(root_symtable->Find(false,th->son[0]->id,false)){
182 | th->son[0]->entry = root_symtable->FindAndReturn(false,th->son[0]->id);
183 | }
184 | ENTRY_FUNC *func_temp = (ENTRY_FUNC *)th->son[0]->entry;
185 | if(th->son.size() == 2){
186 | int param_num = th->son[1]->son.size();
187 | std::string params[param_num];
188 | for(int i=0;isymtable){
190 | std::string p_temp = "p"+std::to_string(i);
191 | for(int j=0;jsymtable->val.size();j++){
192 | if(func_temp->symtable->val[j]->isParam && p_temp == func_temp->symtable->val[j]->eeyore_id){
193 | wait_for_pointer = func_temp->symtable->val[j]->isArray;
194 | }
195 | }
196 | } else{
197 | if((func_temp->id == "getarray" && i == 0)
198 | || (func_temp->id == "putarray" == 0 && i == 1)){
199 | wait_for_pointer = true;
200 | }
201 | }
202 | val1 = irgen_AddExp(th->son[1]->son[i]->son[0]);
203 | wait_for_pointer = false;
204 | params[i] = val1;
205 | }
206 | for(int i=0;iisreturn){
211 | val1 = "t"+std::to_string(t_i);
212 | t_i++;
213 | fprintf(sysyout," %s = call f_%s\n",val1.c_str(),func_temp->id.c_str());
214 | } else{
215 | t_i++;
216 | if(func_temp->id == "starttime"){
217 | fprintf(sysyout," param %d\n", th->lineno);
218 | fprintf(sysyout," call f__sysy_starttime\n");
219 | } else if(func_temp->id == "stoptime"){
220 | fprintf(sysyout," param %d\n", th->lineno);
221 | fprintf(sysyout," call f__sysy_stoptime\n");
222 | } else{
223 | fprintf(sysyout," call f_%s\n",func_temp->id.c_str());
224 | }
225 | }
226 | }
227 | return val1;
228 | }
229 |
230 | static std::string irgen_MulExp(AST *th){
231 | std::string val1, val2, val3;
232 | val1 = irgen_UnaryExp(th->son[0]);
233 | if(th->son.size() == 1){
234 | return val1;
235 | } else{
236 | val3 = "t"+std::to_string(t_i);
237 | t_i++;
238 | for(int i=1;ison.size();i+=2){
239 | val2 = irgen_UnaryExp(th->son[i+1]);
240 | if(i == 1){
241 | print_indent();
242 | fprintf(sysyout,"%s = %s %c %s\n",val3.c_str(), val1.c_str(),th->son[i]->op,val2.c_str());
243 | } else{
244 | print_indent();
245 | fprintf(sysyout,"%s = %s %c %s\n",val3.c_str(), val3.c_str(),th->son[i]->op,val2.c_str());
246 | }
247 | }
248 | return val3;
249 | }
250 | }
251 |
252 | static std::string irgen_AddExp(AST *th){
253 | std::string val1, val2, val3;
254 | val1 = irgen_MulExp(th->son[0]);
255 | if(th->son.size() == 1){
256 | return val1;
257 | } else{
258 | val3 = "t"+std::to_string(t_i);
259 | t_i++;
260 | for(int i=1; i < th->son.size(); i+=2){
261 | val2 = irgen_MulExp(th->son[i+1]);
262 | if(i == 1){
263 | print_indent();
264 | fprintf(sysyout,"%s = %s %c %s\n",val3.c_str(), val1.c_str(),th->son[i]->op,val2.c_str());
265 | } else{
266 | print_indent();
267 | fprintf(sysyout,"%s = %s %c %s\n",val3.c_str(), val3.c_str(),th->son[i]->op,val2.c_str());
268 | }
269 | }
270 | return val3;
271 | }
272 | }
273 |
274 | static void irgen_InitVal(AST *th, int addr, int layer, ENTRY_VAL *e){
275 | int nval = e->size/4;
276 | int nval_temp = 0;
277 | for(int i=0;ishape[i];
279 | }
280 | for(int i=0;ison.size();i++){
281 | if(th->son[i]->son.size() == 0){
282 | irgen_InitVal(th->son[i], addr,layer+1,e);
283 | nval_temp += nval/e->shape[layer];
284 | addr += nval/e->shape[layer]*4;
285 | } else if(th->son[i]->son[0]->type == _Exp){
286 | if(symtable_ptr == root_symtable){
287 | print_indent();
288 | fprintf(sysyout,"%s[%d] = %d\n", e->eeyore_id.c_str(), addr, th->son[i]->son[0]->val);
289 | addr += 4;
290 | nval_temp++;
291 | } else{
292 | std::string init_temp = irgen_AddExp(th->son[i]->son[0]->son[0]);
293 | print_indent();
294 | fprintf(sysyout,"%s[%d] = %s\n", e->eeyore_id.c_str(), addr, init_temp.c_str());
295 | addr += 4;
296 | nval_temp++;
297 | }
298 | } else{
299 | irgen_InitVal(th->son[i],addr,layer+1,e);
300 | nval_temp += nval/e->shape[layer];
301 | addr += nval/e->shape[layer]*4;
302 | }
303 | }
304 | for(;nval_tempeeyore_id.c_str(), addr);
307 | addr += 4;
308 | }
309 | }
310 |
311 | static void irgen_ConstInitVal(AST *th, int addr, int layer, ENTRY_VAL *e){
312 | int nval = e->size/4;
313 | int nval_temp = 0;
314 | for(int i=0;ishape[i];
316 | }
317 | for(int i=0;ison.size();i++){
318 | if(th->son[i]->son.size() == 0){
319 | irgen_ConstInitVal(th->son[i],addr,layer+1,e);
320 | nval_temp += nval/e->shape[layer];
321 | addr += nval/e->shape[layer]*4;
322 | } else if(th->son[i]->son[0]->type == _ConstExp){
323 | int init_temp = th->son[i]->son[0]->val;
324 | //e->arr[nval_temp] = init_temp;
325 | print_indent();
326 | fprintf(sysyout,"%s[%d] = %d\n", e->eeyore_id.c_str(), addr, init_temp);
327 | addr += 4;
328 | nval_temp++;
329 | } else{
330 | irgen_ConstInitVal(th->son[i], addr,layer+1,e);
331 | nval_temp += nval/e->shape[layer];
332 | addr += nval/e->shape[layer]*4;
333 | }
334 | }
335 | for(;nval_temparr[nval_temp] = 0;
337 | print_indent();
338 | fprintf(sysyout,"%s[%d] = 0\n", e->eeyore_id.c_str(), addr);
339 | addr += 4;
340 | }
341 | }
342 |
343 | static std::string irgen_RelExp(AST *th){
344 | std::string val1, val2, val3, op;
345 | val1 = irgen_AddExp(th->son[0]);
346 | if(th->son.size() == 1){
347 | return val1;
348 | } else{
349 | val3 = "t"+std::to_string(t_i);
350 | t_i++;
351 | for(int i=1; i < th->son.size(); i+=2){
352 | if(th->son[i]->type == _LE){
353 | op = "<=";
354 | } else if(th->son[i]->type == _GE){
355 | op = ">=";
356 | } else{
357 | op = th->son[i]->op;
358 | }
359 | val2 = irgen_AddExp(th->son[i+1]);
360 | if(i == 1){
361 | fprintf(sysyout," %s = %s %s %s\n",val3.c_str(), val1.c_str(),op.c_str(),val2.c_str());
362 | } else{
363 | fprintf(sysyout," %s = %s %s %s\n",val3.c_str(), val3.c_str(),op.c_str(),val2.c_str());
364 | }
365 | }
366 | return val3;
367 | }
368 | }
369 |
370 | static std::string irgen_EqExp(AST *th){
371 | std::string val1, val2, val3, op;
372 | val1 = irgen_RelExp(th->son[0]);
373 | if(th->son.size() == 1){
374 | return val1;
375 | } else{
376 | val3 = "t"+std::to_string(t_i);
377 | t_i++;
378 | for(int i=1; i < th->son.size(); i+=2){
379 | if(th->son[i]->type == _EQ){
380 | op = "==";
381 | } else{
382 | op = "!=";
383 | }
384 | val2 = irgen_RelExp(th->son[i+1]);
385 | if(i == 1){
386 | fprintf(sysyout," %s = %s %s %s\n",val3.c_str(), val1.c_str(),op.c_str(),val2.c_str());
387 | } else{
388 | fprintf(sysyout," %s = %s %s %s\n",val3.c_str(), val3.c_str(),op.c_str(),val2.c_str());
389 | }
390 | }
391 | return val3;
392 | }
393 | }
394 |
395 | static void irgen_LAndExp(AST *th, int label_false){
396 | std::string val1;
397 | for(int i=0;i< th->son.size();i+=2){
398 | val1 = irgen_EqExp(th->son[i]);
399 | fprintf(sysyout," if %s == 0 goto l%d\n",val1.c_str(),label_false);
400 | }
401 | }
402 |
403 | static void irgen_LOrExp(AST *th, int label_true, int label_false){
404 | int size_temp = th->son.size();
405 | for(int i=0;i< size_temp;i+=2){
406 | if(i+2 < size_temp){
407 | irgen_LAndExp(th->son[i], label);
408 | fprintf(sysyout," goto l%d\n",label_true);
409 | fprintf(sysyout,"l%d:\n",label);
410 | label++;
411 | } else{
412 | irgen_LAndExp(th->son[i], label_false);
413 | }
414 | }
415 | }
416 |
417 | static void irgen_Stmt(AST *th){
418 | if(th->son.size() == 0){
419 | //';'
420 | return;
421 | }
422 | if(th->son[0]->type == _RETURN){
423 | if(th->son.size() == 1){
424 | //RETURN ';'
425 | fprintf(sysyout," return\n");
426 | } else{
427 | //RETURN Exp ';'
428 | std::string return_temp = irgen_AddExp(th->son[1]->son[0]);
429 | fprintf(sysyout," return %s\n",return_temp.c_str());
430 | }
431 | } else if(th->son[0]->type == _LVal){
432 | //LVal '=' Exp ';'
433 | std::string left_temp = irgen_LVal(th->son[0],true);
434 | std::string right_temp = irgen_AddExp(th->son[1]->son[0]);
435 | fprintf(sysyout," %s = %s\n",left_temp.c_str(),right_temp.c_str());
436 | } else if(th->son[0]->type == _Exp){
437 | //Exp ';'
438 | irgen_AddExp(th->son[0]->son[0]);
439 | } else if(th->son[0]->type == _Block){
440 | //Block
441 | irgen_Block(th->son[0]);
442 | } else if(th->son[0]->type == _WHILE){
443 | //WHILE '(' Cond ')' Stmt
444 | int label_in_temp = label_in_global;
445 | int label_out_temp = label_out_global;
446 | th->label_in = label;
447 | th->label_in2 = label+1;
448 | th->label_out = label+2;
449 | label += 3;
450 | label_in_global = th->label_in;
451 | label_out_global = th->label_out;
452 | fprintf(sysyout,"l%d:\n",th->label_in);
453 | irgen_LOrExp(th->son[1]->son[0], th->label_in2, th->label_out);
454 | fprintf(sysyout,"l%d:\n",th->label_in2);
455 | irgen_Stmt(th->son[2]);
456 | fprintf(sysyout," goto l%d\n",th->label_in);
457 | fprintf(sysyout,"l%d:\n",th->label_out);
458 | label_in_global = label_in_temp;
459 | label_out_global = label_out_temp;
460 | } else if(th->son[0]->type == _IF && th->son.size() == 5){
461 | //IF '(' Cond ')' Stmt ELSE Stmt
462 | th->label_in = label;
463 | th->label_in2 = label+1;
464 | th->label_out = label+2;
465 | label += 3;
466 | irgen_LOrExp(th->son[1]->son[0],th->label_in,th->label_in2);
467 | fprintf(sysyout,"l%d:\n",th->label_in);
468 | irgen_Stmt(th->son[2]);
469 | fprintf(sysyout," goto l%d\n",th->label_out);
470 | fprintf(sysyout,"l%d:\n",th->label_in2);
471 | irgen_Stmt(th->son[4]);
472 | fprintf(sysyout,"l%d:\n",th->label_out);
473 | } else if(th->son[0]->type == _IF && th->son.size() == 3){
474 | //IF '(' Cond ')' Stmt
475 | th->label_in = label;
476 | th->label_out = label+1;
477 | label += 2;
478 | irgen_LOrExp(th->son[1]->son[0], th->label_in,th->label_out);
479 | fprintf(sysyout,"l%d:\n",th->label_in);
480 | irgen_Stmt(th->son[2]);
481 | fprintf(sysyout,"l%d:\n",th->label_out);
482 | } else if(th->son[0]->type == _BREAK){
483 | //BREAK ';'
484 | fprintf(sysyout," goto l%d\n",label_out_global);
485 | } else if(th->son[0]->type == _CONTINUE){
486 | //CONTINUE ';'
487 | fprintf(sysyout," goto l%d\n",label_in_global);
488 | }
489 | }
490 |
491 | static void irgen_Block(AST *th){
492 | symtable_ptr = symtable_vector[symtable_i];
493 | symtable_i++;
494 | for(int i=0;ison.size();i++){
495 | if(th->son[i]->son[0]->type == _Decl){
496 | irgen_Decl(th->son[i]->son[0]);
497 | } else{
498 | irgen_Stmt(th->son[i]->son[0]);
499 | }
500 | }
501 | symtable_ptr = symtable_ptr->father;
502 | }
503 |
504 | static void irgen_FuncDef(AST *th){
505 | ENTRY_FUNC *func_ptr = (ENTRY_FUNC *)th->son[1]->entry;
506 | fprintf(sysyout,"f_%s [%d]\n",func_ptr->id.c_str(), func_ptr->NumberOfParam);
507 | indent++;
508 | p_i = 0;
509 | print_decl(func_ptr->symtable,func_ptr->NumberOfTemp);
510 | irgen_Block(th->son[th->son.size()-1]);
511 | if(func_ptr->isreturn){
512 | fprintf(sysyout," return 0\n");
513 | } else{
514 | fprintf(sysyout," return\n");
515 | }
516 | indent--;
517 | fprintf(sysyout,"end f_%s\n",th->son[1]->id.c_str());
518 | }
519 |
520 | static void irgen_Decl(AST *th){
521 | AST *ptr = th->son[0];
522 | if(ptr->type == _VarDecl){
523 | ptr = ptr->son[1]; //VarDef_temp
524 | for(int i=0;ison.size();i++){
525 | AST *ptr_temp = ptr->son[i]; //VarDef
526 | ENTRY_VAL *entry_temp = (ENTRY_VAL *)ptr_temp->son[0]->entry;
527 | if(ptr_temp->son[1]->son.size() == 0){
528 | if(ptr_temp->son.size() > 2){
529 | if(symtable_ptr == root_symtable){
530 | entry_temp->val = ptr_temp->son[2]->son[0]->val;
531 | print_indent();
532 | fprintf(sysyout,"%s = %d\n", entry_temp->eeyore_id.c_str(), entry_temp->val);
533 | } else{
534 | std::string val_temp = irgen_AddExp(ptr_temp->son[2]->son[0]->son[0]);
535 | print_indent();
536 | fprintf(sysyout,"%s = %s\n", entry_temp->eeyore_id.c_str(), val_temp.c_str());
537 | }
538 | } else{
539 | if(symtable_ptr == root_symtable){
540 | entry_temp->val = 0;
541 | }
542 | }
543 | } else {
544 | if(ptr_temp->son.size() > 2){
545 | //entry_temp->arr = new int [entry_temp->size/4];
546 | irgen_InitVal(ptr_temp->son[2], 0, 0, entry_temp);
547 | }
548 | }
549 | }
550 | } else if(ptr->type == _ConstDecl){
551 | ptr = ptr->son[2]; //ConstDef_temp
552 | for(int i=0;ison.size();i++){
553 | AST *ptr_temp = ptr->son[i]; //ConstDef
554 | ENTRY_VAL *entry_temp = (ENTRY_VAL *)ptr_temp->son[0]->entry;
555 | if(ptr_temp->son[1]->son.size() == 0){
556 | entry_temp->val = ptr_temp->son[2]->son[0]->val;
557 | print_indent();
558 | fprintf(sysyout,"%s = %d\n", entry_temp->eeyore_id.c_str(), entry_temp->val);
559 | } else {
560 | if(ptr_temp->son.size() > 2){
561 | //entry_temp->arr = new int [entry_temp->size/4];
562 | irgen_ConstInitVal(ptr_temp->son[2], 0, 0, entry_temp);
563 | }
564 | }
565 | }
566 | }
567 | }
568 |
569 | static void irgen(AST *th){
570 | print_decl(root_symtable, 0);
571 | for(int i=0;ison.size();i++){
572 | if(th->son[i]->type==_Decl){
573 | irgen_Decl(th->son[i]);
574 | } else if(th->son[i]->type==_FuncDef){
575 | irgen_FuncDef(th->son[i]);
576 | }
577 | }
578 | }
579 |
580 | void codegen_eeyore(char *input_file_path, char *output_file_path){
581 | FILE *input_file = fopen(input_file_path,"r");
582 | FILE *output_file = fopen(output_file_path,"w");
583 | sysyin = input_file;
584 | sysyout = output_file;
585 |
586 | root_symtable = new TABLE("root");
587 | symtable_vector.push_back(root_symtable);
588 | symtable_ptr = root_symtable;
589 | new ENTRY_FUNC("getint",root_symtable,true,nullptr,0,0);
590 | new ENTRY_FUNC("getch",root_symtable,true,nullptr,0,0);
591 | new ENTRY_FUNC("getarray",root_symtable,true,nullptr,0,1);
592 | new ENTRY_FUNC("putint",root_symtable,false,nullptr,0,1);
593 | new ENTRY_FUNC("putch",root_symtable,false,nullptr,0,1);
594 | new ENTRY_FUNC("putarray",root_symtable,false,nullptr,0,2);
595 | new ENTRY_FUNC("starttime",root_symtable,false,nullptr,0,0);
596 | new ENTRY_FUNC("stoptime",root_symtable,false,nullptr,0,0);
597 | sysyparse();
598 | irgen(root_sysy);
599 |
600 | fclose(input_file);
601 | fclose(output_file);
602 | sysyin = stdin;
603 | sysyout = stdout;
604 | }
605 |
--------------------------------------------------------------------------------
/src/ast_sysy.h:
--------------------------------------------------------------------------------
1 | #ifndef AST_SYSY_H
2 | #define AST_SYSY_H
3 |
4 | #include
5 | #include
6 |
7 | class ENTRY;
8 | class ENTRY_VAL;
9 | class ENTRY_FUNC;
10 | class TABLE;
11 |
12 | enum TYPE {
13 | _INT, _VOID, _CONST, _IF, _ELSE, _WHILE, _BREAK, _CONTINUE, _RETURN, _LE,
14 | _GE, _EQ, _NE, _AND, _OR, _IDENT, _INT_CONST, _OP, _CompUnit,
15 | _Decl, _ConstDecl, _ConstDef_temp, _BType, _ConstDef, _ConstExp_temp, _ConstInitVal, _ConstInitVal_temp, _VarDecl, _VarDef_temp,
16 | _VarDef, _InitVal, _InitVal_temp, _FuncDef, _FuncFParams, _FuncFParam, _Block, _BlockItem_temp, _BlockItem, _Stmt,
17 | _Exp, _Cond, _LVal, _PrimaryExp, _Number, _UnaryExp, _UnaryOp, _FuncRParams, _MulExp, _AddExp, _RelExp,
18 | _EqExp, _LAndExp, _LOrExp, _ConstExp
19 | };
20 |
21 | class AST{
22 | public:
23 | AST() = default;
24 | AST(TYPE t):type(t){}
25 | AST(TYPE t, char o):type(t), op(o) {}
26 | AST(TYPE t, int v):type(t), val(v) {}
27 |
28 | std::vector son;
29 | TYPE type;
30 | char op;
31 | int val;
32 | std::string id;
33 | ENTRY *entry;
34 | int lineno;
35 | bool isint = false; //尚未实现
36 | int label_in;
37 | int label_in2;
38 | int label_out;
39 | };
40 |
41 | class ENTRY{
42 | public:
43 | ENTRY() = default;
44 | ENTRY(std::string i, TABLE *t): id(i), table(t) {};
45 |
46 | std::string id;
47 | TABLE *table;
48 | };
49 |
50 | class TABLE{
51 | public:
52 | TABLE() = default;
53 | TABLE(std::string s): space(s){};
54 | TABLE(std::string s, TABLE *f): space(s), father(f) {
55 | this->father->son.push_back(this);
56 | };
57 |
58 | bool Find(bool isVal, std::string id, bool recursive);
59 | ENTRY *FindAndReturn(bool isVal, std::string id);
60 |
61 | std::string space;
62 | std::vector val;
63 | std::vector func;
64 | TABLE *father;
65 | std::vector son;
66 | };
67 |
68 | class ENTRY_VAL: public ENTRY{
69 | public:
70 | ENTRY_VAL(std::string i, TABLE *t, int s):ENTRY(i,t),size(s) {
71 | table->val.push_back(this);
72 | isConst = false;
73 | isArray = false;
74 | isParam = false;
75 | };
76 |
77 | bool isConst;
78 | bool isArray;
79 | bool isParam;
80 | std::string eeyore_id;
81 | int size;
82 | std::vector shape;
83 | int val;
84 | //int *arr; 实现const数组编译时确定值的路线之一,不太靠谱
85 | };
86 |
87 | class ENTRY_FUNC: public ENTRY{
88 | public:
89 | ENTRY_FUNC(std::string i, TABLE *t, bool isr,TABLE *s, int nt, int np):ENTRY(i,t),isreturn(isr),symtable(s),NumberOfTemp(nt),NumberOfParam(np) {
90 | table->func.push_back(this);
91 | };
92 |
93 | TABLE *symtable;
94 | bool isreturn;
95 | int NumberOfParam;
96 | int NumberOfTemp;
97 | };
98 |
99 | #endif
100 |
--------------------------------------------------------------------------------
/src/ast_tigger.cpp:
--------------------------------------------------------------------------------
1 | #include"ast_tigger.h"
2 | #include
3 | #include
4 | #include"tigger.tab.hpp"
5 |
6 | extern FILE *tiggerin;
7 | extern FILE *tiggerout;
8 |
9 | AST *root_tigger;
10 |
11 | static void irgen(AST *th);
12 | static void irgen_decl(AST *th);
13 | static void irgen_func(AST *th);
14 | static void irgen_exp(AST *th, int STK);
15 |
16 | //s0为保留寄存器,t0 t1 t2寄存器在eeyore2tigger阶段中使用
17 | static void irgen_exp(AST *th, int STK){
18 | if(th->son.size() == 4 && th->son[2]->type == _BinOp){
19 | //Reg '=' Reg BinOp Reg
20 | //Reg '=' Reg BinOp NUM
21 | std::string reg1, reg2, reg3, op;
22 | reg1 = th->son[0]->id;
23 | reg2 = th->son[1]->id;
24 | if(th->son[3]->type == _Reg){
25 | reg3 = th->son[3]->id;
26 | } else{
27 | //暂时没做直接立即数加法
28 | fprintf(tiggerout," li s0, %d\n",th->son[3]->val);
29 | reg3 = "s0";
30 | }
31 | op = th->son[2]->op;
32 | if(op == "+"){
33 | fprintf(tiggerout," add %s, %s, %s\n",reg1.c_str(),reg2.c_str(),reg3.c_str());
34 | } else if(op == "-"){
35 | fprintf(tiggerout," sub %s, %s, %s\n",reg1.c_str(),reg2.c_str(),reg3.c_str());
36 | } else if(op == "*"){
37 | fprintf(tiggerout," mul %s, %s, %s\n",reg1.c_str(),reg2.c_str(),reg3.c_str());
38 | } else if(op == "/"){
39 | fprintf(tiggerout," div %s, %s, %s\n",reg1.c_str(),reg2.c_str(),reg3.c_str());
40 | } else if(op == "%"){
41 | fprintf(tiggerout," rem %s, %s, %s\n",reg1.c_str(),reg2.c_str(),reg3.c_str());
42 | } else if(op == "<"){
43 | fprintf(tiggerout," slt %s, %s, %s\n",reg1.c_str(),reg2.c_str(),reg3.c_str());
44 | } else if(op == ">"){
45 | fprintf(tiggerout," sgt %s, %s, %s\n",reg1.c_str(),reg2.c_str(),reg3.c_str());
46 | } else if(op == "<="){
47 | fprintf(tiggerout," sgt %s, %s, %s\n",reg1.c_str(),reg2.c_str(),reg3.c_str());
48 | fprintf(tiggerout," seqz %s, %s\n",reg1.c_str(),reg1.c_str());
49 | } else if(op == ">="){
50 | fprintf(tiggerout," slt %s, %s, %s\n",reg1.c_str(),reg2.c_str(),reg3.c_str());
51 | fprintf(tiggerout," seqz %s, %s\n",reg1.c_str(),reg1.c_str());
52 | } else if(op == "&&"){
53 | fprintf(tiggerout," snez %s, %s\n",reg1.c_str(),reg2.c_str());
54 | fprintf(tiggerout," snez s0, %s\n",reg3.c_str());
55 | fprintf(tiggerout," and %s, %s, s0\n",reg1.c_str(),reg1.c_str());
56 | } else if(op == "||"){
57 | fprintf(tiggerout," or %s, %s, %s\n",reg1.c_str(),reg2.c_str(),reg3.c_str());
58 | fprintf(tiggerout," snez %s, %s\n",reg1.c_str(),reg1.c_str());
59 | } else if(op == "!="){
60 | fprintf(tiggerout," xor %s, %s, %s\n",reg1.c_str(),reg2.c_str(),reg3.c_str());
61 | fprintf(tiggerout," snez %s, %s\n",reg1.c_str(),reg1.c_str());
62 | } else if(op == "=="){
63 | fprintf(tiggerout," xor %s, %s, %s\n",reg1.c_str(),reg2.c_str(),reg3.c_str());
64 | fprintf(tiggerout," seqz %s, %s\n",reg1.c_str(),reg1.c_str());
65 | }
66 | } else if(th->son.size() == 3 && th->son[1]->type == _OP){
67 | //Reg '=' OP Reg
68 | std::string reg1, reg2, op;
69 | reg1 = th->son[0]->id;
70 | reg2 = th->son[2]->id;
71 | op = th->son[1]->op;
72 | if(op == "-"){
73 | fprintf(tiggerout," neg %s, %s\n",reg1.c_str(),reg2.c_str());
74 | } else if(op == "!"){
75 | fprintf(tiggerout," seqz %s, %s\n",reg1.c_str(),reg2.c_str());
76 | }
77 | } else if(th->son.size() == 2 && th->son[1]->type == _Reg){
78 | //Reg '=' Reg
79 | std::string reg1, reg2, op;
80 | reg1 = th->son[0]->id;
81 | reg2 = th->son[1]->id;
82 | fprintf(tiggerout," mv %s, %s\n",reg1.c_str(),reg2.c_str());
83 | } else if(th->son.size() == 2 && th->son[1]->type == _NUM){
84 | //Reg '=' NUM
85 | fprintf(tiggerout," li %s, %d\n",th->son[0]->id.c_str(),th->son[1]->val);
86 | } else if(th->son.size() == 3 && th->son[0]->type == _Reg && th->son[1]->type == _NUM){
87 | //Reg '[' NUM ']' '=' Reg
88 | std::string reg1, reg2;
89 | reg1 = th->son[0]->id;
90 | reg2 = th->son[2]->id;
91 | int val = th->son[1]->val;
92 | if(val >= -2048 && val <= 2047){
93 | fprintf(tiggerout," sw %s, %d(%s)\n",reg2.c_str(),val,reg1.c_str());
94 | } else{
95 | fprintf(tiggerout," li s0, %d\n",val);
96 | fprintf(tiggerout," add s0, s0, %s\n",reg1.c_str());
97 | fprintf(tiggerout," sw %s, (s0)\n",reg2.c_str());
98 | }
99 | } else if(th->son.size() == 3 && th->son[0]->type == _Reg && th->son[2]->type == _NUM){
100 | //Reg '=' Reg '[' NUM ']'
101 | std::string reg1, reg2;
102 | reg1 = th->son[0]->id;
103 | reg2 = th->son[1]->id;
104 | int val = th->son[2]->val;
105 | if(val >= -2048 && val <= 2047){
106 | fprintf(tiggerout," lw %s, %d(%s)\n",reg1.c_str(),val,reg2.c_str());
107 | } else{
108 | fprintf(tiggerout," li s0, %d\n",val);
109 | fprintf(tiggerout," add s0, s0, %s\n",reg2.c_str());
110 | fprintf(tiggerout," lw %s, (s0)\n",reg1.c_str());
111 | }
112 | } else if(th->son[0]->type == _IF){
113 | //IF Reg LOGICOP Reg GOTO LABEL
114 | std::string reg1, reg2, op, label;
115 | reg1 = th->son[1]->id;
116 | reg2 = th->son[3]->id;
117 | op = th->son[2]->op;
118 | label = th->son[5]->id;
119 | if(op == "<"){
120 | fprintf(tiggerout," blt %s, %s, .%s\n",reg1.c_str(),reg2.c_str(),label.c_str());
121 | } else if(op == ">"){
122 | fprintf(tiggerout," bgt %s, %s, .%s\n",reg1.c_str(),reg2.c_str(),label.c_str());
123 | } else if(op == "<="){
124 | fprintf(tiggerout," ble %s, %s, .%s\n",reg1.c_str(),reg2.c_str(),label.c_str());
125 | } else if(op == ">="){
126 | fprintf(tiggerout," bge %s, %s, .%s\n",reg1.c_str(),reg2.c_str(),label.c_str());
127 | } else if(op == "!="){
128 | fprintf(tiggerout," bne %s, %s, .%s\n",reg1.c_str(),reg2.c_str(),label.c_str());
129 | } else if(op == "=="){
130 | fprintf(tiggerout," beq %s, %s, .%s\n",reg1.c_str(),reg2.c_str(),label.c_str());
131 | }
132 | } else if(th->son[0]->type == _GOTO){
133 | //GOTO LABEL
134 | fprintf(tiggerout," j .%s\n",th->son[1]->id.c_str());
135 | } else if(th->son[0]->type == _LABEL){
136 | //LABEL ':'
137 | fprintf(tiggerout,".%s:\n",th->son[0]->id.c_str());
138 | } else if(th->son[0]->type == _CALL){
139 | //CALL FUNCTION
140 | fprintf(tiggerout," call %s\n",th->son[1]->id.substr(2).c_str());
141 | } else if(th->son[0]->type == _RETURN){
142 | //RETURN
143 | if(STK >= -2044 && STK <= 2047){
144 | fprintf(tiggerout," lw ra, %d(sp)\n",STK-4);
145 | fprintf(tiggerout," addi sp, sp, %d\n",STK);
146 | } else{
147 | fprintf(tiggerout," li s0, %d\n",STK);
148 | fprintf(tiggerout," add s0, s0, sp\n");
149 | fprintf(tiggerout," lw ra, -4(s0)\n");
150 | fprintf(tiggerout," li s0, %d\n", STK);
151 | fprintf(tiggerout," add sp, sp, s0\n");
152 | }
153 | fprintf(tiggerout," ret\n");
154 | } else if(th->son[0]->type == _STORE){
155 | //STORE Reg NUM
156 | std::string reg = th->son[1]->id;
157 | int val = th->son[2]->val;
158 | if(val >= -512 && val <= 511){
159 | fprintf(tiggerout," sw %s, %d(sp)\n",reg.c_str(),val*4);
160 | } else{
161 | fprintf(tiggerout," li s0, %d\n",val*4);
162 | fprintf(tiggerout," add s0, sp, s0\n");
163 | fprintf(tiggerout," sw %s, (s0)\n",reg.c_str());
164 | }
165 | } else if(th->son[0]->type == _LOAD && th->son[1]->type == _NUM){
166 | //LOAD NUM Reg
167 | std::string reg = th->son[2]->id;
168 | int val = th->son[1]->val;
169 | if(val >= -512 && val <= 511){
170 | fprintf(tiggerout," lw %s, %d(sp)\n",reg.c_str(),val*4);
171 | } else{
172 | fprintf(tiggerout," li s0, %d\n",val*4);
173 | fprintf(tiggerout," add s0, sp, s0\n");
174 | fprintf(tiggerout," lw %s, (s0)\n",reg.c_str());
175 | }
176 | } else if(th->son[0]->type == _LOAD && th->son[1]->type == _VARIABLE){
177 | //LOAD VARIABLE Reg
178 | std::string reg, var;
179 | reg = th->son[2]->id;
180 | var = th->son[1]->id;
181 | fprintf(tiggerout," lui %s, %%hi(%s)\n",reg.c_str(),var.c_str());
182 | fprintf(tiggerout," lw %s, %%lo(%s)(%s)\n",reg.c_str(),var.c_str(),reg.c_str());
183 | } else if(th->son[0]->type == _LOADADDR && th->son[1]->type == _NUM){
184 | //LOADADDR NUM Reg
185 | std::string reg = th->son[2]->id;
186 | int val = th->son[1]->val;
187 | if(val >= -512 && val <= 511){
188 | fprintf(tiggerout," addi %s, sp, %d\n",reg.c_str(),val*4);
189 | } else{
190 | fprintf(tiggerout," li s0, %d\n",val*4);
191 | fprintf(tiggerout," add %s, sp, s0\n",reg.c_str());
192 | }
193 | } else if(th->son[0]->type == _LOADADDR && th->son[1]->type == _VARIABLE){
194 | //LOADADDR VARIABLE Reg
195 | std::string reg, var;
196 | reg = th->son[2]->id;
197 | var = th->son[1]->id;
198 | fprintf(tiggerout," la %s, %s\n",reg.c_str(),var.c_str());
199 | }
200 | }
201 |
202 | static void irgen_func(AST *th){
203 | int STK = (th->son[0]->son[2]->val / 4 + 1) * 16;
204 | std::string func_id = th->son[0]->son[0]->id.substr(2);
205 | fprintf(tiggerout," .text\n");
206 | fprintf(tiggerout," .align 2\n");
207 | fprintf(tiggerout," .global %s\n",func_id.c_str());
208 | fprintf(tiggerout," .type %s, @function\n",func_id.c_str());
209 | fprintf(tiggerout,"%s:\n",func_id.c_str());
210 | if(STK >= -2044 && STK <= 2047){
211 | fprintf(tiggerout," addi sp, sp, -%d\n",STK);
212 | fprintf(tiggerout," sw ra, %d(sp)\n",STK-4);
213 | } else{
214 | fprintf(tiggerout," li s0, %d\n",STK);
215 | fprintf(tiggerout," sub sp, sp, s0\n");
216 | fprintf(tiggerout," add s0, s0, sp\n");
217 | fprintf(tiggerout," sw ra, -4(s0)\n");
218 | }
219 | for(int i=0;ison[1]->son.size();i++){
220 | irgen_exp(th->son[1]->son[i],STK);
221 | }
222 | fprintf(tiggerout," .size %s, .-%s\n",func_id.c_str(),func_id.c_str());
223 | }
224 |
225 | static void irgen_decl(AST *th){
226 | std::string var_id = th->son[0]->id;
227 | if(th->son.size() == 2){
228 | fprintf(tiggerout," .global %s\n",var_id.c_str());
229 | fprintf(tiggerout," .section .sdata\n");
230 | fprintf(tiggerout," .align 2\n");
231 | fprintf(tiggerout," .type %s, @object\n",var_id.c_str());
232 | fprintf(tiggerout," .size %s, 4\n",var_id.c_str());
233 | fprintf(tiggerout,"%s:\n",var_id.c_str());
234 | fprintf(tiggerout," .word %d\n", th->son[1]->val);
235 | } else{
236 | fprintf(tiggerout," .comm %s, %d, 4\n",var_id.c_str(),th->son[2]->val);
237 | }
238 | }
239 |
240 | static void irgen(AST *th){
241 | for(int i=0;ison.size();i++){
242 | if(th->son[i]->type == _GlobalVarDecl){
243 | irgen_decl(th->son[i]);
244 | } else if(th->son[i]->type == _FunctionDef){
245 | irgen_func(th->son[i]);
246 | }
247 | }
248 | }
249 |
250 | void codegen_riscv(char *input_file_path, char *output_file_path){
251 | FILE *input_file = fopen(input_file_path,"r");
252 | FILE *output_file = fopen(output_file_path,"w");
253 | tiggerin = input_file;
254 | tiggerout = output_file;
255 |
256 | tiggerparse();
257 | irgen(root_tigger);
258 |
259 | fclose(input_file);
260 | fclose(output_file);
261 | tiggerin = stdin;
262 | tiggerout = stdout;
263 | }
264 |
--------------------------------------------------------------------------------
/src/ast_tigger.h:
--------------------------------------------------------------------------------
1 | #ifndef AST_TIGGER_H
2 | #define AST_TIGGER_H
3 |
4 | #include
5 | #include
6 |
7 | enum TYPE {
8 | _IF, _RETURN, _VARIABLE, _NUM, _MALLOC, _END, _FUNCTION, _LOGICOP, _OP, _GOTO, _LABEL, _CALL, _STORE, _LOAD, _LOADADDR, _Reg,
9 | _Program, _GlobalVarDecl, _FunctionDef, _FunctionHeader, _FunctionEnd,
10 | _Expressions, _Expression, _BinOp
11 | };
12 |
13 | class AST{
14 | public:
15 | AST() = default;
16 | AST(TYPE t):type(t){}
17 |
18 | std::vector son;
19 | TYPE type;
20 | std::string op;
21 | int val;
22 | std::string id;
23 | };
24 |
25 | #endif
26 |
--------------------------------------------------------------------------------
/src/eeyore.l:
--------------------------------------------------------------------------------
1 | %{
2 | #include
3 | #include
4 | #include
5 | #include"ast_eeyore.h"
6 | #include"eeyore.tab.hpp" //保持以上顺序
7 | %}
8 |
9 | %option prefix="eeyore"
10 |
11 | function f_([_a-zA-Z][_a-zA-Z0-9]*)
12 | symbol (T|t|p){decimal}
13 | label l{decimal}
14 | other ("["|"]"|":"|"=")
15 | operator ("&&"|"||"|"+"|"-"|"*"|"/"|"%"|"!")
16 | logicop ("!="|"=="|">"|"<"|">="|"<=")
17 | decimal (-?[1-9][0-9]*)|0
18 | comment ("//".*)
19 |
20 | %%
21 |
22 | "if" {
23 | AST *temp = new AST(_IF);
24 | eeyorelval.ast = temp;
25 | return IF;
26 | }
27 | "goto" {
28 | AST *temp = new AST(_GOTO);
29 | eeyorelval.ast = temp;
30 | return GOTO;
31 | }
32 | "call" {
33 | AST *temp = new AST(_CALL);
34 | eeyorelval.ast = temp;
35 | return CALL;
36 | }
37 | "param" {
38 | AST *temp = new AST(_PARAM);
39 | eeyorelval.ast = temp;
40 | return PARAM;
41 | }
42 | "var" {
43 | AST *temp = new AST(_VAR);
44 | eeyorelval.ast = temp;
45 | return VAR;
46 | }
47 | "return" {
48 | AST *temp = new AST(_RETURN);
49 | eeyorelval.ast = temp;
50 | return RETURN;
51 | }
52 | "end" {
53 | AST *temp = new AST(_END);
54 | eeyorelval.ast = temp;
55 | return END;
56 | }
57 | {function} {
58 | AST *temp = new AST(_FUNCTION);
59 | temp->id = yytext;
60 | eeyorelval.ast = temp;
61 | return FUNCTION;
62 | }
63 | {symbol} {
64 | AST *temp = new AST(_SYMBOL);
65 | temp->id = yytext;
66 | eeyorelval.ast = temp;
67 | return SYMBOL;
68 | }
69 | {label} {
70 | AST *temp = new AST(_LABEL);
71 | temp->id = yytext;
72 | eeyorelval.ast = temp;
73 | return LABEL;
74 | }
75 | {operator} {
76 | AST *temp = new AST(_OP);
77 | temp->op = yytext;
78 | eeyorelval.ast = temp;
79 | return OP;
80 | }
81 | {logicop} {
82 | AST *temp = new AST(_LOGICOP);
83 | temp->op = yytext;
84 | eeyorelval.ast = temp;
85 | return LOGICOP;
86 | }
87 | {other} {
88 | return yytext[0];
89 | }
90 | {decimal} {
91 | AST *temp = new AST(_NUM);
92 | temp->val = atoi(yytext);
93 | eeyorelval.ast = temp;
94 | return NUM;
95 | }
96 | {comment}
97 | \n
98 | .
99 |
100 | %%
101 |
102 | int yywrap(){
103 | return 1;
104 | }
105 |
--------------------------------------------------------------------------------
/src/eeyore.y:
--------------------------------------------------------------------------------
1 | %{
2 | #include
3 | #include
4 | #include"ast_eeyore.h"
5 |
6 | extern int eeyorelex();
7 | extern char *eeyoretext;
8 | extern ENTRY *findvar(FUNC *func, std::string id);
9 | extern AST *root_eeyore;
10 | extern std::vectorglobal_table;
11 | extern std::vectorfunctions;
12 | extern FUNC *func_ptr;
13 |
14 | void yyerror(char *str){
15 | printf("In %s : %s\n", eeyoretext, str);
16 | };
17 |
18 | int v_i = 0;
19 | %}
20 |
21 | %define api.prefix {eeyore}
22 |
23 | %union{
24 | class AST *ast;
25 | }
26 |
27 | %token IF RETURN VAR NUM SYMBOL END FUNCTION LOGICOP OP GOTO LABEL PARAM CALL
28 | %type Program Declaration Initialization FunctionDef FunctionHeader Statements FunctionEnd
29 | %type Statement Expression RightValue BinOp
30 |
31 | %%
32 |
33 | Program : Declaration {
34 | root_eeyore = new AST(_Program);
35 | root_eeyore->son.push_back($1);
36 | $$ = root_eeyore;
37 | }
38 | | Initialization {
39 | root_eeyore = new AST(_Program);
40 | root_eeyore->son.push_back($1);
41 | $$ = root_eeyore;
42 | }
43 | | FunctionDef {
44 | root_eeyore = new AST(_Program);
45 | root_eeyore->son.push_back($1);
46 | $$ = root_eeyore;
47 | }
48 | | Program Declaration {
49 | $1->son.push_back($2);
50 | $$ = $1;
51 | }
52 | | Program Initialization {
53 | $1->son.push_back($2);
54 | $$ = $1;
55 | }
56 | | Program FunctionDef{
57 | $1->son.push_back($2);
58 | $$ = $1;
59 | };
60 |
61 | Declaration : VAR NUM SYMBOL {
62 | if(!func_ptr){
63 | ENTRY *entry = new ENTRY($3->id);
64 | entry->global = true;
65 | entry->array = true;
66 | entry->stack = v_i;
67 | v_i++;
68 | entry->size = $2->val;
69 | entry->init = new int[entry->size/4];
70 | memset(entry->init,0,entry->size);
71 | global_table.push_back(entry);
72 | $3->entry = entry;
73 | } else{
74 | ENTRY *entry = new ENTRY($3->id);
75 | entry->array = true;
76 | entry->size = $2->val;
77 | entry->stack = func_ptr->stack_size;
78 | func_ptr->table.push_back(entry);
79 | func_ptr->stack_size += entry->size/4;
80 | }
81 | AST *temp = new AST(_Declaration);
82 | temp->son.push_back($2);
83 | temp->son.push_back($3);
84 | $$ = temp;
85 | }
86 | | VAR SYMBOL{
87 | if(!func_ptr){
88 | ENTRY *entry = new ENTRY($2->id);
89 | entry->global = true;
90 | entry->stack = v_i;
91 | v_i++;
92 | entry->val = 0;
93 | global_table.push_back(entry);
94 | $2->entry = entry;
95 | } else{
96 | ENTRY *entry = new ENTRY($2->id);
97 | entry->stack = func_ptr->stack_size;
98 | func_ptr->table.push_back(entry);
99 | func_ptr->stack_size++;
100 | }
101 | AST *temp = new AST(_Declaration);
102 | temp->son.push_back($2);
103 | $$ = temp;
104 | };
105 |
106 | Initialization : SYMBOL '=' NUM {
107 | ENTRY *entry = findvar(nullptr,$1->id);
108 | entry->val = $3->val;
109 | AST *temp = new AST(_Initialization);
110 | temp->son.push_back($1);
111 | temp->son.push_back($3);
112 | $$ = temp;
113 | }
114 | | SYMBOL '[' NUM ']' '=' NUM{
115 | ENTRY *entry = findvar(nullptr,$1->id);
116 | entry->init[$3->val/4] = $6->val;
117 | entry->isinit = true;
118 | AST *temp = new AST(_Initialization);
119 | temp->son.push_back($1);
120 | temp->son.push_back($3);
121 | temp->son.push_back($6);
122 | $$ = temp;
123 | };
124 |
125 | FunctionDef : FunctionHeader Statements FunctionEnd{
126 | AST *temp = new AST(_FunctionDef);
127 | temp->son.push_back($1);
128 | temp->son.push_back($2);
129 | temp->son.push_back($3);
130 | $$ = temp;
131 | };
132 |
133 | FunctionHeader : FUNCTION '[' NUM ']'{
134 | func_ptr = new FUNC($1->id, $3->val);
135 | functions.push_back(func_ptr);
136 | for(int i=0;ipnum;i++){
137 | ENTRY *entry = new ENTRY("p"+std::to_string(i));
138 | entry->stack = func_ptr->stack_size;
139 | func_ptr->table.push_back(entry);
140 | func_ptr->stack_size++;
141 | }
142 | AST *temp = new AST(_FunctionHeader);
143 | temp->son.push_back($1);
144 | temp->son.push_back($3);
145 | $$ = temp;
146 | };
147 |
148 | Statements : Statements Statement {
149 | $1->son.push_back($2);
150 | $$ = $1;
151 | }
152 | | {
153 | AST *temp = new AST(_Statements);
154 | $$ = temp;
155 | };
156 |
157 | FunctionEnd : END FUNCTION {
158 | AST *temp = new AST(_FunctionEnd);
159 | $$ = temp;
160 | };
161 |
162 | Statement : Expression {
163 | AST *temp = new AST(_Statement);
164 | temp->son.push_back($1);
165 | $$ = temp;
166 | }
167 | | Declaration {
168 | AST *temp = new AST(_Statement);
169 | temp->son.push_back($1);
170 | $$ = temp;
171 | };
172 |
173 | Expression : SYMBOL '=' RightValue BinOp RightValue {
174 | $1->entry = findvar(func_ptr,$1->id);
175 | AST *temp = new AST(_Expression);
176 | temp->son.push_back($1);
177 | temp->son.push_back($3);
178 | temp->son.push_back($4);
179 | temp->son.push_back($5);
180 | $$ = temp;
181 | }
182 | | SYMBOL '=' OP RightValue {
183 | $1->entry = findvar(func_ptr,$1->id);
184 | AST *temp = new AST(_Expression);
185 | temp->son.push_back($1);
186 | temp->son.push_back($3);
187 | temp->son.push_back($4);
188 | $$ = temp;
189 | }
190 | | SYMBOL '=' RightValue {
191 | $1->entry = findvar(func_ptr,$1->id);
192 | AST *temp = new AST(_Expression);
193 | temp->son.push_back($1);
194 | temp->son.push_back($3);
195 | $$ = temp;
196 | }
197 | | SYMBOL '[' RightValue ']' '=' RightValue {
198 | $1->entry = findvar(func_ptr,$1->id);
199 | AST *temp = new AST(_Expression);
200 | temp->son.push_back($1);
201 | temp->son.push_back($3);
202 | temp->son.push_back($6);
203 | $$ = temp;
204 | }
205 | | SYMBOL '=' SYMBOL '[' RightValue ']' {
206 | $1->entry = findvar(func_ptr,$1->id);
207 | $3->entry = findvar(func_ptr,$3->id);
208 | AST *temp = new AST(_Expression);
209 | temp->son.push_back($1);
210 | temp->son.push_back($3);
211 | temp->son.push_back($5);
212 | $$ = temp;
213 | }
214 | | IF RightValue LOGICOP RightValue GOTO LABEL {
215 | AST *temp = new AST(_Expression);
216 | temp->son.push_back($1);
217 | temp->son.push_back($2);
218 | temp->son.push_back($3);
219 | temp->son.push_back($4);
220 | temp->son.push_back($5);
221 | temp->son.push_back($6);
222 | $$ = temp;
223 | }
224 | | GOTO LABEL {
225 | AST *temp = new AST(_Expression);
226 | temp->son.push_back($1);
227 | temp->son.push_back($2);
228 | $$ = temp;
229 | }
230 | | LABEL ':' {
231 | AST *temp = new AST(_Expression);
232 | temp->son.push_back($1);
233 | $$ = temp;
234 | }
235 | | PARAM RightValue {
236 | AST *temp = new AST(_Expression);
237 | temp->son.push_back($1);
238 | temp->son.push_back($2);
239 | $$ = temp;
240 | }
241 | | CALL FUNCTION {
242 | AST *temp = new AST(_Expression);
243 | temp->son.push_back($1);
244 | temp->son.push_back($2);
245 | $$ = temp;
246 | }
247 | | SYMBOL '=' CALL FUNCTION {
248 | $1->entry = findvar(func_ptr,$1->id);
249 | AST *temp = new AST(_Expression);
250 | temp->son.push_back($1);
251 | temp->son.push_back($3);
252 | temp->son.push_back($4);
253 | $$ = temp;
254 | }
255 | | RETURN RightValue {
256 | AST *temp = new AST(_Expression);
257 | temp->son.push_back($1);
258 | temp->son.push_back($2);
259 | $$ = temp;
260 | }
261 | | RETURN {
262 | AST *temp = new AST(_Expression);
263 | temp->son.push_back($1);
264 | $$ = temp;
265 | };
266 |
267 | RightValue : SYMBOL {
268 | $1->entry = findvar(func_ptr,$1->id);
269 | AST *temp = new AST(_RightValue);
270 | temp->son.push_back($1);
271 | $$ = temp;
272 | }
273 | | NUM {
274 | AST *temp = new AST(_RightValue);
275 | temp->son.push_back($1);
276 | $$ = temp;
277 | };
278 |
279 | BinOp : OP {
280 | AST *temp = new AST(_BinOp);
281 | temp->op = $1->op;
282 | temp->son.push_back($1);
283 | $$ = temp;
284 | }
285 | | LOGICOP {
286 | AST *temp = new AST(_BinOp);
287 | temp->op = $1->op;
288 | temp->son.push_back($1);
289 | $$ = temp;
290 | };
291 |
292 | %%
293 |
--------------------------------------------------------------------------------
/src/lexer.l:
--------------------------------------------------------------------------------
1 | %{
2 | #include
3 | #include
4 | #include
5 | #include"ast_sysy.h"
6 | #include"parser.tab.hpp" //保持此顺序
7 |
8 | int lineno = 1;
9 | %}
10 |
11 | %option prefix="sysy"
12 | %x COMMENTS
13 |
14 | ident ([_a-zA-Z][_a-zA-Z0-9]*)
15 | symbol ("("|")"|"["|"]"|"{"|"}"|";"|",")
16 | operator ("="|">"|"<"|"+"|"-"|"*"|"/"|"%"|"!")
17 | decimal ([1-9][0-9]*)|0
18 | oct 0[0-7]*
19 | hex 0[xX][0-9A-Fa-f]+
20 | comment ("//".*)
21 |
22 | %%
23 |
24 | "/*" {BEGIN COMMENTS;}
25 | .
26 | \n
27 | "*/" {BEGIN INITIAL;}
28 |
29 | "int" {
30 | AST *temp = new AST(_INT);
31 | sysylval.ast = temp;
32 | return INT;
33 | }
34 | "void" {
35 | AST *temp = new AST(_VOID);
36 | sysylval.ast = temp;
37 | return VOID;
38 | }
39 | "const" {
40 | AST *temp = new AST(_CONST);
41 | sysylval.ast = temp;
42 | return CONST;
43 | }
44 | "if" {
45 | AST *temp = new AST(_IF);
46 | sysylval.ast = temp;
47 | return IF;
48 | }
49 | "else" {
50 | AST *temp = new AST(_ELSE);
51 | sysylval.ast = temp;
52 | return ELSE;
53 | }
54 | "while" {
55 | AST *temp = new AST(_WHILE);
56 | sysylval.ast = temp;
57 | return WHILE;
58 | }
59 | "break" {
60 | AST *temp = new AST(_BREAK);
61 | sysylval.ast = temp;
62 | return BREAK;
63 | }
64 | "continue" {
65 | AST *temp = new AST(_CONTINUE);
66 | sysylval.ast = temp;
67 | return CONTINUE;
68 | }
69 | "return" {
70 | AST *temp = new AST(_RETURN);
71 | sysylval.ast = temp;
72 | return RETURN;
73 | }
74 | "<=" {
75 | AST *temp = new AST(_LE);
76 | sysylval.ast = temp;
77 | return LE;
78 | }
79 | ">=" {
80 | AST *temp = new AST(_GE);
81 | sysylval.ast = temp;
82 | return GE;
83 | }
84 | "==" {
85 | AST *temp = new AST(_EQ);
86 | sysylval.ast = temp;
87 | return EQ;
88 | }
89 | "!=" {
90 | AST *temp = new AST(_NE);
91 | sysylval.ast = temp;
92 | return NE;
93 | }
94 | "&&" {
95 | AST *temp = new AST(_AND);
96 | sysylval.ast = temp;
97 | return AND;
98 | }
99 | "||" {
100 | AST *temp = new AST(_OR);
101 | sysylval.ast = temp;
102 | return OR;
103 | }
104 | {ident} {
105 | AST *temp = new AST(_IDENT);
106 | temp->id = yytext;
107 | sysylval.ast = temp;
108 | return IDENT;
109 | }
110 | {operator} {
111 | AST *temp = new AST(_OP, yytext[0]);
112 | sysylval.ast = temp;
113 | return yytext[0];
114 | }
115 | {symbol} {
116 | return yytext[0];
117 | }
118 | {decimal} {
119 | AST *temp = new AST(_INT_CONST,atoi(yytext));
120 | sysylval.ast = temp;
121 | return INT_CONST;
122 | }
123 | {oct} {
124 | int val = strtol(yytext, NULL, 8);
125 | AST *temp = new AST(_INT_CONST,val);
126 | sysylval.ast = temp;
127 | return INT_CONST;
128 | }
129 | {hex} {
130 | int val = strtol(yytext, NULL, 16);
131 | AST *temp = new AST(_INT_CONST,val);
132 | sysylval.ast = temp;
133 | return INT_CONST;
134 | }
135 | {comment}
136 | \n {lineno++;}
137 | .
138 |
139 | %%
140 |
141 | int yywrap(){
142 | return 1;
143 | }
--------------------------------------------------------------------------------
/src/main.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | extern char *optarg;
5 | extern void codegen_eeyore(char *input_file_path, char *output_file_path);
6 | extern void codegen_tigger(char *input_file_path, char *output_file_path);
7 | extern void codegen_riscv(char *input_file_path, char *output_file_path);
8 |
9 | int main(int argc, char *argv[]){
10 | int arg_temp = 0;
11 | char *input_file_path = nullptr;
12 | char *output_file_path = nullptr;
13 | //-S -o
14 | while(EOF != (arg_temp = getopt(argc,argv,"o:S:"))){
15 | switch(arg_temp){
16 | case 'o':
17 | output_file_path = optarg;
18 | break;
19 | case 'S':
20 | input_file_path = optarg;
21 | break;
22 | case '?':
23 | perror("Wrong arg!\n");
24 | return 1;
25 | }
26 | }
27 | if(!output_file_path){
28 | output_file_path = "./output.S";
29 | }
30 | codegen_eeyore(input_file_path, "./output.eeyore");
31 | codegen_tigger("./output.eeyore","./output.tigger");
32 | codegen_riscv("./output.tigger",output_file_path);
33 | return 0;
34 | }
35 |
--------------------------------------------------------------------------------
/src/parser.y:
--------------------------------------------------------------------------------
1 | %{
2 | #include
3 | #include
4 | #include"ast_sysy.h"
5 |
6 | extern int sysylex();
7 | extern int lineno;
8 | extern char *sysytext;
9 | extern AST *root_sysy;
10 | extern TABLE *root_symtable;
11 | extern std::vectorsymtable_vector;
12 | extern TABLE *symtable_ptr;
13 |
14 | void yyerror(char *str){
15 | printf("LINE %d in %s : %s\n",lineno, sysytext, str);
16 | };
17 |
18 | int NumberOfTemp; //记录一个函数需要多少临时变量
19 | %}
20 |
21 | %define api.prefix {sysy}
22 |
23 | %union{
24 | class AST *ast; //class关键字必需添加
25 | }
26 |
27 | %token CONST INT VOID IF ELSE WHILE BREAK CONTINUE RETURN
28 | %token '=' '>' '<' '+' '-' '*' '/' '%' '!'
29 | %token '(' ')' '[' ']' '{' '}' ';' ','
30 | %token LE GE EQ NE AND OR
31 | %token IDENT
32 | %token INT_CONST
33 | %type CompUnit Decl ConstDecl ConstDef_temp BType ConstDef ConstExp_temp ConstInitVal
34 | %type ConstInitVal_temp VarDecl VarDef_temp VarDef InitVal InitVal_temp FuncDef FuncFParams FuncFParam
35 | %type Block BlockItem_temp BlockItem Stmt Exp Cond LVal PrimaryExp UnaryExp UnaryOp FuncRParams
36 | %type MulExp AddExp RelExp EqExp LAndExp LOrExp ConstExp
37 |
38 | %%
39 | //确保正确构建AST,创建所有符号表及条目,记录每个函数需要多少变量,记录每个变量的大小和形状,但不分配eeyore变量名
40 |
41 | CompUnit : CompUnit Decl {
42 | $1->son.push_back($2);
43 | $$ = $1;
44 | }
45 | | CompUnit FuncDef {
46 | $1->son.push_back($2);
47 | $$ = $1;
48 | }
49 | | Decl {
50 | root_sysy = new AST(_CompUnit);
51 | root_sysy->son.push_back($1);
52 | $$ = root_sysy;
53 | }
54 | | FuncDef {
55 | root_sysy = new AST(_CompUnit);
56 | root_sysy->son.push_back($1);
57 | $$ = root_sysy;
58 | }
59 | ;
60 |
61 | Decl : ConstDecl {
62 | AST *temp = new AST(_Decl);
63 | temp->son.push_back($1);
64 | $$ = temp;
65 | }
66 | | VarDecl {
67 | AST *temp = new AST(_Decl);
68 | temp->son.push_back($1);
69 | $$ = temp;
70 | }
71 | ;
72 |
73 | ConstDecl : CONST BType ConstDef_temp ';' {
74 | AST *temp = new AST(_ConstDecl);
75 | temp->son.push_back($1);
76 | temp->son.push_back($2);
77 | temp->son.push_back($3);
78 | $$ = temp;
79 | }
80 | ;
81 |
82 | ConstDef_temp : ConstDef {
83 | AST *temp = new AST(_ConstDef_temp);
84 | temp->son.push_back($1);
85 | $$ = temp;
86 | }
87 | | ConstDef_temp ',' ConstDef {
88 | $1->son.push_back($3);
89 | $$ = $1;
90 | }
91 | ;
92 |
93 | BType : INT {
94 | AST *temp = new AST(_BType);
95 | temp->son.push_back($1);
96 | $$ = temp;
97 | }
98 | | VOID {
99 | AST *temp = new AST(_BType);
100 | temp->son.push_back($1);
101 | $$ = temp;
102 | }
103 | ;
104 |
105 | ConstDef : IDENT ConstExp_temp '=' ConstInitVal {
106 | $1->entry = new ENTRY_VAL($1->id, symtable_ptr,$2->val*4);
107 | ((ENTRY_VAL *)$1->entry)->isConst = true;
108 | if($2->son.size() != 0){
109 | ((ENTRY_VAL *)$1->entry)->isArray = true;
110 | for(int i=0;i<$2->son.size();i++){
111 | ((ENTRY_VAL *)$1->entry)->shape.push_back($2->son[i]->val);
112 | }
113 | }
114 | //还没想好怎么处理常量数组的赋值
115 | if($4->son.size() == 1 && $4->son[0]->type == _ConstExp){
116 | ((ENTRY_VAL *)$1->entry)->val = $4->son[0]->val;
117 | }
118 | AST *temp = new AST(_ConstDef);
119 | temp->son.push_back($1);
120 | temp->son.push_back($2);
121 | temp->son.push_back($4);
122 | $$ = temp;
123 | }
124 | ;
125 |
126 | ConstExp_temp : ConstExp_temp '[' ConstExp ']' {
127 | $1->son.push_back($3);
128 | $1->val *= $3->val;
129 | $$ = $1;
130 | }
131 | | {
132 | AST *temp = new AST(_ConstExp_temp);
133 | temp->val = 1;
134 | $$ = temp;
135 | }
136 | ;
137 |
138 | ConstInitVal : ConstExp {
139 | AST *temp = new AST(_ConstInitVal);
140 | temp->son.push_back($1);
141 | $$ = temp;
142 | }
143 | | '{' '}' {
144 | AST *temp = new AST(_ConstInitVal);
145 | $$ = temp;
146 | }
147 | | '{' ConstInitVal_temp '}' {
148 | AST *temp = new AST(_ConstInitVal);
149 | temp->son = $2->son;
150 | delete $2;
151 | $$ = temp;
152 | }
153 | ;
154 |
155 | ConstInitVal_temp : ConstInitVal {
156 | AST *temp = new AST(_ConstInitVal_temp);
157 | temp->son.push_back($1);
158 | $$ = temp;
159 | }
160 | | ConstInitVal_temp ',' ConstInitVal {
161 | $1->son.push_back($3);
162 | $$ = $1;
163 | }
164 | ;
165 |
166 | VarDecl : BType VarDef_temp ';' {
167 | AST *temp = new AST(_VarDecl);
168 | temp->son.push_back($1);
169 | temp->son.push_back($2);
170 | $$ = temp;
171 | }
172 | ;
173 |
174 | VarDef_temp : VarDef {
175 | AST *temp = new AST(_VarDef_temp);
176 | temp->son.push_back($1);
177 | $$ = temp;
178 | }
179 | | VarDef_temp ',' VarDef {
180 | $1->son.push_back($3);
181 | $$ = $1;
182 | }
183 | ;
184 |
185 | VarDef : IDENT ConstExp_temp {
186 | $1->entry = new ENTRY_VAL($1->id, symtable_ptr,$2->val*4);
187 | if($2->son.size() != 0){
188 | ((ENTRY_VAL *)$1->entry)->isArray = true;
189 | for(int i=0;i<$2->son.size();i++){
190 | ((ENTRY_VAL *)$1->entry)->shape.push_back($2->son[i]->val);
191 | }
192 | }
193 | AST *temp = new AST(_VarDef);
194 | temp->son.push_back($1);
195 | temp->son.push_back($2);
196 | $$ = temp;
197 | }
198 | | IDENT ConstExp_temp '=' InitVal {
199 | $1->entry = new ENTRY_VAL($1->id, symtable_ptr,$2->val*4);
200 | if($2->son.size() != 0){
201 | ((ENTRY_VAL *)$1->entry)->isArray = true;
202 | for(int i=0;i<$2->son.size();i++){
203 | ((ENTRY_VAL *)$1->entry)->shape.push_back($2->son[i]->val);
204 | }
205 | }
206 | AST *temp = new AST(_VarDef);
207 | temp->son.push_back($1);
208 | temp->son.push_back($2);
209 | temp->son.push_back($4);
210 | $$ = temp;
211 | }
212 | ;
213 |
214 | InitVal : Exp {
215 | AST *temp = new AST(_InitVal);
216 | temp->son.push_back($1);
217 | $$ = temp;
218 | }
219 | | '{' '}' {
220 | AST *temp = new AST(_InitVal);
221 | $$ = temp;
222 | }
223 | | '{' InitVal_temp '}' {
224 | AST *temp = new AST(_InitVal);
225 | temp->son = $2->son;
226 | delete $2;
227 | $$ = temp;
228 | }
229 | ;
230 |
231 | InitVal_temp : InitVal {
232 | AST *temp = new AST(_InitVal_temp);
233 | temp->son.push_back($1);
234 | $$ = temp;
235 | }
236 | | InitVal_temp ',' InitVal {
237 | $1->son.push_back($3);
238 | $$ = $1;
239 | }
240 | ;
241 |
242 | FuncDef : BType IDENT '(' {
243 | symtable_ptr = new TABLE("func", symtable_ptr);
244 | symtable_vector.push_back(symtable_ptr);
245 | NumberOfTemp = 0;
246 | } FuncFParams ')' Block {
247 | symtable_ptr->space = $2->id;
248 | bool isreturn = ($1->son[0]->type == _INT);
249 | $2->entry = new ENTRY_FUNC($2->id, symtable_ptr->father,isreturn, symtable_ptr,NumberOfTemp,$5->son.size());
250 | NumberOfTemp = 0;
251 | AST *temp = new AST(_FuncDef);
252 | temp->son.push_back($1);
253 | temp->son.push_back($2);
254 | temp->son.push_back($5);
255 | temp->son.push_back($7);
256 | $$ = temp;
257 | symtable_ptr = symtable_ptr->father;
258 | }
259 | | BType IDENT '(' {
260 | symtable_ptr = new TABLE("func", symtable_ptr);
261 | symtable_vector.push_back(symtable_ptr);
262 | NumberOfTemp = 0;
263 | } ')' Block {
264 | symtable_ptr->space = $2->id;
265 | bool isreturn = ($1->son[0]->type == _INT);
266 | $2->entry = new ENTRY_FUNC($2->id, symtable_ptr->father, isreturn, symtable_ptr,NumberOfTemp,0);
267 | NumberOfTemp = 0;
268 | AST *temp = new AST(_FuncDef);
269 | temp->son.push_back($1);
270 | temp->son.push_back($2);
271 | temp->son.push_back($6);
272 | $$ = temp;
273 | symtable_ptr = symtable_ptr->father;
274 | }
275 | ;
276 |
277 | FuncFParams : FuncFParam {
278 | AST *temp = new AST(_FuncFParams);
279 | temp->son.push_back($1);
280 | $$ = temp;
281 | }
282 | | FuncFParams ',' FuncFParam {
283 | $1->son.push_back($3);
284 | $$ = $1;
285 | }
286 | ;
287 |
288 | FuncFParam : BType IDENT '[' ']' ConstExp_temp {
289 | $2->entry = new ENTRY_VAL($2->id, symtable_ptr,$5->val*4);
290 | ((ENTRY_VAL *)$2->entry)->shape.push_back(1);
291 | if($5->son.size() != 0){
292 | for(int i=0;i<$5->son.size();i++){
293 | ((ENTRY_VAL *)$2->entry)->shape.push_back($5->son[i]->val);
294 | }
295 | }
296 | ((ENTRY_VAL *)$2->entry)->isArray = true;
297 | ((ENTRY_VAL *)$2->entry)->isParam = true;
298 | AST *temp = new AST(_FuncFParam);
299 | temp->son.push_back($1);
300 | temp->son.push_back($2);
301 | temp->son.push_back($5);
302 | $$ = temp;
303 | }
304 | | BType IDENT {
305 | $2->entry = new ENTRY_VAL($2->id, symtable_ptr,4);
306 | ((ENTRY_VAL *)$2->entry)->isParam = true;
307 | AST *temp = new AST(_FuncFParam);
308 | temp->son.push_back($1);
309 | temp->son.push_back($2);
310 | $$ = temp;
311 | }
312 | ;
313 |
314 | Block : '{' BlockItem_temp '}' {
315 | AST *temp = new AST(_Block);
316 | temp->son = $2->son;
317 | delete $2;
318 | $$ = temp;
319 | }
320 | ;
321 |
322 | BlockItem_temp : BlockItem_temp BlockItem {
323 | $1->son.push_back($2);
324 | $$ = $1;
325 | }
326 | | {
327 | AST *temp = new AST(_BlockItem_temp);
328 | $$ = temp;
329 | }
330 | ;
331 |
332 | BlockItem : Decl {
333 | AST *temp = new AST(_BlockItem);
334 | temp->son.push_back($1);
335 | $$ = temp;
336 | }
337 | | Stmt {
338 | AST *temp = new AST(_BlockItem);
339 | temp->son.push_back($1);
340 | $$ = temp;
341 | }
342 | ;
343 |
344 | Stmt : LVal '=' Exp ';' {
345 | if($1->son.size() == 2){
346 | NumberOfTemp++;
347 | } else if($1->son.size() > 2){
348 | NumberOfTemp += 2;
349 | }
350 | AST *temp = new AST(_Stmt);
351 | temp->son.push_back($1);
352 | temp->son.push_back($3);
353 | $$ = temp;
354 | }
355 | | Exp ';' {
356 | AST *temp = new AST(_Stmt);
357 | temp->son.push_back($1);
358 | $$ = temp;
359 | }
360 | | ';' {
361 | AST *temp = new AST(_Stmt);
362 | $$ = temp;
363 | }
364 | | {
365 | symtable_ptr = new TABLE("block", symtable_ptr);
366 | symtable_vector.push_back(symtable_ptr);
367 | } Block {
368 | symtable_ptr = symtable_ptr->father;
369 | AST *temp = new AST(_Stmt);
370 | temp->son.push_back($2);
371 | $$ = temp;
372 | }
373 | | IF '(' Cond ')' Stmt ELSE Stmt {
374 | AST *temp = new AST(_Stmt);
375 | temp->son.push_back($1);
376 | temp->son.push_back($3);
377 | temp->son.push_back($5);
378 | temp->son.push_back($6);
379 | temp->son.push_back($7);
380 | $$ = temp;
381 | }
382 | | IF '(' Cond ')' Stmt {
383 | AST *temp = new AST(_Stmt);
384 | temp->son.push_back($1);
385 | temp->son.push_back($3);
386 | temp->son.push_back($5);
387 | $$ = temp;
388 | }
389 | | WHILE '(' Cond ')' Stmt {
390 | AST *temp = new AST(_Stmt);
391 | temp->son.push_back($1);
392 | temp->son.push_back($3);
393 | temp->son.push_back($5);
394 | $$ = temp;
395 | }
396 | | BREAK ';' {
397 | AST *temp = new AST(_Stmt);
398 | temp->son.push_back($1);
399 | $$ = temp;
400 | }
401 | | CONTINUE ';' {
402 | AST *temp = new AST(_Stmt);
403 | temp->son.push_back($1);
404 | $$ = temp;
405 | }
406 | | RETURN Exp ';' {
407 | AST *temp = new AST(_Stmt);
408 | temp->son.push_back($1);
409 | temp->son.push_back($2);
410 | $$ = temp;
411 | }
412 | | RETURN ';' {
413 | AST *temp = new AST(_Stmt);
414 | temp->son.push_back($1);
415 | $$ = temp;
416 | }
417 | ;
418 |
419 | Exp : AddExp {
420 | AST *temp = new AST(_Exp);
421 | if($1->son.size() > 1){
422 | NumberOfTemp++;
423 | }
424 | temp->val = $1->val;
425 | temp->isint = $1->isint;
426 | temp->son.push_back($1);
427 | $$ = temp;
428 | }
429 | ;
430 |
431 | Cond : LOrExp {
432 | AST *temp = new AST(_Cond);
433 | temp->isint = $1->isint;
434 | temp->son.push_back($1);
435 | $$ = temp;
436 | }
437 | ;
438 |
439 | LVal : IDENT {
440 | if(symtable_ptr->Find(true,$1->id,true)){
441 | $1->entry = symtable_ptr->FindAndReturn(true,$1->id);
442 | } else{
443 | yyerror("cite non-decleared variable\n");
444 | }
445 | AST *temp = new AST(_LVal);
446 | temp->val = ((ENTRY_VAL *)$1->entry)->val;
447 | temp->son.push_back($1);
448 | $$ = temp;
449 | }
450 | | LVal '[' Exp ']' {
451 | $1->son.push_back($3);
452 | $$ = $1;
453 | }
454 | ;
455 |
456 | PrimaryExp : '(' Exp ')' {
457 | AST *temp = new AST(_PrimaryExp);
458 | temp->val = $2->val;
459 | temp->isint = $2->isint;
460 | temp->son.push_back($2);
461 | $$ = temp;
462 | }
463 | | LVal {
464 | AST *temp = new AST(_PrimaryExp);
465 | if($1->son.size() == 2){
466 | NumberOfTemp++;
467 | } else if($1->son.size() > 2){
468 | NumberOfTemp += 2;
469 | }
470 | temp->val = $1->val;
471 | temp->son.push_back($1);
472 | $$ = temp;
473 | }
474 | | INT_CONST {
475 | AST *temp = new AST(_PrimaryExp);
476 | temp->val = $1->val;
477 | temp->isint = true;
478 | temp->son.push_back($1);
479 | $$ = temp;
480 | }
481 | ;
482 |
483 | UnaryExp : PrimaryExp {
484 | AST *temp = new AST(_UnaryExp);
485 | temp->val = $1->val;
486 | temp->isint = $1->isint;
487 | temp->son.push_back($1);
488 | $$ = temp;
489 | }
490 | | IDENT '(' FuncRParams ')' {
491 | NumberOfTemp++;
492 | AST *temp = new AST(_UnaryExp);
493 | temp->son.push_back($1);
494 | temp->son.push_back($3);
495 | $$ = temp;
496 | }
497 | | IDENT '(' ')' {
498 | NumberOfTemp++;
499 | AST *temp = new AST(_UnaryExp);
500 | temp->lineno = lineno;
501 | temp->son.push_back($1);
502 | $$ = temp;
503 | }
504 | | UnaryOp UnaryExp {
505 | AST *temp = new AST(_UnaryExp);
506 | if($1->son[0]->op == '-'){
507 | temp->val = 0-($2->val);
508 | temp->isint = $2->isint;
509 | } else if($1->son[0]->op == '!'){
510 | if($2->val != 0){
511 | temp->val = 0;
512 | } else{
513 | temp->val = 1;
514 | }
515 | }
516 | temp->son.push_back($1);
517 | temp->son.push_back($2);
518 | $$ = temp;
519 | }
520 | ;
521 |
522 | UnaryOp : '+' {
523 | AST *temp = new AST(_UnaryOp);
524 | temp->son.push_back($1);
525 | $$ = temp;
526 | }
527 | | '-' {
528 | NumberOfTemp++;
529 | AST *temp = new AST(_UnaryOp);
530 | temp->son.push_back($1);
531 | $$ = temp;
532 | }
533 | | '!' {
534 | NumberOfTemp++;
535 | AST *temp = new AST(_UnaryOp);
536 | temp->son.push_back($1);
537 | $$ = temp;
538 | }
539 | ;
540 |
541 | FuncRParams : Exp {
542 | AST *temp = new AST(_FuncRParams);
543 | temp->son.push_back($1);
544 | $$ = temp;
545 | }
546 | | FuncRParams ',' Exp {
547 | $1->son.push_back($3);
548 | $$ = $1;
549 | }
550 | ;
551 |
552 | MulExp : UnaryExp {
553 | AST *temp = new AST(_MulExp);
554 | temp->val = $1->val;
555 | temp->isint = $1->isint;
556 | temp->son.push_back($1);
557 | $$ = temp;
558 | }
559 | | MulExp '*' UnaryExp {
560 | $1->val = $1->val * $3->val;
561 | $1->isint = $1->isint && $3->isint;
562 | $1->son.push_back($2);
563 | $1->son.push_back($3);
564 | $$ = $1;
565 | }
566 | | MulExp '/' UnaryExp {
567 | if($3->val != 0){
568 | $1->val = $1->val / $3->val;
569 | $1->isint = $1->isint && $3->isint;
570 | }
571 | $1->son.push_back($2);
572 | $1->son.push_back($3);
573 | $$ = $1;
574 | }
575 | | MulExp '%' UnaryExp {
576 | if($3->val != 0){
577 | $1->val = $1->val % $3->val;
578 | $1->isint = $1->isint && $3->isint;
579 | }
580 | $1->son.push_back($2);
581 | $1->son.push_back($3);
582 | $$ = $1;
583 | }
584 | ;
585 |
586 | AddExp : MulExp {
587 | if($1->son.size() > 1){
588 | NumberOfTemp++;
589 | }
590 | AST *temp = new AST(_AddExp);
591 | temp->val = $1->val;
592 | temp->isint = $1->isint;
593 | temp->son.push_back($1);
594 | $$ = temp;
595 | }
596 | | AddExp '+' MulExp {
597 | if($3->son.size() > 1){
598 | NumberOfTemp++;
599 | }
600 | $1->val = $1->val + $3->val;
601 | $1->isint = $1->isint && $3->isint;
602 | $1->son.push_back($2);
603 | $1->son.push_back($3);
604 | $$ = $1;
605 | }
606 | | AddExp '-' MulExp {
607 | if($3->son.size() > 1){
608 | NumberOfTemp++;
609 | }
610 | $1->val = $1->val - $3->val;
611 | $1->isint = $1->isint && $3->isint;
612 | $1->son.push_back($2);
613 | $1->son.push_back($3);
614 | $$ = $1;
615 | }
616 | ;
617 |
618 | RelExp : AddExp {
619 | AST *temp = new AST(_RelExp);
620 | if($1->son.size() > 1){
621 | NumberOfTemp++;
622 | }
623 | temp->isint = $1->isint;
624 | temp->son.push_back($1);
625 | $$ = temp;
626 | }
627 | | RelExp '<' AddExp {
628 | if($3->son.size() > 1){
629 | NumberOfTemp++;
630 | }
631 | $1->isint = false;
632 | $1->son.push_back($2);
633 | $1->son.push_back($3);
634 | $$ = $1;
635 | }
636 | | RelExp '>' AddExp {
637 | if($3->son.size() > 1){
638 | NumberOfTemp++;
639 | }
640 | $1->isint = false;
641 | $1->son.push_back($2);
642 | $1->son.push_back($3);
643 | $$ = $1;
644 | }
645 | | RelExp LE AddExp {
646 | if($3->son.size() > 1){
647 | NumberOfTemp++;
648 | }
649 | $1->isint = false;
650 | $1->son.push_back($2);
651 | $1->son.push_back($3);
652 | $$ = $1;
653 | }
654 | | RelExp GE AddExp {
655 | if($3->son.size() > 1){
656 | NumberOfTemp++;
657 | }
658 | $1->isint = false;
659 | $1->son.push_back($2);
660 | $1->son.push_back($3);
661 | $$ = $1;
662 | }
663 | ;
664 |
665 | EqExp : RelExp {
666 | if($1->son.size() > 1){
667 | NumberOfTemp++;
668 | }
669 | AST *temp = new AST(_EqExp);
670 | temp->isint = $1->isint;
671 | temp->son.push_back($1);
672 | $$ = temp;
673 | }
674 | | EqExp EQ RelExp {
675 | if($3->son.size() > 1){
676 | NumberOfTemp++;
677 | }
678 | $1->isint = false;
679 | $1->son.push_back($2);
680 | $1->son.push_back($3);
681 | $$ = $1;
682 | }
683 | | EqExp NE RelExp {
684 | if($3->son.size() > 1){
685 | NumberOfTemp++;
686 | }
687 | $1->isint = false;
688 | $1->son.push_back($2);
689 | $1->son.push_back($3);
690 | $$ = $1;
691 | }
692 | ;
693 |
694 | LAndExp : EqExp {
695 | if($1->son.size() > 1){
696 | NumberOfTemp++;
697 | }
698 | AST *temp = new AST(_LAndExp);
699 | temp->isint = $1->isint;
700 | temp->son.push_back($1);
701 | $$ = temp;
702 | }
703 | | LAndExp AND EqExp {
704 | if($3->son.size() > 1){
705 | NumberOfTemp++;
706 | }
707 | $1->isint = false;
708 | $1->son.push_back($2);
709 | $1->son.push_back($3);
710 | $$ = $1;
711 | }
712 | ;
713 |
714 | LOrExp : LAndExp {
715 | AST *temp = new AST(_LOrExp);
716 | temp->isint = $1->isint;
717 | temp->son.push_back($1);
718 | $$ = temp;
719 | }
720 | | LOrExp OR LAndExp {
721 | if($3->son.size() > 1){
722 | NumberOfTemp++;
723 | }
724 | $1->isint = false;
725 | $1->son.push_back($2);
726 | $1->son.push_back($3);
727 | $$ = $1;
728 | }
729 | ;
730 |
731 | ConstExp : AddExp {
732 | AST *temp = new AST(_ConstExp);
733 | if($1->son.size() > 1){
734 | NumberOfTemp++;
735 | }
736 | temp->val = $1->val;
737 | temp->isint = $1->isint;
738 | temp->son.push_back($1);
739 | $$ = temp;
740 | }
741 | ;
742 |
743 | %%
--------------------------------------------------------------------------------
/src/tigger.l:
--------------------------------------------------------------------------------
1 | %{
2 | #include
3 | #include
4 | #include
5 | #include"ast_tigger.h"
6 | #include"tigger.tab.hpp" //保持以上顺序make
7 | %}
8 |
9 | %option prefix="tigger"
10 |
11 | function f_([_a-zA-Z][_a-zA-Z0-9]*)
12 | variable v{decimal}
13 | reg x0|s0|s1|s2|s3|s4|s5|s6|s7|s8|s9|s10|s11|t0|t1|t2|t3|t4|t5|t6|a0|a1|a2|a3|a4|a5|a6|a7
14 | label l{decimal}
15 | other ("["|"]"|":"|"=")
16 | operator ("&&"|"||"|"+"|"-"|"*"|"/"|"%"|"!")
17 | logicop ("!="|"=="|">"|"<"|">="|"<=")
18 | decimal (-?[1-9][0-9]*)|0
19 | comment ("//".*)
20 |
21 | %%
22 |
23 | "if" {
24 | AST *temp = new AST(_IF);
25 | tiggerlval.ast = temp;
26 | return IF;
27 | }
28 | "goto" {
29 | AST *temp = new AST(_GOTO);
30 | tiggerlval.ast = temp;
31 | return GOTO;
32 | }
33 | "call" {
34 | AST *temp = new AST(_CALL);
35 | tiggerlval.ast = temp;
36 | return CALL;
37 | }
38 | "load" {
39 | AST *temp = new AST(_LOAD);
40 | tiggerlval.ast = temp;
41 | return LOAD;
42 | }
43 | "store" {
44 | AST *temp = new AST(_STORE);
45 | tiggerlval.ast = temp;
46 | return STORE;
47 | }
48 | "loadaddr" {
49 | AST *temp = new AST(_LOADADDR);
50 | tiggerlval.ast = temp;
51 | return LOADADDR;
52 | }
53 | "return" {
54 | AST *temp = new AST(_RETURN);
55 | tiggerlval.ast = temp;
56 | return RETURN;
57 | }
58 | "malloc" {
59 | AST *temp = new AST(_MALLOC);
60 | tiggerlval.ast = temp;
61 | return MALLOC;
62 | }
63 | "end" {
64 | AST *temp = new AST(_END);
65 | tiggerlval.ast = temp;
66 | return END;
67 | }
68 | {function} {
69 | AST *temp = new AST(_FUNCTION);
70 | temp->id = yytext;
71 | tiggerlval.ast = temp;
72 | return FUNCTION;
73 | }
74 | {variable} {
75 | AST *temp = new AST(_VARIABLE);
76 | temp->id = yytext;
77 | tiggerlval.ast = temp;
78 | return VARIABLE;
79 | }
80 | {reg} {
81 | AST *temp = new AST(_Reg);
82 | temp->id = yytext;
83 | tiggerlval.ast = temp;
84 | return Reg;
85 | }
86 | {label} {
87 | AST *temp = new AST(_LABEL);
88 | temp->id = yytext;
89 | tiggerlval.ast = temp;
90 | return LABEL;
91 | }
92 | {operator} {
93 | AST *temp = new AST(_OP);
94 | temp->op = yytext;
95 | tiggerlval.ast = temp;
96 | return OP;
97 | }
98 | {logicop} {
99 | AST *temp = new AST(_LOGICOP);
100 | temp->op = yytext;
101 | tiggerlval.ast = temp;
102 | return LOGICOP;
103 | }
104 | {other} {
105 | return yytext[0];
106 | }
107 | {decimal} {
108 | AST *temp = new AST(_NUM);
109 | temp->val = atoi(yytext);
110 | tiggerlval.ast = temp;
111 | return NUM;
112 | }
113 | {comment}
114 | \n
115 | .
116 |
117 | %%
118 |
119 | int yywrap(){
120 | return 1;
121 | }
122 |
--------------------------------------------------------------------------------
/src/tigger.y:
--------------------------------------------------------------------------------
1 | %{
2 | #include
3 | #include
4 | #include"ast_tigger.h"
5 |
6 | extern int tiggerlex();
7 | extern char *tiggertext;
8 | extern AST *root_tigger;
9 |
10 | void yyerror(char *str){
11 | printf("In %s : %s\n",tiggertext, str);
12 | };
13 | %}
14 |
15 | %define api.prefix {tigger}
16 |
17 | %union{
18 | class AST *ast;
19 | }
20 |
21 | %token IF RETURN VARIABLE NUM MALLOC END FUNCTION LOGICOP OP GOTO LABEL CALL STORE LOAD LOADADDR Reg
22 | %type Program GlobalVarDecl FunctionDef FunctionHeader FunctionEnd
23 | %type Expressions Expression BinOp
24 |
25 | %%
26 |
27 | Program : GlobalVarDecl {
28 | root_tigger = new AST(_Program);
29 | root_tigger->son.push_back($1);
30 | $$ = root_tigger;
31 | }
32 | | FunctionDef {
33 | root_tigger = new AST(_Program);
34 | root_tigger->son.push_back($1);
35 | $$ = root_tigger;
36 | }
37 | | Program GlobalVarDecl {
38 | $1->son.push_back($2);
39 | $$ = $1;
40 | }
41 | | Program FunctionDef {
42 | $1->son.push_back($2);
43 | $$ = $1;
44 | };
45 |
46 | GlobalVarDecl : VARIABLE '=' NUM {
47 | AST *temp = new AST(_GlobalVarDecl);
48 | temp->son.push_back($1);
49 | temp->son.push_back($3);
50 | $$ = temp;
51 | }
52 | | VARIABLE '=' MALLOC NUM {
53 | AST *temp = new AST(_GlobalVarDecl);
54 | temp->son.push_back($1);
55 | temp->son.push_back($3);
56 | temp->son.push_back($4);
57 | $$ = temp;
58 | };
59 |
60 | FunctionDef : FunctionHeader Expressions FunctionEnd {
61 | AST *temp = new AST(_FunctionDef);
62 | temp->son.push_back($1);
63 | temp->son.push_back($2);
64 | temp->son.push_back($3);
65 | $$ = temp;
66 | };
67 |
68 | FunctionHeader : FUNCTION '[' NUM ']' '[' NUM ']' {
69 | AST *temp = new AST(_FunctionHeader);
70 | temp->son.push_back($1);
71 | temp->son.push_back($3);
72 | temp->son.push_back($6);
73 | $$ = temp;
74 | };
75 |
76 | Expressions : Expressions Expression {
77 | $1->son.push_back($2);
78 | $$ = $1;
79 | }
80 | | {
81 | AST *temp = new AST(_Expressions);
82 | $$ = temp;
83 | };
84 |
85 | FunctionEnd : END FUNCTION {
86 | AST *temp = new AST(_FunctionEnd);
87 | $$ = temp;
88 | };
89 |
90 | Expression : Reg '=' Reg BinOp Reg {
91 | AST *temp = new AST(_Expression);
92 | temp->son.push_back($1);
93 | temp->son.push_back($3);
94 | temp->son.push_back($4);
95 | temp->son.push_back($5);
96 | $$ = temp;
97 | }
98 | | Reg '=' Reg BinOp NUM {
99 | AST *temp = new AST(_Expression);
100 | temp->son.push_back($1);
101 | temp->son.push_back($3);
102 | temp->son.push_back($4);
103 | temp->son.push_back($5);
104 | $$ = temp;
105 | }
106 | | Reg '=' OP Reg {
107 | AST *temp = new AST(_Expression);
108 | temp->son.push_back($1);
109 | temp->son.push_back($3);
110 | temp->son.push_back($4);
111 | $$ = temp;
112 | }
113 | | Reg '=' Reg {
114 | AST *temp = new AST(_Expression);
115 | temp->son.push_back($1);
116 | temp->son.push_back($3);
117 | $$ = temp;
118 | }
119 | | Reg '=' NUM {
120 | AST *temp = new AST(_Expression);
121 | temp->son.push_back($1);
122 | temp->son.push_back($3);
123 | $$ = temp;
124 | }
125 | | Reg '[' NUM ']' '=' Reg {
126 | AST *temp = new AST(_Expression);
127 | temp->son.push_back($1);
128 | temp->son.push_back($3);
129 | temp->son.push_back($6);
130 | $$ = temp;
131 | }
132 | | Reg '=' Reg '[' NUM ']' {
133 | AST *temp = new AST(_Expression);
134 | temp->son.push_back($1);
135 | temp->son.push_back($3);
136 | temp->son.push_back($5);
137 | $$ = temp;
138 | }
139 | | IF Reg LOGICOP Reg GOTO LABEL {
140 | AST *temp = new AST(_Expression);
141 | temp->son.push_back($1);
142 | temp->son.push_back($2);
143 | temp->son.push_back($3);
144 | temp->son.push_back($4);
145 | temp->son.push_back($5);
146 | temp->son.push_back($6);
147 | $$ = temp;
148 | }
149 | | GOTO LABEL {
150 | AST *temp = new AST(_Expression);
151 | temp->son.push_back($1);
152 | temp->son.push_back($2);
153 | $$ = temp;
154 | }
155 | | LABEL ':' {
156 | AST *temp = new AST(_Expression);
157 | temp->son.push_back($1);
158 | $$ = temp;
159 | }
160 | | CALL FUNCTION {
161 | AST *temp = new AST(_Expression);
162 | temp->son.push_back($1);
163 | temp->son.push_back($2);
164 | $$ = temp;
165 | }
166 | | RETURN {
167 | AST *temp = new AST(_Expression);
168 | temp->son.push_back($1);
169 | $$ = temp;
170 | }
171 | | STORE Reg NUM {
172 | AST *temp = new AST(_Expression);
173 | temp->son.push_back($1);
174 | temp->son.push_back($2);
175 | temp->son.push_back($3);
176 | $$ = temp;
177 | }
178 | | LOAD NUM Reg {
179 | AST *temp = new AST(_Expression);
180 | temp->son.push_back($1);
181 | temp->son.push_back($2);
182 | temp->son.push_back($3);
183 | $$ = temp;
184 | }
185 | | LOAD VARIABLE Reg {
186 | AST *temp = new AST(_Expression);
187 | temp->son.push_back($1);
188 | temp->son.push_back($2);
189 | temp->son.push_back($3);
190 | $$ = temp;
191 | }
192 | | LOADADDR NUM Reg {
193 | AST *temp = new AST(_Expression);
194 | temp->son.push_back($1);
195 | temp->son.push_back($2);
196 | temp->son.push_back($3);
197 | $$ = temp;
198 | }
199 | | LOADADDR VARIABLE Reg {
200 | AST *temp = new AST(_Expression);
201 | temp->son.push_back($1);
202 | temp->son.push_back($2);
203 | temp->son.push_back($3);
204 | $$ = temp;
205 | };
206 | BinOp : OP {
207 | AST *temp = new AST(_BinOp);
208 | temp->op = $1->op;
209 | temp->son.push_back($1);
210 | $$ = temp;
211 | }
212 | | LOGICOP {
213 | AST *temp = new AST(_BinOp);
214 | temp->op = $1->op;
215 | temp->son.push_back($1);
216 | $$ = temp;
217 | };
218 |
219 | %%
220 |
--------------------------------------------------------------------------------
/test.c:
--------------------------------------------------------------------------------
1 | int set(int a[], int pos, int d){
2 | const int bitcount = 30;
3 | int x[bitcount + 1] = {};
4 |
5 | x[0] = 1;
6 | x[1] = x[0] * 2;
7 | x[2] = x[1] * 2;
8 | x[3] = x[2] * 2;
9 | x[4] = x[3] * 2;
10 | x[5] = x[4] * 2;
11 | x[6] = x[5] * 2;
12 | x[7] = x[6] * 2;
13 | x[8] = x[7] * 2;
14 | x[9] = x[8] * 2;
15 | x[10] = x[9] * 2;
16 |
17 | int i = 10;
18 | while (i < bitcount){
19 | i = i + 1;
20 | x[i] = x[i - 1] * 2;
21 | }
22 |
23 | int v = 0;
24 |
25 | if (pos / bitcount >= 10000) return 0;
26 |
27 | if (a[pos / bitcount] / (x[pos % bitcount]) % 2 != d){
28 | if (a[pos / bitcount] / (x[pos % bitcount]) % 2 == 0)
29 | if (d == 1)
30 | v = x[pos % bitcount];
31 |
32 | if (a[pos / bitcount] / x[pos % bitcount] % 2 == 1)
33 | if (d == 0)
34 | v = v - x[pos % bitcount];
35 | }
36 |
37 | a[pos / bitcount] = a[pos / bitcount] + v;
38 | return 0;
39 | }
40 |
41 | int seed[3] = {19971231, 19981013, 1000000000 + 7};
42 | int staticvalue = 0;
43 |
44 | int rand(){
45 | staticvalue = staticvalue * seed[0] + seed[1];
46 | staticvalue = staticvalue % seed[2];
47 | if (staticvalue < 0) staticvalue = seed[2] + staticvalue;
48 | return staticvalue;
49 | }
50 |
51 | int a[10000];
52 | int main(){
53 |
54 | int n = getint();
55 | staticvalue = getint();
56 | starttime();
57 | int x, y;
58 | while (n > 0){
59 | n = n - 1;
60 | x = rand() % 300000;
61 | y = rand() % 2;
62 | set(a, x, y);
63 | }
64 | stoptime();
65 | putarray(10000, a);
66 | return 0;
67 | }
68 |
--------------------------------------------------------------------------------
/test.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | echo --------test.c--------
4 | ./build/compiler -S ./test.c -o ./test.S
5 |
6 | #num=0
7 | #i=0
8 | #for file in $(ls ./functional)
9 | #do
10 | # if((${i}==${num}))
11 | # then
12 | # echo --------${file}--------
13 | # ./build/compiler -e ./functional/${file}
14 | # fi
15 | # let "i++"
16 | #done
--------------------------------------------------------------------------------