Skip to content

Refactor and Modernize Java CUP with AST Auto-Generation Support - #5

Open
EmptyDreams wants to merge 137 commits into
DrMichaelPetter:masterfrom
EmptyDreams:master
Open

Refactor and Modernize Java CUP with AST Auto-Generation Support#5
EmptyDreams wants to merge 137 commits into
DrMichaelPetter:masterfrom
EmptyDreams:master

Conversation

@EmptyDreams

Copy link
Copy Markdown

Thank you sincerely for your years of dedicated work on the Java CUP project.

This pull request represents a comprehensive modernization of Java CUP—refactoring its architecture, replacing outdated patterns with modern Java practices, and adding significant new capabilities, most notably automatic AST generation directly from .cup grammar files.

⚠️ Important: This is a breaking change. It is not backward-compatible, and users who adopt this version will need to update their code (e.g., class names, symbol handling, build scripts, CLI flags). This is an intentional redesign, not a drop-in upgrade.

I fully understand that such a large, compatibility-breaking change may not align with the current maintenance goals or release strategy of the upstream project. If you decide not to merge it, I will maintain this version independently as a separate fork.

Key changes include:

  1. Standardized class naming:
    The original sym class has been renamed to GrammarSymConstants; similarly, classes like parser—which were prone to naming conflicts with user code—have been updated to follow Java’s PascalCase convention.

  2. Refactored source location handling:

    • The original -locations command-line option (which toggled whether position information was attached to symbols) has been removed;
    • A unified Location interface is now used as the standard abstraction for source positions;
    • A new -location CLI option allows users to specify a custom Location implementation (defaults to ComplexLocation), offering greater flexibility and type safety.
  3. Removed outdated or redundant components:

    • The xmlaction module has been entirely removed;
    • All Simple-series symbols and their corresponding SymbolFactory implementations are deleted;
    • The minijava2 test file has been removed—it shares identical grammar with minijava, differing only in that it includes a simulation runtime, which provides limited value in the current testing context.
  4. Overhauled symbol system:

    • The parser-internal symbol class is now named GrammarSymbol, while the user-facing class remains Symbol to clarify responsibilities;
    • Symbol is simplified into an immutable class with cleaner logic;
    • Specialized ComplexSymbol variants for all primitive types (e.g., IntComplexSymbol) eliminate boxing/unboxing overhead;
    • The symbol factory has been completely rewritten to align with the new Symbol and Location design.
  5. Modernized collections:
    Legacy collection types such as Stack and Hashtable have been replaced with modern JDK equivalents (e.g., ArrayList, HashMap). Additionally, a new IntArrayStack is introduced to support integer stack operations without boxing.

  6. Build system migration:

    • Ant has been fully deprecated in favor of Gradle;
    • Source layout updated: src/javasrc/main/java, test grammars moved to src/test/resources;
    • Tests are now executed via Gradle instead of outdated shell scripts, with test cases updated accordingly.
  7. New AST auto-generation feature (core addition):

    • AST node classes can now be auto-generated directly from .cup grammar files;
    • A new -ast CLI option enables AST generation and controls node class naming format;
    • To improve readability, a new %namer directive is introduced:
      By default, a distinct AST class is generated for each non-empty production (productions with identical RHS are merged), but the class name is auto-generated and not human-friendly. Users can append %namer MyNodeName to a production to explicitly assign a readable class name to its AST node;
    • Extended grammar syntax now supports:
      • symbol? — optional;
      • symbol* — nullable list;
      • symbol+ — non-empty list;
      • symbol[sep1 sep2 …]+ or symbol[sep1 sep2 …]*:
        Represents a list separated by one or more delimiters (e.g., comma, semicolon, etc., space-separated). Trailing delimiters are controlled by ! (forbidden) or ? (optional). For example:
        • symbol[comma !]+ → non-empty list, no trailing comma;
        • symbol[comma ?]* → nullable list, trailing comma optional;
      • ...symbol — inline (flatten) child node into the current AST node;
    • All AST nodes provide a toTreeString(boolean) method for human-readable tree printing, with console color highlighting when true.
  8. Miscellaneous improvements:

    • Full code formatting applied;
    • Unused methods and redundant variables removed;
    • Logic optimized for better performance and readability.
  9. And more...

Status:

  • minijava and calc test cases have been updated and pass;
  • ⏳ The c language test case is not yet migrated (in progress);
  • 📝 Documentation (manual.html, changelog) remains unupdated—will be completed promptly if the PR is accepted.

Thank you again for your time and consideration. Regardless of the outcome, I deeply appreciate the foundation Java CUP has provided—and hope this contribution offers a compelling path forward for those seeking a more modern, expressive, and maintainable parser generator.

+ Replace Stack with ArrayStack, and Hashtable with HashMap
+ Optimize some code logic to improve execution efficiency
+ Modify code formatting to enhance readability
- No longer require a production with only a single element to exist necessarily.
…te `Location` design: require each subclass to declare a `public static final <SelfType> NO_LOCATION` to prevent type-casting issues.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant