Editorial comments. This file is a part of a request system for a database "Thermal Potentials". We ran statistical mechanical calculations for pure liquids and solutions, and stored the results -- thermal potentials -- in a database. We retrieved the results from the database to compute derived quantities, e.g., energy or free energy or compressibility factor, etc. A previously computed result is also used as a seed (i.e., the initial approximation) for a new statistical mechanical calculation. Thermal potential -- the result of one calculation -- is an array of (typically, 512) floating-point numbers. It is identified by the following keys: the name of the interaction potential (e.g., Hard Spheres or Lennard-Jones); parameters of the potential; the name of the particular calculation method; the name of the OZ equation closure. The underlying database was INES, the hierarchical database with a very complex request syntax. To retrieve one particular thermal potential from the database, we had to submit a request like LENNARD_JONES_SPHERES: DENSITY=0.450,TEMPERATURE=1.349999/ LM METHOD. MS CLOSURE; The punctuation (slashes, commas, etc) are significant. Often we need to retrieve a series of thermal potentials from the database (e.g., to integrate or plot them). Therefore, we would like to specify a request like N ; N or S LENNARD_JONES_SPHERES ; Potential name DENSITY=(0.500000,0.90) ,TEMPERATURE=2.74; ; Parameters of the potential LM METHOD ; Processing method MS CLOSURE, PY CLOSURE ; OZ Equation closure and be able to expand it into LENNARD_JONES_SPHERES: DENSITY=0.500000,TEMPERATURE=2.74/ LM METHOD. MS CLOSURE; LENNARD_JONES_SPHERES: DENSITY=0.500000,TEMPERATURE=2.74/ LM METHOD. PY CLOSURE; LENNARD_JONES_SPHERES: DENSITY=0.90,TEMPERATURE=2.74/ LM METHOD. MS CLOSURE; LENNARD_JONES_SPHERES: DENSITY=0.90,TEMPERATURE=2.74/ LM METHOD. PY CLOSURE; That is, we want to specify _several_ values for the parameters of the potential, several processing method names and several closure names. We would like to compute the direct product and write a sequence of single product request. Such a request expansion is the task of the present code. The code was written ca. 1985. ------------------------------------------------------------------------ # Program TRBBLDRQ # # Data base system "Thermal Potentials" # # # # Function: # # Parse STANDIN and write into file REQS one or several requests # # (several requests if STANDIN specified several values for some # # parameter, several processing method names, etc.) # # # # Input: # # The program is invoked by LINK. # # File STANDIN should contain: # # Record 1: Ignored # # Record 2: Char 'N' or 'S' in pos. 0: Pure liquid or Solution # # Record 3: Name of the potential for the solvent (pure liquid) # # Record 4: PARAMETER=VALUE or (VALUE,...),... # # Record 5: Processing method name,... # # Record 6: Closure name,... # # The request for `solution' contains three more records, describing # # the solute potential. The format of these records is similar # # to that of records 3-6. # # Records 3-6 may contains comments, after ';' # # # # Output: # # R15 = 0 on success # # File REQS contains one or several requests. Each request has # # the form: # # 1 record: Name for the pure solvent potential: # # 2 record: PARAMETER=VALUE,.../ # # 3 record: Processing method name. Closure Name; # # The request for `solution' contains three similar records, # # describing the solute potential. # .BEGIN .CHAR PURE OR SOLUTION; # Pure liquid or solution req # .FILE REQFILE; # Request file # .MODE .ELEM = .STRUCT(.REF.ELEM NEXT, .STRING VALUE ); .REF.ELEM NILEL = .NIL; .REF.ELEM FIRST ELEM := NILEL, CURR ELEM := NILEL; .PROC ENQUE ELEM = (.STRING STR ).VOID: # Create a new .ELEM with the value STR and link it with the others# # Remove trailing spaces from STR # .BEGIN .REF.ELEM ELEM := ( CURR ELEM :=: NILEL ! FIRST ELEM ! NEXT .OF CURR ELEM ) := .HEAP.ELEM; NEXT .OF ELEM := NILEL; CURR ELEM := ELEM; .INT J; .FOR I .FROM .UPB STR .BY -1 .TO 1 .WHILE J:=I; STR[J]=" " .DO .SKIP .OD; VALUE .OF ELEM := STR[1:J] .END; .PROC PARMS ANALYZE = (.STRING STR ).VOID: # This program analyses a string STR of the form: # # PARAMETER= VALUE OR (VALUE,...),... # # For each "PARAMETER" we create two .ELEM's - one for # # "PARAMETER=", the other for "VALUE" or "VALUE, VALUE, ..." # # In case of several values, we drop the enclosing parentheses. # # We keep the commas that separate the values. # # If the string STR contains more than one parameter, we add # # interspersing .ELEM with the value "," # .BEGIN .INT FP:= 1, # Start index for the curr field# CP:= 1; # Current position in STR # .CHAR C := STR[CP]; # Current char of STR # .CHAR CEOD = .REPR 1, # End-of-string character # CALL = .REPR 0; # A `character' that matches any# .PROC RTRAN = (.CHAR CC,.PROC.VOID ACTION,.PROC.VOID LABEL ).VOID: # Implementation of the R-Automaton (cf Glushkov) # # Basically, a Turing machine as a parser # # # # CC - a character to match against the current one # # ACTION - action to do on match # # LABEL - where to go next # .BEGIN .IF C = CC .OR CC = CALL .THEN ACTION; ( CP = .UPB STR ! C := CEOD ! C := STR[ CP +:= 1 ] ); LABEL .FI .END; # Parsing of STR with R-Technology (Turing Machine) # M1: RTRAN("=",.VOID:(ENQUE ELEM(STR[FP:CP])),M2 ); # Search for end# RTRAN(CEOD,ERR1,.SKIP); # of "PARAMETER" # RTRAN(CALL,.VOID:.SKIP,M1); # on char "=" # M2: RTRAN(" ",.VOID:.SKIP,M2); # Search for the start of value # RTRAN("(",.VOID:(FP:=CP+1),M3); # Expect several values # RTRAN(CEOD,ERR2,.SKIP); # No values -- error # RTRAN(CALL,.VOID:(FP:=CP),M4); # A single value # M3: RTRAN(")",.VOID:(ENQUE ELEM(STR[FP:CP-1])),M5); # End of values# RTRAN(CEOD,ERR3,.SKIP); # No closing parenthesis # RTRAN(CALL,.VOID:.SKIP,M3); # Scan through the end of values# M4: RTRAN(",",.VOID:(ENQUE ELEM(STR[FP:CP-1])),M6); # Search for V # RTRAN(CEOD,.VOID:(ENQUE ELEM(STR[FP:CP])),END); # No more # RTRAN(CALL,.VOID:.SKIP,M4); # Scan thru the end # M5: RTRAN(" ",.VOID:.SKIP,M5); # Check what follows ")" # RTRAN(",",.VOID:.SKIP,M6); # If there are more "PARAMETER" # RTRAN(CEOD,.VOID:.SKIP,END); # There shall be nothing more # RTRAN(CALL,ERR4,.SKIP); # Unrecognizable char # M6: RTRAN(CALL,.VOID:(ENQUE ELEM(","); FP:= CP),M1);# Next PARAMETER# END: .SKIP .EXIT ERR1: PRINT(( NL," NO '=' IN STRING",NL,STR,NL, " STARTING POSITION ",FP )); STOP; ERR2: PRINT(( NL," NO VALUE AFTER '=' IN STRING",NL,STR,NL, " STARTING POSITION ",FP )); STOP; ERR3: PRINT(( NL," MISSING ')' IN STRING",NL,STR,NL, " STARTING POSITION ",FP )); STOP; ERR4: PRINT(( NL," UNRECOGNIZABLE CHAR AFTER ')' IN STRING",NL,STR,NL, " STARTING POSITION ",FP )); STOP .END; .PROC OUTPUT = (.REF.ELEM ELEM,.STRING REQS ).VOID: # Recursive procedure to write requests. Requests are assembled # # from .ELEM's and accumulated in the string REQS # .BEGIN .IF ELEM :=: NILEL .THEN # End of chain of REQS - full request# .INT I,J,K; .IF .NOT CHAR IN STRING(":",I,REQS) .OR .NOT CHAR IN STRING("/",J,REQS) .OR .NOT CHAR IN STRING(";",K,REQS) .THEN PRINT(( NL," Invalid REQS string ",NL,REQS )); STOP .FI; PUT(REQFILE,(REQS[1:I],NL,REQS[I+1:J],NL,REQS[J+1:K],NL)); .IF PURE OR SOLUTION = "S" .THEN K +:= 1; .IF .NOT CHAR IN STRING(":",I,REQS[K:.AT K]) .OR .NOT CHAR IN STRING("/",J,REQS[K:.AT K]) .THEN PRINT(( NL," Invalid REQS string ",NL,REQS )); STOP .FI; PUT(REQFILE,(REQS[K:I],NL,REQS[I+1:J],NL,REQS[J+1:],NL)) .FI .ELSE .INT FP := 1, # Starting scan position # CP := 1; # Current scan position # .WHILE CP <= .UPB VALUE .OF ELEM .DO .STRING VAL; ( CHAR IN STRING(",",CP,(VALUE .OF ELEM)[FP:.AT FP]) .AND .UPB VALUE .OF ELEM /= 1 ! VAL := (VALUE .OF ELEM)[FP:CP-1]; CP +:= 1; FP := CP ! VAL := (VALUE .OF ELEM)[FP:]; CP := .UPB VALUE .OF ELEM + 1 ); OUTPUT(NEXT .OF ELEM,REQS+VAL) .OD .FI .END; # Main program # .STRING STR; MAKE TERM(STANDIN,";"); # Start Comment character # READ(( NL,PURE OR SOLUTION,NL,STR,NL )); ENQUE ELEM(STR+":"); # Name of the potential # READ(( STR,NL )); PARMS ANALYZE(STR); ENQUE ELEM("/"); # Parameters of the potential # READ(( STR,NL )); ENQUE ELEM(STR); ENQUE ELEM("."); # Method name(s) # READ(( STR,NL )); ENQUE ELEM(" "+STR); ENQUE ELEM(";"); # Closure name(s) # .IF PURE OR SOLUTION = "N" .THEN .SKIP .ELIF PURE OR SOLUTION /= "S" .THEN PRINT(( NL," Unknown request type" )); STOP .ELSE # Repeat the above for the solute # READ(( STR,NL )); ENQUE ELEM(STR+":"); READ(( STR,NL )); PARMS ANALYZE(STR); ENQUE ELEM("/"); READ(( STR,NL )); ENQUE ELEM(STR); ENQUE ELEM("."); READ(( STR,NL )); ENQUE ELEM(" "+STR); ENQUE ELEM(";") .FI; OPEN(REQFILE,"REQS ",PSOUT CHANNEL); OUTPUT(FIRST ELEM,""); CLOSE(REQFILE) .END