]> granicus.if.org Git - postgresql/blob - src/backend/parser/parser.c
Implement feature of new FE/BE protocol whereby RowDescription identifies
[postgresql] / src / backend / parser / parser.c
1 /*-------------------------------------------------------------------------
2  *
3  * parser.c
4  *              Main entry point/driver for PostgreSQL grammar
5  *
6  * Note that the grammar is not allowed to perform any table access
7  * (since we need to be able to do basic parsing even while inside an
8  * aborted transaction).  Therefore, the data structures returned by
9  * the grammar are "raw" parsetrees that still need to be analyzed by
10  * parse_analyze.
11  *
12  *
13  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
14  * Portions Copyright (c) 1994, Regents of the University of California
15  *
16  * IDENTIFICATION
17  *        $Header: /cvsroot/pgsql/src/backend/parser/parser.c,v 1.58 2003/05/05 01:59:02 tgl Exp $
18  *
19  *-------------------------------------------------------------------------
20  */
21
22 #include "postgres.h"
23
24 #include "nodes/parsenodes.h"
25 #include "parser/gramparse.h"
26 #include "parser/parse.h"
27 #include "parser/parser.h"
28 #include "parser/parse_expr.h"
29
30
31 List       *parsetree;                  /* result of parsing is left here */
32
33 static int      lookahead_token;        /* one-token lookahead */
34 static bool have_lookahead;             /* lookahead_token set? */
35
36
37 /*
38  * raw_parser
39  *              Given a query in string form, do lexical and grammatical analysis.
40  *
41  * Returns a list of raw (un-analyzed) parse trees.
42  */
43 List *
44 raw_parser(const char *str)
45 {
46         int                     yyresult;
47
48         parsetree = NIL;                        /* in case grammar forgets to set it */
49         have_lookahead = false;
50
51         scanner_init(str);
52         parser_init();
53         parse_expr_init();
54
55         yyresult = yyparse();
56
57         scanner_finish();
58
59         if (yyresult)                           /* error */
60                 return NIL;
61
62         return parsetree;
63 }
64
65
66 /*
67  * Intermediate filter between parser and base lexer (base_yylex in scan.l).
68  *
69  * The filter is needed because in some cases SQL92 requires more than one
70  * token lookahead.  We reduce these cases to one-token lookahead by combining
71  * tokens here, in order to keep the grammar LR(1).
72  *
73  * Using a filter is simpler than trying to recognize multiword tokens
74  * directly in scan.l, because we'd have to allow for comments between the
75  * words ...
76  */
77 int
78 yylex(void)
79 {
80         int                     cur_token;
81
82         /* Get next token --- we might already have it */
83         if (have_lookahead)
84         {
85                 cur_token = lookahead_token;
86                 have_lookahead = false;
87         }
88         else
89                 cur_token = base_yylex();
90
91         /* Do we need to look ahead for a possible multiword token? */
92         switch (cur_token)
93         {
94                 case UNION:
95                         /* UNION JOIN must be reduced to a single UNIONJOIN token */
96                         lookahead_token = base_yylex();
97                         if (lookahead_token == JOIN)
98                                 cur_token = UNIONJOIN;
99                         else
100                                 have_lookahead = true;
101                         break;
102
103                 default:
104                         break;
105         }
106
107         return cur_token;
108 }