diff --git a/tools/python/jwutils/grammar.py b/tools/python/jwutils/grammar.py index 51e83dc..c775e65 100644 --- a/tools/python/jwutils/grammar.py +++ b/tools/python/jwutils/grammar.py @@ -322,6 +322,9 @@ class State: return None return self.things[-1] + def is_optional(self): + return self.in_list() or self.in_option() + class Symbol: 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(name, t_target_lang)) # enable iteration listrule.append(RuleComp(')', t_grammar)) - p = Symbol(name, rules=[[], listrule]) + #p = Symbol(name, rules=[[], listrule]) + p = Symbol(name, rules=[listrule]) #p = Symbol(name) #p.rules = [ [], listrule ] listrule = [] @@ -1666,6 +1670,24 @@ def grammar_create_h(grammar, opts): 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): def __init__(self, name, help): @@ -1702,6 +1724,7 @@ class GrammarCmd(jwutils.Cmd): grammar = grammar_unroll_alternatives(grammar) if args.unroll_options: grammar = grammar_unroll_options(grammar) + grammar = grammar_fix_list_recursion(grammar) #grammar['logical_expression'].dump(ERR) if len(args.check_symbols): check_symbols = []