| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369 |
- {**********************************************************************************
- uPreBasicos
- Unidad con las definiciones y funciones básicas para el tratamiento de los errores
- y contextos del pre-procesador PreSQL.
- Un contexto es una abstracción de datos materializada en una estructura que
- permite almacenar texto, generalmente destinado a ser preprocesado por el PreSQL.
- En el contexto se tiende considera siempre, el salto de línea como si fuera
- un sólo caracter porque se lee con una sola llamada a las funciones VerCar() y
- CogCar().
- En el tratamiento del contexto, se asume que todas las líneas, excepto la
- última, tienen un caracter FIN_LIN como delimitador final.
- Esta unidad se ha adaptado del código Visual Basic del PreSQL 1.3.
- Adaptado Por Tito Hinostroza 23/08/2013
- ***********************************************************************************
- }
- unit uPreBasicos; {$mode objfpc}{$H+}
- interface
- uses Classes, SysUtils, Fgl;
- Const
- FIN_LIN = #13; //Fin de línea
- FIN_CON = #0; //Fin de contexto
- //Tipos de contextos
- TC_ARC = 0 ; //contexto de tipo archivo
- TC_TXT = 1 ; //contexto de tipo texto
- Type
- //Tipo de operando
- TPTipOper = (TIP_DES, //tipo desconocido
- TIP_NUM, //tipo número
- TIP_CAD); //tipo cadena
- //Categoría para clasificar a los operandos
- TPCatOper = (COP_VACIO, //Operando nulo
- // COP_VARPUNTO, //Variable Punto
- COP_DEFINIC, //es una variable (definición)
- COP_FUNCION, //Es una función
- COP_CONST, //Es una constante
- COP_EXPRESION); //Es resultado de una expresión
- //Tipo expresión. Se usa para manejo de evaluación aritmética.
- { Texpre }
- Texpre = object //Tipo expresión
- txt: String; //Texto de la expresión
- tip: TPTipOper; //Tipo de dato que devuelve la expresión
- cat: TPCatOper; //Categoría de expresión
- // uop: String ; //último operador que se ejecutó de la expresión
- private
- fTxt: String; //Valor numérico de la expresión
- fNum: Single; //Valor numérico de la expresión
- procedure FijTxt(txt0: string);
- function LeeTxt: string;
- procedure FijNum(n0: single);
- function LeeNum: single;
- function LeeFec: TDateTime;
- public
- def : pointer; //referencia a la definición (en caso de que lo sea)
- property valTxt: string read LeeTxt write FijTxt;
- property valNum: single read LeeNum write FijNum;
- property valFec: TDateTime read LeeFec;
- End;
- //ID para categorizar a los tokens
- TtkTokenKind = (tkComment, tkIdentifier, tkKey, tkNull, tkNumber, tkSpace, tkString,
- tkUnknown, tkMacro);
- TContexto = class;
- {Posición dentro de un contexto. A diferecnia de "Tcontexto", es un registro y siempre
- guardará una copia permanente. Además no guarda el texto del contexto}
- TPosCont = record
- arc : String ; //Nombre de archivo
- fil : LongInt ; //Fila
- col : Integer ; //Columna
- nlin : LongInt ; //Número de líneas
- fCon : TContexto; //Referencia al Contexto
- End;
- { TPError }
- {Define al objeto PError, el que se usa para tratar los errores del preprocesador. Solo se
- espera que haya uno de estos objetos, por eso se ha declarado como OBJECT}
- TPError = object
- private
- numER : Integer; //codigo de error
- arcER : String; //nombre de archivo que origino el error
- fil : integer; //número de línea del error
- col : integer; //número de columna del error
- public
- cadError : String; //cadena de error
- NombPrograma: string; //Usado para poner en el encabezado del mensaje
- procedure IniError;
- procedure GenError(num: Integer; msje : String; archivo: String = ''; nlin: integer = 0);
- procedure GenError(msje: String; posCon: TPosCont);
- function GenTxtError: string;
- // procedure MosError;
- function ArcError: string;
- function nLinError: longint;
- Function nColError: longint;
- function HayError: boolean;
- end;
- { TContexto }
- {Estructura que define a un objeto contexto. Se usa tanto para leer la entrada como para
- escribir en la salida.}
- TContexto = class
- tip : integer;
- arc : String; //nombre de archivo
- fil : LongInt; //fila actual
- col : Integer; //columna actual
- nlin : LongInt; //Número de líneas del Contexto
- lin : TStringList; {Líneas de texto. Se almacena en TStringList porque es rápida la
- carga desde un archivo y porque es compatible con el almacenamiento
- en el Control Editor.}
- constructor Create;
- destructor Destroy; override;
- //Métodos de lectura
- Function IniCont:Boolean;
- Function FinCont:Boolean;
- Function VerCar:Char;
- Function CogCar:Char;
- Function VerCarAnt: Char;
- Function VerCarSig: Char;
- Function CapBlancos:Boolean;
- //Métodos de escritura
- procedure CurPosIni;
- procedure CurPosFin;
- procedure PonSalto; //Agrega Salto de línea
- procedure SacLinea; //quita la última línea
- procedure PonCar(c: char); //Agrega caracter
- procedure PonCad(s: String); //Agrega cadena
- procedure SacCar; //Quita un caracter
- //Métodos de llenado/lectura
- function LeeCad: string; //Lee el contenido del contexto
- procedure FijCad(cad : string); //Fija el contenido del contexto con cadena
- procedure FijArc(arc0: string); //Fija el contenido del contexto con archivo
- End;
- //Define una lista de Contextos
- TListaCont = specialize TFPGObjectList<TContexto>;
- { TPPro }
- TPPro = object
- private
- Function LeePosContAct: TPosCont;
- procedure FijPosContAct(pc:TPosCont);
- function LeeCadSal: String;
- procedure FijCadSal(cad: string);
- public
- constructor Create;
- destructor Destroy; //override;
- procedure Iniciar; //Prepara la secuencia de preprocesamiento
- //rutinas de entrada
- procedure NuevoContexEntTxt(txt: string; arc0: String);
- procedure NuevoContexEntArc(arc0: String);
- procedure QuitaContexEnt; //quita contexto de entrada actual
- //rutinas basicas de lectura
- Function IniCont:Boolean;
- Function FinCont:Boolean;
- Function VerCar: Char;
- Function VerCarN(numcar:Integer): String;
- Function CogCar:Char;
- // Function VerCarAnt:Char;
- Function CapBlancos:Boolean;
- function Capturar(cap: String): Boolean;
- property PosAct: TPosCont read LeePosContAct write FijPosContAct;
- //rutinas avanzadas de lectura
- Function VerIdentificador:String;
- Function VerIdentifM:String; //VE identificador en mayúscula
- Function VerPalabra():String;
- Function VerElemento():String;
- Function CogIdentificador:String;
- function CogIdentificador(var ide, ideM: string; var uc: char): boolean;
- function CogIdentificador(var ideM: string): boolean;
- Function cogPalabra():String;
- Function CogElemento():String;
- Function CogNumero:Single;
- Function CogNumero(var n:Single):boolean;
- Function CogCadena:String;
- Function CogCadena(var s: string):boolean;
- Function coger_ruta():String;
- function TipoSigToken: TtkTokenKind; //Devuelve el tipo del siguiente token
- Function VerSiEsComentario():Boolean;
- Function CogerHastaFinLinea():String;
- Function CogerHastaComent():String;
- Function VerHastaFinLinea():String;
- function CogerComent: boolean;
- function CogerLista(lista: TStringList; delims: string): string;
- function cogOperador: String; //coge operador
- function jerOp(oper: String): Integer; //jerarquía de operador
- function Evaluar(Op1: Texpre; opr: String; Op2: Texpre): Texpre;
- //rutinas de salida
- procedure NuevoContexSal; //Crea nuevo contexto de salida actual
- procedure QuitaContexSal; //quita contexto de salida actual
- procedure PonCar(c: char); //Agrega caracter
- procedure Escribe(palabra: string);
- procedure EscribeSalto;
- procedure SacCar;
- procedure GenArchivo(ArcSal0: string); //Genera archivo de salida
- function TextSalida: string; //Devuelve el texto preprocesado
- property cadenaSal: String read LeeCadSal write FijCadSal; //Cadena se salida del contexto actual
- private
- ConsE: TListaCont; //Lista de contextos de entrada
- ConsS: TListaCont; //Lista de contextos de salida
- //Variables del Contexto actual
- cEnt : TContexto; //referencia al contexto de entrada actual
- cSal : TContexto; //referencia al contexto de salida actual
- end;
- var
- PErr : TPError; //Objeto de Error
- PPro : TPPro; //Objeto Pre-Procesador
- ////////////////////////////////////////////////////////////////////////////////////////////
- implementation
- //caracteres iniciales válidos para idntificador
- { TODO : Debe desaparecer porque debe poder identificarse el token en la función "TipoSiguienteToken" }
- const CAR_INI_IDENT = ['$','a'..'z','A'..'Z','_']; //No se incluye 'ñ'
- //caracteres válidos para idntificador
- const CAR_IDENT = ['$','a'..'z','A'..'Z','_','0'..'9']; //No se incluye 'ñ'
- //caracteres válidos para idntificador
- const CAR_VAL_PALABRA = ['$','a'..'z','A'..'Z','_','0'..'9','.']; //¿'ñ'?
- { Texpre }
- procedure Texpre.FijTxt(txt0: string);
- //Fija valor de texto de un operando
- begin
- tip := TIP_CAD; //se fija como cadeana, de otra forma no podría recibir este valor
- fTxt := txt0;
- end;
- function Texpre.LeeTxt: string;
- //Lee la variable como texto
- begin
- if tip = TIP_CAD then //si ya es texto, la lectura es directa
- Result := ftxt
- else if tip = TIP_NUM then //Si es numérico, se hace una transformación
- //siempre se podrá transformar
- Result := FloatToStr(fNum) //pero no deja de ser numérico
- else
- Result := '';
- end;
- procedure Texpre.FijNum(n0: single);
- begin
- tip := TIP_NUM; //se fija como número, de otra forma no podría recibir este valor
- fNum := n0;
- end;
- function Texpre.LeeNum: single;
- begin
- if tip = TIP_CAD then begin //si es texto, se hace una transformación
- //puede que no se pueda transformar
- if not TryStrToFloat(trim(ftxt), Result) then //pero no deja de ser texto
- PErr.GenError( 1, 'Número inválido.')
- end else if tip = TIP_NUM then //Si ya es numérico, la lectura es directa
- Result := fNum
- else
- Result := 0;
- end;
- function Texpre.LeeFec: TDateTime;
- begin
- if tip = TIP_CAD then begin //si es texto, se hace una transformación
- //puede que no se pueda transformar
- ftxt := trim(ftxt);
- if not TryStrToDateTime(ftxt, Result) then //pero no deja de ser texto
- PErr.GenError( 1, 'Fecha inválida.')
- end else if tip = TIP_NUM then //Si ya es numérico, la lectura es directa
- Result := fNum
- else
- Result := 0;
- end;
- { TPPro }
- constructor TPPro.Create;
- begin
- //Crea lista de Contextos
- ConsE := TListaCont.Create(true); //crea contenedor de Contextos, con control de objetos.
- cEnt := nil;
- ConsS := TListaCont.Create(true); //crea contenedor de Contextos con control.
- cSal := nil;
- end;
- destructor TPPro.Destroy;
- begin
- //Limpia lista de Contextos
- ConsE.Free;
- //Limpia Contextos de salida
- ConsS.Free;
- end;
- procedure TPPro.Iniciar;
- //Inicia la maquinaria de manejo de Contextos
- begin
- ConsE.Clear; //elimina todos los Contextos de entrada
- ConsS.Clear; //elimina
- end;
- procedure TPPro.NuevoContexEntTxt(txt: string; arc0: String);
- //Crea un Contexto a partir de una cadena.
- //Fija el Contexto Actual "cEnt" como el Contexto creado.
- begin
- cEnt := TContexto.Create; //crea Contexto
- ConsE.Add(cEnt); //Registra Contexto
- cEnt.FijCad(txt); //inicia con texto
- cEnt.arc := arc0; {Se guarda el nombre del archivo actual, solo para poder procesar
- las funciones $NOM_ACTUAL y $DIR_ACTUAL}
- cEnt.CurPosIni; //posiciona al inicio
- end;
- procedure TPPro.NuevoContexEntArc(arc0: String);
- //Crea un Contexto a partir de un archivo. Devuelve el manejador del Contexto
- //Fija el Contexto Actual "cEnt" como el Contexto creado.
- begin
- If not FileExists(arc0) Then begin //ve si existe
- PErr.GenError( 1, 'No se encuentra archivo: ' + arc0);
- Exit;
- end;
- cEnt := TContexto.Create; //crea Contexto
- ConsE.Add(cEnt); //Registra Contexto
- cEnt.FijArc(arc0); //inicia con archivo
- cEnt.CurPosIni; //posiciona al inicio
- end;
- procedure TPPro.QuitaContexEnt;
- //Elimina el contexto de entrada actual. Deja apuntando al anterior en la misma posición.
- begin
- if ConsE.Count = 0 then exit; //no sep uede quitar más
- ConsE.Delete(ConsE.Count-1);
- if ConsE.Count = 0 then
- cEnt := nil
- else //apunta al último
- CEnt := ConsE[ConsE.Count-1];
- end;
- function TPPro.LeePosContAct: TPosCont;
- //Devuelve Contexto actual y su posición
- begin
- Result.fCon := cEnt;
- if cEnt = nil then begin
- //aún no hay Contexto definido
- Result.fil := 1;
- Result.col := 1;
- Result.arc := '';
- Result.nlin := 0;
- end else begin
- Result.fil := cEnt.fil;
- Result.col := cEnt.col;
- Result.arc := cEnt.arc;
- Result.nlin := cEnt.nlin;
- end;
- End;
- procedure TPPro.FijPosContAct(pc:TPosCont);
- //Fija Contexto actual y su posición
- begin
- cEnt := pc.fCon;
- if cEnt = nil then begin
- //no tiene un Contexto actual
- // filAct := 1;
- // colAct := 1;
- // cEnt.arc := '';
- // nlin := 0;
- end else begin
- cEnt.fil := pc.fil;
- cEnt.col := pc.col;
- cEnt.arc := pc.arc;
- cEnt.nlin := pc.nlin;
- end;
- End;
- function TPPro.LeeCadSal: String;
- //Devuelve la cadena equivalente del contexto de salida actual
- begin
- Result := cSal.LeeCad;
- end;
- procedure TPPro.FijCadSal(cad: string);
- //Fija la cadena equivalente del contexto de salida actual
- begin
- cSal.FijCad(cad);
- end;
- //********************************************************************************
- //Funciones Básicas de acceso al Contexto actual. Todo acceso al Contexto actual
- //debe hacerse a través de estas funciones por seguridad.
- //********************************************************************************
- function TPPro.IniCont: Boolean;
- //Devuelve verdadero si se está al inicio del Contexto actual (fila 1, columna 1)
- begin
- Result := cEnt.IniCont;
- End;
- function TPPro.FinCont: Boolean;
- //Devuelve verdadero si se ha pasado del final del Contexto actual
- begin
- Result := cEnt.FinCont;
- End;
- function TPPro.VerCar: Char;
- //Devuelve el caracter actual a partir de la posición actual, del Contexto actual.
- //Si no hay texto en el Contexto actual o si se ha llegado al final del
- //texto, devuelve FIN_CON.
- //Si está al final de una línea devuelve siempre "FIN_LIN"
- begin
- Result := cEnt.VerCar;
- End;
- function TPPro.VerCarN(numcar: Integer): String;
- //Devuelve los N caracteres a partir de la posición actual, del Contexto actual.
- //Si no hay texto en el Contexto actual o si se ha llegado al final del
- //texto, devuelve FIN_CON.
- //Si está al final de una línea devuelve siempre "FIN_LIN"
- var linact:String;
- begin
- If FinCont Then Exit(FIN_CON);
- linact := cEnt.lin[cEnt.fil-1]; //línea actual
- If cEnt.col = Length(linact) + 1 Then begin
- //Se está al fin de la línea. Se considera que cada línea
- //tiene un salto de línea al final, excepto la última línea.
- //En este caso siempre se devuelve FIN_LIN
- Result := FIN_LIN
- end Else //No se está al fin de la línea
- Result := copy(linact, cEnt.col, numcar);
- End;
- function TPPro.CogCar: Char;
- //Devuelve el caracter actual del Contexto actual e incrementa
- //el puntero a la siguiente posición.
- //La siguiente posición del fin de una línea es el caracter "salto de
- //línea", que son en realidad dos caracteres.
- begin
- Result :=cEnt.CogCar;
- End;
- {Function TPPro.VerCarAnt: Char;
- //echa un vistazo al caracter anterior del Contexto
- //Si no hay caracter anterior, devuelve cadena vacía
- Var linact:String;
- begin
- Result := #0;
- If cEnt.FinCont Then Exit; //Realmente debería devolver el caracter final
- If IniCont Then Exit; //No hay caracter anterior
- linact := cEnt.lin[cEnt.fil-1]; //línea actual
- If cEnt.col = 1 Then
- //Está al inicio de una línea
- Result := FIN_LIN //devuelve el salto anterior
- Else
- Result := linact[cEnt.col-1];
- End;}
- function TPPro.CapBlancos: Boolean;
- //Coge los blancos iniciales del contexto de entrada.
- //Si no encuentra algun blanco al inicio, devuelve falso
- begin
- Result := cEnt.CapBlancos;
- End;
- function TPPro.Capturar(cap: String): Boolean;
- //coge la cadena dada ignorando los blancos iniciales.
- Var i:Integer;
- begin
- Result := False;
- cEnt.CapBlancos; //quita blancos iniciales
- i := 1;
- While Not cEnt.FinCont And (i <= Length(cap)) do begin
- If cEnt.VerCar = cap[i] Then begin
- cEnt.CogCar;
- i := i + 1;
- end Else
- Exit; //fallo en algun caracter
- End;
- If i > Length(cap) Then //encontró toda la cadena
- Capturar := True;
- End;
- //********************************************************************************
- //Funciones de mayor nivel para acceso al Contexto actual.
- //********************************************************************************
- function TPPro.VerIdentificador: String;
- //devuelve una palabra correspondiente a un identificador
- //empieza a buscar desde el principio
- Var col0:Integer;
- begin
- col0 := cEnt.col;
- VerIdentificador := CogIdentificador;
- cEnt.col := col0;
- End;
- function TPPro.VerIdentifM: String;
- //Devuleve el dientificador en mayúscula
- begin
- Result := UpCase(VerIdentificador);
- end;
- function TPPro.VerPalabra: String;
- //devuelve una palabra correspondiente a un identificador
- //empieza a buscar desde el principio
- Var ncolTmp:Integer;
- begin
- ncolTmp := cEnt.col;
- VerPalabra := cogPalabra;
- cEnt.col := ncolTmp;
- End;
- function TPPro.VerElemento: String;
- //devuelve una palabra correspondiente a un identificador
- //empieza a buscar desde el principio
- Var fil0, col0: integer;
- begin
- col0 := cEnt.col; //guarda todo el contexto, porque "CogElemento", puede cambiar de línea
- fil0 := cEnt.fil;
- VerElemento := CogElemento;
- cEnt.col := col0; //recupera
- cEnt.fil := fil0;
- End;
- function TPPro.CogIdentificador: String;
- //Coge una palabra correspondiente a un identificador desde la posicion actual del
- //contexto.
- Var temp:String;
- car1, car: char;
- begin
- Result := ''; //no hay identificador inicialmente
- //CapBlancos; //no debe eliminar espacios
- temp := '';
- car1 := VerCar; //lee caracter inicial
- If FinCont Then Exit; //Fin de Contexto
- If Not (car1 in CAR_INI_IDENT) Then //primer caracter valido
- Exit; //no es identificador
- temp += CogCar; //acumula
- //busca hasta encontar fin de identificador
- car := VerCar;
- While car in CAR_IDENT do begin
- if (car = '$') then begin //verifica regla de nombre de identif.
- //verifica si es delimitador o inicio de otro identificador
- if (car1='$') then //es delimitador
- temp += CogCar; //acumula
- break;
- end;
- temp += CogCar; //acumula
- car := VerCar;
- end;
- //se llego al final del archivo
- Result := temp //copia hasta el final
- End;
- function TPPro.CogIdentificador(var ide, ideM: string; var uc:char): boolean;
- {Versión que lee el identificador normal y en mayúscula. Si no encuentra ningún identificador
- devuelve FALSE. Devuelve además el último caracter leido antes del identificador (uc).}
- begin
- if TipoSigToken = tkIdentifier then begin
- uc := cEnt.VerCarAnt; //lee caracter anterior
- ide := CogIdentificador();
- ideM := UpCase(ide); //en mayúscula
- exit(true); //sale con TRUE
- end else //no hay identificador
- exit(false);
- end;
- function TPPro.CogIdentificador(var ideM: string): boolean;
- //Versión sencilal que devuelve el identificador en mayúscula
- begin
- if TipoSigToken = tkIdentifier then begin
- ideM := UpCase(CogIdentificador()); //en mayúscula
- exit(true); //sale con TRUE
- end else //no hay identificador
- exit(false);
- end;
- function TPPro.cogPalabra: String;
- //coge una palabra completa (alfanumerico y punto decimal)
- //desde la posicion donde se encuentra el archivo
- Var temp:String;
- car:char;
- begin
- cogPalabra := ''; //no hay identificador inicialmente
- CapBlancos; //quita blancos iniciales
- temp := '';
- car := VerCar;
- If car = '' Then Exit;
- If Not (car in CAR_VAL_PALABRA) Then //primer caracter valido
- Exit; //no es identificador
- temp := temp + CogCar; //acumula
- //busca hasta encontrar fin de identificador
- While VerCar <> '' do begin
- car := VerCar;
- If car in CAR_VAL_PALABRA Then begin
- CogCar; //toma el caracter
- temp += car; //acumula
- end Else begin
- cogPalabra := temp; //copia el identificador
- Exit;
- End;
- end;
- //se llego al final del archivo
- cogPalabra := temp; //copia hasta el final
- End;
- function TPPro.CogElemento: String;
- {Toma un elemento de una cadena. El elemento puede ser un identificador,
- un símbolo o una frase. Los elementos se separan por caracteres "blancos".
- Por ejemplo, la cadena:
- casa 1 'nueva casa'
- Tiene 3 elementos: "casa", "1" y "nueva casa".}
- Var temp:String;
- car:char;
- begin
- CapBlancos; //quita blancos iniciales
- If cEnt.VerCar = '''' Then //Inicio de cadena
- Result := CogCadena
- Else begin
- temp := '';
- While cEnt.VerCar <> '' do begin
- car := cEnt.VerCar;
- If not (car in [' ',#9,FIN_LIN, FIN_CON]) Then begin
- cEnt.CogCar; //toma el caracter
- temp += car; //acumula
- end Else begin
- Result := temp; //copia el identificador
- Exit;
- End;
- end;
- //se llego al final del archivo
- Result := temp; //copia hasta el final
- End;
- End;
- function TPPro.CogNumero: Single;
- {Coge una cifra numerica, del contexto actual, desde la posicón actual.
- Primero elimina los blancos. Si no encuentra algún caracter numérico al inicio, o el
- signo menos, sale }
- begin
- CogNumero(Result);
- End;
- function TPPro.CogNumero(var n: Single): boolean;
- Var car:char;
- temp:String;
- begin
- Result := false ; //no hay numero
- CapBlancos;
- car := cEnt.VerCar;
- If Not (car in ['0'..'9','.','-']) Then //primer caracter no valido
- Exit; //no es numero
- if (car in ['.','-']) and not (cEnt.VerCarSig in ['0'..'9']) then
- Exit; //no es válido
- temp := cEnt.CogCar; //acumula primer dígito
- //busca hasta encontar fin de identificador
- While cEnt.VerCar in ['0'..'9','.'] do begin
- car := cEnt.CogCar; //toma el caracter
- temp += car; //acumula
- end;
- //se llego al final del número
- n := StrToFloat(temp); //copia hasta el final
- Result := true; //indica que hubo número
- end;
- function TPPro.CogCadena: String;
- begin
- CogCadena(Result);
- End;
- function TPPro.CogCadena(var s: string): boolean;
- {Coge una constante de tipo cadena (entre apóstrofos) desde la posicion
- donde se encuentra el archivo, hasta el delimitador o fin de línea.
- Si no encuentra una cadena, devuelve FALSE}
- Var car : char;
- begin
- PErr.IniError;
- Result := false; //no hay cadena
- CapBlancos; //quita blancos iniciales
- s := '';
- car := cEnt.VerCar;
- If car <> '''' Then //primer caracter no valido
- Exit; //no es constante cadena
- cEnt.CogCar; //toma el caracter
- Result := true; //indica que se encontró cadena
- //busca hasta encontar fin de identificador
- While not(cEnt.VerCar in [FIN_LIN, FIN_CON]) do begin
- car := cEnt.CogCar;
- If car <> '''' Then begin
- s += car; //acumula
- end Else begin
- Exit;
- End;
- end;
- //se llego al final del archivo
- PErr.GenError('No se encontro fin de cadena', PosAct);
- end;
- function TPPro.coger_ruta: String;
- //Coge una cadena que representa la ruta de un archivo (con o sin apóstrofos)
- //desde la posicion donde se encuentra el archivo
- Var temp:String;
- car:String;
- begin
- PErr.IniError;
- coger_ruta := ''; //no hay cadena
- CapBlancos; //quita blancos iniciales
- temp := '';
- car := VerCar;
- If car = '' Then Exit;
- If car = '''' Then begin //ruta en formato de cadena
- temp := CogCadena;
- If PErr.HayError Then Exit;
- coger_ruta := temp;
- Exit; //no es constante cadena
- end Else begin
- //busca hasta encontar blanco (espacio o salto de línea, o tab)
- While Not FinCont And Not (VerCar in [' ',#9,FIN_LIN]) do
- temp += CogCar; //acumula
- Result := temp; //copia
- //se llego al final del archivo
- // GenError 1, "No se encontro fin de cadena", ArcActual, filAct
- End;
- End;
- function TPPro.TipoSigToken: TtkTokenKind;
- //Identifica el token que inicia en la posición actual.
- begin
- case VerCar of
- '$','a'..'z','A'..'Z','_': Result := tkIdentifier;
- else
- Result := tkUnknown;
- end;
- end;
- function TPPro.VerSiEsComentario: Boolean;
- //devuelve verdad si la posicion actual del archivo de entrada corresponde
- //al inicio de un comentario. No Filtra blancos iniciales ni salta lineas
- var cad: string[2];
- begin
- VerSiEsComentario := False;
- cad := VerCarN(2);
- Result := (cad = '--') or (cad = '/*');
- End;
- function TPPro.CogerHastaFinLinea: String;
- //coge una cadena correspondiente a los caracteres desde el punto actual hasta el fin de la linea
- Var temp:String;
- begin
- temp := '';
- While Not cEnt.FinCont And (cEnt.VerCar <> FIN_LIN) do
- temp += cEnt.CogCar;
- cEnt.CogCar; //Coge el fin de línea
- //se llego al final del archivo o al fin de linea
- Result := temp; //copia hasta el final
- End;
- function TPPro.CogerHastaComent: String;
- //Coge texto hasta encontrar el inicio de un comentario o un salto de línea
- var linact : string;
- i,j, min: integer;
- begin
- linact := cEnt.lin[cEnt.fil-1]; //línea actual
- //busca posiicón de comentario
- min := length(linact)+1; //valor inicial
- i := Pos('--',linAct);
- if i<>0 then min := i; //primer valor
- j := Pos('/*',linAct);
- if j < cEnt.col then j := 0; //comentarios anteriores (/* ... */), se ignoran.
- if j<>0 then //hay otro
- if j < min then min := j; //compara valor
- //toma los caracteres necesarios
- Result := Copy(linAct,cEnt.col,min-cEnt.col); //copia hasta el final
- cEnt.col := min; //pone kasta posición leida
- if min = length(linact) + 1 then CogCar; //Coge el fin de línea
- end;
- function TPPro.CogerComent: boolean;
- {Coge un comantario, de tipo /* .. */. Debe llamarse cuando se ha detectado
- el inicio de este comentario. Puede coger varias líneas.}
- begin
- Result := false;
- while not FinCont do begin
- if cEnt.CogCar = '*' then begin
- //puede ser delimitador final
- if cEnt.VerCar = '/' then begin
- cEnt.CogCar; //toma el delimitador
- Result := true;
- exit; //sale
- end;
- end;
- end;
- end;
- function TPPro.CogerLista(lista: TStringList; delims: string): string;
- {Estrae una lista de elementos del contexto actual, hasta encontrar uno de los
- delimitadores indicados en "delims". Si termina por encontrar un delimitador,
- devuelve el delimitador encontrado (siempre en mayúscula). Los delimitadores
- deben indicarse separados por coma, sin esapcios entre ellos}
- var tmp: string;
- l_delims : TstringList;
- begin
- Result:='';
- l_delims := TStringList.Create; //crea lista
- l_delims.Delimiter:=',';
- l_delims.DelimitedText:=delims; //descompone lista
- { --VERSIÓN SIN COGER ELEMENTO
- tmp := VerElemento; //toma primero
- While Not FinCont do begin
- If l_delims.IndexOf(tmp) <> -1 Then //busca delimitador
- begin Result:= tmp; break end; //encontro delimitador, sale.
- lista.add(CogElemento); //agrega elemento
- tmp := VerElemento; //toma siguiente
- end;}
- repeat
- tmp := CogElemento; //toma siguiente
- if tmp = '' then break; //es fin de contexto, porque CogElemento toma cualquier cosa
- If l_delims.IndexOf(tmp) <> -1 Then begin //busca delimitador
- Result:= Upcase(tmp); break; //encontro delimitador, sale.
- end;
- lista.add(tmp); //agrega elemento
- until Cent.FinCont;
- //aquí puede haber llegado por fin de contexto o por haber encontrado
- //algún delimitador.
- l_delims.Free;
- end;
- function TPPro.VerHastaFinLinea: String;
- //Devuelve una cadena correspondiente a los caracteres desde el punto actual hasta el fin de
- //la linea. Empieza a buscar desde el principio.
- Var nfilTmp:LongInt;
- ncolTmp:Integer;
- begin
- nfilTmp := cEnt.fil;
- ncolTmp := cEnt.col;
- VerHastaFinLinea := CogerHastaFinLinea;
- cEnt.fil := nfilTmp; //devuelve el numero de linea inicial
- cEnt.col := ncolTmp;
- End;
- //********************************************************************************
- //Funciones para manejo de la salida
- //********************************************************************************
- procedure TPPro.NuevoContexSal;
- //Crea un nuevo contexto de salida y pone cursor al inicio.
- begin
- //Crea Contexto de salida
- cSal := TContexto.Create;
- ConsS.Add(cSal); //Registra Contexto
- cSal.FijCad(''); //Iniicia cadena y posiciona cursor al final
- end;
- procedure TPPro.QuitaContexSal;
- //Elimina el contexto de salida actual. Deja apuntando al anterior en la misma posición.
- begin
- if ConsS.Count = 0 then exit; //no sep uede quitar más
- ConsS.Delete(ConsS.Count-1);
- if ConsS.Count = 0 then
- cSal := nil
- else //apunta al último
- CSal := ConsS[ConsS.Count-1];
- end;
- procedure TPPro.PonCar(c: char);
- begin
- cSal.PonCar(c);
- end;
- procedure TPPro.Escribe(palabra: string);
- //Escribe un palabra en el archivo de salida. Este debe ser el único punto
- //de acceso al archivo de salida.
- begin
- cSal.PonCad(palabra);
- end;
- procedure TPPro.EscribeSalto;
- //Escribe un salto de línea en el archivo de salida.
- begin
- cSal.PonSalto;
- end;
- procedure TPPro.SacCar;
- //Quita un caracter del dispositivo de salida, borrando la información previamente escrita.
- begin
- cSal.SacCar;
- end;
- procedure TPPro.GenArchivo(ArcSal0: string);
- //Genera el archivo de salida
- begin
- if ArcSal0 = '' then exit; //protección
- cSal.lin.SaveToFile(ArcSal0);
- end;
- function TPPro.TextSalida: string;
- begin
- Result := cSal.lin.Text;
- end;
- function TPPro.cogOperador: String;
- {Coge un operador en la posición del contexto actual. Si no encuentra
- devuelve cadena vacía y no coge caracteres, salvo espacios iniciales.}
- begin
- cogOperador := '';
- CapBlancos; //quita blancos iniciales
- Case VerCar of //completa con operador de más caracteres
- '+': begin
- Result := CogCar;
- // If VerCar = '+' Then begin CogCar; Result := '++' end;
- // If VerCar = '=' Then begin CogCar; Result := '+=' end;
- end;
- '-': begin
- Result := CogCar;
- // If VerCar() = '-' Then begin CogCar; Result := '--' end;
- // If VerCar() = '=' Then begin CogCar; Result := '-=' end;
- end;
- '*': begin
- Result := CogCar;
- // If VerCar() = '=' Then begin CogCar; Result := '*=' end;
- end;
- '/': begin
- Result := CogCar;
- // If VerCar() = '=' Then begin CogCar; Result := '/=' end;
- end;
- // '=': begin
- // Result := CogCar;
- // If VerCar() = '=' Then begin CogCar; Result := '==' end;
- // If VerCar() = '<' Then begin CogCar; Result := '=<' end; //operador 'menor'
- // If VerCar() = '>' Then begin CogCar; Result := '=>' end; //operador 'mayor'
- // end;
- // '>': begin
- // Result := CogCar;
- // If VerCar() = '=' Then begin CogCar; Result := '>=' end;
- // If VerCar() = '>' Then begin CogCar; Result := '>>' end;
- // If VerCar() = '+' Then begin CogCar; Result := '>+' end;
- // If VerCar() = '-' Then begin CogCar; Result := '>-' end;
- // end;
- // '<': begin
- // Result := CogCar;
- // If VerCar() = '=' Then begin CogCar; Result := '<=' end;
- // If VerCar() = '>' Then begin CogCar; Result := '<>' end;
- // If VerCar() = '<' Then begin CogCar; Result := '<<' end;
- // end;
- // '|': begin
- // Result := CogCar;
- // If VerCar() = '|' Then begin CogCar; Result := '||' end; //OR
- // If VerCar() = '!' Then begin CogCar; Result := '|!' end; //XOR
- // end;
- // '~': begin //operador LIKE
- // Result := CogCar;
- // end;
- // '&': begin
- // Result := CogCar;
- // If VerCar = '&' Then begin CogCar; Result := '&&' end; //AND
- // end;
- End;
- End;
- function TPPro.jerOp(oper: String): Integer;
- //Devuelve la jerarquía de un operador ver documentación técnica.
- begin
- Case oper of
- // '>>', '<<', '>+', '>-': jerOp = 1: Exit Function
- // '=': jerOp := 2;
- // '&&', '||', '!', '|!': jerOp := 3;
- // '==', '<>', '>', '>=', '<', '<=', '~': jerOp := 4;
- '+', '-'{, '|', '&'}: jerOp := 5;
- '*', '/'{, '\', '%'}: jerOp := 6;
- // '=<', '=>': jerOp := 7;
- // '^', '++', '--', '+=', '-=', '*=', '/=': jerOp := 8;
- Else jerOp := 0;
- End;
- End;
- function TPPro.Evaluar(Op1: Texpre; opr: String; Op2: Texpre): Texpre;
- //Devuelve el resultado y tipo de una operación
- begin
- PErr.IniError;
- Evaluar.cat := COP_EXPRESION; //ahora es expresión por defecto
- Case opr of
- '': begin //Sin operador. Y se supone sin Op2
- //no hay nada que hacer, ya está en la pila
- Evaluar := Op1;
- end;
- { '=': begin //Asignación
- If Op1.cat = COP_DEFINIC Then begin //Asignación a una variable
- // Evaluar.val := Op2.val;
- // Evaluar.tip := Op2.tip;
- Op1 := Op2;
- tDefi Op1.def:=;
- Evaluar:= Op1
- end Else
- Perr.GenError('Sólo se puede asignar valor a una variable', PosAct);
- end;}
- '+': begin
- Evaluar.valNum := Op1.valNum + Op2.valNum; //Fuerza a Evaluar.tip := TIP_NUM
- end;
- '-': begin
- Evaluar.valNum := Op1.valNum - Op2.valNum;
- end;
- '*': begin
- Evaluar.valNum := Op1.valNum * Op2.valNum;
- end;
- '/': begin
- If Op2.valNum = 0 Then
- Perr.GenError('No se puede dividir por cero.', PosAct)
- Else begin //error
- Evaluar.valNum := Op1.valNum / Op2.valNum;
- End;
- end;
- { '\': begin
- If val(Op2.val) = 0 Then
- Perr.GenError('No se puede dividir por cero.', PosAct);
- Else begin //error
- Evaluar.val := val(Op1.val) \ val(Op2.val);
- Evaluar.tip := TIP_NUM;
- End;
- end;
- '%': begin
- If val(Op2.val) = 0 Then
- Perr.GenError('No se puede dividir por cero.', PosAct);
- Else begin //error
- Evaluar.val := val(Op1.val) Mod val(Op2.val);
- Evaluar.tip := TIP_NUM;
- End;
- end;
- '^': begin
- If val(Op2.val) = 0 And val(Op2.val) = 0 Then
- Perr.GenError('No se puede Evaluar 0^0', PosAct);
- Else begin //error
- Evaluar.val := val(Op1.val) ^ val(Op2.val);
- Evaluar.tip := TIP_NUM;
- End;
- end;
- '++': begin //mono-operando, sólo Op1
- Op1.val := val(Op1.val) + 1 //incrementa
- Evaluar.val := Op1.val;
- Evaluar.tip := TIP_NUM;
- end;
- '--': begin //mono-operando
- Op1.val := val(Op1.val) - 1 //decrementa
- Evaluar.val := Op1.val;
- Evaluar.tip := TIP_NUM;
- //operadores de comparación
- end;
- '==': begin
- If Op1.val := Op2.val Then
- Evaluar.val := 1
- Else //error
- Evaluar.val := 0
- Evaluar.tip := TIP_NUM
- end;
- '<>': begin
- If Op1.val <> Op2.val Then
- Evaluar.val := 1
- Else //error
- Evaluar.val := 0
- Evaluar.tip := TIP_NUM
- end;
- '>': begin
- If Op1.val > Op2.val Then
- Evaluar.val := 1
- Else //error
- Evaluar.val := 0
- Evaluar.tip := TIP_NUM
- end;
- '<': begin
- If Op1.val < Op2.val Then
- Evaluar.val := 1
- Else //error
- Evaluar.val := 0
- Evaluar.tip := TIP_NUM
- end;
- '>=': begin
- If Op1.val >= Op2.val Then
- Evaluar.val := 1
- Else //error
- Evaluar.val := 0
- Evaluar.tip := TIP_NUM
- end;
- '<=': begin
- If Op1.val <= Op2.val Then
- Evaluar.val := 1
- Else //error
- Evaluar.val := 0
- Evaluar.tip := TIP_NUM
- end;
- '|': begin //concatenación de cadenas
- Evaluar.val := Op1.val & Op2.val
- Evaluar.tip := TIP_CAD
- end;
- '~': begin //comparación de cadenas
- If (Op1.val Like Op2.val) Then
- Evaluar.val := 1
- Else //no cuadra
- Evaluar.val := 0
- Evaluar.tip := TIP_NUM
- end;
- '&&': begin //And lógico
- If (val(Op1.val) = 1 And val(Op2.val) = 1) Then
- Evaluar.val := 1
- Else //no cuadra
- Evaluar.val := 0
- Evaluar.tip := TIP_NUM
- end;
- '||': begin
- If (val(Op1.val) = 0 And val(Op2.val) = 0) Then
- Evaluar.val := 0
- Else //no cuadra
- Evaluar.val := 1
- Evaluar.tip := TIP_NUM
- end;
- '!': begin
- If val(Op1.val) = 1 Then
- Evaluar.val := 0
- Else //no cuadra
- Evaluar.val := 1
- Evaluar.tip := TIP_NUM
- end;}
- Else begin
- Perr.GenError('No se reconoce operador: ' + opr, PosAct);
- Exit;
- End;
- end;
- //Completa campos de evaluar
- Evaluar.txt := Op1.txt + opr + Op2.txt; //texto de la expresión
- // Evaluar.uop := opr; //última operación ejecutada
- End;
- { TPError }
- procedure TPError.IniError;
- begin
- numER := 0;
- cadError := '';
- arcER := '';
- fil := 0;
- col := 0;
- end;
- procedure TPError.GenError(num: Integer; msje: String; archivo: String;
- nlin: integer = 0);
- //Genera un error
- begin
- numER := num;
- cadError := msje;
- arcER := archivo;
- fil := nlin;
- end;
- procedure TPError.GenError(msje: String; posCon: TPosCont);
- //Genera un error en la posición indicada
- begin
- numER := 1;
- cadError := msje;
- arcER := posCon.arc;
- fil := posCon.fil;
- col := posCon.col;
- end;
- function TPError.GenTxtError: string;
- //Genera una cadena con el mensaje de error de acuerdo al nivel de detalle que tenga.
- begin
- Result :=cadError;
- If arcER <> '' Then begin //agrega información de archivo
- Result += LineEnding + arcER;
- end;
- If fil <> 0 Then begin //Hay número de línea
- // Result := Pchar('[' + arcER + ']: ' + cadError + ' Línea: ' + IntToStr(fil);
- Result += LineEnding + '(' +IntToStr(fil) + ',' + IntToStr(col) + ') ';
- end;
- end;
- {procedure TPError.MosError;
- //Muestra un mensaje de error
- begin
- writeln(TxtError); No debe ser dependiente del tipo de Aplicación
- end;}
- function TPError.ArcError: string;
- //Devuelve el nombre del archivo de error
- begin
- ArcError := arcER;
- end;
- function TPError.nLinError: longint;
- //Devuelve el número de línea del error
- begin
- nLinError := fil;
- end;
- function TPError.nColError: longint;
- //Devuelve el número de línea del error
- begin
- nColError := col;
- end;
- function TPError.HayError: boolean;
- begin
- HayError := numER <> 0;
- end;
- { TContexto }
- //********************************************************************************
- //Funciones Básicas para administración de los Contextos
- //********************************************************************************
- constructor TContexto.Create;
- begin
- inherited; //solo se pone por seguridad, ya que no es necesario.
- lin := TStringList.Create; //crea lista de cadenas para almacenar el texto
- nlin := 0;
- CurPosFin; //inicia fil y col
- end;
- destructor TContexto.Destroy;
- begin
- lin.Free; //libera lista
- inherited Destroy;
- end;
- function TContexto.IniCont: Boolean;
- //Devuelve verdadero si se está al inicio del Contexto (fila 1, columna 1)
- begin
- Result := (fil = 1) And (col = 1);
- end;
- function TContexto.FinCont: Boolean;
- //Devuelve verdadero si se ha pasado del final del Contexto actual
- begin
- //Protección a Contexto vacío
- If nlin = 0 Then begin
- Result := True;
- Exit;
- End;
- //Verifica optimizando verificando primero la condición más probable
- If fil < nlin Then
- Result := False
- Else If fil > nlin Then
- Result := True
- Else If fil = nlin Then begin
- //Verifica si estamos en la línea final.
- //OJO, en la línea final no existe un salto de línea adicional
- If col >= Length(lin[fil-1]) + 1 Then
- Result := True
- Else
- Result := False
- End;
- end;
- function TContexto.VerCar: Char;
- //Devuelve el caracter actual
- begin
- If FinCont Then Exit(FIN_CON);
- If col = Length(lin[fil-1]) + 1 Then begin
- //Se está al fin de la línea. Se considera que cada línea
- //tiene un salto de línea al final, excepto la última línea.
- //En este caso siempre se devuelve FIN_LIN
- Result := FIN_LIN
- end Else //No se está al fin de la línea
- Result := lin[fil-1][col];
- end;
- function TContexto.CogCar: Char;
- //Lee un caracter del contexto y avanza el cursor una posición.
- begin
- If FinCont Then Exit(FIN_CON);
- If col >= Length(lin[fil-1]) + 1 Then begin
- //Se está al fin de la línea. Trabaja igual que VerCar().
- Result := FIN_LIN;
- col := 1;
- fil := fil + 1; //Pasa a siguiente fila, puede ser que se
- //haya pasado la cantidad de líneas disponibles
- end Else begin //No se está al fin de la línea
- Result := lin[fil-1][col];
- inc(col);
- End;
- end;
- function TContexto.VerCarAnt: Char;
- //echa un vistazo al caracter anterior del Contexto
- //Si no hay caracter anterior, devuelve cadena vacía
- Var linact:String;
- begin
- Result := #0;
- If IniCont Then Exit; //No hay caracter anterior
- linact := lin[fil-1]; //línea actual
- If col = 1 Then
- //Está al inicio de una línea
- Result := FIN_LIN //devuelve el salto anterior
- Else
- Result := linact[col-1];
- end;
- function TContexto.VerCarSig: Char;
- //Devuelve el catacter siguiente al actual. OJO: Solo mira la línea actual.
- begin
- If FinCont Then Exit(FIN_CON);
- If col >= Length(lin[fil-1]) Then begin
- Result := FIN_LIN
- end Else //No se está al fin de la línea
- Result := lin[fil-1][col+1];
- end;
- function TContexto.CapBlancos: Boolean;
- //Coge los blancos iniciales del contexto de entrada.
- //Si no encuentra algun blanco al inicio, devuelve falso
- begin
- Result := False;
- if not (VerCar in [' ', FIN_LIN, #9]) then exit; //no hay blancos
- repeat
- CogCar
- until FinCont or not (VerCar in [' ', FIN_LIN, #9]);
- end;
- procedure TContexto.CurPosIni;
- //Mueve la posición al inicio del contenido.
- begin
- if lin.Count = 0 then begin
- fil := 0; col := 0;
- end else
- begin
- fil := 1;
- col := 1; //posiciona al inicio
- end;
- end;
- procedure TContexto.CurPosFin;
- //Mueve la posición al final del contenido.
- begin
- if lin.Count = 0 then begin
- fil := 0; col := 0;
- end else
- begin
- fil := lin.Count;
- col := length(lin[fil-1])+1; //posiciona al final
- end;
- end;
- procedure TContexto.PonSalto;
- //Escribe un salto de línea en el contexto
- begin
- lin.Add('');
- fil := lin.Count; //actualiza filas
- col := 1; //posiciona en primera columna
- end;
- procedure TContexto.SacLinea;
- //Saca la última línea del contexto. Debe haber por lo menos una línea
- begin
- if lin.Count = 0 then exit;
- lin.Delete(lin.Count-1); //elimina última línea
- CurPosFin; //actualiza posición de cursor
- end;
- procedure TContexto.PonCar(c: char);
- //Escribe un caracter en el contexto. Debe haber por lo menos una línea
- begin
- if lin.Count = 0 then exit; //sin datos
- if c = FIN_LIN then //caracter de salto de línea
- PonSalto
- else begin //caracter normal
- lin[lin.Count-1] := lin[lin.Count-1] + c; //agrega a línea actual
- inc(col); //actualiza columna
- end;
- end;
- procedure TContexto.PonCad(s: String);
- //Escribe una cadena (sin saltos) en el contexto. Debe haber por lo menos una línea
- begin
- if lin.Count = 0 then exit; //sin datos
- lin[lin.Count-1] := lin[lin.Count-1] + s; //agrega a línea actual
- col += length(s); //actualiza columna
- end;
- procedure TContexto.SacCar;
- //Quita un caracter del contexto
- var n:integer;
- begin
- n := lin.Count;
- if n = 0 then exit; //sin datos
- if (n = 1) and (length(lin[0])=0) then exit; //sin datos
- //hay datos
- if col = 1 then //al inicio de línea
- SacLinea
- else begin
- lin[n-1] := copy(lin[n-1],1,col-2); //recorta
- CurPosFin; //actualiza posición de cursor
- end;
- end;
- function TContexto.LeeCad: string;
- //Devuelve el contenido del contexto en una cadena.
- begin
- Result := lin.text;
- end;
- procedure TContexto.FijCad(cad: string);
- //Fija el contenido del contexto con una cadena.
- begin
- tip := TC_TXT; //indica que contenido es Texto
- if cad='' then begin
- //cadena vacía, crea una línea vacía
- lin.Clear;
- lin.Add('');
- nlin := 1; //actualiza número de líneas
- end else begin
- lin.Text := cad;
- nlin := lin.Count; //actualiza número de líneas
- end;
- CurPosFin; //actualiza posición de cursor
- arc := ''; //No se incluye información de archivo
- end;
- procedure TContexto.FijArc(arc0: string);
- //Fija el contenido del contexto con un archivo
- begin
- tip := TC_TXT; //indica que contenido es Texto
- lin.LoadFromFile(arc0);
- nlin := lin.Count; //actualiza número de líneas
- CurPosFin; //actualiza posición de cursor
- arc := arc0; //No se incluye información de archivo
- end;
- initialization
- PPro.Create;
- finalization
- PPro.Destroy;
- end.
|