On 29/06/2019 14:39, josé mariano wrote:
Dear all,
I'm sure that this subject has been addressed many times before on this forum,
but my poor knowledge of English and of computer jargon and concepts results on
not being able to find the answer i'm looking for when I search the forum.
So here is my problem: I have this open source project for the scientific
community were i want to duplicate an old MS-DOS application written in
Fortran. I don't have the source code. The idea is to re-write the software in
Python. Originally, the old application would would need to input files: one
config file, written with a specific format (see below) and a second one, the
so-called scrip file, that defines the sequence of operations to be performed
by the main software, also written in a specific format.
Is there any way you can get the source code? Can you track down the
original author? Are there old backups?
That might eliminate the need for rewriting, and, in any case, would
make it so much easier to be sure you're doing the right thing and not
missing something.
To make the transition to the new application as painless as possible to the
users, because most of them have their collection of scrips (and settings)
developed over the years and are not willing to learn a new script language, I
would like to make the new app 100% compatible with the old input files.
Obviously. Make sure you have tests, tests, and more tests. If there's
documentation, use it, but don't trust it.
That's assuming there are loads of old scripts, that just continuing to
use the old program is not an option. DOSbox to the rescue?
Another option might be to write a script that parses the old files and
converts them to something more friendly to your infrastructure, such as
YAML config files and Python scripts. This has two benefits:
(1) a human can easily check the result. If there are some
incompatibilities, they'll be easier to spot. If the script misses
something, the user can add it in.
(2) it might be easier to add new features later
It is a more complex and less user-friendly solution, though.
The operation of the new software would be like this: From the shell, run
"my_new_software old_script_file.***". The new software would load the
old_script, parse it (?), set the internal variables, load the script and run it.
So, to get to my questions:
- To load and read the config file I need a parser, right? Is their a parser
library where we can define the syntax of the language to use? Are there better
(meaning easier) ways to accomplish the same result?
You need to parse the file, obviously. Python is good for this sort of
thing. str.split() and the re module are your friends. The format looks
reasonably simple, so I'd just parse it into a simple data structure
with the basic tools Python provides.
- For the interpretation of the script file, I don't have any clue how to
this... One important thing, the script language admits some simple control
flow statements like do-wile, again written using a specific sintax.
From the look of it, it's one instruction per line, and the first word
of the line is, in some sense, a command? In this case, one way I can
think of to run it would be an interpreter structured something like this:
class ScriptRunner:
def __init__(self, config, script):
self._variables = {}
self._config = config
self._script_lines = []
for line in script.split('\n'):
line = line.strip()
if line.startswith('!'):
#comment
continue
cmd, *args = line.split()
self._script_lines.append((cmd.lower(), args))
def run_script(self):
self._script_iter = iter(self._script_lines)
while True:
try:
cmd, args = next(self._script_iter)
self.dispatch(cmd, args)
except StopIteration:
return
def dispatch(self, cmd, args):
method_name = f'_cmd_{cmd}'
method = getattr(self, method_name)
method(args)
def _cmd_set(self, args):
varname, value = args
self._variables[varname] = value
def _cmd_while(self, loop_args):
# check condition or something
loop_body = []
while True:
try:
cmd, args = next(self._script_iter)
# MAGIC
if cmd == 'endwhile':
break
else:
loop_body.append((cmd, args))
except StopIteration:
raise RuntimeError('loop not ended')
while condition_is_met:
for cmd, args in loop_body:
# otherwise, just carry on executing the loop body
self.dispatch(cmd, args)
In any case, there are three things you need to keep track of:
variables, where in the script you are, and what control structure
currently "has control".
In this stub, I've used the object for holding program state (variables
that is), a Python iterator to hold the program counter, and the Python
stack to hold the control flow information. There are other ways you can
do it, of course. If the language allows for things like subroutines or
GOTO, things get a little more complicated
There are also tools for this kind of thing. The traditional (UNIX)
choice would be lex & yacc, but I think there are Python parser
libraries that you could use. Others might mention them. I'd tend to say
they're overkill for your purpose, but what do I know.
Thanks a lot for the help and sorry for the long post.
Mariano
Example of a config (settings) file
========================
.....
CONDAD -11
BURAD2 4 SALT1 1.0 KNO3
ELEC5 -2.0 mV 400 58 0. 0
.....
Example of a script
===================
!Conductivity titration
cmnd bur1 f
set vinit 100
set endpt 2000
set mvinc 20
set drftim 1
set rdcrit cond 0.5 per_min
set dosinc bur1 0.02 1000
set titdir up
titratc cond bur1
--
https://mail.python.org/mailman/listinfo/python-list