Skip to content

Commit

Permalink
merge: Merge pull request #20 from natanfeitosa/feat/adiciona-lista
Browse files Browse the repository at this point in the history
feat: Adiciona a lista e alguns métodos
  • Loading branch information
natanfeitosa authored Dec 28, 2023
2 parents d8c1cfc + 31d69c2 commit 224cda1
Show file tree
Hide file tree
Showing 9 changed files with 196 additions and 2 deletions.
2 changes: 2 additions & 0 deletions gramatica/PortuscriptLexer.g4
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ NAO_BIT_A_BIT: '~';
DESLOC_ESQUERDA: '<<';
DESLOC_DIREITA: '>>';
PONTO: '.';
ABRE_COLCHETES: '[';
FECHA_COLCHETES: ']';

ID: (LETRAS | '_') (LETRAS | DIGITOS)*;

Expand Down
4 changes: 3 additions & 1 deletion gramatica/PortuscriptParser.g4
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,6 @@ argumento: expressao;

atomo: ID | 'Verdadeiro' | 'Falso' | 'Nulo' | TEXTO+ | DIGITOS | tupla;

tupla: ABRE_CHAVES expressao VIRGULA (expressao VIRGULA?)* FECHA_CHAVES;
tupla: ABRE_CHAVES expressao VIRGULA (expressao VIRGULA?)* FECHA_CHAVES;

lista: ABRE_COLCHETES expressao (VIRGULA expressao)* FECHA_COLCHETES;
6 changes: 6 additions & 0 deletions lexer/lexer.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,12 @@ func (l *Lexer) ProximoToken() Token {
case "}":
l.avancar()
return Token{TokenFechaChaves, "}"}
case "[":
l.avancar()
return Token{TokenAbreColchetes, "["}
case "]":
l.avancar()
return Token{TokenFechaColchetes, "]"}
case "|":
l.avancar()
return Token{TokenBitABitOu, "|"}
Expand Down
2 changes: 2 additions & 0 deletions lexer/tokens.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ const (
TokenVirgula // ,
TokenAbreChaves // {
TokenFechaChaves // }
TokenAbreColchetes // {
TokenFechaColchetes // }
TokenDoisPontos // :

// Reatribuicao
Expand Down
5 changes: 5 additions & 0 deletions parser/ast_nodes.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,10 @@ type TuplaLiteral struct {
Elementos []BaseNode
}

type ListaLiteral struct {
Elementos []BaseNode
}

func (*Programa) isExpr() {}
func (*DeclVar) isExpr() {}
func (*Reatribuicao) isExpr() {}
Expand All @@ -136,3 +140,4 @@ func (*BlocoPara) isExpr() {}
func (*PareNode) isExpr() {}
func (*ContinueNode) isExpr() {}
func (*TuplaLiteral) isExpr() {}
func (*ListaLiteral) isExpr() {}
16 changes: 16 additions & 0 deletions parser/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -756,6 +756,22 @@ func (p *Parser) parseAtomo() (BaseNode, error) {
literal.Elementos = append(literal.Elementos, exp)
}

p.avancar()
return literal, nil
case lexer.TokenAbreColchetes:
literal := &ListaLiteral{}

for p.token.Tipo != lexer.TokenFechaColchetes {
p.avancar()
exp, err := p.parseExpressao()

if err != nil {
return nil, err
}

literal.Elementos = append(literal.Elementos, exp)
}

p.avancar()
return literal, nil
}
Expand Down
2 changes: 2 additions & 0 deletions ptst/erros.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ var (
TipagemErro = TipoErro.NewTipo("TipagemErro", "Tipo de argumento inapropriado.")
NomeErro = TipoErro.NewTipo("NomeErro", "Erro de nome que não pode ser achado.")
ImportacaoErro = TipoErro.NewTipo("ImportacaoErro", "Não é possível encontrar o módulo ou símbolo nele")
ValorErro = TipoErro.NewTipo("ValorErro", "O valor é inapropriádo ou sua ocorrencia não existe")
IndiceErro = TipoErro.NewTipo("IndiceErro", "O indice está fora do range aceito")
FimIteracao = TipoErro.NewTipo("FimIteracao", "Sinaliza o fim da iteração quando `objeto.__proximo__() não retorna mais nada")

// Apenas para fins de controle, não são necessariamente erros
Expand Down
18 changes: 17 additions & 1 deletion ptst/interpretador.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ func (i *Interpretador) visite(node parser.BaseNode) (Objeto, error) {
return i.visiteDecimalLiteral(node.(*parser.DecimalLiteral))
case *parser.TuplaLiteral:
return i.visiteTuplaLiteral(node.(*parser.TuplaLiteral))
case *parser.ListaLiteral:
return i.visiteListaLiteral(node.(*parser.ListaLiteral))
case *parser.OpBinaria:
return i.visiteOpBinaria(node.(*parser.OpBinaria))
case *parser.Identificador:
Expand Down Expand Up @@ -193,6 +195,20 @@ func (i *Interpretador) visiteTuplaLiteral(node *parser.TuplaLiteral) (Objeto, e
return tupla, nil
}

func (i *Interpretador) visiteListaLiteral(node *parser.ListaLiteral) (Objeto, error) {
lista := &Lista{}

for _, elemento := range node.Elementos {
item, err := i.visite(elemento)
if err != nil {
return nil, err
}

lista.Adiciona(item)
}
return lista, nil
}

func (i *Interpretador) visiteOpBinaria(node *parser.OpBinaria) (Objeto, error) {
esquerda, err := i.visite(node.Esq)

Expand Down Expand Up @@ -402,7 +418,7 @@ func (i *Interpretador) visiteBlocoPara(node *parser.BlocoPara) (Objeto, error)

return nil, err
}
}
}
}

func (i *Interpretador) visitePareNode(node *parser.PareNode) (Objeto, error) {
Expand Down
143 changes: 143 additions & 0 deletions ptst/lista.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
package ptst

type Lista struct {
Itens Tupla
}

var TipoLista = TipoObjeto.NewTipo(
"Lista",
"Lista(obj) -> Lista",
)

func (l *Lista) Tipo() *Tipo {
return TipoLista
}

func (l *Lista) O__iter__() (Objeto, error) {
return NewIterador(l.Itens)
}

func (l *Lista) O__texto__() (Objeto, error) {
return l.Itens.GRepr("[", "]")
}

func (l *Lista) O__tamanho__() (Objeto, error) {
return l.Itens.O__tamanho__()
}

var _ I__iter__ = (*Lista)(nil)
var _ I__texto__ = (*Lista)(nil)
var _ I__tamanho__ = (*Lista)(nil)

func (l *Lista) Adiciona(item Objeto) (Objeto, error) {
l.Itens = append(l.Itens, item)
return nil, nil
}

func (l *Lista) Indice(obj Objeto) (Objeto, error) {
for indice, item := range l.Itens {
if ok, _ := Igual(item, obj); ok.(Booleano) {
return Inteiro(indice), nil
}
}

objTexto, err := NewTexto(obj)
if err != nil {
return nil, err
}

return nil, NewErroF(ValorErro, "O item '%s' não está na lista", objTexto)
}

func (l *Lista) Pop(indice Inteiro) (Objeto, error) {
tamanho, err := l.O__tamanho__()
if err != nil {
return nil, err
}

if indice > tamanho.(Inteiro) || indice < 0 {
return nil, NewErroF(IndiceErro, "O range é de %d indice(s), %d está fora dele", tamanho.(Inteiro), indice)
}

var removido Objeto
var novaTupla Tupla

for idx, item := range l.Itens {
if idx == int(indice) {
removido = item
continue
}

novaTupla = append(novaTupla, item)
}

l.Itens = novaTupla
return removido, nil
}

func init() {
TipoLista.Mapa["adiciona"] = NewMetodoOuPanic("adiciona", func(inst Objeto, args Tupla) (Objeto, error) {
if len(args) < 1 {
return nil, NewErroF(TipagemErro, "O método adiciona() esperava receber no mínimo 1 argumento, mas recebeu um total de %v", len(args))
}

inst.(*Lista).Adiciona(args[0])
return nil, nil
}, "O método recebe um objeto e adiciona ao fim da lista")

// TipoLista.Mapa["insere"] = NewMetodoOuPanic("insere", func(inst Objeto, args Tupla) (Objeto, error) {
// if len(args) < 2 {
// return nil, NewErroF(TipagemErro, "O método insere() esperava receber no mínimo 2 argumentos, mas recebeu um total de %v", len(args))
// }

// indice, objeto := args[0], args[1]

// return nil, nil
// }, "")

TipoLista.Mapa["extende"] = NewMetodoOuPanic("extende", func(inst Objeto, args Tupla) (Objeto, error) {
if len(args) < 1 {
return nil, NewErroF(TipagemErro, "O método extende() esperava receber no mínimo 1 argumento, mas recebeu um total de %v", len(args))
}

inst.(*Lista).Itens = append(inst.(*Lista).Itens, (args[0].(Tupla))...)
return nil, nil
}, "Adiciona os elementos da lista recebida ao fim da lista atual")

TipoLista.Mapa["remove"] = NewMetodoOuPanic("remove", func(inst Objeto, args Tupla) (Objeto, error) {
if len(args) < 1 {
return nil, NewErroF(TipagemErro, "O método remove() esperava receber no mínimo 1 argumento, mas recebeu um total de %v", len(args))
}

instancia := inst.(*Lista)
idx, err := instancia.Indice(args[0])
if err != nil {
return nil, err
}

return instancia.Pop(idx.(Inteiro))
}, "Remove um elemento da lista e o retorna, se existir")

TipoLista.Mapa["pop"] = NewMetodoOuPanic("pop", func(inst Objeto, args Tupla) (Objeto, error) {
idx := Inteiro(0)

if len(args) == 1 {
idx = args[0].(Inteiro)
}

return inst.(*Lista).Pop(idx)
}, "Remove um item da lista com base no seu índice")

TipoLista.Mapa["indice"] = NewMetodoOuPanic("indice", func(inst Objeto, args Tupla) (Objeto, error) {
if len(args) < 1 {
return nil, NewErroF(TipagemErro, "O método indice() esperava receber no mínimo 1 argumento, mas recebeu um total de %v", len(args))
}

return inst.(*Lista).Indice(args[0])
}, "Retorna o índice de um elemento se ele existir na lista")

TipoLista.Mapa["limpa"] = NewMetodoOuPanic("limpa", func(inst Objeto) (Objeto, error) {
inst.(*Lista).Itens = Tupla(nil)
return nil, nil
}, "Limpa completamente a lista")
}

0 comments on commit 224cda1

Please sign in to comment.