From 3d687835352c662dcd440d3542d3b59fb10e3167 Mon Sep 17 00:00:00 2001 From: Marcel Guinhos Date: Tue, 6 Oct 2026 22:09:39 +0000 Subject: [PATCH] First commit --- .gitignore | 11 + INSTRUCOES_DE_IMPLEMENTACAO.md | 51 ++++ LICENSE.md | 21 ++ Makefile | 73 +++++ MicroPascal-parte1.pdf | Bin 0 -> 152264 bytes README.md | 77 +++++ examples/contador.pas | 9 + examples/erro.pas | 6 + examples/logica.pas | 14 + examples/somaimpares.pas | 17 ++ examples/testaparidade.pas | 12 + examples/tipos.pas | 15 + include/micropascal-lexer/lexer.h | 19 ++ include/micropascal-lexer/token.h | 60 ++++ include/micropascal-parser/ast.h | 31 ++ include/micropascal-parser/parser.h | 21 ++ include/micropascal-tests/testes.h | 26 ++ src/main.c | 103 +++++++ src/micropascal-lexer/lexer.c | 333 ++++++++++++++++++++++ src/micropascal-lexer/token.c | 93 ++++++ src/micropascal-parser/ast.c | 85 ++++++ src/micropascal-parser/parser.c | 428 ++++++++++++++++++++++++++++ tests/test_lexer.c | 108 +++++++ tests/test_main.c | 27 ++ tests/test_parser.c | 111 ++++++++ 25 files changed, 1751 insertions(+) create mode 100644 .gitignore create mode 100644 INSTRUCOES_DE_IMPLEMENTACAO.md create mode 100644 LICENSE.md create mode 100644 Makefile create mode 100644 MicroPascal-parte1.pdf create mode 100644 README.md create mode 100644 examples/contador.pas create mode 100644 examples/erro.pas create mode 100644 examples/logica.pas create mode 100644 examples/somaimpares.pas create mode 100644 examples/testaparidade.pas create mode 100644 examples/tipos.pas create mode 100644 include/micropascal-lexer/lexer.h create mode 100644 include/micropascal-lexer/token.h create mode 100644 include/micropascal-parser/ast.h create mode 100644 include/micropascal-parser/parser.h create mode 100644 include/micropascal-tests/testes.h create mode 100644 src/main.c create mode 100644 src/micropascal-lexer/lexer.c create mode 100644 src/micropascal-lexer/token.c create mode 100644 src/micropascal-parser/ast.c create mode 100644 src/micropascal-parser/parser.c create mode 100644 tests/test_lexer.c create mode 100644 tests/test_main.c create mode 100644 tests/test_parser.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7b9aa56 --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +build/ +*.o +*.obj +*.exe +*.out +*.stackdump +.DS_Store +Thumbs.db +desktop.ini +*.swp +*~ diff --git a/INSTRUCOES_DE_IMPLEMENTACAO.md b/INSTRUCOES_DE_IMPLEMENTACAO.md new file mode 100644 index 0000000..28735c9 --- /dev/null +++ b/INSTRUCOES_DE_IMPLEMENTACAO.md @@ -0,0 +1,51 @@ +# Instruções de Implementação do Projeto Mini Pascal em C + +spawna um subagente para implementar isso em C usando a estrutura micro-pascal/src/ micro-pascal/include/ e /build e Makefile use estilo K&R use typedefs para nomes dos tipos, use enums para os TokenKinds. use também AstKind e KeywordKind (enums). + +prefiro que ponteiros se foram usados fiquem colados no nome do tipo, assim: Ponteiro* nome_da_variavel; + +nomes de variaveis precisam ser snake_case, nomes de funções camel case e nomes de tipos PascalCase. + +adicione tests/ também + +os artefatos de testes ficam em build//.tests/... + +e o build normal: + +build//bin + +o Makefile deve suportar windows e linux. + +O Makefile deve ter help. build, run, test. + +coloque os exemplos em examples/ + +lembrando que o src tem que estar bonitinho: + +src/main.c +src/micropascal-lexer/... +src/micropascal-parser/... +... + +o include tmb: + +include/micropascal-lexer/... +src/micropascal-parser/... + +.gitignore + +Quando terminar e estiver funcionando, remova todos os comentários e em dashes e utf-8 do código, dos readmes, dos .gitignores e .gitkeeps. + +Não se coloque como coautor, coloque a mim como autor: mguinhos@gmail.com (Marcel Guinhos; https://mguinhos.github.io/ ; https://github.com/mguinhos ; meu RA (Registro Academico) da UNICAP é 00000855041 meu email academico é marcel.00000855041@unicap.br + +A disciplina é 2026.2-MINF-0203-CONSTRUCAO DE COMPILADORES-MANHÃ (SEMESTRE-TURMA-NOME DA DISCIPLINA) o nome do professor é Robinson Lins. + +certifique-se de que todos os .h estão em include/ + +Dê um git init. nome do branch deve ser main + +Dê um git commit -m "First commit" + +Adicione LICENSE.md MIT +e Adicione README.md + diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..3a62d68 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Marcel Guinhos + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..837cd77 --- /dev/null +++ b/Makefile @@ -0,0 +1,73 @@ +ifeq ($(OS),Windows_NT) + DETECTED_OS := Windows + RM := del /Q + RMDIR := rmdir /S /Q + ARCH_RAW := $(PROCESSOR_ARCHITECTURE) + BIN_EXT := .exe + MKDIR_P = if not exist "$(1)" mkdir "$(1)" + RUN_PREFIX := +else + DETECTED_OS := $(shell uname -s) + RM := rm -f + RMDIR := rm -rf + ARCH_RAW := $(shell uname -m) + BIN_EXT := + MKDIR_P = mkdir -p "$(1)" + RUN_PREFIX := ./ +endif + +ifneq (,$(filter x86_64 amd64 AMD64 x86 i386 i486 i586 i686,$(ARCH_RAW))) + ARCH := x86 +else ifneq (,$(filter aarch64 arm64 ARM64 armv7l armv6l arm,$(ARCH_RAW))) + ARCH := arm +else ifneq (,$(filter ppc64 ppc64le powerpc,$(ARCH_RAW))) + ARCH := powerpc +else + ARCH := $(ARCH_RAW) +endif + +CC ?= cc +CFLAGS ?= -std=c99 -Wall -Wextra -Iinclude + +BUILD_DIR := build/$(ARCH) +BIN_DIR := $(BUILD_DIR)/bin +TEST_DIR := $(BUILD_DIR)/.tests +BIN := $(BIN_DIR)/micropascal$(BIN_EXT) +TEST_BIN := $(TEST_DIR)/micropascal-tests$(BIN_EXT) + +LIB_SRCS := $(wildcard src/micropascal-lexer/*.c) $(wildcard src/micropascal-parser/*.c) +APP_SRCS := src/main.c $(LIB_SRCS) +TEST_SRCS := tests/test_main.c tests/test_lexer.c tests/test_parser.c $(LIB_SRCS) + +ARGS ?= examples/testaparidade.pas + +.PHONY: all help build run test clean + +all: build + +help: + @echo "micro-Pascal - alvos disponiveis" + @echo " make help mostra esta ajuda" + @echo " make build compila o compilador em $(BIN)" + @echo " make run compila e executa em uma amostra (ARGS=arquivo)" + @echo " make test compila e executa a suite de testes" + @echo " make clean remove o diretorio build" + +build: $(BIN) + +$(BIN): $(APP_SRCS) + @$(call MKDIR_P,$(BIN_DIR)) + $(CC) $(CFLAGS) $(APP_SRCS) -o $(BIN) + +$(TEST_BIN): $(TEST_SRCS) + @$(call MKDIR_P,$(TEST_DIR)) + $(CC) $(CFLAGS) $(TEST_SRCS) -o $(TEST_BIN) + +run: build + $(RUN_PREFIX)$(BIN) $(ARGS) + +test: $(TEST_BIN) + $(RUN_PREFIX)$(TEST_BIN) + +clean: + $(RMDIR) build diff --git a/MicroPascal-parte1.pdf b/MicroPascal-parte1.pdf new file mode 100644 index 0000000000000000000000000000000000000000..33ba8bdff647e0712ef916492f445dcb7e68049a GIT binary patch literal 152264 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 Grg zXjkCbO!C;;V}`(7-@x~^GjRK$)!`c!Eu^H9>H@bG>&wB}x<=xDWx<&-Qr}EQ=Q8m5 zW`duwN1mPd!-yWJuxQGeBXc(nCvZc;wrWNS2!p=G1V087O7;3$3Cg&DxCnL5zdtIb0WG26b|I7oG$%?5%Zp zn$3DC!VROeRHCvrz2iuOC|p^+m42L$^dIzV)Zj%c{A>$zrXm$k=Q%+PrkR$sZ`ww} zT5N_FHt?jwcKaIP_kUNj0ySYg< zT9#YhH=SWLPHPtSsN|+iNHc7~!w(DE9wyMR%W$ML3{jhU9CB8I+MDmK!=|K+yUMH~ zFY5YR8z)HRIDHOjDV&6G4W^j2Y~6X4&`@W@FV9Q@xs{s;`sQ|urF&(z?5TrtR9&Jr z`wSzgV?MIs{@N+O!Q&OJyUnoc`ZD{cwf2|k1M~0bfvS>p6d54Xo2P0LOf(=;;T$)Q zG@ia+Zy;JvP6P#xz<10OM#{nM59~|my78y^vUbq;p-O;+WCdzS{`f-dJ8JJkiNm&M zmQ)sOBw@;;G{*|0VZy-H#3*Io68D4FirL*f0g}YsZ0%=}F=!<+)H~6SCux>z?fuV! zcNKl~>V^syQ5)HH05|Oi=`;$?M}PmpZLC_(*x+`-246>9i;Big!$5NNWie z;W&^nXQE;Ymaw|Ez9xFrYUY)gT`}yJ0IU?J{O59h1uTQeKbEh(qd6!a zAkcmrjh}T~G=~IzFDWJ1c%O$6j=S55 zWou<$1%)w};I;FS12o>H`W$4l z=Q}SS(g2xWF$w z78dtTNiE^fx@D@R#>w69t7VqmVDa0Ak9HL9y;MvIeWVn*(h1>($%-{}KXgo@(L8d?O^8t2S$Ah?f{xdD8%u2%3ZzO`a|PZBswP-21XyKTQ&LJ zk3>1vpa-T>R{hv+;3Og~9*~c&WVbHQaAFy`H;RK9cEfR~(G7oa8M$fcC>#ONTfR)&*YkuSD*1fk*9JpX7!zJAtI z_lo!1AUkIXc(|g>KlhMmVRQl5WSAQWVM@4{*d(eSJ_QfGokBz&W5K%P$GgGt$QnL> z*O=2ME2d@=N`bI|5Q>mY@!AB@oT^fIa(8UHoCjAd z%t3XOIS+v zVIj@WT-I8vrCAtA<*soRiq3=PE1nik*k;0xL{Aj8dRx}V1Z6m%SrYR=Me4b1XJ7Jr zMM2GrMeXkxr6VA6>vK3X>eI=MFy7jFqw}JASzs6rl9b=%>eX0xGZ(&j1PKsP1|~02 zY;nRHsrfTYC)FVq5lB;w?#QFL22kH<>AzRH9uWXNbDf&CzLx`kdV0I&d>kEXX+y_u zFgQ>=SosimrLVG%S(?GEn@LCcaT%hOIc72Rc0OHz1kiNRtojh@<`|+I(e9Fbn z4tFLO7pVq{R!};H(#%H$4z|Ol82tf19~$;dD2P!J|4a_wWDmFH%E;I=b^v{31gVcP z^gziaQlf=AjB)U!hZ~;Cj!K5S6K$&2%kUGbjXnk0jZ#-Xm@*$iO$@*CLdGUP=ZqY- zmI!0Kdae5AOb3_0-d4>}{?rG&>Z?$trrJv63hPCQvMZsD%g|usFKw`(QU)eRas-C}FgwKL6pX^p-%!_c>$-|y!GkV3Z z!54M(-Y994oS+=X5Nu;n$4{=s%nm|A^@S zVj=>gJ}{~>26{iC z&?r=%^6$WyYxXO&2XF*>R5T@sPSr);_G`2UD+Qk!*~S(qh6Z&d1u+*Y9Y5@=QIdp7{xkvcV`Eg2eO9HpL%g9)K=*|AUJC7dXfIuj(nbf5h8N04ef+fVlsZ zL;$e4|9QmptHyv8z|a1FtmK%O|1xg_c+&kg9KV87Vz^~MA_OGzW|N5%X?(f&wyXv+ z`(0;~Gzt|?gqca-PtGg~A1?FZBi)>cI{S-2)lgPafG#H$CXBVkHZh6tK{;%ik}FeY zgK$vmvlxXP?NaZ=>JO=o4;IG4CRmw!H1hnS%NLJFR{^m*m#n*ahuC3eifC?e)!q6B zCoVYhtut0$6Cl_b7@|c~fv&!k42O#t9!+6mZ7|}CWGodrV%%h30gaEj6cW~MY0s=O z?lYj}bQh=aQeUhFZiJEX9pdVC#*!xLLV2~7rtB!^)xGD{DIDS`vtW2fUj{s(A6CdR za>Pt8{EqpTo;$iLq)IKRy@*nDh>fv>CTbSS$UNG|8CX=0&O@%-ukI_|mOAemJ%P!- zyMg^_$NXi+$@%}}$2y#I%Cav#jU!d_8#m87XR>(M?(IwwBIlZbC(nA5#ws(=NjeVPpWf^*^ON7%UC~i# z7y!8mHql;`0t=R&BGD#KrJaAjj&XH7G!Q`&jtb*ORILJO4@*fuGy$jk$rjUW2KYKc z#8{J{U?BC{?p#(mk2v-4lKxFso1l3YG@S(>=T9&9m(e^M*YDdE;0?S3xG|p5J-W~> z3|ylr$oD2*-;V<(3}y>p%S7W+K_r-feJMA|9YME5^a2DNR9#wWUd9&uHoyKDef(ma zBzSU%jBML9>zHNMLx+5!)hFXfYXhsKO-=-(<2s^)i5C*EL4KVXoJkXHgSH7I9EPZx zxQwK9I=!){L!~94cmR_b4*P-g^Sdkk_SAd=d4S(%D3=a?Z zmEyzjHIS^1%5iOMqCXtHDbOx?###&`$FWZIv`G$Ek~e4i%^*b>IK}0S9W?VM7u%wY z;VK_P-*%CbE@!us<~;ATX&~G3EfvbJ&JNFsj5JN_EcW57pWQ%YmIMdS?gdY~<7FPN zi>6#VdVM{ydUd5nSdI<}#nrUa&$-U_QS(c)%H_lr^oeN&?PEe@c1J)Dtg|9e9z&M; z=Ea)Y*lU~aaz4E=iQ>n}(soY^ed$q3z?Xa&wrqj(G<4*DoohC9^p;n{zVzjqSp_GO zO_oHC#DZmNdM{v5DyUm!w6n6!J?knTzma3VN>V=lo}mE7i6 zgC^RY^k??*B~$kUoupK!Qlf;_ib|E9xw|)dLMZoYBQ>_im7U&UCWy+#^QN24M?m*5 zA}ijSKds8Y%+#1UerE=hr0x2N{y8;?B8;}yU8fEmV%NNvyJP0dW3Y$g;9}4W{K)V* zXQ4nS3K>|x=6%G!S%&cFb{9&{c4xD|I`|Ud>xf+BF%(Zla%jVIXvS5SwwQ1YB{fV? z#fbH;DUhjs5$Kr(S3!p3{YsF!eMJbuS$mH7 zNc+&NQY(hDb&7_Q)ZdIEu!3ENy#tnI)sp^+3xF#Ua3JtIsJIFR!Bk-)3y&CL<`-aF;6mnEOj;(Q{&m?LryZIa$z$HZ#HNcj_z*q#Td$sP#S1htO!oqb0@~1GpJ{)tot!jz9VHn-NGcqXA_XYIvj|+)OQ2q)cy;#=B(^X7z8T z`G=awCeAfUftCg8%4>N(T=Dk0Gzab954cGjW54Oz)oDIzzy1KRulU%tc0M@H@3VMj zh77g1T+1owBYG-}n)|9ASzVQ~!7ys}eSPTcwlfI3snYaC+g4<;c$p@Uv$eC^2`_lPQ)gr~|aJE>q^}Rl6NUj?V=`o#gMSvVKs%M9~c#zjSE%Iv4S6 zkAl%IqcXJUT|Xl*h<0sP(P_}VU2V_Uf8IuZsh(h*c^?p{ahA~h(|PbO7WIEq2(U2! zcDsuzN!kId#sTF)9$nhB#_r?!N?bB;-m<=@BL$jzq=sP%UmE8tT9-lY3IqWvB?mDM2LWWuQF8@ z_)Yvp_JbUrD4aC=ZMcPDl>@fEhYjcLZ!&aiuj>WR*Z~nf_2I^hqopJxuuACjYjRt# zntIA%uY7Mn+UZfMf0zoEzhsg*nSVQ)Rn`969J$Gd`@wr`Ix6&&3jjm|lDs`p^(R$; zi7O{3hYTRq$lnws1&_E0&s6d!%e+`;N5_^riYF1SQhE4zcBY_}wbuB8<&l;9Ez+-` z#9k{W<}6p=%L9a^98?ymL;fgjDT1HbIBqO78=49#tF;`eL;m7~dz0&oV1LCyX0J1H4oCJcrq1){UK7bem_Xqci{UIZkqTgu>pU&fB0MhTx1Tdfe7tB0EY zfu9t*OxWkiOE?L1<6&{3L3S%%*2fT&vMIUN2Zyd&gitOGZHmUUD*?35Q=gE>C!>{_ z^!nKo?3L9#Rwas#DCyob|0G+*vZVKZviO-($(b<{)DyKoHTu?5_@J`guzi%Aji(WP zOHV0oH2z}QCNA4QT>*l#f53-vNxwIgh$Jn}0VJ18qHkWrl(E3>WPP5VH}SiGPuvVF zEyb~wccBgfaxI?5=os!G1_iS%jy*}Q7YQJ8b$hLra)p_nyJw2$Ft0Ru)O6_PES|li zTlMO9(frYoiVXnr+&^7aERh4}v4Vq*)6$c4HV0OFM&YvX8(%*!e8qAfr_ilk5HuvO zHj{sCE;qRIJJ&XH=5)OGMhvpk=?io=ndNaYBF7rj#%5{bRxe=UL@7_uRJwO6O3JZ2 z#s7S{=s zu;5(x78Oli$f=NZ55f=%;9(5krP6Nb@Y?(5WwLXZh9chPj}4FRX(({%9*{Ck2%rT; zDdzW|QqFvC)2%VWb$-Za3A;RAoBY4R zCx3r_xqd;^4U3KW(+2#@1p9XzH5OK8W+g@iMmB{B0K&+o%*e{hp~|Qr!L-B7!5AF2 z>$eC2!=+Ui1cgJA?4M5`Oydt*PFM&(#8guUbjT!VBdLwIf)Xb`#h-U{Pm7@1Cg0hB6YoEs_u>|3RWObklQ%-ADv zBXVPi^RlW>**gxcEO2%Pj{Lx+F?b`1ObivDnlgS5eTiM@X+nY2O|{-J(fQgCJ8AULs~sAaS1p8XE^dzBJ$ z0EimOIZ@o^bIb*Tw^K?4B&R9jcb_)@BTNP6auiVV^!R5X9YWAKU-1x5qfHNeWEf94 zLodvnQ*>a-RhFFiJQQ~=-e5?R$L!0GnQRH6E#EK?GogEWyGTaT*_v;V-S+c0^s5yY z6S#>!SR2n4REIbpnpPz~jgCa1CLO=iu=gsQoZ{DTzN8}|4{d`VuyS=PFsYy@7m2nv zZe(u<3~`5jY9S7{#%3@}q7Zp-MKSMCRQCusrJxkKbRX&v!6MN_ZU{`jnTt1#f#|&p zIRw9U+k1X-ttmL$ySSG`(fIMI_q8)8a7Eg^XTdvoUj7@zut}?=D*a}V6I#Bd4jn&D z+-ne)Z<>SRkxL<&Q;q89=noEjUtzCqlME~EuxVXu?_-`m3-nH!()PC;mP+b&TE9%Io(YDITQ!OQXm(pNHG4sp$ed z3Gvp}+t_7GC~2DWlEmPCBZHzS&tc}qX=Cr#s|I>x|6Q~q_NkYr5Vh|gM|)$KtlvLB zB6M_SzPY{u`i8v&^V=Ax|7o-QB_6~6yOWY^f@B;i6`=Eq7mPL#$7ru>?)UE)i2%M> zQc$c?%V*-k)sEz&Ad#qs;g+BYaKr^7-}-2l_(Jrn^RmnW`R!@vwp-`?={QSu5_Zpc zee;sJ1)GPc2ow~Xjy+1=-R9#!h0G*l}| z%PcTkUbcz_E>58)YsH@Z&2nvOS~~(3tcAl2VR^!?u-aH{Oyyf)6*&_z|APF1)KYhP z%iX2AlYOkB(E7??i_v2Uc?)g1BZu~OZyMU6d8gZ5X4&^j0pXMFq)n%Qp%0RED(y~L znn7>vs+@&50J3;LWca!uRtF74bVnFBjuYqZ|^+{Z8CWTS^Y+-{F0%!wC{uoxOTzUb7-9d)2 zvM*dDOW*$BvRJ^WXLD=JocHx$Js0LI9Ua{s>jlUVE&8Sm1vy9`)5C5li({lr4$`%Dh^GMOVPwZ;zn)@ zI)vNffSZwSFS5S=OPwZE2e9vGeepO*38B6n=RNt0y( zMT(?M|3U7^Fw%DU7I8*@bu2)3DQU|G!VU4UK>-LHp&UpIiTa=;ET`}OE60@n z1lo6i?45>DTI@8PZXVe~ic%%hz8Vj}dPtp+R4)^x1q+3_UJ)0ZSCssrmswDKhJ*UE z#}Js?mct+b5BvkKC78O(G=AFwyapJvY(k9yEHB+6ZI~zh%u$y;IJ_GYD19syxzp6z-%Ph|qscr?OcVB6 zV&_@ep`O@e_|sA#i1@ja zC45AovxdMfbAq&8DKXDXlHGeb>y8i}7*YOD>+LTwIriVX;;5={MUisB-CP5TVqw~% z?`I5{#O~i$fyqi+e+)@T@qVBrVG*SC7bQms(CC7CpNyxiNx=M!zf3jigBZpbj65*VRAG9e;%_3A-4zF+u(ou|)2tzD? zF}?9Bub73GFYgH@kU(8^zG38lA426CD!dmBd1RJY>UdAZx_sbpN3(_8v2S8!bGD zINIHan|pHSofe6jfa*p*9X+E@>25<;&j&pJZR-k8+;_L0$&cxF|FyUutrx0O<|&H7 zZE%lZIvDRJh6aJKXYf$EvQEOygm5db4tu0X?o(PLat#szv3Id{Zuo(vLa+4t$?)^z zwawJ0)N^003&-pr;C*tTPZV79IaIm3tz>lp<`Bdd{up2VOu7xsSEVjQOi+YkTMJUo zRBBu!v^&Hq{RzDMyD8lWfcHSxqOZ@xBz(l*4wjG%q@5KX*8JL}^bJFVHE4TLNF7Bd zdwqTGgG%A)d|>IxBl;mR z*kc$++3lT>u>ed_rmT})X7H&xlp?Qcq?Uo9uDXoxJ{w+j^JhA=sV?r=?jfda<(D6P;3_N?PN|vBRsSMTQAV}#e z8UPm{(goFdP~9WeN%-Nlsa2gp_4Nx9;ZX)s`2j1jp3s7iLkmbpw9*-!;fyoQP(hFDxf*9)E9?S^3M{Y2MIu+3E_tz zg`+_!(y9qa{M@d~OaW8g1C|t^x_9Bp=}HI{j)X4alz;cRu^5Qzq~3Yy?!d?p9)qzi zd0uV##rnom%UO<_M~Jgw*6?RM@yYkE5Y|>D2`6cSnonf|(=w@4Rxl z>ZR+Wb$7vy0wEs9FfCmBQMB{CKm8~gs*StHdnvtz)C0087T<#kL3Iy(;UuSUK3>mY zu;u2Vb;yg{n-$D#23(dAzbO6G{K_%DEmpxzfXw;cXxfB3x$%s39Q4h)R_YK+{i8-d z^V&gb7}rpgdz_mow&M^oZtz!r5qc_Ud1PT28eSo!f&FF&%LzDz?kf(bB=%-@5z~0w z(#gTmL+1mu*3aD?K+-2NRHw1W&^WE4CssC;A@YbC0MqN1K`i_PU3z?L@R_eCg99ID zq>1|ZCg2Jy_h;x#O5i)9TVLPh8P}rXjy%B)rbGuQCUJFb2_jhi`t81QK4aL|#j8$^ zE3fx+pGy}tz>ntC)iVl@zYgsgGSb>hMDZB-AysF!U|`dpv-&)L4?!NQee`_u1Vo@f zIgb#Ce>z7063S#||GkJ%NjfeNpaTMQZ|hQd2)^cIV}o6PZB!;L9*^`mDKxbu#nOX< zEam2;hI{BHKVaOL4ypD2e(#HQ*S7;gIyX6jhhP}RpStL))nZK6M3Wu~`8}%3m!ty; zj&_AEt6YwOR@{#2NH{ENEKp@rnA*xP!6ZXxa?xTWunCiSsnn?gc0eyoI)|F#2gmi^ zGAcgpjuA?k8BPLM&!Wc(-83O=c_i%VlZ{=QeS7++&yTY|n5;=BS&~0=nMrjm&fF~W z(hNQH`!ovp-=i^LN=tK(y1kQ4&c7#K8{n77ND!H;!Fa6%f#KLA4FgJorrYA)F6Z zS97VnzjH$fPpSq>)wS{<_!i@`=l2S)fHm3r$Mgz31R&9_2wm(SKC(Qd0$;*s@N0QP zq&@@4OrIhA5+Q0}b0cZi38i2hKPSVliD}NZX z{H%tDckVfA58@mM)am`pz5Y7O_+f4GVWvU!C$gfR>{fZ?K|WDdcP0cjNSM=~KA{`eFB10@)h1YX!=UZB!5H4O5@qfs2dJiEvvKjC6u zq-C?{gS*g11B4*(aHB4xAz|QdMI>lHPOviHwSk##`HD*@$z8x%o;xBl{i^y~VA^;f z9Ie`yyf0yktM34Pn~V|Gc`S@Q<-??RQbQ;G*3?l9rv`un%QJY zZs)c4UucE4XR`CEM_?kM;H#a`li%sLyug>usa;AgSFx6}t5JShlxla?V7~nlvochz z)s8ZZ6Q1iphs7qCcG~Han{k{@kK0H2y$+&zL3*3U4nQacRLe1utygKq+;j?7g z&E5eGAn_@fmncaiki8Q8e8`DDK%_;$VZE_sWPd3wKWy|9!3@=dFt6#bEL3W&G&=YT zxYg-XfM{AvwESBr1r5@|uCxvaSSR_GX#hk{V-8(~*Y@r*yGn2&nc{-EzI1yK7y4m@ zz4?VHrBgY&!yF5wx<$)5r25^8=DI=_NYXG-t_{y>qnZ_{bU>nr<#MB3JSg0|6&h%} zkY}|HxVf;_k4Bniy`hrczUc@fBAjxGvvUKA+Hc*y>?H_c(<6nUdj;(5wyP{mFpxDT&*G5yQ1z!+82ok)f@z(9aY6 zc<*dMV!R7gJ5uur0Y#F4=7wkbX(;%ROK!1ztBkd2%5vI9bN4drzEot(c!LZl5NRvJ zxsiIo%wm7Qj*@bcGUf%Z2Yry~0^fui-6kS}<_4EK>4G1s7$eA;y`KVZ5N>tnD-npA z@DQddN~yCTG+M#LM^46$#ZdYphxJKA&&4W9EZOJ3`zOpK&~Ssh&E#;5@Utq*|{ z!@ciw+@*Y6JM+uzMRS0s*l<`A+FHTquP_t zo_af$nR|9x+s;1qBbV>*4A>600&xzxR#^ zOUsfxicU*6Z_|CV%DP+i0-p8Gqx#cS{Ut!l#PwUgsHz}|0?=&(IJ7rGY>O|z=aNP7 zAD`aMgV_$DH${^Y%r<|OrlX9EvdIHx`>@R^459KXTJ;Nx$7_ z&5`wSMWoo$Y6ES4W`*Ulg3em!I|27~Tlr$E=ynl%p!_O4KI;nWi-Y@lg$Ty8u1#Y| z>PeDok=KMI;S+FN!6%46jl*Apz%2i6F6xr5sw5kCMg&lShjsW+JtE)my55>$u-vc9 z`F>-FkA#O|U7cKn2*B`8ABN{LFmp1kD)@NS@8snYR&xR*3z2*ik_w0Y7{kl6w%}a%c-+&U zsr#a&3{V9i#}CYdWebo!R{JrfQxKWxlJkw4y7;i27K501HdxX!{v7PW?W zKJi|Yl|Xh!(qb%WEW6&8qJOST}k4X~^G4X}@rh5==Q`*_bENUwK65yf&(RRFvH zw!9?=Q(IG&AFSdbl>M9PCHIyeH;|1+IYnl{ufgGN|&|Q?5fBFso zf*b!JGGyiYm5uzec==CrS^!Z4`2Uy4@c%wy0vMhCZ~bbS{;|3J3$-Zw@9_VxghrDI zYNb=z2DsV87i(-=g&Ou(iKU6%RwOc_0!JNy{YND&0bYS-PX|cLWBH2%xn5=B53f}g z9<4VHZd}2(&9f55ulEl(XT%(yT)Fc`gtC}*jg93-#grg*lmyJyUfGIam9KZ^v+t+b z+wO2`ISg+OwW@=!$V$u)$QILIUcm5dnPfgzlS8{BClWe~?4ELY$xs5ls{ z425mq@4pPTUR^ak1Wk37v~~=X6NXFOc-b#l%ty!SRu0t#l6)nDYR@`(of+daF3qS@ z$zd(P_%v_05fIF6q{i`~aZ-_Z&_1Ml`;9}qv#_83j7x`2fwFm-mF?j5;lec}*Gn_j zBA)B#R5AL6u%Q!jLElb>;cHrTBow!)w390+hdn#Rgb;8>K@l3|T=$NdRU3$K1G)Lf^&e-rym1s2gkoOCcC2Zp%rMm@W4 zj^u;=h5HjoVQsecD5CKBcFP|3L5cc(%w)8#Yi_2SF0?}A?p3+oD89b5ZL1l4Q?v-ot9w#suDGzL%Re(rBGB<8}z5>rQLN=C6_< z`QuM4Nsn;6z#z}~);s-uANQhkLNsjbgm;MyPJ+EfVD}1^CYpuFJqf=S$UZ)MHs7<& zOh3H7fET55{Rz|j$E5i$7BUOlZ)Jl3oktuPF#ywq;nxFCqdhMP4dwq8$rGE64uTQK zM@m5b3MY`64Vj5v6j0d@n4mhqku%xz#+IS|H%*1_qUDFC`6K;vqV*owe=u$OeC-(? z8Od3e(5v~v{mkY=mhHa9wqeD4g@QaeNPW$rBW{33iiB{$W$d?*TNW1sLqU0oP7|)s zR^|Uq`-_{5lm(-X%4KZ^EiEH2$1qOx;lhDcQc=LJZT+|)?XEYFFiX^ zxaB-1UGo-04r1J9mu!Cr5}k3wbvg>)U%pUmU}06LQ{el+X8XMEnN=Q z>P~bfuPC%vlSFV@NGlrd`1J zF`c|sR3kT><}R0*py3+Dz0*^XL%3Ha-R&gUxL}+`ycJYIvG`2!tt?~)S@gm$bv03V z21pF-<;ne7m*s;QZRu~CRdTCh`L6m|?jQ3@-J>79ouh-c2eIv_7leCi_hLgMKbLl$ ziXFe$m6hz2w~gXyQszP8>_wlWD0f+J(&s(t*UGNvaWl%T9m;E)A+nLT6u@aR$5;-f zFs~|sbHPy*X19vl&2;mg63av>CQxt-Q~{~t`JyCWUN`6W1GP6UjXx%|pDIOEvwOG1 zF5SzB=(0p7c$&IFUP_FY(_72MM7w|3>s@vPlc4q>c&y}M}6JN zrX^j^%CM&`5ydS2NW}rYWv9 zKKel{6Ty`Y(mxsmn;BSym)hb;EKv&Y)6RI%gID)uS&yTERH(7b#85b3Uo?FbV$d9HO0Jh2;uFR%R4;Yqv*X2ix@>@> zgC)T0@XHe!ckmNuT(98LPYh$R5%D zy#j|Hn5XYr8`=yc9_=hAgeRZs`3$J~3p1a*pl~8E^oqZKH1eW-B6XD{MT_1Qy&n*) zYVOG=C!WbteCq*0Q${jSN(>oobXDo_Gabu$u8KLjPnJntJ&d4bBo?0&r{nE;Z8=Bs zo61Qlv8D<%RTlfBI$Dgf7gQ+kpFr3uyzlv~7bsAd%Y2%xpxO;g9HRpvM|UBUNaz~I ziA=Lr_ZOFEz_2sF7Nl$W4nhq zZF&wTzqr5PD$>KgX3@cKUP}z*D#=+{weX20mPwq9pvfB#+lXU$7^Ks<4kxZAZJ6|i zJ!SZ9yB%s4{WM$eDQ_@Kd*HqqPZ(N!oUu~7wCMkErZ0T1=s3~WD=6jjje}S#LuD_S z&>;pb1=%sr0k44|qRuZF$9*$%PwD{r*%f~8st7rKydyo?=i@k#YbKoQ_fj)NslnVU z7S2vkGk_}=I#`((pX^EXWW}aA3~AW+@~T8>w>xCZy}G%`D{xgT+6&}+o5iX5Wlklp zqjkjj%z^^z>0;@dvT&IiLf=(Ws~=v~UHi@cx-(D%Rc)#^mY zi3qjfkurk^q%(%Z_#%NOz`aeNj|{)ing`IdRmS)TVZoi7TfUtaHFRcm-QU`)?hQg` zS;_|7*T_5=0mS;n!_0x32bD<3AX`tjkKb%`^8uIPrVlbT!;-HY50V(kcX+S}=noV< zp4Cfs)Da^G)0~H@$)eSXVuC7-11|XFhtC2Avs>9LpEC#N<~&Dd8Z4#M`JhmFDz{JC z8m^vh=sl3AozDcH+?aGwh36hkYkGRJb|mXFT@rBhm*&UfXks=xl)mx=hu_b!1}G{O zfJb1f;SSG~R}^jzmdu>`SiC|7Ie?RpTQP3Fcnhd5aw6E zE2=Dz8<4Cp3K#E@6&h^YHn6@3NEL?@ODVr?X2^Kk0BX&8rp_%|)ly=E!*QR?j!7*z zCXQoL2Uqfoy?zQ^G>ADW?ZbvJzYTXW!t8;kw_=0Qx-89Gm=7(oCTArlJp*v75II*4ha@;QRN>Q6ki22y>Y}`G)SgXX5M!PO2lRQksBo zQnwUzrX|eS(&RyhmMh7FsYAO}3s-DevkpnSmrJJ&`&Htz-PaDbRVTzq8uG{tROd7^ z2);ct;K8E47;AgwSQp9|7nptKPjy$Qs)D9X+-^S=eV z35N2*y!8;3?^sF*vk!F&UX?ez_KZ?kqTv_(I0`QvB}vx9qUH_2JoB#fKK{zD_lG0; zpLQC5v8Y*ox35r*`zNpyz0dT6HDRRLAB>9nY`E&Z?ECTStW*#pzYrogn3A7V0NmN( zy8^OPu@KzqV*9>yul8J@X3zQfmU9Z|QSQ@q1 z7th;QXfm1)YY@ITi4vv3Wl&`^ozar4gDLEOWQ% zX*;d&$f|oFiO_L4N)uCR&EtFdLJlfbm7D`|6VB|#KJCflqh1m%9#Wk{ZO8fH2XeyEe8uI5BCt_E~4?ELkF`g%zFubJGc?3^5~jHiV^oj zZdoxXZre22_YmBCM>Z^zd!6`=>&aAS)4OQ_^-7<79k?;n7mtZKVZ|7Y)bJ7K#p?Ag z($aCK74`6jnSzwXIH=Ef15N~2MT2p)(wK6vV<0M#L#zjU#Gc3+?U^FC+y z3OY$t&i&w_0}Y-_LL#k~b7K{wWy<_MI%bm1T<4(;VTwu9olBkhgU&Ui_bcMnDBs%$ z*TYYu1|LHSid=1)kXN0Oe>{n; zE=siFH(s)@V3!bdIFNW=6TOsXED>vhCzFNmPTZg0Vj<_@r_!@d-JW>X5GZjrW{sZQ z+qQ!L30~OLes~A7f`C=IX1+LbiE*m)$<&k;E_90~Gf$3?fU_ceU>Zq9m^++m8Ba;d zv-xGVchtGX+)v-@YgJc`QzcQi+M4N^ZhRCTJf)f`qIP`?`~FnThGTpOb=+3zjgEjC z*%3V5Crin%G~@<;+m!DeENO?eAM?bIh14vymY+^z$HT#Z-8TaWw zU8pS*&z@fkXR=5NB}e7-`C2X+`@wBJ$szMT%f6Cv7 z<8*8KL;^7IPK5Zo`g`}~dL}cjsj9Zxjk7@l)v+OqCyKYn@6HXOee_0f=G3kBJ!p0G z%9>Y`ZXJ(o?C0~c>2Ql&-PSU=W#D-UbGp)!M(3J76XVBhHa5AV&@EikdZxTe282Sp zC-e<|*JJ*0b&&ZVP&E-x!GwRpZUBt+-Xg;pH-QKh`>E9o2y|&54PKyq=}Q z2H$hy{-E}R`ncQK3U#MS@~XL}{x-_V1$%e-$Q1{H*WJn}MF-0?5)LE7<)PAUsWrbF zzErDn)TKgp@TFif077K;d!HIPpoIF&(B$eFxvnrlp?=-dM6~Rg(y$XF#^5AzNgaZQ z5oGpd%^Zl}_}!>d_!WNhukst71Fx&uY)|M|Lz_B;i}y~@T3BSEI*>Rv|c0MBpharxCD;_yl%L|gNP!qA~Di!m{89MFJcY7GDE9;3%$Qz-}>hj zh@`r=wYlah<2h0_Cf(juYVvO^2dfg0t4q6N&POM&;q6}(KOU3F zP_qkHy=A4`6*V2J4}GLEg1!W0D{&*UJ?neU7sDsF@&SHNE+?@;xD-C8N3`rY)1avo zNuda`$D1hIcx^O$^O5AoxN^RFmM8xgaND5*K)CjINVKjumfY7hQK&{ja*Scz>=)>eW&WP$F#X6O zEbktO_Gk~~RyDGk?0Y0U#TCdawWSf@2;ATM;X`95h-0Iflo07lzgA-&Pm+DU}Z2EVAFuHBB)u`#(};JM;1u&GZ_T&>u5lBek{8DvKptGg(}X4{akYaeMk(mN2G5BJvQM4GPq5C zSGhmLRdN2Zh$0gD6u_h-3ppiw<1ms?U4Txhf>6I+kEaKs%aT7llmDDK6e{!re^3EY z2eJ40MsT>#qjkfKE43<{Y;NAioGrHzZt3#!vHn;AlBIe`)w89NCB~Z!WhovgXFGtMcatf>DQ=5w^Sb2b$tvEP7i}BJ(Qg}ojK)Sp!^$Jj zpG`ZH$3Wx|iY+l~$s4RoKhcmzMc{g7E{vmCs}$yjMb9ST;Az@=YwLIz&foy+VXc<= z>D9{zIvfeFI3eU8J)!&EoBhLe0oGqv6O|POO8>?$>2q&--6cr|XY;y}i1Efn3+4?< zWVnYHSM_jv1?;)5_tWd8wQ%Yi3;6~$%8i#5XO2!f@+B@%O(d;v5|53X;MBtizgT6+ zj-ba&H5w(aAXO4Y{xZt#9hA5Zz4y&RDhyWtUBng|nR=Tia?Y<~1XZy2rcdZK74OVJt`z zrJ0zLWi4okG1))$ZVq=&YBLtWiAhSQ(n1`l-?Q+dcbLB{Q)6sXOY7K!6j*do7S2kzW%|Guwg4w-jTXe;@~^%Q8lgs z1e|Nj+k4Y^lS;p75qC;^f6$0oIetNk04tV%rwVJ~OU%*8P_Jvab%Z9}OipTbd;KDz zR2P>Y%5v12(N>q`tR>%+8LxpM^yb_y?QKB3I=STAuy{NubY7M%^%r#8`~zWMqMWhj zf+dLi{0k6pjC3^>OM8xGlQ{!ks>C9z(=3WIzrupHqee0Hl{#;16F^LX$$1L@c{iyp z1`ht|%){V!8oB7_3ZBdb0sb9keEgygD=EnRJG$!Fo8U98}gY=GQTmgAW;>4}sZ zJ)sZ%Y!0HB5jCJ{D>;Av)=22{<%T>-us)dv3c1pt_{TSpySbkv##vxoioCN%jF(?_ zKBZpCrOIjW-Qc#93gU||_-X7)Em#>lc|Hx}znYI0p2yvb5qoA&&Zos>W z(~AU`-us@$uoCFJu^fQF(o6O?rRyVcY+Cn3f^-#~UZy{hv|?+DWLc6T%>7{79c4-{ zBlR)$NYGTkV5?iGGBLO1+eZ|1UcVP{ec$xdbL%n=d##Vp7%&Xrj(j^nTo~9?iaTw& z$!!S6OHo`<%HeUw2w7hG-CdUrXU|_3?;h&UV~yKwaF$Hqh(hpns*6R$5;UZ{58$)m zTodw<9_M)3$HZMOHw!I{4=GvtPUb@Orej&8Jt}avSgSOG?x{0ZE!Uk{_%fUI;TBhC3z_v> zHN54~XbUq3zPW)bNu-^~>UjZt+{wHqA=bFeD~=d(8xvd5;` z%%nG8TNp1@=}9uajR-jd6EDny2s+hJpg5$pFo_TenwB3KvmgnV|CfjSE?Dl5;f}Cr zsF#KA$-t95rRNSe3hIJ3%WU8nEEWy=781a>a>@ri0>XGcZTIEEhz@t%X=^?B9T773 zIG-#_-u@NjPF^zR?>@?3=CXfR{rI~??st)ne@T{@^;cP9!T(RP#EhK(Q(5A_xHEsR z$^SW7V$fgpOXvV1Z&t9RE(aj(38)gYviymH37}pK?DYV$9{(U=0`Q)H|NrlGi2+?y zfNy{u*vbB>fB`6h0&*7|fD|rJ1n}LgjDYYeP$oc22@v`OJEMT!$(`Kre>nWigY`~h z%q%r|&#CJ~yGx-1s@GSrp_T95t!P>;Ej9@-( zKwJ688BiX8zzCe#9W@Ye2apK}Q0e{q!+xGI0n|%CX25DK;PC*rF#$rQ0LM94clj;_ zeiBf3@b*3{AUp~@^?L#kO9t`>^pSxBAk6wb2XJB80ZkP^w-}Ijy%RhJ!~tbouvqWk#f*Vh@LfU% zC>Zd6a5hX}tr>ua3^;(rdjIi>|8qfOfY=<+F$U-IcSU2sy8Jz>J4IvWpOQ6qlE&bt z0AC(B{7uprXc9mYoEPxofdjZicRvGX#qv`f`5%k-k7)o|0m$QmbNSz+X$DzumMe%u2z2S5V+ zX9Aqt&k_L5<2&IUI5$A}n(2--?Jgk*?#4gw0cv{JoA0gw&$*-I0w=(Ikoji`z=q>a z@%`=!P&uF!-)jn}F9XKqX96hO9fiu>&w#Q4rTFnPplo**=I#nmHX!>SSAgQ&8KS!@ zLO|l@M*x}^V6A@q3}|M6PWsOTIJciA07R+*J*1ykfSLkL`g_)Zv^Jo~{xbn&eTRhx zKL?Q71_arEUIE_09j@r^3h)j9>4xtafbADxE`KDzCh=zp04ay>z#{NHU`6&jaK>E% zcsqa7&<2~mzlmrA%^PeHf8++#=WgBq?jE2%f78(hnmt(K{m0LM`ut5v8_@O!8`2+F zfco4G9d{W3^||9?yGsC7xSNoI6F?VXx>L=%O8}+*uBZK1oo9d|1<3Oc9RL3|vQu{& z;Q#9tQVx>@hq4QwChF7cc0(~uoaW}yZ(mx`M6yb#a;I^)o2-2p@@i>-F)8@qET8U( z^&U3nLpG~Or?$qt93XZYMPk)JrpPO(AYamUx+yk2W>r7gzCL#@xdUa27G(srWw_Nx z<9?-wf2e1C0%GFRz(9Xu-fzoy*}isczt%cC4`+ZYH_`36yP2bfc8XIVfIiEhHo*XSlhewJwqPhErWWai~S|= z6ke?zV!l&ZH~OpC8cFAz38WF6J8^4$o|~Y@E;XCn01#Z|k$J+6@aFRQc5x}LFbC1; zTnBF^whFbkT+_296f(R9Gz6=&PkPJ`mojZRUKC_x4-sohV)Tz|{WJKDQKJ|B+ zyn=giSlr6yDgb)BtBXM0p;xW#=`rifvujbK4zJaV+mL=nEH^iy2LUNi=xN;A-ZGe& z$k>X{^uHE=IDJ6qm?)<%#w5wHO0z7Ywdw`WC#&E8Y7~23e+mLo{wleY0o}h##n*zA zvi{rqJtSv_Drf zf#6%(J0*i1;f9~#HF5SfGK_(|GH&*?)#S2u-$-Rgb-G7aQPv{*{i^1#A?)toL)a5r zgw$f44p@B)425X}^F!myF0Id0a#txnxQH=#4w) z=gfuu_-*%;h1enTA-io?b81BT>4&xXYA4w>!4$S?jNbmo^QZE4)Vk2|$@*?&h@j3d zGmj0EF(xOI`E#vQryXql9=u|~74RU|ucrzAb~1k6P&^Fl&Du~9fpfo6TidlJ3To5D zsgl>W7DeynDo^=0C7bw(ZiD&KzMZm3oyNM4l5M)2?cJgF9v;H^U*ryzy5cHdeRTKP zE6RD5%oi4uJh(RBS*v<~kYo6Q3eIj}^6;?nn&^7(ka)t`QvY|I2s~o^Q78IkG4bD> z=--{_xcL9gPDJ6zA?M#17LY8vF*u^*6P&cQeSSWF^Y-TS9BqQxQs;NQ2<&S8NiPEZ zved2o7d92jA8ab|cWf&CJ)1HQN#5~O1iit!50CU99(11!>d}>utgvi$^Pqnk@;qF& zXLT)(@Iq|!v+N=)bZ^G^!1GIPQr^}whA9Z)V#KXBH|T<;*MrN{#m|l<|27sq{BhonoHeur5iPmW%Y9M-~H6v2ysO-4wmIuA!C=u!urL_vW|ogLLSswclk2igXumA=)FvFuUp2(IaYLT^ZEdw=_Z zrlGwI3M>7L=YPgYX+as+!){h7A3e9WqevH?LxALCQo+gY%;o=~u_*bUjz#N# zG8R4j-#iu#7UeXi@P)~0U4A-0G^|jV%o-~$VS9UHPH0{&GLwR7F=d=QU3%MDSl_7G zo_KpbuH|tEY_Fr&xvc!IYyBZ)7?_U!!Z#}o(8qx_7yz-3*F@g}4oBPCXy-#yJ-y@6pH~xI zJLwF3X&pi{N>l zpjcwOi2^is+z4n|8lq1cqF*GCLc$S3P#=ZIEDBibbd~j`ynyXb0zE@vgZLOyK%jd+ z#1N)sGGa?Gh8QMN25mi2>p>7DU1A6^%A>=jwQ52glgmove;}h!9tI6)J!7Po1NJfzfRbi?FsHp z>);F{Dr{K3+VOB|%LFC+_v@nq{!O@JU-YS2QcPH})e@X=%UqgEn#?Qc{ey|QWM7Er zm?L>P@@2{8;mcC`HmyBXf*8@*kjE0|InLC-$Fo5?7Ya9Sx|jOE_v?W_$zXNZX#)rG z;(;S({(-B{Zs*a(I@re%uk< zR~X8y+!U$Is^>()-bTrC7U*LR`-ac6p-cY6!;-0Q$!k5MS3FDPBuh@kxzl1cHafE0 zqGrvak@QP-B*Q~|$19LkcmtN;Gd}ITK4bdP$;;vWFLZF&8dVF28dP)zwu1$ob)CLZ9OF!|(V_Tj7EoM%{v@p}hL z@u{Veh|5YPPY6JJn^Hlann+o^>g}+L<0dh1jMC6|$5L1mTNKpHwH*+Z`(U&aK>nP< zqZ@&n`e^%;4167aXfr%;c4Yz;XLzTqW$zk*+dTJY7nytKLzX zTmR^6MF+7`jY=CgefksxFVFnJW!1Lf90Tl{ z7n*BMb%r~x1F+vDHggvy%i#;ZR)YHU=$BGj_s;*~4;$zn$6 z^Ze6N%rV~1xAb-RfnPpzo*&UGIKr}X;j}(n?~u48>!{wa@jlG#q-tPLpwE@w4#twT z9%-$fJ9}|xUljXz#f|n|-mpaw9|Oz719O4mDaGw-{)Rc0EeN@WEhG@;iuXEd`(%Hj2KT}^lqLTR9Nj4sMbDgNYRPVF4 zD~eYSqDl0Tl$={*T*&Z;{U4hZc$Pg=#a|T?H}obyH5NC#o)?;U&AITjZQI@(ikt>^ zFTyA_E|ilxyQ`z|EcY0HopUSLN?8yDK+i&B6dHT z(~%~|%EDxT&x`L7+e#QTr z;TqV9_@lnW_7Ca>KSXPQzQj*|lX?h>e&3z|#1-mx$E#QSy@U>Z%}8`VrimOAPLK@X zhG#X`OWV`SjIF)Q%gED#wUJlX_sZ0QefN#IDxmm_#PK=6lY-_O?;Hr`NnsCw+7-xE z{el*UHH-rj{@EtE59vd5r0@XPE&$%>wI<4PKGGS9h!8|D}Z|I>g{P6;l=+#@K zv|i{8b0GHlAPgfSNc@OGF=?q~nvP52Uuv(nOJnRZ5S2i%&ozZvrT!OWW zE?@ti%FM3i>?7%wTvz^pX>#X5qM4cS!qvRV8EbkIPsp(sz?2d*O#d83k3Qy$=&90? za>dxYQK4S7r$i+xRqH}4;gQyqq?wGZn9wB-yJD)4$M@*sZZ1wfbA5r5f41UnT4rE( zfydR}qf-2^32R#M*Zt^}Ipo7?D@t(Inw|9`y>N{)XnHMf_15t+D?nZ6-0QYL!vfyvnK* zPxbn3{P(THd4A}oyT%VFee~W7*(Rc6`o1w9Q;ul)_rWz0 zds^1Y6p(zYLnNo*vaOi)gg^WVsT7;$?x8B80+(@m^W~XUqsTwWgtDkRWWrZRlL=R?@qQ$M69a?~$und@uL?=a{;= z+Z>RCcDPCn@@xZeG)`?QHJ{DSBG82Kj7NX%jQeu6-;YL?QsXT%;PR-KjiYqoz@k8X zzZ!Rycq3@PI`Ue_glqpLPdKSWP3O=|xrp?LJmMZrx^cOJX{YbOh|n1V=^n3}^TSTN zv9&i%=S83Q9}4@Nz9`@rb@x|(R%^rNt4!M(YN_0(Trv4>6f;J?mas(6`H0lkJJK45 zG_$w`6WYc(S!^8W`-m}o4R&SS4nk2B)oJ)UGl`zUITK@uCs1nonpyUeh1jh2!4pgX zfzKeaS^@?Y7nr~&MQv&Z@k7{lcYx3+CVx<6DxMVaK(5%(M|NkO-IGIE#^k`rual5W zo9Wl@HV%p=kRFBVmJp&CH|oDNDy4SiIo2$w*D;Nm<+ppXqm7&9&{%4~j2pvA-Wd@` zB0Q5{2+;Y9p)7b(>-*NT&ySC z&i10c5E^m0m%)LTCeLIPQOWS0(T^T$@7P^+Fs<~XrZMKw;D$p00_>Jl+a!bhqa%=p z*Z?+e{)l$8mMrys>ggKIbzen*%Mk>ZssozhY{y2$S$5;bxIjk{-4X>of8j)4rYU&V zjGzT6>U+-zD(#!JpA#GDkav=X5B+3Wa$)JEqI(fU8uhWuW#|d)dMc~vswjCP6GYuh zXaVD!S!IIHXcyUJi^ret4a6CG@2@Eg6v_HcV>?~**0^+K5OcgpGqfDlTz($iLskzu(2b(gr}n|H@te>OCM4Fg^(+0!9LXM8HrWkch|+ z2++?wL88n*{sR&Pu>ZuGfS(OUsr|SHJeP_6C)x!3Y^J*j;@uNOfl>0#GgtTp zcmaS6|HxVYZv(vG0Kdf_vyUHiK7XaR0PsNI=?NJ4LI(oiKmbAs@Eq6yIMyAd4--9r zXaQhGbRcF|fE zkTWP_tr5&h;h|)b)uz1;+4nv;K27LyE*fyvWF83WX!5NY%X9<$PGJ$7ZIrMY#L zumKa^`|!Z*2oidn?(mt$*+N{=OUA&!aT)K8_a|Alr!VEB4P~D?N+VE>pN$D}?jocR z2a!Hd&Luv3ZE^A+y~e-nGyE5Ljhw$gY`+8XzJGbJIOL!Cj6eG0KlqFQ1oW=+{SIII zulOPVciaQ+CI9ww{(FwctZX8`A8qbTJ$NhtegTXHccaa(W5FMyQ~vvm1%H{F{?i%$ zuSC+)09_Rzw+xmgOVu*!+_M=UB^(B%^t_Ue63O0#tA%tSLd7lk<)Mz?!Pb@7KqH^A z;>TBgy%e-}V|;mU(HDo=#n{M^q&-APmo3OJFvQZRqY2B8_EWPHJK4twJ+_FCkK)m} z-Un&VxM+;JWQ<8&=_V*=O_bPciFR<;wwONL%v<4k#u6t)Wz1tsz!H09{C9_ zG@$?40%?|FiH)jtL?K?ac_ZnVm<44SP23AUZgk|$)Ul||csiCPSNpTRh|7FrH>zGx zh?j9py+9=BiB;Lab>YdhdFBPY_h82-|DJcRm9;2ch&2sOL$ z@$ZH=oo#=*Ba&uu78B8QRh)L-j5G0O(;kqkV_-}%g(PTb1#gOl%j)p0Y2~Lt5?6=M z(~&P#xM9OFqqt?AtBx<=1&f$GN2C%g4s?+cS8WDB{}JMwSe>^QbFPSr|~q)fHA zzntos%@I+Ky0HQgE#P5E zP|(VmMDq^G%y}0)0)$ok+1U2OgZziF?VkpZ{GS@A0027M{~w1Q4rYP>#BBd`{efSA zqk_Qx#;<1kFRksLb;|!XW*Y=D@T(xRbVw} z`C-h^u&Ay*geqzX-S5nX-oW-uX-3SD&*V#Pttw1M;M3#Wu=hgcf!Pv5I4FimtQ68C zh61o@ZRGY&vLU!1vbcQ%<-ZLJuR%E6Z)O}VM(5izV+~6^RXOAoo1Btq-!S`@gCFR5 zDtt6%SG65HGV&(C)z#spU5NWAQbIt58O+@Ho`~7~SJ-QW%-dYAL!25}lSug=`YBOl z81+U-#UOJrz7*k@)VTLBG5zgOaQQ|6>vLqTr8y)dgbNevjQtt->FDBs6j(c^+6XG+ zh~`U-hl33IA7RzR+pAHd)dOhJ`f5xiKZ!Z{dpKBaPrD|hgi5(8G4@x}Wzj0~*|T=$ z+QQnAvGi$D3BAmq#(v)ML7S$&LL$9qt7!>e`hnRo$RG}iG1=*L%%c9Q5w9A>`85T| zC)u1tboOIO!fDdx0Ie6My5i_5!*q(C4jbX zVkH1|5?6hbV(b_!h3;%DjaqvxK}<$=WHa3shRjb?`O@9cok92ZLmvLyX^F#fAdzHv9xJga)kW{#?hU#QKxp@ozFD5q$D{Cg zEtB+-XWtHMOPM+vE7X}U4k$G1#EePQJSq7~?TKrotZ8s7^zKc1m+01DBOXOa(eiVM zoqs?(OovNzN6z55v`qIJ9&ewfHGM=*14Z2}`9?9vE=Trf2R5t}wQnITJl@OdL1+&(hY%38ASJDLm z6N}jmw|n9r#G_Y&3l=HaM&WT6;*n$#)z+#6UP}A&#lKdR6&&rdBq`92I;f9Yxfbq|33Ru#DXP&J$AC{aCr-W%d5mS|IsGTKVj7QWrxFG({`0_mMp{*|w z5}B@{CzA6~uz#y>3hoCGZM6EA)8QHR7x}vCQv}-iD&}lokKAo%If5@0IsJDO^Mlqj zHp%w9eBRQKn`!bm1->qPhhMSRUJ}EM;P{-q(3qfaN~L0cI(q}9D?z<z5*%?`ieKE_0VXri) z>E++Dg>}jYqoq9R-FJ&sv@uc{xozS{iI%@9zU8KVgQt;`-ihN_Z{+tr29a(>I8v+i zeMQ^HqV>dv#CD+nLiFq`r~Ph(`NJhS7SJ!z?aGRhw%fo6a|h}G08*f1>frcGD;=*D z!%~G>ft|HS!q3!RZ!^kIl05Qy;J)~#olyd(j-w45x=0=&#ktuGdYCtbrs#mj8!Fqm z$&H*^DsYM8IYjl9LL99#m9T<`T!G}`!$qP;eL++@0D=m$pPq$<5?+Hb0)BU~WYTwY zE*EQ|g)vL%BZ?am0S%TyZ-xXCdG1>`cq^5!?=Tr?)%i_hVALv%tKb+K(z^o>+Pb&l zrASFs;^?i>H0nH5*O7$>^B^?F!{V*cuy(#W5S1jOJ|epRxSFz}vq|_B(<}b9 zjFz&5_wHZy-%=pga?tJsJ*j1cWq+yPEd*WJTiifmmQZ0L0GBqO{DJpf_$+JGho?98 z4(SEPagkHSYL0R(D7$I#gXY1E`Ol(H&=A~3&eKkosmodHXI!0gUX(|o;Tdnm?20_v zyVqiPyll=u-&1n*sq^&gp}sOALbF@knhR?Yx&YsVoXo)1qsHX6#slJI#hiiPea62m zME*0kjQLk?H?44KGhivufA0dDt0F)@=TaBWU?UR7b^@;V0z6wn4z?gX4F?tjqkzRg zXWyeBRegtX`vD3=;?G;j7;nGCiw8FfOM`|CiIl`xRdURfOOuuFsW?eD(g&^$gg*4; zH%wujeB6%hM7az%1?3jzpYDLUJK)d=_eDqWEG_=IAgV%o8oJtbUQ5Dz1oa3aE+Jrl z`Qd=WEyqDQY>Po|et+nRe@rT?$SMV7bG7j23XHD!SM`_DOd%JVBKPYepMYMyB!|CI ztE%t4DmxHbTMw0eF|QoYvA$&$bNpD;Hn;A>L?7(OjA{g38QpdYLEe=>(+y9?RVPnbFX zmH7`y6dbVpa|`0HE$T|Gs?yY&+b! zzTZ2zpg&v-|L-#|`P20=fQ{j=zQ2QtWZ^Oh8Swq zpzQY#uC5^9(hTMJS@l4QP4UuQhBNmkpAacqKX{6$%Jp1KSU*9yRbBK$UeA3Q6YU=B z7>=0A2folTFS!z*AabsD-@PVw4GrpA6TW z78pgbO>OD2AhQp8e^O?&&s(rR(pKCsS$Sh}-*Hc!{Q03Y~-~fljv&9LXG7uTF6>& zODGk@xxZcMQq^cV5D_bRN7!B+ABGN_m=5K(fmCAYC(-4*0z*%!n{#8GfLuCv)P`-BDK%#2^Fv*^*7rDD=z=#+u)yqKx^=+x)M^?g+> zVsQf-95mK6xk_6L?gRf884{XFqdL@2?u%vEP7oCS9s!|#v||r&SCiLXKG=|i#Doad zXBTD3+EMOr;(Q4}h)vChy83r>=`;_<)3hhb3=6tVV)|1porP4Mj`4wGk&`s!aE6G>>_!6_D`YhUpifsgc2->*wFYtQut~nQwDWXatJ$oO!FO~JcvEZg7h219$1*eV?{3>c``Z=8{+b%rc0Ot4W(W8 z#THS{JSW$<<>9NQt)hrayDKh=5=*KSS_QX~TVC&rN&c$@F#Zn`S1xkGmUmT#R zf-2w=l>=X@ASZj{Jw!Av*DLIOP9*ItvhO{ym({N4C9 zh2NAmtg#4LQC%p4a;7R|Nb)f3RNx}1-D~DTr9z?J;(QOprjVYcRQ17EMvqO=PZ@>? zTAyGQ8kl-?UcubDw~D;g8eyQ&c8I3>#iEV<)uN??Et=LZ7L6Tj(Uc7p1aR`8A8T@~ zrzR(0<6};nLMdM4G&~oNpz^6Ca|!an&WJ>AkCSLhir8B!m>)+sjq4XG@FQn?7CxD% z$jOH0CDnS3=dwp$m{C^Ja)p{$LYJ?bXJ@P(nluGV7h2Yv=5NSB^%PPvdy_-8Dmbl| z$x#e3Fd&(jR-`hoaM|Y>qr%$;&jxvX85FJv+|Hh1n5Uz3X-_TFzdez5;)v_ozp*h& ze}}Yb-4c;UF}_*FGMPFIItKQuScg`E(y77|FJYa+##DO- zC&nR?(G3J~+w(B^zV1rQl%;c9Wl4FCg7UbP)R6&B1?Y@VFj8ksczPX`_TSDj@25#9 zc!?~{-oBeYNg9bsT7s)X9S^Y7DK_RcBFWsy%Db-=Ce}^R>)?w%NB(?Kb`^t+kjGZ( z@m#Mcq&~)M9l_w-s^pRwZ%^5tG)2_3yOITxQPVW_sDZru`xNYHFX5f?y~JIlF>0yw zEk-_{6ojVgCyL?ORuBc_Lz*uA;dAK4Lv(jGjZo*iO(O+t+S+)=olR^1VbfYI{rs4g z)5eQE&KeCXA+5)D0Gk&4!>0B6=b9HHp+vM)(E9O9gtO9;cJPdMGDlXAJ*uNFr(ZHM ze2kZs&ZNm${5Z&@sGQ7d+_2%ihAD_Zp8T zS>09D^-C|Gm}Ke<5?*az@tG*Ci-jjbzgGpwrc{D#EOqR_cTgiRe~)bd%dDYT8Z?F?a9sari*Zn;OQA2E3K&b?hYRlsU!}HsyDpzC zEYs}av9xKak$_H@xJ;IlJ?AR;o~oC|7(90V`l+Z?X$NgKg>Bi8XmI9mu#@L&gPgkK z2j0v^9CQ_Qr2#xci=vkwcnLZj3J%Iyd7KSia>nr?&5lkct3Nq${R~%+`l#bJU862L zztG@%K%;d&G1?8e$u;bKx0I!?gBi=msq!vfD9?uJFVqv5YMX^$Km=DaTf zwb*yowX@euWSDfU(`8%P&*2}?BI=xROD3aCit)AS=7wocQq7NhJJ3!Ku+bytixVcA z6`f+*?bsPttmO~28HXK_n6Eu%Lehbe+mF1KT|4$gNoICGj1NSx{ZR6^E&3n{gt-*rv!=F0J>?Te8;zbP0`J7-#gq8;bsLYY_ly{=)re0XWyw;>f_VhX(}u)vJN!W|H98 zODm|-=?X|gW1LLOQZ;3)w9b~*3QMvT5%HQ)hikD|b%+?>j|rb&Gn-#G6kvtO9eZ&R zkTYM@#N*0!8&oqzt=A2}>TNl=kcCgw(ZZNgl|mv&b(_taBj|P1dF!Wm*dbP>_quA4 zB2$r-SvEssj;p1eHHed^f{In1cPIod>)8%*(GR7*#(i=1NXi#H-wPP<^! z*t;4QQa8w&CuSqI@5s+6q%jR;YN#-=2q+Nmujy-Z
    e6n>i}Vlv4ytlZ#7$DK^1 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/bin e os artefatos de teste em +build//.tests. + +Para usar outro programa de entrada: + +``` +make run ARGS=examples/somaimpares.pas +``` + +Para imprimir apenas a sequencia de tokens: + +``` +build/x86/bin/micropascal examples/testaparidade.pas --tokens +``` + +## Escopo + +- Analise lexica completa, com todos os tokens da especificacao. +- Analise sintatica por descida recursiva, com a precedencia e a + associatividade definidas na especificacao. + +Mensagens de erro: + +- Léxico: Erro léxico no caracter [x] +- Sintático: Erro de sintaxe no token [lexema] + +## Licenca + +MIT. Veja LICENSE.md. diff --git a/examples/contador.pas b/examples/contador.pas new file mode 100644 index 0000000..f70b107 --- /dev/null +++ b/examples/contador.pas @@ -0,0 +1,9 @@ +program Contador; +var + i : integer; +begin + i := 0; + repeat + i := i + 1; + until i >= 10; +end. diff --git a/examples/erro.pas b/examples/erro.pas new file mode 100644 index 0000000..47f50f8 --- /dev/null +++ b/examples/erro.pas @@ -0,0 +1,6 @@ +program Erro; +var + x : integer +begin + x := 1; +end. diff --git a/examples/logica.pas b/examples/logica.pas new file mode 100644 index 0000000..e5fa28e --- /dev/null +++ b/examples/logica.pas @@ -0,0 +1,14 @@ +program Logica; +var + a, b, c : integer; +begin + a := 1; + b := 2; + c := 3; + if not a = b and c <> a or a <= c then + write('o') + ; + while a < b do + a := a + 1 + ; +end. diff --git a/examples/somaimpares.pas b/examples/somaimpares.pas new file mode 100644 index 0000000..98115b2 --- /dev/null +++ b/examples/somaimpares.pas @@ -0,0 +1,17 @@ +program SomaImpares; +var + n : integer; + i, proximoImpar, soma : integer; +begin + n := 4; + i := 0; + soma := 0; + while i < n do + begin + proximoImpar := 2*i + 1; + soma := soma + proximoImpar; + i := i + 1; + end; + write(soma); + write('\n'); +end. diff --git a/examples/testaparidade.pas b/examples/testaparidade.pas new file mode 100644 index 0000000..478463b --- /dev/null +++ b/examples/testaparidade.pas @@ -0,0 +1,12 @@ +program TestaParidade; +var + n : integer; +begin + n := 2 * 13 + 5; + if n = (n div 2)*2 then + write('p') + ; + else + write('i') + ; +end. diff --git a/examples/tipos.pas b/examples/tipos.pas new file mode 100644 index 0000000..5ac6a40 --- /dev/null +++ b/examples/tipos.pas @@ -0,0 +1,15 @@ +program Tipos; +var + a, b : integer; + c : real; + d : char; +begin + a := 1; + b := 2; + c := 1.5 + 2.5 * 2.0; + d := 'x'; + write(a); + write(b); + write(c); + write(d); +end. diff --git a/include/micropascal-lexer/lexer.h b/include/micropascal-lexer/lexer.h new file mode 100644 index 0000000..b1a7063 --- /dev/null +++ b/include/micropascal-lexer/lexer.h @@ -0,0 +1,19 @@ +#ifndef MICROPASCAL_LEXER_LEXER_H +#define MICROPASCAL_LEXER_LEXER_H + +#include "micropascal-lexer/token.h" + +typedef struct Lexer { + const char* fonte; + size_t tamanho; + size_t posicao; + int linha; + int coluna; + int houve_erro; +} Lexer; + +void lexerInicializar(Lexer* lexer, const char* fonte); +Token lexerProximoToken(Lexer* lexer); +void tokenLiberar(Token* token); + +#endif diff --git a/include/micropascal-lexer/token.h b/include/micropascal-lexer/token.h new file mode 100644 index 0000000..90bd683 --- /dev/null +++ b/include/micropascal-lexer/token.h @@ -0,0 +1,60 @@ +#ifndef MICROPASCAL_LEXER_TOKEN_H +#define MICROPASCAL_LEXER_TOKEN_H + +#include + +typedef enum TokenKind { + TOKEN_EOF, + TOKEN_IDENTIFICADOR, + TOKEN_INTEIRO_LITERAL, + TOKEN_REAL_LITERAL, + TOKEN_CHAR_LITERAL, + TOKEN_MENOR, + TOKEN_MAIOR, + TOKEN_MENOR_IGUAL, + TOKEN_MAIOR_IGUAL, + TOKEN_IGUAL, + TOKEN_DIFERENTE, + TOKEN_MAIS, + TOKEN_MENOS, + TOKEN_MULTIPLICACAO, + TOKEN_DIVISAO, + TOKEN_DIV, + TOKEN_AND, + TOKEN_OR, + TOKEN_NOT, + TOKEN_ATRIBUICAO, + TOKEN_ABRE_PARENTESES, + TOKEN_FECHA_PARENTESES, + TOKEN_VIRGULA, + TOKEN_PONTO_VIRGULA, + TOKEN_PONTO, + TOKEN_DOIS_PONTOS, + TOKEN_PROGRAM, + TOKEN_IF, + TOKEN_THEN, + TOKEN_ELSE, + TOKEN_WHILE, + TOKEN_DO, + TOKEN_REPEAT, + TOKEN_UNTIL, + TOKEN_INTEGER, + TOKEN_REAL, + TOKEN_CHAR, + TOKEN_BEGIN, + TOKEN_END, + TOKEN_WRITE, + TOKEN_VAR, + TOKEN_ERRO +} TokenKind; + +typedef struct Token { + TokenKind kind; + char* lexema; + int linha; + int coluna; +} Token; + +const char* tokenKindNome(TokenKind kind); + +#endif diff --git a/include/micropascal-parser/ast.h b/include/micropascal-parser/ast.h new file mode 100644 index 0000000..e2b1b04 --- /dev/null +++ b/include/micropascal-parser/ast.h @@ -0,0 +1,31 @@ +#ifndef MICROPASCAL_PARSER_AST_H +#define MICROPASCAL_PARSER_AST_H + +typedef enum AstKind { + AST_PROGRAMA, + AST_SECAO_VAR, + AST_DECL_VAR, + AST_TIPO, + AST_BLOCO, + AST_LISTA_COMANDOS, + AST_ATRIBUICAO, + AST_ITERACAO, + AST_DECISAO, + AST_ESCRITA, + AST_EXPRESSAO_BINARIA, + AST_EXPRESSAO_UNARIA, + AST_EXPRESSAO_PARENTESES, + AST_EXPRESSAO_LITERAL, + AST_EXPRESSAO_IDENTIFICADOR +} AstKind; + +typedef struct AstNo { + AstKind kind; + char* valor; + struct AstNo* esquerda; + struct AstNo* direita; + struct AstNo* terceiro; + struct AstNo* proximo; +} AstNo; + +#endif diff --git a/include/micropascal-parser/parser.h b/include/micropascal-parser/parser.h new file mode 100644 index 0000000..9107739 --- /dev/null +++ b/include/micropascal-parser/parser.h @@ -0,0 +1,21 @@ +#ifndef MICROPASCAL_PARSER_PARSER_H +#define MICROPASCAL_PARSER_PARSER_H + +#include "micropascal-lexer/lexer.h" +#include "micropascal-parser/ast.h" + +typedef struct Parser { + Lexer* lexer; + Token atual; + int houve_erro; + int total_erros; + int silencioso; +} Parser; + +void parserInicializar(Parser* parser, Lexer* lexer); +void parserSilenciarErros(Parser* parser, int silenciar); +AstNo* parserAnalisarPrograma(Parser* parser); +void astLiberar(AstNo* no); +void astImprimir(const AstNo* no, int profundidade); + +#endif diff --git a/include/micropascal-tests/testes.h b/include/micropascal-tests/testes.h new file mode 100644 index 0000000..a59e15b --- /dev/null +++ b/include/micropascal-tests/testes.h @@ -0,0 +1,26 @@ +#ifndef MICROPASCAL_TESTS_TESTES_H +#define MICROPASCAL_TESTS_TESTES_H + +#include + +typedef struct ResultadoTeste { + int total; + int passaram; + int falharam; +} ResultadoTeste; + +void runLexerTests(ResultadoTeste* resultado_testes); +void runParserTests(ResultadoTeste* resultado_testes); + +#define TESTE_ASSERT(resultado_testes, condicao, descricao) \ + do { \ + (resultado_testes)->total++; \ + if (condicao) { \ + (resultado_testes)->passaram++; \ + } else { \ + (resultado_testes)->falharam++; \ + printf("FALHOU: %s (linha %d)\n", descricao, __LINE__); \ + } \ + } while (0) + +#endif diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..85de655 --- /dev/null +++ b/src/main.c @@ -0,0 +1,103 @@ +#include "micropascal-lexer/lexer.h" +#include "micropascal-parser/parser.h" + +#include +#include +#include + +static char* lerArquivo(const char* caminho, long* tamanho) +{ + FILE* arquivo = fopen(caminho, "rb"); + char* conteudo; + if (arquivo == NULL) { + return NULL; + } + fseek(arquivo, 0, SEEK_END); + *tamanho = ftell(arquivo); + fseek(arquivo, 0, SEEK_SET); + conteudo = (char*)malloc((size_t)(*tamanho) + 1); + if (conteudo == NULL) { + fclose(arquivo); + return NULL; + } + if (fread(conteudo, 1, (size_t)(*tamanho), arquivo) != (size_t)(*tamanho)) { + free(conteudo); + fclose(arquivo); + return NULL; + } + conteudo[*tamanho] = '\0'; + fclose(arquivo); + return conteudo; +} + +static void imprimirTokens(const char* fonte) +{ + Lexer lexer; + Token token; + lexerInicializar(&lexer, fonte); + do { + token = lexerProximoToken(&lexer); + if (token.kind == TOKEN_ERRO) { + tokenLiberar(&token); + break; + } + printf("%s [%s]\n", tokenKindNome(token.kind), token.lexema); + if (token.kind == TOKEN_EOF) { + tokenLiberar(&token); + break; + } + tokenLiberar(&token); + } while (1); +} + +int main(int argc, char** argv) +{ + const char* caminho; + const char* modo; + char* fonte; + long tamanho = 0; + + if (argc < 2) { + printf("Uso: micropascal [--tokens|--ast]\n"); + return 1; + } + + caminho = argv[1]; + modo = "--ast"; + if (argc >= 3) { + modo = argv[2]; + } + + fonte = lerArquivo(caminho, &tamanho); + if (fonte == NULL) { + printf("Nao foi possivel abrir o arquivo [%s]\n", caminho); + return 1; + } + + if (strcmp(modo, "--tokens") == 0) { + imprimirTokens(fonte); + free(fonte); + return 0; + } + + { + Lexer lexer; + Parser parser; + AstNo* programa; + lexerInicializar(&lexer, fonte); + parserInicializar(&parser, &lexer); + programa = parserAnalisarPrograma(&parser); + tokenLiberar(&parser.atual); + if (parser.houve_erro) { + astLiberar(programa); + free(fonte); + return 1; + } + printf("Analise sintatica concluida com sucesso.\n"); + astImprimir(programa, 0); + astLiberar(programa); + } + + free(fonte); + return 0; +} diff --git a/src/micropascal-lexer/lexer.c b/src/micropascal-lexer/lexer.c new file mode 100644 index 0000000..5b165b6 --- /dev/null +++ b/src/micropascal-lexer/lexer.c @@ -0,0 +1,333 @@ +#include "micropascal-lexer/lexer.h" + +#include +#include +#include +#include + +void lexerInicializar(Lexer* lexer, const char* fonte) +{ + lexer->fonte = fonte; + lexer->tamanho = strlen(fonte); + lexer->posicao = 0; + lexer->linha = 1; + lexer->coluna = 1; + lexer->houve_erro = 0; +} + +static int lexerAcabou(const Lexer* lexer) +{ + return lexer->posicao >= lexer->tamanho; +} + +static char lexerEspiar(const Lexer* lexer, size_t deslocamento) +{ + size_t indice = lexer->posicao + deslocamento; + if (indice >= lexer->tamanho) { + return '\0'; + } + return lexer->fonte[indice]; +} + +static char lexerAvancar(Lexer* lexer) +{ + char atual = lexer->fonte[lexer->posicao]; + lexer->posicao++; + if (atual == '\n') { + lexer->linha++; + lexer->coluna = 1; + } else { + lexer->coluna++; + } + return atual; +} + +static int ehLetra(char c) +{ + return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_'; +} + +static int ehDigito(char c) +{ + return c >= '0' && c <= '9'; +} + +static char* lexerCopiarIntervalo(const Lexer* lexer, size_t inicio, size_t fim) +{ + size_t comprimento = fim - inicio; + char* resultado = (char*)malloc(comprimento + 1); + if (resultado == NULL) { + return NULL; + } + memcpy(resultado, lexer->fonte + inicio, comprimento); + resultado[comprimento] = '\0'; + return resultado; +} + +static Token lexerCriarToken(const Lexer* lexer, TokenKind kind, size_t inicio, int linha, int coluna) +{ + Token token; + token.kind = kind; + token.lexema = lexerCopiarIntervalo(lexer, inicio, lexer->posicao); + token.linha = linha; + token.coluna = coluna; + return token; +} + +static TokenKind lexerPalavraReservada(const char* lexema) +{ + if (strcmp(lexema, "program") == 0) { + return TOKEN_PROGRAM; + } + if (strcmp(lexema, "if") == 0) { + return TOKEN_IF; + } + if (strcmp(lexema, "then") == 0) { + return TOKEN_THEN; + } + if (strcmp(lexema, "else") == 0) { + return TOKEN_ELSE; + } + if (strcmp(lexema, "while") == 0) { + return TOKEN_WHILE; + } + if (strcmp(lexema, "do") == 0) { + return TOKEN_DO; + } + if (strcmp(lexema, "repeat") == 0) { + return TOKEN_REPEAT; + } + if (strcmp(lexema, "until") == 0) { + return TOKEN_UNTIL; + } + if (strcmp(lexema, "integer") == 0) { + return TOKEN_INTEGER; + } + if (strcmp(lexema, "real") == 0) { + return TOKEN_REAL; + } + if (strcmp(lexema, "char") == 0) { + return TOKEN_CHAR; + } + if (strcmp(lexema, "begin") == 0) { + return TOKEN_BEGIN; + } + if (strcmp(lexema, "end") == 0) { + return TOKEN_END; + } + if (strcmp(lexema, "write") == 0) { + return TOKEN_WRITE; + } + if (strcmp(lexema, "var") == 0) { + return TOKEN_VAR; + } + if (strcmp(lexema, "div") == 0) { + return TOKEN_DIV; + } + if (strcmp(lexema, "and") == 0) { + return TOKEN_AND; + } + if (strcmp(lexema, "or") == 0) { + return TOKEN_OR; + } + if (strcmp(lexema, "not") == 0) { + return TOKEN_NOT; + } + return TOKEN_IDENTIFICADOR; +} + +static Token lexerErro(Lexer* lexer, char caractere, int linha, int coluna) +{ + Token token; + lexer->houve_erro = 1; + token.kind = TOKEN_ERRO; + printf("Erro léxico no caracter [%c]\n", caractere); + token.lexema = lexerCopiarIntervalo(lexer, lexer->posicao, lexer->posicao); + token.linha = linha; + token.coluna = coluna; + return token; +} + +static Token lexerLerIdentificador(Lexer* lexer) +{ + size_t inicio = lexer->posicao; + int linha = lexer->linha; + int coluna = lexer->coluna; + Token token; + while (!lexerAcabou(lexer) && (ehLetra(lexerEspiar(lexer, 0)) || ehDigito(lexerEspiar(lexer, 0)))) { + lexerAvancar(lexer); + } + token = lexerCriarToken(lexer, TOKEN_IDENTIFICADOR, inicio, linha, coluna); + token.kind = lexerPalavraReservada(token.lexema); + return token; +} + +static Token lexerLerNumero(Lexer* lexer) +{ + size_t inicio = lexer->posicao; + int linha = lexer->linha; + int coluna = lexer->coluna; + TokenKind kind = TOKEN_INTEIRO_LITERAL; + if (lexerEspiar(lexer, 0) == '.') { + lexerAvancar(lexer); + while (!lexerAcabou(lexer) && ehDigito(lexerEspiar(lexer, 0))) { + lexerAvancar(lexer); + } + return lexerCriarToken(lexer, TOKEN_REAL_LITERAL, inicio, linha, coluna); + } + while (!lexerAcabou(lexer) && ehDigito(lexerEspiar(lexer, 0))) { + lexerAvancar(lexer); + } + if (lexerEspiar(lexer, 0) == '.' && ehDigito(lexerEspiar(lexer, 1))) { + kind = TOKEN_REAL_LITERAL; + lexerAvancar(lexer); + while (!lexerAcabou(lexer) && ehDigito(lexerEspiar(lexer, 0))) { + lexerAvancar(lexer); + } + } + return lexerCriarToken(lexer, kind, inicio, linha, coluna); +} + +static Token lexerLerChar(Lexer* lexer) +{ + size_t inicio = lexer->posicao; + int linha = lexer->linha; + int coluna = lexer->coluna; + char conteudo; + lexerAvancar(lexer); + if (lexerAcabou(lexer)) { + return lexerErro(lexer, '\'', linha, coluna); + } + conteudo = lexerEspiar(lexer, 0); + if (conteudo == '\\') { + char escapado = lexerEspiar(lexer, 1); + if (escapado == 'n' || escapado == 't') { + lexerAvancar(lexer); + lexerAvancar(lexer); + } else { + return lexerErro(lexer, conteudo, linha, coluna); + } + } else if (ehLetra(conteudo) || ehDigito(conteudo)) { + lexerAvancar(lexer); + } else { + return lexerErro(lexer, conteudo, linha, coluna); + } + if (lexerEspiar(lexer, 0) != '\'') { + return lexerErro(lexer, lexerEspiar(lexer, 0), linha, coluna); + } + lexerAvancar(lexer); + return lexerCriarToken(lexer, TOKEN_CHAR_LITERAL, inicio, linha, coluna); +} + +Token lexerProximoToken(Lexer* lexer) +{ + size_t inicio; + int linha; + int coluna; + char atual; + Token token; + + while (!lexerAcabou(lexer)) { + atual = lexerEspiar(lexer, 0); + if (atual == ' ' || atual == '\n' || atual == '\t' || atual == '\r') { + lexerAvancar(lexer); + continue; + } + break; + } + + if (lexerAcabou(lexer)) { + token.kind = TOKEN_EOF; + token.lexema = lexerCopiarIntervalo(lexer, lexer->posicao, lexer->posicao); + token.linha = lexer->linha; + token.coluna = lexer->coluna; + return token; + } + + inicio = lexer->posicao; + linha = lexer->linha; + coluna = lexer->coluna; + atual = lexerEspiar(lexer, 0); + + if (ehLetra(atual)) { + return lexerLerIdentificador(lexer); + } + if (ehDigito(atual)) { + return lexerLerNumero(lexer); + } + if (atual == '\'') { + return lexerLerChar(lexer); + } + if (atual == '.' && ehDigito(lexerEspiar(lexer, 1))) { + return lexerLerNumero(lexer); + } + + switch (atual) { + case '<': + lexerAvancar(lexer); + if (lexerEspiar(lexer, 0) == '=') { + lexerAvancar(lexer); + return lexerCriarToken(lexer, TOKEN_MENOR_IGUAL, inicio, linha, coluna); + } + if (lexerEspiar(lexer, 0) == '>') { + lexerAvancar(lexer); + return lexerCriarToken(lexer, TOKEN_DIFERENTE, inicio, linha, coluna); + } + return lexerCriarToken(lexer, TOKEN_MENOR, inicio, linha, coluna); + case '>': + lexerAvancar(lexer); + if (lexerEspiar(lexer, 0) == '=') { + lexerAvancar(lexer); + return lexerCriarToken(lexer, TOKEN_MAIOR_IGUAL, inicio, linha, coluna); + } + return lexerCriarToken(lexer, TOKEN_MAIOR, inicio, linha, coluna); + case '=': + lexerAvancar(lexer); + return lexerCriarToken(lexer, TOKEN_IGUAL, inicio, linha, coluna); + case '+': + lexerAvancar(lexer); + return lexerCriarToken(lexer, TOKEN_MAIS, inicio, linha, coluna); + case '-': + lexerAvancar(lexer); + return lexerCriarToken(lexer, TOKEN_MENOS, inicio, linha, coluna); + case '*': + lexerAvancar(lexer); + return lexerCriarToken(lexer, TOKEN_MULTIPLICACAO, inicio, linha, coluna); + case '/': + lexerAvancar(lexer); + return lexerCriarToken(lexer, TOKEN_DIVISAO, inicio, linha, coluna); + case ':': + lexerAvancar(lexer); + if (lexerEspiar(lexer, 0) == '=') { + lexerAvancar(lexer); + return lexerCriarToken(lexer, TOKEN_ATRIBUICAO, inicio, linha, coluna); + } + return lexerCriarToken(lexer, TOKEN_DOIS_PONTOS, inicio, linha, coluna); + case '(': + lexerAvancar(lexer); + return lexerCriarToken(lexer, TOKEN_ABRE_PARENTESES, inicio, linha, coluna); + case ')': + lexerAvancar(lexer); + return lexerCriarToken(lexer, TOKEN_FECHA_PARENTESES, inicio, linha, coluna); + case ',': + lexerAvancar(lexer); + return lexerCriarToken(lexer, TOKEN_VIRGULA, inicio, linha, coluna); + case ';': + lexerAvancar(lexer); + return lexerCriarToken(lexer, TOKEN_PONTO_VIRGULA, inicio, linha, coluna); + case '.': + lexerAvancar(lexer); + return lexerCriarToken(lexer, TOKEN_PONTO, inicio, linha, coluna); + default: + lexerAvancar(lexer); + return lexerErro(lexer, atual, linha, coluna); + } +} + +void tokenLiberar(Token* token) +{ + if (token->lexema != NULL) { + free(token->lexema); + token->lexema = NULL; + } +} diff --git a/src/micropascal-lexer/token.c b/src/micropascal-lexer/token.c new file mode 100644 index 0000000..d6c546c --- /dev/null +++ b/src/micropascal-lexer/token.c @@ -0,0 +1,93 @@ +#include "micropascal-lexer/token.h" + +const char* tokenKindNome(TokenKind kind) +{ + switch (kind) { + case TOKEN_EOF: + return "EOF"; + case TOKEN_IDENTIFICADOR: + return "IDENTIFICADOR"; + case TOKEN_INTEIRO_LITERAL: + return "INTEIRO_LITERAL"; + case TOKEN_REAL_LITERAL: + return "REAL_LITERAL"; + case TOKEN_CHAR_LITERAL: + return "CHAR_LITERAL"; + case TOKEN_MENOR: + return "MENOR"; + case TOKEN_MAIOR: + return "MAIOR"; + case TOKEN_MENOR_IGUAL: + return "MENOR_IGUAL"; + case TOKEN_MAIOR_IGUAL: + return "MAIOR_IGUAL"; + case TOKEN_IGUAL: + return "IGUAL"; + case TOKEN_DIFERENTE: + return "DIFERENTE"; + case TOKEN_MAIS: + return "MAIS"; + case TOKEN_MENOS: + return "MENOS"; + case TOKEN_MULTIPLICACAO: + return "MULTIPLICACAO"; + case TOKEN_DIVISAO: + return "DIVISAO"; + case TOKEN_DIV: + return "DIV"; + case TOKEN_AND: + return "AND"; + case TOKEN_OR: + return "OR"; + case TOKEN_NOT: + return "NOT"; + case TOKEN_ATRIBUICAO: + return "ATRIBUICAO"; + case TOKEN_ABRE_PARENTESES: + return "ABRE_PARENTESES"; + case TOKEN_FECHA_PARENTESES: + return "FECHA_PARENTESES"; + case TOKEN_VIRGULA: + return "VIRGULA"; + case TOKEN_PONTO_VIRGULA: + return "PONTO_VIRGULA"; + case TOKEN_PONTO: + return "PONTO"; + case TOKEN_DOIS_PONTOS: + return "DOIS_PONTOS"; + case TOKEN_PROGRAM: + return "PROGRAM"; + case TOKEN_IF: + return "IF"; + case TOKEN_THEN: + return "THEN"; + case TOKEN_ELSE: + return "ELSE"; + case TOKEN_WHILE: + return "WHILE"; + case TOKEN_DO: + return "DO"; + case TOKEN_REPEAT: + return "REPEAT"; + case TOKEN_UNTIL: + return "UNTIL"; + case TOKEN_INTEGER: + return "INTEGER"; + case TOKEN_REAL: + return "REAL"; + case TOKEN_CHAR: + return "CHAR"; + case TOKEN_BEGIN: + return "BEGIN"; + case TOKEN_END: + return "END"; + case TOKEN_WRITE: + return "WRITE"; + case TOKEN_VAR: + return "VAR"; + case TOKEN_ERRO: + return "ERRO"; + default: + return "DESCONHECIDO"; + } +} diff --git a/src/micropascal-parser/ast.c b/src/micropascal-parser/ast.c new file mode 100644 index 0000000..59c14a6 --- /dev/null +++ b/src/micropascal-parser/ast.c @@ -0,0 +1,85 @@ +#include "micropascal-parser/ast.h" + +#include +#include +#include +#include + +void astLiberar(AstNo* no); +void astImprimir(const AstNo* no, int profundidade); + +static const char* astKindNome(AstKind kind) +{ + switch (kind) { + case AST_PROGRAMA: + return "Programa"; + case AST_SECAO_VAR: + return "SecaoVar"; + case AST_DECL_VAR: + return "DeclVar"; + case AST_TIPO: + return "Tipo"; + case AST_BLOCO: + return "Bloco"; + case AST_LISTA_COMANDOS: + return "ListaComandos"; + case AST_ATRIBUICAO: + return "Atribuicao"; + case AST_ITERACAO: + return "Iteracao"; + case AST_DECISAO: + return "Decisao"; + case AST_ESCRITA: + return "Escrita"; + case AST_EXPRESSAO_BINARIA: + return "ExpressaoBinaria"; + case AST_EXPRESSAO_UNARIA: + return "ExpressaoUnaria"; + case AST_EXPRESSAO_PARENTESES: + return "ExpressaoParenteses"; + case AST_EXPRESSAO_LITERAL: + return "ExpressaoLiteral"; + case AST_EXPRESSAO_IDENTIFICADOR: + return "ExpressaoIdentificador"; + default: + return "Desconhecido"; + } +} + +void astLiberar(AstNo* no) +{ + if (no == NULL) { + return; + } + astLiberar(no->esquerda); + astLiberar(no->direita); + astLiberar(no->terceiro); + astLiberar(no->proximo); + if (no->valor != NULL) { + free(no->valor); + } + free(no); +} + +void astImprimir(const AstNo* no, int profundidade) +{ + int i; + const AstNo* atual; + if (no == NULL) { + return; + } + for (i = 0; i < profundidade; i++) { + printf(" "); + } + printf("%s", astKindNome(no->kind)); + if (no->valor != NULL) { + printf(" (%s)", no->valor); + } + printf("\n"); + astImprimir(no->esquerda, profundidade + 1); + astImprimir(no->direita, profundidade + 1); + astImprimir(no->terceiro, profundidade + 1); + for (atual = no->proximo; atual != NULL; atual = atual->proximo) { + astImprimir(atual, profundidade); + } +} diff --git a/src/micropascal-parser/parser.c b/src/micropascal-parser/parser.c new file mode 100644 index 0000000..9c7609b --- /dev/null +++ b/src/micropascal-parser/parser.c @@ -0,0 +1,428 @@ +#include "micropascal-parser/parser.h" + +#include +#include +#include + +static AstNo* parserCriarNo(AstKind kind, const char* valor) +{ + AstNo* no = (AstNo*)malloc(sizeof(AstNo)); + no->kind = kind; + if (valor != NULL) { + no->valor = (char*)malloc(strlen(valor) + 1); + strcpy(no->valor, valor); + } else { + no->valor = NULL; + } + no->esquerda = NULL; + no->direita = NULL; + no->terceiro = NULL; + no->proximo = NULL; + return no; +} + +static void parserAvancar(Parser* parser) +{ + tokenLiberar(&parser->atual); + parser->atual = lexerProximoToken(parser->lexer); +} + +void parserInicializar(Parser* parser, Lexer* lexer) +{ + parser->lexer = lexer; + parser->atual.kind = TOKEN_EOF; + parser->atual.lexema = NULL; + parser->atual.linha = 0; + parser->atual.coluna = 0; + parser->houve_erro = 0; + parser->total_erros = 0; + parser->silencioso = 0; + parserAvancar(parser); +} + +void parserSilenciarErros(Parser* parser, int silenciar) +{ + parser->silencioso = silenciar; +} + +static void parserErro(Parser* parser) +{ + const char* lexema = parser->atual.lexema; + if (lexema == NULL) { + lexema = ""; + } + parser->houve_erro = 1; + parser->total_erros++; + if (!parser->silencioso) { + printf("Erro de sintaxe no token [%s]\n", lexema); + } +} + +static int parserVerificar(Parser* parser, TokenKind kind) +{ + return parser->atual.kind == kind; +} + +static int parserConsumir(Parser* parser, TokenKind kind) +{ + if (parserVerificar(parser, kind)) { + parserAvancar(parser); + return 1; + } + return 0; +} + +static int parserEsperar(Parser* parser, TokenKind kind) +{ + if (parserConsumir(parser, kind)) { + return 1; + } + parserErro(parser); + return 0; +} + +static int parserEmInicioDeComando(Parser* parser) +{ + switch (parser->atual.kind) { + case TOKEN_BEGIN: + case TOKEN_IDENTIFICADOR: + case TOKEN_WHILE: + case TOKEN_REPEAT: + case TOKEN_IF: + case TOKEN_WRITE: + return 1; + default: + return 0; + } +} + +static AstNo* parserAnalisarBloco(Parser* parser); +static AstNo* parserAnalisarComando(Parser* parser); +static AstNo* parserAnalisarExpressao(Parser* parser); +static AstNo* parserAnalisarTipo(Parser* parser) +{ + switch (parser->atual.kind) { + case TOKEN_INTEGER: + parserAvancar(parser); + return parserCriarNo(AST_TIPO, "integer"); + case TOKEN_REAL: + parserAvancar(parser); + return parserCriarNo(AST_TIPO, "real"); + case TOKEN_CHAR: + parserAvancar(parser); + return parserCriarNo(AST_TIPO, "char"); + default: + parserErro(parser); + return NULL; + } +} + +static AstNo* parserAnalisarDeclVar(Parser* parser) +{ + AstNo* decl = parserCriarNo(AST_DECL_VAR, NULL); + AstNo* ultimo = NULL; + AstNo* identificador; + AstNo* tipo; + + if (!parserEsperar(parser, TOKEN_IDENTIFICADOR)) { + astLiberar(decl); + return NULL; + } + identificador = parserCriarNo(AST_EXPRESSAO_IDENTIFICADOR, NULL); + decl->esquerda = identificador; + ultimo = identificador; + + while (parserVerificar(parser, TOKEN_VIRGULA)) { + parserAvancar(parser); + if (!parserEsperar(parser, TOKEN_IDENTIFICADOR)) { + return decl; + } + ultimo->proximo = parserCriarNo(AST_EXPRESSAO_IDENTIFICADOR, NULL); + ultimo = ultimo->proximo; + } + + if (!parserEsperar(parser, TOKEN_DOIS_PONTOS)) { + return decl; + } + tipo = parserAnalisarTipo(parser); + decl->direita = tipo; + if (!parserEsperar(parser, TOKEN_PONTO_VIRGULA)) { + return decl; + } + return decl; +} + +static AstNo* parserAnalisarSecaoVar(Parser* parser) +{ + AstNo* secao = parserCriarNo(AST_SECAO_VAR, NULL); + AstNo* ultimo = NULL; + if (!parserEsperar(parser, TOKEN_VAR)) { + astLiberar(secao); + return NULL; + } + while (parserVerificar(parser, TOKEN_IDENTIFICADOR)) { + AstNo* decl = parserAnalisarDeclVar(parser); + if (decl == NULL) { + break; + } + if (ultimo == NULL) { + secao->esquerda = decl; + } else { + ultimo->proximo = decl; + } + ultimo = decl; + } + return secao; +} + +static AstNo* parserAnalisarExprBasica(Parser* parser) +{ + AstNo* no; + switch (parser->atual.kind) { + case TOKEN_ABRE_PARENTESES: + parserAvancar(parser); + no = parserCriarNo(AST_EXPRESSAO_PARENTESES, NULL); + no->esquerda = parserAnalisarExpressao(parser); + parserEsperar(parser, TOKEN_FECHA_PARENTESES); + return no; + case TOKEN_NOT: + parserAvancar(parser); + no = parserCriarNo(AST_EXPRESSAO_UNARIA, "not"); + no->esquerda = parserAnalisarExprBasica(parser); + return no; + case TOKEN_INTEIRO_LITERAL: + no = parserCriarNo(AST_EXPRESSAO_LITERAL, parser->atual.lexema); + parserAvancar(parser); + return no; + case TOKEN_REAL_LITERAL: + no = parserCriarNo(AST_EXPRESSAO_LITERAL, parser->atual.lexema); + parserAvancar(parser); + return no; + case TOKEN_CHAR_LITERAL: + no = parserCriarNo(AST_EXPRESSAO_LITERAL, parser->atual.lexema); + parserAvancar(parser); + return no; + case TOKEN_IDENTIFICADOR: + no = parserCriarNo(AST_EXPRESSAO_IDENTIFICADOR, parser->atual.lexema); + parserAvancar(parser); + return no; + default: + parserErro(parser); + return NULL; + } +} + +static AstNo* parserAnalisarExpMul(Parser* parser) +{ + AstNo* esquerda = parserAnalisarExprBasica(parser); + while (parser->atual.kind == TOKEN_MULTIPLICACAO || parser->atual.kind == TOKEN_DIVISAO || parser->atual.kind == TOKEN_DIV) { + char operador[8]; + AstNo* direita; + AstNo* novo; + strcpy(operador, parser->atual.lexema); + parserAvancar(parser); + direita = parserAnalisarExprBasica(parser); + novo = parserCriarNo(AST_EXPRESSAO_BINARIA, operador); + novo->esquerda = esquerda; + novo->direita = direita; + esquerda = novo; + } + return esquerda; +} + +static AstNo* parserAnalisarExpAd(Parser* parser) +{ + AstNo* esquerda = parserAnalisarExpMul(parser); + while (parser->atual.kind == TOKEN_MAIS || parser->atual.kind == TOKEN_MENOS) { + char operador[8]; + AstNo* direita; + AstNo* novo; + strcpy(operador, parser->atual.lexema); + parserAvancar(parser); + direita = parserAnalisarExpMul(parser); + novo = parserCriarNo(AST_EXPRESSAO_BINARIA, operador); + novo->esquerda = esquerda; + novo->direita = direita; + esquerda = novo; + } + return esquerda; +} + +static AstNo* parserAnalisarExpRel(Parser* parser) +{ + AstNo* esquerda = parserAnalisarExpAd(parser); + while (parser->atual.kind == TOKEN_IGUAL || parser->atual.kind == TOKEN_DIFERENTE || parser->atual.kind == TOKEN_MENOR || parser->atual.kind == TOKEN_MAIOR || parser->atual.kind == TOKEN_MENOR_IGUAL || parser->atual.kind == TOKEN_MAIOR_IGUAL) { + char operador[8]; + AstNo* direita; + AstNo* novo; + strcpy(operador, parser->atual.lexema); + parserAvancar(parser); + direita = parserAnalisarExpAd(parser); + novo = parserCriarNo(AST_EXPRESSAO_BINARIA, operador); + novo->esquerda = esquerda; + novo->direita = direita; + esquerda = novo; + } + return esquerda; +} + +static AstNo* parserAnalisarExpOrAnd(Parser* parser) +{ + AstNo* esquerda = parserAnalisarExpRel(parser); + while (parser->atual.kind == TOKEN_OR || parser->atual.kind == TOKEN_AND) { + char operador[8]; + AstNo* direita; + AstNo* novo; + strcpy(operador, parser->atual.lexema); + parserAvancar(parser); + direita = parserAnalisarExpRel(parser); + novo = parserCriarNo(AST_EXPRESSAO_BINARIA, operador); + novo->esquerda = esquerda; + novo->direita = direita; + esquerda = novo; + } + return esquerda; +} + +static AstNo* parserAnalisarExpressao(Parser* parser) +{ + return parserAnalisarExpOrAnd(parser); +} + +static AstNo* parserAnalisarAtribuicao(Parser* parser) +{ + AstNo* no = parserCriarNo(AST_ATRIBUICAO, parser->atual.lexema); + parserAvancar(parser); + if (!parserEsperar(parser, TOKEN_ATRIBUICAO)) { + return no; + } + no->esquerda = parserAnalisarExpressao(parser); + parserEsperar(parser, TOKEN_PONTO_VIRGULA); + return no; +} + +static AstNo* parserAnalisarIteracao(Parser* parser) +{ + AstNo* no; + if (parser->atual.kind == TOKEN_WHILE) { + parserAvancar(parser); + no = parserCriarNo(AST_ITERACAO, "while"); + no->esquerda = parserAnalisarExpressao(parser); + parserEsperar(parser, TOKEN_DO); + no->direita = parserAnalisarComando(parser); + return no; + } + parserAvancar(parser); + no = parserCriarNo(AST_ITERACAO, "repeat"); + no->esquerda = parserAnalisarComando(parser); + parserEsperar(parser, TOKEN_UNTIL); + no->direita = parserAnalisarExpressao(parser); + parserEsperar(parser, TOKEN_PONTO_VIRGULA); + return no; +} + +static AstNo* parserAnalisarDecisao(Parser* parser) +{ + AstNo* no; + parserAvancar(parser); + no = parserCriarNo(AST_DECISAO, NULL); + no->esquerda = parserAnalisarExpressao(parser); + parserEsperar(parser, TOKEN_THEN); + no->direita = parserAnalisarComando(parser); + if (parserVerificar(parser, TOKEN_ELSE)) { + parserAvancar(parser); + no->terceiro = parserAnalisarComando(parser); + } + return no; +} + +static AstNo* parserAnalisarEscrita(Parser* parser) +{ + AstNo* no; + parserAvancar(parser); + no = parserCriarNo(AST_ESCRITA, NULL); + parserEsperar(parser, TOKEN_ABRE_PARENTESES); + no->esquerda = parserAnalisarExpressao(parser); + parserEsperar(parser, TOKEN_FECHA_PARENTESES); + parserEsperar(parser, TOKEN_PONTO_VIRGULA); + return no; +} + +static AstNo* parserAnalisarComando(Parser* parser) +{ + switch (parser->atual.kind) { + case TOKEN_BEGIN: { + AstNo* bloco = parserAnalisarBloco(parser); + parserEsperar(parser, TOKEN_PONTO_VIRGULA); + return bloco; + } + case TOKEN_IDENTIFICADOR: + return parserAnalisarAtribuicao(parser); + case TOKEN_WHILE: + case TOKEN_REPEAT: + return parserAnalisarIteracao(parser); + case TOKEN_IF: + return parserAnalisarDecisao(parser); + case TOKEN_WRITE: + return parserAnalisarEscrita(parser); + default: + parserErro(parser); + return NULL; + } +} + +static AstNo* parserAnalisarBloco(Parser* parser) +{ + AstNo* bloco = parserCriarNo(AST_BLOCO, NULL); + AstNo* lista = parserCriarNo(AST_LISTA_COMANDOS, NULL); + AstNo* ultimo = NULL; + + if (!parserEsperar(parser, TOKEN_BEGIN)) { + astLiberar(bloco); + astLiberar(lista); + return NULL; + } + while (parserEmInicioDeComando(parser)) { + AstNo* comando = parserAnalisarComando(parser); + if (comando == NULL) { + break; + } + if (ultimo == NULL) { + lista->esquerda = comando; + } else { + ultimo->proximo = comando; + } + ultimo = comando; + } + parserEsperar(parser, TOKEN_END); + bloco->esquerda = lista; + return bloco; +} + +AstNo* parserAnalisarPrograma(Parser* parser) +{ + AstNo* programa = parserCriarNo(AST_PROGRAMA, NULL); + + if (!parserEsperar(parser, TOKEN_PROGRAM)) { + astLiberar(programa); + return NULL; + } + if (parserVerificar(parser, TOKEN_IDENTIFICADOR)) { + free(programa->valor); + programa->valor = (char*)malloc(strlen(parser->atual.lexema) + 1); + strcpy(programa->valor, parser->atual.lexema); + parserAvancar(parser); + } else { + parserErro(parser); + } + parserEsperar(parser, TOKEN_PONTO_VIRGULA); + if (parserVerificar(parser, TOKEN_VAR)) { + programa->esquerda = parserAnalisarSecaoVar(parser); + } + programa->direita = parserAnalisarBloco(parser); + parserEsperar(parser, TOKEN_PONTO); + if (!parserVerificar(parser, TOKEN_EOF)) { + parserErro(parser); + } + return programa; +} diff --git a/tests/test_lexer.c b/tests/test_lexer.c new file mode 100644 index 0000000..88535e5 --- /dev/null +++ b/tests/test_lexer.c @@ -0,0 +1,108 @@ +#include "micropascal-tests/testes.h" +#include "micropascal-lexer/lexer.h" + +#include + +static TokenKind tokenDe(const char* fonte) +{ + Lexer lexer; + Token token; + lexerInicializar(&lexer, fonte); + token = lexerProximoToken(&lexer); + tokenLiberar(&token); + return token.kind; +} + +static int lexemaDe(const char* fonte, const char* esperado) +{ + Lexer lexer; + Token token; + int igual; + lexerInicializar(&lexer, fonte); + token = lexerProximoToken(&lexer); + igual = token.lexema != NULL && strcmp(token.lexema, esperado) == 0; + tokenLiberar(&token); + return igual; +} + +static int contaTokens(const char* fonte) +{ + Lexer lexer; + Token token; + int contador = 0; + lexerInicializar(&lexer, fonte); + while (1) { + token = lexerProximoToken(&lexer); + contador++; + if (token.kind == TOKEN_EOF || token.kind == TOKEN_ERRO) { + tokenLiberar(&token); + break; + } + tokenLiberar(&token); + } + return contador; +} + +void runLexerTests(ResultadoTeste* resultado_testes) +{ + TESTE_ASSERT(resultado_testes, tokenDe("program") == TOKEN_PROGRAM, "reconhece program"); + TESTE_ASSERT(resultado_testes, tokenDe("if") == TOKEN_IF, "reconhece if"); + TESTE_ASSERT(resultado_testes, tokenDe("then") == TOKEN_THEN, "reconhece then"); + TESTE_ASSERT(resultado_testes, tokenDe("else") == TOKEN_ELSE, "reconhece else"); + TESTE_ASSERT(resultado_testes, tokenDe("while") == TOKEN_WHILE, "reconhece while"); + TESTE_ASSERT(resultado_testes, tokenDe("do") == TOKEN_DO, "reconhece do"); + TESTE_ASSERT(resultado_testes, tokenDe("repeat") == TOKEN_REPEAT, "reconhece repeat"); + TESTE_ASSERT(resultado_testes, tokenDe("until") == TOKEN_UNTIL, "reconhece until"); + TESTE_ASSERT(resultado_testes, tokenDe("integer") == TOKEN_INTEGER, "reconhece integer"); + TESTE_ASSERT(resultado_testes, tokenDe("real") == TOKEN_REAL, "reconhece real"); + TESTE_ASSERT(resultado_testes, tokenDe("char") == TOKEN_CHAR, "reconhece char"); + TESTE_ASSERT(resultado_testes, tokenDe("begin") == TOKEN_BEGIN, "reconhece begin"); + TESTE_ASSERT(resultado_testes, tokenDe("end") == TOKEN_END, "reconhece end"); + TESTE_ASSERT(resultado_testes, tokenDe("write") == TOKEN_WRITE, "reconhece write"); + TESTE_ASSERT(resultado_testes, tokenDe("var") == TOKEN_VAR, "reconhece var"); + TESTE_ASSERT(resultado_testes, tokenDe("div") == TOKEN_DIV, "reconhece div"); + TESTE_ASSERT(resultado_testes, tokenDe("and") == TOKEN_AND, "reconhece and"); + TESTE_ASSERT(resultado_testes, tokenDe("or") == TOKEN_OR, "reconhece or"); + TESTE_ASSERT(resultado_testes, tokenDe("not") == TOKEN_NOT, "reconhece not"); + + TESTE_ASSERT(resultado_testes, tokenDe("Begin") == TOKEN_IDENTIFICADOR, "Begin nao e palavra reservada"); + TESTE_ASSERT(resultado_testes, tokenDe("PROGRAM") == TOKEN_IDENTIFICADOR, "PROGRAM nao e palavra reservada"); + TESTE_ASSERT(resultado_testes, tokenDe("_contador") == TOKEN_IDENTIFICADOR, "identificador com underscore"); + TESTE_ASSERT(resultado_testes, tokenDe("abc123") == TOKEN_IDENTIFICADOR, "identificador alfanumerico"); + TESTE_ASSERT(resultado_testes, lexemaDe("xyz", "xyz"), "lexema do identificador preservado"); + + TESTE_ASSERT(resultado_testes, tokenDe("123") == TOKEN_INTEIRO_LITERAL, "inteiro literal"); + TESTE_ASSERT(resultado_testes, tokenDe("0") == TOKEN_INTEIRO_LITERAL, "inteiro literal zero"); + TESTE_ASSERT(resultado_testes, tokenDe("3.14") == TOKEN_REAL_LITERAL, "real literal"); + TESTE_ASSERT(resultado_testes, tokenDe("0.5") == TOKEN_REAL_LITERAL, "real literal com zero a esquerda"); + TESTE_ASSERT(resultado_testes, tokenDe(".5") == TOKEN_REAL_LITERAL, "real literal sem parte inteira"); + TESTE_ASSERT(resultado_testes, tokenDe("7.0") == TOKEN_REAL_LITERAL, "real literal inteiro"); + + TESTE_ASSERT(resultado_testes, tokenDe("'a'") == TOKEN_CHAR_LITERAL, "char literal letra"); + TESTE_ASSERT(resultado_testes, tokenDe("'0'") == TOKEN_CHAR_LITERAL, "char literal digito"); + TESTE_ASSERT(resultado_testes, tokenDe("'\\n'") == TOKEN_CHAR_LITERAL, "char literal quebra de linha"); + TESTE_ASSERT(resultado_testes, tokenDe("'\\t'") == TOKEN_CHAR_LITERAL, "char literal tabulacao"); + + TESTE_ASSERT(resultado_testes, tokenDe("<") == TOKEN_MENOR, "menor"); + TESTE_ASSERT(resultado_testes, tokenDe(">") == TOKEN_MAIOR, "maior"); + TESTE_ASSERT(resultado_testes, tokenDe("<=") == TOKEN_MENOR_IGUAL, "menor ou igual"); + TESTE_ASSERT(resultado_testes, tokenDe(">=") == TOKEN_MAIOR_IGUAL, "maior ou igual"); + TESTE_ASSERT(resultado_testes, tokenDe("=") == TOKEN_IGUAL, "igual"); + TESTE_ASSERT(resultado_testes, tokenDe("<>") == TOKEN_DIFERENTE, "diferente"); + TESTE_ASSERT(resultado_testes, tokenDe("+") == TOKEN_MAIS, "mais"); + TESTE_ASSERT(resultado_testes, tokenDe("-") == TOKEN_MENOS, "menos"); + TESTE_ASSERT(resultado_testes, tokenDe("*") == TOKEN_MULTIPLICACAO, "multiplicacao"); + TESTE_ASSERT(resultado_testes, tokenDe("/") == TOKEN_DIVISAO, "divisao de reais"); + TESTE_ASSERT(resultado_testes, tokenDe(":=") == TOKEN_ATRIBUICAO, "atribuicao"); + TESTE_ASSERT(resultado_testes, tokenDe("(") == TOKEN_ABRE_PARENTESES, "abre parenteses"); + TESTE_ASSERT(resultado_testes, tokenDe(")") == TOKEN_FECHA_PARENTESES, "fecha parenteses"); + TESTE_ASSERT(resultado_testes, tokenDe(",") == TOKEN_VIRGULA, "virgula"); + TESTE_ASSERT(resultado_testes, tokenDe(";") == TOKEN_PONTO_VIRGULA, "ponto e virgula"); + TESTE_ASSERT(resultado_testes, tokenDe(".") == TOKEN_PONTO, "ponto"); + TESTE_ASSERT(resultado_testes, tokenDe(":") == TOKEN_DOIS_PONTOS, "dois pontos"); + + TESTE_ASSERT(resultado_testes, contaTokens(" \n\t\r ") == 1, "brancos ignorados resultam em EOF"); + TESTE_ASSERT(resultado_testes, contaTokens("a b") == 3, "conta tokens simples"); + TESTE_ASSERT(resultado_testes, tokenDe("$") == TOKEN_ERRO, "caractere invalido gera erro"); + TESTE_ASSERT(resultado_testes, tokenDe("@") == TOKEN_ERRO, "arroba gera erro"); +} diff --git a/tests/test_main.c b/tests/test_main.c new file mode 100644 index 0000000..bb3c06a --- /dev/null +++ b/tests/test_main.c @@ -0,0 +1,27 @@ +#include "micropascal-tests/testes.h" + +#include + +int main(void) +{ + ResultadoTeste resultado_testes; + resultado_testes.total = 0; + resultado_testes.passaram = 0; + resultado_testes.falharam = 0; + + printf("Executando testes do lexer\n"); + runLexerTests(&resultado_testes); + + printf("Executando testes do parser\n"); + runParserTests(&resultado_testes); + + printf("\nTotal: %d | Passaram: %d | Falharam: %d\n", + resultado_testes.total, + resultado_testes.passaram, + resultado_testes.falharam); + + if (resultado_testes.falharam > 0) { + return 1; + } + return 0; +} diff --git a/tests/test_parser.c b/tests/test_parser.c new file mode 100644 index 0000000..1d4d11f --- /dev/null +++ b/tests/test_parser.c @@ -0,0 +1,111 @@ +#include "micropascal-tests/testes.h" +#include "micropascal-lexer/lexer.h" +#include "micropascal-parser/parser.h" + +#include + +static int programaValido(const char* fonte) +{ + Lexer lexer; + Parser parser; + AstNo* programa; + int valido; + lexerInicializar(&lexer, fonte); + parserInicializar(&parser, &lexer); + parserSilenciarErros(&parser, 1); + programa = parserAnalisarPrograma(&parser); + valido = !parser.houve_erro; + tokenLiberar(&parser.atual); + astLiberar(programa); + return valido; +} + +static const char* PROGRAMA_SIMPLES = + "program P;\n" + "var\n" + " x : integer;\n" + "begin\n" + " x := 1;\n" + "end.\n"; + +static const char* PROGRAMA_PARIDADE = + "program TestaParidade;\n" + "var\n" + " n : integer;\n" + "begin\n" + " n := 2 * 13 + 5;\n" + " if n = (n div 2)*2 then\n" + " write('p')\n" + " ;\n" + " else\n" + " write('i')\n" + " ;\n" + "end.\n"; + +static const char* PROGRAMA_IMPARES = + "program SomaImpares;\n" + "var\n" + " n : integer;\n" + " i, proximoImpar, soma : integer;\n" + "begin\n" + " n := 4;\n" + " i := 0;\n" + " soma := 0;\n" + " while i < n do\n" + " begin\n" + " proximoImpar := 2*i + 1;\n" + " soma := soma + proximoImpar;\n" + " i := i + 1;\n" + " end;\n" + " write(soma);\n" + " write('\\n');\n" + "end.\n"; + +static const char* PROGRAMA_REPEAT = + "program Contador;\n" + "var\n" + " i : integer;\n" + "begin\n" + " i := 0;\n" + " repeat\n" + " i := i + 1;\n" + " until i >= 10;\n" + "end.\n"; + +static const char* PROGRAMA_TIPOS = + "program Tipos;\n" + "var\n" + " a, b : integer;\n" + " c : real;\n" + " d : char;\n" + "begin\n" + " a := 1;\n" + " b := 2;\n" + " c := 1.5 + 2.5;\n" + " d := 'x';\n" + "end.\n"; + +void runParserTests(ResultadoTeste* resultado_testes) +{ + TESTE_ASSERT(resultado_testes, programaValido(PROGRAMA_SIMPLES), "programa simples valido"); + TESTE_ASSERT(resultado_testes, programaValido(PROGRAMA_PARIDADE), "programa TestaParidade valido"); + TESTE_ASSERT(resultado_testes, programaValido(PROGRAMA_IMPARES), "programa SomaImpares valido"); + TESTE_ASSERT(resultado_testes, programaValido(PROGRAMA_REPEAT), "programa com repeat until valido"); + TESTE_ASSERT(resultado_testes, programaValido(PROGRAMA_TIPOS), "programa com varios tipos valido"); + + TESTE_ASSERT(resultado_testes, programaValido("program P;\nbegin\n x := 1 + 2 * 3;\nend.\n"), "precedencia multiplicacao sobre soma"); + TESTE_ASSERT(resultado_testes, programaValido("program P;\nbegin\n x := (1 + 2) * 3;\nend.\n"), "parenteses"); + TESTE_ASSERT(resultado_testes, programaValido("program P;\nbegin\n x := not a and b or c;\nend.\n"), "operadores not and or"); + TESTE_ASSERT(resultado_testes, programaValido("program P;\nbegin\n x := a = b;\nend.\n"), "igualdade"); + TESTE_ASSERT(resultado_testes, programaValido("program P;\nbegin\n x := a <> b;\nend.\n"), "diferente"); + TESTE_ASSERT(resultado_testes, programaValido("program P;\nbegin\n x := a <= b;\nend.\n"), "menor ou igual"); + TESTE_ASSERT(resultado_testes, programaValido("program P;\nbegin\n if a then b := 1;\nend.\n"), "decisao sem else"); + TESTE_ASSERT(resultado_testes, programaValido("program P;\nbegin\n while a do b := 1;\nend.\n"), "iteracao while"); + + TESTE_ASSERT(resultado_testes, !programaValido("program P\nbegin end.\n"), "falta ponto e virgula apos nome"); + TESTE_ASSERT(resultado_testes, !programaValido("program P;\nbegin\n x := ;\nend.\n"), "expressao ausente"); + TESTE_ASSERT(resultado_testes, !programaValido("program P;\nbegin\n x := 1 +\nend.\n"), "operando ausente"); + TESTE_ASSERT(resultado_testes, !programaValido("program P;\nbegin\n if a then\nend.\n"), "comando ausente apos then"); + TESTE_ASSERT(resultado_testes, !programaValido("program P;\nvar x integer;\nbegin end.\n"), "falta dois pontos na declaracao"); + TESTE_ASSERT(resultado_testes, !programaValido("program P;\nbegin\n x := 1\nend.\n"), "falta ponto e virgula no comando"); +}