Tencent/matrix · error

Empty grammar.

Error message

Empty grammar.

What it means

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.

Solutions

  1. Open the .y file and add at least one rule after the %% separator (e.g. `input ::= .;`)
  2. Check the declarations section: the second %% (start of rules) must be present; add it if missing
  3. Audit %ifdef/%ifndef blocks around the rule section and ensure at least one branch keeps rules for the current build flags
  4. Verify you are invoking lemon on the actual grammar file, not an include/tokens file

Example fix

// before (foo.y)
%name Foo
%token_type {int}
%%
// after
%name Foo
%token_type {int}
%%
input ::= expr.
expr ::= INT.
Defensive patterns

Strategy: validation

Validate before calling

// shell check before invoking lemon
grep -q '^%%' grammar.y || { echo 'grammar.y has no rules section (missing second %%)'; exit 1; }
after=$(awk '/^%%/{c++} END{print c+0}' grammar.y)
[ "$after" -ge 2 ] && awk 'p;/^%%/{p=1}' grammar.y | grep -vE '^\s*(//.*)?$' | grep -q . && echo OK || { echo 'rules section is empty'; exit 1; }

Prevention

When it happens

Trigger: 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.

Common situations: 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).

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of Tencent/matrix@3b8293bd65 (2026-09-08). Data as JSON: /api/errors/0662c9a48569ce42. Report an issue: GitHub.

Appendix: source

Thrown at matrix/matrix-android/matrix-sqlite-lint/src/lemon/lemon-gen/lemon.c:1450

  lem.filename = OptArg(0);
  lem.basisflag = basisflag;
  lem.has_fallback = 0;
  lem.nconflict = 0;
  lem.name = lem.include = lem.arg = lem.tokentype = lem.start = 0;
  lem.vartype = 0;
  lem.stacksize = 0;
  lem.error = lem.overflow = lem.failure = lem.accept = lem.tokendest =
     lem.tokenprefix = lem.outname = lem.extracode = 0;
  lem.vardest = 0;
  lem.tablesize = 0;
  Symbol_new("$");
  lem.errsym = Symbol_new("error");

  /* Parse the input file */
  Parse(&lem);
  if( lem.errorcnt ) exit(lem.errorcnt);
  if( lem.rule==0 ){
    fprintf(stderr,"Empty grammar.\n");
    exit(1);
  }

  /* Count and index the symbols of the grammar */
  lem.nsymbol = Symbol_count();
  Symbol_new("{default}");
  lem.symbols = Symbol_arrayof();
  for(i=0; i<=lem.nsymbol; i++) lem.symbols[i]->index = i;
  qsort(lem.symbols,lem.nsymbol+1,sizeof(struct symbol*),
        (int(*)())Symbolcmpp);
  for(i=0; i<=lem.nsymbol; i++) lem.symbols[i]->index = i;
  for(i=1; isupper(lem.symbols[i]->name[0]); i++);
  lem.nterminal = i;

  /* Generate a reprint of the grammar, if requested on the command line */
  if( rpflag ){
    Reprint(&lem);
  }else{

View on GitHub (pinned to 3b8293bd65)