25
Acc¸c˜ oes semˆ anticas em Gram´ aticas Livres de Contexto ´ Arvore de Sintaxe Abstracta ´ Arvores de Sintaxe Abstracta Sim˜ ao Melo de Sousa Computer Science Department University of Beira Interior, Portugal S. Melo de Sousa ´ Arvores de Sintaxe Abstracta

Sim~ao Melo de Sousa - di.ubi.ptdesousa/2015-2016/PL/ast.pdf · %token INT PLUS MINUS TIMES DIV EOF %left PLUS MINUS %left TIMES DIV %left uminus %start expr ... AST: representa˘c~ao

Embed Size (px)

Citation preview

Acccoes semanticas em Gramaticas Livres de ContextoArvore de Sintaxe Abstracta

Arvores de Sintaxe Abstracta

Simao Melo de Sousa

Computer Science DepartmentUniversity of Beira Interior, Portugal

S. Melo de Sousa Arvores de Sintaxe Abstracta

Acccoes semanticas em Gramaticas Livres de ContextoArvore de Sintaxe Abstracta

Plano

1 Acccoes semanticas em Gramaticas Livres de ContextoValores Semanticos em Gramaticas DescendentesValores Semanticos em Gramaticas Ascendentes

2 Arvore de Sintaxe Abstracta

S. Melo de Sousa Arvores de Sintaxe Abstracta

Acccoes semanticas em Gramaticas Livres de ContextoArvore de Sintaxe Abstracta

Valores Semanticos em Gramaticas DescendentesValores Semanticos em Gramaticas Ascendentes

Plano

1 Acccoes semanticas em Gramaticas Livres de ContextoValores Semanticos em Gramaticas DescendentesValores Semanticos em Gramaticas Ascendentes

2 Arvore de Sintaxe Abstracta

S. Melo de Sousa Arvores de Sintaxe Abstracta

Acccoes semanticas em Gramaticas Livres de ContextoArvore de Sintaxe Abstracta

Valores Semanticos em Gramaticas DescendentesValores Semanticos em Gramaticas Ascendentes

Princıpios Gerais

Um compilador deve fazer mais do que simplesmente reconhecer se umafrase analisada pertence ou nao a linguagem gerada pela gramatica.

pode/deve fazer algo com o texto reconhecido.

As accoes semanticas duma gramatica possibilitadas por ferramentascomo o yacc permitam a definicao e a execucao de tais operacoes emcada producao da gramatica.

S. Melo de Sousa Arvores de Sintaxe Abstracta

Acccoes semanticas em Gramaticas Livres de ContextoArvore de Sintaxe Abstracta

Valores Semanticos em Gramaticas DescendentesValores Semanticos em Gramaticas Ascendentes

Princıpios Gerais

Cada sımbolo da gramatica (terminal ou nao terminal) pode ser associadoa um determinado tipo de valor (semantico).

Por exemplo numa gramatica para a aritmetica sobre inteiros, o naoterminal especificando as expressoes aritmeticas, digamos exp, pode serassociado ao tipo inteiro. Uma expressao em particular (i.e. reconhecidopor exp) tera como valor o inteiro que resulta do seu calculo.

Para uma regra A → B C D, o valor semantico de A pode ser calculadoa partir dos valores semanticos de B, C e D.

S. Melo de Sousa Arvores de Sintaxe Abstracta

Acccoes semanticas em Gramaticas Livres de ContextoArvore de Sintaxe Abstracta

Valores Semanticos em Gramaticas DescendentesValores Semanticos em Gramaticas Ascendentes

Gramaticas LL(1) e valores semanticos em Ocaml

Leitura e manipulac~ao de express~oes logicas simples com streams

Este metodo de leitura implementa um lexer/parser descendente para a

gramatica LL(1) das express~oes logicas seguinte (N -> {TRUE , FALSE}, V

-> Variaveis):

E ::= T E’

E’ ::= -> T E’

E’ ::= <-> T E’

E’ ::= \epsilon

T ::= F T’

T’ ::= & F T’

T’ ::= | F T’

T’ ::= \epsilon

F ::= N

F ::= V

F ::= ! E

F ::= ( E )

S. Melo de Sousa Arvores de Sintaxe Abstracta

Acccoes semanticas em Gramaticas Livres de ContextoArvore de Sintaxe Abstracta

Valores Semanticos em Gramaticas DescendentesValores Semanticos em Gramaticas Ascendentes

Gramaticas LL(1) e valores semanticos em Ocaml

(*val parse_expr : Genlex.token stream -> formula *)

let rec parse_expr = parser (* corresponde a entrada E da gramatica *)

[< e1 = parse_conj; e = parse_more_imps e1 >] -> e

and parse_more_imps e1 = parser (* corresponde a entrada E’ da gramatica *)

[< ’Kwd "->"; e2 = parse_conj; e = parse_more_imps (Implica(e1, e2)) >] -> e

| [< ’Kwd "<->"; e2 = parse_conj; e = parse_more_imps (Equivale(e1, e2)) >] -> e

| [< >] -> e1

and parse_conj = parser (* corresponde a entrada T da gramatica *)

[< e1 = parse_simple; e = parse_more_conjs e1 >] -> e

and parse_more_conjs e1 = parser (* corresponde a entrada T’ da gramatica *)

[< ’Kwd "&"; e2 = parse_simple; e = parse_more_conjs (E(e1, e2)) >] -> e

| [< ’Kwd "|"; e2 = parse_simple; e = parse_more_conjs (Ou(e1, e2)) >] -> e

| [< >] -> e1

and parse_simple = parser (* corresponde a entrada F da gramatica *)

[< ’Ident s >] -> Var s

| [< ’Kwd "TRUE" >] -> Verdade

| [< ’Kwd "FALSE" >] -> Falso

| [< ’Kwd "!"; e = parse_expr >] -> Nao e

| [< ’Kwd "("; e = parse_expr; ’Kwd ")" >] -> e

let parse_expression = parser [< e = parse_expr; _ = Stream.empty >] -> e

S. Melo de Sousa Arvores de Sintaxe Abstracta

Acccoes semanticas em Gramaticas Livres de ContextoArvore de Sintaxe Abstracta

Valores Semanticos em Gramaticas DescendentesValores Semanticos em Gramaticas Ascendentes

Valores Semanticos em Yacc

%{

%}

%token <int> INT

%token PLUS MINUS TIMES DIV EOF

%left PLUS MINUS

%left TIMES DIV

%left uminus

%start expr

%type <int> expr

%%

expr: INT {$1}

| expr PLUS expr {$1 + $3}

| expr MINUS expr {$1 - $3}

| expr TIMES expr {$1 * $3}

| expr DIV expr {$1 / $3}

| MINUS expr %prec uminus {-$2}

;

S. Melo de Sousa Arvores de Sintaxe Abstracta

Acccoes semanticas em Gramaticas Livres de ContextoArvore de Sintaxe Abstracta

Valores Semanticos em Gramaticas DescendentesValores Semanticos em Gramaticas Ascendentes

Pilha de Valores Semanticos

Pilha de valores Input Accao

ε 1 + 2 ∗ 3 $ shift1 : INT + 2 ∗ 3 $ reduce1 : expr + 2 ∗ 3 $ shift1 : expr | + 2 ∗ 3 $ shift1 : expr | + | 2 : INT ∗ 3 $ reduce1 : expr | + | 2 : expr ∗ 3 $ shift1 : expr | + | 2 : expr | ∗ 3 $ shift1 : expr | + | 2 : expr | ∗ | 3 : INT $ reduce1 : expr | + | 2 : expr | ∗ | 3 : expr $ reduce1 : expr | + | 6 : expr $ reduce7 : expr $ accept

S. Melo de Sousa Arvores de Sintaxe Abstracta

Acccoes semanticas em Gramaticas Livres de ContextoArvore de Sintaxe Abstracta

Valores Semanticos em Gramaticas DescendentesValores Semanticos em Gramaticas Ascendentes

Valores Semanticos em Yacc

%{

type op = Soma | Diff | Mult | Div

type ast = Binop of ast*op*ast | Neg of ast | Val of int

%}

%token INT PLUS MINUS TIMES DIV EOF

%left PLUS MINUS

%left TIMES DIV

%left uminus

%start expr

%type <ast> expr

%%

expr: INT {Val $1}

| expr PLUS expr {Binop ($1,Soma,$3)}

| expr MINUS expr {Binop ($1,Diff,$3)}

| expr TIMES expr {Binop ($1,Mult,$3)}

| expr DIV expr {Binop ($1,Div,$3)}

| MINUS expr %prec uminus {Neg $2}

;

S. Melo de Sousa Arvores de Sintaxe Abstracta

Acccoes semanticas em Gramaticas Livres de ContextoArvore de Sintaxe Abstracta

Plano

1 Acccoes semanticas em Gramaticas Livres de Contexto

2 Arvore de Sintaxe Abstracta

S. Melo de Sousa Arvores de Sintaxe Abstracta

Acccoes semanticas em Gramaticas Livres de ContextoArvore de Sintaxe Abstracta

Princıpios

E possıvel escrever compiladores completos utilizando exclusivamente omecanismo de accoes semanticas associadas as producoes.

No entanto, tais compiladores sao difıceis de ler e de manter.

Outra ponto ao desfavor de tal arquitectura e o facto de o processo semanticoter de acompanhar a analise sintactica (i.e. obrigacao de seguir a ordem doparsing quando esta pode nao ser a mais comoda).

por forma a melhorar a modularidade e a separacao clara entre processosintactico e processo semantico e habitual deixar as accoes semanticasproduzirem uma estrutura de dados que codifica todo o programa analisado eque podera ser explorada e utilizada conveniente pelas restantes fases dacompilacao: a arvore de sintaxe abstracta, AST.

S. Melo de Sousa Arvores de Sintaxe Abstracta

Acccoes semanticas em Gramaticas Livres de ContextoArvore de Sintaxe Abstracta

Princıpios

Linguagens de programacao modernos = programacao estruturada=⇒ AST: representacao estruturada de programas

As AST facilitam:

A verificacao dos tipos;a geracao de programas;a transformacao, a manipulacao e a optimizacao de programas

S. Melo de Sousa Arvores de Sintaxe Abstracta

Acccoes semanticas em Gramaticas Livres de ContextoArvore de Sintaxe Abstracta

Princıpios

Fala-se assim de Sintaxe Concreta vs. Sintaxe Abstracta

Sintaxe Concreta = Sintaxe oferecida ao programador

sintaxe Abstracta = Sintaxe manipulada pelo computador

S. Melo de Sousa Arvores de Sintaxe Abstracta

Acccoes semanticas em Gramaticas Livres de ContextoArvore de Sintaxe Abstracta

Princıpios

S. Melo de Sousa Arvores de Sintaxe Abstracta

Acccoes semanticas em Gramaticas Livres de ContextoArvore de Sintaxe Abstracta

Princıpios

Sintaxe concreta:

1 while b do begin i1;i2 end2 while b do i1;i2 done3 enquanto b fazer i1 seguido de i2 fim

Este exemplos representam a mesma sequencia de comandos, naturalmenteserao traduzidos para a mesma sintaxe abstracta.

Melhor ainda, as AST permitam um bom tratamento de construcoes sintacticasqualificadas de acucar sintactico. Por exemplo a estrutura cıclica repeat podeser vista como um caso particular de while. Assim

repeat i until b pode dar convenientemente a mesma AST de que i; while

not b do i

S. Melo de Sousa Arvores de Sintaxe Abstracta

Acccoes semanticas em Gramaticas Livres de ContextoArvore de Sintaxe Abstracta

Princıpios

Em Ocaml, os tipos indutivos fornecem uma forma comoda de representar estas AST.

T: sequencia de X type T = X listT: Alternativamente A, B ou C type T = Ca of A | Cb of B | Cc of C

S. Melo de Sousa Arvores de Sintaxe Abstracta

Acccoes semanticas em Gramaticas Livres de ContextoArvore de Sintaxe Abstracta

AST em Yacc

%{

type op = Soma | Diff | Mult | Div

type e = Binop of e*op*e | Neg of e | Val of int

type ast = e list

%}

%token INT PLUS MINUS TIMES DIV EOF DOT

%left PLUS MINUS

%left TIMES DIV

%left uminus

%start prog

%type <ast> prog

%%

prog:

/*empty*/ {[]}

| expr DOT prog {$1::$2}

expr: INT {Val $1}

| expr PLUS expr {Binop ($1,Soma,$3)}

| expr MINUS expr {Binop ($1,Diff,$3)}

| expr TIMES expr {Binop ($1,Mult,$3)}

| expr DIV expr {Binop ($1,Div,$3)}

| MINUS expr %prec uminus {Neg $2}

;

S. Melo de Sousa Arvores de Sintaxe Abstracta

Acccoes semanticas em Gramaticas Livres de ContextoArvore de Sintaxe Abstracta

Algumas Consideracoes

A analise da AST pelas fases de compilacao seguintes pode resultar nadeteccao de erros. Neste caso como assinalar esta ocorrencia de formaconveniente, por exemplo indicando a localizacao precisa da localizacao.

De facto o processamento da AST ja nao ocorre com o contacto directodo ficheiro fonte.

Por isso e necessario juntar na AST toda a informacao necessaria alocalizacao fısica das estruturas contidas na AST (ou seja do localconcreto no ficheiro onde ocorrem as estruturas arquivadas na AST).

O OcamlYacc disponibiliza varios mecanismos para tal processamento(ver os tipos de dados position e lexbuf do modulo Lexing).

S. Melo de Sousa Arvores de Sintaxe Abstracta

Acccoes semanticas em Gramaticas Livres de ContextoArvore de Sintaxe Abstracta

Algumas Consideracoes

(Do manual de referencia - Modulo Lexing): Note that the lexingengine will only manage the pos cnum field of lex curr p by updating itwith the number of characters read since the start of the lexbuf. For theother fields to be accurate, they must be initialised before the first use ofthe lexbuf, and updated by the lexer actions.

Da mesma forma, um dos aspectos importantes por considerar ´e o tipoda informacao contida na AST. Esta informacao ira ser calculada na faseseguinte e integrada na AST em si (decoracao da AST). Como tal estainformacao deve ja ser contemplada na fase da definicao da AST.

Assim de forma geral, cada informacao relevante as fases posteriorespodem ser acrescentada a AST para um processamento adequado.

S. Melo de Sousa Arvores de Sintaxe Abstracta

Acccoes semanticas em Gramaticas Livres de ContextoArvore de Sintaxe Abstracta

Arith - Um exemplo completo

open Lexing

type type_expr = Undef | INT | FLOAT

type binop = Sum | Diff | Prod | Quot

type expr =

| F of float * position * position

| I of int * position * position

| Var of string * type_expr * position * position

| Op of binop * expr * expr * type_expr * position * position

| Neg of expr * type_expr * position * position

| Letin of string * expr * expr * type_expr * position * position

type instr =

Set of string * expr * position * position

| Print of expr * position * position

| Dummy

type prg = instr list

S. Melo de Sousa Arvores de Sintaxe Abstracta

Acccoes semanticas em Gramaticas Livres de ContextoArvore de Sintaxe Abstracta

Arith - Um exemplo completo

{ open Lexing

(...)

(* func~ao para a visualizac~ao de mensagens de erros lexicos *)

let print_lexing_error st pos =

prerr_string ("Erro Lexico em "^pp_position pos^"\n\ta sequencia \""^

st^"\" n~ao e autorizada\n")

let kwd_tbl = ["let",LET ;"in",IN ;"set",SET;"print",PRINT]

let id_or_kwd s = try List.assoc s kwd_tbl with _ -> IDENT(s)

(* A posic~ao exacta no ficheiro e algo da responsabilidade do

utilizador.. Esta func~ao, chamada quando e detectada um fim de linha

incrementa o numero de linha e actualiza o campo pos_bol.

Relembramos que o unico campo da responsabilidade do ocamllex e o

campo pos_cnum que arquiva o numero de caracteres entre o inıcio do

ficheiro e a posic~ao actual. Assim, para calcular a posic~ao na linha

corrrente basta calcular pos_cnum - pos_bol *)

let incr_pos lx = let pos = lx.lex_curr_p in

lx.lex_curr_p <- {pos with pos_bol = pos.pos_cnum ; pos_lnum = pos.pos_lnum +1}

}

let letter = [’a’-’z’ ’A’-’Z’]

let digit = [’0’-’9’]

let ident = letter (letter | digit | ’_’)*

let integer = digit+

let floatn = integer ’.’integer?

let space = [’ ’ ’\r’ ’\t’]

S. Melo de Sousa Arvores de Sintaxe Abstracta

Acccoes semanticas em Gramaticas Livres de ContextoArvore de Sintaxe Abstracta

Arith - Um exemplo completo

rule nexttoken = parse

space+ { nexttoken lexbuf }

| ’\n’ { incr_pos lexbuf ; nexttoken lexbuf}

| ident { id_or_kwd (lexeme lexbuf) }

| ’+’ { PLUS }

| ’-’ { MINUS }

| ’*’ { TIMES }

| ’/’ { DIV }

| ’=’ { EQ }

| ’(’ { LP }

| ’)’ { RP }

| ’;’ { DOT }

| floatn { Fl (float_of_string (lexeme lexbuf)) }

| integer { In (int_of_string (lexeme lexbuf)) }

| eof { EOF }

| "//" [^’\n’] { nexttoken lexbuf}

| "(*" { comment lexbuf ; nexttoken lexbuf }

| "*)" {(print_lexing_error "unbalanced comments");nexttoken lexbuf)

| _ {(print_lexing_error (lexeme lexbuf) lexbuf.lex_curr_p);

nexttoken lexbuf}

and comment = parse

"(*" { comment lexbuf; comment lexbuf }

| "*)" { () }

| ’\n’ { incr_pos lexbuf ; comment lexbuf}

| _ { comment lexbuf }

| eof { print_lexing_error "unbalanced comments");nexttoken lexbuf }

S. Melo de Sousa Arvores de Sintaxe Abstracta

Acccoes semanticas em Gramaticas Livres de ContextoArvore de Sintaxe Abstracta

Arith - Um exemplo completo

%{

open Ast (...)

let parse_error msg = prerr_string msg

%}

%token <int> In

%token <float> Fl

%token <string> IDENT

%token SET LET IN PRINT EOF LP RP PLUS MINUS TIMES DIV EQ DOT

%nonassoc IN

%left MINUS PLUS

%left TIMES DIV

%nonassoc uminus

%start prog

%type < Ast.prg > prog

S. Melo de Sousa Arvores de Sintaxe Abstracta

Acccoes semanticas em Gramaticas Livres de ContextoArvore de Sintaxe Abstracta

Arith - Um exemplo completo

%%

prog:

| instrs EOF {List.rev $1)};

instrs:

| instr {[$1]}

| instrs instr {$2::$1}

| instrs error {pp_syntax_error (rhs_start_pos 2) (rhs_end_pos 2);$1};

instr:

| SET IDENT EQ expr DOT {Set($2,$4,symbol_start_pos (), symbol_end_pos ())}

| PRINT expr DOT {Print($2,symbol_start_pos (), symbol_end_pos ())};

expr:

| Fl {F($1,symbol_start_pos (), symbol_end_pos ())}

| In {I($1,symbol_start_pos (), symbol_end_pos ())}

| IDENT {Var ($1, undef_type,symbol_start_pos (), symbol_end_pos ())}

| expr PLUS expr {Op(Sum,$1,$3, Undef,symbol_start_pos (), symbol_end_pos ())}

| expr MINUS expr {Op(Diff,$1,$3, Undef,symbol_start_pos (), symbol_end_pos ())}

| expr TIMES expr {Op(Prod,$1,$3, Undef,symbol_start_pos (), symbol_end_pos ())}

| expr DIV expr {Op(Quot,$1,$3, Undef,symbol_start_pos (), symbol_end_pos ())}

| MINUS expr %prec uminus {Neg ($2, Undef,symbol_start_pos (), symbol_end_pos ())}

| LET IDENT EQ expr IN expr {Letin($2,$4,$6, Undef,symbol_start_pos (), symbol_end_pos ())}

| LP expr RP {$2};

S. Melo de Sousa Arvores de Sintaxe Abstracta