{================================================}

BASIC APASCALADO VIII - Finalmente Pascal !

A seguir apresenta-se um programa em Pascal básico, 
fácilmente convertível em Basic.

Já é altura de perceberem Pascal!

Chamo a atenção  para o facto  do programa  servir 
para fazer qualquer outra coisa;  basta alterar as 
tabelas e redefinir as acções a tomar. 

T.P.C.(trabalho para casa):  fazer  esta  história 
para   um  real  em  virgula   flutuante,  notação 
científica. É fácil, basta acrescentar a gramática 
do expoente (um "E" seguido dum inteiro com sinal). 

Alô!  Está aí  alguém?  Bem, de qualquer modo  não 
está previsto mais  nenhum artigo,  pelo menos por 
uns tempos.  Não há mal que  sempre dure,  nem bem 
que não se acabe!

{================================================}

PROGRAM automato (INPUT,OUTPUT);

(* Pascal simples para ser fácilmente
 * convertido em Basic.
 * (C) 1988 ZARSOFT Corporation
 * Written by ZE OLIVEIRA
 *)

VAR	         {-- declaraçäo de variaveis --}
  E,A       :ARRAY [1..5,1..5] OF INTEGER;
                       {-- automato e acçöes --} 
  texto     :STRING[80]; {-- texto a analisar -} 
  txt_index :INTEGER;  {-- indice de análise --} 
  erro      :BOOLEAN; {- relatorio da análise -} 
             {-- de tipo inteiro no spectrum --}

  {--- variaveis para RECONHECE ---------------} 
  estado,                  {-- estado actual --}
  accao    :INTEGER;	   {-- acçäo a tomar --}
  terminal :CHAR;      {- caracter a analisar -}
  code_terminal :INTEGER; { codigo do caracter }

  {---- variaveis para o calculo do numero ----} 
  sinal,		 {-- sinal do numero --}
  contador,		  {-- casas decimais --}
  inteiro   :INTEGER;      {-- parte inteira --} 
  decimal,		   {-- parte decimal --}
  numero    :REAL;	       {-- resultado --}

{================================================}

FUNCTION VAL (car:CHAR):INTEGER;
{ funçäo inteira; semelhante à do spectrum }
BEGIN  VAL := ORD(car)-ORD('0')  END;

{------------------------------------------------}

FUNCTION POWER (base,expoente:REAL):REAL;

{-- calcula base elevado a expoente --} 
BEGIN  POWER := EXP(expoente*LN(base))  END;

{================================================}

PROCEDURE executa_accao;
VAR  i  :INTEGER;  { variavel local a este PROC  } 
{-- no spectrum todas as variaveis säo globais --} 
BEGIN
  IF accao = 0
    THEN
      BEGIN	              {-- inicializar --}
        sinal := 1; inteiro := 0; decimal := 0;
    	contador := 0; numero := 0
      END;
  IF accao = 1
    THEN; { skip - nao fazer nada }
  IF accao = 2	          {-- numero negativo --}
    THEN sinal := -1;
  IF accao = 3	  {- adicionar à parte inteira -}
    THEN inteiro := inteiro*10+VAL(terminal);
  IF accao = 4
    THEN	   { adicionar à parte decimal -}
      BEGIN
	contador := contador+1;
        decimal := decimal+ POWER(10,-contador)*VAL(terminal)
      END;
  IF accao = 5	         {-- terminar calculo --}
    THEN numero := sinal*(inteiro+decimal);
  IF accao = -1
    THEN	                     {-- erro --}
      BEGIN
	erro := TRUE;
      	WRITELN('sintax error');
	WRITELN(texto);
        FOR i := 1 TO txt_index-1 DO WRITE(' ');´
        WRITELN('^');
	{-- WRITE(a)    ->   PRINT a; --}
        {-- WRITELN(a)  ->   PRINT a  --}
      END
END; {-- executa_accao --}

{================================================}

FUNCTION get_simbolo :CHAR;
{	funçäo tipo caracter }
{	retorna o proximo caracter a analisar }
BEGIN
  txt_index := txt_index+1; 
  get_simbolo := texto[txt_index]
  { a funçäo retorna o valor desta atribuiçäo }
END;

{------------------------------------------------}

FUNCTION get_codigo (term:CHAR):INTEGER;
{	funçäo tipo inteira }
{retorna o numero da coluna para aceder às tabelas} 
VAR { uma variavel local - global no spectrum }
  cod :INTEGER;  { auxiliar para o calculo }
BEGIN
  cod := 5;  {-- por defeito é fim de texto --}
  IF term = '+' THEN cod := 1;
  IF term = '-' THEN cod := 2;
  IF term = '.' THEN cod := 3; 
  IF (term >= '0')  AND (term <= '9')  THEN cod := 4;
  get_codigo := cod
  { a funçäo retorna o valor da variavel "cod" }
END; {-- get_codigo --}

{------------------------------------------------}

PROCEDURE reconhece;
BEGIN {-- principio do procedimento --} 
  txt_index := 0; erro := FALSE;
  texto := texto+'$';      {- para simplificar, -}
                     {- o texto termina com "$" -} 
  accao := 0;
  executa_accao;
  estado := 1;
  terminal := get_simbolo; 
  code_terminal := get_codigo(terminal);
  {executar enquanto (terminal <> '$') e nao erro} 
  WHILE ( (code_terminal <> 5) AND NOT(erro) )  DO 
    BEGIN
      accao := A[estado,code_terminal]; 
      estado := E[estado,code_terminal]; 
      executa_accao;
      terminal := get_simbolo; 
      code_terminal := get_codigo(terminal);
    END;
  IF NOT(erro)
    THEN BEGIN accao:=5; executa_accao END
END; {--- reconhece --}

{------------------------------------------------} 
(* De acordo com BASPAS1 MICROSE7E 56,
 * no spectrum, o ciclo WHILE é transformado em:
 *     FOR w = NOT( ct<>5 AND NOT(e) ) TO 0 STEP 0
 *		   ...
 *		 IF ct<>5 AND NOT(e) THEN NEXT w
 * Em basic apascalado näo existem GOTOs.
 *) 
{------------------------------------------------}
PROCEDURE inicializar;
VAR   l,c :INTEGER; { variaveis auxiliares }
BEGIN
  FOR l:=1 TO 5 DO
    FOR c:=1 TO 5 DO
      BEGIN A[l,c]:=-1; E[l,c]:=-1 END;
  E[1,1]:=2; E[1,2]:=2; E[1,3]:=3; E[1,4]:=4;
  E[2,3]:=3; E[2,4]:=4; E[3,4]:=5;
  E[4,3]:=5; E[4,4]:=4; E[5,4]:=5;
  A[1,1]:=1; A[1,2]:=2; A[1,3]:=1; A[1,4]:=3;
  A[2,3]:=1; A[2,4]:=3; A[3,4]:=4;
  A[4,3]:=1; A[4,4]:=3; A[5,4]:=4;
  A[4,5]:=5; A[5,5]:=5;
  { há maneiras mais fáceis de fazer isto }
END; {-- inicializar --}

{================================================}

BEGIN {--- programa principal ---}
  inicializar;
  WRITE('diz um numero  ');
  READLN(texto);
  reconhece;
  IF NOT(erro)
    THEN WRITELN('numero = ',numero)
END. {--- programa principal ---}

{================================================}

-----------------------------
ZE OLIVEIRA zarsoft(a)clix.pt
-----------------------------