grammar.py: Add grammar_fix_list_recursion()

This replaces the mechanism to always construct lists with a leading
empty rule. This leads to many RR-conflicts, so this empty rule is omitted
and later added conditionally by grammar_fix_list_recursion(). Sadly,
the condition is bollocks, since it's always true.

Signed-off-by: Jan Lindemann <jan@janware.com>
This commit is contained in:
Jan Lindemann 2017-11-06 12:01:06 +01:00
commit 930efae39f

View file

@ -322,6 +322,9 @@ class State:
return None return None
return self.things[-1] return self.things[-1]
def is_optional(self):
return self.in_list() or self.in_option()
class Symbol: class Symbol:
def __init__(self, token, tp = None, rules = None): def __init__(self, token, tp = None, rules = None):
@ -674,7 +677,8 @@ def grammar_unroll_lists(grammar):
listrule.insert(0, RuleComp('(', t_grammar)) listrule.insert(0, RuleComp('(', t_grammar))
listrule.insert(0, RuleComp(name, t_target_lang)) # enable iteration listrule.insert(0, RuleComp(name, t_target_lang)) # enable iteration
listrule.append(RuleComp(')', t_grammar)) listrule.append(RuleComp(')', t_grammar))
p = Symbol(name, rules=[[], listrule]) #p = Symbol(name, rules=[[], listrule])
p = Symbol(name, rules=[listrule])
#p = Symbol(name) #p = Symbol(name)
#p.rules = [ [], listrule ] #p.rules = [ [], listrule ]
listrule = [] listrule = []
@ -1666,6 +1670,24 @@ def grammar_create_h(grammar, opts):
return out return out
def grammar_fix_list_recursion(grammar):
dead_end = set()
for kl, l in grammar.iteritems():
if not re.match('^list_', kl):
continue
for ks, s in grammar.iteritems():
for rule in s.rules:
state = State()
for c in rule:
state.update(c.token, c.line)
if c.token == kl:
if state.is_optional():
continue
dead_end.add(c.token)
for t in dead_end:
grammar[t].rules.insert(0, [])
return grammar
class GrammarCmd(jwutils.Cmd): class GrammarCmd(jwutils.Cmd):
def __init__(self, name, help): def __init__(self, name, help):
@ -1702,6 +1724,7 @@ class GrammarCmd(jwutils.Cmd):
grammar = grammar_unroll_alternatives(grammar) grammar = grammar_unroll_alternatives(grammar)
if args.unroll_options: if args.unroll_options:
grammar = grammar_unroll_options(grammar) grammar = grammar_unroll_options(grammar)
grammar = grammar_fix_list_recursion(grammar)
#grammar['logical_expression'].dump(ERR) #grammar['logical_expression'].dump(ERR)
if len(args.check_symbols): if len(args.check_symbols):
check_symbols = [] check_symbols = []