// cd.cd -- class dictionary for class dictionaries. // $Id: cd.cd,v 1.10 2003/01/22 20:34:33 dougo Exp $ package edu.neu.ccs.demeter.aplib.cd; import java.util.*; import java.io.*; import edu.neu.ccs.demeter.aplib.*; Main = . // testing stub public ClassGraph = [ Preamble ] [ SList(ClassGraphEntry) ] implements ClassGraphI. public Preamble = Package *l LocalImports. Package = "package" PackageName ";". LocalImports = [ SList(Import) *l *l ] . Import = "import" PackageName [ ImportAllClasses ] ";". ImportAllClasses = ".*". ClassGraphEntry : lookahead {{ 2 }} Directive | Definition. Directive : ParseDirective | VisitorDirective. ParseDirective = ParseKeyword. VisitorDirective = VisitorKeyword. Definition : ClassDef. public ClassDef = ClassKeyword_List ParamClassName [ *s ParseDirective ] *s ClassParts [ *s EOFtoken ] "." . ClassKeyword_List ~ { lookahead {{ 1 }} ClassKeyword }. ParamClassName = ClassName ["(" Commalist(ClassName) ")"]. ClassParts : ConstOrAltClass | RepetitionClass. ConstOrAltClass : ConstructionClass | AlternationClass common List(PartOrSyntax) ClassParents. PartOrSyntax : Part | OptionalPart | Syntax. public Part = [ "<" PartName ">" *s ] PartKeyword_List ClassSpec [ lookahead {{ 2 }} PartInit ] implements EdgeI. PartKeyword_List ~ { lookahead {{ 1 }} PartKeyword }. PartInit = PartInitKeyword *s JavaCode. public OptionalPart = "[" [ lookahead {{ 2 }} LocalLookahead ] Sandwich(Part) "]". ClassParents = [ Superclasses ] [ Interfaces ]. Superclasses = ExtendsKeyword Commalist(Superclass). public Superclass = ClassSpec implements EdgeI. Interfaces = ImplementsKeyword Commalist(Interface). public Interface = ClassSpec implements EdgeI. ConstructionClass = "=" *s. AlternationClass = ":" *s // disallow the first subclass to start with "common" [ lookahead {{ _Subclass(), { !getToken(1).image.equals("common") } }} Barlist(Subclass) ] [ lookahead {{ 1 }} *s CommonKeyword *s ] . public Subclass = [ lookahead {{ 2 }} LocalLookahead ] ClassSpec implements EdgeI. LocalLookahead = LookaheadKeyword JavaCode. RepetitionClass = "~" *s Sandwich(RepeatedPart). public RepeatedPart = [ ClassSpec ] OpenBrace [ lookahead {{ 2 }} LocalLookahead ] Sandwich(RepeatedElement) *s "}". OpenBrace = "{". // workaround for syntax-between-opts bug public RepeatedElement = ClassSpec. Sandwich(S) = List(Syntax) *s S *s List(Syntax) . ClassSpec = ClassName ["(" Commalist(ClassSpec) ")" ] . Syntax : PlainSyntax | PrintCommand. public PlainSyntax = String. PrintCommand : PrintIndent | PrintUnindent | PrintSkip | PrintSpace. PrintIndent = "+" . PrintUnindent = "-" . PrintSkip = "*l" . PrintSpace = "*s" . // Terminal buffer classes. PackageName ~ IdentOrKeyword { lookahead {{ 2 }} "." IdentOrKeyword }. ClassName = Name. PartName = IdentOrKeyword. JavaCode = Text. // The problem here is that "." is used to end a class def, which is // usually followed by the beginning of another class def, which // starts with an ident or keyword... So we have to use semantic // lookahead to make sure we're not in that situation if we want to // consume the next ident for the qualified name. If the ident is // followed by . ident . then we know we're still in the qualified // name. Otherwise, we have several possibilities for when not to // consume: // 1. ident1 . ident2 = ... (or : or ~) // ident2 is a class being defined. // 2. ident1 . ident2 ( ... // ident2 is a parameterized class being defined. // 3. ident1 . visitor ... (or notparsed) // assume a class keyword begins a class definition. // 4. ident1 . parse ... (or noparse or visitors or endvisitors) // assume a directive keyword is a directive. Name ~ IdentOrKeyword { lookahead (@ "." _IdentOrKeyword(), { getToken(3).image.equals(".") || getToken(3).kind == EOF || ("=:~(".indexOf(getToken(3).image) == -1 && !getToken(2).image.equals("visitor") && !getToken(2).image.equals("notparsed") && !getToken(2).image.equals("parse") && !getToken(2).image.equals("noparse") && !getToken(2).image.equals("visitors") && !getToken(2).image.equals("endvisitors")) } @) "." IdentOrKeyword }. // All the keywords that look like identifiers in the grammar that // aren't keywords in Java. IdentOrKeyword : ParseIdent | NoParseIdent | VisitorsIdent | EndVisitorsIdent | VisitorIdent | NotParsedIdent | DerivedIdent | InitIdent | CommonIdent | LookaheadIdent | OtherIdent. ParseIdent = "parse". NoParseIdent = "noparse". VisitorsIdent = "visitors". EndVisitorsIdent = "endvisitors". VisitorIdent = "visitor". NotParsedIdent = "notparsed". DerivedIdent = "derived". InitIdent = "init". CommonIdent = "common". LookaheadIdent = "lookahead". OtherIdent = Ident. // Keywords. ParseKeyword : DoParse | DontParse. DoParse = "parse". DontParse = "noparse". VisitorKeyword : BeginVisitors | EndVisitors. BeginVisitors = "visitors". EndVisitors = "endvisitors". ClassKeyword : PublicClass | FinalClass | InterfaceClass | VisitorClass | NotParsedClass. PublicClass = "public". FinalClass = "final". InterfaceClass = "interface". VisitorClass = "visitor". NotParsedClass = "notparsed". PartKeyword : FinalPart | StaticPart | ReadOnlyPart | PrivatePart | DerivedPart. FinalPart = "final". StaticPart = "static". ReadOnlyPart = "read-only". PrivatePart = "private". DerivedPart = "derived". PartInitKeyword = "init". ExtendsKeyword = "extends". ImplementsKeyword = "implements". CommonKeyword = "common". LookaheadKeyword = "lookahead". public EOFtoken = "EOF". // Parameterized class definitions. List(S) ~ {*s S}. NList(S) ~ S {*s S}. SList(S) ~ S { *l S } . DList(S) ~ S { *l *l S } *l . Commalist(S) ~ S {"," *s S}. Barlist(S) ~ S { *s "|" *s S}. noparse // Utility classes. ClassType = boolean boolean boolean boolean boolean boolean boolean boolean. PartType = boolean boolean boolean boolean boolean . Parts ~ { Part }. // Visitors. visitors public ClassDefVisitor : . public ClassNameAccessor : . public PartVisitor : . public SyntaxVisitor : . public EdgeVisitor : .