about CASE string OF

Programming language questions
Post Reply
luowy
Posts: 87
Joined: Thu Dec 17, 2015 1:32 pm

about CASE string OF

Post by luowy »

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.
User avatar
adimetrius
Posts: 68
Joined: Sun Aug 04, 2019 1:02 pm

Re: about CASE string OF

Post by adimetrius »

luowy,
What specifically do you think is ugly in that text - I mean with a cascading IF..ELSIF..END?
luowy
Posts: 87
Joined: Thu Dec 17, 2015 1:32 pm

Re: about CASE string OF

Post by luowy »

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.
User avatar
Ivan Denisov
Posts: 362
Joined: Tue Sep 17, 2013 12:21 am
Location: Krasnoyarsk, Russia

Re: about CASE string OF

Post by Ivan Denisov »

I think, that it is good and can be legal. Does this syntax generates faster code? This should be possible.
luowy
Posts: 87
Joined: Thu Dec 17, 2015 1:32 pm

Re: about CASE string OF

Post by luowy »

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.
cfbsoftware
Posts: 55
Joined: Wed Sep 18, 2013 10:06 pm
Contact:

Re: about CASE string OF

Post by cfbsoftware »

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
luowy
Posts: 87
Joined: Thu Dec 17, 2015 1:32 pm

Re: about CASE string OF

Post by luowy »

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: 87
Joined: Thu Dec 17, 2015 1:32 pm

Re: about CASE string OF

Post by luowy »

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 728 times
User avatar
Ivan Denisov
Posts: 362
Joined: Tue Sep 17, 2013 12:21 am
Location: Krasnoyarsk, Russia

Re: about CASE string OF

Post by Ivan Denisov »

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.
Post Reply