| # Copyright 2017-2020 The Verible Authors. |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| |
| """Build rule for generating C or C++ sources with Flex. |
| |
| IMPORTANT: we _strongly recommend_ that you include a unique and project- |
| specific `%option prefix="myproject"` directive in your scanner spec to avoid |
| very hard-to-debug symbol name conflict problems if two scanners are linked |
| into the same dynamically-linked executable. |
| |
| By default, flex includes the definition of a static function `yyunput` in its |
| output. If you never use the lex `unput` function in your lex rules, however, |
| `yyunput` will never be called. This causes problems building the output file, |
| as llvm issues warnings about static functions that are never called. To avoid |
| this problem, use `%option nounput` in the declarations section if your lex |
| rules never use `unput`. |
| |
| Note that if you use the c++ mode of flex, you will need to include the |
| boilerplate header `FlexLexer.h` file in any `cc_library` which includes the |
| generated flex scanner directly. This is typically done by |
| `#include <FlexLexer.h>` which typically is installed in /usr/include |
| when flex is installed. |
| |
| Examples |
| -------- |
| |
| This is a simple example. |
| ``` |
| genlex( |
| name = "html_lex_lex", |
| src = "html.lex", |
| out = "html_lexer.c", |
| ) |
| ``` |
| |
| This example uses a `.tab.hh` file. |
| ``` |
| genlex( |
| name = "rules_l", |
| src = "rules.lex", |
| includes = [ |
| "rules.tab.hh", |
| ], |
| out = "rules.yy.cc", |
| ) |
| ``` |
| """ |
| |
| def _genlex_impl(ctx): |
| """Implementation for genlex rule.""" |
| |
| # Compute the prefix, if not specified. |
| if ctx.attr.prefix: |
| prefix = ctx.attr.prefix |
| else: |
| prefix = ctx.file.src.basename.partition(".")[0] |
| |
| # Construct the arguments. |
| args = ctx.actions.args() |
| args.add("-o", ctx.outputs.out) |
| args.add("-P", prefix) |
| args.add_all(ctx.attr.lexopts) |
| args.add(ctx.file.src) |
| |
| ctx.actions.run( |
| executable = ctx.executable._flex, |
| env = { |
| "M4": ctx.executable._m4.path, |
| }, |
| arguments = [args], |
| inputs = ctx.files.src + ctx.files.includes, |
| tools = [ctx.executable._m4], |
| outputs = [ctx.outputs.out], |
| mnemonic = "Flex", |
| progress_message = "Generating %s from %s" % ( |
| ctx.outputs.out.short_path, |
| ctx.file.src.short_path, |
| ), |
| ) |
| |
| genlex = rule( |
| attrs = { |
| "src": attr.label( |
| mandatory = True, |
| allow_single_file = [ |
| ".l", |
| ".ll", |
| ".lex", |
| ".lpp", |
| ], |
| doc = "The .lex source file for this rule", |
| ), |
| "includes": attr.label_list( |
| allow_files = True, |
| doc = "A list of headers that are included by the .lex file", |
| ), |
| "out": attr.output( |
| mandatory = True, |
| doc = "The generated source file", |
| ), |
| "prefix": attr.string( |
| doc = "External symbol prefix for Flex. This string is " + |
| "passed to flex as the -P option, causing the resulting C " + |
| "file to define external functions named 'prefix'text, " + |
| "'prefix'in, etc. The default is the basename of the source" + |
| "file without the .lex extension.", |
| ), |
| "lexopts": attr.string_list( |
| doc = "A list of options to be added to the flex command line.", |
| ), |
| "_flex": attr.label( |
| default = Label("//bazel:flex_bin"), |
| executable = True, |
| cfg = "host", |
| ), |
| "_m4": attr.label( |
| default = Label("//bazel:m4_bin"), |
| executable = True, |
| cfg = "host", |
| ), |
| }, |
| doc = "Generate C/C++-language sources from a lex file using Flex.", |
| output_to_genfiles = True, |
| implementation = _genlex_impl, |
| ) |