about CASE string OF

Programming language questions

about CASE string OF

Postby luowy » Sun Aug 11, 2019 3:57 pm

Is anyone interested in CASE string OF ?
e.g.
Code: Select all
MODULE ObxTest;
   IMPORT Log := StdLog;
   PROCEDURE Do* ();
      VAR str: ARRAY 12 OF CHAR;
   BEGIN
      str := "hello5";
      CASE str OF
      | "hello", "hello2", 'book':
         Log.String('world'); Log.Ln;
      | "world":
         Log.String('hello'); Log.Ln;
       (*ELSE*)
      END;
   END Do;

END ObxTest.


I find the MasterColorScanner has such code
Code: Select all
   PROCEDURE (scanner: Scanner) GetAttributes (IN str: ARRAY OF CHAR):
      TextModels.Attributes, NEW;
      VAR a: TextModels.Attributes;
   BEGIN
      a := scanner.syntax.Ident;
      
      IF (str$ = "PROCEDURE") THEN
         a := scanner.syntax.KeyWord;
         state := regular;
         (* интерпретировать звездочку как маркер экспорта *)
         stateExport := exportCare;
         
      ELSIF (str$ = "VAR") OR (str$ = "TYPE") OR (str$ = "CONST")THEN
         a := scanner.syntax.KeyWord;
         state := regular;
         (* интерпретировать звездочку как маркер экспорта *)
         stateExport := exportCare;
         
      ELSIF(str$ = "BEGIN")THEN
         a := scanner.syntax.KeyWord;
         state := regular;
         stateExport := regular;
         
      ELSIF(str$ = "END")THEN
         a := scanner.syntax.KeyWord;
         
         IF state = declare THEN
            stateExport := exportCare;
         ELSE
            state := regular;
         END;
      
      ELSIF
         (str$ = "MODULE")
         OR (str$ = "DEFINITION") OR (str$ = "IMPORT")
         OR (str$ = "CLOSE") OR (str$ = "ARRAY")
         OR (str$ = "IF") OR (str$ = "THEN")
         OR (str$ = "ELSIF") OR (str$ = "ELSE") OR (str$ = "REPEAT")
         OR (str$ = "UNTIL") OR (str$ = "WHILE") OR (str$ = "DO")
         OR (str$ = "LOOP") OR (str$ = "FOR") OR (str$ = "TO") OR (str$ = "BY")
         OR (str$ = "POINTER") OR (str$ = "OF") OR (str$ = "CASE")
         OR (str$ = "WITH") OR (str$ = "MENU") OR (str$ = "SEPARATOR")
      THEN
         a := scanner.syntax.KeyWord;
         state := regular;
         
      ELSIF (str$ = "RECORD") 
      THEN
         a := scanner.syntax.KeyWord;
         state := regular;
         IF stateExport = declare THEN
            (* разблокируем для выделения жирным идентификаторов в полях записей *)
            stateExport := exportCare
         END
         
      ELSIF (str$ = "RETURN") OR (str$ = "EXIT") OR (str$ = "HALT")
         OR (str$ = "ASSERT")
      THEN
         a := scanner.syntax.Exit;
         state := regular;
         
      ELSIF (str$ = "BYTE") OR (str$ = "CARDINAL") OR (str$ = "CHAR")
         OR (str$ = "INTEGER") OR (str$ = "LONGCARD") OR (str$ = "LONGINT")
         OR (str$ = "REAL") OR (str$ = "BOOLEAN") OR (str$ = "SET") OR (str$ = "STRING")
         OR (str$ = "SHORTCARD") OR (str$ = "SHORTCHAR") OR (str$ = "SHORTINT")
         OR (str$ = "SHORTREAL") OR (str$ = "LONGREAL") OR (str$ = "HUGEINT")
         OR (str$ = "LONGSET") OR (str$ = "ANYPTR") OR (str$ = "ANYREC")
      THEN
         a := scanner.syntax.PrimeType;
         state := regular;
         
      ELSIF (state = systemDot) & ((str$ = "ADR") OR (str$ = "LSH")
            OR (str$ = "ROT") OR (str$ = "TYP") OR (str$ = "VAL") OR (str$ = "GET")
            OR (str$ = "PUT") OR (str$ = "MOVE")
            OR (str$ = "SIZE") OR (str$ = "BIT") OR (str$ = "COPY")) (* O7 *)
      THEN
         a := scanner.syntax.SystemMod;
         state := regular;
         
      ELSIF (str$ = "OR") OR (str$ = "DIV") OR (str$ = "MOD") OR (str$ = "DIV0")
         OR (str$ = "REM0") OR (str$ = "ORD") OR (str$ = "CHR") OR (str$ = "ODD")
         OR (str$ = "MAX") OR (str$ = "MIN") OR (str$ = "INC") OR (str$ = "DEC")
         OR (str$ = "INCL") OR (str$ = "EXCL") OR (str$ = "LEN") OR (str$ = "ABS")
         OR (str$ = "BITS") OR (str$ = "SHORT") OR (str$ = "SIZE") OR (str$ = "LONG")
         OR (str$ = "ENTIER") OR (str$ = "CAP") OR (str$ = "ASH") OR (str$ = "IS")
         OR (str$ = "IN") OR (str$ = "OUT") OR (str$ = "COPY") OR (str$ = "FLOOR")
         OR (str$ = "FLT") OR (str$ = "ASR") OR (str$ = "LSL") OR (str$ = "ROR")
      THEN
         a := scanner.syntax.Oper;
         state := regular;
         
      ELSIF (str$ = "NEW") OR (str$ = "FINALIZE") OR (str$ = "ABSTRACT")
         OR (str$ = "EXTENSIBLE") OR (str$ = "LIMITED") OR (str$ = "EMPTY") OR (str$ = "DISPOSE")
      THEN
         a := scanner.syntax.New;
         state := regular;
         
      ELSIF (str$ = "NIL") OR (str$ = "TRUE") OR (str$ = "FALSE")
         OR (str$ = "INF")
      THEN
         a := scanner.syntax.Const;
         state := regular;
         
      ELSIF (str$ = "SYSTEM") THEN
         a := scanner.syntax.SystemMod;
         state := system; (* после SYSTEM чувствуем SIZE иначе *)
            
      END;
      
      RETURN a;
   END GetAttributes;

This code is a bit mess,
many modern languages have the syntax of "case/switch string" , but CP not;
I have done a simple patch for this syntax,but not sure our community like it or not.
wellcome someone who interesting it to test and improve it;

luowy
Last edited by luowy on Mon Aug 19, 2019 7:15 am, edited 1 time in total.
luowy
 
Posts: 42
Joined: Thu Dec 17, 2015 1:32 pm

Re: about CASE string OF

Postby adimetrius » Sun Aug 11, 2019 5:13 pm

luowy,
What specifically do you think is ugly in that text - I mean with a cascading IF..ELSIF..END?
User avatar
adimetrius
 
Posts: 3
Joined: Sun Aug 04, 2019 1:02 pm

Re: about CASE string OF

Postby luowy » Mon Aug 12, 2019 3:37 am

I mean a bit mess , sometimes CASE is more readable and writable than IF... ESLIF ....
e.g.
Code: Select all
      IF (str$ = "PROCEDURE") THEN
         a := scanner.syntax.KeyWord;
         state := regular;
         (* интерпретировать звездочку как маркер экспорта *)
         stateExport := exportCare;
         
      ELSIF (str$ = "VAR") OR (str$ = "TYPE") OR (str$ = "CONST")THEN
         a := scanner.syntax.KeyWord;
         state := regular;
         (* интерпретировать звездочку как маркер экспорта *)
         stateExport := exportCare;
         
      ELSIF(str$ = "BEGIN")THEN
         a := scanner.syntax.KeyWord;
         state := regular;
         stateExport := regular;
         
      ELSIF(str$ = "END")THEN
         a := scanner.syntax.KeyWord;
         
         IF state = declare THEN
            stateExport := exportCare;
         ELSE
            state := regular;
         END;
     
      ELSIF
         (str$ = "MODULE")
         OR (str$ = "DEFINITION") OR (str$ = "IMPORT")
         OR (str$ = "CLOSE") OR (str$ = "ARRAY")
         OR (str$ = "IF") OR (str$ = "THEN")
         OR (str$ = "ELSIF") OR (str$ = "ELSE") OR (str$ = "REPEAT")
         OR (str$ = "UNTIL") OR (str$ = "WHILE") OR (str$ = "DO")
         OR (str$ = "LOOP") OR (str$ = "FOR") OR (str$ = "TO") OR (str$ = "BY")
         OR (str$ = "POINTER") OR (str$ = "OF") OR (str$ = "CASE")
         OR (str$ = "WITH") OR (str$ = "MENU") OR (str$ = "SEPARATOR")
      THEN
         a := scanner.syntax.KeyWord;
         state := regular;
       

same code as above
Code: Select all
     CASE  str OF
     |"PROCEDURE":
        a := scanner.syntax.KeyWord;
         state := regular;
         (* интерпретировать звездочку как маркер экспорта *)
         stateExport := exportCare;
         
     |"VAR",  "TYPE",  "CONST":
         a := scanner.syntax.KeyWord;
         state := regular;
         (* интерпретировать звездочку как маркер экспорта *)
         stateExport := exportCare;
         
      |"BEGIN":
         a := scanner.syntax.KeyWord;
         state := regular;
         stateExport := regular;
         
     |"END":
         a := scanner.syntax.KeyWord;
         
         IF state = declare THEN
            stateExport := exportCare;
         ELSE
            state := regular;
         END;
     
     | "MODULE","DEFINITION",  "IMPORT",  "CLOSE",  "ARRAY",
         "IF",  "THEN","ELSIF",  "ELSE",  "REPEAT","UNTIL",  "WHILE",
         "DO", "LOOP",  "FOR",  "TO",  "BY", "POINTER",  "OF",  "CASE",
        "WITH",  "MENU",  "SEPARATOR":

         a := scanner.syntax.KeyWord;
         state := regular;
         
Last edited by luowy on Mon Aug 19, 2019 7:17 am, edited 1 time in total.
luowy
 
Posts: 42
Joined: Thu Dec 17, 2015 1:32 pm

Re: about CASE string OF

Postby Ivan Denisov » Mon Aug 12, 2019 4:01 am

I think, that it is good and can be legal. Does this syntax generates faster code? This should be possible.
User avatar
Ivan Denisov
 
Posts: 271
Joined: Tue Sep 17, 2013 12:21 am
Location: Krasnoyarsk, Russia

Re: about CASE string OF

Postby luowy » Mon Aug 12, 2019 7:00 am

Ivan Denisov wrote: Does this syntax generates faster code?
no, as same as the if..elsif..end;
I have writed an improved one,output like:
Code: Select all
   PROCEDURE Keyword(VAR name: ARRAY OF CHAR; VAR sym,c: BYTE);
   BEGIN
      sym:=ident;
      CASE name[0] OF
      | "A":
         IF name = "ARRAY" THEN sym := array
         END
      | "B":
         IF name = "BEGIN" THEN sym := begin
         ELSIF name = "BY" THEN sym := by
         END
      | "C":
         IF name = "CASE" THEN sym := case
         ELSIF name = "CONST" THEN sym := const
         ELSIF name = "CLOSE" THEN sym := close
         END
      | "D":
         IF name = "DO" THEN sym := do
         ELSIF name = "DIV" THEN sym := div
         END
      | "E":
         IF name = "END" THEN sym := end
         ELSIF name = "ELSE" THEN sym := else
         ELSIF name = "ELSIF" THEN sym := elsif
         ELSIF name = "EXIT" THEN sym := exit
         END
      | "F": IF name = "FOR" THEN sym := for END
      | "I":
         IF name = "IF" THEN sym := if
         ELSIF name = "IN" THEN sym := in
         ELSIF name = "IS" THEN sym := is
         ELSIF name = "IMPORT" THEN sym := import
         END
      | "L":
         IF name = "LOOP" THEN sym := loop
         END
      | "M":
         IF name = "MOD" THEN sym := mod
         ELSIF name = "MODULE" THEN sym := module
         END
      | "N": IF name = "NIL" THEN sym := nil END
      | "O":
         IF name = "OR" THEN sym := or
         ELSIF name = "OF" THEN sym := of
         ELSIF name = "OUT" THEN sym := out
         END
      | "P":
         IF name = "PROCEDURE" THEN sym := procedure
         ELSIF name = "POINTER" THEN sym := pointer
         END
      | "R":
         IF name = "RECORD" THEN sym := record
         ELSIF name = "REPEAT" THEN sym := repeat
         ELSIF name = "RETURN" THEN sym := return
         END
      | "T":
         IF name = "THEN" THEN sym := then
         ELSIF name = "TO" THEN sym := to
         ELSIF name = "TYPE" THEN sym := type
         END
      | "U": IF name = "UNTIL" THEN sym := until END
      | "V": IF name = "VAR" THEN sym := var END
      | "W":
         IF name = "WHILE" THEN sym := while
         ELSIF name = "WITH" THEN sym := with
         END
      ELSE
      END;
      IF sym = ident THEN c:=idents; ELSE c :=keywords  END;
   END Keyword;
But its implementation is a bit complicated, and Its output code size is a bit larger, I gave up it.
luowy
 
Posts: 42
Joined: Thu Dec 17, 2015 1:32 pm

Re: about CASE string OF

Postby cfbsoftware » Mon Aug 12, 2019 11:52 am

I also use the technique:
Code: Select all
      CASE name[0] OF
      | "A":
         IF name = "ARRAY" THEN sym := array
etc.

in the Astrobe compilers. It is the most efficient of the suggestions here. It is also used in the BlackBox compiler (Dev\CPS.odc) and John Gough's Gardens Point Component Pascal compiler. Look for Procedure CheckLiteral:

https://github.com/k-john-gough/gpcp/bl ... PascalS.cp

However, Wirth uses a different technique altogether to search for keywords in his latest Oberon compiler. He uses the length of the string to limit the number of items that need to be searched.

Look for the uses and definition of the function EnterKW which creates the keyword table and the procedure Identifier that searches it:

https://people.inf.ethz.ch/wirth/Projec ... RS.Mod.txt
cfbsoftware
 
Posts: 37
Joined: Wed Sep 18, 2013 10:06 pm

Re: about CASE string OF

Postby luowy » Mon Aug 12, 2019 4:48 pm

cfbsoftware wrote:Wirth uses a different technique altogether to search for keywords in his latest Oberon compiler. He uses the length of the string to limit the number of items that need to be searched.
thanks, I will try .
but first I need to understand the condition alogrithm and pseudo output of the "useTree", "useTable".
luowy
 
Posts: 42
Joined: Thu Dec 17, 2015 1:32 pm

Re: about CASE string OF

Postby luowy » Fri Aug 16, 2019 10:16 am

the improved one has finished, almost same size and speed as handwritten code,Welcome to test and feedback.
Attachments
StringCase.zip
(44.41 KiB) Downloaded 18 times
luowy
 
Posts: 42
Joined: Thu Dec 17, 2015 1:32 pm

Re: about CASE string OF

Postby Ivan Denisov » Tue Aug 20, 2019 11:29 am

luowy wrote:the improved one has finished, almost same size and speed as handwritten code,Welcome to test and feedback.

Speed is very good and syntax is better. IMHO, this can be the part of BlackBox.
User avatar
Ivan Denisov
 
Posts: 271
Joined: Tue Sep 17, 2013 12:21 am
Location: Krasnoyarsk, Russia


Return to Component Pascal

Who is online

Users browsing this forum: No registered users and 0 guests

cron