comp.lang.ada
 help / color / mirror / Atom feed
From: agent@drrob1.com
Subject: Re: confusing string error
Date: Fri, 14 Feb 2014 19:46:51 -0500
Date: 2014-02-14T19:46:51-05:00	[thread overview]
Message-ID: <3kdtf9l42gimm37vgia3eibsmr638r27ig@4ax.com> (raw)
In-Reply-To: 87ha81u9r7.fsf@adaheads.sparre-andersen.dk

On Fri, 14 Feb 2014 14:03:24 +0100, Jacob Sparre Andersen
<jacob@jacob-sparre.dk> wrote:

>agent@drrob1.com writes:
>
>> Code fragment:
>>
>
>You haven't provided enough information to compile and evaluate your
>example.
>
>Greetings,
>
>Jacob

I was trying not to bomb the newsgroup.  But it seems you want it.  So
here we go.  Assume that a valid spec file exists.  I included the
relevent types I define in it in my comments, as it is in my actual
code.

Package body tokenizea is
      TKNMAXSIZ : constant := 80;
      DGTMAXSIZ : constant := 9;
      OPMAXSIZ  : constant := 2;
      POUNDSIGN : constant Character := '#';  -- (* 35 *)
      PLUSSIGN  : constant Character := '+';  -- (* 43 *)
      COMMA     : constant Character := ',';  -- (* 44 *)
      MINUSSIGN : constant Character := '-';  -- (* 45 *)
      SEMCOL    : constant Character := ';';  -- (* 59 *)
      LTSIGN    : constant Character := '<';  -- (* 60 *)
      EQUALSIGN : constant Character := '=';  -- (* 61 *)
      GTSIGN    : constant Character := '>';  -- (* 62 *)
      MULTSIGN  : constant Character := '*';
      DIVSIGN   : constant Character := '/';
      ASCZERO   : constant :=  Character'Pos('0'); -- 48, 30H.
      SQUOTE    : constant Character := ''';  -- Character'Val(39)
      DQUOTE    : constant Character := '"';  -- Character'Val(34);
      NullChar  : constant Character :=  Character'Val(0);
      CharDgt0  : constant Character := '0';
      CharDgt9  : constant Character := '9';

-- Now declared in package spec file
--  TYPE FSATYP is (DELIM, OP, DGT, ALLELSE);
--  Type TokenType is Record
--    uStr: Unbound_String;
--    State : FSATYP;
--    delimCH : Character;
--    DelimState: FSATYP;
--    Sum : Integer;
--  END Record;
--  Type CharType is Record
--    ch : Character;
--    State : FSATYP;
--  END Record;

--  These variables are declared here to make the variable static so
-- to maintain
--  their values between procedure calls.
  CURPOSN,HOLDCURPOSN,PREVPOSN : Natural;
  TKNBUF,HOLDTKNBUF : Unbounded_String;
  FSAARRAY  : ARRAY (Character) OF FSATYP;
  out_of_range, token_too_long : EXCEPTION  ;

PROCEDURE InitFSAArray is
BEGIN
  FSAARRAY := (others => AllElse) ;
  FOR C in CharDgt0 .. CharDgt9 Loop
    FSAARRAY(C) := DGT;
  END Loop;
  FSAARRAY(NullChar) := DELIM;
  FSAARRAY(' ') := DELIM;
  FSAARRAY(',') := DELIM;
  FSAARRAY(';') := DELIM; -- (* semcol *)
  FSAARRAY('#') := OP;    -- (* poundsign *)
  FSAARRAY('*') := OP;    -- (* multsign *)
  FSAARRAY('+') := OP;    -- (* plussign *)
  FSAARRAY('-') := OP;    -- (* minussign *)
  FSAARRAY('/') := OP;    -- (* divsign *)
  FSAARRAY('<') := OP;    -- (* LTSIGN *)
  FSAARRAY('=') := OP;    -- (* EQUAL *)
  FSAARRAY('>') := OP;    -- (* GTSIGN *)
END InitFSAArray;

PROCEDURE INI1TKN(Str : String) is
-- *************************** INI1TKN 
--INITIALIZE TOKEN.
BEGIN
    CURPOSN  := 1;
    TKNBUF   := To_Unbounded_String(Str);
    PREVPOSN := 0;
    InitFSAArray;
END INI1TKN;

PROCEDURE PeekCHR(Char: OUT CharType; EOL : Out BOOLEAN) is
BEGIN
  IF CURPOSN > LENGTH(TKNBUF) THEN
    EOL := TRUE;
    Char.ch := NullChar;
    Char.State := DELIM;
    RETURN;
  ELSE
    EOL := FALSE;
  END IF;
  Char.CH := CAP(Element(TKNBUF,CURPOSN));
  Char.State := FSAARRAY(Char.CH);
END PeekCHR;

Procedure NextChr is
BEGIN
  CURPOSN := CurPosn + 1;
End NextChr;

PROCEDURE GETCHR(Char: OUT CharType; EOL : Out BOOLEAN) is
BEGIN
	PeekChr(Char, EOL);
	NextChr;
END GETCHR;

PROCEDURE UNGETCHR is
-- ********************************* UNGETCHR 
BEGIN
  IF (CURPOSN < 1) OR (CURPOSN > LENGTH(TKNBUF)+1) THEN
    RAISE out_of_range;
  END IF;
  CURPOSN := CurPosn - 1;
END UNGETCHR;

Function GETOPCODE(TOKEN : TokenType) RETURN Natural is
-- *************************** GETOPCODE 
-- GET OPCODE.
-- THIS ROUTINE RECEIVES A TOKEN OF FSATYP OP (MEANING IT IS AN
-- OPERATOR)
-- AND ANALYZES IT TO DETERMINE AN OPCODE, WHICH IS A 
-- Number FROM  1..15.
-- THE OPCODE ASSIGNMENTS FOR THE OP TOKENS ARE:
--  < is 1                  <= is 2
--  > is 3                  >= is 4
--  = is 5   == is 5        <> is 6    # is 7
--  + is 8                  += is 9
--  - is 10                 -= is 11
--  * is 12                 *= is 13
--  / is 14                 /= is 15
--
    CH1,CH2 : CHARacter;
    OpCode : Natural;
BEGIN
  OPCODE := 0;
  IF (LENGTH(Token.uStr) < 1) OR (LENGTH(Token.uStr) > 2) THEN
    RAISE token_too_long;
    RETURN OpCode;
  END IF;
  CH1 := Element(Token.uStr,1);
  CH2 := Element(Token.uStr,2);
  CASE CH1 is
    WHEN  LTSIGN => OPCODE := 1;
    WHEN  GTSIGN => OPCODE := 3;
    WHEN  EQUALSIGN => OPCODE := 5;
    WHEN  PLUSSIGN  => OPCODE := 8;
    WHEN  MINUSSIGN => OPCODE := 10;
    WHEN  POUNDSIGN => OPCODE := 7;
    WHEN  MULTSIGN  => OPCODE := 12;
    WHEN  DIVSIGN   => OPCODE := 14;
    WHEN OTHERS =>
      RETURN OpCode;
  END CASE;
  IF LENGTH(Token.uStr) = 1 THEN
    RETURN OpCode;
  ELSIF (CH2 = EQUALSIGN) AND (CH1 /= EQUALSIGN) AND 
      (CH1 /= POUNDSIGN) THEN
    OPCODE := OpCode + 1;
  ELSIF (CH1 = LTSIGN) AND (CH2 = GTSIGN) THEN
    OPCODE := 6;
  END IF;
  Return OpCode;
END GETOPCODE;

PROCEDURE GETTKN(TOKEN : Out TokenType; EOL : Out BOOLEAN) is
--*************************** GETTKN 
--
    NEGATV         : BOOLEAN;
    ORDCH,Len      : Natural;
    CHAR           : CHARType;
    QUOCHR         : CHARacter; --  (* Holds the active quote char *)
    QUOFLG         : BOOLEAN;
BEGIN
  QUOCHR := NullChar;
  QUOFLG := FALSE;
  PREVPOSN := CURPOSN;
  ToKeN.STATE := DELIM;
  Token.SUM := 0;
  Token.uStr := Null_Unbounded_String;
  NEGATV := FALSE;

  LOOP
    GETCHR(CHAR,EOL);
    IF EOL THEN
--  NO NEXT CHAR.  IF TKNSTATE IS DELIM, THEN GETTKN WAS CALLED WHEN
-- THERE WERE
--  NO MORE TOKENS ON LINE.  OTHERWISE IT MEANS THAT WE HAVE FETCHED
-- THE LAST
--  TOKEN ON THIS LINE.
      IF Token.STATE = DELIM THEN EOL := TRUE; END IF;
      EXIT;
    END IF;
    ORDCH := Character'Pos(Char.Ch);
    IF QUOFLG AND (Char.CH /= NullChar) THEN CHaR.STATE := ALLELSE;
END IF;
    CASE ToKeN.STATE is
      WHEN DELIM =>  -- token.state
        CASE CHaR.STATE is
          WHEN DELIM => 
-- NULL char is a special delimiter because it will
-- immediately cause a return even if there is no token yet,
-- i.e., the token is only delimiters.  This is because of
-- the NULL char is the string terminater for general strings
-- and especially for environment strings, for which this
-- TOKENIZE module was originally written. *)
                   IF CHAR.CH = NullChar THEN EXIT; END IF;
          WHEN OP => 
                     ToKeN.STATE := OP;
                     Token.uStr := Token.uStr & Char.Ch;
                     IF LENGTH(Token.uStr) > TKNMAXSIZ THEN
                       RAISE token_too_long;
                     END IF;
          WHEN DGT => 
                     Token.uStr := Token.uStr & Char.Ch;
                     ToKeN.STATE := DGT;
                     TOKEN.SUM := ORDCH - ASCZERO;
          WHEN ALLELSE => 
                     Token.uStr := Token.uStr & Char.Ch;
                     ToKeN.STATE := ALLELSE;
                     QUOFLG := (Char.CH = SQUOTE) OR (Char.CH =
DQUOTE);
                     IF QUOFLG THEN
                       QUOCHR := Char.CH;
                     ELSE
                       IF LENGTH(Token.uStr) > TKNMAXSIZ THEN
                         RAISE token_too_long;
                       END IF; -- if token too long
                       Token.SUM := ORDCH;
                     END IF; -- QUOFLG
        END CASE; -- Of Char.State
      WHEN OP => -- token.state
        CASE CHaR.STATE is
          WHEN DELIM =>
                       EXIT;
          WHEN OP =>
                    IF LENGTH(Token.uStr) > OPMAXSIZ THEN
                      RAISE token_too_long;
                    END IF;
                    Token.uStr := Token.uStr & Char.CH;
          WHEN DGT =>
                   IF (Element(Token.uStr,LENGTH(Token.uStr)) = '+')
OR
                     (Element(Token.uStr,LENGTH(Token.uStr)) = '-')
THEN
                     IF LENGTH(Token.uStr) = 1 THEN
                       IF ELEMENT(Token.uStr,1) = '-' THEN NEGATV :=
TRUE; END IF;
                       ToKeN.STATE := DGT;
-- OVERWRITE ARITHMETIC SIGN CHARACTER
                       Token.uStr := Null_Unbounded_String;
                       Token.uStr := Token.uStr & Char.CH;
                       Token.SUM := ORDCH - ASCZERO;
                     ELSE  -- TOKEN length > 1 SO MUST FIRST RETURN OP
                       UNGETCHR; -- (* UNGET THIS DIGIT CHAR *)
                       UNGETCHR; -- (* UNGET THE ARITH SIGN CHAR *)
                       Len := LENGTH(Token.uStr);
-- SO DELIMCH CORRECTLY RETURNS THE ARITH SIGN CHAR
                       Char.CH := Element(Token.uStr,Len); 
-- del last char of the token which is the sign character
                       Token.uStr := Delete(Token.uStr,Len,Len); 
                       EXIT;
                     END IF; -- if length of the token = 1
                   ELSE -- IF have a sign character
                     UNGETCHR;
                     EXIT;
                   END IF; -- If have a sign character
          WHEN ALLELSE =>
                   UNGETCHR;
                   EXIT;
        END CASE; -- Char.State
      WHEN DGT => -- tokenstate
        CASE CHaR.STATE is
          WHEN DELIM => EXIT;
          WHEN OP =>
                    UNGETCHR;
                    EXIT;
          WHEN DGT =>
                    Token.uStr := Token.uStr & Char.CH;
                    Token.SUM := 10*Token.SUM + ORDCH - ASCZERO;
          WHEN ALLELSE => 
                         UNGETCHR;
                         EXIT;
        END CASE; -- Char.State
      WHEN ALLELSE => -- tokenstate
        CASE CHaR.STATE is
          WHEN DELIM =>
--  Always exit if get a NULL char as a delim.  A quoted string can
-- only get here if CH is NULL.
                       EXIT;
          WHEN OP =>
                    UNGETCHR;
                    EXIT;
          WHEN DGT =>
                     IF LENGTH(Token.uStr) > TKNMAXSIZ THEN
                       RAISE token_too_long;
                     END IF; -- if token too long
                     Token.uStr := Token.uStr & Char.CH;
                     Token.SUM := Token.SUM + ORDCH;
          WHEN ALLELSE =>
                     IF Char.CH = QUOCHR THEN
                       QUOFLG := FALSE;
                       CHaR.STATE := DELIM; 
                       EXIT;
                     ELSE
                       IF LENGTH(Token.uStr) > TKNMAXSIZ THEN
                         RAISE token_too_long;
                       END IF; -- if token too long
                       Token.uStr := Token.uStr & Char.CH;
                       Token.SUM := Token.SUM + ORDCH;
                     END IF; -- if char is a quote char
        END CASE; --  Char.State
    END CASE; -- of Token.State
  END LOOP; -- to process characters
  Token.DELIMCH    := Char.CH;
  Token.DELIMSTATE := CHaR.STATE;
  IF (ToKeN.STATE = DGT) AND NEGATV THEN Token.SUM := -Token.SUM; END
IF;
--  For OP tokens, must return the opcode as the sum value.  Do this
--  by calling GETOPCODE.
  IF ToKeN.STATE = OP THEN
    Token.SUM := GetOpCode(Token);
  END IF;
END GETTKN;

BEGIN  -- main package body routine.
  HOLDCURPOSN := 0;  -- probably not needed in Ada.
  HOLDTKNBUF := Null_unbounded_string; -- looks like Ada automatically
init's all declarations to either 0 or null, as suits the data type
  InitFSAArray;
END tokenizea;



with tokenizea; use tokenizea;
Procedure testtokenizea is

  subType Str255Type is String(1..256);

  INBUF,s : Str255type;
  Token   : TokenType;
  Char    : CharType;
  I,J     : INTEGER;
  Last    : Natural;
  L       : LONG_INTeger;
  CH      : CHARacter;
  EOL     : Boolean;

BEGIN
    Put(" Input line : ");
    Get_Line(s,Last);
    New_line;
    I := s'last;
    Put(" Number of characters read is "); Put(Last);
    Put(".  Value of s'last is "); Put(I);
    INI1TKN(s(1..Last));
    LOOP
      GETTKN(TOKEN,EOL);
      Put(To_String(TOKEN.uStr));
      put(", token.state = ");
      Put(FSATyp'Image(ToKeN.STATE));
      Put(", sum=");
      Put(Token.Sum);
      Put(", DELIMCH= ");
      Put(Token.DELIMCH);
      Put(", DELIMSTATE= ");
      Put(FSATyp'Image(Token.DELIMSTATE));
      New_Line;
      EXIT When EOL;
    END LOOP; -- getting subsequent tokens on same line
END testtokenizea;



Thanks in advance

--Rob


  reply	other threads:[~2014-02-15  0:46 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-02-14 12:38 confusing string error agent
2014-02-14 13:03 ` Jacob Sparre Andersen
2014-02-15  0:46   ` agent [this message]
2014-02-15  1:50     ` adambeneschan
2014-02-15  8:41       ` Simon Wright
2014-02-15  1:57     ` adambeneschan
2014-02-15  9:33     ` Simon Wright
2014-02-15 12:53       ` agent
2014-02-15 16:58         ` adambeneschan
2014-02-15 18:29           ` Simon Wright
2014-02-17 12:57             ` agent
2014-02-15 13:15       ` agent
2014-02-15 17:56         ` Jeffrey Carter
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox