From e95ed1e55afd107b22c2c638166aed2819aac9d9 Mon Sep 17 00:00:00 2001 From: Daniel Santa Rosa Date: Mon, 28 Nov 2022 23:21:29 -0300 Subject: [PATCH 1/4] =?UTF-8?q?=F0=9F=9A=A7=20Change=20production=20rules?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Prooduction.py | 104 ++-------- src/Sintatic/ProductionRules.py | 346 ++++++++++++++++++++++++-------- src/main.py | 6 + 3 files changed, 288 insertions(+), 168 deletions(-) diff --git a/src/Prooduction.py b/src/Prooduction.py index be9a498..bcbb062 100644 --- a/src/Prooduction.py +++ b/src/Prooduction.py @@ -1,6 +1,6 @@ from typing import List, Optional, TypedDict from TokenUtils.Token import Token -from Sintatic.ProductionRules import map, ProductionRules, Rule, REL, Boolean, SimboloSomaSub, Operavel, Matriz, Print, comp, Read, RetornoFuncao, ChamadaFuncao, Expressao, ExpressaoRelacional, ExpressaoLogica +from Sintatic.ProductionRules import map, ProductionRules, Rule # Testes relacionais @@ -298,7 +298,7 @@ def isNonTerminal(token: str): return False; def isSemiTerminal(sm: str): - semis = { '-IDE', '-NRO', '-CAC', '-LOG', '-ART' }; + semis = { '-IDE', '-NRO', '-CAC', '-LOG', '-ART', '-PRE' }; if sm in semis: return True; return False; @@ -344,11 +344,21 @@ def getFists(productionRules: ProductionRules): elif (isNonTerminal(rule[0])): # se o primerio elemento for um não terminal elemProduction = map.get(rule[0]); # Busca a produção desse não terminal if (elemProduction == None): # Se a procução não existe - raise Exception("Produção inexistente"); # Há um erro + raise Exception("Produção: ", rule[0], "inexistente"); # Há um erro l: List[str] = []; for lst in getFists(elemProduction): # Encontra o conjunto fist da produção l.extend(lst); # Transforma em uma unica lista de string conjuntoFisrt.append(l); # Adiciona lista ao conjuto da prudção atual + #crbempty = canRuleBeEmpty(rule[0]); + #crbindex = 0 + #if (crbempty and len(rule) > 1): + # elemProduction = map.get(rule[1]); + # if (elemProduction == None): # Se a procução não existe + # raise Exception("Produção: ", rule[0], "inexistente"); # Há um erro + # r: List[str] = []; + # for st in getFists(elemProduction): # Encontra o conjunto fist da produção + # r.extend(st); # Transforma em uma unica lista de string + # conjuntoFisrt.append(r); else: # Se form um terminal conjuntoFisrt.append([rule[0]]); return conjuntoFisrt; # Retorna o conjunto encontrado @@ -395,20 +405,24 @@ def Production(prod: ProductionRules, tokens: 'list[Token]', initialTokenindex: lookahead = tokens[tokenIndex]; if (isNonTerminal(to)): # Se for um não terminal p = map.get(to); # Encontra a produção para esse não terminal - if (p == None): # Erro caso a produção não exista + if (p == None): + print("\n\n-- produção tentado entcontrar"); + print(to); # Erro caso a produção não exista raise Exception("Produção inexistente!!"); res = Production(p, tokens, tokenIndex); tokenIndex = res['tokenIndex'] - 1; elif (isSemiTerminal(to)): # Se for um terminal, cujo valor do token não é importante if (matchSemiterminal(lookahead.token, to)): # verifica o apenas se o tipo do token é o esperado - print("Passado ", to); + print("Passado ", to, " - ", lookahead.value); else: msg = "Esperado: " + to + " mas recebido" + lookahead.token; raise Exception(msg); elif (to == lookahead.value): # se for um termina, verifica se o valor recebido é igual - print("Passado: ", to); # ao valor esperao + print("Passado: ", to, " - ", lookahead.value); # ao valor esperao else: # se não for, lança erro + print(rule); + print(lookahead); raise Exception('Esperado ' + to + " mas recebido: " + lookahead.value); tokenIndex = tokenIndex + 1; return { @@ -418,80 +432,4 @@ def Production(prod: ProductionRules, tokens: 'list[Token]', initialTokenindex: if __name__ == "__main__": # Testes de operador relacional - print("------ Relacionais ------"); - Production(REL, t_rel_eq); - Production(REL, t_rel_diff); - Production(REL, t_rel_geq); - Production(REL, t_rel_gt); - Production(REL, t_rel_leq); - Production(REL, t_rel_lt); - Production(REL, t_rel_atr); - - # Testes booleanos - print("------ Booleanos ------"); - Production(Boolean, t_bool_true); - Production(Boolean, t_bool_false); - - # Testes operadores de soma e subtração - print("------ SomaSub ------"); - Production(SimboloSomaSub, t_somasub_soma); - Production(SimboloSomaSub, t_somasub_sub); - - # Testes operadores de soma e subtração - print("------ Operavel ------"); - Production(Operavel, t_operavel_IDE); - Production(Operavel, t_operavel_NRO); - - # Testes matriz - print("------ Matriz ------"); - Production(Matriz, t_matrix_single_IDE); - Production(Matriz, t_matrix_single_nro); - Production(Matriz, t_matrix_multiplo); - - # Testes matriz - print("------ Print ------"); - Production(Print, t_print_CAC); - Production(Print, t_print_IDE); - Production(Print, t_print_Comp); - Production(Print, t_print_Matriz); - - # Testes matriz - print("------ Tipo composto ------"); - Production(comp, t_comp); - - # Testes read - print("------ Print ------"); - Production(Read, t_read_Comp); - Production(Read, t_read_Matriz); - Production(Read, t_readt_IDE); - - # Testes retorno de função - print("------ RetornoFuncao ------"); - Production(RetornoFuncao, t_retunFunction_empty); - Production(RetornoFuncao, t_retunFunction_1IDE); - Production(RetornoFuncao, t_retunFunction_2IDE); - Production(RetornoFuncao, t_retunFunction_NRO); - Production(RetornoFuncao, t_retunFunction_CAC); - Production(RetornoFuncao, t_retunFunction_Matriz); - Production(RetornoFuncao, t_retunFunction_comp); - Production(RetornoFuncao, t_retunFunction_retunFunction1); - Production(RetornoFuncao, t_retunFunction_retunFunction2); - - # Testes de chamada de função ou procedimento - print("------ ChamadaFuncao ------"); - Production(ChamadaFuncao, t_chamada); - - # Testes de operaçãoes aritimeticas - print("------ Expressao ------"); - Production(Expressao, t_aritimetic_IDE_Plus_NRO); - Production(Expressao, t_aritimetic_NRO_Plus_NRO); - Production(Expressao, t_aritimetic_IDE_Mult_IDE); - Production(Expressao, t_aritimetic_Mix); - - # Testes de operaçãoes relacionais - print("------ ExpressaoRelacional ------"); - Production(ExpressaoRelacional, t_relational); - - # Testes de expressões lógicas - print("------ ExpressaoLogica ------"); - Production(ExpressaoLogica, t_logic); \ No newline at end of file + d = 54; \ No newline at end of file diff --git a/src/Sintatic/ProductionRules.py b/src/Sintatic/ProductionRules.py index fbbc36c..95d93d9 100644 --- a/src/Sintatic/ProductionRules.py +++ b/src/Sintatic/ProductionRules.py @@ -7,106 +7,282 @@ # Operadores relacionais REL = [['!='], ['=='], ['<'], ['<='], ['>'], ['>='], ['=']]; -# Valor booleano -Boolean = [['true'], ['false']]; - -# Soma ou subtração -SimboloSomaSub = [['+'], ['-']]; - -# Operavel -Operavel = [['-IDE'], ['-NRO']]; - -# Expressao Aritmetica -Expressao = [['', '']]; -ExpressaoComMult = [['',''], []]; -ExpressaoMulti =[['', '']]; -ExpressaoMultiComValor = [['*', ''], ['/', ''], []] -Valor = [[''],['(', '', ')']]; - -# Expressaõ relacional -ExpressaoRelacional = [['', '', ''], []] -ValorRelacional = [['-IDE', ''], ['-NRO'], ['-CAC'], ['(', ''], ['']]; -ValorRelacionalComIDE = [['(', '', ')'], ['.', '-IDE'], [''], []]; -ValorRelacionalComParentesis = [['', ')'], ['', ')'], ['', ')']]; - -# Expressão logica -ExpressaoLogica = [['', '', '']]; -ExpressaoOpcional = [['', '', ''], []]; -op = [['&&', '||']]; -neg = [[''], ['']]; -OperadorLogico = [['&&', ''], ['||', '']]; -Negacao = [['!', '']]; - -# Matriz -Matriz = [['-IDE', '']]; -DimensoesDeAcesso = [['', '']]; -Access = [['[', '', ']']]; -end = [[''], []]; -Indice = [['-NRO'], ['-IDE']]; - -# Print -Print = [['print', '(', '', ')', ';']]; -ConteudoDoPrint = [['-IDE', ''], ['-CAC']]; -ConteudoDoPrintComIDE = [[''], ['.', '-IDE'], []]; - -# Tipo composto -comp = [['-IDE', '.', '-IDE']]; - -# Read -Read = [['read', '(', '', ')', ';']]; -Ler = [['-IDE', '']]; -LerComIDE = [[''], ['.', '-IDE'], []]; - -# Chamada funcção -RetornoFuncao = [['-IDE', '(', '', ')']] -ParametrosOpcionais = [[''], []]; -ListaDeParametros = [['', '']]; -MultiplosParametros = [[',', ''], []]; -Parametro = [['-IDE', ''], ['-NRO'], ['-CAC']]; -ParametroComIDE = [[''], ['.', '-IDE'], ['(', '', ')'], []]; +EstruturaDoPrograma = [[ + '', + '', + '', + '' +]] + +# Valor booleano +Boolean = [['true'], ['false']] + + +# Definição da quantidade de Dimensoes de acesso a uma variavel de forma opcional +OpcionalDimensoesDeAcesso = [[''], []] + + +# Definição da quantidade de Dimensoes de acesso de uma matriz +DimensoesDeAcesso = [['', '']]; +TamanhoDaDimensao = [['[', '', ']']]; +DimensaoOpcional = [['', ''], []]; +IndiceDeAcesso = [['-NRO'], ['-IDE'], []]; + + +# Declaração opcional de uma estrutura +OpcionalStruct = [['', ''], []] + + +# Declaração de um tipo composto +DeclaracaoStruct = [['struct', '-IDE', '']] +# Corpo de uma estrutura ou especialização de uma estrutura +CorpoDaEstrutura = [['{', '', '}'], ['']]; +# Extends de uma struct +EspecializacaoDeStruct = [['extends', '-IDE', '{', '', '}']]; + + +# Variaveis do corpo de uma struct +VariaveisDaStruct = [['', '']]; +OpcionaisVariaveisDaStruct = [[''], []]; + + +# Declaração de variavel dentro de estrutura +DeclaracaoDeVariavelDeStruct = [['', '', ';']]; +# Identificaçao da variavel e atribuicaço de valor +ListaDeVariaveisStruct = [['-IDE', '', '']] +# listagem e atribuição de outras variaveis +AtribuicaoMultiplaStruct = [['', '']] +# multiplas declarações opcionais +OutrasAtribuicoesOpcionais = [[',', ''], []] +# Valor opcional de atribuiçao +AtribuicaoDeVariavelStruc = [['=', ''], []] +ValorDeStribuicaoStruct = [['-IDE', '', ''], ['-NRO'], ['-CAC'], [''], ['(', '', ')'], ['!', '-IDE', '', '', '']] + +# elemento de matriz +# elemento de tipo composto +# retorno de função +Valor_Comecando_Com_IDE = [[''], ['(', '', ')']] + +VALESSSSXPRESS = [['', ''], []] + +# = | + + +# Declaração opcional de variáveis globais +OpcionaislVariaveisGlobais = [[''], []] +# Bloco de variaveis globais +VariaveisGlobais = [['var', '{', '', '}']] +DeclaracaoDentroDoBlocoDeVar = [['']] + + +# Declaração do opcionais de constantes +OpcionaisConstantes = [[''], []] +# Bloco de constantes +Constantes = [['const', '{', '', '}']] +DeclaracaoDentroDoBlocoDeConst = [['']] + + +# Area para declaração de funões ou procedimentos +AreaDeFuncoesEProcedimentos = [['', '']] +HasAnotherFuncOrProc = [[''], []] +FuncaoOuProcedimento = [[''], ['']] + + +# Bloco +BlocoDeCodigo = [['{', '', '}']] +Conteudos = [['', ''], []] +ConteudoDeBloco = [[''], [''], [''], [''], [''], ['-IDE', '']] + # Chamada de função ou procedimento -ChamadaFuncao = [['', ';']]; +# atribuiçõo de valor em uma variavel +# atribuição de valor em matriz +VariacoesComIDEnoBloco = [['(', '', ')', ';'], ['=', '', ';'], ['', '=', '', ';']] +# = + + +# While +While = [['while', '(', '', ')', '']] + + + +# If +If = [['if', '(', '', ')', 'then', '']] +ConteudoDoIf = [['', '']] +OpcionalElse = [['else', ''], []] + + + +# Elemento de matriz +# = IDE +DimensaoDaMatriz = [['', '']] +IndiceDeAcessoDaMatriz = [['[', '', ']']] +OpcionalIndice = [['', ''], []] +ValorDoIndice = [['-NRO'], ['-IDE']] + + +#! Print +Print = [['print', '(', '', ')', ';']] +ConteudoDoPrint = [['-IDE', ''], ['-CAC']] +ConteudoDoPrintIDE = [['.', '-IDE'], [''], []] + + +#! Read +Read = [['read', '(', '', ')', ';']] +Ler = [['-IDE', '']] + + +#! Chamada funcção +#! = IDE '(' ')' +OpcionaisArgumentos = [[''], []] +ListaDeArgumentos = [['', '']] +OutrosArgumentos = [[',', ''], []] +Argumento = [['']] + +#! Ou também chamada de procedimento +#! = ';' + + +#! Expressao Aritmetica +ExpressaoAritmetica = [['', '']] +ValorOuMultiDiv = [['', '']] +MultiplicacaoOuDivisao = [['*', ''], ['/', ''], []] +ExpressaoComSomaSub = [['', ''], []] +Valor = [[''], ['(', '', ')']] +SimboloSomaSub = [['+'], ['-']] +Operavel = [['-IDE', ''], ['-NRO']] + + +#! Expressão logica +#! = '!' IDE +ExpressaoLogica = [['', '', '']] +ExpressaoOpcional = [['', '', ''], []] +op = [['&&'], ['||'] ] +#! negação ou variavel contendo valor booleano +neg = [[''], ['-IDE', ''], ['(', '', ')']] +OperadorLogico = [['&&',''], ['||', '']] +Negacao = [['!', '-IDE', '']] + + + +#! Expressaõ relacional +ExpressaoRelacional = [['', '', '', '']] +EXP_REL_Opcional = [['', ''], []] +OperandoRelacional = [[''], ['(', '', ')']] + +#! Se começar com negção então é logica +AlgumaDasExpressoes = [ + ['!', '-IDE', '', '', ''], + ['-IDE', '',' '], + ['-NRO', '', '',' '], + ['-CAC', '', '', ''], + ['', ''], +] + +#! expressao logica ou +ADE_com_IDE_VALOR = [['', ''], ['', '', '']] +ADE_com_Bool = [['', '', ''], []] +#! = IDE +#! | NRO +#! | CAC +#! | + + +#! Declaração de uma função +Funcao = [['function', '', '-IDE', '(', '', ')', '{', '}']] +#! Lista de parametros pode ser vazia +ListParametros = [['',' '], []] +#! Se mais de um parametro +OutroParametro = [[',', ''], []] +#! Definição do parametro +Parametro = [['', '-IDE']] + +#! Tipo +Tipo = [['int'], ['real'], ['boolean'], ['string'], ['-IDE']] +#! Declaração de um procedimento +Procedimento = [['procedure', '-IDE', '(', '', ')', '']] Mapped = Dict[str, ProductionRules] map: Mapped = { - '': comp, - '': Matriz, - '' : DimensoesDeAcesso, - '': Access, - '': end, - '': Indice, - '': REL, + '': EstruturaDoPrograma, '': Boolean, - '': SimboloSomaSub, - '': Operavel, + '' : OpcionalDimensoesDeAcesso, + '': DimensoesDeAcesso, + '': TamanhoDaDimensao, + '': DimensaoOpcional, + '': IndiceDeAcesso, + '': OpcionalStruct, + '': DeclaracaoStruct, + '': CorpoDaEstrutura, + '': EspecializacaoDeStruct, + '': VariaveisDaStruct, + '': OpcionaisVariaveisDaStruct, + '': DeclaracaoDeVariavelDeStruct, + '': ListaDeVariaveisStruct, + '': AtribuicaoMultiplaStruct, + '': OutrasAtribuicoesOpcionais, + '': AtribuicaoDeVariavelStruc, + '': ValorDeStribuicaoStruct, + '': Valor_Comecando_Com_IDE, + '': VALESSSSXPRESS, + '': OpcionaislVariaveisGlobais, + '': VariaveisGlobais, + '': DeclaracaoDentroDoBlocoDeVar, + '': OpcionaisConstantes, + '': Constantes, + '': DeclaracaoDentroDoBlocoDeConst, + '': AreaDeFuncoesEProcedimentos, + '': FuncaoOuProcedimento, + '': BlocoDeCodigo, + '': Conteudos, + '': ConteudoDeBloco, + '': VariacoesComIDEnoBloco, + '': While, + + + '': If, + '': ConteudoDoIf, + '': OpcionalElse, + '': DimensaoDaMatriz, + '': IndiceDeAcessoDaMatriz, + '': OpcionalIndice, + '': ValorDoIndice, '': Print, '': ConteudoDoPrint, - '': ConteudoDoPrintComIDE, + '': ConteudoDoPrintIDE, '': Read, '': Ler, - '': LerComIDE, - '': RetornoFuncao, - '': ParametrosOpcionais, - '': ListaDeParametros, - '': Parametro, - '': ParametroComIDE, - '': MultiplosParametros, - '': ChamadaFuncao, - '': Expressao, - '': ExpressaoMulti, + '': OpcionaisArgumentos, + '': ListaDeArgumentos, + '': OutrosArgumentos, + '': Argumento, + '': ExpressaoAritmetica, + '': ValorOuMultiDiv, + '': MultiplicacaoOuDivisao, + '': ExpressaoComSomaSub, + '': ExpressaoOpcional, + '': Valor, - '': ExpressaoMultiComValor, - '': ExpressaoComMult, - '': ExpressaoRelacional, - '': ValorRelacional, + '': SimboloSomaSub, + '': Operavel, '': ExpressaoLogica, - '': ExpressaoOpcional, + '': ExpressaoOpcional, '': op, '': neg, '': OperadorLogico, '': Negacao, - '': ValorRelacionalComIDE, - '': ValorRelacionalComParentesis, + '': ExpressaoRelacional, + '': EXP_REL_Opcional, + '': OperandoRelacional, + '': AlgumaDasExpressoes, + '': ADE_com_IDE_VALOR, + '': ADE_com_Bool, + '': Funcao, + '': ListParametros, + '': OutroParametro, + '': Parametro, + '': Tipo, + '': Procedimento, + '': HasAnotherFuncOrProc, }; diff --git a/src/main.py b/src/main.py index 4044f0b..41f5433 100644 --- a/src/main.py +++ b/src/main.py @@ -1,3 +1,5 @@ +from Prooduction import Production +from Sintatic.ProductionRules import AreaDeFuncoesEProcedimentos, EstruturaDoPrograma, OpcionaisConstantes, OpcionaislVariaveisGlobais, OpcionalStruct from TokenUtils.Token import Token from TokenUtils.orderTokens import isError, orderTokens from automata.findTokensInStringAutomata import findTokensInStringAutomata @@ -52,6 +54,10 @@ def lexico(): outputFile.writelines(tokenListPerFile[filename]) source_file.close(); outputFile.close(); + if (errorsNum == 0): + print("\n\n-------------- Sintatico -------------- \n\n"); + #tokensFound.append(Token('EOF', tokensFound[-1].line, 0, 0, 'EOF')); + Production(EstruturaDoPrograma, tokensFound); return; lexico(); From e76d6eb5cf60bc0e15322afb4267d449f126657d Mon Sep 17 00:00:00 2001 From: Daniel Santa Rosa Date: Wed, 30 Nov 2022 09:14:12 -0300 Subject: [PATCH 2/4] =?UTF-8?q?=F0=9F=AA=B2=20Fix=20wrong=20productions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Sintatic/ProductionRules.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Sintatic/ProductionRules.py b/src/Sintatic/ProductionRules.py index 95d93d9..0a488e8 100644 --- a/src/Sintatic/ProductionRules.py +++ b/src/Sintatic/ProductionRules.py @@ -173,7 +173,7 @@ #! Se começar com negção então é logica AlgumaDasExpressoes = [ ['!', '-IDE', '', '', ''], - ['-IDE', '',' '], + ['-IDE', '', ''], ['-NRO', '', '',' '], ['-CAC', '', '', ''], ['', ''], @@ -189,9 +189,9 @@ #! Declaração de uma função -Funcao = [['function', '', '-IDE', '(', '', ')', '{', '}']] +Funcao = [['function', '', '-IDE', '(', '', ')', '']] #! Lista de parametros pode ser vazia -ListParametros = [['',' '], []] +ListParametros = [['', ''], []] #! Se mais de um parametro OutroParametro = [[',', ''], []] #! Definição do parametro @@ -285,4 +285,5 @@ '': Tipo, '': Procedimento, '': HasAnotherFuncOrProc, + '': REL, }; From adc1610f05bdfbfbc6c75caa4d3457b492b341d4 Mon Sep 17 00:00:00 2001 From: Daniel Santa Rosa Date: Wed, 30 Nov 2022 09:16:23 -0300 Subject: [PATCH 3/4] =?UTF-8?q?=F0=9F=9A=A7=20Improve=20canProductionBeEmp?= =?UTF-8?q?ty=20reliability?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Prooduction.py | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/Prooduction.py b/src/Prooduction.py index bcbb062..e67db62 100644 --- a/src/Prooduction.py +++ b/src/Prooduction.py @@ -314,15 +314,9 @@ def canRuleBeEmpty(rule: str): return False; def canProductionBeEmpty(production: ProductionRules): - res = False; - for rule in production: - if (len(rule) < 1): - res = True; - continue; - for r in rule: - if (canRuleBeEmpty(r)): - res = True; - return res; + for conjunto in getFists(production): + if "" in conjunto: + return True def matchSemiterminal(received: str, target: str): sanitazed = target[1:]; From dc8c19a3c7b8cedb7cc3ca0453c469cb1e2e026b Mon Sep 17 00:00:00 2001 From: Daniel Santa Rosa Date: Wed, 30 Nov 2022 09:17:23 -0300 Subject: [PATCH 4/4] =?UTF-8?q?=F0=9F=AA=B2=20Fix=20getFists=20not=20worki?= =?UTF-8?q?ng=20properly=20when=20first=20symbol=20of=20a=20production=20c?= =?UTF-8?q?an=20be=20empty?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Prooduction.py | 28 ++++++++++++---------------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/src/Prooduction.py b/src/Prooduction.py index e67db62..ad9009f 100644 --- a/src/Prooduction.py +++ b/src/Prooduction.py @@ -336,23 +336,19 @@ def getFists(productionRules: ProductionRules): if (len(rule) == 0): # Se for uma produção vazia conjuntoFisrt.append([""]); # coloca uma string varia no conjunto first elif (isNonTerminal(rule[0])): # se o primerio elemento for um não terminal - elemProduction = map.get(rule[0]); # Busca a produção desse não terminal - if (elemProduction == None): # Se a procução não existe - raise Exception("Produção: ", rule[0], "inexistente"); # Há um erro l: List[str] = []; - for lst in getFists(elemProduction): # Encontra o conjunto fist da produção - l.extend(lst); # Transforma em uma unica lista de string - conjuntoFisrt.append(l); # Adiciona lista ao conjuto da prudção atual - #crbempty = canRuleBeEmpty(rule[0]); - #crbindex = 0 - #if (crbempty and len(rule) > 1): - # elemProduction = map.get(rule[1]); - # if (elemProduction == None): # Se a procução não existe - # raise Exception("Produção: ", rule[0], "inexistente"); # Há um erro - # r: List[str] = []; - # for st in getFists(elemProduction): # Encontra o conjunto fist da produção - # r.extend(st); # Transforma em uma unica lista de string - # conjuntoFisrt.append(r); + nonEmpty = False; + for tokentype in rule: + if (nonEmpty): + continue; + elemProduction = map.get(tokentype); # Busca a produção desse não terminal + if (elemProduction == None): # Se a procução não existe + raise Exception("Produção: ", tokentype, "inexistente"); # Há um erro + for lst in getFists(elemProduction): # Encontra o conjunto fist da produção + l.extend(lst); # Transforma em uma unica lista de string + if (not canRuleBeEmpty(tokentype)): + nonEmpty = True; + conjuntoFisrt.append(l); # Adiciona lista ao conjuto da prudção atual else: # Se form um terminal conjuntoFisrt.append([rule[0]]); return conjuntoFisrt; # Retorna o conjunto encontrado