{"record":{"id":"0662c9a48569ce42","repo":"Tencent/matrix","slug":"empty-grammar","errorCode":null,"errorMessage":"Empty grammar.\n","messagePattern":"Empty grammar\\.\n","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"matrix/matrix-android/matrix-sqlite-lint/src/lemon/lemon-gen/lemon.c","lineNumber":1450,"sourceCode":"  lem.filename = OptArg(0);\n  lem.basisflag = basisflag;\n  lem.has_fallback = 0;\n  lem.nconflict = 0;\n  lem.name = lem.include = lem.arg = lem.tokentype = lem.start = 0;\n  lem.vartype = 0;\n  lem.stacksize = 0;\n  lem.error = lem.overflow = lem.failure = lem.accept = lem.tokendest =\n     lem.tokenprefix = lem.outname = lem.extracode = 0;\n  lem.vardest = 0;\n  lem.tablesize = 0;\n  Symbol_new(\"$\");\n  lem.errsym = Symbol_new(\"error\");\n\n  /* Parse the input file */\n  Parse(&lem);\n  if( lem.errorcnt ) exit(lem.errorcnt);\n  if( lem.rule==0 ){\n    fprintf(stderr,\"Empty grammar.\\n\");\n    exit(1);\n  }\n\n  /* Count and index the symbols of the grammar */\n  lem.nsymbol = Symbol_count();\n  Symbol_new(\"{default}\");\n  lem.symbols = Symbol_arrayof();\n  for(i=0; i<=lem.nsymbol; i++) lem.symbols[i]->index = i;\n  qsort(lem.symbols,lem.nsymbol+1,sizeof(struct symbol*),\n        (int(*)())Symbolcmpp);\n  for(i=0; i<=lem.nsymbol; i++) lem.symbols[i]->index = i;\n  for(i=1; isupper(lem.symbols[i]->name[0]); i++);\n  lem.nterminal = i;\n\n  /* Generate a reprint of the grammar, if requested on the command line */\n  if( rpflag ){\n    Reprint(&lem);\n  }else{","sourceCodeStart":1432,"sourceCodeEnd":1468,"githubUrl":"https://github.com/Tencent/matrix/blob/3b8293bd65d47eeea7caf1f32a3a5d4d5eab60e7/matrix/matrix-android/matrix-sqlite-lint/src/lemon/lemon-gen/lemon.c#L1432-L1468","documentation":"Lemon (the SQLite parser generator, bundled with matrix-sqlite-lint) prints 'Empty grammar.' and exits with status 1 when, after parsing the .y grammar file, no grammar rules were defined (lem.rule==0). The generator cannot build a parser from zero rules, so it aborts before symbol counting. This means the input file either had no '%%' rule section or every rule was excluded by conditional compilation.","triggerScenarios":"Running `lemon foo.y` where foo.y contains no rules after %% (only %name/%token declarations or comments), or all rules were stripped by %ifdef/%ifndef blocks whose condition excluded the entire grammar section.","commonSituations":"Hand-written .y files where the author stopped after the declarations section and forgot the rules after the second %%; scripted generation of grammars that emits an empty rule section; a %ifdef guard whose macro is undefined so all rules are skipped; wrong file passed to lemon (a header or token list instead of a grammar).","solutions":["Open the .y file and add at least one rule after the %% separator (e.g. `input ::= .;`)","Check the declarations section: the second %% (start of rules) must be present; add it if missing","Audit %ifdef/%ifndef blocks around the rule section and ensure at least one branch keeps rules for the current build flags","Verify you are invoking lemon on the actual grammar file, not an include/tokens file"],"exampleFix":"// before (foo.y)\n%name Foo\n%token_type {int}\n%%\n// after\n%name Foo\n%token_type {int}\n%%\ninput ::= expr.\nexpr ::= INT.","handlingStrategy":"validation","validationCode":"// shell check before invoking lemon\ngrep -q '^%%' grammar.y || { echo 'grammar.y has no rules section (missing second %%)'; exit 1; }\nafter=$(awk '/^%%/{c++} END{print c+0}' grammar.y)\n[ \"$after\" -ge 2 ] && awk 'p;/^%%/{p=1}' grammar.y | grep -vE '^\\s*(//.*)?$' | grep -q . && echo OK || { echo 'rules section is empty'; exit 1; }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always end a .y file with a rules section after the second %%","Add a lint step that asserts at least one production exists before running lemon","Review %ifdef guards so at least one branch keeps rules","Run lemon on the actual grammar file, not auxiliary token lists"],"tags":["grammar","parser-generator","lemon","build-tool"],"backgroundTag":"empty-required-field","analyzedSha":"3b8293bd65d47eeea7caf1f32a3a5d4d5eab60e7","analyzedAt":"2026-09-08T08:01:39.722Z","contentChangedAt":"2026-09-08T08:01:39.722Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}