anchor.diff:  
   
   //грамматика, допускающая операции +, * и позволяющая группировать их с помощью скобок, преобразованная в НФХ
  -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")
  +//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
  +//recognize testGrammar1 str
   printfn "Time = %A" (System.DateTime.Now - start)
  +
  +recognize testGrammar_lbl1 "a*a+"
   
   //System.Console.WriteLine("Test3:")
   //recognize testGrammar2 "abcd"
  
positive.code:                    match oldForm with
                     |l::ls -> if l = leftNonTerminal then //ищем первый нетерминал
                                  match x with //замена l в соответствии с правилом x
                                  |ToBranch(a,b,c) -> b::c::ls
                                  |ToLeaf(a,b)     -> b.ToString()::ls
                               else l::(newForm ls)
                     |_     -> []
                  System.Console.Write(String.concat "" ("->"::(newForm current)))                   
  
negative.code: 
  //Правила контекстно-свободной грамматики в нормальной форме Хомского
  type Rule = 
     |ToBranch of string*string*string*Option<string> //А->BC, A,B,C - нетерминалы
     |ToLeaf of string*char*Option<string> //A->a, а - терминал 
  
  //Вывод правил
  let printRules =
     (function
     | ToBranch(a,b,c,l) -> System.Console.WriteLine(String.concat "" [a; "->"; b; c; "  "; (match l with | Some t -> t | None -> "")])
     | ToLeaf(a,b,l)     -> System.Console.WriteLine(String.concat "" [a;"->";b.ToString();"  "; (match l with | Some t -> t | None -> "") ]))
     |> List.iter
  
  //Последовательное применение правил rs, начиная с первого левого нетерминала start                             
  let printOutput rs start =
     //последовательно строит сентенциальные формы вывода
     let rec sentForm current rules =
        match rules with
        |x::xs -> //первый левый нетерминал
                  let leftNonTerminal = List.find (fun (y:string) -> (y = (y.ToUpper()))&&((y.ToUpper()) <> (y.ToLower()))) current
  