anchor.diff:     let recTable = recognitionTable g s
      //восстановление вывода по таблице начиная с ячейки recTable(i,l) нетерминала top
      let rec subRecognize i l top = 
  -      let nonTerminals,(leftI,leftL),(rightI,rightL),rs = recTable.[i,l]
  +      let nonTerminals,(leftI,leftL),(rightI,rightL),lbl,rs = recTable.[i,l]
         //правило вида А->_, где А = top
  -      let currentRule = List.find (fun (ToBranch(st,_,_)|ToLeaf(st,_)) -> st = top) rs
  +      let currentRule = List.find (fun (ToBranch(st,_,_,l)|ToLeaf(st,_,l)) -> st = top) rs
         let leftNT,rightNT = 
            match currentRule with
  -         |ToBranch(_,left,right) -> left,right
  -         |ToLeaf(_,terminal)     -> terminal.ToString(),""  
  +         |ToBranch(_,left,right,l) -> left,right
  +         |ToLeaf(_,terminal,l)     -> terminal.ToString(),""  
         match i,l with
  -      | _,0 -> [ToLeaf(top,leftNT.[0])]
  +      | _,0 -> [ToLeaf(top,leftNT.[0],None)]
         | _     -> currentRule::(subRecognize leftI leftL leftNT)@(subRecognize rightI rightL rightNT)
  -   let resultRules = if List.exists ((=)start) ((fun (a,_,_,_) -> a) recTable.[0, s.Length-1])
  +   let resultRules = if List.exists ((=)start) ((fun (a,_,_,_,l) -> a) recTable.[0, s.Length-1])
                        then subRecognize 0 (s.Length-1) start//если цепочка принадлежит языку L(g)
                        else []
   
  
positive.code:                                                                        
  let recognitionTable (rules,_) (s:string) = 
             
     let recTable = Microsoft.FSharp.Collections.Array2D.create s.Length s.Length ([],(0,0),(0,0),[])
     //recTable(i,l), для l > 0
  
     let inline processRule rule i k l =
          match rule with
          |ToBranch(a,b,c) -> let nonTerminals1,_,_,_ = recTable.[i,k]
                              let nonTerminals2,_,_,_ = recTable.[k+i+1,l-k-1]
                              let nonTerminals,_,_,rules = recTable.[i,l]
                              if (List.exists ((=)b) nonTerminals1) && (List.exists ((=)c) nonTerminals2)
                              then recTable.[i,l] <- (a::nonTerminals),(i,k),(k+i+1,l-k-1),(rule::rules)
          |_               -> ()   
  
     let elem i l = rules |>  Array.iter (fun rule -> for k in 0..(l-1) do processRule rule i k l)
  
negative.code: 
  
  //грамматика, допускающая операции +, * и позволяющая группировать их с помощью скобок, преобразованная в НФХ
  //let testGrammar1 = (Array.ofList <| (List.map ToBranch [("E","T","N1");("N1","N2","E");("E","F","N3");("N3","N4","T");("E","N5","N6");("N6","E","N7");("E1","N2","E");("T","F","N3");("T","N5","N6");("T1","N4","T");("F","N5","N6")]) @ (List.map ToLeaf [("N2",'+');("N4",'*');("E",'a');("N5",'(');("N7",')');("T",'a');("F",'a')]),"E")
  //let testGrammar2 = ((List.map ToBranch [("S","A","B");("B","N1","N2");("N1","D1","D2")])@(List.map ToLeaf [("A",'a');("D2",'c');("B",'a');("D1",'b');("N2",'d')]),"S")
  //System.Console.WriteLine("Test1:")
  //recognize testGrammar1 "a*a+a"
  
  let testGrammar_lbl1 = (Array.ofList <| (List.map ToBranch [("E","T","X",Some("l1"));("E","T","Y",Some("l2"));("E","E","E",None)]) @ (List.map ToLeaf [("T",'a',None);("X",'*',None);("Y",'+',None)]),"E")
  
  
  let str = List.init 20 (fun i -> "(a+a)*a") |> String.concat "+"
  System.Console.WriteLine("Test2:")
  let start = System.DateTime.Now
  //recognize testGrammar1 str
  printfn "Time = %A" (System.DateTime.Now - start)
  
  recognize testGrammar_lbl1 "a*a+"
  
  //System.Console.WriteLine("Test3:")
  //recognize testGrammar2 "abcd"
  