bydgoszcz

simple, fast and efficient programming language
git clone git://git.kocotian.pl/bydgoszczscript.git
Log | Files | Refs | README | LICENSE

compile.c (23830B)


      1 /*
      2    bydgoszcz - simple, fast and efficient programming language
      3    Copyright (C) 2021  Kacper Kocot <kocotian@kocotian.pl>
      4 
      5    This program is free software; you can redistribute it and/or modify
      6    it under the terms of the GNU General Public License as published by
      7    the Free Software Foundation; either version 3 of the License, or
      8    (at your option) any later version.
      9 
     10    This program is distributed in the hope that it will be useful,
     11    but WITHOUT ANY WARRANTY; without even the implied warranty of
     12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13    GNU General Public License for more details.
     14 
     15    You should have received a copy of the GNU General Public License
     16    along with this program; if not, write to the Free Software Foundation,
     17    Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
     18 
     19 */
     20 
     21 #define _XOPEN_SOURCE 700
     22 #define _POSIX_C_SOURCE 200809L
     23 
     24 #include <compile.h>
     25 #include <stddef.h>
     26 #include <stdio.h>
     27 #include <stdlib.h>
     28 #include <string.h>
     29 #include <unistd.h>
     30 
     31 #include <errwarn.h>
     32 #include <str.h>
     33 #include <util.h>
     34 
     35 #define MAX_TYPESIZE 8192
     36 #define MAX_EXPRESSIONSIZE 8192
     37 
     38 typedef struct {
     39 	char ldata[MAX_TYPESIZE], rdata[MAX_TYPESIZE];
     40 	size_t llen, rlen;
     41 } TypeString;
     42 
     43 typedef struct {
     44 	char data[MAX_EXPRESSIONSIZE];
     45 	size_t len;
     46 } ExpressionString;
     47 
     48 static Token *enextToken(File *f, TokenType type);
     49 static void g_array(File *f, TypeString *str);
     50 static void g_struct(File *f, TypeString *str);
     51 static void g_type(File *f, TypeString *str);
     52 static void g_expression(File *f, ExpressionString *str);
     53 static void g_zadzwon(File *f, ExpressionString *str);
     54 static void g_obywatel(File *f);
     55 static void g_aglomeracja(File *f);
     56 static void g_miasto(File *f);
     57 static void initType(TypeString *t, int blank);
     58 
     59 static Token *
     60 enextToken(File *f, TokenType type)
     61 {
     62 	Token *r;
     63 	if ((r = nextToken(f)) == NULL)
     64 		errwarn(*f, 1, "unexpected end of input");
     65 	if (type != TokenNULL && r->type != type)
     66 		errwarn(*f, 1, "token type mismatch (expected %s, have %s)",
     67 				stringizeTokenType(type), stringizeTokenType(r->type));
     68 	return r;
     69 }
     70 
     71 static void
     72 g_array(File *f, TypeString *str)
     73 {
     74 	Token *t;
     75 	ExpressionString count;
     76 	TypeString type;
     77 
     78 	initType(&type, 1);
     79 	t = enextToken(f, TokenNULL);
     80 	if (t->type == TokenNumber) {
     81 		g_expression(f, &count);
     82 		t = enextToken(f, TokenIdentifier);
     83 		if (Strccmp(t->c, "elementow"))
     84 			errwarn(*f, 1, "unexpected identifier (expected elementow)");
     85 		t = enextToken(f, TokenNULL);
     86 	}
     87 	if (t->type == TokenIdentifier) {
     88 		if (Strccmp(t->c, "typu"))
     89 			errwarn(*f, 1, "unexpected identifier (expected typu)");
     90 		g_type(f, &type);
     91 	} else {
     92 		errwarn(*f, 1, "unexpected token (expected identifier)");
     93 	}
     94 	snprintf((char *)(str->ldata),
     95 			MAX_TYPESIZE,
     96 			"%.*s",
     97 			(int)(type.llen), type.ldata);
     98 	str->llen = strlen(str->ldata);
     99 	snprintf((char *)(str->rdata),
    100 			MAX_TYPESIZE,
    101 			"[%.*s]",
    102 			Strevalf(count));
    103 	str->rlen = strlen(str->rdata);
    104 }
    105 
    106 static void
    107 g_struct(File *f, TypeString *str)
    108 {
    109 	Token *t;
    110 	String name, fname;
    111 	TypeString type;
    112 
    113 	initType(&type, 1);
    114 	*str->ldata = 0;
    115 	strncat(str->ldata, "struct", MAX_TYPESIZE);
    116 	t = enextToken(f, TokenNULL);
    117 	if (t->type == TokenIdentifier) {
    118 		name = t->c;
    119 		strncat(str->ldata, " ", MAX_TYPESIZE);
    120 		++(str->llen);
    121 		str->llen += UMIN(strlen(str->ldata) + name.len, MAX_TYPESIZE);
    122 		strncat(str->ldata, name.data,
    123 				UMIN(name.len, MAX_TYPESIZE - str->llen));
    124 		str->ldata[UMIN(str->llen, MAX_TYPESIZE)] = 0;
    125 		t = enextToken(f, TokenNULL);
    126 	}
    127 	if (t->type == TokenColon) {
    128 		strncat(str->ldata, " {\n", MAX_TYPESIZE);
    129 		while ((t = enextToken(f, TokenIdentifier))) {
    130 			if (!Strccmp(t->c, "koniec")) {
    131 				strncat(str->ldata, "}", MAX_TYPESIZE);
    132 				str->llen = strlen(str->ldata);
    133 				break;
    134 			} else {
    135 				fname = t->c;
    136 				while ((t = enextToken(f, TokenNULL))) {
    137 					if (t->type == TokenIdentifier) {
    138 						if (!Strccmp(t->c, "przechowuje")) {
    139 							g_type(f, &type);
    140 						} else {
    141 							errwarn(*f, 1, "unexpected identifier (expected przechowuje)");
    142 						}
    143 					} else if (t->type == TokenSemicolon) {
    144 						snprintf((char *)(str->ldata + strlen(str->ldata)),
    145 								MAX_TYPESIZE - strlen(str->ldata),
    146 								"%.*s %.*s%.*s;\n",
    147 								(int)(type.llen), type.ldata,
    148 								Strevalf(fname),
    149 								(int)(type.rlen), type.rdata);
    150 						break;
    151 					} else {
    152 						errwarn(*f, 1, "unexpected token (expected identifier or semicolon)");
    153 					}
    154 				}
    155 			}
    156 		}
    157 	} else if (t->type == TokenSemicolon) {
    158 	} else {
    159 		errwarn(*f, 1, "unexpected token (expected colon)");
    160 	}
    161 }
    162 
    163 static void
    164 g_type(File *f, TypeString *str)
    165 {
    166 	Token *t;
    167 	String name, s;
    168 	TypeString arr;
    169 
    170 	int ptrlvl, isptrconst, isvalconst, isunsigned, isshort, islong;
    171 	ptrlvl = isptrconst = isvalconst = isunsigned = isshort = islong = 0;
    172 
    173 	initType(&arr, 1);
    174 
    175 	while ((t = enextToken(f, TokenIdentifier))) {
    176 		s = t->c;
    177 		if (!Strccmp(s, "wskaznik")) {
    178 			t = enextToken(f, TokenIdentifier);
    179 			if (Strccmp(t->c, "na"))
    180 				errwarn(*f, 1, "expected 'na' after 'wskaznik'");
    181 			++ptrlvl;
    182 		}
    183 		else if (!Strccmp(s, "staly")) isptrconst = 1;
    184 		else if (!Strccmp(s, "stale")) isvalconst = 1;
    185 		else if (!Strccmp(s, "nieoznakowane")) isunsigned = 1;
    186 		else if (!Strccmp(s, "oznakowane")) isunsigned = 2;
    187 		else if (!Strccmp(s, "krotkie")) isshort = 1;
    188 		else if (!Strccmp(s, "dlugie")) islong = 1;
    189 		else {
    190 			/* Basic types */
    191 			if (!Strccmp(t->c, "zadupie"))
    192 				name.len = strlen(name.data = "void");
    193 			else if (!Strccmp(t->c, "literki"))
    194 				name.len = strlen(name.data = "char");
    195 			else if (!Strccmp(t->c, "cyferki"))
    196 				name.len = strlen(name.data = "int");
    197 			else if (!Strccmp(t->c, "latajace"))
    198 				name.len = strlen(name.data = "float");
    199 			else if (!Strccmp(t->c, "podwojne"))
    200 				name.len = strlen(name.data = "double");
    201 			else if (!Strccmp(t->c, "cierpienie"))
    202 				name.len = strlen(name.data = "int");
    203 			else if (!Strccmp(t->c, "rodzine")) {
    204 				TypeString type;
    205 				initType(&type, 1);
    206 				g_array(f, &type);
    207 				name.len = type.llen;
    208 				name.data = type.ldata;
    209 				str->rlen = strlen(strncpy(str->rdata,
    210 							type.rdata,
    211 							UMIN(MAX_TYPESIZE, type.rlen)));
    212 			}
    213 			/* Composite types */
    214 			else if (!Strccmp(t->c, "organizacje")) {
    215 				TypeString type;
    216 				initType(&type, 1);
    217 				g_struct(f, &type);
    218 				name.len = type.llen;
    219 				name.data = type.ldata;
    220 			}
    221 			/* Other types */
    222 			else
    223 				name = t->c;
    224 			break;
    225 		}
    226 	}
    227 	str->llen = (size_t)(*(str->ldata) = 0);
    228 	if (isptrconst && ptrlvl)
    229 		str->llen = strlen(strncat(str->ldata, "const ", MAX_TYPESIZE - str->llen));
    230 	if (isunsigned == 1)
    231 		str->llen = strlen(strncat(str->ldata, "unsigned ", MAX_TYPESIZE - str->llen));
    232 	else if (isunsigned == 2)
    233 		str->llen = strlen(strncat(str->ldata, "signed ", MAX_TYPESIZE - str->llen));
    234 	if (isshort)
    235 		str->llen = strlen(strncat(str->ldata, "short ", MAX_TYPESIZE - str->llen));
    236 	else if (islong)
    237 		str->llen = strlen(strncat(str->ldata, "long ", MAX_TYPESIZE - str->llen));
    238 
    239 	strncat(str->ldata,
    240 			name.data,
    241 			UMIN(MAX_TYPESIZE - str->llen, name.len));
    242 
    243 	str->llen += name.len;
    244 
    245 	while (ptrlvl > 0 && ptrlvl--)
    246 		strncat(str->ldata, "*", MAX_TYPESIZE), str->llen++;
    247 	if (isvalconst)
    248 		strncat(str->ldata, " const", MAX_TYPESIZE), str->llen += 6;
    249 	strncat(str->ldata,
    250 			arr.ldata,
    251 			UMIN(MAX_TYPESIZE - str->llen, arr.llen));
    252 }
    253 
    254 static void
    255 g_expression(File *f, ExpressionString *str)
    256 {
    257 	Token *t;
    258 
    259 	t = &(f->curtok);
    260 	if (t->type == TokenNumber || t->type == TokenString) {
    261 		strncpy(str->data, t->c.data, UMIN(MAX_EXPRESSIONSIZE, t->c.len));
    262 		str->len = t->c.len;
    263 	} else if (t->type == TokenIdentifier) {
    264 		if (!Strccmp(t->c, "zadzwon")) {
    265 			g_zadzwon(f, str);
    266 		} else if (!Strccmp(t->c, "powieksz")
    267 		       ||  !Strccmp(t->c, "pomniejsz")
    268 		       ||  !Strccmp(t->c, "popowieksz")
    269 		       ||  !Strccmp(t->c, "popomniejsz")) {
    270 			ExpressionString expr;
    271 			int v = !Strccmp(t->c, "powieksz") ? 1 : !Strccmp(t->c, "pomniejsz") ? 2 :
    272 			!Strccmp(t->c, "popowieksz") ? 3 : !Strccmp(t->c, "popomniejsz") ? 4 : 0;
    273 			t = enextToken(f, TokenNULL);
    274 			g_expression(f, &expr);
    275 			str->len = (size_t)snprintf(str->data, MAX_EXPRESSIONSIZE, "%s%.*s%s",
    276 					v == 1 ? "++" : v == 2 ? "--" : "",
    277 					Strevalf(expr),
    278 					v == 3 ? "++" : v == 4 ? "--" : "");
    279 		} else if (!Strccmp(t->c, "prawda")) {
    280 			str->len = (size_t)snprintf(str->data, MAX_EXPRESSIONSIZE, "1");
    281 		} else if (!Strccmp(t->c, "nieprawda")) {
    282 			str->len = (size_t)snprintf(str->data, MAX_EXPRESSIONSIZE, "0");
    283 		} else if (!Strccmp(t->c, "ustaw")) {
    284 			ExpressionString what, as;
    285 			t = enextToken(f, TokenNULL);
    286 			g_expression(f, &what);
    287 			t = enextToken(f, TokenIdentifier);
    288 			if (Strccmp(t->c, "jako"))
    289 				errwarn(*f, 1, "unexpected identifier (expected jako)");
    290 			t = enextToken(f, TokenNULL);
    291 			g_expression(f, &as);
    292 			str->len = (size_t)snprintf(str->data, MAX_EXPRESSIONSIZE, "%.*s = %.*s",
    293 					Strevalf(what), Strevalf(as));
    294 		} else if (!Strccmp(t->c, "dodaj")) {
    295 			ExpressionString what, where;
    296 			t = enextToken(f, TokenNULL);
    297 			g_expression(f, &what);
    298 			t = enextToken(f, TokenIdentifier);
    299 			if (Strccmp(t->c, "do"))
    300 				errwarn(*f, 1, "unexpected identifier (expected do)");
    301 			t = enextToken(f, TokenNULL);
    302 			g_expression(f, &where);
    303 			str->len = (size_t)snprintf(str->data, MAX_EXPRESSIONSIZE, "%.*s += %.*s",
    304 					Strevalf(where), Strevalf(what));
    305 		} else if (!Strccmp(t->c, "odejmij")) {
    306 			ExpressionString what, from;
    307 			t = enextToken(f, TokenNULL);
    308 			g_expression(f, &what);
    309 			t = enextToken(f, TokenIdentifier);
    310 			if (Strccmp(t->c, "od"))
    311 				errwarn(*f, 1, "unexpected identifier (expected od)");
    312 			t = enextToken(f, TokenNULL);
    313 			g_expression(f, &from);
    314 			str->len = (size_t)snprintf(str->data, MAX_EXPRESSIONSIZE, "%.*s -= %.*s",
    315 					Strevalf(from), Strevalf(what));
    316 		} else if (!Strccmp(t->c, "pomnoz")) {
    317 			ExpressionString what, bywhat;
    318 			t = enextToken(f, TokenNULL);
    319 			g_expression(f, &what);
    320 			t = enextToken(f, TokenIdentifier);
    321 			if (Strccmp(t->c, "przez"))
    322 				errwarn(*f, 1, "unexpected identifier (expected przez)");
    323 			t = enextToken(f, TokenNULL);
    324 			g_expression(f, &bywhat);
    325 			str->len = (size_t)snprintf(str->data, MAX_EXPRESSIONSIZE, "%.*s *= %.*s",
    326 					Strevalf(what), Strevalf(bywhat));
    327 		} else if (!Strccmp(t->c, "podziel")) {
    328 			ExpressionString what, bywhat;
    329 			t = enextToken(f, TokenNULL);
    330 			g_expression(f, &what);
    331 			t = enextToken(f, TokenIdentifier);
    332 			if (Strccmp(t->c, "przez"))
    333 				errwarn(*f, 1, "unexpected identifier (expected przez)");
    334 			t = enextToken(f, TokenNULL);
    335 			g_expression(f, &bywhat);
    336 			str->len = (size_t)snprintf(str->data, MAX_EXPRESSIONSIZE, "%.*s /= %.*s",
    337 					Strevalf(what), Strevalf(bywhat));
    338 		} else if (!Strccmp(t->c, "suma")) {
    339 			ExpressionString first, second;
    340 			t = enextToken(f, TokenNULL);
    341 			g_expression(f, &first);
    342 			t = enextToken(f, TokenIdentifier);
    343 			if (Strccmp(t->c, "oraz"))
    344 				errwarn(*f, 1, "unexpected identifier (expected oraz)");
    345 			t = enextToken(f, TokenNULL);
    346 			g_expression(f, &second);
    347 			str->len = (size_t)snprintf(str->data, MAX_EXPRESSIONSIZE, "%.*s + %.*s",
    348 					Strevalf(first), Strevalf(second));
    349 		} else if (!Strccmp(t->c, "roznica")) {
    350 			ExpressionString first, second;
    351 			t = enextToken(f, TokenNULL);
    352 			g_expression(f, &first);
    353 			t = enextToken(f, TokenIdentifier);
    354 			if (Strccmp(t->c, "oraz"))
    355 				errwarn(*f, 1, "unexpected identifier (expected oraz)");
    356 			t = enextToken(f, TokenNULL);
    357 			g_expression(f, &second);
    358 			str->len = (size_t)snprintf(str->data, MAX_EXPRESSIONSIZE, "%.*s - %.*s",
    359 					Strevalf(first), Strevalf(second));
    360 		} else if (!Strccmp(t->c, "iloczyn")) {
    361 			ExpressionString first, second;
    362 			t = enextToken(f, TokenNULL);
    363 			g_expression(f, &first);
    364 			t = enextToken(f, TokenIdentifier);
    365 			if (Strccmp(t->c, "oraz"))
    366 				errwarn(*f, 1, "unexpected identifier (expected oraz)");
    367 			t = enextToken(f, TokenNULL);
    368 			g_expression(f, &second);
    369 			str->len = (size_t)snprintf(str->data, MAX_EXPRESSIONSIZE, "%.*s * %.*s",
    370 					Strevalf(first), Strevalf(second));
    371 		} else if (!Strccmp(t->c, "iloraz")) {
    372 			ExpressionString first, second;
    373 			t = enextToken(f, TokenNULL);
    374 			g_expression(f, &first);
    375 			t = enextToken(f, TokenIdentifier);
    376 			if (Strccmp(t->c, "oraz"))
    377 				errwarn(*f, 1, "unexpected identifier (expected oraz)");
    378 			t = enextToken(f, TokenNULL);
    379 			g_expression(f, &second);
    380 			str->len = (size_t)snprintf(str->data, MAX_EXPRESSIONSIZE, "%.*s / %.*s",
    381 					Strevalf(first), Strevalf(second));
    382 		} else if (!Strccmp(t->c, "reszta")) {
    383 			ExpressionString first, second;
    384 			t = enextToken(f, TokenIdentifier);
    385 			if (Strccmp(t->c, "z"))
    386 				errwarn(*f, 1, "unexpected identifier (expected z)");
    387 			t = enextToken(f, TokenNULL);
    388 			g_expression(f, &first);
    389 			t = enextToken(f, TokenIdentifier);
    390 			if (Strccmp(t->c, "przez"))
    391 				errwarn(*f, 1, "unexpected identifier (expected przez)");
    392 			t = enextToken(f, TokenNULL);
    393 			g_expression(f, &second);
    394 			str->len = (size_t)snprintf(str->data, MAX_EXPRESSIONSIZE, "%.*s %% %.*s",
    395 					Strevalf(first), Strevalf(second));
    396 		} else if (!Strccmp(t->c, "adres")) {
    397 			ExpressionString expr;
    398 			t = enextToken(f, TokenNULL);
    399 			g_expression(f, &expr);
    400 			str->len = (size_t)snprintf(str->data, MAX_EXPRESSIONSIZE, "&(%.*s)",
    401 					Strevalf(expr));
    402 		} else if (!Strccmp(t->c, "zawartosc")) {
    403 			ExpressionString expr;
    404 			t = enextToken(f, TokenNULL);
    405 			g_expression(f, &expr);
    406 			str->len = (size_t)snprintf(str->data, MAX_EXPRESSIONSIZE, "*(%.*s)",
    407 					Strevalf(expr));
    408 		} else if (!Strccmp(t->c, "przeciwienstwo")) {
    409 			ExpressionString expr;
    410 			t = enextToken(f, TokenNULL);
    411 			g_expression(f, &expr);
    412 			str->len = (size_t)snprintf(str->data, MAX_EXPRESSIONSIZE, "-(%.*s)",
    413 					Strevalf(expr));
    414 		} else if (!Strccmp(t->c, "nie")) {
    415 			ExpressionString expr;
    416 			t = enextToken(f, TokenNULL);
    417 			g_expression(f, &expr);
    418 			str->len = (size_t)snprintf(str->data, MAX_EXPRESSIONSIZE, "!(%.*s)",
    419 					Strevalf(expr));
    420 		} else if (!Strccmp(t->c, "wielkosc")) {
    421 			ExpressionString expr;
    422 			t = enextToken(f, TokenNULL);
    423 			g_expression(f, &expr);
    424 			str->len = (size_t)snprintf(str->data, MAX_EXPRESSIONSIZE, "sizeof (%.*s)",
    425 					Strevalf(expr));
    426 		} else if (!Strccmp(t->c, "naprawde") || !Strccmp(t->c, "czy")) {
    427 			ExpressionString lexpr, rexpr;
    428 			int not; int equal; int greater; int lower;
    429 			not = equal = greater = lower = 0;
    430 			t = enextToken(f, TokenNULL);
    431 			g_expression(f, &lexpr);
    432 			t = enextToken(f, TokenIdentifier);
    433 			if (!Strccmp(t->c, "nie")) {
    434 				not = 1;
    435 				t = enextToken(f, TokenIdentifier);
    436 			}
    437 			else if (Strccmp(t->c, "jest"))
    438 				errwarn(*f, 1, "unexpected identifier (expected jest)");
    439 			t = enextToken(f, TokenIdentifier);
    440 tester:
    441 			if (!Strccmp(t->c, "rowne")) {
    442 				equal = 1;
    443 			} else {
    444 				if (!Strccmp(t->c, "wieksze")) {
    445 					greater = 1;
    446 				} else if (!Strccmp(t->c, "mniejsze")) {
    447 					lower = 1;
    448 				}
    449 				t = enextToken(f, TokenIdentifier);
    450 				if (!Strccmp(t->c, "albo")) {
    451 					t = enextToken(f, TokenIdentifier);
    452 					goto tester;
    453 				} else if (Strccmp(t->c, "niz"))
    454 					errwarn(*f, 1, "unexpected identifier (expected albo or niz)");
    455 			}
    456 			t = enextToken(f, TokenNULL);
    457 			g_expression(f, &rexpr);
    458 			str->len = (size_t)snprintf(str->data, MAX_EXPRESSIONSIZE, "%s((%.*s) %s%s (%.*s))",
    459 					not ? "!" : "",
    460 					Strevalf(lexpr),
    461 					greater ? ">" : lower ? "<" : equal ? "=" : "",
    462 					equal ? "=" : "",
    463 					Strevalf(rexpr));
    464 		} else if (!Strccmp(t->c, "czlonek")) {
    465 			ExpressionString organization;
    466 			String member;
    467 			t = enextToken(f, TokenIdentifier);
    468 			member = t->c;
    469 			t = enextToken(f, TokenIdentifier);
    470 			if (Strccmp(t->c, "organizacji"))
    471 				errwarn(*f, 1, "unexpected identifier (expected organizacji)");
    472 			t = enextToken(f, TokenNULL);
    473 			g_expression(f, &organization);
    474 			str->len = (size_t)snprintf(str->data, MAX_EXPRESSIONSIZE, "(%.*s).%.*s",
    475 					Strevalf(organization), Strevalf(member));
    476 		} else if (!Strccmp(t->c, "element")) {
    477 			ExpressionString element, family;
    478 			t = enextToken(f, TokenNULL);
    479 			g_expression(f, &element);
    480 			t = enextToken(f, TokenIdentifier);
    481 			if (Strccmp(t->c, "rodziny"))
    482 				errwarn(*f, 1, "unexpected identifier (expected rodziny)");
    483 			t = enextToken(f, TokenNULL);
    484 			g_expression(f, &family);
    485 			str->len = (size_t)snprintf(str->data, MAX_EXPRESSIONSIZE, "(%.*s)[%.*s]",
    486 					Strevalf(family), Strevalf(element));
    487 		} else if (!Strccmp(t->c, "rzucaj")) {
    488 			ExpressionString expr;
    489 			TypeString type;
    490 			initType(&type, 1);
    491 			t = enextToken(f, TokenNULL);
    492 			g_expression(f, &expr);
    493 			t = enextToken(f, TokenIdentifier);
    494 			if (Strccmp(t->c, "w"))
    495 				errwarn(*f, 1, "unexpected identifier (expected organizacji)");
    496 			g_type(f, &type);
    497 			str->len = (size_t)snprintf(str->data, MAX_EXPRESSIONSIZE, "(%.*s)(%.*s)",
    498 					(int)(type.llen), type.ldata, Strevalf(expr));
    499 		} else if (!Strccmp(t->c, "nieoznakowane")) {
    500 			ExpressionString expr;
    501 			TypeString type;
    502 			initType(&type, 1);
    503 			t = enextToken(f, TokenNULL);
    504 			g_expression(f, &expr);
    505 			str->len = (size_t)snprintf(str->data, MAX_EXPRESSIONSIZE, "(unsigned)(%.*s)",
    506 					Strevalf(expr));
    507 		} else if (!Strccmp(t->c, "oznakowane")) {
    508 			ExpressionString expr;
    509 			TypeString type;
    510 			initType(&type, 1);
    511 			t = enextToken(f, TokenNULL);
    512 			g_expression(f, &expr);
    513 			str->len = (size_t)snprintf(str->data, MAX_EXPRESSIONSIZE, "(signed)(%.*s)",
    514 					Strevalf(expr));
    515 		} else if (!Strccmp(t->c, "__c")) {
    516 			t = enextToken(f, TokenString);
    517 			strncpy(str->data, t->c.data + 1, t->c.len - 2);
    518 			str->len = t->c.len - 2;
    519 		} else {
    520 			strncpy(str->data, t->c.data, UMIN(MAX_EXPRESSIONSIZE, t->c.len));
    521 			str->len = t->c.len;
    522 		}
    523 	} else {
    524 		errwarn(*f, 1, "expected expression");
    525 	}
    526 	str->data[UMIN(str->len, MAX_EXPRESSIONSIZE - 1)] = 0;
    527 }
    528 
    529 static void
    530 g_zadzwon(File *f, ExpressionString *str)
    531 {
    532 	Token *t;
    533 	String name;
    534 	ExpressionString expr;
    535 
    536 	t = enextToken(f, TokenIdentifier);
    537 	name = t->c;
    538 	str->len = (size_t)snprintf(str->data, MAX_EXPRESSIONSIZE,
    539 			"%.*s(", Strevalf(name));
    540 	t = enextToken(f, TokenNULL);
    541 	if (t->type == TokenIdentifier) {
    542 		if (!Strccmp(t->c, "daj")) {
    543 			t = enextToken(f, TokenColon);
    544 			while ((t = enextToken(f, TokenNULL))) {
    545 				g_expression(f, &expr);
    546 				strncat(str->data, expr.data, MAX_EXPRESSIONSIZE);
    547 				str->len += expr.len;
    548 				t = enextToken(f, TokenNULL);
    549 				if (t->type == TokenSemicolon)
    550 					break;
    551 				else if (t->type == TokenComma) {
    552 					strncat(str->data, ", ", MAX_EXPRESSIONSIZE);
    553 					str->len += 2;
    554 				} else {
    555 					errwarn(*f, 1, "unexpected %s (expected comma or semicolon)",
    556 							stringizeTokenType(t->type));
    557 				}
    558 			}
    559 		} else {
    560 			errwarn(*f, 1, "unexpected identifier (expected daj)");
    561 		}
    562 	}
    563 	strncat(str->data, ")", MAX_EXPRESSIONSIZE);
    564 	str->len += 1;
    565 }
    566 
    567 static void
    568 g_obywatel(File *f)
    569 {
    570 	String name;
    571 	TypeString type;
    572 	ExpressionString expr;
    573 
    574 	Token *t;
    575 
    576 	initType(&type, 0);
    577 	t = enextToken(f, TokenIdentifier);
    578 	name = t->c;
    579 	expr.len = strlen(strcpy(expr.data, ""));
    580 	while ((t = enextToken(f, TokenNULL))) {
    581 		if (t->type == TokenIdentifier) {
    582 			if (!Strccmp(t->c, "przechowuje")) {
    583 				g_type(f, &type);
    584 			} else if (!Strccmp(t->c, "rowne")) {
    585 				t = enextToken(f, TokenNULL);
    586 				g_expression(f, &expr);
    587 			} else {
    588 				errwarn(*f, 1, "unexpected identifier (expected przechowuje)");
    589 			}
    590 		} else if (t->type == TokenSemicolon) {
    591 			dprintf(f->outfd, "%.*s %.*s%.*s%s%.*s;\n",
    592 					(int)(type.llen), type.ldata,
    593 					Strevalf(name),
    594 					(int)(type.rlen), type.rdata,
    595 					expr.len ? " = " : "",
    596 					(int)(expr.len), expr.data);
    597 			return;
    598 		} else {
    599 			errwarn(*f, 1, "unexpected token (expected identifier or semicolon)");
    600 		}
    601 	}
    602 }
    603 
    604 static void
    605 g_aglomeracja(File *f)
    606 {
    607 	Token *t;
    608 	ExpressionString expr;
    609 
    610 	while ((t = enextToken(f, TokenNULL))) {
    611 		if (t->type == TokenIdentifier) {
    612 			if (!Strccmp(t->c, "koniec")) {
    613 				dprintf(f->outfd, "}\n");
    614 				return;
    615 			} else if (!Strccmp(t->c, "obywatel")) {
    616 				g_obywatel(f);
    617 			} else if (!Strccmp(t->c, "typ")) {
    618 				dprintf(f->outfd, "typedef ");
    619 				g_obywatel(f);
    620 			} else if (!Strccmp(t->c, "oddaj")) {
    621 				dprintf(f->outfd, "return ");
    622 				t = enextToken(f, TokenNULL);
    623 				goto expr;
    624 			} else if (!Strccmp(t->c, "jesli") || !Strccmp(t->c, "dopoki")) {
    625 				int isif; isif = !Strccmp(t->c, "jesli");
    626 				dprintf(f->outfd, isif ? "if (" : "while (");
    627 				while ((t = enextToken(f, TokenNULL))) {
    628 					g_expression(f, &expr);
    629 					t = enextToken(f, TokenIdentifier);
    630 					dprintf(f->outfd, "(%.*s)", Strevalf(expr));
    631 					if ((isif && !Strccmp(t->c, "wtedy")) || (!isif && !Strccmp(t->c, "rob")))
    632 						break;
    633 					else if (!Strccmp(t->c, "albo")) {
    634 						dprintf(f->outfd, " || ");
    635 					} else if (!Strccmp(t->c, "oraz")) {
    636 						dprintf(f->outfd, " && ");
    637 					} else {
    638 						errwarn(*f, 1, "unexpected identifier (expected albo, oraz or %s)",
    639 								isif ? "wtedy" : "rob");
    640 					}
    641 				}
    642 				dprintf(f->outfd, ") {\n");
    643 				t = enextToken(f, TokenColon);
    644 				g_aglomeracja(f);
    645 			} else if (!Strccmp(t->c, "inaczej")) {
    646 				dprintf(f->outfd, "} else {\n");
    647 			} else {
    648 				goto expr;
    649 			}
    650 		} else if (t->type == TokenSemicolon) {
    651 		} else {
    652 expr:
    653 			g_expression(f, &expr);
    654 			dprintf(f->outfd, "%.*s;\n", Strevalf(expr));
    655 		}
    656 	}
    657 
    658 	return;
    659 }
    660 
    661 static void
    662 g_miasto(File *f)
    663 {
    664 	String name;
    665 	TypeString type;
    666 	ExpressionString args;
    667 
    668 	Token *t;
    669 
    670 	initType(&type, 0);
    671 	t = enextToken(f, TokenIdentifier);
    672 	name = t->c;
    673 	args.len = (unsigned)(*(args.data) = 0);
    674 	while ((t = enextToken(f, TokenNULL))) {
    675 		if (t->type == TokenColon) {
    676 			dprintf(f->outfd, "%.*s %.*s(%.*s) {\n",
    677 					(int)(type.llen), type.ldata, Strevalf(name), Strevalf(args));
    678 			g_aglomeracja(f);
    679 			return;
    680 		} else if (t->type == TokenIdentifier) {
    681 			if (!Strccmp(t->c, "oddaje")) {
    682 				g_type(f, &type);
    683 			} else if (!Strccmp(t->c, "przyjmuje")) {
    684 				t = enextToken(f, TokenColon);
    685 				while ((t = enextToken(f, TokenIdentifier))) {
    686 					if (!Strccmp(t->c, "cdn")) {
    687 						args.len += (size_t)snprintf(
    688 								(char *)(args.data + strlen(args.data)),
    689 								MAX_TYPESIZE - strlen(args.data),
    690 								"...");
    691 						t = enextToken(f, TokenSemicolon);
    692 						break;
    693 					} else {
    694 						String argname;
    695 						TypeString argtype;
    696 
    697 						initType(&type, 0);
    698 						argname = t->c;
    699 						t = enextToken(f, TokenNULL);
    700 						if (t->type == TokenIdentifier) {
    701 							if (!Strccmp(t->c, "przechowuje")) {
    702 								g_type(f, &argtype);
    703 							} else {
    704 								errwarn(*f, 1, "unexpected identifier (expected przechowuje)");
    705 							}
    706 							t = enextToken(f, TokenNULL);
    707 						}
    708 						if (t->type == TokenComma || t->type == TokenSemicolon) {
    709 							args.len += (size_t)snprintf(
    710 									(char *)(args.data + strlen(args.data)),
    711 									MAX_TYPESIZE - strlen(args.data),
    712 									"%.*s %.*s%.*s%s",
    713 									(int)(argtype.llen), argtype.ldata,
    714 									Strevalf(argname),
    715 									(int)(argtype.rlen), argtype.rdata,
    716 									t->type == TokenComma ? ", " : "");
    717 							if (t->type == TokenSemicolon) break;
    718 						} else {
    719 							errwarn(*f, 1, "unexpected token (expected identifier or semicolon)");
    720 						}
    721 					}
    722 				}
    723 			} else {
    724 				errwarn(*f, 1, "unexpected identifier (expected przyjmuje or oddaje)");
    725 			}
    726 		} else {
    727 			errwarn(*f, 1, "unexpected token (expected colon, przyjmuje or oddaje)");
    728 		}
    729 	}
    730 }
    731 
    732 static void
    733 initType(TypeString *t, int blank)
    734 {
    735 	t->llen = strlen(strcpy(t->ldata, blank ? "" : "int"));
    736 	t->rlen = strlen(strcpy(t->rdata, ""));
    737 }
    738 
    739 void
    740 compile(File f)
    741 {
    742 	Token *t;
    743 
    744 	while ((t = nextToken(&f)) != NULL) {
    745 		if (!Strccmp(t->c, "wykorzystaj")) {
    746 			t = enextToken(&f, TokenString);
    747 			dprintf(f.outfd, "#include <%.*s.h>\n",
    748 					(int)t->c.len - 2, t->c.data + 1);
    749 		} else if (!Strccmp(t->c, "miasto")) {
    750 			g_miasto(&f);
    751 		} else if (!Strccmp(t->c, "obywatel")) {
    752 			g_obywatel(&f);
    753 		} else if (!Strccmp(t->c, "typ")) {
    754 			dprintf(f.outfd, "typedef ");
    755 			g_obywatel(&f);
    756 		} else {
    757 			errwarn(f, 1, "unexpected token");
    758 		}
    759 	}
    760 }