public IEnumerable <Bytecode> Compile(Parser.RegularExpression e) { this.groupcounter = 0; this.labelcounter = 0; foreach (var item in InternalCompile(e)) { yield return(item); } yield return(new Match { }); }
private IEnumerable <Bytecode> InternalCompile(Parser.RegularExpression e) { if (e is Parser.Primitive) { var prim = e as Parser.Primitive; yield return(new Symbol { Lo = prim.Lo, Hi = prim.Hi }); } else if (e is Parser.Sequence) { var seq = e as Parser.Sequence; var left = InternalCompile(seq.Left); var right = InternalCompile(seq.Right); foreach (var item in left.Concat(right)) { yield return(item); } } else if (e is Parser.Group) { var group = e as Parser.Group; var id = this.groupcounter++; yield return(new Save { Id = 2 * id }); foreach (var item in InternalCompile(group.Re)) { yield return(item); } yield return(new Save { Id = 2 * id + 1 }); } else if (e is Parser.Or) { var choice = e as Parser.Or; var l1 = new Label { Location = this.labelcounter++ }; var l2 = new Label { Location = this.labelcounter++ }; var l3 = new Label { Location = this.labelcounter++ }; var e1 = InternalCompile(choice.Left); var e2 = InternalCompile(choice.Right); yield return(new Fork { Fst = l1, Snd = l2 }); yield return(l1); foreach (var item in e1) { yield return(item); } yield return(new Jump { Where = l3 }); yield return(l2); foreach (var item in e2) { yield return(item); } yield return(l3); } else if (e is Parser.Star) { var star = e as Parser.Star; var l1 = new Label { Location = this.labelcounter++ }; var l2 = new Label { Location = this.labelcounter++ }; var l3 = new Label { Location = this.labelcounter++ }; var e1 = InternalCompile(star.Re); yield return(l1); if (star.Greedy) { yield return new Fork { Fst = l2, Snd = l3, Greedy = true } } ; else { yield return new Fork { Fst = l3, Snd = l2, Greedy = false } }; yield return(l2); foreach (var item in e1) { yield return(item); } yield return(new Jump { Where = l1 }); yield return(l3); } else if (e is Parser.Plus) { var plus = e as Parser.Plus; var l1 = new Label { Location = this.labelcounter++ }; var l2 = new Label { Location = this.labelcounter++ }; var l3 = new Label { Location = this.labelcounter++ }; var e1 = InternalCompile(plus.Re); yield return(l1); foreach (var item in e1) { yield return(item); } if (plus.Greedy) { yield return new Fork { Fst = l1, Snd = l3, Greedy = true } } ; else { yield return new Fork { Fst = l3, Snd = l1, Greedy = false } }; yield return(l3); } else if (e is Parser.Question) { throw new Exception("Finish types"); } yield break; }