 import OysterKit
 
 fileprivate final class Symbol : SymbolType {
-    var behaviouralRule : Rule
-
-    static func buildRule(for identifier: String, from grammar: _STLR.Grammar, in symbolTable: SymbolTable<Symbol>) -> Symbol {
-        return Symbol(behaviouralRule: grammar[identifier].rule(using: symbolTable))
-    }
-    
-    fileprivate init(behaviouralRule:Rule){
-        self.behaviouralRule = behaviouralRule
+    let identifier : String
+    private var expression: Rule
+    private var baseAnnotations : RuleAnnotations
+    private var baseKind : Behaviour.Kind
+
+    static func build(for identifier: String, from grammar: _STLR.Grammar, in symbolTable: SymbolTable<Symbol>) -> Symbol {
+        let symbol : Symbol
+        let declaration = grammar[identifier]
+        if grammar.isLeftHandRecursive(identifier: identifier){
+            let recursive = BehaviouralRecursiveRule(stubFor: Behaviour(.scanning), with: [:])
+            symbol = Symbol(identifier, with: recursive, baseKind: declaration.behaviour.kind, baseAnnotations: declaration.annotations?.ruleAnnotations ?? [:])
+            symbolTable[identifier] = symbol
+            recursive.surrogateRule = grammar[identifier].expression.rule(using: symbolTable)
+        } else {
+            symbol = Symbol(identifier, with: grammar[identifier].expression.rule(using: symbolTable), baseKind: declaration.behaviour.kind, baseAnnotations: declaration.annotations?.ruleAnnotations ?? [:])
+            symbolTable[identifier] = symbol
+        }
+        
+        return symbol
+    }
+    
+    init(_ identifier:String, with expression:Rule, baseKind: Behaviour.Kind, baseAnnotations:RuleAnnotations){
+        self.identifier = identifier
+        self.expression = expression
+        self.baseKind = baseKind
+        self.baseAnnotations = baseAnnotations
+    }
+    
+    func reference(with behaviour:Behaviour, and instanceAnnotations:RuleAnnotations)->Rule{
+        return expression.annotatedWith(baseAnnotations.merge(with: instanceAnnotations)).reference(behaviour.kind).rule(with:behaviour,annotations: nil).scan()
+    }
+    
+    var  rule : Rule {
+        return expression.rule(with: Behaviour(baseKind), annotations: baseAnnotations)
     }
 }
 

            guard let lastRule = rules.last else {
                return []
            }
            return [lastRule.rule(using: symbolTable)]
        } else {
            return rootRules.map({$0.rule(using: symbolTable)})
        }
    }
}



}

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 {
