Nyxynyx
Nyxynyx

Reputation: 63639

Using Python to Parse a File for Nested Loops

Currently Python reads each line of a file and executes a function doStep(). This function is passed whatever is on the line being read.

data.txt

a
b
c
b

read.py

fin = open('data.txt')
for step in fin:
    doStep(step)

Python will then execute

doStep(a)
doStep(b)
doStep(c)
doStep(b)

Question: If I want to define nested loops in data.txt, how should it be defined and parsed? The nesting and number of loop iterations should be defined in data.txt

For example, by reading data.txt I want to loop this 5 times

doStep('a')
doStep('b')
doStep('c')

and loop this 10 times

doStep('x')
doStep('y')
doStep('z')

and repeat everything 3 times (nesting).

Upvotes: 1

Views: 1218

Answers (5)

enthus1ast
enthus1ast

Reputation: 2109

Instead of an data.txt file you could use a normal data.py file. There you could import the routines from your read.py and executes the funktions/methodes with all the python magic.

Upvotes: 1

ndpu
ndpu

Reputation: 22561

You can place iteration number at first in line and data after it:

data.txt:

5, a, b, c
10, x, y, z

and use split to parse string:

with open('data.txt') as fin:
    for line in fin:
        l = line.split(', ')
        n, steps = l[:1], l[1:]
        for _ in range(n):
            for step in steps:
                doStep(step)

Upvotes: 1

Samy Arous
Samy Arous

Reputation: 6814

The easiest way to implement a loop, would be to do something as easy as a label/loop operation. I would use a syntax which does not conflict with your data.

.. label1
a
b
c
-- label1 5
d
.. label2
x
y
z
-- label2 10

While reading your file I would keep track of the current position in file and keep track of all the labels. A stack can be used to hold the counters for each loop (handling nested loops).

When a loop is found, if the stack is empty put the number of iteration and the loop position on it and seek back to the label position. If the stack is not empty, pop the last value and decrease it. if it's not 0, put it back on the stack.

Upvotes: 1

Bach
Bach

Reputation: 6217

This is just an example, but there are many things of doing that.

Data file:

@5
a
b
c
@;
@10
x
y
z
@;

Python code:

times = None
buffer = []
fin = open('data.txt')
for line in fin:
    if line[0] == '@':
        if line[1] == ';':
            for step in buffer * times:
                doStep(step)
            times = None
            buffer = []
            continue
        times = int(line[1:])
        continue
    if times:
        buffer.append(line)
    else:
        doStep(line)

This solution is much worse in general than parsing, but it still a very simple (example) solution for a very simple task (unless you wish to generalize it, it may do).

Upvotes: 1

Joe
Joe

Reputation: 47609

You have a simple grammar in your file, currently (<item>\n)*. To parse this is easy, you just loop line by line.

You now want to increase the complexity of the grammar to include loops. How you do this is up to you. You might want to include a command which says 'jump to line number n' or some kind of recursive grammar which includes repetition.

Start by reading about EBNF. Then read about writing a simple parser. Yours will be much simpler than that example.

Your grammar might look like:

file = file_item*
file_item = single_item | repeated_items
repeated_items = single_item*
single_item = [a-z]*

Alternatively, you can define your own data structures (for example as Python classes) which represent repetitions, and serialise that (e.g. with pickle). You can then deserialise and 'play back' your data structures to retrieve the output.

Upvotes: 1

Related Questions