Está en la página 1de 37

Compiladores

Introducción al Análisis Sintáctico

Gramáticas de Contexto Libre,


Arboles de Parseo y Derivaciones
Definiendo Context-Free Grammars
(CFGs)
• Terminales
– Símbolos para strings o tokens
• No terminales
– Variables sintácticas
• Símbolo de Inicio
– Un no-terminal especial es designado
• Producciones
– La forma en que los terminales y no-terminales son
combinados para formar strings
– Un no-terminal en el lado izquierdo (LHS) y un string de
terminales y no-terminales en el lado derecho (RHS)
Ejemplo de una CFG
<S>  ( <S> ) <S> | ε
Ejemplo de una CFG
<S>  ( <S> ) <S>

<S>  ε
Ejemplo de una CFG
<S>  ( <S> ) <S>

<S>  ε Terminales
Ejemplo de una CFG
<S>  ( <S> ) <S>

<S>  ε No-terminales
Ejemplo de una CFG
<S>  ( <S> ) <S>

<S>  ε Símbolo de Inicio: <S>


Ejemplo de una CFG
<S>  ( <S> ) <S>

<S>  ε Producciones
Los lenguajes regulares son un subconjunto
de los lenguajes libres de contexto
Expresión Regular Gramática libre de contexto
a <A>  a
Si p y q son expresiones regulares, usando CFGs <P> y <Q>
p·q <S>  <P> <Q>

p|q <S>  <P>


<S>  <Q>

p* <S>  <S> <P>


<S>  ε
Los lenguajes regulares son un subconjunto
de los lenguajes libres de contexto
Expresión Regular Gramática libre de contexto

Si p es una expresión regular, usando una CFG <P>,

Qué es?
??? <S>  <S> <P>
<S>  <P>

P? ???
Entonces por qué usar expresiones
regulares?
• Separar el análisis sintáctico en partes léxica y no-
léxica es una buena modularización

• Las reglas léxicas son simples y pueden ser expresadas


usando expresiones regulares

• Las expresiones regulares son más concisas

• Las implementaciones de analizadores léxicos para


expresiones regulares son más eficientes
Creando una CFG
• Tenemos que crear una CFG a partir de las
definiciones del lenguaje

• Hay muchas cosas involucradas


– Vamos a ver algunas de ellas en clase

• Veamos un lenguaje simple


Ejemplo: Una CFG para expresiones
• Expresiones aritméticas simples con + y *
– 8.2 + 35.6
– 8.32 + 86 * 45.3
– (6.001 + 6.004) * (6.035 * -(6.042 + 6.046))
• Terminales (o tokens)
– num para todos los números
– plus_op (‘+’), minus_op (‘-’), times_op(‘*’),
left_paren_op(‘(‘), right_paren_op(‘)’)
• Cuál es la gramática para todas las expresiones
posibles?
Ejemplo: Una CFG para expresiones

<expr>  <expr> <op> <expr>


<expr>  ( <expr> )
<expr>  - <expr>
<expr>  num
<op>  +
<op>  *
Ejemplo: Una CFG para expresiones

<expr>  <expr> <op> <expr>


<expr>  ( <expr> )
<expr>  - <expr>
<expr>  num Terminales
<op>  +
<op>  *
Ejemplo: Una CFG para expresiones

<expr>  <expr> <op> <expr>


<expr>  ( <expr> )
<expr>  - <expr>
<expr>  num Terminales
<op>  +
<op>  *
Ejemplo: Una CFG para expresiones

<expr>  <expr> <op> <expr>


<expr>  ( <expr> )
<expr>  - <expr>
<expr>  num No-terminales
<op>  +
<op>  *
Ejemplo: Una CFG para expresiones

<expr>  <expr> <op> <expr>


<expr>  ( <expr> )
<expr>  - <expr>
<expr>  num No-terminales
<op>  +
<op>  *
Ejemplo: Una CFG para expresiones

<expr>  <expr> <op> <expr>


<expr>  ( <expr> )
<expr>  - <expr>
<expr>  num Símbolo de Inicio:
<op>  + <expr>
<op>  *
Ejemplo: Una CFG para expresiones

<expr>  <expr> <op> <expr>


<expr>  ( <expr> )
<expr>  - <expr>
<expr>  num Producciones
<op>  +
<op>  *
Ejemplo: Una CFG para expresiones

<expr>  <expr> <op> <expr>


<expr>  ( <expr> )
<expr>  - <expr>
<expr>  num
<op>  +
<op>  *
Ejemplo: Una CFG para expresiones

<expr>  <expr> <op> <expr> | ( <expr> )


| - <expr> | num

<op>  + | *
Pregunta: Cuál es el lenguaje
definido por esta CFG?

<S>  a<S>a | aa
Derivaciones
• Cómo mostramos que una secuencia de tokens
es aceptada por una CFG?
• Una producción es usada para derivar una
secuencia de tokens a partir del símbolo de
inicio
• Dados los strings , y 
y una producción A  
Un solo paso de la derivación es
A  
Ejemplo de Derivación
• Gramática
<expr>  <expr><op><expr> | (<expr>) | -<expr> | num
<op>  + | *

• Entrada
36 * ( 8 + 23.4)

• Token Stream
num ‘*’ ‘(‘ num ‘+’ num ‘)’
Oscar Bonilla 25 Universidad Galileo
Arbol de Parseo

• Representación gráfica de la estructura


parseada

• Muestra la secuencia de derivaciones efectuada


– Nodos internos son no-terminales
– Hojas son terminales
– Cada nodo padre es el lado izquierdo (LHS) y los
hijos son el lado derecho (RHS) de una producción
Ejemplo de Arbol de Parseo

<expr>
Ejemplo de Arbol de Parseo
<expr>  <expr> <op> <expr>

<expr>

<expr> <op> <expr>


Ejemplo de Arbol de Parseo
<expr>  num

<expr>

<expr> <op> <expr>

num
Ejemplo de Arbol de Parseo
<op>  ‘*’

<expr>

<expr> <op> <expr>

num *
Ejemplo de Arbol de Parseo
<expr>  ‘(‘ <expr> ‘)’

<expr>

<expr> <op> <expr>

<expr>
num * ( )
Ejemplo de Arbol de Parseo
<expr>  <expr> <op> <expr>

<expr>

<expr> <op> <expr>

<expr>
num * ( )
<expr> <op> <expr>
Ejemplo de Arbol de Parseo
<expr>  num

<expr>

<expr> <op> <expr>

<expr>
num * ( )
<expr> <op> <expr>

num
Ejemplo de Arbol de Parseo
<op>  ‘+’

<expr>

<expr> <op> <expr>

<expr>
num * ( )
<expr> <op> <expr>

num +
Ejemplo de Arbol de Parseo
<expr>  num

<expr>

<expr> <op> <expr>

<expr>
num * ( )
<expr> <op> <expr>

num + num
Ejemplo de Arbol de Parseo
num ‘*’ ‘(‘ num ‘+’ num ‘)’

<expr>

<expr> <op> <expr>

<expr>
num * ( )
<expr> <op> <expr>

num + num
La Gramática es Ambigua
• Aplicar diferentes ordenes de derivación
produce árboles de parseo diferentes
• Esto no es bueno!
– Lleva a resultados ambiguos
– Muy probablemente va a producir resultados
inesperados
• Algunas veces el reescribir la gramática con
más no-terminales va a eliminar la ambiguedad

También podría gustarte