annotate lwcc/cc-parse.c @ 506:7e8298f7bc0a

Add basic syntax for typecasting Add parser support for type casts. This current scheme handles only integer types. Also include parenthesis grouping in expressions.
author William Astle <lost@l-w.ca>
date Sun, 27 Oct 2019 12:06:01 -0600
parents 14a40f8bb4eb
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
498
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
1 /*
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
2 lwcc/cc-parse.c
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
3
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
4 Copyright © 2019 William Astle
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
5
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
6 This file is part of LWTOOLS.
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
7
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
8 LWTOOLS is free software: you can redistribute it and/or modify it under the
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
9 terms of the GNU General Public License as published by the Free Software
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
10 Foundation, either version 3 of the License, or (at your option) any later
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
11 version.
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
12
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
13 This program is distributed in the hope that it will be useful, but WITHOUT
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
16 more details.
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
17
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
18 You should have received a copy of the GNU General Public License along with
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
19 this program. If not, see <http://www.gnu.org/licenses/>.
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
20 */
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
21
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
22 #include <string.h>
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
23
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
24 #include <lw_alloc.h>
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
25 #include <lw_string.h>
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
26
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
27 #include "cpp.h"
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
28 #include "tree.h"
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
29
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
30 #define TOK_KW_IF -1
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
31 #define TOK_KW_ELSE -2
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
32 #define TOK_KW_WHILE -3
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
33 #define TOK_KW_DO -4
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
34 #define TOK_KW_FOR -5
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
35 #define TOK_KW_VOID -6
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
36 #define TOK_KW_INT -7
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
37 #define TOK_KW_CHAR -8
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
38 #define TOK_KW_SHORT -9
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
39 #define TOK_KW_LONG -10
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
40 #define TOK_KW_UNSIGNED -11
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
41 #define TOK_KW_SIGNED -12
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
42 #define TOK_KW_FLOAT -13
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
43 #define TOK_KW_DOUBLE -14
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
44 #define TOK_KW_STRUCT -15
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
45 #define TOK_KW_UNION -16
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
46 #define TOK_KW_TYPEDEF -17
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
47 #define TOK_KW_STATIC -18
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
48 #define TOK_KW_SWITCH -19
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
49 #define TOK_KW_CASE -20
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
50 #define TOK_KW_DEFAULT -21
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
51 #define TOK_KW_BREAK -22
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
52 #define TOK_KW_CONTINUE -23
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
53 #define TOK_KW_CONST -24
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
54 #define TOK_KW_AUTO -25
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
55 #define TOK_KW_ENUM -26
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
56 #define TOK_KW_REGISTER -27
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
57 #define TOK_KW_SIZEOF -28
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
58 #define TOK_KW_VOLATILE -29
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
59 #define TOK_KW_RETURN -30
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
60 #define TOK_KW_EXTERN -31
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
61 #define TOK_KW_GOTO -32
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
62 #define TOK_TYPENAME -100
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
63 #define TOK_CONST_INT -150
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
64
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
65 static struct { int tok; char *word; } keyword_list[] = {
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
66 { TOK_KW_IF, "if" },
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
67 { TOK_KW_ELSE, "else" },
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
68 { TOK_KW_WHILE, "while" },
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
69 { TOK_KW_DO, "do" },
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
70 { TOK_KW_FOR, "for" },
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
71 { TOK_KW_VOID, "void" },
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
72 { TOK_KW_INT, "int" },
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
73 { TOK_KW_CHAR, "char" },
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
74 { TOK_KW_SHORT, "short" },
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
75 { TOK_KW_LONG, "long" },
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
76 { TOK_KW_UNSIGNED, "unsigned" },
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
77 { TOK_KW_SIGNED, "signed" },
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
78 { TOK_KW_FLOAT, "float" },
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
79 { TOK_KW_DOUBLE, "double" },
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
80 { TOK_KW_STRUCT, "struct" },
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
81 { TOK_KW_UNION, "union" },
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
82 { TOK_KW_TYPEDEF, "typedef" },
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
83 { TOK_KW_STATIC, "static" },
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
84 { TOK_KW_SWITCH, "switch" },
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
85 { TOK_KW_CASE, "case" },
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
86 { TOK_KW_DEFAULT, "default" },
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
87 { TOK_KW_BREAK, "break" },
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
88 { TOK_KW_CONTINUE, "continue" },
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
89 { TOK_KW_CONST, "const" },
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
90 { TOK_KW_AUTO, "auto" },
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
91 { TOK_KW_ENUM, "enum" },
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
92 { TOK_KW_REGISTER, "register" },
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
93 { TOK_KW_SIZEOF, "sizeof" },
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
94 { TOK_KW_VOLATILE, "volatile" },
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
95 { TOK_KW_RETURN, "return" },
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
96 { TOK_KW_EXTERN, "extern" },
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
97 { TOK_KW_GOTO, "goto" },
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
98 { TOK_NONE, "" }
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
99 };
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
100
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
101
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
102 struct parser_state
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
103 {
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
104 struct preproc_info *pp; // preprocessor data
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
105 struct token *curtok; // the current token
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
106 };
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
107
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
108
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
109 struct token *parse_next(struct parser_state *ps)
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
110 {
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
111 struct token *tok;
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
112 int i;
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
113
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
114 for (;;)
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
115 {
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
116 tok = preproc_next(ps -> pp);
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
117 if (tok -> ttype == TOK_WSPACE)
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
118 continue;
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
119 if (tok -> ttype == TOK_EOL)
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
120 continue;
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
121 if (tok -> ttype == TOK_CHAR)
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
122 {
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
123 // random character
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
124 fprintf(stderr, "Random character %02x\n", tok -> strval[0]);
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
125 if (tok -> strval[0] < 32 || tok -> strval[0] > 126)
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
126 continue;
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
127 }
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
128 break;
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
129 }
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
130 if (tok -> ttype == TOK_IDENT)
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
131 {
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
132 // convert identifier tokens to their respective meanings
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
133 for (i = 0; keyword_list[i].tok != TOK_NONE; i++)
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
134 {
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
135 if (strcmp(keyword_list[i].word, tok -> strval) == 0)
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
136 {
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
137 tok -> ttype = keyword_list[i].tok;
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
138 goto out;
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
139 }
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
140 }
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
141 // check for registered types here
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
142 }
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
143 else if (tok -> ttype == TOK_NUMBER)
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
144 {
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
145 // look for anything that isn't 0-9
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
146 for (i = 0; tok -> strval[i]; i++)
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
147 {
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
148 if (tok -> strval[i] < '0' || tok -> strval[i] > '9')
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
149 break;
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
150 }
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
151 if (tok -> strval[i] == 0)
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
152 tok -> ttype = TOK_CONST_INT;
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
153 }
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
154 out:
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
155 fprintf(stderr, "Lexed: ");
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
156 token_print(tok, stderr);
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
157 fprintf(stderr, " (%d)\n", tok -> ttype);
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
158 if (ps -> curtok)
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
159 token_free(ps -> curtok);
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
160 ps -> curtok = tok;
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
161 return tok;
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
162 }
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
163
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
164 void parse_generr(struct parser_state *ps, char *tag)
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
165 {
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
166 fprintf(stderr, "(%s) Unexpected token (%d): ", tag, ps -> curtok -> ttype);
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
167 token_print(ps -> curtok, stderr);
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
168 fprintf(stderr, "\n");
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
169
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
170 }
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
171
502
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
172 node_t *parse_expr_real(struct parser_state *ps, int prec);
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
173
506
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
174 // parse an elementary type (int, etc.)
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
175 node_t *parse_elem_type(struct parser_state *ps)
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
176 {
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
177 int sgn = -1;
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
178 int nt = -1;
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
179 int nn = 1;
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
180
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
181 if (ps -> curtok -> ttype == TOK_KW_SIGNED)
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
182 {
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
183 sgn = 1;
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
184 parse_next(ps);
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
185 }
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
186 else if (ps -> curtok -> ttype == TOK_KW_UNSIGNED)
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
187 {
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
188 sgn = 0;
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
189 parse_next(ps);
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
190 }
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
191
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
192 switch (ps -> curtok -> ttype)
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
193 {
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
194 // NOTE: char is unsigned by default
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
195 case TOK_KW_CHAR:
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
196 if (sgn == -1 || sgn == 0)
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
197 nt = NODE_TYPE_UCHAR;
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
198 else
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
199 nt = NODE_TYPE_CHAR;
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
200 break;
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
201
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
202 case TOK_KW_SHORT:
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
203 nt = sgn ? NODE_TYPE_SHORT : NODE_TYPE_USHORT;
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
204 break;
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
205
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
206 case TOK_KW_INT:
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
207 nt = sgn ? NODE_TYPE_INT : NODE_TYPE_UINT;
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
208 break;
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
209
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
210 case TOK_KW_LONG:
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
211 parse_next(ps);
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
212 if (ps -> curtok -> ttype == TOK_KW_LONG)
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
213 {
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
214 nt = sgn ? NODE_TYPE_LONGLONG : NODE_TYPE_ULONGLONG;
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
215 break;
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
216 }
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
217 nn = 0;
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
218 nt = sgn ? NODE_TYPE_LONG : NODE_TYPE_ULONG;
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
219 break;
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
220
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
221 }
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
222 if (nt == -1)
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
223 {
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
224 if (sgn == -1)
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
225 {
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
226 return NULL;
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
227 }
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
228 else
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
229 {
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
230 nt = sgn ? NODE_TYPE_INT : NODE_TYPE_UINT;
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
231 }
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
232 }
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
233 else if (nn)
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
234 {
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
235 parse_next(ps);
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
236 }
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
237 return node_create(nt);
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
238 }
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
239
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
240 // if ident is non-zero, accept an identifier as part of the type; otherwise
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
241 // do not accept an identifier; currently a stub
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
242 node_t *parse_type(struct parser_state *ps, int ident)
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
243 {
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
244 node_t *rv;
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
245
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
246 // see if we have an elementary type
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
247 rv = parse_elem_type(ps);
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
248
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
249 // look for "struct", etc.
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
250
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
251 // look for pointer indicator(s)
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
252
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
253 // look for identifier if wanted/allowed
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
254
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
255 // look for array indicator or function parameter list
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
256 return rv;
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
257 }
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
258
501
f3e9732973f1 Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents: 498
diff changeset
259 node_t *parse_term_real(struct parser_state *ps)
498
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
260 {
506
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
261 node_t *rv, *rv2;
501
f3e9732973f1 Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents: 498
diff changeset
262
f3e9732973f1 Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents: 498
diff changeset
263 switch (ps -> curtok -> ttype)
498
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
264 {
501
f3e9732973f1 Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents: 498
diff changeset
265 case TOK_CONST_INT:
498
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
266 rv = node_create(NODE_CONST_INT, ps -> curtok -> strval);
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
267 parse_next(ps);
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
268 return rv;
506
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
269
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
270 // opening paren: either grouping or type cast
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
271 case TOK_OPAREN:
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
272 parse_next(ps);
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
273 // parse a type without an identifier
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
274 rv2 = parse_type(ps, 0);
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
275 if (rv2)
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
276 {
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
277 if (ps -> curtok -> ttype != TOK_CPAREN)
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
278 {
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
279 node_destroy(rv2);
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
280 parse_generr(ps, "missing ) on type cast");
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
281 return NULL;
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
282 }
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
283 parse_next(ps);
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
284 // detect C99 compound literal here
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
285 rv = parse_expr_real(ps, 175);
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
286 if (!rv)
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
287 {
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
288 node_destroy(rv);
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
289 return NULL;
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
290 }
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
291 return node_create(NODE_TYPECAST, rv2, rv);
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
292 }
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
293 // grouping
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
294 rv = parse_expr_real(ps, 0);
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
295 if (ps -> curtok -> ttype != TOK_CPAREN)
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
296 {
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
297 node_destroy(rv);
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
298 parse_generr(ps, "missing ) on expression grouping");
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
299 return NULL;
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
300 }
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
301 parse_next(ps);
7e8298f7bc0a Add basic syntax for typecasting
William Astle <lost@l-w.ca>
parents: 502
diff changeset
302 return rv;
498
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
303 }
501
f3e9732973f1 Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents: 498
diff changeset
304
f3e9732973f1 Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents: 498
diff changeset
305 parse_generr(ps, "term");
498
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
306 return NULL;
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
307 }
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
308
502
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
309 node_t *parse_expr_fncall(struct parser_state *ps, node_t *term1)
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
310 {
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
311 if (ps -> curtok -> ttype != TOK_CPAREN)
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
312 {
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
313 node_destroy(term1);
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
314 parse_generr(ps, "missing )");
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
315 return NULL;
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
316 }
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
317 parse_next(ps);
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
318 return node_create(NODE_OPER_FNCALL, term1, NULL);
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
319 }
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
320
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
321 node_t *parse_expr_postinc(struct parser_state *ps, node_t *term1)
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
322 {
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
323 return node_create(NODE_OPER_POSTINC, term1);
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
324 }
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
325
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
326 node_t *parse_expr_postdec(struct parser_state *ps, node_t *term1)
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
327 {
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
328 return node_create(NODE_OPER_POSTDEC, term1);
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
329 }
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
330
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
331 node_t *parse_expr_subscript(struct parser_state *ps, node_t *term1)
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
332 {
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
333 node_t *term2;
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
334 term2 = parse_expr_real(ps, 0);
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
335 if (!term2)
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
336 {
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
337 node_destroy(term1);
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
338 return NULL;
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
339 }
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
340 if (ps -> curtok -> ttype != TOK_CSQUARE)
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
341 {
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
342 node_destroy(term2);
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
343 node_destroy(term1);
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
344 parse_generr(ps, "missing ]");
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
345 return NULL;
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
346 }
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
347 parse_next(ps);
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
348 return node_create(NODE_OPER_SUBSCRIPT, term1, term2);
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
349 }
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
350
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
351 node_t *parse_expr_cond(struct parser_state *ps, node_t *term1)
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
352 {
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
353 node_t *term2, *term3;
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
354 // conditional operator
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
355 // NOTE: the middle operand is evaluated as though it is its own
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
356 // independent expression because the : must appear. The third
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
357 // operand is evaluated at the ternary operator precedence so that
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
358 // subsequent operand binding behaves correctly (if surprisingly). This
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
359 // would be less confusing if the ternary operator was fully bracketed
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
360 // (that is, had a terminator)
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
361 term2 = parse_expr_real(ps, 0);
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
362 if (!term2)
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
363 {
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
364 node_destroy(term1);
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
365 return NULL;
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
366 }
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
367 if (ps -> curtok -> ttype == TOK_COLON)
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
368 {
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
369 parse_next(ps);
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
370 term3 = parse_expr_real(ps, 25);
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
371 if (!term3)
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
372 {
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
373 node_destroy(term1);
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
374 node_destroy(term2);
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
375 return NULL;
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
376 }
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
377 return node_create(NODE_OPER_COND, term1, term2, term3);
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
378 }
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
379 else
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
380 {
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
381 node_destroy(term1);
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
382 node_destroy(term2);
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
383 parse_generr(ps, "missing :");
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
384 return NULL;
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
385 }
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
386 }
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
387
501
f3e9732973f1 Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents: 498
diff changeset
388 node_t *parse_expr_real(struct parser_state *ps, int prec)
f3e9732973f1 Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents: 498
diff changeset
389 {
502
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
390 static struct { int tok; int nodetype; int prec; int ra; node_t *(*spec)(struct parser_state *, node_t *); } operlist[] = {
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
391 // { TOK_OPAREN, NODE_OPER_FNCALL, 200, 0, parse_expr_fncall },
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
392 // { TOK_OSQUARE, NODE_OPER_SUBSCRIPT, 200, 0, parse_expr_subscript },
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
393 // { TOK_ARROW, NODE_OPER_PTRMEM, 200, 0 },
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
394 // { TOK_DOT, NODE_OPER_OBJMEM, 200, 0 },
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
395 // { TOK_DBLADD, NODE_OPER_POSTINC, 200, 0, parse_expr_postinc },
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
396 // { TOK_DBLSUB, NODE_OPER_POSTDEC, 200, 0, parse_expr_postdec },
501
f3e9732973f1 Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents: 498
diff changeset
397 { TOK_STAR, NODE_OPER_TIMES, 150 },
f3e9732973f1 Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents: 498
diff changeset
398 { TOK_DIV, NODE_OPER_DIVIDE, 150 },
502
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
399 { TOK_MOD, NODE_OPER_MOD, 150 },
501
f3e9732973f1 Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents: 498
diff changeset
400 { TOK_ADD, NODE_OPER_PLUS, 100 },
f3e9732973f1 Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents: 498
diff changeset
401 { TOK_SUB, NODE_OPER_MINUS, 100 },
502
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
402 { TOK_LSH, NODE_OPER_LSH, 90 },
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
403 { TOK_RSH, NODE_OPER_RSH, 90 },
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
404 { TOK_LT, NODE_OPER_LT, 80 },
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
405 { TOK_LE, NODE_OPER_LE, 80 },
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
406 { TOK_GT, NODE_OPER_GT, 80 },
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
407 { TOK_GE, NODE_OPER_GE, 80 },
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
408 { TOK_EQ, NODE_OPER_EQ, 70 },
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
409 { TOK_NE, NODE_OPER_NE, 70 },
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
410 { TOK_BWAND, NODE_OPER_BWAND, 60},
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
411 { TOK_XOR, NODE_OPER_BWXOR, 55 },
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
412 { TOK_BWOR, NODE_OPER_BWOR, 50 },
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
413 { TOK_BAND, NODE_OPER_BAND, 40 },
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
414 { TOK_BOR, NODE_OPER_BOR, 35 },
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
415 { TOK_QMARK, NODE_OPER_COND, 25, 1, parse_expr_cond },
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
416 // { TOK_ASS, NODE_OPER_ASS, 20, 1 },
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
417 // { TOK_ADDASS, NODE_OPER_ADDASS, 20, 1 },
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
418 // { TOK_SUBASS, NODE_OPER_SUBASS, 20, 1 },
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
419 // { TOK_MULASS, NODE_OPER_MULASS, 20, 1 },
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
420 // { TOK_DIVASS, NODE_OPER_DIVASS, 20, 1 },
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
421 // { TOK_MODASS, NODE_OPER_MODASS, 20, 1 },
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
422 // { TOK_LSHASS, NODE_OPER_LSHASS, 20, 1 },
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
423 // { TOK_RSHASS, NODE_OPER_RSHASS, 20, 1 },
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
424 // { TOK_BWANDASS, NODE_OPER_BWANDASS, 20, 1},
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
425 // { TOK_BWORASS, NODE_OPER_BWORASS, 20, 1 },
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
426 // { TOK_XORASS, NODE_OPER_BWXORASS, 20, 1 },
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
427 { TOK_COMMA, NODE_OPER_COMMA, 1 },
501
f3e9732973f1 Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents: 498
diff changeset
428 { 0, 0, 0 }
f3e9732973f1 Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents: 498
diff changeset
429 };
f3e9732973f1 Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents: 498
diff changeset
430 node_t *term1, *term2;
f3e9732973f1 Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents: 498
diff changeset
431 int i;
f3e9732973f1 Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents: 498
diff changeset
432
f3e9732973f1 Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents: 498
diff changeset
433 term1 = parse_term_real(ps);
f3e9732973f1 Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents: 498
diff changeset
434 if (!term1)
f3e9732973f1 Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents: 498
diff changeset
435 return NULL;
f3e9732973f1 Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents: 498
diff changeset
436
f3e9732973f1 Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents: 498
diff changeset
437 nextoper:
f3e9732973f1 Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents: 498
diff changeset
438 for (i = 0; operlist[i].tok; i++)
f3e9732973f1 Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents: 498
diff changeset
439 if (operlist[i].tok == ps -> curtok -> ttype)
f3e9732973f1 Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents: 498
diff changeset
440 break;
f3e9732973f1 Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents: 498
diff changeset
441 fprintf(stderr, "Matched operator: %d, %d\n", operlist[i].tok, operlist[i].prec);
f3e9732973f1 Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents: 498
diff changeset
442 // if we hit the end of the expression, return
f3e9732973f1 Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents: 498
diff changeset
443 if (operlist[i].tok == 0)
f3e9732973f1 Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents: 498
diff changeset
444 return term1;
f3e9732973f1 Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents: 498
diff changeset
445
502
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
446 // is previous operation higher precedence? If so, just return the first term
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
447 if (operlist[i].prec < prec)
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
448 return term1;
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
449
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
450 // is this operator left associative and previous operation is same precedence?
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
451 // if so, just return the first term
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
452 if (operlist[i].ra == 0 && operlist[i].prec == prec)
501
f3e9732973f1 Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents: 498
diff changeset
453 return term1;
f3e9732973f1 Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents: 498
diff changeset
454
502
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
455 // consume the operator
501
f3e9732973f1 Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents: 498
diff changeset
456 parse_next(ps);
502
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
457
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
458 // special handling
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
459 if (operlist[i].spec)
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
460 {
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
461 term2 = (operlist[i].spec)(ps, term1);
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
462 if (!term2)
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
463 {
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
464 node_destroy(term1);
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
465 return NULL;
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
466 }
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
467 term1 = term2;
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
468 goto nextoper;
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
469 }
501
f3e9732973f1 Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents: 498
diff changeset
470 term2 = parse_expr_real(ps, operlist[i].prec);
f3e9732973f1 Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents: 498
diff changeset
471 if (!term2)
f3e9732973f1 Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents: 498
diff changeset
472 {
f3e9732973f1 Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents: 498
diff changeset
473 parse_generr(ps, "expr");
502
14a40f8bb4eb Add various operators to lwcc
William Astle <lost@l-w.ca>
parents: 501
diff changeset
474 node_destroy(term1);
501
f3e9732973f1 Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents: 498
diff changeset
475 }
f3e9732973f1 Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents: 498
diff changeset
476
f3e9732973f1 Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents: 498
diff changeset
477 term1 = node_create(operlist[i].nodetype, term1, term2);
f3e9732973f1 Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents: 498
diff changeset
478 term2 = NULL;
f3e9732973f1 Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents: 498
diff changeset
479 goto nextoper;
f3e9732973f1 Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents: 498
diff changeset
480 }
f3e9732973f1 Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents: 498
diff changeset
481
f3e9732973f1 Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents: 498
diff changeset
482 node_t *parse_expr(struct parser_state *ps)
f3e9732973f1 Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents: 498
diff changeset
483 {
f3e9732973f1 Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents: 498
diff changeset
484 return parse_expr_real(ps, 0);
f3e9732973f1 Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents: 498
diff changeset
485 }
f3e9732973f1 Add basic integer operations to lwcc
William Astle <lost@l-w.ca>
parents: 498
diff changeset
486
498
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
487 node_t *parse_statement(struct parser_state *ps)
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
488 {
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
489 node_t *rv;
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
490 node_t *n;
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
491
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
492 switch (ps -> curtok -> ttype)
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
493 {
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
494 case TOK_KW_RETURN:
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
495 parse_next(ps);
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
496 n = parse_expr(ps);
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
497 if (!n)
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
498 {
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
499 parse_generr(ps, "statement");
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
500 return NULL;
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
501 }
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
502 rv = node_create(NODE_STMT_RETURN);
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
503 node_addchild(rv, n);
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
504 break;
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
505
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
506 default:
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
507 return NULL;
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
508 }
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
509
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
510 if (ps -> curtok -> ttype != TOK_EOS)
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
511 parse_generr(ps, "statement");
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
512 else
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
513 parse_next(ps);
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
514 return rv;
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
515 }
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
516
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
517 node_t *parse_globaldecl(struct parser_state *ps)
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
518 {
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
519 node_t *rv = NULL;
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
520 node_t *stmt;
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
521 char *fnname = NULL;
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
522 if (ps -> curtok -> ttype == TOK_KW_INT)
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
523 {
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
524 // variable name
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
525 parse_next(ps);
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
526 if (ps -> curtok -> ttype != TOK_IDENT)
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
527 goto error;
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
528 fnname = lw_strdup(ps -> curtok -> strval);
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
529 parse_next(ps);
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
530 if (ps -> curtok -> ttype != TOK_OPAREN)
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
531 goto error;
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
532 parse_next(ps);
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
533 if (ps -> curtok -> ttype != TOK_CPAREN)
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
534 goto error;
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
535 parse_next(ps);
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
536 if (ps -> curtok -> ttype != TOK_OBRACE)
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
537 goto error;
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
538 parse_next(ps);
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
539 stmt = parse_statement(ps);
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
540 if (!stmt)
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
541 goto error;
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
542 rv = node_create(NODE_FUNDEF, node_create(NODE_TYPE_INT), node_create(NODE_IDENT, fnname), node_create(NODE_FUNARGS), stmt);
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
543 if (ps -> curtok -> ttype != TOK_CBRACE)
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
544 goto error;
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
545 parse_next(ps);
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
546 lw_free(fnname);
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
547 return rv;
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
548 }
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
549
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
550
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
551 error:
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
552 if (fnname)
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
553 lw_free(fnname);
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
554 parse_generr(ps, "globaldecl");
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
555 return rv;
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
556 }
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
557
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
558 node_t *parse_program(struct preproc_info *pp)
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
559 {
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
560 node_t *rv;
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
561 node_t *node;
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
562 struct parser_state ps;
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
563
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
564 ps.pp = pp;
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
565 ps.curtok = NULL;
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
566
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
567 rv = node_create(NODE_PROGRAM);
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
568
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
569 // prime the parser
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
570 parse_next(&ps);
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
571 while (ps.curtok -> ttype != TOK_EOF)
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
572 {
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
573 node = parse_globaldecl(&ps);
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
574 if (!node)
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
575 break;
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
576 node_addchild(rv, node);
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
577 }
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
578
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
579 return rv;
1bd2d590d734 Rejig parser to eliminate lemon
William Astle <lost@l-w.ca>
parents:
diff changeset
580 }