Skip to content

feat(tdl): Add ANTLR actions to generate the AST during the parsing. - #210

Merged
LinZhihao-723 merged 12 commits into
y-scope:mainfrom
LinZhihao-723:antlr-action
Aug 25, 2025
Merged

feat(tdl): Add ANTLR actions to generate the AST during the parsing.#210
LinZhihao-723 merged 12 commits into
y-scope:mainfrom
LinZhihao-723:antlr-action

Conversation

@LinZhihao-723

@LinZhihao-723 LinZhihao-723 commented Aug 25, 2025

Copy link
Copy Markdown
Member

Description

This PR uses ANTLR actions to add AST generation in the parser, directly embedded in the grammar file. The parsed AST will be returned as a TranslationUnit as introduced in #209.

Since we also execute a part of the semantic checks during the parsing (when an AST node is created), we need to propagate these errors through exceptions. This PR also adds a parser Exception for us to propagate these errors. Need to notice that these errors are second-level citizens, as the native ANTLR parser and lexer errors are prioritized when forwarding errors.

We've added unit tests to ensure the AST can be serialized into an expected form. However, the source location is not properly tested yet since the current serialization method doesn't support that. We will add this in a future PR.

Checklist

  • The PR satisfies the contribution guidelines.
  • This is a breaking change and that has been indicated in the PR title, OR this isn't a
    breaking change.
  • Necessary docs have been updated, OR no docs need to be updated.

Validation performed

  • Ensure all workflows pass.
  • Ensure AST can be properly parsed and serialized into an expected form using unit tests.
  • Ensure the parsing exceptions can be caught and propagated properly using unit tests.

Summary by CodeRabbit

  • New Features

    • Parser now builds and returns a location-aware AST for translation units; supports lists, maps, tuples and multiple functions per namespace.
    • New parser exception type provides error codes and source locations for clearer diagnostics and conversion to error objects.
  • Refactor

    • Parsing rewritten to construct AST nodes during parse and consistently propagate location-aware errors.
  • Tests

    • Added detailed AST serialization assertions and error-path tests validating exception messages, locations and specific error codes.

@LinZhihao-723
LinZhihao-723 marked this pull request as ready for review August 25, 2025 19:15
@LinZhihao-723
LinZhihao-723 requested review from a team and sitaowang1998 as code owners August 25, 2025 19:15
@coderabbitai

coderabbitai Bot commented Aug 25, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

Exports a new parser Exception header, rewrites the TDL grammar to construct AST nodes during parsing, updates generated ANTLR parser/lexer/visitor files to carry AST retvals and a new FuncDefs rule, changes the parse API to return a TranslationUnit AST (with exception-to-Error conversion), and tightens tests to assert AST serialization and specific error cases.

Changes

Cohort / File(s) Summary
Build/export config
src/spider/CMakeLists.txt
Adds tdl/parser/Exception.hpp to SPIDER_TDL_SHARED_HEADERS to make the header public.
Parser exception type
src/spider/tdl/parser/Exception.hpp
New public spider::tdl::parser::Exception storing std::error_code and SourceLocation, with what(), to_error(), accessors, and static helpers throw_tryx/throw_tryv.
Grammar overhaul (AST-building)
src/spider/tdl/parser/TaskDefLang.g4
Reworks many rules to return AST nodes/vectors, adds funcDefs, propagates SourceLocation, and uses AST factory calls wrapped with exception helpers for location-aware AST construction.
ANTLR-generated parser/visitor/lexer updates
src/spider/tdl/parser/antlr_generated/*
TaskDefLangParser.{h,cpp}, TaskDefLangLexer.{h,cpp}, TaskDefLangVisitor.{h,cpp}, TaskDefLangBaseVisitor.{h,cpp}
Adds AST and utility includes; introduces FuncDefsContext and related public APIs and retval fields; expands context types with AST-bearing members; adds visitFuncDefs/base visitor override; updates rule indices and sempreds.
Parser integration and API
src/spider/tdl/parser/parse.hpp, src/spider/tdl/parser/parse.cpp
Changes parse_translation_unit_from_istream to return boost::outcome_v2::std_checked<std::unique_ptr<ast::TranslationUnit>, Error>; returns/moves context->tu on success; catches spider::tdl::parser::Exception and converts to Error, while prioritizing lexer/parser error listeners.
Parser runtime includes
src/spider/tdl/parser/antlr_generated/TaskDefLang*.{h,cpp}, src/spider/tdl/parser/antlr_generated/TaskDefLangVisitor.{h,cpp}, TaskDefLangBaseVisitor.{h,cpp}
Adds standard headers (<memory>, <utility>, <vector>) and AST headers (e.g., ast/FloatSpec.hpp, ast/IntSpec.hpp, ast/nodes.hpp, Exception.hpp, SourceLocation.hpp) at top of generated translation units.
Tests (AST serialization and errors)
tests/tdl/test-parser.cpp
Tests include AST headers, assert full serialized AST equality for a sample input, and add an error test validating Exception is produced for duplicated function names (checking error code and source location).

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Client
  participant Lexer
  participant Parser
  participant Listeners as Error listeners
  participant AST as TranslationUnit
  participant Ex as Exception

  Client->>Parser: parse_translation_unit_from_istream(input)
  Parser->>Lexer: tokenize(input)
  Lexer-->>Parser: tokens
  Note over Parser: Parser builds AST during rule actions\n(each rule produces retval nodes with SourceLocation)
  Parser->>Parser: translationUnit()
  alt AST built without throwing
    Parser-->>AST: context->tu (unique_ptr)
    Parser->>Listeners: check lexer/parser listeners
    alt listeners report error
      Parser-->>Client: return Error(from listeners)
    else
      Parser-->>Client: return moved AST (success)
    end
  else AST construction throws
    Parser-->>Ex: throw Exception(error_code, location)
    Parser->>Listeners: check lexer/parser listeners
    alt listeners report error
      Parser-->>Client: return Error(from listeners)
    else
      Ex-->>Parser: to_error()
      Parser-->>Client: return Error(from Exception)
    end
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related PRs

Suggested reviewers

  • sitaowang1998

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

♻️ Duplicate comments (2)
src/spider/tdl/parser/antlr_generated/TaskDefLangBaseVisitor.cpp (1)

2-11: Generated file — headers appear due to grammar @Header; no manual edits

Given our team’s policy to avoid linting generated sources, this looks fine. If you adopt @parser::header as suggested in the grammar, these includes will disappear from this file on the next generation.

src/spider/tdl/parser/antlr_generated/TaskDefLangLexer.cpp (1)

2-11: Generated file — unnecessary heavy includes are a side effect of @Header

No action here; once the grammar switches to @parser::header, the lexer won’t pull in AST/Exception headers, reducing rebuild noise.

🧹 Nitpick comments (19)
src/spider/tdl/parser/Exception.hpp (1)

67-69: Improve end-user message content carried into Error

what() returns a fixed string, so to_error() currently loses useful context (e.g., the std::error_code’s message). Recommend threading the error_code.message() into the Error message to simplify downstream reporting.

Apply this diff:

-    [[nodiscard]] auto to_error() const -> Error {
-        return Error{std::string{what()}, m_source_location, m_error_code};
-    }
+    [[nodiscard]] auto to_error() const -> Error {
+        std::string msg = std::string{what()};
+        if (m_error_code) {
+            msg.append(": ").append(m_error_code.message());
+        }
+        return Error{std::move(msg), m_source_location, m_error_code};
+    }
src/spider/tdl/parser/TaskDefLang.g4 (4)

3-13: Scope the injected headers to the parser only to avoid polluting generated lexer/visitor units

Using @Header injects these includes into all generated artifacts (lexer, parser, visitors). The lexer doesn’t need AST/Exception headers, and this increases rebuild surface. Prefer @parser::header (and only add a @lexer::header if you truly need something in the lexer).

Apply this diff:

-@header {
+@parser::header {
 #include <memory>
 #include <utility>
 #include <vector>

 #include <spider/tdl/parser/ast/FloatSpec.hpp>
 #include <spider/tdl/parser/ast/IntSpec.hpp>
 #include <spider/tdl/parser/ast/nodes.hpp>
 #include <spider/tdl/parser/Exception.hpp>
 #include <spider/tdl/parser/SourceLocation.hpp>
 }

If any lexer-specific include is required later, add a separate, minimal:

@lexer::header {
  // (keep empty for now)
}

15-35: Avoid C++ keyword collisions: rename rule ‘namespace’ to ‘namespaceDecl’

ANTLR usually suffixed C++ keywords in generated method names (e.g., namespace_()), but relying on keyword workarounds hurts readability and IDE navigation. Renaming the rule and references improves clarity.

Apply these diffs:

-translationUnit returns [std::unique_ptr<spider::tdl::parser::ast::TranslationUnit> tu]
+translationUnit returns [std::unique_ptr<spider::tdl::parser::ast::TranslationUnit> tu]
 @init {
     $tu = spider::tdl::parser::ast::TranslationUnit::create({
             $ctx->start->getLine(),
             $ctx->start->getCharPositionInLine()
     });
 }
-: (namespace {
-    auto const ns_loc{$namespace.retval->get_source_location()};
+: (namespaceDecl {
+    auto const ns_loc{$namespaceDecl.retval->get_source_location()};
     spider::tdl::parser::Exception::throw_tryv(
-        $tu->add_namespace(std::move($namespace.retval)),
+        $tu->add_namespace(std::move($namespaceDecl.retval)),
         ns_loc
     );
 } | structDef {
     auto const struct_loc{$structDef.retval->get_source_location()};
     spider::tdl::parser::Exception::throw_tryv(
         $tu->add_struct_spec(std::move($structDef.retval)),
         struct_loc
     );
 })* EOF
-namespace returns [std::unique_ptr<spider::tdl::parser::ast::Node> retval]
+namespaceDecl returns [std::unique_ptr<spider::tdl::parser::ast::Node> retval]
 : 'namespace' id '{' funcDefs '}' {
   SourceLocation const loc{
     $ctx->start->getLine(),
     $ctx->start->getCharPositionInLine()
   };
   $retval = spider::tdl::parser::Exception::throw_tryx(
     spider::tdl::parser::ast::Namespace::create(
       std::move($id.retval),
       std::move($funcDefs.retval),
       loc
     ),
     loc
   );
 }

Also applies to: 37-52


92-99: params: explicit @init for clarity (nit)

You’re clearing $retval in the empty alt; adding an @init { $retval.clear(); } conveys intent, avoids accidental reuse if ANTLR rewrites alts.

Proposed small change:

-params returns [std::vector<std::unique_ptr<spider::tdl::parser::ast::Node>> retval]
-: namedVarList {
+params returns [std::vector<std::unique_ptr<spider::tdl::parser::ast::Node>> retval]
+@init { $retval.clear(); }
+: namedVarList {
     $retval = std::move($namedVarList.retval);
 }
 | {
-    $retval.clear();
+    /* empty params already handled by @init */
 }
 ;

54-63: Function definitions aggregation: also consider ordering guarantees (nit)

Your approach preserves source order. After the EBNF refactor, you’ll still preserve it via push order. Just a heads-up to keep tests asserting order where relevant.

src/spider/tdl/parser/antlr_generated/TaskDefLangLexer.h (1)

2-10: Move AST and Error Headers into the Parser-Only Header Block

The generated TaskDefLangLexer.h (and related lexer files) still pull in:

  • <spider/tdl/parser/ast/FloatSpec.hpp>
  • <spider/tdl/parser/ast/IntSpec.hpp>
  • <spider/tdl/parser/ast/nodes.hpp>
  • <spider/tdl/parser/Exception.hpp>
  • <spider/tdl/parser/SourceLocation.hpp>

Yet none of these types are ever referenced by the lexer (grep found no usages in lexer files), so they simply bloat rebuilds and couple the lexer to AST/error headers.

Action items:

  • In your .g4 (e.g. TaskDefLang.g4), remove AST/error includes from the global @header block.
  • Add a @parser::header block containing only those AST and error headers.
  • Keep only minimal shared includes (e.g. <vector>) in the global @header.
  • Regenerate all ANTLR artifacts—do not hand-edit the generated files.

Example grammar adjustment:

--- TaskDefLang.g4
- @header {
-   #include <vector>
-   #include <spider/tdl/parser/ast/FloatSpec.hpp>
-   #include <spider/tdl/parser/ast/IntSpec.hpp>
-   #include <spider/tdl/parser/ast/nodes.hpp>
-   #include <spider/tdl/parser/Exception.hpp>
-   #include <spider/tdl/parser/SourceLocation.hpp>
- }
+ @header {
+   #include <vector>
+ }
+
+ @parser::header {
+   #include <spider/tdl/parser/ast/FloatSpec.hpp>
+   #include <spider/tdl/parser/ast/IntSpec.hpp>
+   #include <spider/tdl/parser/ast/nodes.hpp>
+   #include <spider/tdl/parser/Exception.hpp>
+   #include <spider/tdl/parser/SourceLocation.hpp>
+ }

This decouples the lexer from AST/error types and avoids unnecessary rebuilds.

src/spider/tdl/parser/antlr_generated/TaskDefLangVisitor.h (1)

2-10: Trim heavy includes from the public visitor interface.

This header declares only an interface; it doesn’t need AST node definitions or Exception/SourceLocation. Pulling them in here increases transitive dependencies for every includer.

Action: relocate these includes to the parser implementation or a dedicated builder, or switch the grammar’s header block to the parser-only section so they don’t land in the visitor interface.

src/spider/tdl/parser/antlr_generated/TaskDefLangVisitor.cpp (1)

2-10: Non-essential includes in TU—keep, but consider narrowing.

In a .cpp, extra includes are less harmful, but you likely don’t need to pull in all AST headers and Exception/SourceLocation if this translation unit only wires up the visitor base. If these landed via a global @Header block, consider scoping them to @parser::header to minimise churn.

src/spider/tdl/parser/antlr_generated/TaskDefLangBaseVisitor.h (1)

2-10: Reduce header bloat in BaseVisitor.

Similar to TaskDefLangVisitor.h, BaseVisitor does not require full AST/Exception headers. Relocate or narrow includes via the grammar’s header sections to keep the public surface lean.

src/spider/tdl/parser/parse.hpp (2)

10-10: Prefer forward declaration over including all AST nodes.

Including ast/nodes.hpp in a public header forces every includer to parse the full AST set. Since you return a pointer, you can forward-declare ast::TranslationUnit and move the heavy include to the .cpp.

Apply this change (within this header, remove the heavy include):

-#include <spider/tdl/parser/ast/nodes.hpp>

And add a forward declaration (outside the changed range; example placement shown):

// Place after the includes, before the function declaration:
namespace spider::tdl::parser::ast {
  struct TranslationUnit;
}

17-18: Docstring aligns with new semantics—consider minor clarity.

Optionally clarify ownership and immutability, e.g., “Returns a unique_ptr owning the AST root (caller owns).” If the AST shouldn’t be mutated by clients, consider returning std::unique_ptr<const ast::TranslationUnit>.

tests/tdl/test-parser.cpp (3)

54-59: Guard against accidental nullptr translation_unit before dereference.

Outcome success doesn’t guarantee non-null unique_ptr in perpetuity. Add a sanity check to prevent UB if future changes ever allow a null AST on success.

 TEST_CASE("Parsing `cTestInput1`", "[tdl][parser]") {
   std::istringstream input_stream{std::string{cTestInput1}};
   auto const parse_result{parse_translation_unit_from_istream(input_stream)};
   REQUIRE_FALSE(parse_result.has_error());
-  auto const& translation_unit{parse_result.value()};
+  auto const& translation_unit{parse_result.value()};
+  REQUIRE(translation_unit != nullptr);

60-246: The golden-string equality makes the test brittle; consider stabilizing the assertion.

Exact textual equality across hundreds of lines is fragile to benign formatting changes (spacing, newlines, serialization wording). Options:

  • Normalise newlines/whitespace before comparing.
  • Print the actual string on failure for easier diffing.
  • Move expected output to a snapshot file to simplify maintenance.

Minimal, low-noise tweak (adds better failure diagnostics) while keeping equality:

-    REQUIRE(serialize_result.value() == cExpectedSerializedAst);
+    INFO("\n--- Serialized AST (actual) ---\n" << serialize_result.value());
+    REQUIRE(serialize_result.value() == cExpectedSerializedAst);

If cross-platform is a concern, consider normalising CRLF to LF before comparison:

+#include <algorithm>
+#include <string>
...
-    INFO("\n--- Serialized AST (actual) ---\n" << serialize_result.value());
-    REQUIRE(serialize_result.value() == cExpectedSerializedAst);
+    auto actual = serialize_result.value();
+    actual.erase(std::remove(actual.begin(), actual.end(), '\r'), actual.end());
+    INFO("\n--- Serialized AST (actual) ---\n" << actual);
+    REQUIRE(actual == cExpectedSerializedAst);

281-302: Add a test to verify ANTLR lexer/parser errors take precedence over propagated Exceptions.

You already cover the pure-propagated Exception path. It’d be valuable to assert the documented precedence behaviour when both could arise.

Example SECTION to append:

+    SECTION("ANTLR error takes precedence over propagated exception") {
+        // Tuple<> as a param triggers a parser mismatch; duplicate function name would also
+        // trigger a propagated exception if reached. Expect the ANTLR error instead.
+        constexpr std::string_view cBothErrors{
+            "namespace test { fn empty(Tuple<int8>); fn empty(); }"
+        };
+        std::istringstream input_stream{std::string{cBothErrors}};
+        auto const parse_result{parse_translation_unit_from_istream(input_stream)};
+        REQUIRE(parse_result.has_error());
+        auto const& error{parse_result.error()};
+        REQUIRE(error.get_message().rfind("Parser:", 0) == 0); // starts with "Parser:"
+    }

If you want, I can push an update with this new test.

src/spider/tdl/parser/parse.cpp (2)

38-45: Deduplicate error-listener checks to reduce repetition.

Same two-branch check is performed twice. A small helper improves readability and reduces risk of inconsistent future edits.

   // Parse the translation unit
-  try {
+  auto first_error = [&]() -> std::optional<Error> {
+    if (lexer_error_listener.has_error()) return lexer_error_listener.error();
+    if (parser_error_listener.has_error()) return parser_error_listener.error();
+    return std::nullopt;
+  };
+  try {
     auto* context{parser.translationUnit()};
 
-    if (lexer_error_listener.has_error()) {
-        return lexer_error_listener.error();
-    }
-
-    if (parser_error_listener.has_error()) {
-        return parser_error_listener.error();
-    }
+    if (auto e = first_error()) return *e;
 
     return std::move(context->tu);
   } catch (Exception const& e) {
     // When an exception is caught, we still prioritize the parser and lexer errors since they
     // are the root cause of the exceptions.
 
-    if (lexer_error_listener.has_error()) {
-        return lexer_error_listener.error();
-    }
-
-    if (parser_error_listener.has_error()) {
-        return parser_error_listener.error();
-    }
+    if (auto le = first_error()) return *le;
 
     return e.to_error();
   }

Also applies to: 51-57


46-47: Defensive check: ensure context->tu is non-null before returning.

If grammar actions ever fail to create the TU yet no listener reported an error, this could return a null AST on “success”. Consider guarding and converting to an Error.

I can wire a small guard to return a synthetic Error if desired.

src/spider/tdl/parser/antlr_generated/TaskDefLangParser.cpp (2)

382-472: Left-recursive FuncDefs rule is implemented correctly; consider minor allocation hint.

The precedence-based left recursion plus accumulating retval via moves is solid. As a micro-optimisation, you could reserve capacity when re-building the vector to reduce reallocations, though impact is minimal here.

If you want this, it’s best added via grammar action so it persists across regeneration.


665-686: Minor: clearing an already-empty vector is redundant for empty parameter lists.

In the empty-params branch, _localctx->retval.clear() is unnecessary as the vector is default-constructed empty.

Note: If you choose to address this, please change it in the grammar actions (not by editing generated sources).

src/spider/tdl/parser/antlr_generated/TaskDefLangParser.h (1)

2-11: Consider reducing header surface by forward declaring AST types.

Including heavy AST headers (nodes, IntSpec, FloatSpec, Exception) in the public parser header increases rebuild costs. If feasible via grammar header actions, forward-declare the minimal AST types used in member declarations and move heavy includes to the .cpp.

Trade-off: generated code simplicity vs. compile-time. If generation tooling makes this awkward, feel free to skip.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 7ead5ef and 0fe01bb.

📒 Files selected for processing (14)
  • src/spider/CMakeLists.txt (1 hunks)
  • src/spider/tdl/parser/Exception.hpp (1 hunks)
  • src/spider/tdl/parser/TaskDefLang.g4 (1 hunks)
  • src/spider/tdl/parser/antlr_generated/TaskDefLangBaseVisitor.cpp (1 hunks)
  • src/spider/tdl/parser/antlr_generated/TaskDefLangBaseVisitor.h (2 hunks)
  • src/spider/tdl/parser/antlr_generated/TaskDefLangLexer.cpp (1 hunks)
  • src/spider/tdl/parser/antlr_generated/TaskDefLangLexer.h (1 hunks)
  • src/spider/tdl/parser/antlr_generated/TaskDefLangParser.cpp (43 hunks)
  • src/spider/tdl/parser/antlr_generated/TaskDefLangParser.h (20 hunks)
  • src/spider/tdl/parser/antlr_generated/TaskDefLangVisitor.cpp (1 hunks)
  • src/spider/tdl/parser/antlr_generated/TaskDefLangVisitor.h (2 hunks)
  • src/spider/tdl/parser/parse.cpp (2 hunks)
  • src/spider/tdl/parser/parse.hpp (1 hunks)
  • tests/tdl/test-parser.cpp (3 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-07-17T19:44:06.132Z
Learnt from: sitaowang1998
PR: y-scope/spider#168
File: lint-tasks.yaml:62-65
Timestamp: 2025-07-17T19:44:06.132Z
Learning: ANTLR-generated C++ code in the G_SRC_DSL_DIR (src/stdl) should not be included in linting tasks because it's auto-generated code that doesn't follow manual coding standards.

Applied to files:

  • src/spider/tdl/parser/antlr_generated/TaskDefLangVisitor.cpp
  • src/spider/tdl/parser/antlr_generated/TaskDefLangBaseVisitor.cpp
🧬 Code graph analysis (3)
tests/tdl/test-parser.cpp (2)
src/spider/tdl/parser/parse.cpp (2)
  • parse_translation_unit_from_istream (18-61)
  • parse_translation_unit_from_istream (18-19)
src/spider/tdl/parser/parse.hpp (1)
  • parse_translation_unit_from_istream (20-21)
src/spider/tdl/parser/antlr_generated/TaskDefLangParser.h (3)
src/spider/tdl/parser/antlr_generated/TaskDefLangBaseVisitor.h (17)
  • spider (22-100)
  • std (35-37)
  • std (39-41)
  • std (43-45)
  • std (47-49)
  • std (51-53)
  • std (55-57)
  • std (59-61)
  • std (63-65)
  • std (67-69)
  • std (71-73)
  • std (75-77)
  • std (79-81)
  • std (83-85)
  • std (87-89)
  • std (91-93)
  • std (95-97)
src/spider/tdl/parser/antlr_generated/TaskDefLangVisitor.h (1)
  • spider (22-71)
src/spider/tdl/parser/antlr_generated/TaskDefLangParser.cpp (55)
  • getRuleIndex (218-220)
  • getRuleIndex (218-218)
  • getRuleIndex (320-322)
  • getRuleIndex (320-320)
  • getRuleIndex (395-397)
  • getRuleIndex (395-395)
  • getRuleIndex (493-495)
  • getRuleIndex (493-493)
  • getRuleIndex (569-571)
  • getRuleIndex (569-569)
  • getRuleIndex (641-643)
  • getRuleIndex (641-641)
  • getRuleIndex (715-717)
  • getRuleIndex (715-715)
  • getRuleIndex (786-788)
  • getRuleIndex (786-786)
  • id (311-313)
  • id (311-311)
  • id (480-482)
  • id (480-480)
  • id (706-708)
  • id (706-706)
  • id (873-875)
  • id (873-873)
  • id (976-976)
  • id (1021-1023)
  • id (1021-1021)
  • funcDefs (315-317)
  • funcDefs (315-315)
  • funcDefs (390-392)
  • funcDefs (390-390)
  • funcDefs (408-410)
  • funcDefs (408-408)
  • funcDefs (412-412)
  • funcDef (386-388)
  • funcDef (386-386)
  • funcDef (505-505)
  • accept (223-228)
  • accept (223-223)
  • accept (325-330)
  • accept (325-325)
  • accept (400-405)
  • accept (400-400)
  • accept (498-503)
  • accept (498-498)
  • accept (574-579)
  • accept (574-574)
  • accept (646-651)
  • accept (646-646)
  • accept (720-725)
  • accept (720-720)
  • accept (791-796)
  • accept (791-791)
  • funcDefsSempred (1674-1682)
  • funcDefsSempred (1674-1674)
src/spider/tdl/parser/antlr_generated/TaskDefLangParser.cpp (1)
src/spider/tdl/parser/Exception.hpp (1)
  • throw_tryx (26-29)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: lint
  • GitHub Check: non-storage-unit-tests (ubuntu-22.04)
  • GitHub Check: non-storage-unit-tests (ubuntu-24.04)
🔇 Additional comments (27)
src/spider/tdl/parser/Exception.hpp (1)

13-76: Solid, minimal exception type for Result-to-exception bridging — LGTM

The design is clear, header-only, and fits the C++ target’s needs for throwing with location context. Accessors are nodiscard, and the helpers constrain T to be move-constructible, which aligns with returning unique_ptr and vectors throughout the grammar actions. No blockers from me here.

src/spider/tdl/parser/TaskDefLang.g4 (3)

158-172: Type rules look consistent; confirm tupleType is intentionally return-only

  • varType handles builtins + user-defined structs (via id), with containers (List/Map) routed through builtinType: OK.
  • retType additionally allows tupleType, meaning tuples are return-only today.

If that’s by design (multi-value returns only) we’re good. If tuples should also be allowed in parameters or fields, consider allowing tupleType in varType as well.

Also applies to: 174-181, 195-206, 208-223, 225-236, 238-278


146-156: Identifier creation: good location capture — LGTM

Using $ctx->start for SourceLocation makes sense here, and Identifier::create returning a unique_ptr aligns with the rest of the AST factory usage.


15-35: Top-level TU assembly: error propagation and location plumbing look correct

Capturing child node locations and passing them into throw_tryv on add_namespace/add_struct_spec is a good pattern to preserve precise error origin.

src/spider/CMakeLists.txt (1)

258-259: Expose Exception.hpp publicly — LGTM

Adding tdl/parser/Exception.hpp to SPIDER_TDL_SHARED_HEADERS is correct and matches its use across parser clients and tests.

src/spider/tdl/parser/antlr_generated/TaskDefLangLexer.h (1)

1-65: ANTLR-generated code is already excluded from linting

Verified that all ANTLR‐generated sources under tdl/parser/antlr_generated/ are omitted from lint and format jobs:

  • In CMakeLists.txt (around lines 200–210), the SPIDER_TDL_ANTLR_GENERATED_SOURCES variable lists only generated files, keeping them out of manual lint targets.
  • In lint‐tasks.yaml (around lines 64–66), the EXCLUDE_PATTERNS entry explicitly includes "tdl/parser/antlr_generated/*", preventing these files from being processed by the lint pipeline.

No further changes required.

src/spider/tdl/parser/antlr_generated/TaskDefLangVisitor.h (1)

38-39: Review Approved: visitFuncDefs Addition Verified

All cross-file references for the new visitFuncDefs method have been checked and are consistent:

  • TaskDefLangVisitor.h declares
    virtual std::any visitFuncDefs(TaskDefLangParser::FuncDefsContext *context) = 0; (line 38).

  • TaskDefLangParser.h defines
    class FuncDefsContext : public antlr4::ParserRuleContext (lines 59, 112).

  • TaskDefLangBaseVisitor.h overrides
    virtual std::any visitFuncDefs(TaskDefLangParser::FuncDefsContext *ctx) override (line 39).

  • TaskDefLangParser.cpp implements the accept method to dispatch to
    parserVisitor->visitFuncDefs(this); (line 402).

No further changes are required—this addition correctly aligns with the grammar evolution.

src/spider/tdl/parser/antlr_generated/TaskDefLangBaseVisitor.h (1)

39-41: BaseVisitor override for visitFuncDefs: LGTM.

The default visitChildren(ctx) behaviour is consistent with other nodes and keeps backward-compatible traversal semantics.

src/spider/tdl/parser/parse.hpp (2)

5-5: Header hygiene: include is appropriate.

Good call adding for the unique_ptr return type.


21-21: Confirm std_checked alias availability

The alias boost::outcome_v2::std_checked<T, E> is indeed declared in <boost/outcome/std_result.hpp> and brought into boost::outcome_v2 via BOOST_OUTCOME_V2_NAMESPACE(live.boost.org). No additional headers or aliases are required to use std_checked.

If you instead intend to use the result<T, E> alias, switch to:

  • Header: <boost/outcome/result.hpp>
  • Type: boost::outcome_v2::result<std::unique_ptr<ast::TranslationUnit>, Error>

Otherwise, your current include and use of std_checked across the project is correct.

tests/tdl/test-parser.cpp (1)

8-8: Include of AST nodes header in tests is appropriate.

Needed for accessing ast types (e.g., Namespace::ErrorCodeEnum) and for serialization. No issues.

src/spider/tdl/parser/parse.cpp (2)

47-60: Exception prioritization logic is correct.

Catching parser::Exception and still preferring ANTLR listener errors matches the intended precedence semantics.


18-20: Signature alignment confirmed across declaration, definition, and call sites

  • The function declaration in src/spider/tdl/parser/parse.hpp (lines 20–21) and the definition in src/spider/tdl/parser/parse.cpp (lines 18–19) both now return
    boost::outcome_v2::std_checked<std::unique_ptr<ast::TranslationUnit>, Error>.
  • All call sites (e.g. in tests/tdl/test-parser.cpp) invoke parse_translation_unit_from_istream via auto and correctly handle the outcome.

No further updates are required.

src/spider/tdl/parser/antlr_generated/TaskDefLangParser.cpp (9)

2-11: Including AST and Exception headers in the generated parser is warranted.

Required to construct AST nodes and surface location-aware exceptions during parse-time AST building.


234-238: Good: TranslationUnit root is created early with a well-defined SourceLocation.

Location uses _localctx->start (0-based column), consistent with tests expecting positions like {1, 1} and {1, 10}.

If the project decides to use 1-based columns later, this is the central place to adjust.


256-281: Safe insertion into TU with location-propagated error reporting.

Using throw_tryv(...) to add namespaces/structs ensures semantic errors are surfaced at the declaration’s location. Nicely done.


345-368: Namespace AST construction looks correct and exception-safe.

  • Id and funcDefs are moved into Namespace::create.
  • Location captured from rule start is consistent with other rules.

989-999: Identifier node creation and location capture are correct.

Constructing Identifier with token text and start location matches the serialization expectations.


1050-1091: VarType rule: struct references vs builtins are cleanly separated.

ID → Struct type with location; Builtins forwarded from builtinType. The error handling via throw_tryx on Struct creation is appropriate.


1225-1295: Tuple element list supports empty and multi-element cases (Tuple<>).

This aligns with tests (Empty tuple case). The accumulation logic mirrors NamedVarList/FuncDefs.


1532-1660: Builtin types: location computed once per alternative; correct forwarding for list/map.

  • Primitive Int/Float/Bool nodes get a consistent loc.
  • Container alternatives forward the retval from nested rules.

1662-1702: Semantic predicate wiring is consistent with new rules.

funcDefsSempred, namedVarListSempred, varTypeListSempred indices align with rule indices introduced earlier.

src/spider/tdl/parser/antlr_generated/TaskDefLangParser.h (5)

75-87: Making TranslationUnitContext expose the AST root (unique_ptr) is aligned with the new API.

This cleanly transfers ownership to parse.cpp via std::move(context->tu).


97-104: NamespaceContext additions (idContext + funcDefsContext + retval) look coherent.

No concerns; this mirrors the codegen in the .cpp.


112-129: FuncDefsContext public surface is sensible for a left-recursive list.

Exposes child accessors and the accumulated retval vector. Matches the visitor additions.


360-365: New funcDefs semantic predicate hook is correctly declared.

Keeps parity with the .cpp and the new rule.


33-38: Rule index renumbering is internal to generated code—no external references found

  • A ripgrep search for getRuleIndex() and TaskDefLangParser::Rule… references only returned hits in the ANTLR-generated parser files (TaskDefLangParser.h/.cpp).
  • There are no integer comparisons or hard-coded rule-ID usages in any other part of the codebase.

The shift of RuleFuncDefs and subsequent enum values is confined to the generated parser. No client code needs updating.

Comment thread src/spider/tdl/parser/parse.hpp
Comment thread src/spider/tdl/parser/TaskDefLang.g4
Comment thread src/spider/tdl/parser/TaskDefLang.g4
sitaowang1998
sitaowang1998 previously approved these changes Aug 25, 2025

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (4)
src/spider/tdl/parser/TaskDefLang.g4 (2)

54-63: Refactor left-recursive funcDefs to iterative EBNF to simplify and avoid sempred complexity.

ANTLR 4 supports left recursion, but combining it with attribute actions adds complexity and increases the chance of subtle bugs. An iterative form is simpler and avoids deep recursion on long lists. This also removes the need for a dedicated sempred for this rule.

Apply this diff at the grammar level:

-funcDefs returns [std::vector<std::unique_ptr<spider::tdl::parser::ast::Node>> retval]
-: funcDef {
-    $retval.clear();
-    $retval.emplace_back(std::move($funcDef.retval));
-}
-| parsed_funcs=funcDefs funcDef {
-    $retval = std::move($parsed_funcs.retval);
-    $retval.emplace_back(std::move($funcDef.retval));
-}
-;
+funcDefs returns [std::vector<std::unique_ptr<spider::tdl::parser::ast::Node>> retval]
+@init { $retval.clear(); }
+: f=funcDef { $retval.emplace_back(std::move($f.retval)); }
+  ( f2=funcDef { $retval.emplace_back(std::move($f2.retval)); } )*
+;

118-127: Refactor left-recursive namedVarList to iterative EBNF.

Same rationale as funcDefs: reduces complexity, avoids recursion depth on large param lists, and removes sempreds.

Suggested replacement:

-namedVarList returns [std::vector<std::unique_ptr<spider::tdl::parser::ast::Node>> retval]
-: namedVar {
-    $retval.clear();
-    $retval.emplace_back(std::move($namedVar.retval));
-}
-| parsed_named_vars=namedVarList ',' namedVar {
-    $retval = std::move($parsed_named_vars.retval);
-    $retval.emplace_back(std::move($namedVar.retval));
-}
-;
+namedVarList returns [std::vector<std::unique_ptr<spider::tdl::parser::ast::Node>> retval]
+@init { $retval.clear(); }
+: nv=namedVar { $retval.emplace_back(std::move($nv.retval)); }
+  ( ',' nv2=namedVar { $retval.emplace_back(std::move($nv2.retval)); } )*
+;
src/spider/tdl/parser/antlr_generated/TaskDefLangParser.cpp (2)

380-473: funcDefs left recursion introduces sempred and recursion depth for long lists. Prefer iterative form.

This complexity is a direct result of the grammar shape. Switching the grammar to iterative EBNF will regenerate this section into a simpler loop without sempreds and with less stack use on large inputs.

If you adopt the grammar diff suggested in TaskDefLang.g4, re-generate to pick up the improvement here.


799-865: namedVarList left recursion has the same maintainability and perf drawbacks.

Regenerate after the grammar refactor; this will become a simple loop and remove namedVarListSempred.

🧹 Nitpick comments (4)
src/spider/tdl/parser/TaskDefLang.g4 (2)

92-99: Minor grammar tidy-up: prefer EBNF instead of explicit empty alternative.

You can avoid an explicit empty alternative and imperative clear() by using a single optional group with @init. This reduces actions surface area.

Proposed change:

-params returns [std::vector<std::unique_ptr<spider::tdl::parser::ast::Node>> retval]
-: namedVarList {
-    $retval = std::move($namedVarList.retval);
-}
-| {
-    $retval.clear();
-}
-;
+params returns [std::vector<std::unique_ptr<spider::tdl::parser::ast::Node>> retval]
+@init { $retval.clear(); }
+: ( namedVarList { $retval = std::move($namedVarList.retval); } )?
+;

183-195: Empty alternative in varTypeList enables Tuple<>; reconfirm whether zero-arity tuples are desired.

The explicit empty alternative permits Tuple<>. If that’s not desired, switch to a one-or-more EBNF. If it is desired, we can still simplify the rule to an optional plus-form without left recursion.

Option A (keep allowing empty, remove left recursion):

-varTypeList returns [std::vector<std::unique_ptr<spider::tdl::parser::ast::Node>> retval]
-: varType {
-    $retval.clear();
-    $retval.emplace_back(std::move($varType.retval));
-}
-| parsed_var_types=varTypeList ',' varType {
-    $retval = std::move($parsed_var_types.retval);
-    $retval.emplace_back(std::move($varType.retval));
-}
-| {
-    $retval.clear();
-}
-;
+varTypeList returns [std::vector<std::unique_ptr<spider::tdl::parser::ast::Node>> retval]
+@init { $retval.clear(); }
+: ( vt=varType { $retval.emplace_back(std::move($vt.retval)); }
+    ( ',' vt2=varType { $retval.emplace_back(std::move($vt2.retval)); } )*
+  )?
+;

Option B (disallow empty tuples):

+varTypeList returns [std::vector<std::unique_ptr<spider::tdl::parser::ast::Node>> retval]
+@init { $retval.clear(); }
+: vt=varType { $retval.emplace_back(std::move($vt.retval)); }
+  ( ',' vt2=varType { $retval.emplace_back(std::move($vt2.retval)); } )*
+;
src/spider/tdl/parser/antlr_generated/TaskDefLangParser.cpp (2)

1215-1298: VarTypeList permits empty; Tuple<> is therefore accepted. Confirm semantics.

The base-case branch that clears retval is the generated counterpart of the empty alternative. If zero-arity tuples are not part of the type system, switch to a one-or-more rule and regenerate.


1665-1705: Sempreds exist only due to left-recursive list rules.

They’ll disappear after the EBNF refactor, simplifying the parser.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 0fe01bb and c94eadb.

📒 Files selected for processing (2)
  • src/spider/tdl/parser/TaskDefLang.g4 (1 hunks)
  • src/spider/tdl/parser/antlr_generated/TaskDefLangParser.cpp (42 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/spider/tdl/parser/antlr_generated/TaskDefLangParser.cpp (1)
src/spider/tdl/parser/Exception.hpp (1)
  • throw_tryx (26-29)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: non-storage-unit-tests (ubuntu-22.04)
  • GitHub Check: lint
  • GitHub Check: non-storage-unit-tests (ubuntu-24.04)
🔇 Additional comments (22)
src/spider/tdl/parser/TaskDefLang.g4 (13)

3-13: Header injection looks correct and minimal.

Includes for AST specs, Exception, and SourceLocation are necessary for the in-grammar actions. No issues spotted.


15-35: Solid TU construction and error propagation.

Creating the TranslationUnit in @init and attaching namespaces/structs via throw_tryv with precise SourceLocation is clean and exception-safe.


37-52: Namespace node assembly is clear and location-aware.

Good use of throw_tryx and moving retvals. This also keeps parse-time semantic failures localized to the rule’s start location.


65-81: Function assembly is correct; SourceLocation captured at rule start.

No correctness concerns. Move semantics and exception translation look good.


83-90: Optional return is well-encoded.

Returning nullptr when '->' is absent is unambiguous and keeps the AST concise.


101-116: NamedVar node creation is consistent with the rest of the AST actions.

Location and exception wrapping are correct.


129-144: Trailing comma permitted in structDef but not in params — intentional?

Struct fields allow an optional trailing ',' before '}', whereas function params do not. If this difference is not intentional, consider normalising the experience (either allow trailing commas in params or disallow here).

Would you like a follow-up diff to add an optional trailing comma to params for consistency?


158-172: VarType excludes tupleType; confirm type system intent.

Currently, tupleType appears only in retType, so tuples cannot be used as parameter or field types, nor nested in List/Map. If that’s by design, consider documenting it in the grammar comments; if not, we can extend varType accordingly.

I can send a focused diff to allow tupleType in varType (and thereby in List/Map if desired).


197-208: List type construction is correct.

Good move semantics and location handling.


210-225: Map type construction is correct; key/value types are varType.

Note: with the current grammar, keys/values cannot be tuples — only builtin/list/map/struct. Confirm that this restriction is intentional.


227-238: Tuple type creation is clean; semantics depend on varTypeList choice.

Once you confirm whether empty tuples are allowed, we can lock this down with either Option A or B above.


240-280: Builtin types are clear; tuple intentionally excluded here.

Loc is captured in @init, which is appropriate. Inclusion of List/Map as “builtin” aligns with current type model.


282-285: Lexical rules (ID/SPACE/COMMENT) are fine.

Skipping whitespace/comments in the lexer keeps parser rules tidy.

src/spider/tdl/parser/antlr_generated/TaskDefLangParser.cpp (9)

2-11: Generated includes from @Header are correctly injected.

Matches the grammar’s @Header; no issues.


66-70: Rule name table correctly reflects new/renamed rules.

Addition of funcDefs and other AST-bearing rules is reflected; OK.


230-237: TranslationUnit assembly matches grammar actions and uses throw_tryv.

Namespace/StructSpec attachments are exception-wrapped and location-aware. Looks correct.

Also applies to: 256-281


345-369: Namespace context wires id + funcDefs into Namespace AST cleanly.

Everything aligns with the grammar; no issues.


894-951: Trailing comma acceptance is implemented; confirm it’s intentionally limited to structDef.

Params do not accept a trailing comma; struct fields do. If that asymmetry isn’t desired, adjust the grammar and regenerate.


1538-1663: BuiltinType covers primitives/List/Map; tuple types are excluded here by design.

No correctness concerns. If you later allow tuple as a general varType, this section will need coordinated changes.


653-697: Return/params/funcDef behaviours align with the grammar and AST actions.

Good balance of optionality (ret), empty params, and location-aware function construction.

Also applies to: 581-619, 505-547


1038-1100: Type selection paths are accurate; confirm tuple restrictions outside returns.

varType disallows tuple; retType allows it (including via Tuple<...>). If this is intentional, consider a brief comment in the grammar to guide future contributors.

Also applies to: 1129-1185


976-1009: Identifier AST creation correctly uses token text and SourceLocation.

No issues.

sitaowang1998
sitaowang1998 previously approved these changes Aug 25, 2025

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
src/spider/tdl/parser/antlr_generated/TaskDefLangParser.cpp (1)

231-235: Generated code won’t compile as-is due to unqualified SourceLocation and TU create brace-init

  • Lines 231–235: TranslationUnit::create({ ... }) should receive a spider::tdl::parser::SourceLocation{...}.
  • Multiple blocks construct SourceLocation const loc{...} without namespace qualification (e.g., Lines 353–366, 504–517, 718–730, 881–893, 1286–1294, 1359–1371, 1428–1436, 1479–1483). These will be undefined.

Do not patch this file directly. Fix the grammar actions (TaskDefLang.g4) as suggested; regenerate to produce compilable code.

Use this quick check:

#!/bin/bash
set -euo pipefail
# TU create with ambiguous brace-init
rg -n 'TranslationUnit::create\(\s*\{' src/spider/tdl/parser/antlr_generated/TaskDefLangParser.cpp
# Unqualified SourceLocation
rg -nP '\b(?<!spider::tdl::parser::)SourceLocation\b' src/spider/tdl/parser/antlr_generated/TaskDefLangParser.cpp -S

Also applies to: 353-366, 504-517, 718-730, 881-893, 1286-1294, 1359-1371, 1428-1436, 1493-1595

🧹 Nitpick comments (6)
src/spider/tdl/parser/TaskDefLang.g4 (4)

54-61: Confirm intent: namespaces now require ≥1 function (funcDefs uses “+”)

funcDefs is +-quantified, making namespace Foo {} invalid. If empty namespaces should be allowed, switch to *.

-: (funcDef {
+: (funcDef {
     $retval.emplace_back(std::move($funcDef.retval));
-})+
+})*
 ;

181-194: Tuple<> emptiness semantics: do you want to allow Tuple<> (empty)?

varTypeList’s second alternative returns an empty vector when the next token is >; this makes Tuple<> legal. If a non-empty tuple is required, drop the empty alternative. If a 2+ element tuple is required, enforce it here.

  • Non-empty (≥1):
-: first_var_type=varType { ... } (',' subsequent_var_type=varType { ... })*
-| {
-    $retval.clear();
-}
+: first_var_type=varType {
+    $retval.emplace_back(std::move($first_var_type.retval));
+} (',' subsequent_var_type=varType {
+    $retval.emplace_back(std::move($subsequent_var_type.retval));
+})*
 ;
  • At least 2 elements:
-: first_var_type=varType { ... } (',' subsequent_var_type=varType { ... })*
+: first_var_type=varType {
+    $retval.emplace_back(std::move($first_var_type.retval));
+} ',' second_var_type=varType {
+    $retval.emplace_back(std::move($second_var_type.retval));
+} (',' subsequent_var_type=varType {
+    $retval.emplace_back(std::move($subsequent_var_type.retval));
+})*
 ;

156-170: Design choice: tuples only allowed in return types — verify or support tuples as parameter/member types

Currently, varType excludes tupleType, so tuples can appear only in returns (retType). If that limitation isn’t intentional, extend varType to include tupleType to enable nested types like List<Tuple<...>> and parameter/struct fields with tuple types.

Minimal change:

 varType returns [std::unique_ptr<spider::tdl::parser::ast::Node> retval]
-: builtinType {
+: builtinType {
     $retval = std::move($builtinType.retval);
 }
-| id {
+| id {
     ...
 }
+| tupleType {
+    $retval = std::move($tupleType.retval);
+}
 ;

If you adopt this, you can keep tupleType in retType or simplify retType: varType;.

Also applies to: 172-179


127-142: Struct trailing comma handling is good — consider mirroring for function params for consistency

structDef accepts an optional trailing comma before }; params/namedVarList do not. Consider allowing a trailing comma in params for consistency and nicer diffs.

Example:

-namedVarList ... : first=namedVar { ... } (',' next=namedVar { ... })* ;
+namedVarList ... : first=namedVar { ... } (',' next=namedVar { ... })* (',')? ;
src/spider/tdl/parser/antlr_generated/TaskDefLangParser.cpp (1)

96-112: Behavioural confirmation: empty varTypeList alternative maps to lookahead ‘>’

The generated parser selects the empty varTypeList alt when lookahead is T__13 (‘>’). If you decide to disallow Tuple<>, adjust the grammar as noted; the generator will update these switch cases accordingly.

Also applies to: 420-434, 1204-1216, 1405-1424

src/spider/tdl/parser/antlr_generated/TaskDefLangParser.h (1)

2-11: Consider forward declarations to reduce header coupling and build times

Including heavy AST headers in the generated header increases compile times for all dependents. Since this header only needs pointer types, forward-declare the AST types here and include the full headers in the generated .cpp (which already happens via @Header). With ANTLR C++ target, you can move full includes to @parser::header (if template supports) or keep them in the .g4 @header but wrap forward declarations specifically for the .h via a preprocessor guard.

Example forward decls (placed before the class):

  • namespace spider::tdl::parser::ast { struct Node; struct TranslationUnit; struct Bool; struct Int; struct Float; struct List; struct Map; struct Tuple; struct StructSpec; }

This is optional and depends on your generation strategy, but it can materially speed up builds on larger codebases.

Also applies to: 75-88, 93-107, 112-127, 162-175, 194-210, 226-241, 244-259, 260-276, 277-293, 294-309, 310-325, 326-356

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between c94eadb and 74b1072.

📒 Files selected for processing (4)
  • src/spider/tdl/parser/TaskDefLang.g4 (1 hunks)
  • src/spider/tdl/parser/antlr_generated/TaskDefLangParser.cpp (37 hunks)
  • src/spider/tdl/parser/antlr_generated/TaskDefLangParser.h (17 hunks)
  • tests/tdl/test-parser.cpp (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/tdl/test-parser.cpp
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-25T21:42:57.051Z
Learnt from: LinZhihao-723
PR: y-scope/spider#210
File: src/spider/tdl/parser/parse.hpp:21-21
Timestamp: 2025-08-25T21:42:57.051Z
Learning: The spider TDL parser API (parse_translation_unit_from_istream) is in early development with no external users yet, so breaking changes don't require full version bumping and changelog documentation.

Applied to files:

  • src/spider/tdl/parser/antlr_generated/TaskDefLangParser.cpp
  • src/spider/tdl/parser/TaskDefLang.g4
🧬 Code graph analysis (2)
src/spider/tdl/parser/antlr_generated/TaskDefLangParser.cpp (1)
src/spider/tdl/parser/Exception.hpp (1)
  • throw_tryx (26-29)
src/spider/tdl/parser/antlr_generated/TaskDefLangParser.h (3)
src/spider/tdl/parser/antlr_generated/TaskDefLangBaseVisitor.h (17)
  • spider (22-100)
  • std (35-37)
  • std (39-41)
  • std (43-45)
  • std (47-49)
  • std (51-53)
  • std (55-57)
  • std (59-61)
  • std (63-65)
  • std (67-69)
  • std (71-73)
  • std (75-77)
  • std (79-81)
  • std (83-85)
  • std (87-89)
  • std (91-93)
  • std (95-97)
src/spider/tdl/parser/antlr_generated/TaskDefLangVisitor.h (1)
  • spider (22-71)
src/spider/tdl/parser/antlr_generated/TaskDefLangParser.cpp (56)
  • getRuleIndex (215-217)
  • getRuleIndex (215-215)
  • getRuleIndex (317-319)
  • getRuleIndex (317-317)
  • getRuleIndex (392-394)
  • getRuleIndex (392-392)
  • getRuleIndex (464-466)
  • getRuleIndex (464-464)
  • getRuleIndex (540-542)
  • getRuleIndex (540-540)
  • getRuleIndex (612-614)
  • getRuleIndex (612-612)
  • getRuleIndex (686-688)
  • getRuleIndex (686-686)
  • getRuleIndex (757-759)
  • getRuleIndex (757-757)
  • id (308-310)
  • id (308-308)
  • id (451-453)
  • id (451-451)
  • id (677-679)
  • id (677-677)
  • id (825-827)
  • id (825-825)
  • id (928-928)
  • id (973-975)
  • id (973-973)
  • funcDefs (312-314)
  • funcDefs (312-312)
  • funcDefs (404-404)
  • accept (220-225)
  • accept (220-220)
  • accept (322-327)
  • accept (322-322)
  • accept (397-402)
  • accept (397-397)
  • accept (469-474)
  • accept (469-469)
  • accept (545-550)
  • accept (545-545)
  • accept (617-622)
  • accept (617-617)
  • accept (691-696)
  • accept (691-691)
  • accept (762-767)
  • accept (762-762)
  • namespace_ (198-200)
  • namespace_ (198-198)
  • namespace_ (202-204)
  • namespace_ (202-202)
  • namespace_ (329-329)
  • namedVar (698-698)
  • namedVar (748-750)
  • namedVar (748-748)
  • namedVar (752-754)
  • namedVar (752-752)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: non-storage-unit-tests (ubuntu-22.04)
  • GitHub Check: non-storage-unit-tests (ubuntu-24.04)
  • GitHub Check: lint
🔇 Additional comments (1)
src/spider/tdl/parser/antlr_generated/TaskDefLangParser.h (1)

33-38: Rule indices renumbered — verify downstream consumers and tests

Rules shifted due to the new FuncDefs non-terminal. If any tooling or tests reference rule indices or names, ensure they don’t rely on previous numeric values.

Comment thread src/spider/tdl/parser/TaskDefLang.g4
@LinZhihao-723
LinZhihao-723 merged commit d9db9f1 into y-scope:main Aug 25, 2025
7 checks passed
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.

2 participants