Home | History | Annotate | Download | only in Parser
      1 
      2 /* Parser generator main program */
      3 
      4 /* This expects a filename containing the grammar as argv[1] (UNIX)
      5    or asks the console for such a file name (THINK C).
      6    It writes its output on two files in the current directory:
      7    - "graminit.c" gets the grammar as a bunch of initialized data
      8    - "graminit.h" gets the grammar's non-terminals as #defines.
      9    Error messages and status info during the generation process are
     10    written to stdout, or sometimes to stderr. */
     11 
     12 /* XXX TO DO:
     13    - check for duplicate definitions of names (instead of fatal err)
     14 */
     15 
     16 #define PGEN
     17 
     18 #include "Python.h"
     19 #include "internal/mem.h"
     20 #include "internal/pystate.h"
     21 #include "pgenheaders.h"
     22 #include "grammar.h"
     23 #include "node.h"
     24 #include "parsetok.h"
     25 #include "pgen.h"
     26 
     27 int Py_DebugFlag;
     28 int Py_VerboseFlag;
     29 int Py_IgnoreEnvironmentFlag;
     30 _PyRuntimeState _PyRuntime = _PyRuntimeState_INIT;
     31 
     32 /* Forward */
     33 grammar *getgrammar(const char *filename);
     34 
     35 void
     36 Py_Exit(int sts)
     37 {
     38     exit(sts);
     39 }
     40 
     41 /* Needed by obmalloc.c */
     42 int PyGILState_Check(void)
     43 { return 1; }
     44 
     45 void _PyMem_DumpTraceback(int fd, const void *ptr)
     46 {}
     47 
     48 int
     49 main(int argc, char **argv)
     50 {
     51     grammar *g;
     52     FILE *fp;
     53     char *filename, *graminit_h, *graminit_c;
     54 
     55     if (argc != 4) {
     56         fprintf(stderr,
     57             "usage: %s grammar graminit.h graminit.c\n", argv[0]);
     58         Py_Exit(2);
     59     }
     60     filename = argv[1];
     61     graminit_h = argv[2];
     62     graminit_c = argv[3];
     63     g = getgrammar(filename);
     64     fp = fopen(graminit_c, "w");
     65     if (fp == NULL) {
     66         perror(graminit_c);
     67         Py_Exit(1);
     68     }
     69     if (Py_DebugFlag)
     70         printf("Writing %s ...\n", graminit_c);
     71     printgrammar(g, fp);
     72     fclose(fp);
     73     fp = fopen(graminit_h, "w");
     74     if (fp == NULL) {
     75         perror(graminit_h);
     76         Py_Exit(1);
     77     }
     78     if (Py_DebugFlag)
     79         printf("Writing %s ...\n", graminit_h);
     80     printnonterminals(g, fp);
     81     fclose(fp);
     82     freegrammar(g);
     83     Py_Exit(0);
     84     return 0; /* Make gcc -Wall happy */
     85 }
     86 
     87 grammar *
     88 getgrammar(const char *filename)
     89 {
     90     FILE *fp;
     91     node *n;
     92     grammar *g0, *g;
     93     perrdetail err;
     94 
     95     fp = fopen(filename, "r");
     96     if (fp == NULL) {
     97         perror(filename);
     98         Py_Exit(1);
     99     }
    100     g0 = meta_grammar();
    101     n = PyParser_ParseFile(fp, filename, g0, g0->g_start,
    102                   (char *)NULL, (char *)NULL, &err);
    103     fclose(fp);
    104     if (n == NULL) {
    105         fprintf(stderr, "Parsing error %d, line %d.\n",
    106             err.error, err.lineno);
    107         if (err.text != NULL) {
    108             size_t len;
    109             int i;
    110             fprintf(stderr, "%s", err.text);
    111             len = strlen(err.text);
    112             if (len == 0 || err.text[len-1] != '\n')
    113                 fprintf(stderr, "\n");
    114             for (i = 0; i < err.offset; i++) {
    115                 if (err.text[i] == '\t')
    116                     putc('\t', stderr);
    117                 else
    118                     putc(' ', stderr);
    119             }
    120             fprintf(stderr, "^\n");
    121             PyObject_FREE(err.text);
    122         }
    123         Py_Exit(1);
    124     }
    125     g = pgen(n);
    126     PyNode_Free(n);
    127     if (g == NULL) {
    128         printf("Bad grammar.\n");
    129         Py_Exit(1);
    130     }
    131     return g;
    132 }
    133 
    134 /* Can't happen in pgen */
    135 PyObject*
    136 PyErr_Occurred()
    137 {
    138     return 0;
    139 }
    140 
    141 void
    142 Py_FatalError(const char *msg)
    143 {
    144     fprintf(stderr, "pgen: FATAL ERROR: %s\n", msg);
    145     Py_Exit(1);
    146 }
    147 
    148 /* No-nonsense my_readline() for tokenizer.c */
    149 
    150 char *
    151 PyOS_Readline(FILE *sys_stdin, FILE *sys_stdout, const char *prompt)
    152 {
    153     size_t n = 1000;
    154     char *p = (char *)PyMem_MALLOC(n);
    155     char *q;
    156     if (p == NULL)
    157         return NULL;
    158     fprintf(stderr, "%s", prompt);
    159     q = fgets(p, n, sys_stdin);
    160     if (q == NULL) {
    161         *p = '\0';
    162         return p;
    163     }
    164     n = strlen(p);
    165     if (n > 0 && p[n-1] != '\n')
    166         p[n-1] = '\n';
    167     return (char *)PyMem_REALLOC(p, n+1);
    168 }
    169 
    170 /* No-nonsense fgets */
    171 char *
    172 Py_UniversalNewlineFgets(char *buf, int n, FILE *stream, PyObject *fobj)
    173 {
    174     return fgets(buf, n, stream);
    175 }
    176 
    177 
    178 #include <stdarg.h>
    179 
    180 void
    181 PySys_WriteStderr(const char *format, ...)
    182 {
    183     va_list va;
    184 
    185     va_start(va, format);
    186     vfprintf(stderr, format, va);
    187     va_end(va);
    188 }
    189