 }
 
 fileprivate extension _STLR.Expression {
-    func rule(with behaviour:Behaviour, and annotations:RuleAnnotations, using symbolTable:SymbolTable<Symbol>)->Rule {
+    func rule(using symbolTable:SymbolTable<Symbol>)->Rule {
         switch self {
         case .sequence(let elements):
-            return elements.sequence(with: behaviour, and: annotations, using: symbolTable)
+            return elements.map({ (element) -> Rule in
+                element.rule(symbolTable: symbolTable)
+            }).sequence
         case .choice(let elements):
-            return elements.choice(with: behaviour, and: annotations, using: symbolTable)
+            return elements.map({ (element) -> Rule in
+                element.rule(symbolTable: symbolTable)
+            }).choice
         case .element(let element):
-            #warning("There is an optimization oppertunity here. If it's a single element with no specific annotations we don't need to wrap in a sequence but can 'merge' and hoist")
-            return [element].sequence(with: behaviour, and: annotations, using: symbolTable)
+            return element.rule(symbolTable: symbolTable)
         }
     }
 }

        return assumed.merge(with: annotations?.ruleAnnotations ?? [:])
    }

    func rule(using symbolTable:SymbolTable<Symbol>)->Rule {
        if symbolTable[hasRule: identifier] {
            return symbolTable[identifier].behaviouralRule
        }
        
        if symbolTable.ast.isLeftHandRecursive(identifier: identifier){
            let rule = BehaviouralRecursiveRule(stubFor: behaviour, with: ruleAnnotations)
            symbolTable[identifier] = Symbol(behaviouralRule: rule)
            rule.surrogateRule = expression.rule(with: behaviour, and: ruleAnnotations, using: symbolTable).reference(behaviour.kind)
            return rule
        } else {
            let rule = expression.rule(with: behaviour, and: ruleAnnotations, using: symbolTable).reference(behaviour.kind)
            symbolTable[identifier] = Symbol(behaviouralRule: rule)
            return rule
        }
    }
}

public extension _STLR.Grammar {

}

fileprivate extension _STLR.Element {
    private static func rule(for element:_STLR.Element, using symbolTable:SymbolTable<Symbol>)->Rule {
        if let terminal = element.terminal {
            return terminal.rule(with: element.behaviour, and: element.annotations?.ruleAnnotations ?? [:])
        } else if let identifier = element.identifier {
            return symbolTable[identifier].reference(with: element.behaviour, and: element.annotations?.ruleAnnotations ?? [:])
        } else if let group = element.group {
            return group.expression.rule(using: symbolTable).rule(with: element.behaviour,annotations: element.annotations?.ruleAnnotations ?? [:])
        }
        fatalError("Element is not a terminal, and identifier reference, or a group")
    }
    func rule(symbolTable:SymbolTable<Symbol>)->Rule {
        let element : _STLR.Element
        if let token = token {
            element = _STLR.Element(annotations: annotations?.filter({!$0.label.isToken}), group: nil, identifier: "\(token)", lookahead: lookahead, negated: negated, quantifier: quantifier, terminal: nil, transient: transient, void: void)
        } else {
            element = self
        }
        return _STLR.Element.rule(for:element, using:symbolTable)
     }
}

extension _STLR.CharacterSetName {
