"O parser ascendente tenta encontrar a derivação mais à direita em ordem inversa, partindo da sentença de entrada e chegando ao símbolo inicial."
E → E + T | T
T → T * F | F
F → id | (E)
// Exemplo: gramática if-then-else ambígua
S → if E then S | if E then S else S | other
// Exemplo
S → aAc | aBd
A → b
B → b
%{
/* Declarações em C */
%}
/* Declarações Yacc */
%token NUM ID
%left '+' '-'
%left '*' '/'
%%
/* Regras gramaticais */
expr : expr '+' expr { $$ = $1 + $3; }
| NUM { $$ = $1; }
;
%%
/* Código C adicional */
%{
#include
#include
void yyerror(char *s);
int yylex();
%}
%token NUMBER ID
%left '+' '-'
%left '*' '/'
%right '^'
%nonassoc UMINUS
%%
program:
expr { printf("Resultado: %d\n", $1); }
;
expr:
expr '+' expr { $$ = $1 + $3; }
| expr '-' expr { $$ = $1 - $3; }
| expr '*' expr { $$ = $1 * $3; }
| expr '/' expr {
if ($3 == 0) {
yyerror("Divisão por zero");
$$ = 0;
} else {
$$ = $1 / $3;
}
}
| expr '^' expr {
int i, result = 1;
for (i = 0; i < $3; i++)
result *= $1;
$$ = result;
}
| '-' expr %prec UMINUS { $$ = -$2; }
| '(' expr ')' { $$ = $2; }
| NUMBER { $$ = $1; }
| ID { $$ = /* valor da variável */; }
;
%%
void yyerror(char *s) {
fprintf(stderr, "Erro: %s\n", s);
}
int main() {
yyparse();
return 0;
}
import ply.yacc as yacc
import ply.lex as lex
# Definição do analisador léxico
tokens = (
'NUMBER',
'PLUS',
'MINUS',
'TIMES',
'DIVIDE',
'LPAREN',
'RPAREN',
)
# Regras léxicas
t_PLUS = r'\+'
t_MINUS = r'-'
t_TIMES = r'\*'
t_DIVIDE = r'/'
t_LPAREN = r'\('
t_RPAREN = r'\)'
t_ignore = ' \t'
def t_NUMBER(t):
r'\d+'
t.value = int(t.value)
return t
def t_error(t):
print(f"Caractere ilegal '{t.value[0]}'")
t.lexer.skip(1)
# Construir o lexer
lexer = lex.lex()
# Regras sintáticas
def p_expression_binop(p):
'''expression : expression PLUS expression
| expression MINUS expression
| expression TIMES expression
| expression DIVIDE expression'''
if p[2] == '+' : p[0] = p[1] + p[3]
elif p[2] == '-': p[0] = p[1] - p[3]
elif p[2] == '*': p[0] = p[1] * p[3]
elif p[2] == '/': p[0] = p[1] / p[3]
def p_expression_group(p):
'expression : LPAREN expression RPAREN'
p[0] = p[2]
def p_expression_number(p):
'expression : NUMBER'
p[0] = p[1]
def p_error(p):
if p:
print(f"Erro de sintaxe em '{p.value}'")
else:
print("Erro de sintaxe no final da entrada")
# Construir o parser
parser = yacc.yacc()
# Função para testar
def parse(s):
return parser.parse(s)
# Ordem de precedência (do menor para o maior)
precedence = (
('left', 'PLUS', 'MINUS'),
('left', 'TIMES', 'DIVIDE'),
('right', 'UMINUS'), # Menos unário
)
def p_expression_uminus(p):
'expression : MINUS expression %prec UMINUS'
p[0] = -p[2]
def p_nome_da_regra(p):
'não_terminal : sequência de símbolos'
# ou
'''não_terminal : alternativa1
| alternativa2
| alternativa3'''
# Ações semânticas aqui
p[0] = ... # Valor retornado pelo não-terminal
def p_declaration(p):
'declaration : TYPE ID ASSIGN expression SEMICOLON'
p[0] = ('declare', p[1], p[2], p[4]) # Cria uma tupla representando a declaração
symbol_table[p[2]] = {'type': p[1], 'value': None} # Adiciona à tabela de símbolos
import ply.yacc as yacc
import ply.lex as lex
# Definição do analisador léxico
tokens = ('NUMBER', 'ID', 'PLUS', 'MINUS', 'TIMES', 'DIVIDE', 'LPAREN', 'RPAREN', 'EQUALS')
# Regras léxicas
t_PLUS = r'\+'
t_MINUS = r'-'
t_TIMES = r'\*'
t_DIVIDE = r'/'
t_LPAREN = r'\('
t_RPAREN = r'\)'
t_EQUALS = r'='
t_ID = r'[a-zA-Z_][a-zA-Z0-9_]*'
def t_NUMBER(t):
r'\d+'
t.value = int(t.value)
return t
t_ignore = ' \t'
def t_newline(t):
r'\n+'
t.lexer.lineno += len(t.value)
def t_error(t):
print(f"Caractere ilegal '{t.value[0]}'")
t.lexer.skip(1)
# Construir o lexer
lexer = lex.lex()
# Precedência e associatividade
precedence = (
('left', 'EQUALS'),
('left', 'PLUS', 'MINUS'),
('left', 'TIMES', 'DIVIDE'),
('right', 'UMINUS'),
)
# Dicionário para armazenar variáveis
variables = {}
# Regras de gramática
def p_statement_assign(p):
'statement : ID EQUALS expression'
variables[p[1]] = p[3]
p[0] = ('assign', p[1], p[3])
def p_statement_expr(p):
'statement : expression'
p[0] = ('expr', p[1])
def p_expression_binop(p):
'''expression : expression PLUS expression
| expression MINUS expression
| expression TIMES expression
| expression DIVIDE expression'''
if p[2] == '+' : p[0] = ('add', p[1], p[3])
elif p[2] == '-': p[0] = ('sub', p[1], p[3])
elif p[2] == '*': p[0] = ('mul', p[1], p[3])
elif p[2] == '/': p[0] = ('div', p[1], p[3])
def p_expression_uminus(p):
'expression : MINUS expression %prec UMINUS'
p[0] = ('neg', p[2])
def p_expression_group(p):
'expression : LPAREN expression RPAREN'
p[0] = p[2]
def p_expression_number(p):
'expression : NUMBER'
p[0] = ('num', p[1])
def p_expression_id(p):
'expression : ID'
p[0] = ('var', p[1])
def p_error(p):
if p:
print(f"Erro de sintaxe em '{p.value}'")
else:
print("Erro de sintaxe no final da entrada")
# Construir o parser
parser = yacc.yacc()
# Função para testar
def parse(s):
return parser.parse(s)
# Exemplo de uso
resultado = parse("x = 10 + 20 * (30 - 5)")
print(resultado)
# Modo detalhado de depuração
parser = yacc.yacc(debug=True)
# Ou na hora de analisar
resultado = parser.parse(texto, debug=True)
tokens = (
'NUMBER',
'PLUS', 'MINUS', 'TIMES', 'DIVIDE',
'LPAREN', 'RPAREN',
)
t_PLUS = r'\+'
t_MINUS = r'-'
t_TIMES = r'\*'
t_DIVIDE = r'/'
t_LPAREN = r'\('
t_RPAREN = r'\)'
def t_NUMBER(t):
r'\d+'
t.value = int(t.value)
return t
precedence = (
('left', 'PLUS', 'MINUS'),
('left', 'TIMES', 'DIVIDE'),
('right', 'UMINUS'),
)
def p_expression_binop(p):
'''expression : expression PLUS expression
| expression MINUS expression
| expression TIMES expression
| expression DIVIDE expression'''
# Implemente as operações aqui
program : statement_list
statement_list : statement
| statement_list statement
statement : if_statement
| while_statement
| print_statement
| assign_statement
if_statement : IF condition THEN statement_list END
| IF condition THEN statement_list ELSE statement_list END
while_statement : WHILE condition DO statement_list END
print_statement : PRINT expression SEMICOLON
assign_statement : ID EQUALS expression SEMICOLON
condition : expression GREATER expression
| expression LESS expression
| expression EQUALS EQUALS expression
expression : expression PLUS term
| expression MINUS term
| term
term : term TIMES factor
| term DIVIDE factor
| factor
factor : NUMBER
| ID
| LPAREN expression RPAREN
x = 10;
y = 20;
if x < y then
print x;
else
print y;
end
while x < 100 do
print x;
x = x + 10;
end
# Construir o lexer
lexer = lex.lex()
# Construir o parser usando o lexer
parser = yacc.yacc()
# Analisar uma entrada
resultado = parser.parse(texto, lexer=lexer)