¿Puedes agregar nuevas declaraciones a la sintaxis de Python?

Puede agregar nuevas declaraciones (como print, raise, with¿A la sintaxis de Python?

Digamos, para permitir ..

mystatement "Something"

O...

new_if True:
    print "example"

No tanto si tú debería, pero más bien si es posible (corte de modificar el código de intérpretes pitón)

Pregunta hecha hace 15 años, 4 meses, 10 días - Por debugdynamo


11 Respuestas:

  • Usted puede encontrar esto útil - Python internals: añadir una nueva declaración a Python, citado aquí:


    Este artículo es un intento de entender mejor cómo funciona el front-end de Python. Sólo leer documentación y código fuente puede ser un poco aburrido, así que estoy tomando un enfoque práctico aquí: Voy a añadir un until declaración a Python.

    Toda la codificación para este artículo se hizo contra la rama de punta Py3k en la rama Espejo de repositorio Python Mercurial.

    El until declaración

    Algunos idiomas, como Ruby, tienen un until declaración, que es el complemento while ()until num == 0 equivale a while num != 0). En Ruby, puedo escribir:

    num = 3
    until num == 0 do
      puts num
      num -= 1
    end
    

    Y imprimirá:

    3
    2
    1
    

    Quiero añadir una capacidad similar a Python. Es decir, poder escribir:

    num = 3
    until num == 0:
      print(num)
      num -= 1
    

    A language-advocacy digression

    Este artículo no intenta sugerir la adición de un until declaración a Python. Aunque creo que tal declaración haría algo más claro, y este artículo muestra lo fácil que es añadir, respeto completamente la filosofía del minimalismo de Python. Todo lo que estoy tratando de hacer aquí, en realidad, es obtener una idea de los trabajos internos de Python.

    Modificación de la gramática

    Python utiliza un generador de parser personalizado llamado pgen. Este es un parser LL(1) que convierte el código fuente Python en un árbol parse. La entrada al generador de parser es el archivo Grammar/Grammar[1]. Este es un archivo de texto simple que especifica la gramática de Python.

    [1]: Desde aquí en adelante, las referencias a los archivos en la fuente Python se dan relativamente a la raíz del árbol fuente, que es el directorio donde se ejecuta configura y hacer para construir Python.

    Hay que hacer dos modificaciones en el archivo de gramática. El primero es añadir una definición para el until declaración. He encontrado dónde while se definió la declaración (continuación)while_stmt), y añadido until_stmt infra [2]:

    compound_stmt: if_stmt | while_stmt | until_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef | decorated
    if_stmt: 'if' test ':' suite ('elif' test ':' suite)* ['else' ':' suite]
    while_stmt: 'while' test ':' suite ['else' ':' suite]
    until_stmt: 'until' test ':' suite
    

    [2]: Esto demuestra una técnica común que uso al modificar el código fuente No estoy familiarizado con: trabajo por similitud. Este principio no resolverá todos sus problemas, pero definitivamente puede aliviar el proceso. Desde todo lo que hay que hacer while también tiene que hacerse until, sirve como una buena guía.

    Note que he decidido excluir el else cláusula de mi definición untilsólo para hacerlo un poco diferente (y porque francamente no me gusta else cláusula de bucles y no piense que encaja bien con el Zen de Python).

    El segundo cambio es modificar la regla para compound_stmt incluir until_stmt, como se puede ver en el snippet arriba. Es justo después. while_stmtOtra vez.

    Cuando corres make después de modificar Grammar/Grammar, note que pgen programa se ejecuta para regenerar Include/graminit.h y Python/graminit.c, y luego se re-compilan varios archivos.

    Modificación del código de generación AST

    Después de que el analizador de Python haya creado un árbol parse, este árbol se convierte en un AST, ya que los AST son mucho más simple para trabajar con en etapas posteriores del proceso de compilación.

    Así que vamos a visitar Parser/Python.asdl que define la estructura de los AST de Python y añade un nodo AST para nuestro nuevo until declaración, otra vez justo debajo de while:

    | While(expr test, stmt* body, stmt* orelse)
    | Until(expr test, stmt* body)
    

    Si ahora corres make, note que antes de compilar un montón de archivos, Parser/asdl_c.py se ejecuta para generar código C del archivo de definición AST. Esto (como Grammar/Grammar) es otro ejemplo del código fuente Python usando un mini-idioma (en otras palabras, un DSL) para simplificar la programación. Observa también que desde entonces Parser/asdl_c.py es un script Python, esto es una especie de arranque - para construir Python desde cero, Python ya tiene que estar disponible.

    Mientras tanto Parser/asdl_c.py generó el código para gestionar nuestro nuevo nodo AST definido (en los archivos Include/Python-ast.h y Python/Python-ast.c), todavía tenemos que escribir el código que convierte un nodo de parse-tree relevante en él a mano. Esto se hace en el archivo Python/ast.c. Allí, una función llamada ast_for_stmt convierte los nodos de árbol parse para las declaraciones en los nodos AST. De nuevo, guiado por nuestro viejo amigo while, saltamos hacia el gran switch para tramitar las declaraciones compuestas y añadir una cláusula until_stmt:

    case while_stmt:
        return ast_for_while_stmt(c, ch);
    case until_stmt:
        return ast_for_until_stmt(c, ch);
    

    Ahora debemos implementar ast_for_until_stmt. Aquí está:

    static stmt_ty
    ast_for_until_stmt(struct compiling *c, const node *n)
    {
        /* until_stmt: 'until' test ':' suite */
        REQ(n, until_stmt);
    
        if (NCH(n) == 4) {
            expr_ty expression;
            asdl_seq *suite_seq;
    
            expression = ast_for_expr(c, CHILD(n, 1));
            if (!expression)
                return NULL;
            suite_seq = ast_for_suite(c, CHILD(n, 3));
            if (!suite_seq)
                return NULL;
            return Until(expression, suite_seq, LINENO(n), n->n_col_offset, c->c_arena);
        }
    
        PyErr_Format(PyExc_SystemError,
                     "wrong number of tokens for 'until' statement: %d",
                     NCH(n));
        return NULL;
    }
    

    De nuevo, esto fue codificado mientras miraba de cerca el equivalente ast_for_while_stmt, con la diferencia para until He decidido no apoyar a la else cláusula. Como se espera, el AST se crea recursivamente, utilizando otras funciones de creación de AST como ast_for_expr para la expresión de la condición y ast_for_suite para el cuerpo del until declaración. Finalmente, un nuevo nodo llamado Until es devuelto.

    Tenga en cuenta que accedemos al nodo de árbol parse n usando algunas macros como NCH y CHILD. Esto vale la pena entender - su código está en Include/node.h.

    Digresión: Composición AST

    Elegí crear un nuevo tipo de AST para el until declaración, pero en realidad esto no es necesario. Podría haber ahorrado algo de trabajo e implementado la nueva funcionalidad usando la composición de los nodos existentes de AST, ya que:

    until condition:
       # do stuff
    

    Es funcionalmente equivalente a:

    while not condition:
      # do stuff
    

    En lugar de crear el Until nodos ast_for_until_stmtPodría haber creado un Not nodo con un While nodo como niño. Dado que el compilador AST ya sabe cómo manejar estos nodos, los próximos pasos del proceso podrían ser saltados.

    Compiling ASTs into bytecode

    El siguiente paso es compilar el AST en Python bytecode. La compilación tiene un resultado intermedio que es un CFG (Graf de Control de Flujo), pero dado que el mismo código lo maneja, ignoraré este detalle por ahora y lo dejaré para otro artículo.

    El código que vamos a mirar a continuación es Python/compile.c. Following the lead of while, encontramos la función compiler_visit_stmt, que es responsable de compilar las declaraciones en bytecode. Añadimos una cláusula para Until:

    case While_kind:
        return compiler_while(c, s);
    case Until_kind:
        return compiler_until(c, s);
    

    Si te preguntas qué Until_kind es, es una constante (realmente un valor del _stmt_kind enumeración) generado automáticamente desde el archivo de definición AST en Include/Python-ast.h. De todos modos, llamamos compiler_until que, por supuesto, todavía no existe. Voy a llegar un momento.

    Si tienes curiosidad como yo, notarás que compiler_visit_stmt es peculiar. Ninguna cantidad grep-para el árbol fuente revela dónde se llama. Cuando este es el caso, sólo queda una opción - C macro-fu. De hecho, una breve investigación nos lleva a la VISIT macro definida en Python/compile.c:

    #define VISIT(C, TYPE, V) {\
        if (!compiler_visit_ ## TYPE((C), (V))) \
            return 0; \
    

    Es usado para invocar compiler_visit_stmt dentro compiler_body. De vuelta a nuestro negocio, sin embargo...

    Como prometió, aquí está. compiler_until:

    static int
    compiler_until(struct compiler *c, stmt_ty s)
    {
        basicblock *loop, *end, *anchor = NULL;
        int constant = expr_constant(s->v.Until.test);
    
        if (constant == 1) {
            return 1;
        }
        loop = compiler_new_block(c);
        end = compiler_new_block(c);
        if (constant == -1) {
            anchor = compiler_new_block(c);
            if (anchor == NULL)
                return 0;
        }
        if (loop == NULL || end == NULL)
            return 0;
    
        ADDOP_JREL(c, SETUP_LOOP, end);
        compiler_use_next_block(c, loop);
        if (!compiler_push_fblock(c, LOOP, loop))
            return 0;
        if (constant == -1) {
            VISIT(c, expr, s->v.Until.test);
            ADDOP_JABS(c, POP_JUMP_IF_TRUE, anchor);
        }
        VISIT_SEQ(c, stmt, s->v.Until.body);
        ADDOP_JABS(c, JUMP_ABSOLUTE, loop);
    
        if (constant == -1) {
            compiler_use_next_block(c, anchor);
            ADDOP(c, POP_BLOCK);
        }
        compiler_pop_fblock(c, LOOP, loop);
        compiler_use_next_block(c, end);
    
        return 1;
    }
    

    Tengo una confesión que hacer: este código no fue escrito basado en una comprensión profunda de Python bytecode. Como el resto del artículo, se hizo en la imitación de los parientes compiler_while función. Al leerlo cuidadosamente, sin embargo, teniendo en cuenta que el Python VM está basado en la pila, y el glancing en la documentación de la dis módulo, que tiene una lista de bytecodes Python con descripciones, es posible entender lo que está pasando.

    Eso es, hemos terminado... ¿Verdad?

    Después de hacer todos los cambios y correr make, podemos ejecutar el nuevo Python compilado y probar nuestro nuevo until declaración:

    >>> until num == 0:
    ...   print(num)
    ...   num -= 1
    ...
    3
    2
    1
    

    ¡Voila, funciona! Veamos el bytecode creado para la nueva declaración usando el dis módulo como sigue:

    import dis
    
    def myfoo(num):
        until num == 0:
            print(num)
            num -= 1
    
    dis.dis(myfoo)
    

    Aquí está el resultado:

    4           0 SETUP_LOOP              36 (to 39)
          >>    3 LOAD_FAST                0 (num)
                6 LOAD_CONST               1 (0)
                9 COMPARE_OP               2 (==)
               12 POP_JUMP_IF_TRUE        38
    
    5          15 LOAD_NAME                0 (print)
               18 LOAD_FAST                0 (num)
               21 CALL_FUNCTION            1
               24 POP_TOP
    
    6          25 LOAD_FAST                0 (num)
               28 LOAD_CONST               2 (1)
               31 INPLACE_SUBTRACT
               32 STORE_FAST               0 (num)
               35 JUMP_ABSOLUTE            3
          >>   38 POP_BLOCK
          >>   39 LOAD_CONST               0 (None)
               42 RETURN_VALUE
    

    La operación más interesante es el número 12: si la condición es verdadera, saltamos después del bucle. Esto es semántica correcta para until. Si el salto no se ejecuta, el cuerpo del lazo sigue corriendo hasta que salta de nuevo a la condición de operación 35.

    Sentirse bien acerca de mi cambio, entonces intenté ejecutar la función (ejecutar myfoo(3)) en lugar de mostrar su bytecode. El resultado fue menos que alentador:

    Traceback (most recent call last):
      File "zy.py", line 9, in
        myfoo(3)
      File "zy.py", line 5, in myfoo
        print(num)
    SystemError: no locals when loading 'print'
    

    Esto no puede ser bueno. ¿Qué salió mal?

    El caso de la tabla de símbolos desaparecidos

    Uno de los pasos que realiza el compilador Python al compilar el AST es crear una tabla de símbolos para el código que compila. La llamada a PySymtable_Build dentro PyAST_Compile llamadas al módulo de mesa de símbolos (Python/symtable.c), que camina el AST de una manera similar a las funciones de generación de código. Tener una tabla de símbolos para cada alcance ayuda al compilador a encontrar alguna información clave, como cuáles variables son globales y que son locales a un alcance.

    Para solucionar el problema, tenemos que modificar el symtable_visit_stmt función Python/symtable.c, añadir código para el manejo until declaraciones, después del código similar para while declaraciones [3]:

    case While_kind:
        VISIT(st, expr, s->v.While.test);
        VISIT_SEQ(st, stmt, s->v.While.body);
        if (s->v.While.orelse)
            VISIT_SEQ(st, stmt, s->v.While.orelse);
        break;
    case Until_kind:
        VISIT(st, expr, s->v.Until.test);
        VISIT_SEQ(st, stmt, s->v.Until.body);
        break;
    

    [3]: Por cierto, sin este código hay una advertencia de compilador para Python/symtable.c. El compilador nota que el Until_kind El valor de enumeración no se maneja en la declaración de conmutación symtable_visit_stmt y se queja. ¡Siempre es importante comprobar las advertencias del compilador!

    Y ahora realmente hemos terminado. Compilar la fuente después de este cambio hace la ejecución de myfoo(3) trabajo como se esperaba.

    Conclusión

    En este artículo he demostrado cómo agregar una nueva declaración a Python. Aunque requirió un poco de tinkering en el código del compilador Python, el cambio no fue difícil de implementar, porque usé una declaración similar y existente como una directriz.

    El compilador Python es un sofisticado pedazo de software, y no pretendo ser un experto en él. Sin embargo, estoy realmente interesado en los internos de Python, y en particular su parte delantera. Por lo tanto, encontré este ejercicio un compañero muy útil para el estudio teórico de los principios y código fuente del compilador. Servirá como base para futuros artículos que se profundizarán en el compilador.

    Referencias

    He utilizado algunas referencias excelentes para la construcción de este artículo. Aquí están, en ningún orden particular:

    • PEP 339: Diseño del compilador CPython - probablemente la pieza más importante y completa funcionario documentación para el compilador Python. Siendo muy corto, muestra dolorosamente la escasez de buena documentación de los internos de Python.
    • "Python Compiler Internals" - un artículo de Thomas Lee
    • "Python: Diseño e Implementación" - una presentación de Guido van Rossum
    • Pitón (2.5) Máquina Virtual, Una visita guiada - una presentación de Peter Tröger

    fuente original

    Respondida el Oct 18, 2008 a las 10:54 - por pixelprodigy50bb

    Votos positivos: 0 | Votos negativos: 0

  • Una manera de hacer cosas como esta es preprocesar la fuente y modificarla, traduciendo su declaración agregada a pitón. Hay varios problemas que este enfoque traerá, y no lo recomendaría para el uso general, pero para la experimentación con el lenguaje, o metaprogramación de propósito específico, puede ocasionalmente ser útil.

    Por ejemplo, digamos que queremos introducir una declaración "impresión", que en lugar de imprimir a la pantalla se registra en un archivo específico. ie:

    myprint "This gets logged to file"
    

    sería equivalente a

    print >>open('/tmp/logfile.txt','a'), "This gets logged to file"
    

    Hay varias opciones sobre cómo hacer el reemplazo, desde la sustitución de regex a la generación de un AST, a escribir su propio parser dependiendo de cómo cerrar su sintaxis coincide con el pitón existente. Un buen enfoque intermedio es utilizar el módulo tokenizer. Esto debe permitir que agregue nuevas palabras clave, estructuras de control, etc mientras interprete la fuente de manera similar al intérprete de pitón, evitando así las soluciones de rotura crude regex. Para el anterior "impresión", usted podría escribir el siguiente código de transformación:

    import tokenize
    
    LOGFILE = '/tmp/log.txt'
    def translate(readline):
        for type, name,_,_,_ in tokenize.generate_tokens(readline):
            if type ==tokenize.NAME and name =='myprint':
                yield tokenize.NAME, 'print'
                yield tokenize.OP, '>>'
                yield tokenize.NAME, "open"
                yield tokenize.OP, "("
                yield tokenize.STRING, repr(LOGFILE)
                yield tokenize.OP, ","
                yield tokenize.STRING, "'a'"
                yield tokenize.OP, ")"
                yield tokenize.OP, ","
            else:
                yield type,name
    

    (Esto hace que mi impresión sea efectivamente una palabra clave, por lo que el uso como una variable en otro lugar probablemente causará problemas)

    El problema entonces es cómo utilizarlo para que su código sea usable de pitón. Una manera sería escribir su propia función de importación, y utilizarla para cargar el código escrito en su idioma personalizado. ie:

    import new
    def myimport(filename):
        mod = new.module(filename)
        f=open(filename)
        data = tokenize.untokenize(translate(f.readline))
        exec data in mod.__dict__
        return mod
    

    Esto requiere que usted maneja su código personalizado de forma diferente de los módulos de pitón normales sin embargo. ie "some_mod = myimport("some_mod.py")en lugar de "import some_mod"

    Otra solución bastante limpia (aunque hacky) es crear una codificación personalizada (Ver PEP 263como esto La receta lo demuestra. Podrías implementar esto como:

    import codecs, cStringIO, encodings
    from encodings import utf_8
    
    class StreamReader(utf_8.StreamReader):
        def __init__(self, *args, **kwargs):
            codecs.StreamReader.__init__(self, *args, **kwargs)
            data = tokenize.untokenize(translate(self.stream.readline))
            self.stream = cStringIO.StringIO(data)
    
    def search_function(s):
        if s!='mylang': return None
        utf8=encodings.search_function('utf8') # Assume utf8 encoding
        return codecs.CodecInfo(
            name='mylang',
            encode = utf8.encode,
            decode = utf8.decode,
            incrementalencoder=utf8.incrementalencoder,
            incrementaldecoder=utf8.incrementaldecoder,
            streamreader=StreamReader,
            streamwriter=utf8.streamwriter)
    
    codecs.register(search_function)
    

    Ahora después de que este código se ejecute (por ejemplo, usted podría colocarlo en su .pythonrc o site.py) cualquier código que comience con el comentario "# codificación: mylang" se traducirá automáticamente a través del paso anterior de preprocesamiento. Por ejemplo.

    # coding: mylang
    myprint "this gets logged to file"
    for i in range(10):
        myprint "so does this : ", i, "times"
    myprint ("works fine" "with arbitrary" + " syntax" 
      "and line continuations")
    

    Caveats:

    Hay problemas en el enfoque del preprocesador, ya que probablemente estará familiarizado con si ha trabajado con el preprocesador C. El principal es depurar. Todo el pitón ve es el archivo preprocesado que significa que el texto impreso en el rastro de la pila etc se refiere a eso. Si usted ha realizado una traducción significativa, esto puede ser muy diferente de su texto fuente. El ejemplo anterior no cambia los números de línea, así que no será muy diferente, pero cuanto más lo cambies, más difícil será averiguarlo.

    Respondida el Oct 18, 2008 a las 11:02 - por algorithmarchitect

    Votos positivos: 0 | Votos negativos: 0

  • Sí, en cierta medida es posible. Hay un módulo ahí fuera que usa sys.settrace() para la aplicación goto y comefrom "Palabras clave":

    from goto import goto, label
    for i in range(1, 10):
      for j in range(1, 20):
        print i, j
        if j == 3:
          goto .end # breaking out from nested loop
    label .end
    print "Finished"
    

    Respondida el Oct 18, 2008 a las 11:12 - por compilerczar

    Votos positivos: 0 | Votos negativos: 0

  • Falta de cambio y recompilación del código fuente (que es posible con código abierto), cambiar el idioma base no es realmente posible.

    Incluso si usted recompile la fuente, no sería pitón, sólo su versión modificada hackeado-up que necesita tener mucho cuidado de no introducir errores en.

    Sin embargo, no estoy seguro por qué querrías. Las características orientadas al objeto de Python hacen que sea bastante simple para lograr resultados similares con el idioma tal como está.

    Respondida el Oct 18, 2008 a las 11:19 - por techinnovator

    Votos positivos: 0 | Votos negativos: 0

  • Respuesta general: usted necesita preprocesar sus archivos fuente.

    Respuesta más específica: instalar EasyExtend, y pasar por los siguientes pasos

    i) Crear un nuevo langlet (lengua de extensión )

    import EasyExtend
    EasyExtend.new_langlet("mystmts", prompt = "my> ", source_ext = "mypy")
    

    Sin especificación adicional se crearán un montón de archivos bajo EasyExtend/langlets/mystmts/ .

    ii) Abrir mystmts/parsedef/Grammar.ext y añadir las siguientes líneas

    small_stmt: (expr_stmt | print_stmt  | del_stmt | pass_stmt | flow_stmt |
                 import_stmt | global_stmt | exec_stmt | assert_stmt | my_stmt )
    
    my_stmt: 'mystatement' expr
    

    Esto es suficiente para definir la sintaxis de su nueva declaración. El pequeño_stmt no-terminal es parte de la gramática de Python y es el lugar donde se conecta la nueva declaración. El analizador reconocerá ahora la nueva declaración, es decir, un archivo fuente que lo contiene será analizado. El compilador lo rechazará aunque porque todavía tiene que ser transformado en Python válido.

    iii) Ahora hay que añadir semántica de la declaración. Para esto hay que editar msytmts/langlet.py y añadir un visitante de nodo my_stmt.

     def call_my_stmt(expression):
         "defines behaviour for my_stmt"
         print "my stmt called with", expression
    
     class LangletTransformer(Transformer):
           @transform
           def my_stmt(self, node):
               _expr = find_node(node, symbol.expr)
               return any_stmt(CST_CallFunc("call_my_stmt", [_expr]))
    
     __publish__ = ["call_my_stmt"]
    

    iv) cd a langlets/mystmts y tipo

    python run_mystmts.py
    

    Ahora se iniciará una sesión y se podrá utilizar la declaración recién definida:

    __________________________________________________________________________________
    
     mystmts
    
     On Python 2.5.1 (r251:54863, Apr 18 2007, 08:51:08) [MSC v.1310 32 bit (Intel)]
     __________________________________________________________________________________
    
     my> mystatement 40+2
     my stmt called with 42
    

    Algunos pasos para llegar a una declaración trivial, ¿verdad? Aún no hay una API que permita definir cosas simples sin tener que preocuparse por las gramáticas. Pero EE es muy confiable modulo algunos errores. Así que es sólo cuestión de tiempo que emerge una API que permite a los programadores definir cosas convenientes como operadores de infix o pequeñas declaraciones usando simplemente programación OO conveniente. Para cosas más complejas como incrustar idiomas enteros en Python mediante la construcción de un langlet no hay manera de rodear un enfoque de gramática completa.

    Respondida el Oct 18, 2008 a las 11:25 - por codechampion

    Votos positivos: 0 | Votos negativos: 0

  • Aquí hay una manera muy simple pero descabellada de añadir nuevas declaraciones, en modo interpretativo solamente. Lo estoy usando para pequeños comandos de 1 letras para editar anotaciones de genes usando solo sís. displayhook, pero para poder responder a esta pregunta añadí sís. excepthook para los errores de sintaxis también. Este último es realmente feo, trayendo el código crudo del búfer de línea de lectura. El beneficio es, es trivialmente fácil añadir nuevas declaraciones de esta manera.

    
    jcomeau@intrepid:~/$ cat demo.py; ./demo.py
    #!/usr/bin/python -i
    'load everything needed under "package", such as package.common.normalize()'
    import os, sys, readline, traceback
    if __name__ == '__main__':
        class t:
            @staticmethod
            def localfunction(*args):
                print 'this is a test'
                if args:
                    print 'ignoring %s' % repr(args)
    
        def displayhook(whatever):
            if hasattr(whatever, 'localfunction'):
                return whatever.localfunction()
            else:
                print whatever
    
        def excepthook(exctype, value, tb):
            if exctype is SyntaxError:
                index = readline.get_current_history_length()
                item = readline.get_history_item(index)
                command = item.split()
                print 'command:', command
                if len(command[0]) == 1:
                    try:
                        eval(command[0]).localfunction(*command[1:])
                    except:
                        traceback.print_exception(exctype, value, tb)
            else:
                traceback.print_exception(exctype, value, tb)
    
        sys.displayhook = displayhook
        sys.excepthook = excepthook
    >>> t
    this is a test
    >>> t t
    command: ['t', 't']
    this is a test
    ignoring ('t',)
    >>> ^D
    
    

    Respondida el Oct 18, 2008 a las 11:33 - por htmlhelix

    Votos positivos: 0 | Votos negativos: 0

  • He encontrado una guía para agregar nuevas declaraciones:

    https://troeger.eu/files/teaching/pythonvm08lab.pdf

    Básicamente, para añadir nuevas declaraciones, debe editar Python/ast.c (entre otras cosas) y recompilar el binario pitón.

    Aunque sea posible, no. Usted puede lograr casi todo a través de funciones y clases (que no requerirá que la gente recompile pitón sólo para ejecutar su script.)

    Respondida el Oct 18, 2008 a las 11:40 - por logicluminary

    Votos positivos: 0 | Votos negativos: 0

  • Es posible hacer esto usando EasyExtend:

    EasyExtend (EE) es un preprocesador generador y metaprogramación marco escrito en Python puro integrado con CPython. El principal propósito de EasyExtend es la creación idiomas de extensión, es decir, añadir sintaxis personalizada y semántica a Python.

    Respondida el Oct 18, 2008 a las 11:45 - por pythonpirate

    Votos positivos: 0 | Votos negativos: 0

  • No es exactamente agregar nuevas declaraciones a la sintaxis del lenguaje, pero las macros son una herramienta poderosa: https://github.com/lihaoyi/macropy

    Respondida el Oct 18, 2008 a las 11:53 - por debugdynamob312

    Votos positivos: 0 | Votos negativos: 0

  • No es posible agregar nuevas declaraciones a la sintaxis básica de Python, ya que la sintaxis del lenguaje es fija y está definida en la especificación del lenguaje Python (PEP 8 y PEP 20). Sin embargo, puedes lograr comportamientos similares a través de funciones o clases personalizadas que encapsulen la lógica que deseas implementar. Esto te permitirá crear tu propio "lenguaje interno" en Python utilizando funciones y clases personalizadas.

    Por ejemplo, en lugar de tener una nueva declaración mystatement "Something", podrías crear una función llamada mystatement que reciba "Something" como argumento y realice la lógica deseada.

    Del mismo modo, en lugar de tener una nueva declaración new_if True: print "example", podrías crear una clase llamada NewIf que tenga un método run que verifique si la condición es verdadera y luego imprima el mensaje.

    Recuerda que Python es conocido por su simplicidad y legibilidad, por lo que es recomendable seguir las convenciones establecidas en el lenguaje para mantener el código fácil de entender

    Respondida el Oct 19, 2008 a las 10:56 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • Es posible agregar nuevas declaraciones a la sintaxis de Python modificando el código del intérprete de Python. Sin embargo, no se recomienda hacerlo, ya que podría romper la compatibilidad con versiones anteriores y causar problemas imprevistos.

    El intérprete de Python es un programa escrito en C. Las declaraciones de Python se analizan y compilan en código de bytes, que luego ejecuta la máquina virtual de Python. Para agregar nuevas declaraciones, necesitarías modificar el analizador y el compilador en el código C del intérprete.

    Una vez que hayas modificado el código del intérprete, puedes compilarlo y ejecutarlo para usar tu nueva sintaxis. Sin embargo, es importante tener en cuenta que tu versión modificada del intérprete no será compatible con las versiones estándar de Python y puede causar problemas con las bibliotecas y los módulos existentes.

    En lugar de modificar el intérprete de Python, se recomienda utilizar mecanismos de extensión existentes, como decoradores o metaclases, para ampliar la funcionalidad de Python sin modificar su sintaxis subyacente.

    Respondida el Oct 19, 2008 a las 11:05 - por Gemini

    Votos positivos: 0 | Votos negativos: 0