{"record":{"id":"d91f4e8d82174866","repo":"mono/mono","slug":"s-e-line-d-of-s-unterminated-action","errorCode":null,"errorMessage":"%s: e - line %d of \"%s\", unterminated action\n","messagePattern":"(.+?): e - line (.+?) of \"(.+?)\", unterminated action\n","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"mcs/jay/error.c","lineNumber":231,"sourceCode":"void\nterminal_lhs (int s_lineno)\n{\n    fprintf(stderr, \"%s: e - line %d of \\\"%s\\\", a token appears on the lhs \\\nof a production\\n\", myname, s_lineno, input_file_name);\n    done(1);\n}\n\nvoid\nprec_redeclared (void)\n{\n    fprintf(stderr, \"%s: w - line %d of  \\\"%s\\\", conflicting %%prec \\\nspecifiers\\n\", myname, lineno, input_file_name);\n}\n\nvoid\nunterminated_action (int a_lineno, const char *a_line, const char *a_cptr)\n{\n    fprintf(stderr, \"%s: e - line %d of \\\"%s\\\", unterminated action\\n\",\n\t    myname, a_lineno, input_file_name);\n    print_pos(a_line, a_cptr);\n    done(1);\n}\n\nvoid\ndollar_warning (int a_lineno, int i)\n{\n    fprintf(stderr, \"%s: w - line %d of \\\"%s\\\", $%d references beyond the \\\nend of the current rule\\n\", myname, a_lineno, input_file_name, i);\n}\n\nvoid\ndollar_error (int a_lineno, const char *a_line, char *a_cptr)\n{\n    fprintf(stderr, \"%s: e - line %d of \\\"%s\\\", illegal $-name\\n\",\n\t    myname, a_lineno, input_file_name);\n    print_pos(a_line, a_cptr);","sourceCodeStart":213,"sourceCodeEnd":249,"githubUrl":"https://github.com/mono/mono/blob/0f53e9e151d92944cacab3e24ac359410c606df6/mcs/jay/error.c#L213-L249","documentation":"Emitted by unterminated_action() in mcs/jay/error.c:231, reached from copy_action() (reader.c:1189) when an action block `{ ... }` reaches end-of-file (get_line() returns NULL) before its closing brace. jay tracks brace depth while copying the embedded C# action; an unbalanced brace means the action never terminates, so generation aborts via done(1) after printing the offending position.","triggerScenarios":"An action `{ ... ` with no matching `}`; a brace opened in a string or comment that confuses depth counting; a rule action that continues past the last line of the file.","commonSituations":"Forgetting the closing brace of an action; brace inside a C# string literal or char literal that throws off jay's simple brace counter; trailing action on the file's final rule with no newline/brace.","solutions":["Add the missing `}` to close every action block, matching `{` count.","Escape or restructure braces that appear inside string/char literals within actions so jay's depth tracking stays balanced.","Ensure the file ends with a newline after the last action's closing brace."],"exampleFix":"// before\nexpr : expr '+' expr { yylval = $1 + $3;   /* no closing brace -> unterminated_action */\n// after\nexpr : expr '+' expr { yylval = $1 + $3; }","handlingStrategy":"validation","validationCode":"# Brace balance across action blocks: open and close counts in the rules section must match.\nsec=$(awk 'f&&/^%%/{exit} /^%%/{f=1;next} f' grammar.jay)\nopens=$(printf '%s' \"$sec\" | tr -cd '{' | wc -c)\ncloses=$(printf '%s' \"$sec\" | tr -cd '}' | wc -c)\n[ \"$opens\" -eq \"$closes\" ] || { echo \"unbalanced braces in actions: $opens open vs $closes close\"; exit 1; }","typeGuard":null,"tryCatchPattern":"jay -c -o Parser.cs grammar.jay || { echo \"jay aborted; check for an unterminated action (missing closing brace)\"; exit 1; }","preventionTips":["Close every action block on the same rule; match each `{` with a `}`.","Escape or restructure braces inside C# string/char literals in actions.","Run a brace-balance lint over the rules section before invoking jay."],"tags":["jay","grammar","action","unterminated","braces"],"backgroundTag":null,"analyzedSha":"0f53e9e151d92944cacab3e24ac359410c606df6","analyzedAt":"2026-08-13T18:54:37.190Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}