fuzzy_dl_owl2.fuzzydl.parser.tokenizer.generate
Single source of truth for all token / keyword tables in the parser.
Regenerates tokens.h, tokens.py, lexer_re2c.re and lexer_flex.l from one master list so keywords are never out of sync again.
- Usage:
python generate.py
A code generation utility that synchronizes token definitions and lexer source files for the FuzzyDL parser from a central list of keywords.
Description
Acting as the single source of truth for the parser infrastructure, this utility ensures that token definitions remain synchronized across C and Python environments. It dynamically loads the FuzzyDLKeyword enumeration from a separate constants module to derive the canonical list of language keywords and their string representations. By centralizing this data, the system prevents inconsistencies that often arise when maintaining separate token tables for different compiler components.
The generator constructs a comprehensive mapping of token names to integer codes, distinguishing between structural punctuation, meta tokens, and language-specific keywords. It produces a C header file containing an enum definition, a Python module exposing token constants, and a lexer specification compatible with either re2c or flex depending on the runtime arguments. During the generation of the Python module, the process preserves any hand-written logic by splitting the existing file content and appending it to the newly generated header.
To ensure correct lexical analysis, the generated lexer rules sort keywords by descending literal length so that longer identifiers are not shadowed by shorter prefixes. Additionally, the output sanitizes C identifiers by prefixing keyword names to avoid conflicts with system macros defined in standard headers. The resulting artifacts are written directly to the filesystem, providing a build-time step that automates the maintenance of the parser’s low-level scanning and tokenization logic.
Attributes
Functions
|
Returns the C enum identifier for a token name. |
Returns the keyword names sorted by literal longest-first so a prefix never |
|
Loads |
|
|
Returns the width of the widest quoted literal across a sequence of token |
|
Right-pads a quoted literal with spaces so columns line up in generated |
Returns the token names of the STRUCTURAL entries, dropping the Python display name. |
|
|
Renders the flex scanner source |
|
Renders the re2c scanner source |
|
Renders the C header |
|
Renders the Python module |
|
Regenerates the token/lexer source files from the master tables and writes them to disk. |
|
Returns the literal string that a token name matches in source. |
Module Contents
- _c_name(name: str) str[source]
Returns the C enum identifier for a token name.
The bare
FuzzyDLKeywordnames collide with system macros in C (e.g.DOMAINis defined by<math.h>), so every keyword / operator identifier is prefixed withKW_in the generated C. TheT_*special tokens already have a safe prefix and are emitted unchanged —_fdl_tuples.pyxrefers to them by those exact names.- Parameters:
name (str) – The token name to translate.
- Returns:
The safe C enum identifier.
- Return type:
str
- _lexer_keywords()[source]
Returns the keyword names sorted by literal longest-first so a prefix never shadows a longer keyword (e.g. ‘w-sum-zero’ before ‘w-sum’, ‘g-and’ before ‘and’).
- Returns:
The keyword names ordered by descending literal length, then name.
- Return type:
list[str]
- _load_fuzzy_dl_keyword()[source]
Loads
FuzzyDLKeywordstraight from constants.py by file path.This generator runs as a standalone script during the build (build.py), before the compiled
_fdl_lexerextension exists. A normal package import would drag infuzzy_dl_owl2.fuzzydl.parser.__init__→tokenizer.tokens→import _fdl_lexerand crash. constants.py only depends on the stdlib + pyparsing, so loading it in isolation avoids the package __init__ chain entirely while keeping the keyword table as the single source of truth.- Returns:
The
FuzzyDLKeywordenum class loaded in isolation from constants.py.- Return type:
type
- _max_lit_width(names) int[source]
Returns the width of the widest quoted literal across a sequence of token names, used to align columns in generated scanner source code.
- Parameters:
names (Iterable[str]) – Sequence of token names to measure.
- Returns:
The maximum quoted-literal width.
- Return type:
int
- _pad(lit: str, width: int) str[source]
Right-pads a quoted literal with spaces so columns line up in generated scanner source code.
- Parameters:
lit (str) – The literal string to pad.
width (int) – The target column width.
- Returns:
The quoted and padded literal.
- Return type:
str
- _structural_names()[source]
Returns the token names of the STRUCTURAL entries, dropping the Python display name.
- Returns:
The token names of every STRUCTURAL entry.
- Return type:
list[str]
- gen_lexer_flex() str[source]
Renders the flex scanner source
lexer_flex.lfrom the master tables, the flex counterpart ofgen_lexer_re2c(). Keyword and structural literals are emitted as flex rules sorted longest-literal-first, followed by the number and identifier rules and the publicfdl_count_tokens/fdl_tokenizeentry points that driveyylexover the whole input. The result is returned as a string rather than written to disk.- Returns:
The full text of the generated
lexer_flex.lscanner source.- Return type:
str
- gen_lexer_re2c() str[source]
Renders the re2c scanner source
lexer_re2c.refrom the master tables. Keyword and structural literals are emitted as re2c rules sorted longest-literal-first (so a short prefix never shadows a longer keyword), followed by the number and identifier rules and the publicfdl_count_tokens/fdl_tokenizeentry points. Literal columns are padded for readability via_pad(). The result is returned as a string rather than written to disk.- Returns:
The full text of the generated
lexer_re2c.rescanner source.- Return type:
str
- gen_tokens_h() str[source]
Renders the C header
tokens.hfrom the masterPARSER_TOKENStable. Every token code is emitted as anenummember in lock-step with the Python table (specials first, thenFuzzyDLKeywordorder, then theT_EOFsentinel), with keyword identifiersKW_-prefixed via_c_name()to dodge system-macro collisions. The result is returned as a string rather than written to disk.- Returns:
The full text of the generated
tokens.hheader.- Return type:
str
- gen_tokens_py() str[source]
Renders the Python module
tokens.pyfrom the master tables. The generated header defines theTOK_NAMEScode-to-display-name mapping plus the exported token-code constants (NUMBER,IDENT,ERROR,FIRST_KEYWORD, the structural names,T_IDENT,T_EOF). The remainder of the module — the_Buffer/_BytesBuffer/Tokensclasses and the tokenize helpers — is copied verbatim from the existingtokens.py(everything after the_PAGE = mmap.PAGESIZEmarker), so hand-written edits to those classes are preserved across regeneration. The result is returned as a string rather than written to disk.- Returns:
The full text of the generated
tokens.pymodule.- Return type:
str
- main(lexer_type: str) None[source]
Regenerates the token/lexer source files from the master tables and writes them to disk.
tokens.handtokens.pyare always written; the scanner source is written for exactly one backend depending onlexer_type("re2c"emitslexer_re2c.re,"flex"emitslexer_flex.l). Progress and a final token-count summary are printed to stdout.- Parameters:
lexer_type (str) – Which lexer backend to emit, either
"re2c"or"flex".
- token_literal(name: str) str[source]
Returns the literal string that a token name matches in source.
For a token whose name is a
FuzzyDLKeywordmember this returnsFuzzyDLKeyword[name].get_name()(single source of truth inconstants.py); for the bracket / comma tokens it returns the hard-coded literal from_NON_KEYWORD_LITERALS.- Parameters:
name (str) – The token name to look up.
- Returns:
The source-text literal matched by this token.
- Return type:
str
- FuzzyDLKeyword
- HERE
- KEYWORDS
- META = [('T_NUMBER', 'NUMBER'), ('T_IDENT', 'IDENT'), ('T_ERROR', 'ERROR')]
- PARSER_TOKENS: dict[str, int]
- STRUCTURAL
- _NON_KEYWORD_LITERALS: dict[str, str]