Skip to content

Comments

Add -E / --all-errors flag to nwn_script_comp#153

Open
cgtudor wants to merge 3 commits intoniv:masterfrom
cgtudor:support-all-errors-output
Open

Add -E / --all-errors flag to nwn_script_comp#153
cgtudor wants to merge 3 commits intoniv:masterfrom
cgtudor:support-all-errors-output

Conversation

@cgtudor
Copy link

@cgtudor cgtudor commented Feb 11, 2026

Built on top of #152 and dependent on it. If I could have made that branch the base and have it still show in this repo, I would have.

Adds a new -E / --all-errors flag to nwn_script_comp that collects and reports all compilation errors in a file instead of stopping at the first one. This is useful for (potential) IDEs, language servers, and batch validation workflows.

Multi-error collection infrastructure

The compiler gains a multi-error mode controlled by SetCollectAllErrors(). When enabled:

  • Parse error recovery: Instead of tearing down compiler state on a parse error, the parser captures the error, skips forward to a synchronization point (; or } at brace depth 0), resets the SR stack, and continues parsing. This allows multiple parse errors in different functions to be reported in a single pass.
  • Semantic error recovery: The tree walker (WalkParseTree) saves and restores code-gen state around each FUNCTIONAL_UNIT node. A semantic error in one function rolls back that function and continues to the next.
  • Error accumulation: Errors are stored in m_vCapturedErrors / m_vnCapturedErrorStrRefs vectors (up to a configurable limit) and exposed through GetCollectedErrorCount() / GetCollectedError().
  • API surface: New C API functions (scriptCompApiSetCollectAllErrors, scriptCompApiGetCollectedErrorCount, scriptCompApiGetCollectedError) and corresponding Nim bindings.

Mixed parse + semantic error reporting

When a file has both parse errors and semantic errors in different functions, the initial implementation only reported parse errors; semantic errors in correctly-parsed functions were silently lost. This happened because:

  1. Parse error recovery called DeleteCompileStack() which destroyed the entire parse tree, including already-completed functions.
  2. CompileFile skipped GenerateFinalCodeFromParseTree entirely when parse errors existed, so the tree walker never ran.

The fix saves completed function subtrees from the SR stack before error recovery destroys them, accumulating them in m_pSavedParseTree. After parsing completes, these saved trees are walked for semantic errors via InitializeFinalCode + InsertGlobalVariablesInParseTree + WalkParseTree. Post-recovery functions that were parsed after the error but before EOF are also collected, including completing any pending grammar reductions (e.g., linking a function body that was still in pReturnTree).

For example, a file with a semantic error on line 31 and a parse error on line 43 now reports both:

_inc_socialrank.nss(43): ERROR: UNKNOWN STATE IN COMPILER [FUNCTIONAL_UNIT(0,6):VOID_IDENTIFIER]
_inc_socialrank.nss(31): ERROR: DECLARATION DOES NOT MATCH PARAMETERS

Output format

When -E is active, each collected error is printed as a separate log line. Without -E, the compiler behaves exactly as before (stops at the first error).

Testing

Tested with five scenarios:

Test Description Result
Pure semantic errors File with 2 type errors in separate functions 2 semantic errors reported
Pure parse errors File with 2 syntax errors in separate functions 2 parse errors reported
Mixed errors File with 1 parse error + 2 semantic errors in different functions All 3 errors reported
Mixed errors again Wrong arg count (line 31) + junk between ) and { (line 43) Both errors reported
No errors Normal file Compiles successfully (exit 0)

Also verified normal mode (without -E) is unaffected.

Changelog

Added

  • -E / --all-errors flag for nwn_script_comp: collects and reports all compilation errors per file instead of stopping at the first. Useful for IDEs and language servers.

Licence

  • I am licencing my change under the project's MIT licence, including all changes to GPL-3.0 licenced parts of the codebase.

This flag allows the compilation of a file (or files) without requiring an entry point (void main or StartingConditional). Useful for validating files, especially for compatibility with the vscode language server.
This is to support collecting and outputing all errors instead of exiting early after finding one. Useful for validation and language servers.
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