#! /usr/bin/env python3# This script generates token related files from Grammar/Tokens:## Doc/library/token-list.inc# Include/token.h# Parser/token.c# Lib/token.pyNT_OFFSET = 256def load_tokens(path):tok_names = []string_to_tok = {}ERRORTOKEN = Nonewith open(path) as fp:for line in fp:line = line.strip()# strip commentsi = line.find('#')if i >= 0:line = line[:i].strip()if not line:continuefields = line.split()name = fields[0]value = len(tok_names)if name == 'ERRORTOKEN':ERRORTOKEN = valuestring = fields[1] if len(fields) > 1 else Noneif string:string = eval(string)string_to_tok[string] = valuetok_names.append(name)return tok_names, ERRORTOKEN, string_to_tokdef update_file(file, content):try:with open(file, 'r') as fobj:if fobj.read() == content:return Falseexcept (OSError, ValueError):passwith open(file, 'w') as fobj:fobj.write(content)return Truetoken_h_template = """\/* Auto-generated by Tools/scripts/generate_token.py *//* Token types */#ifndef Py_LIMITED_API#ifndef Py_TOKEN_H#define Py_TOKEN_H#ifdef __cplusplusextern "C" {#endif#undef TILDE /* Prevent clash of our definition with system macro. Ex AIX, ioctl.h */%s\#define N_TOKENS %d#define NT_OFFSET %d/* Special definitions for cooperation with parser */#define ISTERMINAL(x) ((x) < NT_OFFSET)#define ISNONTERMINAL(x) ((x) >= NT_OFFSET)#define ISEOF(x) ((x) == ENDMARKER)PyAPI_DATA(const char * const) _PyParser_TokenNames[]; /* Token names */PyAPI_FUNC(int) PyToken_OneChar(int);PyAPI_FUNC(int) PyToken_TwoChars(int, int);PyAPI_FUNC(int) PyToken_ThreeChars(int, int, int);#ifdef __cplusplus}#endif#endif /* !Py_TOKEN_H */#endif /* Py_LIMITED_API */"""def make_h(infile, outfile='Include/token.h'):tok_names, ERRORTOKEN, string_to_tok = load_tokens(infile)defines = []for value, name in enumerate(tok_names[:ERRORTOKEN + 1]):defines.append("#define %-15s %d\n" % (name, value))if update_file(outfile, token_h_template % (''.join(defines),len(tok_names),NT_OFFSET)):print("%s regenerated from %s" % (outfile, infile))token_c_template = """\/* Auto-generated by Tools/scripts/generate_token.py */#include "Python.h"#include "token.h"/* Token names */const char * const _PyParser_TokenNames[] = {%s\};/* Return the token corresponding to a single character */intPyToken_OneChar(int c1){%s\return OP;}intPyToken_TwoChars(int c1, int c2){%s\return OP;}intPyToken_ThreeChars(int c1, int c2, int c3){%s\return OP;}"""def generate_chars_to_token(mapping, n=1):result = []write = result.appendindent = ' ' * nwrite(indent)write('switch (c%d) {\n' % (n,))for c in sorted(mapping):write(indent)value = mapping[c]if isinstance(value, dict):write("case '%s':\n" % (c,))write(generate_chars_to_token(value, n + 1))write(indent)write(' break;\n')else:write("case '%s': return %s;\n" % (c, value))write(indent)write('}\n')return ''.join(result)def make_c(infile, outfile='Parser/token.c'):tok_names, ERRORTOKEN, string_to_tok = load_tokens(infile)string_to_tok['<>'] = string_to_tok['!=']chars_to_token = {}for string, value in string_to_tok.items():assert 1 <= len(string) <= 3name = tok_names[value]m = chars_to_token.setdefault(len(string), {})for c in string[:-1]:m = m.setdefault(c, {})m[string[-1]] = namenames = []for value, name in enumerate(tok_names):if value >= ERRORTOKEN:name = '<%s>' % namenames.append(' "%s",\n' % name)names.append(' "<N_TOKENS>",\n')if update_file(outfile, token_c_template % (''.join(names),generate_chars_to_token(chars_to_token[1]),generate_chars_to_token(chars_to_token[2]),generate_chars_to_token(chars_to_token[3]))):print("%s regenerated from %s" % (outfile, infile))token_inc_template = """\.. Auto-generated by Tools/scripts/generate_token.py%s.. data:: N_TOKENS.. data:: NT_OFFSET"""def make_rst(infile, outfile='Doc/library/token-list.inc'):tok_names, ERRORTOKEN, string_to_tok = load_tokens(infile)tok_to_string = {value: s for s, value in string_to_tok.items()}names = []for value, name in enumerate(tok_names[:ERRORTOKEN + 1]):names.append('.. data:: %s' % (name,))if value in tok_to_string:names.append('')names.append(' Token value for ``"%s"``.' % tok_to_string[value])names.append('')if update_file(outfile, token_inc_template % '\n'.join(names)):print("%s regenerated from %s" % (outfile, infile))token_py_template = '''\"""Token constants."""# Auto-generated by Tools/scripts/generate_token.py__all__ = ['tok_name', 'ISTERMINAL', 'ISNONTERMINAL', 'ISEOF']%sN_TOKENS = %d# Special definitions for cooperation with parserNT_OFFSET = %dtok_name = {value: namefor name, value in globals().items()if isinstance(value, int) and not name.startswith('_')}__all__.extend(tok_name.values())EXACT_TOKEN_TYPES = {%s}def ISTERMINAL(x):return x < NT_OFFSETdef ISNONTERMINAL(x):return x >= NT_OFFSETdef ISEOF(x):return x == ENDMARKER'''def make_py(infile, outfile='Lib/token.py'):tok_names, ERRORTOKEN, string_to_tok = load_tokens(infile)constants = []for value, name in enumerate(tok_names):constants.append('%s = %d' % (name, value))constants.insert(ERRORTOKEN,"# These aren't used by the C tokenizer but are needed for tokenize.py")token_types = []for s, value in sorted(string_to_tok.items()):token_types.append(' %r: %s,' % (s, tok_names[value]))if update_file(outfile, token_py_template % ('\n'.join(constants),len(tok_names),NT_OFFSET,'\n'.join(token_types),)):print("%s regenerated from %s" % (outfile, infile))def main(op, infile='Grammar/Tokens', *args):make = globals()['make_' + op]make(infile, *args)if __name__ == '__main__':import sysmain(*sys.argv[1:])
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。