Skip to content

Build Lex and Yacc

lex_yacc_library

Used to describe a lex yacc target, generate a scanner and a grammer for a compiler.

Lex and yacc are often be used together. when we compile a lex file, yy.tab.h is needed which is generated by yacc. but when we compile yy.tab.cc which is generated from the yacc file. it call the parse function which is generated by lex.

If we saparate them into 2 libraries, there will depends on each other, there is a loop dependency.

So we build the in one rule, the srcs must be a tuple of 2 elements, which are the lex and yacc file. the suffix should be l and y for C code, and should be ll and yy for c++ result.

This rule will generate a library and a header file.

Attributes:

  • recursive=True — generate a reentrant C scanner.
  • prefix='xxx' — rename the yy symbol prefix (passed as flex -P / bison -p), so several parsers can coexist in one binary without their yyparse / yylval / ... globals colliding.
  • lexflags=[...] / yaccflags=[...] — extra flags passed straight through to flex / bison. Note that flags which change the names of the generated files are not supported: blade derives those names by its own rule and will not see the override.

lex_yacc_library also support most cc_library attributes.

Example:

lex_yacc_library(
     name = 'parser',
     srcs = [
         'line_parser.ll',
         'line_parser.yy'
     ],
     deps = [
         ":xcubetools",
     ],
     recursive = True
)

The generated header

The header bison -d emits is named after the yacc source: <yacc_file>.hh for a C++ grammar (.yy), or <yacc_file>.h for a C grammar (.y). For the example above it is line_parser.yy.hh, and it declares the tokens and yyparse.

A target that uses the parser includes it by its workspace-relative path, the same as any other generated header:

#include "path/to/line_parser.yy.hh"

Including it is also what lets the header dependency check see that your target genuinely uses the lex_yacc_library; relying only on the symbols (via your own forward declarations) without including this header would make the dependency look unused.