Skeleton.readDefault()
    Changed: URL url = l.getResource("JFlex/skeleton.default");
    To: URL url = l.getResource("skeleton.default");
    Required to make JUnit tests pass

Parser action handles processing of AST
    Expands all macros
    Builds NFA
    Just remove everything after scanner.t.stop()?
        That's just the timer stop

Regexes are stored as general tree nodes with a type enumeration

Predefined classes are expanded into lists of intervals (i.e. regular char classes)
    They appear to be 7-bit, even when other classes are unicode

BAR is pipe (i.e. alternation)

Frontend and backend classes are mixed (generated classes too)

AST Classes
    Action
    CharClassInterval
    EOFActions
    Interval
    Macros
    RegExp/1/2/s
    sym (generated enumeration)
    SemCheck
        regex checks
        potentially useful

Possible AST Classes
    CharSet? (for char classes?)
        No - only used by emitter
    CharClasses?
        Seems to be a list of all encountered char classes
        Probably backend-only: char classes are returned as RegExp1(sym.CCLASS, ...)
    IntCharSet?
        Used by CharClasses
    Options?
        No - actually program arguments

What happened to all of the options and code regions?
    %unicode/%full update charClasses.setMaxCharCode
    Stored in the scanner
        User code (i.e. freeform header) (string)
        %public, %abstract, %final (boolean)
        %extends, %implements (string)
        %type (string)
        etc
    May need add new flags for options that are expressed as combos of effects

%eof{ %eof} is executed once and returns no value
%eofval{ %eofval} is executed every time and returns a value
%eofthrow applies to %eof

Issue: don't want to process %includes
    Comment out yypushStream( new FileReader(f) );
Issue: have to escape closing sequences in chunks of user code
Issue: %eof
    Turn into %eofval with flag and if
        Issue: name flag without creating conflict
    Add to MetaLexer
        Issue: other lexers don't have it (e.g. flex)
    Forbid it (temporarily?)
Issue: how does %eofval interact with states?  Is it run in all states?
    Appears to be equiv to <YYINITIAL> { <<EOF>> { ... } }
        No - this was based on looking at the generated code, not running it
    Appears to be equiv to adding <<EOF>> { ... } at the end of the file
        Consequence: affects exclusive states as well (seems to be a JFlex bug)
        Note: no warning about unreachability (whereas you will get one if you actually convert to <<EOF>>)

Bug?
    <<EOF>> {...}
    means
    < all states> <<EOF>> {...}
    rather than
    < all inclusive states > <<EOF>> {...}

Require CUP to rebuild JFlex
    CUP is covered by a GPL-compatible, BSD-style license

Their own lexer spec has "dangerous lookahead".

                     //shared
                     String fileName = scanner.file.getName();
                     String name = fileName.substring(0, fileName.indexOf('.'));
                     boolean helper = false;
                     
                     //component
                     metalexer.ast.List<State> states = new metalexer.ast.List<State>();
                     {
                         //TODO-AC
                     }
                     Set<StringSymbol> imports = new HashSet<StringSymbol>(); //no imports - everything in layout
                     metalexer.ast.List<ExternDecl> externDecls = new metalexer.ast.List<ExternDecl>(); //first cut: no externs
                     Set<StringSymbol> compDeclRegions = new HashSet<StringSymbol>(); //first cut: all in layout
                     Set<StringSymbol> compYylexExceptions = new HashSet<StringSymbol>(); //first cut: all in layout
                     Set<StringSymbol> compInitRegions = new HashSet<StringSymbol>(); //first cut: all in layout
                     Set<StringSymbol> compInitExceptions = new HashSet<StringSymbol>(); //first cut: all in layout
                     Set<StringSymbol> appendRegions = new HashSet<StringSymbol>(); //none
                     metalexer.ast.List<MacroDecl> macroDecls = new metalexer.ast.List<MacroDecl>();
                     {
                         //TODO-AC
                     }
                     RuleSection localRuleSection = null; //TODO-AC
                     metalexer.ast.List<InheritSection> inheritSections = new metalexer.ast.List<InheritSection>(); //none
                     
                     Component comp = new Component(name, helper, new Opt<StateRef>(), states, imports, externDecls, compDeclRegions, compYylexExceptions, compInitRegions, compInitExceptions, appendRegions, macroDecls, localRuleSection, inheritSections);
                     
                     
                     //layout
                     String localHeader = scanner.userCode.toString(); //TODO-AC: need separator?
                     String inheritedHeader = ""; //TODO-AC: need separator?
                     CompRef startComponent = new CompRef(name);
                     metalexer.ast.List<CompDecl> components = new metalexer.ast.List<CompDecl>();
                     {
                         components.add(new CompDecl(name, new Opt<Component>(comp)));
                     }
                     metalexer.ast.List<LexerOption> options = new metalexer.ast.List<LexerOption>();
                     {
                         //TODO-AC
                     }
                     metalexer.ast.List<Declaration> decls = new metalexer.ast.List<Declaration>(); //first cut: no declarations
                     Set<StringSymbol> declRegions = new HashSet<StringSymbol>();
                     {
                         //TODO-AC
                     }
                     Set<StringSymbol> yylexExceptions = new HashSet<StringSymbol>();
                     {
                         //TODO-AC
                     }
                     Set<StringSymbol> initRegions = new HashSet<StringSymbol>();
                     {
                         //TODO-AC
                     }
                     Set<StringSymbol> initExceptions = new HashSet<StringSymbol>();
                     {
                         //TODO-AC
                     }
                     metalexer.ast.List<BodyElement> bodyElements = new metalexer.ast.List<BodyElement>(); //none
                     
                     Layout layout = new Layout(name, helper, localHeader, inheritedHeader, new Opt<CompRef>(startComponent), components, options, decls, declRegions, yylexExceptions, initRegions, initExceptions, bodyElements);
                     
                     layout.generateMetaLexer("."); //TODO-AC: destdir