
|
========== RPNLib 0.1 ========== O presente documento servirá como orientação para a construção da RPNLib, uma biblioteca de classes que será utilizada para a construção da RPNCalc. Veja o anúncio completo do projeto em: http://br.groups.yahoo.com/group/objectpascal/message/43 Os detalhes do projeto serão discutidos na lista: http://br.groups.yahoo.com/group/rpncalc-dev/ Para contato ou em caso de dúvidas sobre o projeto: rpncalc-dev-owner@yahoogrupos.com.br Projeto criado e administrado por: João Morais http://www.joaomorais.com.br/ ====== RPNLib ====== Unidade principal da RPNLib Tentarei explicar a sintaxe e a utilidade de cada uma das classes e tipos de dados que serão criados para a RPNLib. A explicação será dada da forma mais suscinta possível, apenas como orientação dos trabalhos que vêm pela frente. ERPNLib = class(Exception); ------- Classe antecessora de todas as classes de exceções (erros) da RPNLib. ESintaxe = class(ERPNLib); -------- Classe antecessora de todas as classes de erros de sintaxe. Ocorre na entrada dos dados à Biblioteca (geralmente, entradas efetuadas pelo usuário) ESintaxeExpressao = class(ESintaxe); ESintaxeNumero = class(ESintaxe); ESintaxeString = class(ESintaxe); ESintaxeMatriz = class(ESintaxe); ESintaxeLista = class(ESintaxe); ESintaxeBinario = class(ESintaxe); EParametro = class(ERPNLib); ---------- Número de parâmetros é insuficiente EFormula = class(ERPNLib); -------- Fórmula com sintaxe incorreta EIdentificador = class(ERPNLib); -------------- Identificador duplicado (ao instalar função interna ou externa) ou identificador com caracteres inválidos :: Está sujeito a criação de classes herdeiras EEstatistica = class(ERPNLib); ------------ Erro nos módulos de cálculo estatístico :: Está sujeito a criação de classes herdeiras O grupo "TItemData", listado abaixo, identifica um tipo de dado (nativo ou implementado, tal como TParser) para cada tipo de dado possível na nossa Pilha[2]. TItemDataFormula = TParser; ---------------- Fórmula matemática - inicia sempre com um ' (apóstrofe) TItemDataNumero = TParserFloat; --------------- Número decimal de ponto flutuante TItemDataString = string; --------------- String - inicia sempre com uma " (aspas) TItemDataMatriz = TStringList; --------------- Matriz uni ou bidimensional - inicia sempre com um [ (abre colchete) Cada item do TStringList aponta para um Objeto TItemPilha TItemDataLista = TStringList; -------------- Lista - conjunto de qualquer outro tipo de dado, inclusive outra(s) lista(s) Inicia sempre com um { (abre-chave) TItemDataBinario = record ---------------- Número inteiro usado para transformação de base numérica - a base é identificada com uma das letras 'b', 'o', 'd', 'h' ao final do número - inicia sempre com um # (sustenido, cancela, cerquinha, jogo da velha, conforme o gosto :) ) TTipoDado = ( tdExpressao, tdNumero, tdString, tdMatriz, tdLista, tdBinario, tdFuncao, tdNulo, tdErro); --------- Identifica o tipo de dado. Necessário para criar a instância[1] correta na Pilha[2] de dados. TFormatoAngulo = ( faGraus, faGrados, faRadianos); -------------- Utilizado para identificar o tipo de ângulo atual nos cálculos trigonométricos TFNApresentacao = ( fnPadrao, fnFixo, fnCientifico, fnEngenharia); --------------- Identifica o formato de apresentação dos números decimais com ponto flutuante O detalhamento de cada formato está fora do escopo deste documento TFormatoNumero = class(TObject) -------------- Classe com instância[1] única dentro da RPNLib. Utilizada para controlar o formato numérico atual, aonde podemos destacar tipo de ângulo, formato, número de casas decimais, ponto ou vírgula no decimal, entre outros. TItemPilha = class(TObject) ---------- Classe antecessora de todos os tipos de dados possíveis na Pilha[2] de Dados. Possui métodos virtuais[3] de formatação, tal como AsString, que retorna o dado atual no formato string para apresentação no visor. TItemFormula = class(TItemPilha) TItemNumero = class(TItemPilha) TItemString = class(TItemPilha) TItemMatriz = class(TItemPilha) TItemLista = class(TItemPilha) TItemBinario = class(TItemPilha) ------------ Cada classe acima controla o tipo de dado a que foi designada, herdando e implementando os métodos virtuais[3] de TItemPilha. TPilha = class(TObject) ------ Classe de instância[1] única dentro da RPNLib. Possui uma lista com todos os ItemPilha criados, e diversos métodos para controle desses dados, aonde podemos destacar: incluir e eliminar itens, interpretação da entrada do usuário e consequente empilhamento dos dados, entre outros. TBibl = class(TObject) ----- Classe de instância[1] única dentro da RPNLib. Possui todas as funções internas (implementadas em código) e externas (implementadas como fórmulas - TParser), e todas as variáveis atualmente disponíveis. Possui diversos métodos para controle dessas funções e variáveis, tal como instalar função, instalar variável, entre outros. =============== Unidade RPNPars =============== Unidade responsálvel pelo parsing[4] de fórmulas matemáticas. O Parsing da RPNLib (RPNPars) merece um tratamento especial e diferenciado devido a sua complexidade. Aqui serão compiladas, executadas e gerenciadas todas as fórmulas utilizadas na RPNLib. ERPNParsing = class(ERPNLib); ----------- Classe antecessora de todas as exceções ocorridas durante o parsing[4] de uma fórmula EParsingErroSintaxe = class(ERPNParsing); EParsingBrancos = class(ERPNParsing); EParsingComplexa = class(ERPNParsing); EParsingAninhamentos = class(ERPNParsing); EParsingParenteses = class(ERPNParsing); EParsingNomeImproprio = class(ERPNParsing); EParsingErroInterno = class(ERPNParsing); ------------------- As classes descritas acima foram trazidas da TParser, um componente avaliador de fórmulas matemáticas, que pode ser encontrado em http://www.joaomorais.com.br/pascal/download.php?cat=101 Pretendo reescrever toda a rotina, primeiro para termos uma solução 100% própria, e também para fins de estudo (não estamos construindo essa Lib atoa, correto?) Assim sendo, estas classes descritas acima estão altamente sujeitas a alterações. TToken = ( variab, constant, minus, sum, diff, prod, divis, modulo, IntDiv, integerpower, realpower, square, third, fourth, FuncOneVar, FuncTwoVar); ------ Utilizado internamente pela rotina para identificar o token atual :: Está sujeito a pequenas alterações TParserFloat = extended; ------------ Todos os números decimais utilizados para os cálculos internos e para o resultado serão tratados como TParserFloat. A alteração indiscriminada do tipo definido aqui pode causar alguns estragos devido a erros de arredondamento. PParserFloat = ^TParserFloat; ------------ Ponteiro ao tipo TParserFloat (prefiro não entrar em detalhes ainda ;-) ) POperation = ^TOperation; ---------- Ponteiro à TOperation. Esta estrutura é explicada em seguida. TMathProcedure = procedure(AnOp: POperation); -------------- Toda função interna é uma procedure controlada pela classe TBibl. Este tipo é utilizado para criar um Typecast[5] para executar determinada função interna. TParser = class(TObject) ------- Classe responsável pela manutenção de uma fórmula. Possui a sua versão em string e um ponteiro ao primeiro token (TOperation) de uma sequência utilizada para executá-la. TFuncao = class(TObject) ------- Classe antecessora de todas as funções matemáticas da Biblioteca (TBibl) da RPNLib. TFuncaoExterna = class(TFuncao) -------------- Função que utiliza um TParser para alcançar um resultado. TFuncaoInterna = class(TFuncao) -------------- Função que utiliza uma procedure em determinado endereço de memória para alcançar um resultado. TOperation = record ---------- Estrutura de uma lista encadeada (por ponteiros) para execução de uma função externa. Esta lista é criada pelo algoritmo de Parsing[4] de fórmulas matemáticas. ========= GLOSSÁRIO ========= [1] Instância É um objeto criado na memória. Toda classe precisa 'instanciar' um objeto (criar um objeto) para que seja possível trabalhar com ele. Cada instância é totalmente independente de outra, mesmo que seja da mesma classe. Elas apenas compartilham a mesma estrutura e regras internas. [2] Pilha Área de armazenamento de dados LIFO (Last In, First Out - o último que entra é o primeiro que sai). A Pilha da RPNLib armazena objetos da classe TItemPilha, ou seja, números, strings, matrizes, fórmulas, etc. [3] Método Virtual É um método sujeito a implementação por uma classe herdeira. É muito útil para a construção de uma rotina genérica que possuirá diversas implementações diferentes. O conceito e a utilidade de métodos virtuais ficarão mais claras com o decorrer do acompanhamento deste projeto. [4] Parsing É um equivalente a 'interpretação', 'compilação', 'codificação'. O Parsing de fórmulas em formato string, tal como 'SIN(X)', é a sua transformação em uma lista encadeada (por ponteiros) de tokens que serão responsáveis pelas etapas do cálculo. [5] Typecast Método utilizado para identificação do tipo real de um objeto. Em português claro, o Typecast é utilizado para informar ao compilador com qual tipo de dado ele está trabalhando. Neste projeto é utilizado em duas situações: :: Typecast de classes: uma variável de uma classe antecessora pode guardar um objeto de uma classe herdeira. Ex.: uma variável do tipo TItemPilha pode armazenar um objeto da classe TItemFormula. Se tivermos certeza que o objeto seja deste tipo, usamos TItemFormula(VarItemPilha).Formula para capturar a propriedade Formula do objeto. Devemos usar Typecast porque TItemPilha (o tipo de VarItemPilha) não possui uma propriedade Formula. (ih... piorou, né? :) ) :: Typecast de procedure: o endereço das procedures das funções internas são armazenadas em uma variável TObject. Para que possamos executar a procedure, devemos fazer um Typecast da variável, desta forma: TMathProcedure(VarObject)(Parâmetro); |