Thank not me but this PILS expression:
[code]{ .demo
| :ok
! Get the amalgamated Juce header file
file “C:/juce/juce_amalgamated.h” text
! Concatenate continued lines
= (""=, “”)
! Simplified lexer - recognize strings and identifiers
! skips comments, spaces, linefeeds and directives
! (literal prefixes/suffixes will come out as false identifiers)
split
[ identifier string ignore other
.identifier [“A-Z”, “a-z”, “_”, “"] [*: "A-Z", "a-z", "_", "”, “0-9”],
.string “”"" [: “” 1, [-: “”""] 1] “”"", “’” [: “” 1, [-: “’”] 1] “’”,
.ignore [+: " “, “”>, “”=, “/" [: [-: “/"] 1,] "/”, [”//”, “#”] [*: [-: “”=] 1,]]
.other 1
]
! filter the tokens
each
{ [other], ok | :ok }
{ [string], ok | :ok }
{ [identifier], name | :ok name: . }
{ [identifier], ok call
[ .“and” .“and_eq” .“asm .auto” .“bitand” .“bitor” .“bool” .“break” .“case”
.“catch” .“char” .“class” .“compl” .“const” .“const_cast” .“continue” .“default”
.“delete” .“do” .“double” .“dynamic_cast” .“else” .“enum” .“explicit” .“export”
.“extern” .“false” .“float” .“for” .“friend” .“goto” .“if” .“inline” .“int” .“long”
.“mutable” .“namespace” .“new” .“not” .“not_eq” .“operator” .“or” .“or_eq”
.“private” .“protected” .“public” .“register” .“reinterpret_cast” .“return”
.“short” .“signed” .“sizeof” .“static” .“static_assert” .“static_cast” .“struct”
.“switch” .“template” .“this” .“throw” .“true” .“try” .“typedef” .“typeid”
.“typename” .“union” .“unsigned” .“using” .“virtual” .“void” .“volatile”
.“wchar_t” .“while” .“xor” .“xor_eq”
.“JUCE_API”
.“BEGIN_JUCE_NAMESPACE”
.“END_JUCE_NAMESPACE”
.“forcedinline”
]
| :ok
}
! feed them to a state machine that picks up class heads in the juce ns
first [waitfor: . “BEGIN_JUCE_NAMESPACE”; classes: .?] fold
{ (ok = * ;waitfor; ?) := ? | :ok }
{ (* ;waitfor; ok) := waitfor | :ok }
{ (state = classes: .?)
:= ? call
[ .“extern” .“template” .“typedef” .“forcedinline” .“const” .“static” .“void”
.“struct”
]
| :ok waitfor: . “;” .in “{” .out “}”; state
}
{ (state = classes: .?) := “namespace”
| :ok waitfor: . “{”; waitfor: . “}” .in “{” .out “}”; state
}
{ (state = waitfor: .? .in .out; ?) := in | :ok waitfor: . out .in .out; state }
{ (state = classes: .?) := “class”
| :ok class: state
}
{ (ok = class: ?) := “JUCE_API” | :ok }
{ (class: state) := name: . | :ok class: . name; state }
{ (class: .; classes: .) := “{”
| :ok
waitfor: . “}” .in “{” .out “}”;
waitfor: . “;” .in “{” .out “}”;
classes: …(class: …bases ()
}
{ (state = classes: .) := “END_JUCE_NAMESPACE”
| :ok waitfor: . “BEGIN_JUCE_NAMESPACE”; state
}
{ (class: .?; state) := “;” | :ok state }
{ (class: .; state) := “:” | :ok base: class: …bases (); state }
{ (base: state) := access call [.“public” .“private” .“protected”]
| :ok base: .access; state
}
{ (base: .access; state) := name: . base
| :ok base: …access; state
}
{ (base: …access; class: …bases; classes: .) := “{”
| :ok
waitfor: . “}” .in “{” .out “}”;
waitfor: . “;” .in “{” .out “}”;
classes: …(class: …bases . & (base: …access)
}
{ (base: …access; state) := “<”
| :ok
waitfor: . “>” .in “<” .out “>”;
base: …(template:) .access; state
}
{ (base: …access; class: …bases; state) := “,”
| :ok base: class: …bases . & (base: …access); state
}
! Extract the class chain from the end state
call {waitfor: . “BEGIN_JUCE_NAMESPACE”; classes: . ok|:ok}
! Walk the chain and index the classes by name
repeat {class: …bases; more|:ok list := (;name class .value bases); more } .:list
singles [ok]
! List classes that inherit from Component in non-primary positions
call
{ index
| :ok
index legs
{ class := bases
| :try bases --# 1 find
{ base: …access?
| :try base call:
(index -> {bases|:who :try bases find ([call: base] -> who)}) +++
{“Component”|:ok class: …base}
}
}
}
}
[/code]
The outputs is:
[class: . "FileListComponent" .base "ListBox"]
[class: . "FileTreeComponent" .base "TreeView"]
Execution time is 0.45 sec on a 2.2GHZ dual core. The programming system is presently wxWidgets based but I’m porting it to Juce ASAP.