⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 parsermodule.c

📁 python s60 1.4.5版本的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/*  parsermodule.c
 *
 *  Copyright 1995-1996 by Fred L. Drake, Jr. and Virginia Polytechnic
 *  Institute and State University, Blacksburg, Virginia, USA.
 *  Portions copyright 1991-1995 by Stichting Mathematisch Centrum,
 *  Amsterdam, The Netherlands.  Copying is permitted under the terms
 *  associated with the main Python distribution, with the additional
 *  restriction that this additional notice be included and maintained
 *  on all distributed copies.
 *
 *  This module serves to replace the original parser module written
 *  by Guido.  The functionality is not matched precisely, but the
 *  original may be implemented on top of this.  This is desirable
 *  since the source of the text to be parsed is now divorced from
 *  this interface.
 *
 *  Unlike the prior interface, the ability to give a parse tree
 *  produced by Python code as a tuple to the compiler is enabled by
 *  this module.  See the documentation for more details.
 *
 *  I've added some annotations that help with the lint code-checking
 *  program, but they're not complete by a long shot.  The real errors
 *  that lint detects are gone, but there are still warnings with
 *  Py_[X]DECREF() and Py_[X]INCREF() macros.  The lint annotations
 *  look like "NOTE(...)".
 */

#include "Python.h"                     /* general Python API             */
#include "graminit.h"                   /* symbols defined in the grammar */
#include "node.h"                       /* internal parser structure      */
#include "errcode.h"                    /* error codes for PyNode_*()     */
#include "token.h"                      /* token definitions              */
                                        /* ISTERMINAL() / ISNONTERMINAL() */
#include "compile.h"                    /* PyNode_Compile()               */

#ifdef lint
#include <note.h>
#else
#define NOTE(x)
#endif

#ifdef macintosh
char *strdup(char *);
#endif

/*  String constants used to initialize module attributes.
 *
 */
static char*
parser_copyright_string
= "Copyright 1995-1996 by Virginia Polytechnic Institute & State\n\
University, Blacksburg, Virginia, USA, and Fred L. Drake, Jr., Reston,\n\
Virginia, USA.  Portions copyright 1991-1995 by Stichting Mathematisch\n\
Centrum, Amsterdam, The Netherlands.";


static char*
parser_doc_string
= "This is an interface to Python's internal parser.";

static char*
parser_version_string = "0.5";


typedef PyObject* (*SeqMaker) (int length);
typedef int (*SeqInserter) (PyObject* sequence,
                            int index,
                            PyObject* element);

/*  The function below is copyrighted by Stichting Mathematisch Centrum.  The
 *  original copyright statement is included below, and continues to apply
 *  in full to the function immediately following.  All other material is
 *  original, copyrighted by Fred L. Drake, Jr. and Virginia Polytechnic
 *  Institute and State University.  Changes were made to comply with the
 *  new naming conventions.  Added arguments to provide support for creating
 *  lists as well as tuples, and optionally including the line numbers.
 */


static PyObject*
node2tuple(node *n,                     /* node to convert               */
           SeqMaker mkseq,              /* create sequence               */
           SeqInserter addelem,         /* func. to add elem. in seq.    */
           int lineno)                  /* include line numbers?         */
{
    if (n == NULL) {
        Py_INCREF(Py_None);
        return (Py_None);
    }
    if (ISNONTERMINAL(TYPE(n))) {
        int i;
        PyObject *v;
        PyObject *w;

        v = mkseq(1 + NCH(n));
        if (v == NULL)
            return (v);
        w = PyInt_FromLong(TYPE(n));
        if (w == NULL) {
            Py_DECREF(v);
            return ((PyObject*) NULL);
        }
        (void) addelem(v, 0, w);
        for (i = 0; i < NCH(n); i++) {
            w = node2tuple(CHILD(n, i), mkseq, addelem, lineno);
            if (w == NULL) {
                Py_DECREF(v);
                return ((PyObject*) NULL);
            }
            (void) addelem(v, i+1, w);
        }
        return (v);
    }
    else if (ISTERMINAL(TYPE(n))) {
        PyObject *result = mkseq(2 + lineno);
        if (result != NULL) {
            (void) addelem(result, 0, PyInt_FromLong(TYPE(n)));
            (void) addelem(result, 1, PyString_FromString(STR(n)));
            if (lineno == 1)
                (void) addelem(result, 2, PyInt_FromLong(n->n_lineno));
        }
        return (result);
    }
    else {
        PyErr_SetString(PyExc_SystemError,
                        "unrecognized parse tree node type");
        return ((PyObject*) NULL);
    }
}
/*
 *  End of material copyrighted by Stichting Mathematisch Centrum.
 */



/*  There are two types of intermediate objects we're interested in:
 *  'eval' and 'exec' types.  These constants can be used in the st_type
 *  field of the object type to identify which any given object represents.
 *  These should probably go in an external header to allow other extensions
 *  to use them, but then, we really should be using C++ too.  ;-)
 */

#define PyST_EXPR  1
#define PyST_SUITE 2


/*  These are the internal objects and definitions required to implement the
 *  ST type.  Most of the internal names are more reminiscent of the 'old'
 *  naming style, but the code uses the new naming convention.
 */

static PyObject*
parser_error = 0;


typedef struct {
    PyObject_HEAD                       /* standard object header           */
    node* st_node;                      /* the node* returned by the parser */
    int   st_type;                      /* EXPR or SUITE ?                  */
} PyST_Object;


staticforward void
parser_free(PyST_Object *st);

staticforward int
parser_compare(PyST_Object *left, PyST_Object *right);

staticforward PyObject *
parser_getattr(PyObject *self, char *name);


static
PyTypeObject PyST_Type = {
    PyObject_HEAD_INIT(NULL)
    0,
    "parser.st",                        /* tp_name              */
    (int) sizeof(PyST_Object),          /* tp_basicsize         */
    0,                                  /* tp_itemsize          */
    (destructor)parser_free,            /* tp_dealloc           */
    0,                                  /* tp_print             */
    parser_getattr,                     /* tp_getattr           */
    0,                                  /* tp_setattr           */
    (cmpfunc)parser_compare,            /* tp_compare           */
    0,                                  /* tp_repr              */
    0,                                  /* tp_as_number         */
    0,                                  /* tp_as_sequence       */
    0,                                  /* tp_as_mapping        */
    0,                                  /* tp_hash              */
    0,                                  /* tp_call              */
    0,                                  /* tp_str               */
    0,                                  /* tp_getattro          */
    0,                                  /* tp_setattro          */

    /* Functions to access object as input/output buffer */
    0,                                  /* tp_as_buffer         */

    Py_TPFLAGS_DEFAULT,                 /* tp_flags             */

    /* __doc__ */
    "Intermediate representation of a Python parse tree."
};  /* PyST_Type */


static int
parser_compare_nodes(node *left, node *right)
{
    int j;

    if (TYPE(left) < TYPE(right))
        return (-1);

    if (TYPE(right) < TYPE(left))
        return (1);

    if (ISTERMINAL(TYPE(left)))
        return (strcmp(STR(left), STR(right)));

    if (NCH(left) < NCH(right))
        return (-1);

    if (NCH(right) < NCH(left))
        return (1);

    for (j = 0; j < NCH(left); ++j) {
        int v = parser_compare_nodes(CHILD(left, j), CHILD(right, j));

        if (v != 0)
            return (v);
    }
    return (0);
}


/*  int parser_compare(PyST_Object* left, PyST_Object* right)
 *
 *  Comparison function used by the Python operators ==, !=, <, >, <=, >=
 *  This really just wraps a call to parser_compare_nodes() with some easy
 *  checks and protection code.
 *
 */
static int
parser_compare(PyST_Object *left, PyST_Object *right)
{
    if (left == right)
        return (0);

    if ((left == 0) || (right == 0))
        return (-1);

    return (parser_compare_nodes(left->st_node, right->st_node));
}


/*  parser_newstobject(node* st)
 *
 *  Allocates a new Python object representing an ST.  This is simply the
 *  'wrapper' object that holds a node* and allows it to be passed around in
 *  Python code.
 *
 */
static PyObject*
parser_newstobject(node *st, int type)
{
    PyST_Object* o = PyObject_New(PyST_Object, &PyST_Type);

    if (o != 0) {
        o->st_node = st;
        o->st_type = type;
    }
    else {
        PyNode_Free(st);
    }
    return ((PyObject*)o);
}


/*  void parser_free(PyST_Object* st)
 *
 *  This is called by a del statement that reduces the reference count to 0.
 *
 */
static void
parser_free(PyST_Object *st)
{
    PyNode_Free(st->st_node);
    PyObject_Del(st);
}


/*  parser_st2tuple(PyObject* self, PyObject* args, PyObject* kw)
 *
 *  This provides conversion from a node* to a tuple object that can be
 *  returned to the Python-level caller.  The ST object is not modified.
 *
 */
static PyObject*
parser_st2tuple(PyST_Object *self, PyObject *args, PyObject *kw)
{
    PyObject *line_option = 0;
    PyObject *res = 0;
    int ok;

    static char *keywords[] = {"ast", "line_info", NULL};

    if (self == NULL) {
        ok = PyArg_ParseTupleAndKeywords(args, kw, "O!|O:st2tuple", keywords,
                                         &PyST_Type, &self, &line_option);
    }
    else
        ok = PyArg_ParseTupleAndKeywords(args, kw, "|O:totuple", &keywords[1],
                                         &line_option);
    if (ok != 0) {
        int lineno = 0;
        if (line_option != NULL) {
            lineno = (PyObject_IsTrue(line_option) != 0) ? 1 : 0;
        }
        /*
         *  Convert ST into a tuple representation.  Use Guido's function,
         *  since it's known to work already.
         */
        res = node2tuple(((PyST_Object*)self)->st_node,
                         PyTuple_New, PyTuple_SetItem, lineno);
    }
    return (res);
}


/*  parser_st2list(PyObject* self, PyObject* args, PyObject* kw)
 *
 *  This provides conversion from a node* to a list object that can be
 *  returned to the Python-level caller.  The ST object is not modified.
 *
 */
static PyObject*
parser_st2list(PyST_Object *self, PyObject *args, PyObject *kw)
{
    PyObject *line_option = 0;
    PyObject *res = 0;
    int ok;

    static char *keywords[] = {"ast", "line_info", NULL};

    if (self == NULL)
        ok = PyArg_ParseTupleAndKeywords(args, kw, "O!|O:st2list", keywords,
                                         &PyST_Type, &self, &line_option);
    else
        ok = PyArg_ParseTupleAndKeywords(args, kw, "|O:tolist", &keywords[1],
                                         &line_option);
    if (ok) {
        int lineno = 0;
        if (line_option != 0) {
            lineno = PyObject_IsTrue(line_option) ? 1 : 0;
        }
        /*
         *  Convert ST into a tuple representation.  Use Guido's function,
         *  since it's known to work already.
         */
        res = node2tuple(self->st_node,
                         PyList_New, PyList_SetItem, lineno);
    }
    return (res);
}


/*  parser_compilest(PyObject* self, PyObject* args)
 *
 *  This function creates code objects from the parse tree represented by
 *  the passed-in data object.  An optional file name is passed in as well.
 *
 */
static PyObject*
parser_compilest(PyST_Object *self, PyObject *args, PyObject *kw)
{
    PyObject*     res = 0;
    char*         str = "<syntax-tree>";
    int ok;

    static char *keywords[] = {"ast", "filename", NULL};

    if (self == NULL)
        ok = PyArg_ParseTupleAndKeywords(args, kw, "O!|s:compilest", keywords,
                                         &PyST_Type, &self, &str);
    else
        ok = PyArg_ParseTupleAndKeywords(args, kw, "|s:compile", &keywords[1],
                                         &str);

    if (ok)
        res = (PyObject *)PyNode_Compile(self->st_node, str);

    return (res);
}


/*  PyObject* parser_isexpr(PyObject* self, PyObject* args)
 *  PyObject* parser_issuite(PyObject* self, PyObject* args)
 *
 *  Checks the passed-in ST object to determine if it is an expression or
 *  a statement suite, respectively.  The return is a Python truth value.
 *
 */
static PyObject*
parser_isexpr(PyST_Object *self, PyObject *args, PyObject *kw)
{
    PyObject* res = 0;
    int ok;

    static char *keywords[] = {"ast", NULL};

    if (self == NULL)
        ok = PyArg_ParseTupleAndKeywords(args, kw, "O!:isexpr", keywords,
                                         &PyST_Type, &self);
    else
        ok = PyArg_ParseTupleAndKeywords(args, kw, ":isexpr", &keywords[1]);

    if (ok) {
        /* Check to see if the ST represents an expression or not. */
        res = (self->st_type == PyST_EXPR) ? Py_True : Py_False;
        Py_INCREF(res);
    }
    return (res);
}


static PyObject*
parser_issuite(PyST_Object *self, PyObject *args, PyObject *kw)
{
    PyObject* res = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -