// repetition.beh -- Repetition conversion // $Id: repetition.beh,v 1.4 2003/01/22 20:34:33 dougo Exp $ // What we want to do is convert the repetition class definition // // Foo_List ~ "a" Foo { (@ lookahead @) "b" Foo "c" } "d". // // into two construction class definitions, a container // // Foo_List = "a" Nonempty_Foo_List "d". // // and a link node // // Nonempty_Foo_List = Foo // [ (@ lookahead @) "b" Nonempty_Foo_List "c" ]. // // If the repetition class is possibly empty (i.e. Foo_List ~ { Foo }), // then the part of the new Foo_List class is optional, and // the lookahead is added in this optional part as well. ClassGraph { /** Convert all repetition classes to (pairs of) construction classes with recursive edges. */ void convertRepetition() via RepetitionClass bypassing -> *,nonempty,* to { PlainSyntax, PrintIndent, PrintUnindent, PrintSkip, PrintSpace, ClassName } { {{ ClassGraph cg; ClassName classname; String container, linknode, linknodename; boolean inRepeatedPart; }} before ClassGraph {{ cg = host; }} before ClassDef {{ classname = host.get_classname(); container = null; }} before RepetitionClass {{ container = "= "; linknodename = RepetitionClass.makeLinknodeName(classname); }} before Syntax {{ if (inRepeatedPart) linknode += host + " "; else container += host + " "; }} before RepeatedPart {{ String first = " " + linknodename; inRepeatedPart = true; linknode = "[ "; LocalLookahead l = host.get_locallookahead(); if (l != null) { linknode += l + " "; } if (host.get_nonempty() == null) { // The repetition is possibly empty; make the link node optional. if (l != null) { first = l + " " + first; } first = "[ " + first + " ] "; } container += first; }} before ClassName {{ linknode = "= " + host + " " + linknode + " " + linknodename + " "; }} after RepeatedPart {{ linknode += "]."; inRepeatedPart = false; }} after RepetitionClass {{ container += "."; }} after ClassDef {{ if (container != null) { // Replace the repetition class with the new container class. host.set_classparts(ConstructionClass.parse(container)); // Add the class definition for the new link node class. ClassDef linknodedef = host.deepCopy(); linknodedef.set_paramclassname(ParamClassName.parse(linknodename)); linknodedef.set_classparts(ConstructionClass.parse(linknode)); linknodedef.set_eoftoken(null); cg.addClassDef(linknodedef); } }} } } RepetitionClass { static String makeLinknodeName(ClassName classname) {{ return "Nonempty_" + classname; }} }