Você está na página 1de 23

Universidade Federal de Minas Gerais Departamento de Ciencia da Computacao

Compiladores I Trabalho Pratico 4

Anlise Sinttica a a

Alunos: Daniel Brasil Magnani Felipe Martim Vieira

Professor(a): Mariza Bigonha

17 de maio de 2010

Sumrio a
1 Introduo ca 2 Desenvolvimento 2.1 Lex . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2 Yacc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3 Gramtica a 4 Instrues para utilizao co ca 5 Testes 5.1 Teste 5.2 Teste 5.3 Teste 5.4 Teste 5.5 Teste 5.6 Teste 5.7 Teste 2 3 3 4 5 7 8 8 8 9 10 12 13 14 15

A B C D E F G

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

. . . . . . .

6 Concluso a

7 Cdigo-fonte o 15 7.1 lexemas.l . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15 7.2 gramatica.y . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16

Introduo ca

O compilador o programa responsvel por transformar um cdigo-fonte e a o de uma linguagem de programao em outra linguagem, geralmente um cdigo ca o binrio, ou executvel. O processo de compilao feito atravs de vrias etapas, a a ca e e a como mostrado na gura 1.

Figura 1: Fases do processo de compilao ca Depois da gerao de cdigo pelo compilador, um interpretador usado ca o e para executar as instrues contidas neste cdigo e nalmente realizar as tarefas co o descritas no cdigo-fonte feito pelo programador. o

Figura 2: Interpretador O objetivo deste trabalho implementar a segunda fase do processo de come pilao, a anlise sinttica. Ela responsvel pelas seguintes tarefas: ca a a e a

Receber uma cadeia de tokens do analisador lxico. e Vericar se a cadeia de tokens pertence ` linguagem gerada pela gramtica. a a Emitir mensagens de erro e se recuperar desses erros. Construir uma rvore de derivao e pass-la ao restante do front-end do a ca a compilador.

Figura 3: Posio do analisador sinttico (parser) no modelo de compilador. ca a

Desenvolvimento
Para implementar a anlise lxica, utilizamos as ferramentais lex e yacc. a e

2.1

Lex

O programa Lex um gerador de analisadores lxicos, atravs da denio e e e ca de expresses regulares para descrever padres para os tokens. A notao de o o ca entrada para a ferramenta Lex chamada de linguagem Lex, e a ferramenta em e si o compilador Lex. Internamente, o compilador Lex transforma os padres e o de entrada em m diagrama de transio e gera cdigo em um arquivo chamado ca o lex.yy.c, que simula esse diagrama de transio. ca Um programa Lex possui o seguinte formato: declara~es co %% regras de tradu~o ca %% fun~es auxiliares co A seo de declaraes inclui declaraes de variveis, constantes manifestas ca co co a e denies regulares. Cada uma das regras de traduo possui o formato: co ca Padro { Ao } a ca

Figura 4: Utilizao do Lex ca

2.2

Yacc

Yacc o gerador de analisador sinttico utilizado neste trabalho. Um tradue a tor pode ser constru usando o Yacc. Inicialmente, prepara-se um arquivo, do digamos, translate.y, contendo uma especicao Yacc dor tradutor. O comando ca do sistema UNIX $ yacc -d translate.y transforma o arquivo translate.y em um programa C chamado y.tab.c, usando o mtodo LALR. O programa y.tab.c uma representao de um anale e ca isador LALR escrito em C, junto com outras rotinas C que o usurio pode ter a preparado. Compilando y.tab.c junto com a biblioteca ly que contm o programa e de anlise LR usando o comando a $ cc y.tab.c -ly obtemos o programa objeto desejado a.out, que realiza a traduo especica cada pelo programa Yacc original. Se outros procedimentos forem necessrios, a eles podem ser compilados ou carregados com y.tab.c, assim como qualquer outro programa em C. Um programa fonte Yacc possui trs partes: e declara~es co %% regras de tradu~o ca %% rotinas de suporte em C

Figura 5: Utilizao do Yacc ca

Gramtica a
A gramtica utilizada para realizar a anlise sinttica foi: a a a

Tokens: PROGRAM BEGIN_ END DECLARE INTEGER BOOLEAN CHAR LABEL REAL ARRAY OF PROCEDURE IF THEN ELSE WHILE DO READ WRITE GOTO RETURN NOT OR MOD AND TRUE FALSE GE NE ASSIGN program block_stmt decl_list : : | : | | : | | : : | : | : | | | PROGRAM identifier block_stmt BEGIN_ stmt_list END DECLARE decl_list BEGIN_ stmt_list END decl decl_list ; decl variable_decl proc_decl type ident_list identifier ident_list , identifier simple_type array_type INTEGER BOOLEAN CHAR LABEL

decl

variable_decl ident_list type simple_type

array_type tamanho proc_decl formal_list parameter_decl parameter_type proc_signature type_list stmt_list stmt label unlabelled_stmt

assign_stmt variable array_element if_stmt condition while_stmt stmt_prefix read_stmt write_stmt goto_stmt proc_stmt return_stmt expr_list expression simple_expr term factor_a

: : : | : | : : : | : | : | : | : : | | | | | | | | : : | : : | : : : : : : : | : : | : | : | : | :

ARRAY tamanho OF simple_type integer_constant PROCEDURE identifier block_stmt PROCEDURE identifier ( formal_list ) block_stmt parameter_decl formal_list ; parameter_decl parameter_type identifier type PROCEDURE identifier PROCEDURE identifier ( type_list ) parameter_type type_list , parameter_type stmt stmt_list ; stmt label : unlabelled_stmt unlabelled_stmt identifier assign_stmt if_stmt while_stmt read_stmt write_stmt goto_stmt proc_stmt return_stmt block_stmt variable ASSIGN expression identifier array_element identifier [ expression ] IF condition THEN stmt_list END IF condition THEN stmt_list ELSE stmt_list END expression stmt_prefix stmt_list END WHILE condition DO READ ( ident_list ) WRITE ( expr_list ) GOTO label identifier identifier ( expr_list ) RETURN expression expr_list , expression simple_expr simple_expr relop simple_expr term simple_expr addop term factor_a term mulop factor_a factor 6

factor

relop

addop

mulop

constant

boolean_constant integer_constant unsigned_integer char_constant identifier digit

caractere

| | : | | : | | | | : | | : | | | : | | : | : : | : : : | | | | | | | | | :

NOT factor - factor variable constant ( expression ) = > < GE NE + - OR * / MOD AND integer_constant char_constant boolean_constant FALSE TRUE unsigned_integer digit unsigned_integer digit caractere ID 0 1 2 3 4 5 6 7 8 9 CHARACTER

Instruoes para utilizao c ca

Um arquivo de entrada, chamado lexemas.l, foi escrito na linguagem Lex e descreve o analisador lxico a ser gerado. Atravs do comando: e e $ lex lexemas.l o compilador Lex transforma lexemas.l em um programa C, e o armazena em um arquivo que sempre se chama lex.yy.c. Outro arquivo, chamado gramatica.y, foi escrito na linguagem Yacc e descreve a gramtica da linguagem. Usando o comando: a 7

$ yacc -d gramatica.y o Yacc transforma gramatica.y em um programa C, que armazenado no e arquivo chamdo y.tab.c. Esses dois arquivos so compilados pelo gcc pelo comando: a $ gcc -o parser lex.yy.c y.tab.c que gera o executvel, que o analisador sinttico propriamente dito. a e a Para executar o programa utilizando como entrada o arquivo in.txt, por exemplo, usa-se o comando: $ ./parser < in.txt

Testes
Quase todos os testes apresentam erros de sintaxe.

5.1

Teste A

Erro: O tipo real no aceito pela linguagem SL. a e Entrada: program teste1 declare real a, b, c begin if a > b then c := a + b else c := a - b * c end end

Sa da: ******** Analisador Sintatico ******** identifier: teste1 ERRO!! Linha: 3 syntax error!

5.2

Teste B

Erro: A declarao b:boolean no aceita. ca a e Entrada: program teste2 declare integer i, j, k b : boolean 8

begin i j k b b end

:= := := := :=

4 * (5-3) * -10 / 50); i * 88; i* j / k; k := -4 +3; not false; 4 (3 and 7) = 0 or 1 != 4

Sa da: ******** Analisador Sintatico ******** identifier: teste2 identifier: i identifier: j ident_list identifier: k ident_list variable_decl ERRO!! Linha: 4 syntax error!

5.3

Teste C

Erro: O formato de declarao de arrays no est correto. ca a a Entrada: program teste3 declare integer j, k; array 100 integer array 100 integer array 100 integer begin i := 3; j := 4; a(i) := a(2*i+3) c(i) := a(i) end

Sa da: ******** Analisador Sintatico ******** identifier: teste3 identifier: j identifier: k ident_list variable_decl digit: 1 9

digit: 0 unsigned_integer digit: 0 unsigned_integer integer_constant tamanho ERRO!! Linha: 4 syntax error!

5.4

Teste D

No h erros no teste D. a a Entrada: program teste4 declare integer divisor, number; boolean nofactor, prime begin read(number); write(number); divisor := number; nofactor := true; while nofactor and (divisor > if (number mod divisor) = else divisor := divisor end end; prime := nofactor; if prime then write(S) else end

1) do 0 then nofactor := false 1

write(N) end

Sa da: ******** Analisador Sintatico ******** identifier: teste4 identifier: divisor identifier: number ident_list variable_decl identifier: nofactor identifier: prime ident_list variable_decl decl_list identifier: number read_stmt stmt identifier: number 10

write_stmt stmt stmt_list identifier: divisor identifier: number assign_stmt stmt stmt_list identifier: nofactor boolean_constant constant assign_stmt stmt stmt_list identifier: nofactor mulop: AND identifier: divisor relop: > digit: 1 integer_constant expression factor term condition stmt_prefix identifier: number mulop: MOD identifier: divisor term factor relop: = digit: 0 integer_constant expression condition identifier: nofactor constant assign_stmt stmt identifier: divisor identifier: divisor addop: digit: 1 integer_constant simple_expr assign_stmt stmt if_stmt stmt while_stmt 11

stmt stmt_list identifier: prime identifier: nofactor assign_stmt stmt stmt_list identifier: prime condition identifier: S write_stmt stmt identifier: N write_stmt stmt if_stmt stmt stmt_list block_stmt program

5.5

Teste E

Erro: A declarao number : integer invlida. ca e a Entrada: program teste5 declare integer number; boolean nofactor, prime; procedure checkfactor(number : integer; nofactor: boolean) begin integer integer; boolean boolean divisor := number; prime := true; while prime and divisor > 1 do if (number mod divisor) = 0 then prime := false else divisor := divisor - 1 end nofactor := prime end; begin read(number); write(number); checkfactor(number,nofactor); prime := nofactor; if prime then write(S) else write(N) end end

Sa da: 12

******** Analisador Sintatico ******** identifier: teste5 identifier: number variable_decl identifier: nofactor identifier: prime ident_list variable_decl decl_list identifier: checkfactor ERRO!! Linha: 5 syntax error!

5.6

Teste F

Erro: A gramtica SL no permite a construo procedure p(procedure f ). a a ca Entrada: program test6 declare boolean b; procedure p(procedure f) declare integer x; procedure q begin write(x) end begin x := if b then 5 else 0 end; b := not b; if b then p(q) end; f end procedure r begin write(.) end begin write(x); write(=); b :=false; p(r) end

Sa da: ******** Analisador Sintatico ******** identifier: test6 identifier: b variable_decl identifier: p ERRO!!

13

Linha: 4 syntax error!

5.7

Teste G

Erro: A palavra labe no existe na linguagem SL. a Entrada: program teste7 declare labe L1, L2; integer x; begin x := 0; L1: x := x + 1; declare integer y; begin y := 1; declare integer z; begin z := x + y; if z < 10 then goto L1 else goto L2 end end end; L2: write(x) end

Sa da: ******** Analisador Sintatico ******** identifier: teste7 ERRO!! Linha: 3 syntax error!

14

Concluso a

O desenvolvimento deste trabalho possibilitou o aprendizado acerca do funcionamento de um analisador sinttico. Pudemos aprender como funcionam as a ferramentas Lex e Yacc e atravs delas fomos capazes de gerar o analisador e sinttico apropriado para a linguagem SL. O desenvolvimento desse trabalho foi a um passo muito importante para que o prximo trabalho seja conclu o do, e que no nal do curso um compilador seja implementado na ntegra.

7
7.1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 %{ #i n c l u d e #i n c l u d e #i n c l u d e #i n c l u d e %}

Cdigo-fonte o
lexemas.l

< s t d l i b . h> <s t d i o . h> <s t r i n g . h> y . tab . h

/ d e f i n i c o e s r e g u l a r e s letter digit id number %% program begin end declare integer boolean char label real array of procedure if then else while do read write goto return

/ [ AZaz ] [0 9] { l e t t e r }({ l e t t e r }|{ d i g i t }) { d i g i t }+(\.{ d i g i t }+) ? (E[+ ]?{ d i g i t }+)?

{ return { return { return { return { return { return { return { return { return { return { return { return { return { return { return { return { return { return { return { return { return

PROGRAM; } BEGIN ; } END; } DECLARE; } INTEGER; } BOOLEAN; } CHAR; } LABEL; } REAL; } ARRAY; } OF; } PROCEDURE; } IF ; } THEN; } ELSE ; } WHILE; } DO; } READ; } WRITE; } GOTO; } RETURN; } 15

37 not 38 o r 39 and 40 mod 41 f a l s e 42 t r u e 43 >= 44 != 45 := 46 47 > | < | = | ; | : | , 48 ( | ) | [ | ] 49 | + | | | / 50 51 [ \n]+ 52 { d i g i t } 53 { i d } 54 . 55 56 %%

{ return { return { return { return { return { return { return { return { return

NOT; } OR; } AND; } MOD; } FALSE; } TRUE; } GE; } NE; } ASSIGN ; }

{ return ( int ) yytext [ 0 ] ; } { return ( int ) yytext [ 0 ] ; } { return ( int ) yytext [ 0 ] ; }

{ return ( int ) yytext [ 0 ] ; } { y y l v a l . s t r i n g=s t r d u p ( y y t e x t ) ; r e t u r n ID ; } { y y l v a l . number=( i n t ) y y t e x t [ 1 ] ; r e t u r n CHARACTER; }

7.2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

gramatica.y

%{ #i n c l u d e <c t y p e . h> #i n c l u d e <s t d i o . h> #i n c l u d e <s t r i n g . h> i n t yydebug =1; e x t e r n i n t y y l i n e n o , yychar ; void yyerror ( const char s t r ) { p r i n t f ( ERRO! ! \ nLinha : %d\n%s ! \ n , y y l i n e n o , s t r ) ; } i n t yywrap ( ) { return 1; } main ( ) { p r i n t f ( A n a l i s a d o r S i n t a t i c o \ n ) ; yyparse ( ) ; }

%}

16

26 27 %token PROGRAM BEGIN END DECLARE INTEGER BOOLEAN CHAR LABEL REAL ARRAY OF PROCEDURE IF THEN ELSE WHILE DO READ WRITE GOTO RETURN NOT OR MOD AND TRUE FALSE GE NE ASSIGN 28 29 %union { 30 i n t number ; 31 char s t r i n g ; 32 } 33 34 %token <number> CHARACTER 35 %token <s t r i n g > ID 36 %type <number> c a r a c t e r e 37 %type <s t r i n g > i d e n t i f i e r 38 39 %r i g h t = 40 %l e f t + AND 41 %l e f t / OR MOD 42 43 %% 44 program : PROGRAM i d e n t i f i e r b l o c k s t m t 45 { p r i n t f ( program \n ) ; } ; 46 47 b l o c k s t m t : BEGIN s t m t l i s t END 48 | DECLARE d e c l l i s t BEGIN s t m t l i s t END 49 { p r i n t f ( b l o c k s t m t \n ) ; } ; 50 51 d e c l l i s t : 52 | decl 53 | d e c l l i s t ; decl 54 { p r i n t f ( d e c l l i s t \n ) ; } ; 55 56 d e c l : 57 | variable decl 58 | proc decl 59 { p r i n t f ( d e c l \n ) ; } ; 60 61 v a r i a b l e d e c l : type i d e n t l i s t 62 { p r i n t f ( v a r i a b l e d e c l \n ) ; } ; 63 64 i d e n t l i s t : identifier 65 | ident list , identifier 66 { p r i n t f ( i d e n t l i s t \n ) ; } ; 67 68 type : simple type 69 | array type 70 { p r i n t f ( type \n ) ; } ; 71 72 s i m p l e t y p e : INTEGER 73 | BOOLEAN 17

74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123

| CHAR | LABEL { p r i n t f ( s i m p l e t y p e \n ) ; } ; array type : ARRAY tamanho OF s i m p l e t y p e { p r i n t f ( a r r a y t y p e \n ) ; } ; : integer constant { p r i n t f ( tamanho\n ) ; } ; : PROCEDURE i d e n t i f i e r b l o c k s t m t | PROCEDURE i d e n t i f i e r ( f o r m a l l i s t { p r i n t f ( p r o c d e c l \n ) ; } ; : parameter decl | f o r m a l l i s t ; parameter decl { p r i n t f ( f o r m a l l i s t \n ) ; } ; : parameter type i d e n t i f i e r { p r i n t f ( p a r a m e t e r d e c l \n ) ; } ; : type { p r i n t f ( p a r a m e t e r t y p e \n ) ; } ; : PROCEDURE i d e n t i f i e r | PROCEDURE i d e n t i f i e r ( t y p e l i s t { p r i n t f ( p r o c s i g n a t u r e \n ) ; } ; : parameter type | t y p e l i s t , parameter type { p r i n t f ( t y p e l i s t \n ) ; } ; : stmt | s t m t l i s t ; stmt { p r i n t f ( s t m t l i s t \n ) ; } ; : label : unlabelled stmt | unlabelled stmt { p r i n t f ( stmt \n ) ; } ; : identifier { p r i n t f ( l a b e l \n ) ; } ; : | | | | | | assign stmt if stmt while stmt read stmt write stmt goto stmt proc stmt 18

tamanho

proc decl

) block stmt

formal list

parameter decl

parameter type

proc signature

type list

stmt list

stmt

label

unlabelled stmt

124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173

| return stmt | block stmt { p r i n t f ( u n l a b e l l e d s t m t \n ) ; } ; assign stmt : v a r i a b l e ASSIGN e x p r e s s i o n { p r i n t f ( a s s i g n s t m t \n ) ; } ; : identifier | array element { p r i n t f ( v a r i a b l e \n ) ; } ; : i d e n t i f i e r [ expression ] { p r i n t f ( a r r a y e l e m e n t \n ) ; } ; : IF c o n d i t i o n THEN s t m t l i s t END | IF c o n d i t i o n THEN s t m t l i s t ELSE s t m t l i s t END { p r i n t f ( i f s t m t \n ) ; } ; : expression { p r i n t f ( c o n d i t i o n \n ) ; } ; : s t m t p r e f i x s t m t l i s t END { p r i n t f ( w h i l e s t m t \n ) ; } ; : WHILE c o n d i t i o n DO { p r i n t f ( s t m t p r e f i x \n ) ; } ; : READ ( i d e n t l i s t ) { p r i n t f ( r e a d s t m t \n ) ; } ; : WRITE ( e x p r l i s t ) { p r i n t f ( w r i t e s t m t \n ) ; } ; : GOTO l a b e l { p r i n t f ( g o t o s t m t \n ) ; } ; : identifier | i d e n t i f i e r ( expr list { p r i n t f ( p r o c s t m t \n ) ; } ; : RETURN { p r i n t f ( r e t u r n s t m t \n ) ; } ; : expression | expr lis t , expression { p r i n t f ( e x p r l i s t \n ) ; } ; : simple expr | simple expr relop simple expr { p r i n t f ( e x p r e s s i o n \n ) ; } ; 19

variable

array element

if stmt

condition

while stmt

stmt prefix

read stmt

write stmt

goto stmt

proc stmt

return stmt

expr list

expression

174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223

simple expr

: term | s i m p l e e x p r addop term { p r i n t f ( s i m p l e e x p r \n ) ; } ; : factor a | term mulop f a c t o r a { p r i n t f ( term \n ) ; } ; : factor | NOT f a c t o r | factor { p r i n t f ( f a c t o r a \n ) ; } ; : variable | constant | ( expression ) { p r i n t f ( f a c t o r \n ) ; } ; : | | | | ; = { p r i n t f ( r e l o p : =\n ) ; } > { p r i n t f ( r e l o p : >\n ) ; } < { p r i n t f ( r e l o p : <\n ) ; } GE { p r i n t f ( r e l o p : >=\n ) ; } NE { p r i n t f ( r e l o p : !=\n ) ; }

term

factor a

factor

relop

addop

: + { p r i n t f ( addop : +\n ) ; } | { p r i n t f ( addop : \n ) ; } | OR { p r i n t f ( addop : OR\n ) ; } ; : { p r i n t f ( mulop : | / { p r i n t f ( mulop : | MOD { p r i n t f ( mulop : | AND { p r i n t f ( mulop : ; \n ) ; } /\n ) ; } MOD\n ) ; } AND\n ) ; }

mulop

constant

: integer constant | char constant | boolean constant { p r i n t f ( c o n s t a n t \n ) ; } ; : FALSE | TRUE { p r i n t f ( b o o l e a n c o n s t a n t \n ) ; } ; : unsigned integer { p r i n t f ( i n t e g e r c o n s t a n t \n ) ; } ; ;

boolean constant

integer constant

20

224 u n s i g n e d i n t e g e r 225 226 227 228 229 230 c h a r c o n s t a n t 231 232 233 234 i d e n t i f i e r 235 236 237 d i g i t 238 239 240 241 242 243 244 245 246 247 248 249 c a r a c t e r e 250 251 252 253 %%

: digit | unsigned integer digit { p r i n t f ( u n s i g n e d i n t e g e r \n ) ; } ; ;

: caractere { p r i n t f ( c h a r c o n s t a n t \n ) ; } ; ; : ID { $$=$1 ; p r i n t f ( i d e n t i f i e r : %s \n , $1 ) ; } ; : | | | | | | | | | ; 0 1 2 3 4 5 6 7 8 9 { p r i n t f ( d i g i t { p r i n t f ( d i g i t { p r i n t f ( d i g i t { p r i n t f ( d i g i t { p r i n t f ( d i g i t { p r i n t f ( d i g i t { p r i n t f ( d i g i t { p r i n t f ( d i g i t { p r i n t f ( d i g i t { p r i n t f ( d i g i t : : : : : : : : : : 0\n ) ; } 1\n ) ; } 2\n ) ; } 3\n ) ; } 4\n ) ; } 5\n ) ; } 6\n ) ; } 7\n ) ; } 8\n ) ; } 9\n ) ; }

: CHARACTER { p r i n t f ( c a r a c t e r e : %c \n , $1 ) ; } ;

21

Referncias e
[1] en.wikipedia.org/wiki/Lex_(software) [2] http://dinosaur.compilertools.net/lex/index.html [3] http://ds9a.nl/lex-yacc/cvs/output/lexyacc.html [4] http://osr507doc.sco.com/en/tools/Lex_yacc.html [5] Alfred V. Aho, Ravi Sethi and Jerey D. Ullman, Compilers - Principles Techniques and Tools, 2006

22

Você também pode gostar