How to get textX model to treat fifth test case as separate line

50 Views Asked by At

Sample code that is failing when adding the fifth test line to the input variable. Leave the fifth line out and the model works.

from textx import metamodel_from_str

mm = metamodel_from_str('''
File:
    lines+=Line;

Line:
    startwords=Startwords
    dirp=DirPhrase?
    words=Words?
    command=Commands?
;

Startwords: 
    (StartKeywords | Signs)?;

StartKeywords:
    'bag';

Commands:
    ('sleep over'|'walk');

Words:
    words+=Word?;

Word:
    !DirType !Commands ID;

Signs:
    signs+=Sign;

Sign:
    !Commands !StartKeywords Word;

DirPhrase:
    dirtyp=DirType
    dir=Dir
;

DirType:
    'fast';

Dir:
    ('left'|'right')+;

''')

input = '''
bag  sun kiss  sleep over
animal walk
big horse walk
big white cow fast left
little black cow fast right
'''
#little black cow fast right


model = mm.model_from_str(input, debug=False)

l = model.lines[0]
assert l.startwords == 'bag'
assert l.words.words == ['sun', 'kiss']
assert l.command == 'sleep over'

l = model.lines[1]
assert l.startwords.signs == ['animal']
assert l.words == None
assert l.command == 'walk'

l = model.lines[2]
assert l.startwords.signs == ['big', 'horse']
assert l.words == None
assert l.command == 'walk'

l = model.lines[3]
assert l.startwords.signs == ['big', 'white', 'cow']
assert l.words == None
assert l.command == None
assert l.dirp.dirtyp == 'fast'
assert l.dirp.dir == 'left'

if len(model.lines) == 5:
    l = model.lines[4]
    assert l.startwords.signs == ['little', 'black', 'cow']
    assert l.words == None
    assert l.command == None
    assert l.dirp.dirtyp == 'fast'
    assert l.dirp.dir == 'right'

What is happening is somehow the fifth input line is getting read into l.words during the fourth input line processing. The assert there fails because l.words is supposed to be None. I have tried using [eolterm] modifier however that created other errors.

1

There are 1 best solutions below

3
On

Solved the issue using [eolterm] in the following section of code from this

Words:
    words+=Word?;

to this

Words:
    words+=Word[eolterm];

[eolterm] does not like the ? so had to remove that. With that gone it works like a champ.