cpp
authorMichael Wallner <mike@php.net>
Mon, 28 Nov 2016 09:00:15 +0000 (10:00 +0100)
committerMichael Wallner <mike@php.net>
Wed, 3 May 2017 06:44:00 +0000 (08:44 +0200)
37 files changed:
Makefile.frag
src/context.c
src/cpp.c [new file with mode: 0644]
src/cpp.h [new file with mode: 0644]
src/cpp_tokiter.c [new file with mode: 0644]
src/marshal.c
src/module.c
src/parser.c
src/parser.h
src/parser.re
src/parser_def.h
src/parser_proc.c
src/parser_proc.h
src/parser_proc.y
src/parser_proc_def.h [new file with mode: 0644]
src/plist.c
src/plist.h
src/token.c
src/token.h
src/types.h
src/types/assert_stmt.c
src/types/cpp_exp.c [new file with mode: 0644]
src/types/cpp_exp.h [new file with mode: 0644]
src/types/cpp_macro_call.c [new file with mode: 0644]
src/types/cpp_macro_call.h [new file with mode: 0644]
src/types/cpp_macro_decl.c [new file with mode: 0644]
src/types/cpp_macro_decl.h [new file with mode: 0644]
src/types/decl_enum_item.c
src/types/impl_def_val.c
src/types/let_exp.c
src/types/num_exp.c
src/types/num_exp.h
src/types/number.c
src/types/number.h
src/types/set_exp.c
tests/idn/idn.psi
tests/parser/cpp/define001.psi [new file with mode: 0644]

index 502b1e21d8d9bb5309e71508c64a3160fe604f7b..39ba8c0731bd897dcd0b0a23a55d3bbe6a2a3119 100644 (file)
@@ -23,7 +23,8 @@ $(PHP_PSI_BUILDDIR)/lemon: $(PHP_PSI_BUILDDIR)/lemon.c | $(PHP_PSI_BUILDDIR)/lem
 $(PHP_PSI_SRCDIR)/src/parser_proc.h: $(PHP_PSI_SRCDIR)/src/parser_proc.c
 
 $(PHP_PSI_SRCDIR)/src/parser_proc.inc:
-$(PHP_PSI_SRCDIR)/src/parser_proc.y: $(PHP_PSI_SRCDIR)/src/parser_def.h $(PHP_PSI_SRCDIR)/src/parser_proc.inc
+$(PHP_PSI_SRCDIR)/src/parser_proc_def.h: $(PHP_PSI_SRCDIR)/src/parser_def.h
+$(PHP_PSI_SRCDIR)/src/parser_proc.y: $(PHP_PSI_SRCDIR)/src/parser_proc_def.h $(PHP_PSI_SRCDIR)/src/parser_proc.inc
        cat $(PHP_PSI_SRCDIR)/src/parser_proc.inc >$@
        $(CPP) -P -DGENERATE $< >>$@
 $(PHP_PSI_SRCDIR)/src/parser_proc.c: $(PHP_PSI_SRCDIR)/src/parser_proc.y $(LEMON)
index d4510ebc579d1af794c4bd89b8c563c4b373d935..199f533317ed7dfce6981ec01778a3fdfd819511 100644 (file)
@@ -256,14 +256,7 @@ void psi_context_build(struct psi_context *C, const char *paths)
                                        continue;
                                }
 
-                               while (0 < psi_parser_scan(&P)) {
-                                       psi_parser_parse(&P, psi_token_alloc(&P));
-                                       if (P.num == PSI_T_EOF) {
-                                               break;
-                                       }
-                               }
-
-                               psi_parser_parse(&P, NULL);
+                               psi_parser_parse(&P);
                                psi_context_add_data(C, PSI_DATA(&P));
                                psi_parser_dtor(&P);
                        }
@@ -341,7 +334,7 @@ zend_function_entry *psi_context_compile(struct psi_context *C)
                                zend_string *name = strpprintf(0, "psi\\%s\\%s", e->name, item->name);
 
                                zc.name = zend_string_dup(name, 1);
-                               ZVAL_LONG(&zc.value, psi_long_num_exp(item->num, NULL));
+                               ZVAL_LONG(&zc.value, psi_long_num_exp(item->num, NULL, NULL));
                                zend_register_constant(&zc);
                                zend_string_release(name);
                        }
diff --git a/src/cpp.c b/src/cpp.c
new file mode 100644 (file)
index 0000000..8fcd5cf
--- /dev/null
+++ b/src/cpp.c
@@ -0,0 +1,453 @@
+/*******************************************************************************
+ Copyright (c) 2017, Michael Wallner <mike@php.net>.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+     * Redistributions of source code must retain the above copyright notice,
+       this list of conditions and the following disclaimer.
+     * Redistributions in binary form must reproduce the above copyright
+       notice, this list of conditions and the following disclaimer in the
+       documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+#include "php_psi_stdinc.h"
+
+#include "cpp.h"
+#include "parser.h"
+
+static inline bool psi_cpp_level_skipped(struct psi_cpp_data *cpp)
+{
+       return cpp->skip == cpp->level;
+}
+static inline void psi_cpp_level_skip(struct psi_cpp_data *cpp)
+{
+       assert(!cpp->skip);
+       cpp->skip = cpp->level;
+}
+static inline void psi_cpp_level_unskip(struct psi_cpp_data *cpp)
+{
+       if (psi_cpp_level_skipped(cpp)) {
+               cpp->skip = 0;
+       }
+}
+static inline bool psi_cpp_level_masked(struct psi_cpp_data *cpp)
+{
+       return cpp->seen & (1 << cpp->level);
+}
+static inline void psi_cpp_level_mask(struct psi_cpp_data *cpp)
+{
+       assert(!psi_cpp_level_masked(cpp));
+       cpp->seen |= (1 << cpp->level);
+}
+static inline void psi_cpp_level_unmask(struct psi_cpp_data *cpp)
+{
+       cpp->seen &= ~(1 << cpp->level);
+}
+
+static void psi_cpp_eval(struct psi_data *D, struct psi_cpp_data *cpp)
+{
+       assert(cpp->exp);
+
+       PSI_DEBUG_PRINT(D, "PSI: CPP EVAL < %s (level=%u, skip=%u)\n",
+                       cpp->exp->token->text, cpp->level, cpp->skip);
+
+#if PSI_CPP_DEBUG
+       psi_cpp_exp_dump(2, cpp->exp);
+#endif
+
+       switch (cpp->exp->type) {
+       case PSI_T_ERROR:
+               if (!cpp->skip) {
+                       D->error(D, cpp->exp->token, PSI_ERROR, "%s",
+                                       cpp->exp->data.tok->text);
+               }
+               break;
+       case PSI_T_WARNING:
+               if (!cpp->skip) {
+                       D->error(D, cpp->exp->token, PSI_WARNING, "%s",
+                                       cpp->exp->data.tok->text);
+               }
+               break;
+       case PSI_T_UNDEF:
+               if (!cpp->skip) {
+                       psi_cpp_undef(cpp, cpp->exp->data.tok);
+               }
+               break;
+       case PSI_T_DEFINE:
+               if (!cpp->skip) {
+                       psi_cpp_define(cpp, cpp->exp->data.decl);
+                       /* FIXME: copy */
+                       cpp->exp->data.decl = NULL;
+               }
+               break;
+       case PSI_T_IFDEF:
+               ++cpp->level;
+               if (!cpp->skip) {
+                       if (psi_cpp_defined(cpp, cpp->exp->data.tok)) {
+                               psi_cpp_level_mask(cpp);
+                       } else {
+                               psi_cpp_level_skip(cpp);
+                       }
+               }
+               break;
+       case PSI_T_IFNDEF:
+               ++cpp->level;
+               if (!cpp->skip) {
+                       if (psi_cpp_defined(cpp, cpp->exp->data.tok)) {
+                               psi_cpp_level_skip(cpp);
+                       } else {
+                               psi_cpp_level_mask(cpp);
+                       }
+               }
+               break;
+       case PSI_T_IF:
+               ++cpp->level;
+               if (!cpp->skip) {
+                       if (psi_cpp_if(cpp->exp, &cpp->defs, D)) {
+                               psi_cpp_level_mask(cpp);
+                       } else {
+                               psi_cpp_level_skip(cpp);
+                       }
+               }
+               break;
+       case PSI_T_ENDIF:
+               if (!cpp->level) {
+                       D->error(D, cpp->exp->token, PSI_WARNING, "Ingoring lone #endif");
+               } else {
+                       psi_cpp_level_unskip(cpp);
+                       psi_cpp_level_unmask(cpp);
+                       --cpp->level;
+               }
+               break;
+       case PSI_T_ELSE:
+               /* FIXME: catch "else" after "else" */
+               if (!cpp->level) {
+                       D->error(D, cpp->exp->token, PSI_WARNING, "Ingoring lone #else");
+               } else if (psi_cpp_level_skipped(cpp) && !psi_cpp_level_masked(cpp)) {
+                       /*
+                        * if skip is set on this level and the level has
+                        * not been masked yet, then unskip and mask this level
+                        */
+                       psi_cpp_level_unskip(cpp);
+                       psi_cpp_level_mask(cpp);
+               } else if (!cpp->skip && psi_cpp_level_masked(cpp)) {
+                       /*
+                        * previous block masked this level
+                        */
+                       psi_cpp_level_skip(cpp);
+               } else {
+                       assert(cpp->skip < cpp->level);
+               }
+               break;
+       case PSI_T_ELIF:
+               if (!cpp->level) {
+                       D->error(D, cpp->exp->token, PSI_WARNING, "Ingoring lone #elif");
+               } else if (psi_cpp_level_skipped(cpp) && !psi_cpp_level_masked(cpp)) {
+                       /*
+                        * if skip is set on this level and the level has
+                        * not been masked yet, then unskip and mask this
+                        * level, if the condition evals truthy
+                        */
+                       if (psi_cpp_if(cpp->exp, &cpp->defs, D)) {
+                               psi_cpp_level_unskip(cpp);
+                               psi_cpp_level_mask(cpp);
+                       }
+               } else if (!cpp->skip && psi_cpp_level_masked(cpp)) {
+                       /*
+                        * previous block masked this level
+                        */
+                       psi_cpp_level_skip(cpp);
+               } else {
+                       assert(cpp->skip < cpp->level);
+               }
+               break;
+       default:
+               assert(0);
+               break;
+       }
+
+       PSI_DEBUG_PRINT(D, "PSI: CPP EVAL > %s (level=%u, skip=%u)\n",
+                       cpp->exp->token->text, cpp->level, cpp->skip);
+
+       psi_cpp_exp_free(&cpp->exp);
+}
+
+static bool psi_cpp_stage1(struct psi_parser *P, struct psi_cpp_data *cpp)
+{
+       bool name = false, define = false, hash = false, eol = true, esc = false, ws = false;
+
+       psi_cpp_tokiter_reset(cpp);
+       while (psi_cpp_tokiter_valid(cpp)) {
+               struct psi_token *token = psi_cpp_tokiter_current(cpp);
+
+               /* strip comments */
+               if (token->type == PSI_T_COMMENT) {
+                       psi_cpp_tokiter_del_cur(cpp, true);
+                       continue;
+               }
+
+               /* line continuations */
+               if (token->type == PSI_T_EOL) {
+                       if (esc) {
+                               psi_cpp_tokiter_del_range(cpp, psi_cpp_tokiter_index(cpp) - 1, 2, true);
+                               psi_cpp_tokiter_prev(cpp);
+                               esc = false;
+                               continue;
+                       }
+               } else if (token->type == PSI_T_BSLASH) {
+                       esc = !esc;
+               } else {
+                       esc = false;
+               }
+
+               /* this whole turf is needed to distinct between:
+                * #define foo (1,2,3)
+                * #define foo(a,b,c)
+                */
+
+               if (token->type == PSI_T_WHITESPACE) {
+                       ws = true;
+                       psi_cpp_tokiter_del_cur(cpp, true);
+                       continue;
+               }
+
+               switch (token->type) {
+               case PSI_T_EOL:
+                       eol = true;
+                       break;
+               case PSI_T_HASH:
+                       if (eol) {
+                               hash = true;
+                               eol = false;
+                       }
+                       break;
+               case PSI_T_DEFINE:
+                       if (hash) {
+                               define = true;
+                               hash = false;
+                       }
+                       break;
+               case PSI_T_NAME:
+                       if (define) {
+                               name = true;
+                               define = false;
+                       }
+                       break;
+               case PSI_T_LPAREN:
+                       if (name) {
+                               name = false;
+                               if (!ws) {
+                                       /* mask special token for parser */
+                                       struct psi_token *no_ws = psi_token_copy(token);
+
+                                       no_ws->type = PSI_T_NO_WHITESPACE;
+                                       no_ws->text[0] = '\xA0';
+                                       psi_cpp_tokiter_ins_cur(cpp, no_ws);
+                                       continue;
+                               }
+                       }
+                       /* no break */
+               default:
+                       name = define = hash = eol = false;
+                       break;
+               }
+
+               ws = false;
+               psi_cpp_tokiter_next(cpp);
+       }
+
+       return true;
+}
+
+static bool psi_cpp_stage2(struct psi_parser *P, struct psi_cpp_data *cpp)
+{
+       do {
+               bool is_eol = true, do_cpp = false, do_expansion = true, skip_paren = false, skip_all = false;
+
+               psi_cpp_tokiter_reset(cpp);
+
+               while (psi_cpp_tokiter_valid(cpp)) {
+                       struct psi_token *current = psi_cpp_tokiter_current(cpp);
+
+                       if (current->type == PSI_T_HASH) {
+                               if (is_eol) {
+                                       do_cpp = true;
+                                       is_eol = false;
+                               }
+                       } else if (current->type == PSI_T_EOL) {
+#if PSI_CPP_DEBUG
+                               fprintf(stderr, "PSI: CPP do_expansion=true, PSI_T_EOL\n");
+#endif
+                               is_eol = true;
+                               skip_all = false;
+                               do_expansion = true;
+                               if (!do_cpp) {
+                                       psi_cpp_tokiter_del_cur(cpp, true);
+                                       continue;
+                               }
+                       } else {
+                               is_eol = false;
+
+                               if (do_cpp) {
+                                       switch (current->type) {
+                                       case PSI_T_DEFINE:
+#if PSI_CPP_DEBUG
+                                               fprintf(stderr, "PSI: CPP do_expansion=false, PSI_T_DEFINE, skip_all\n");
+#endif
+                                               do_expansion = false;
+                                               skip_all = true;
+                                               break;
+                                       case PSI_T_DEFINED:
+                                               skip_paren = true;
+                                               /* no break */
+                                       case PSI_T_IFDEF:
+                                       case PSI_T_IFNDEF:
+                                       case PSI_T_UNDEF:
+#if PSI_CPP_DEBUG
+                                               fprintf(stderr, "PSI: CPP do_expansion=false, PSI_T_{IF{,N},UN}DEF\n");
+#endif
+                                               do_expansion = false;
+                                               break;
+                                       case PSI_T_LPAREN:
+                                               if (!skip_all) {
+                                                       if (skip_paren) {
+                                                               skip_paren = false;
+                                                       } else {
+                                                               do_expansion = true;
+#if PSI_CPP_DEBUG
+                                                               fprintf(stderr, "PSI: CPP do_expansion=true, PSI_T_LPAREN, !skip_all, !skip_paren\n");
+#endif
+                                                       }
+                                               }
+                                               break;
+                                       case PSI_T_NAME:
+                                               break;
+                                       default:
+                                               do_expansion = !skip_all;
+#if PSI_CPP_DEBUG
+                                               fprintf(stderr, "PSI CPP do_expansion=%s, <- !skip_all\n", do_expansion?"true":"false");
+#endif
+                                       }
+                               }
+                       }
+
+                       if (cpp->skip) {
+                               /* FIXME: del_range */
+                               if (!do_cpp) {
+#if PSI_CPP_DEBUG
+                                       fprintf(stderr, "PSI: CPP skip ");
+                                       psi_token_dump(2, current);
+#endif
+                                       psi_cpp_tokiter_del_cur(cpp, true);
+                                       continue;
+                               }
+                       }
+
+                       if (do_expansion && current->type == PSI_T_NAME && psi_cpp_tokiter_defined(cpp)) {
+                               bool expanded = false;
+
+                               while (psi_cpp_tokiter_expand(cpp)) {
+                                       expanded = true;
+                               }
+                               if (expanded) {
+                                       continue;
+                               }
+                       }
+
+                       if (do_cpp) {
+                               if (is_eol) {
+                                       do_cpp = false;
+                                       skip_all = false;
+                               }
+
+                               if (P->flags & PSI_DEBUG) {
+                                       fprintf(stderr, "PSI> Parse (%zu) ", psi_cpp_tokiter_index(cpp));
+                                       psi_token_dump(2, current);
+                               }
+
+                               psi_parser_proc_parse(P->proc, current->type, current, P);
+                               psi_cpp_tokiter_del_cur(cpp, false);
+
+                               if (is_eol) {
+                                       psi_parser_proc_parse(P->proc, 0, NULL, P);
+                                       psi_cpp_eval(PSI_DATA(P), cpp);
+                               }
+
+#if PSI_CPP_DEBUG
+                               psi_cpp_tokiter_dump(2, cpp);
+#endif
+
+                               continue;
+                       }
+
+                       psi_cpp_tokiter_next(cpp);
+               }
+       } while (cpp->expanded);
+
+       return true;
+}
+
+bool psi_cpp_preprocess(struct psi_parser *P, struct psi_cpp_data *cpp)
+{
+       if (!psi_cpp_stage1(P, cpp)) {
+               return false;
+       }
+
+       if (!psi_cpp_stage2(P, cpp)) {
+               return false;
+       }
+
+       return true;
+}
+
+bool psi_cpp_defined(struct psi_cpp_data *cpp, struct psi_token *tok)
+{
+       bool defined;
+
+       if (tok->type == PSI_T_NAME) {
+               defined = zend_hash_str_exists(&cpp->defs, tok->text, tok->size);
+       } else {
+               defined = false;
+       }
+
+#if PSI_CPP_DEBUG
+       fprintf(stderr, "PSI: CPP defined -> %s ", defined ? "true" : "false");
+       psi_token_dump(2, tok);
+#endif
+
+       return defined;
+}
+
+void psi_cpp_define(struct psi_cpp_data *cpp, struct psi_cpp_macro_decl *decl)
+{
+       zend_hash_str_add_ptr(&cpp->defs, decl->token->text, decl->token->size, decl);
+}
+
+bool psi_cpp_undef(struct psi_cpp_data *cpp, struct psi_token *tok)
+{
+       return SUCCESS == zend_hash_str_del(&cpp->defs, tok->text, tok->size);
+}
+
+bool psi_cpp_if(struct psi_cpp_exp *exp, HashTable *defs, struct psi_data *D)
+{
+       if (!psi_num_exp_validate(D, exp->data.num, NULL, NULL, NULL, NULL, NULL)) {
+               return false;
+       }
+       if (!psi_long_num_exp(exp->data.num, NULL, defs)) {
+               return false;
+       }
+       return true;
+}
diff --git a/src/cpp.h b/src/cpp.h
new file mode 100644 (file)
index 0000000..1a8fc2c
--- /dev/null
+++ b/src/cpp.h
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ Copyright (c) 2017, Michael Wallner <mike@php.net>.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+     * Redistributions of source code must retain the above copyright notice,
+       this list of conditions and the following disclaimer.
+     * Redistributions in binary form must reproduce the above copyright
+       notice, this list of conditions and the following disclaimer in the
+       documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+#ifndef PSI_CPP_H
+#define PSI_CPP_H
+
+#include "data.h"
+
+#ifndef PSI_CPP_DEBUG
+# define PSI_CPP_DEBUG 0
+#endif
+
+struct psi_cpp_data {
+       HashTable defs;
+       unsigned level;
+       unsigned skip;
+       unsigned seen;
+       size_t index;
+       struct psi_plist *tokens;
+       unsigned expanded;
+       struct psi_cpp_exp *exp;
+};
+
+bool psi_cpp_preprocess(struct psi_parser *P, struct psi_cpp_data *cpp);
+bool psi_cpp_if(struct psi_cpp_exp *exp, HashTable *defs, struct psi_data *D);
+bool psi_cpp_defined(struct psi_cpp_data *cpp, struct psi_token *tok);
+void psi_cpp_define(struct psi_cpp_data *cpp, struct psi_cpp_macro_decl *decl);
+bool psi_cpp_undef(struct psi_cpp_data *cpp, struct psi_token *tok);
+
+void psi_cpp_tokiter_reset(struct psi_cpp_data *cpp);
+bool psi_cpp_tokiter_seek(struct psi_cpp_data *cpp, size_t index);
+void psi_cpp_tokiter_dump(int fd, struct psi_cpp_data *cpp);
+struct psi_token *psi_cpp_tokiter_current(struct psi_cpp_data *cpp);
+size_t psi_cpp_tokiter_index(struct psi_cpp_data *cpp);
+void psi_cpp_tokiter_next(struct psi_cpp_data *cpp);
+void psi_cpp_tokiter_prev(struct psi_cpp_data *cpp);
+bool psi_cpp_tokiter_valid(struct psi_cpp_data *cpp);
+bool psi_cpp_tokiter_del_cur(struct psi_cpp_data *cpp, bool free_token);
+bool psi_cpp_tokiter_del_range(struct psi_cpp_data *cpp, size_t offset,
+               size_t num_eles, bool free_tokens);
+bool psi_cpp_tokiter_ins_cur(struct psi_cpp_data *cpp, struct psi_token *tok);
+bool psi_cpp_tokiter_ins_range(struct psi_cpp_data *cpp, size_t offset,
+               size_t num_eles, void **eles);
+bool psi_cpp_tokiter_defined(struct psi_cpp_data *cpp);
+bool psi_cpp_tokiter_expand(struct psi_cpp_data *cpp);
+
+#endif
diff --git a/src/cpp_tokiter.c b/src/cpp_tokiter.c
new file mode 100644 (file)
index 0000000..e1d45f3
--- /dev/null
@@ -0,0 +1,419 @@
+/*******************************************************************************
+ Copyright (c) 2017, Michael Wallner <mike@php.net>.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+     * Redistributions of source code must retain the above copyright notice,
+       this list of conditions and the following disclaimer.
+     * Redistributions in binary form must reproduce the above copyright
+       notice, this list of conditions and the following disclaimer in the
+       documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+#include "php_psi_stdinc.h"
+
+#include "cpp.h"
+#include "parser.h"
+
+
+void psi_cpp_tokiter_dump(int fd, struct psi_cpp_data *cpp)
+{
+       size_t i;
+       struct psi_token *T;
+
+       for (i = 0; psi_plist_get(cpp->tokens, i, &T); ++i) {
+               dprintf(fd, "PSI: CPP tokens %5zu %c ", i, cpp->index == i ? '*' : ' ');
+               psi_token_dump(fd, T);
+       }
+}
+
+void psi_cpp_tokiter_reset(struct psi_cpp_data *cpp)
+{
+#if PSI_CPP_DEBUG
+       fprintf(stderr, "PSI: CPP reset (%zu tokens)\n", psi_plist_count(cpp->tokens));
+       psi_cpp_tokiter_dump(2, cpp);
+#endif
+       cpp->index = 0;
+       cpp->expanded = 0;
+}
+
+bool psi_cpp_tokiter_seek(struct psi_cpp_data *cpp, size_t index)
+{
+       if (index < psi_plist_count(cpp->tokens)) {
+               cpp->index = index;
+               return true;
+       }
+       return false;
+}
+
+struct psi_token *psi_cpp_tokiter_current(struct psi_cpp_data *cpp)
+{
+       struct psi_token *current = NULL;
+       bool found = psi_plist_get(cpp->tokens, cpp->index, &current);
+
+       assert(found);
+
+       return current;
+}
+
+size_t psi_cpp_tokiter_index(struct psi_cpp_data *cpp)
+{
+       return cpp->index;
+}
+
+void psi_cpp_tokiter_next(struct psi_cpp_data *cpp)
+{
+#if 0 && PSI_CPP_DEBUG
+       fprintf(stderr, "PSI: CPP next -> index=%zu -> index=%zu\n", cpp->index, cpp->index+1);
+#endif
+       ++cpp->index;
+}
+
+void psi_cpp_tokiter_prev(struct psi_cpp_data *cpp)
+{
+#if 0 && PSI_CPP_DEBUG
+       fprintf(stderr, "PSI: CPP prev -> index=%zu -> index=%zu\n", cpp->index, cpp->index-1);
+#endif
+       if (cpp->index) {
+               --cpp->index;
+       }
+}
+
+bool psi_cpp_tokiter_valid(struct psi_cpp_data *cpp)
+{
+#if 0 && PSI_CPP_DEBUG
+       fprintf(stderr, "PSI: CPP valid -> index=%zu -> %d\n", cpp->index, cpp->index < psi_plist_count(cpp->tokens));
+#endif
+       return cpp->index < psi_plist_count(cpp->tokens);
+}
+
+bool psi_cpp_tokiter_del_cur(struct psi_cpp_data *cpp, bool free_token)
+{
+       struct psi_token *cur = NULL;
+       bool deleted = psi_plist_del(cpp->tokens, cpp->index, &cur);
+
+#if PSI_CPP_DEBUG
+       fprintf(stderr, "PSI: CPP del_cur -> index=%zu, del=%d, free=%d ",
+                       cpp->index, (int) deleted, (int) free_token);
+       if (cur) {
+               psi_token_dump(2, cur);
+       } else {
+               fprintf(stderr, "NULL\n");
+       }
+#endif
+       if (cur && free_token) {
+               free(cur);
+       }
+       if (deleted && cpp->index >= psi_plist_count(cpp->tokens)) {
+               cpp->index = MAX(0, psi_plist_count(cpp->tokens)-1);
+       }
+       return deleted;
+}
+
+bool psi_cpp_tokiter_del_range(struct psi_cpp_data *cpp, size_t offset, size_t num_eles, bool free_tokens)
+{
+       struct psi_token **ptr;
+       bool deleted;
+
+       if (free_tokens) {
+               ptr = calloc(num_eles, sizeof(*ptr));
+       } else {
+               ptr = NULL;
+       }
+
+#if PSI_CPP_DEBUG
+       fprintf(stderr, "PSI: CPP del_range -> index=%zu, offset=%zu, num_eles=%zu\n", cpp->index, offset, num_eles);
+#endif
+
+       deleted = psi_plist_del_range(cpp->tokens, offset, num_eles, (void *) ptr);
+
+       if (deleted) {
+               if (cpp->index >= psi_plist_count(cpp->tokens)) {
+                       cpp->index = MAX(0, psi_plist_count(cpp->tokens)-1);
+               }
+               if (free_tokens) {
+                       while (num_eles--) {
+                               if (ptr[num_eles]) {
+                                       free(ptr[num_eles]);
+                               }
+                       }
+                       free(ptr);
+               }
+       }
+       return deleted;
+}
+
+bool psi_cpp_tokiter_ins_cur(struct psi_cpp_data *cpp, struct psi_token *tok)
+{
+       struct psi_plist *tokens = psi_plist_ins(cpp->tokens, cpp->index, &tok);
+
+#if PSI_CPP_DEBUG
+       fprintf(stderr, "PSI: CPP ins_cur -> index=%zu ", cpp->index);
+       psi_token_dump(2, tok);
+#endif
+
+       if (!tokens) {
+               return false;
+       }
+       cpp->tokens = tokens;
+       return true;
+}
+
+bool psi_cpp_tokiter_ins_range(struct psi_cpp_data *cpp, size_t offset,
+               size_t num_eles, void **eles)
+{
+       struct psi_plist *tokens = psi_plist_ins_range(cpp->tokens, offset,
+                       num_eles, eles);
+
+#if PSI_CPP_DEBUG
+       fprintf(stderr, "PSI: CPP ins_range -> index=%zu, offset=%zu, num_eles=%zu\n", cpp->index, offset, num_eles);
+#endif
+
+       if (!tokens) {
+               return false;
+       }
+       cpp->tokens = tokens;
+       return true;
+}
+
+bool psi_cpp_tokiter_defined(struct psi_cpp_data *cpp)
+{
+       if (psi_cpp_tokiter_valid(cpp)) {
+               struct psi_token *current = psi_cpp_tokiter_current(cpp);
+
+               return psi_cpp_defined(cpp, current);
+       }
+
+       return false;
+}
+
+void psi_cpp_tokiter_expand_tokens(struct psi_cpp_data *cpp, struct psi_plist *tokens)
+{
+       if (tokens && psi_plist_count(tokens)) {
+               size_t i;
+               struct psi_token **exp_tokens = calloc(psi_plist_count(tokens), sizeof(*exp_tokens));
+
+               for (i = 0; psi_plist_get(tokens, i, &exp_tokens[i]); ++i) {
+                       exp_tokens[i] = psi_token_copy(exp_tokens[i]);
+
+#if PSI_CPP_DEBUG
+                       fprintf(stderr, "PSI: CPP expand > ");
+                       psi_token_dump(2, exp_tokens[i]);
+#endif
+               }
+               psi_cpp_tokiter_ins_range(cpp, psi_cpp_tokiter_index(cpp), i, (void *) exp_tokens);
+               free(exp_tokens);
+       }
+}
+
+static void psi_cpp_tokiter_free_call_tokens(struct psi_plist **arg_tokens_list, size_t arg_count, bool free_tokens)
+{
+       size_t i;
+
+       for (i = 0; i < arg_count; ++i) {
+               if (arg_tokens_list[i]) {
+                       if (free_tokens) {
+                               struct psi_token *tok;
+
+                               while (psi_plist_pop(arg_tokens_list[i], &tok)) {
+                                       free(tok);
+                               }
+                       }
+                       psi_plist_free(arg_tokens_list[i]);
+               }
+       }
+       free(arg_tokens_list);
+}
+
+static struct psi_plist **psi_cpp_tokiter_read_call_tokens(
+               struct psi_cpp_data *cpp, size_t arg_count)
+{
+       size_t arg_index = 0, lparens = 1, rparens = 0;
+       struct psi_plist **arg_tokens = calloc(arg_count, sizeof(*arg_tokens));
+       struct psi_plist *free_tokens = psi_plist_init((void (*)(void *)) psi_token_free);
+       struct psi_token *tok;
+
+       arg_tokens[0] = psi_plist_init(NULL);
+
+       /* free macro name token on success */
+       tok = psi_cpp_tokiter_current(cpp);
+       free_tokens = psi_plist_add(free_tokens, &tok);
+
+       /* next token must be a LPAREN for a macro call */
+       psi_cpp_tokiter_next(cpp);
+       tok = psi_cpp_tokiter_current(cpp);
+       if (!psi_cpp_tokiter_valid(cpp) || tok->type != PSI_T_LPAREN) {
+               goto fail;
+       }
+
+       /* free LPAREN on success */
+       free_tokens = psi_plist_add(free_tokens, &tok);
+
+       while (lparens > rparens) {
+               psi_cpp_tokiter_next(cpp);
+               if (!psi_cpp_tokiter_valid(cpp)) {
+                       goto fail;
+               }
+               tok = psi_cpp_tokiter_current(cpp);
+
+               switch (tok->type) {
+               case PSI_T_LPAREN:
+                       ++lparens;
+                       arg_tokens[arg_index] = psi_plist_add(arg_tokens[arg_index], &tok);
+                       break;
+               case PSI_T_RPAREN:
+                       if (++rparens == lparens) {
+                               /* closing RPAREN */
+                               if (arg_index + 1 < arg_count) {
+                                       goto fail;
+                               }
+                               free_tokens = psi_plist_add(free_tokens, &tok);
+                       } else {
+                               arg_tokens[arg_index] = psi_plist_add(arg_tokens[arg_index], &tok);
+                       }
+                       break;
+               case PSI_T_COMMA:
+                       if (1 == (lparens - rparens)) {
+                               /* too many commas? */
+                               if (++arg_index >= arg_count) {
+                                       goto fail;
+                               }
+                               free_tokens = psi_plist_add(free_tokens, &tok);
+                               /* next arg */
+                               arg_tokens[arg_index] = psi_plist_init(NULL);
+                       } else {
+                               arg_tokens[arg_index] = psi_plist_add(arg_tokens[arg_index], &tok);
+                       }
+                       break;
+               default:
+                       arg_tokens[arg_index] = psi_plist_add(arg_tokens[arg_index], &tok);
+               }
+       }
+
+       psi_plist_free(free_tokens);
+       return arg_tokens;
+
+fail:
+       psi_cpp_tokiter_free_call_tokens(arg_tokens, arg_count, false);
+       return NULL;
+}
+
+static void psi_cpp_tokiter_expand_call_tokens(struct psi_cpp_data *cpp,
+               struct psi_cpp_macro_decl *macro, struct psi_plist **arg_tokens_list)
+{
+       size_t i;
+       struct psi_token *tok;
+
+       for (i = 0; psi_plist_get(macro->tokens, i, &tok); ++i) {
+               struct psi_plist *arg_tokens = NULL;
+
+               if (tok->type == PSI_T_NAME) {
+                       size_t s;
+                       struct psi_token *arg_name;
+
+                       for (s = 0; psi_plist_get(macro->sig, s, &arg_name); ++s) {
+                               if (arg_name->size == tok->size) {
+                                       if (!memcmp(arg_name->text, tok->text, tok->size)) {
+                                               arg_tokens = arg_tokens_list[s];
+                                               break;
+                                       }
+                               }
+                       }
+               }
+
+               if (arg_tokens) {
+                       size_t tok_count = psi_plist_count(arg_tokens);
+
+                       if (tok_count) {
+                               psi_cpp_tokiter_expand_tokens(cpp, arg_tokens);
+                               psi_cpp_tokiter_seek(cpp, psi_cpp_tokiter_index(cpp) + tok_count);
+                       }
+               } else {
+                       psi_cpp_tokiter_ins_cur(cpp, psi_token_copy(tok));
+                       psi_cpp_tokiter_next(cpp);
+               }
+       }
+}
+
+static bool psi_cpp_tokiter_expand_call(struct psi_cpp_data *cpp,
+               struct psi_cpp_macro_decl *macro)
+{
+       /* function-like macro
+        * #define FOO(a,b) a>b // macro->sig == {a, b}, macro->tokens = {a, >, b}
+        * # if FOO(1,2) // expands to if 1 > 2
+        */
+       size_t start = psi_cpp_tokiter_index(cpp);
+       struct psi_plist **arg_tokens_list;
+
+       /* read in tokens, until we have balanced parens */
+       arg_tokens_list = psi_cpp_tokiter_read_call_tokens(cpp, psi_plist_count(macro->sig));
+       if (!arg_tokens_list) {
+               psi_cpp_tokiter_seek(cpp, start);
+               return false;
+       }
+
+       /* ditch arg tokens */
+       psi_cpp_tokiter_del_range(cpp, start, psi_cpp_tokiter_index(cpp) - start + 1, false);
+       psi_cpp_tokiter_seek(cpp, start);
+
+       /* insert and expand macro tokens */
+       psi_cpp_tokiter_expand_call_tokens(cpp, macro, arg_tokens_list);
+       psi_cpp_tokiter_free_call_tokens(arg_tokens_list, psi_plist_count(macro->sig), true);
+
+       /* back to where we took off */
+       psi_cpp_tokiter_seek(cpp, start);
+       ++cpp->expanded;
+       return true;
+}
+
+bool psi_cpp_tokiter_expand(struct psi_cpp_data *cpp)
+{
+       if (psi_cpp_tokiter_valid(cpp)) {
+               struct psi_token *current = psi_cpp_tokiter_current(cpp);
+
+               if (current) {
+                       struct psi_cpp_macro_decl *macro = zend_hash_str_find_ptr(
+                                       &cpp->defs, current->text, current->size);
+
+                       /* don't expand itself */
+                       if (macro && macro->token != current) {
+#if PSI_CPP_DEBUG
+                               fprintf(stderr, "PSI: CPP expand < ");
+                               psi_token_dump(2, current);
+#endif
+                               if (macro->sig) {
+                                       return psi_cpp_tokiter_expand_call(cpp, macro);
+                               } else {
+                                       size_t index = psi_cpp_tokiter_index(cpp);
+
+                                       /* delete current token from stream */
+                                       psi_cpp_tokiter_del_cur(cpp, true);
+
+                                       if (index != psi_cpp_tokiter_index(cpp)) {
+                                               /* might have been last token */
+                                               psi_cpp_tokiter_next(cpp);
+                                       }
+                                       /* replace with tokens from macro */
+                                       psi_cpp_tokiter_expand_tokens(cpp, macro->tokens);
+
+                                       ++cpp->expanded;
+                                       return true;
+                               }
+                       }
+               }
+       }
+       return false;
+}
index 63a7dc914bbcfc278c98c627d809fafac260325f..b36eb5ffe879086a52b20eab217f74dcada4cf7f 100644 (file)
@@ -398,7 +398,7 @@ void psi_set_to_stringl(zval *return_value, struct psi_set_exp *set, impl_val *r
                struct psi_set_exp *sub_exp;
 
                psi_plist_get(set->inner, 0, &sub_exp);
-               RETVAL_STRINGL(str, psi_long_num_exp(sub_exp->data.num, frame));
+               RETVAL_STRINGL(str, psi_long_num_exp(sub_exp->data.num, frame, NULL));
        } else {
                RETVAL_EMPTY_STRING();
        }
@@ -528,7 +528,7 @@ void psi_set_to_array_counted(zval *return_value, struct psi_set_exp *set, impl_
        }
 
        psi_plist_get(set->inner, 0, &sub_exp);
-       count = psi_long_num_exp(sub_exp->data.num, frame);
+       count = psi_long_num_exp(sub_exp->data.num, frame, NULL);
        psi_plist_get(set->inner, 1, &sub_exp);
 
        for (ptr = (char *) ret_val; 0 < count--; ptr += size) {
index b253e0a68d1b632d129b6f95d2969a52d95bc77b..1db2adff529377b922a848f262fbf71e6a680449 100644 (file)
@@ -143,14 +143,7 @@ static PHP_FUNCTION(psi_validate)
                RETURN_FALSE;
        }
 
-       while (0 < psi_parser_scan(&P)) {
-               psi_parser_parse(&P, psi_token_alloc(&P));
-               if (P.num == PSI_T_EOF) {
-                       break;
-               }
-       }
-       psi_parser_parse(&P, NULL);
-
+       psi_parser_parse(&P);
        psi_data_ctor(&D, P.error, P.flags);
        RETVAL_BOOL(psi_data_validate(&D, PSI_DATA(&P)) && !P.errors);
        psi_data_dtor(&D);
@@ -180,14 +173,7 @@ static PHP_FUNCTION(psi_validate_string)
                RETURN_FALSE;
        }
 
-       while (0 < psi_parser_scan(&P)) {
-               psi_parser_parse(&P, psi_token_alloc(&P));
-               if (P.num == PSI_T_EOF) {
-                       break;
-               }
-       }
-       psi_parser_parse(&P, NULL);
-
+       psi_parser_parse(&P);
        psi_data_ctor(&D, P.error, P.flags);
        RETVAL_BOOL(psi_data_validate(&D, PSI_DATA(&P)) && !P.errors);
        psi_data_dtor(&D);
index 9cafa4eb9d7d4ca92da840a1bf4c774605534650..2b6c11ef10e8eb9c3172a3fb73b9b0917255c041 100644 (file)
@@ -1,4 +1,4 @@
-/* Generated by re2c 0.16 on Tue Feb 21 15:25:35 2017 */
+/* Generated by re2c 0.16 on Tue Mar  7 09:49:40 2017 */
 #line 1 "src/parser.re"
 /*******************************************************************************
  Copyright (c) 2016, Michael Wallner <mike@php.net>.
 #include "php_psi_stdinc.h"
 #include <sys/mman.h>
 #include <assert.h>
+#include <stdarg.h>
 
 #include "parser.h"
 
-void *psi_parser_proc_init(void);
-void psi_parser_proc_free(void **parser_proc);
-void psi_parser_proc_parse(void *parser_proc, token_t r, struct psi_token *token, struct psi_parser *parser);
-void psi_parser_proc_trace(FILE *out, char *prefix);
+#define YYMAXFILL 12
+#ifndef YYMAXFILL
+# define YYMAXFILL 256
+#endif
+#line 57 "src/parser.re"
+
+
+static void free_cpp_def(zval *p)
+{
+       if (Z_TYPE_P(p) == IS_PTR) {
+               psi_cpp_macro_decl_free((void *) &Z_PTR_P(p));
+       } else if (Z_REFCOUNTED_P(p)) {
+               zval_ptr_dtor(p);
+       }
+}
 
 struct psi_parser *psi_parser_init(struct psi_parser *P, psi_error_cb error, unsigned flags)
 {
@@ -49,6 +61,11 @@ struct psi_parser *psi_parser_init(struct psi_parser *P, psi_error_cb error, uns
        P->line = 1;
        P->proc = psi_parser_proc_init();
 
+       zend_hash_init(&P->cpp.defs, 0, NULL, free_cpp_def, 1);
+       zval tmp;
+       ZVAL_ARR(&tmp, &P->cpp.defs);
+       add_assoc_string(&tmp, "PHP_OS", PHP_OS);
+
        if (flags & PSI_DEBUG) {
                psi_parser_proc_trace(stderr, "PSI> ");
        }
@@ -56,162 +73,183 @@ struct psi_parser *psi_parser_init(struct psi_parser *P, psi_error_cb error, uns
        return P;
 }
 
+void psi_parser_reset(struct psi_parser *P)
+{
+       P->cur = P->tok = P->mrk = P->input.buffer;
+       P->lim = P->input.buffer + P->input.length;
+}
+
 bool psi_parser_open_file(struct psi_parser *P, const char *filename)
 {
-       FILE *fp = fopen(filename, "r");
+       struct stat sb;
+       FILE *fp;
+       char *fb;
 
-       if (!fp) {
+       if (stat(filename, &sb)) {
                P->error(PSI_DATA(P), NULL, PSI_WARNING,
-                               "Could not open '%s' for reading: %s",
+                               "Could not stat '%s': %s",
                                filename, strerror(errno));
                return false;
        }
 
-       P->input.type = PSI_PARSE_FILE;
-       P->input.data.file.handle = fp;
-
-#if HAVE_MMAP
-       struct stat sb;
-       int fd = fileno(fp);
+       if (!(fb = malloc(sb.st_size + YYMAXFILL))) {
+               P->error(PSI_DATA(P), NULL, PSI_WARNING,
+                               "Could not allocate %zu bytes for reading '%s': %s",
+                               sb.st_size + YYMAXFILL, filename, strerror(errno));
+               return false;
+       }
 
-       if (fstat(fd, &sb)) {
+       if (!(fp = fopen(filename, "r"))) {
+               free(fb);
                P->error(PSI_DATA(P), NULL, PSI_WARNING,
-                               "Could not stat '%s': %s",
+                               "Could not open '%s' for reading: %s",
                                filename, strerror(errno));
                return false;
        }
 
-       P->input.data.file.buffer = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fd, 0);
-       if (MAP_FAILED == P->input.data.file.buffer) {
+       if (sb.st_size != fread(fb, 1, sb.st_size, fp)) {
+               free(fb);
+               fclose(fp);
                P->error(PSI_DATA(P), NULL, PSI_WARNING,
-                               "Could not map '%s' for reading: %s",
-                               filename, strerror(errno));
+                               "Could not read %zu bytes from '%s': %s",
+                               sb.st_size + YYMAXFILL, filename, strerror(errno));
                return false;
        }
-       P->input.data.file.length = sb.st_size;
-#else
-       P->input.data.file.buffer = malloc(BSIZE);
-#endif
+       memset(fb + sb.st_size, 0, YYMAXFILL);
+
+       if (P->input.buffer) {
+               free(P->input.buffer);
+       }
+       P->input.buffer = fb;
+       P->input.length = sb.st_size;
 
        P->file.fn = strdup(filename);
 
+       psi_parser_reset(P);
+
        return true;
 }
 
 bool psi_parser_open_string(struct psi_parser *P, const char *string, size_t length)
 {
-       P->input.type = PSI_PARSE_STRING;
-       P->input.data.string.length = length;
-       if (!(P->input.data.string.buffer = strndup(string, length))) {
+       char *sb;
+
+       if (!(sb = malloc(length + YYMAXFILL))) {
+               P->error(PSI_DATA(P), NULL, PSI_WARNING,
+                               "Could not allocate %zu bytes: %s",
+                               length + YYMAXFILL, strerror(errno));
                return false;
        }
 
+       memcpy(sb, string, length);
+       memset(sb + length, 0, YYMAXFILL);
+
+       if (P->input.buffer) {
+               free(P->input.buffer);
+       }
+       P->input.buffer = sb;
+       P->input.length = length;
+
        P->file.fn = strdup("<input>");
 
+       psi_parser_reset(P);
+
        return true;
 }
 
-static ssize_t psi_parser_fill(struct psi_parser *P, size_t n)
+#if 0
+static void psi_parser_register_constants(struct psi_parser *P)
 {
-       PSI_DEBUG_PRINT(P, "PSI< Fill: n=%zu (input.type=%d)\n", n, P->input.type);
+       zend_string *key;
+       zval *val;
 
-       /* init if n==0 */
-       if (!n) {
-               switch (P->input.type) {
-               case PSI_PARSE_FILE:
-                       P->cur = P->tok = P->mrk = P->input.data.file.buffer;
-#if HAVE_MMAP
-                       P->eof = P->input.data.file.buffer + P->input.data.file.length;
-                       P->lim = P->eof;
-#else
-                       P->eof = NULL;
-                       P->lim = P->input.data.file.buffer;
-#endif
-                       break;
+       ZEND_HASH_FOREACH_STR_KEY_VAL(&P->cpp.defs, key, val)
+       {
+               struct psi_impl_def_val *iv;
+               struct psi_const_type *ct;
+               struct psi_const *c;
+               const char *ctn;
+               token_t ctt;
+               impl_val tmp;
+               zend_string *str;
 
-               case PSI_PARSE_STRING:
-                       P->cur = P->tok = P->mrk = P->input.data.string.buffer;
-                       P->eof = P->input.data.string.buffer + P->input.data.string.length;
-                       P->lim = P->eof;
+               ZVAL_DEREF(val);
+               switch (Z_TYPE_P(val)) {
+               case IS_TRUE:
+               case IS_FALSE:
+                       ctt = PSI_T_BOOL;
+                       ctn = "bool";
+                       tmp.zend.bval = Z_TYPE_P(val) == IS_TRUE;
+                       break;
+               case IS_LONG:
+                       ctt = PSI_T_INT;
+                       ctn = "int";
+                       tmp.zend.lval = Z_LVAL_P(val);
+                       break;
+               case IS_DOUBLE:
+                       ctt = PSI_T_FLOAT;
+                       ctn = "float";
+                       tmp.dval = Z_DVAL_P(val);
+                       break;
+               default:
+                       ctt = PSI_T_STRING;
+                       ctn = "string";
+                       str = zval_get_string(val);
+                       tmp.zend.str = zend_string_dup(str, 1);
+                       zend_string_release(str);
                        break;
                }
 
-               PSI_DEBUG_PRINT(P, "PSI< Fill: cur=%p lim=%p eof=%p\n", P->cur, P->lim, P->eof);
+               iv = psi_impl_def_val_init(ctt, NULL);
+               iv->ival = tmp;
+               ct = psi_const_type_init(ctt, ctn);
+               c = psi_const_init(ct, key->val, iv);
+               if (!P->consts) {
+                       P->consts = psi_plist_init((psi_plist_dtor) psi_const_free);
+               }
+               P->consts = psi_plist_add(P->consts, &c);
        }
+       ZEND_HASH_FOREACH_END();
+}
+#endif
 
-       switch (P->input.type) {
-       case PSI_PARSE_STRING:
-               break;
+void psi_parser_parse(struct psi_parser *P)
+{
+       size_t i = 0;
+       struct psi_token *T;
 
-       case PSI_PARSE_FILE:
-#if !HAVE_MMAP
-               if (!P->eof) {
-                       size_t consumed = P->tok - P->buf;
-                       size_t reserved = P->lim - P->tok;
-                       size_t available = BSIZE - reserved;
-                       size_t didread;
+       P->cpp.tokens = psi_parser_scan(P);
 
-                       if (consumed) {
-                               memmove(P->buf, P->tok, reserved);
-                               P->tok -= consumed;
-                               P->cur -= consumed;
-                               P->lim -= consumed;
-                               P->mrk -= consumed;
-                       }
+       psi_cpp_preprocess(P, &P->cpp);
 
-                       didread = fread(P->lim, 1, available, P->fp);
-                       P->lim += didread;
-                       if (didread < available) {
-                               P->eof = P->lim;
+       if (psi_plist_count(P->cpp.tokens)) {
+               while (psi_plist_get(P->cpp.tokens, i++, &T)) {
+                       if (P->flags & PSI_DEBUG) {
+                               fprintf(stderr, "PSI> ");
+                               psi_token_dump(2, T);
                        }
-                       PSI_DEBUG_PRINT(P, "PSI< Fill: consumed=%zu reserved=%zu available=%zu didread=%zu\n",
-                                       consumed, reserved, available, didread);
+                       psi_parser_proc_parse(P->proc, T->type, T, P);
                }
-#endif
-               break;
-       }
-
-       PSI_DEBUG_PRINT(P, "PSI< Fill: avail=%td\n", P->lim - P->cur);
-
-       return P->lim - P->cur;
-}
-
-void psi_parser_parse(struct psi_parser *P, struct psi_token *T)
-{
-       if (T) {
-               psi_parser_proc_parse(P->proc, T->type, T, P);
-       } else {
                psi_parser_proc_parse(P->proc, 0, NULL, P);
        }
+
+       psi_plist_free(P->cpp.tokens);
+       P->cpp.tokens = NULL;
 }
 
 void psi_parser_dtor(struct psi_parser *P)
 {
        psi_parser_proc_free(&P->proc);
 
-       switch (P->input.type) {
-       case PSI_PARSE_FILE:
-               if (P->input.data.file.buffer) {
-#if HAVE_MMAP
-                       munmap(P->input.data.file.buffer, P->input.data.file.length);
-#else
-                       free(P->input.data.file.buffer);
-#endif
-               }
-               if (P->input.data.file.handle) {
-                       fclose(P->input.data.file.handle);
-               }
-               break;
-
-       case PSI_PARSE_STRING:
-               if (P->input.data.string.buffer) {
-                       free(P->input.data.string.buffer);
-               }
-               break;
+       if (P->input.buffer) {
+               free(P->input.buffer);
+               P->input.buffer = NULL;
        }
 
        psi_data_dtor(PSI_DATA(P));
 
+       zend_hash_destroy(&P->cpp.defs);
+
        memset(P, 0, sizeof(*P));
 }
 
@@ -224,42 +262,42 @@ void psi_parser_free(struct psi_parser **P)
        }
 }
 
-#define YYMAXFILL 12
-#if BSIZE < YYMAXFILL
-# error BSIZE must be greater than YYMAXFILL
-#endif
+#define NEWLINE() \
+       P->col = 1; \
+       ++P->line
 
-#define RETURN(t) do { \
+#define NEWTOKEN(t) \
        P->num = t; \
-       PSI_DEBUG_PRINT(P, "PSI< TOKEN: %d %.*s (EOF=%d %s:%u:%u)\n", \
-                               P->num, (int) (P->cur-P->tok), P->tok, P->num == PSI_T_EOF, \
-                               P->file.fn, P->line, P->col); \
-       return t; \
-} while(1)
-
-#define ADDCOLS \
-       P->col += P->cur - P->tok
+       token = psi_token_alloc(P); \
+       tokens = psi_plist_add(tokens, &token); \
+       P->col += P->cur - P->tok; \
+       if (P->flags & PSI_DEBUG) { \
+               fprintf(stderr, "PSI< "); \
+               psi_token_dump(2, token); \
+       } \
+       token = NULL
 
-#define NEWLINE(label) \
-       P->col = 1; \
-       ++P->line; \
-       goto label
 
-token_t psi_parser_scan(struct psi_parser *P)
+struct psi_plist *psi_parser_scan(struct psi_parser *P)
 {
+       struct psi_plist *tokens;
+       struct psi_token *token;
+
        if (!P->cur) {
-               psi_parser_fill(P, 0);
+               return NULL;
        }
-       for (;;) {
-               ADDCOLS;
-       nextline:
+
+       tokens = psi_plist_init(NULL);
+
+       start: ;
                P->tok = P->cur;
+
                
-#line 259 "src/parser.c"
+#line 297 "src/parser.c"
                {
                        unsigned char yych;
                        unsigned int yyaccept = 0;
-                       if ((P->lim - P->cur) < 12) { if (!psi_parser_fill(P,12)) RETURN(PSI_T_EOF); };
+                       if ((P->lim - P->cur) < 12) if (P->cur >= P->lim) goto done;;
                        yych = *P->cur;
                        switch (yych) {
                        case '\t':
@@ -269,17 +307,17 @@ token_t psi_parser_scan(struct psi_parser *P)
                        case '!':       goto yy9;
                        case '"':       goto yy11;
                        case '#':       goto yy12;
-                       case '$':       goto yy13;
-                       case '%':       goto yy14;
-                       case '&':       goto yy16;
-                       case '(':       goto yy18;
-                       case ')':       goto yy20;
-                       case '*':       goto yy22;
-                       case '+':       goto yy24;
-                       case ',':       goto yy26;
-                       case '-':       goto yy28;
-                       case '.':       goto yy30;
-                       case '/':       goto yy31;
+                       case '$':       goto yy14;
+                       case '%':       goto yy15;
+                       case '&':       goto yy17;
+                       case '(':       goto yy19;
+                       case ')':       goto yy21;
+                       case '*':       goto yy23;
+                       case '+':       goto yy25;
+                       case ',':       goto yy27;
+                       case '-':       goto yy29;
+                       case '.':       goto yy31;
+                       case '/':       goto yy32;
                        case '0':
                        case '1':
                        case '2':
@@ -289,30 +327,29 @@ token_t psi_parser_scan(struct psi_parser *P)
                        case '6':
                        case '7':
                        case '8':
-                       case '9':       goto yy33;
-                       case ':':       goto yy36;
-                       case ';':       goto yy38;
-                       case '<':       goto yy40;
-                       case '=':       goto yy42;
-                       case '>':       goto yy44;
+                       case '9':       goto yy34;
+                       case ':':       goto yy37;
+                       case ';':       goto yy39;
+                       case '<':       goto yy41;
+                       case '=':       goto yy43;
+                       case '>':       goto yy45;
                        case 'A':
-                       case 'a':       goto yy46;
+                       case 'a':       goto yy47;
                        case 'B':
-                       case 'b':       goto yy48;
+                       case 'b':       goto yy49;
                        case 'C':
-                       case 'c':       goto yy49;
+                       case 'c':       goto yy50;
                        case 'D':
-                       case 'd':       goto yy50;
+                       case 'd':       goto yy51;
                        case 'E':
-                       case 'e':       goto yy51;
+                       case 'e':       goto yy52;
                        case 'F':
-                       case 'f':       goto yy52;
+                       case 'f':       goto yy53;
                        case 'G':
                        case 'H':
                        case 'J':
                        case 'K':
                        case 'Q':
-                       case 'W':
                        case 'X':
                        case 'Y':
                        case '_':
@@ -321,52 +358,53 @@ token_t psi_parser_scan(struct psi_parser *P)
                        case 'j':
                        case 'k':
                        case 'q':
-                       case 'w':
                        case 'x':
-                       case 'y':       goto yy53;
+                       case 'y':       goto yy54;
                        case 'I':
-                       case 'i':       goto yy55;
+                       case 'i':       goto yy56;
                        case 'L':
-                       case 'l':       goto yy56;
+                       case 'l':       goto yy57;
                        case 'M':
-                       case 'm':       goto yy57;
+                       case 'm':       goto yy58;
                        case 'N':
-                       case 'n':       goto yy58;
+                       case 'n':       goto yy59;
                        case 'O':
-                       case 'o':       goto yy59;
+                       case 'o':       goto yy60;
                        case 'P':
-                       case 'p':       goto yy60;
+                       case 'p':       goto yy61;
                        case 'R':
-                       case 'r':       goto yy61;
+                       case 'r':       goto yy62;
                        case 'S':
-                       case 's':       goto yy62;
+                       case 's':       goto yy63;
                        case 'T':
-                       case 't':       goto yy63;
+                       case 't':       goto yy64;
                        case 'U':
-                       case 'u':       goto yy64;
+                       case 'u':       goto yy65;
                        case 'V':
-                       case 'v':       goto yy65;
+                       case 'v':       goto yy66;
+                       case 'W':
+                       case 'w':       goto yy67;
                        case 'Z':
-                       case 'z':       goto yy66;
-                       case '[':       goto yy67;
-                       case '\\':      goto yy69;
-                       case ']':       goto yy70;
-                       case '^':       goto yy72;
-                       case '{':       goto yy74;
-                       case '|':       goto yy76;
-                       case '}':       goto yy78;
-                       case '~':       goto yy80;
+                       case 'z':       goto yy68;
+                       case '[':       goto yy69;
+                       case '\\':      goto yy71;
+                       case ']':       goto yy73;
+                       case '^':       goto yy75;
+                       case '{':       goto yy77;
+                       case '|':       goto yy79;
+                       case '}':       goto yy81;
+                       case '~':       goto yy83;
                        default:        goto yy2;
                        }
 yy2:
                        ++P->cur;
 yy3:
-#line 371 "src/parser.re"
-                       {break;}
-#line 367 "src/parser.c"
+#line 426 "src/parser.re"
+                       { goto error; }
+#line 405 "src/parser.c"
 yy4:
                        ++P->cur;
-                       if (P->lim <= P->cur) { if (!psi_parser_fill(P,1)) RETURN(PSI_T_EOF); };
+                       if (P->lim <= P->cur) if (P->cur >= P->lim) goto done;;
                        yych = *P->cur;
                        switch (yych) {
                        case '\t':
@@ -374,36 +412,37 @@ yy4:
                        default:        goto yy6;
                        }
 yy6:
-#line 306 "src/parser.re"
-                       { continue; }
-#line 380 "src/parser.c"
+#line 425 "src/parser.re"
+                       { NEWTOKEN(PSI_T_WHITESPACE); goto start; }
+#line 418 "src/parser.c"
 yy7:
                        ++P->cur;
-#line 305 "src/parser.re"
-                       { NEWLINE(nextline); }
-#line 385 "src/parser.c"
+#line 424 "src/parser.re"
+                       { NEWTOKEN(PSI_T_EOL); NEWLINE(); goto start; }
+#line 423 "src/parser.c"
 yy9:
                        ++P->cur;
                        switch ((yych = *P->cur)) {
-                       case '=':       goto yy82;
+                       case '=':       goto yy85;
                        default:        goto yy10;
                        }
 yy10:
-#line 290 "src/parser.re"
-                       {RETURN(PSI_T_NOT);}
-#line 395 "src/parser.c"
+#line 333 "src/parser.re"
+                       { NEWTOKEN(PSI_T_NOT); goto start; }
+#line 433 "src/parser.c"
 yy11:
                        yyaccept = 0;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '"':       goto yy3;
-                       default:        goto yy84;
+                       default:        goto yy87;
                        }
 yy12:
-                       yyaccept = 0;
-                       yych = *(P->mrk = ++P->cur);
-                       goto yy87;
-yy13:
+                       ++P->cur;
+#line 316 "src/parser.re"
+                       { NEWTOKEN(PSI_T_HASH); goto start; }
+#line 445 "src/parser.c"
+yy14:
                        yych = *++P->cur;
                        switch (yych) {
                        case '0':
@@ -468,44 +507,44 @@ yy13:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy90;
+                       case 'z':       goto yy89;
                        default:        goto yy3;
                        }
-yy14:
+yy15:
                        ++P->cur;
-#line 291 "src/parser.re"
-                       {RETURN(PSI_T_MODULO);}
-#line 479 "src/parser.c"
-yy16:
+#line 334 "src/parser.re"
+                       { NEWTOKEN(PSI_T_MODULO); goto start; }
+#line 518 "src/parser.c"
+yy17:
                        ++P->cur;
                        switch ((yych = *P->cur)) {
-                       case '&':       goto yy93;
-                       default:        goto yy17;
+                       case '&':       goto yy92;
+                       default:        goto yy18;
                        }
-yy17:
-#line 292 "src/parser.re"
-                       {RETURN(PSI_T_AMPERSAND);}
-#line 489 "src/parser.c"
 yy18:
+#line 335 "src/parser.re"
+                       { NEWTOKEN(PSI_T_AMPERSAND); goto start; }
+#line 528 "src/parser.c"
+yy19:
                        ++P->cur;
-#line 274 "src/parser.re"
-                       {RETURN(PSI_T_LPAREN);}
-#line 494 "src/parser.c"
-yy20:
+#line 317 "src/parser.re"
+                       { NEWTOKEN(PSI_T_LPAREN); goto start; }
+#line 533 "src/parser.c"
+yy21:
                        ++P->cur;
-#line 275 "src/parser.re"
-                       {RETURN(PSI_T_RPAREN);}
-#line 499 "src/parser.c"
-yy22:
+#line 318 "src/parser.re"
+                       { NEWTOKEN(PSI_T_RPAREN); goto start; }
+#line 538 "src/parser.c"
+yy23:
                        ++P->cur;
-#line 288 "src/parser.re"
-                       {RETURN(PSI_T_ASTERISK);}
-#line 504 "src/parser.c"
-yy24:
+#line 331 "src/parser.re"
+                       { NEWTOKEN(PSI_T_ASTERISK); goto start; }
+#line 543 "src/parser.c"
+yy25:
                        yyaccept = 1;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
-                       case '.':       goto yy95;
+                       case '.':       goto yy94;
                        case '0':
                        case '1':
                        case '2':
@@ -515,23 +554,23 @@ yy24:
                        case '6':
                        case '7':
                        case '8':
-                       case '9':       goto yy33;
-                       default:        goto yy25;
+                       case '9':       goto yy34;
+                       default:        goto yy26;
                        }
-yy25:
-#line 293 "src/parser.re"
-                       {RETURN(PSI_T_PLUS);}
-#line 525 "src/parser.c"
 yy26:
+#line 336 "src/parser.re"
+                       { NEWTOKEN(PSI_T_PLUS); goto start; }
+#line 564 "src/parser.c"
+yy27:
                        ++P->cur;
-#line 277 "src/parser.re"
-                       {RETURN(PSI_T_COMMA);}
-#line 530 "src/parser.c"
-yy28:
+#line 320 "src/parser.re"
+                       { NEWTOKEN(PSI_T_COMMA); goto start; }
+#line 569 "src/parser.c"
+yy29:
                        yyaccept = 2;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
-                       case '.':       goto yy95;
+                       case '.':       goto yy94;
                        case '0':
                        case '1':
                        case '2':
@@ -541,18 +580,18 @@ yy28:
                        case '6':
                        case '7':
                        case '8':
-                       case '9':       goto yy33;
-                       default:        goto yy29;
+                       case '9':       goto yy34;
+                       default:        goto yy30;
                        }
-yy29:
-#line 294 "src/parser.re"
-                       {RETURN(PSI_T_MINUS);}
-#line 551 "src/parser.c"
 yy30:
+#line 337 "src/parser.re"
+                       { NEWTOKEN(PSI_T_MINUS); goto start; }
+#line 590 "src/parser.c"
+yy31:
                        yyaccept = 0;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
-                       case '.':       goto yy97;
+                       case '.':       goto yy96;
                        case '0':
                        case '1':
                        case '2':
@@ -562,28 +601,27 @@ yy30:
                        case '6':
                        case '7':
                        case '8':
-                       case '9':       goto yy98;
+                       case '9':       goto yy97;
                        default:        goto yy3;
                        }
-yy31:
-                       yyaccept = 3;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case '*':       goto yy100;
-                       case '/':       goto yy86;
-                       default:        goto yy32;
-                       }
 yy32:
-#line 295 "src/parser.re"
-                       {RETURN(PSI_T_SLASH);}
-#line 580 "src/parser.c"
+                       ++P->cur;
+                       switch ((yych = *P->cur)) {
+                       case '*':       goto yy99;
+                       case '/':       goto yy101;
+                       default:        goto yy33;
+                       }
 yy33:
-                       yyaccept = 4;
+#line 338 "src/parser.re"
+                       { NEWTOKEN(PSI_T_SLASH); goto start; }
+#line 618 "src/parser.c"
+yy34:
+                       yyaccept = 3;
                        P->mrk = ++P->cur;
-                       if ((P->lim - P->cur) < 3) { if (!psi_parser_fill(P,3)) RETURN(PSI_T_EOF); };
+                       if ((P->lim - P->cur) < 3) if (P->cur >= P->lim) goto done;;
                        yych = *P->cur;
                        switch (yych) {
-                       case '.':       goto yy95;
+                       case '.':       goto yy94;
                        case '0':
                        case '1':
                        case '2':
@@ -593,125 +631,131 @@ yy33:
                        case '6':
                        case '7':
                        case '8':
-                       case '9':       goto yy33;
+                       case '9':       goto yy34;
                        case 'E':
-                       case 'e':       goto yy102;
-                       default:        goto yy35;
+                       case 'e':       goto yy103;
+                       default:        goto yy36;
                        }
-yy35:
-#line 366 "src/parser.re"
-                       {RETURN(PSI_T_NUMBER);}
-#line 605 "src/parser.c"
 yy36:
+#line 419 "src/parser.re"
+                       { NEWTOKEN(PSI_T_NUMBER); goto start; }
+#line 643 "src/parser.c"
+yy37:
                        ++P->cur;
-#line 278 "src/parser.re"
-                       {RETURN(PSI_T_COLON);}
-#line 610 "src/parser.c"
-yy38:
+#line 321 "src/parser.re"
+                       { NEWTOKEN(PSI_T_COLON); goto start; }
+#line 648 "src/parser.c"
+yy39:
                        ++P->cur;
-#line 276 "src/parser.re"
-                       {RETURN(PSI_T_EOS);}
-#line 615 "src/parser.c"
-yy40:
+#line 319 "src/parser.re"
+                       { NEWTOKEN(PSI_T_EOS); goto start; }
+#line 653 "src/parser.c"
+yy41:
                        ++P->cur;
                        switch ((yych = *P->cur)) {
-                       case '<':       goto yy103;
-                       case '=':       goto yy105;
-                       default:        goto yy41;
+                       case '<':       goto yy104;
+                       case '=':       goto yy106;
+                       default:        goto yy42;
                        }
-yy41:
-#line 302 "src/parser.re"
-                       {RETURN(PSI_T_LCHEVR);}
-#line 626 "src/parser.c"
 yy42:
+#line 346 "src/parser.re"
+                       { NEWTOKEN(PSI_T_LCHEVR); goto start; }
+#line 664 "src/parser.c"
+yy43:
                        ++P->cur;
                        switch ((yych = *P->cur)) {
-                       case '=':       goto yy107;
-                       default:        goto yy43;
+                       case '=':       goto yy108;
+                       default:        goto yy44;
                        }
-yy43:
-#line 287 "src/parser.re"
-                       {RETURN(PSI_T_EQUALS);}
-#line 636 "src/parser.c"
 yy44:
+#line 330 "src/parser.re"
+                       { NEWTOKEN(PSI_T_EQUALS); goto start; }
+#line 674 "src/parser.c"
+yy45:
                        ++P->cur;
                        switch ((yych = *P->cur)) {
-                       case '=':       goto yy109;
-                       case '>':       goto yy111;
-                       default:        goto yy45;
+                       case '=':       goto yy110;
+                       case '>':       goto yy112;
+                       default:        goto yy46;
                        }
-yy45:
-#line 303 "src/parser.re"
-                       {RETURN(PSI_T_RCHEVR);}
-#line 647 "src/parser.c"
 yy46:
-                       yyaccept = 5;
+#line 347 "src/parser.re"
+                       { NEWTOKEN(PSI_T_RCHEVR); goto start; }
+#line 685 "src/parser.c"
+yy47:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'R':
-                       case 'r':       goto yy113;
-                       default:        goto yy54;
+                       case 'r':       goto yy114;
+                       default:        goto yy55;
                        }
-yy47:
-#line 367 "src/parser.re"
-                       {RETURN(PSI_T_NAME);}
-#line 659 "src/parser.c"
 yy48:
-                       yyaccept = 5;
+#line 420 "src/parser.re"
+                       { NEWTOKEN(PSI_T_NAME); goto start; }
+#line 697 "src/parser.c"
+yy49:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'O':
-                       case 'o':       goto yy115;
-                       default:        goto yy54;
+                       case 'o':       goto yy116;
+                       default:        goto yy55;
                        }
-yy49:
-                       yyaccept = 5;
+yy50:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'A':
-                       case 'a':       goto yy116;
+                       case 'a':       goto yy117;
                        case 'H':
-                       case 'h':       goto yy117;
+                       case 'h':       goto yy118;
                        case 'O':
-                       case 'o':       goto yy118;
-                       default:        goto yy54;
+                       case 'o':       goto yy119;
+                       default:        goto yy55;
                        }
-yy50:
-                       yyaccept = 5;
+yy51:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
+                       case 'E':
+                       case 'e':       goto yy120;
                        case 'O':
-                       case 'o':       goto yy119;
-                       default:        goto yy54;
+                       case 'o':       goto yy121;
+                       default:        goto yy55;
                        }
-yy51:
-                       yyaccept = 5;
+yy52:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
+                       case 'L':
+                       case 'l':       goto yy122;
                        case 'N':
-                       case 'n':       goto yy120;
-                       default:        goto yy54;
+                       case 'n':       goto yy123;
+                       case 'R':
+                       case 'r':       goto yy124;
+                       default:        goto yy55;
                        }
-yy52:
-                       yyaccept = 5;
+yy53:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'A':
-                       case 'a':       goto yy121;
+                       case 'a':       goto yy125;
                        case 'L':
-                       case 'l':       goto yy122;
+                       case 'l':       goto yy126;
                        case 'R':
-                       case 'r':       goto yy123;
+                       case 'r':       goto yy127;
                        case 'U':
-                       case 'u':       goto yy124;
-                       default:        goto yy54;
+                       case 'u':       goto yy128;
+                       default:        goto yy55;
                        }
-yy53:
-                       yyaccept = 5;
+yy54:
+                       yyaccept = 4;
                        P->mrk = ++P->cur;
-                       if (P->lim <= P->cur) { if (!psi_parser_fill(P,1)) RETURN(PSI_T_EOF); };
+                       if (P->lim <= P->cur) if (P->cur >= P->lim) goto done;;
                        yych = *P->cur;
-yy54:
+yy55:
                        switch (yych) {
                        case '0':
                        case '1':
@@ -775,136 +819,146 @@ yy54:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy47;
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy48;
                        }
-yy55:
-                       yyaccept = 5;
+yy56:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
+                       case 'F':
+                       case 'f':       goto yy129;
                        case 'N':
-                       case 'n':       goto yy125;
-                       default:        goto yy54;
+                       case 'n':       goto yy131;
+                       default:        goto yy55;
                        }
-yy56:
-                       yyaccept = 5;
+yy57:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'E':
-                       case 'e':       goto yy126;
+                       case 'e':       goto yy132;
                        case 'I':
-                       case 'i':       goto yy127;
+                       case 'i':       goto yy133;
                        case 'O':
-                       case 'o':       goto yy128;
-                       default:        goto yy54;
+                       case 'o':       goto yy134;
+                       default:        goto yy55;
                        }
-yy57:
-                       yyaccept = 5;
+yy58:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'I':
-                       case 'i':       goto yy129;
-                       default:        goto yy54;
+                       case 'i':       goto yy135;
+                       default:        goto yy55;
                        }
-yy58:
-                       yyaccept = 5;
+yy59:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'U':
-                       case 'u':       goto yy130;
-                       default:        goto yy54;
+                       case 'u':       goto yy136;
+                       default:        goto yy55;
                        }
-yy59:
-                       yyaccept = 5;
+yy60:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'B':
-                       case 'b':       goto yy131;
-                       default:        goto yy54;
+                       case 'b':       goto yy137;
+                       default:        goto yy55;
                        }
-yy60:
-                       yyaccept = 5;
+yy61:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'A':
-                       case 'a':       goto yy132;
+                       case 'a':       goto yy138;
                        case 'O':
-                       case 'o':       goto yy133;
+                       case 'o':       goto yy139;
                        case 'R':
-                       case 'r':       goto yy134;
-                       default:        goto yy54;
+                       case 'r':       goto yy140;
+                       default:        goto yy55;
                        }
-yy61:
-                       yyaccept = 5;
+yy62:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'E':
-                       case 'e':       goto yy135;
-                       default:        goto yy54;
+                       case 'e':       goto yy141;
+                       default:        goto yy55;
                        }
-yy62:
-                       yyaccept = 5;
+yy63:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'E':
-                       case 'e':       goto yy136;
+                       case 'e':       goto yy142;
                        case 'H':
-                       case 'h':       goto yy137;
+                       case 'h':       goto yy143;
                        case 'I':
-                       case 'i':       goto yy138;
+                       case 'i':       goto yy144;
                        case 'T':
-                       case 't':       goto yy139;
-                       default:        goto yy54;
+                       case 't':       goto yy145;
+                       default:        goto yy55;
                        }
-yy63:
-                       yyaccept = 5;
+yy64:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'E':
-                       case 'e':       goto yy140;
+                       case 'e':       goto yy146;
                        case 'O':
-                       case 'o':       goto yy141;
+                       case 'o':       goto yy147;
                        case 'R':
-                       case 'r':       goto yy142;
+                       case 'r':       goto yy148;
                        case 'Y':
-                       case 'y':       goto yy143;
-                       default:        goto yy54;
+                       case 'y':       goto yy149;
+                       default:        goto yy55;
                        }
-yy64:
-                       yyaccept = 5;
+yy65:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'I':
-                       case 'i':       goto yy144;
+                       case 'i':       goto yy150;
                        case 'N':
-                       case 'n':       goto yy145;
-                       default:        goto yy54;
+                       case 'n':       goto yy151;
+                       default:        goto yy55;
                        }
-yy65:
-                       yyaccept = 5;
+yy66:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'O':
-                       case 'o':       goto yy146;
-                       default:        goto yy54;
+                       case 'o':       goto yy152;
+                       default:        goto yy55;
                        }
-yy66:
-                       yyaccept = 5;
+yy67:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'A':
+                       case 'a':       goto yy153;
+                       default:        goto yy55;
+                       }
+yy68:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'V':
-                       case 'v':       goto yy147;
-                       default:        goto yy54;
+                       case 'v':       goto yy154;
+                       default:        goto yy55;
                        }
-yy67:
-                       ++P->cur;
-#line 281 "src/parser.re"
-                       {RETURN(PSI_T_LBRACKET);}
-#line 905 "src/parser.c"
 yy69:
-                       yych = *++P->cur;
-                       switch (yych) {
+                       ++P->cur;
+#line 324 "src/parser.re"
+                       { NEWTOKEN(PSI_T_LBRACKET); goto start; }
+#line 959 "src/parser.c"
+yy71:
+                       ++P->cur;
+                       switch ((yych = *P->cur)) {
                        case 'A':
                        case 'B':
                        case 'C':
@@ -957,74 +1011,64 @@ yy69:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy148;
-                       default:        goto yy3;
+                       case 'z':       goto yy155;
+                       default:        goto yy72;
                        }
-yy70:
-                       ++P->cur;
-#line 282 "src/parser.re"
-                       {RETURN(PSI_T_RBRACKET);}
-#line 968 "src/parser.c"
 yy72:
+#line 339 "src/parser.re"
+                       { NEWTOKEN(PSI_T_BSLASH); goto start; }
+#line 1021 "src/parser.c"
+yy73:
+                       ++P->cur;
+#line 325 "src/parser.re"
+                       { NEWTOKEN(PSI_T_RBRACKET); goto start; }
+#line 1026 "src/parser.c"
+yy75:
                        ++P->cur;
-#line 297 "src/parser.re"
-                       {RETURN(PSI_T_CARET);}
-#line 973 "src/parser.c"
-yy74:
+#line 341 "src/parser.re"
+                       { NEWTOKEN(PSI_T_CARET); goto start; }
+#line 1031 "src/parser.c"
+yy77:
                        ++P->cur;
-#line 279 "src/parser.re"
-                       {RETURN(PSI_T_LBRACE);}
-#line 978 "src/parser.c"
-yy76:
+#line 322 "src/parser.re"
+                       { NEWTOKEN(PSI_T_LBRACE); goto start; }
+#line 1036 "src/parser.c"
+yy79:
                        ++P->cur;
                        switch ((yych = *P->cur)) {
-                       case '|':       goto yy151;
-                       default:        goto yy77;
+                       case '|':       goto yy158;
+                       default:        goto yy80;
                        }
-yy77:
-#line 296 "src/parser.re"
-                       {RETURN(PSI_T_PIPE);}
-#line 988 "src/parser.c"
-yy78:
-                       ++P->cur;
-#line 280 "src/parser.re"
-                       {RETURN(PSI_T_RBRACE);}
-#line 993 "src/parser.c"
 yy80:
+#line 340 "src/parser.re"
+                       { NEWTOKEN(PSI_T_PIPE); goto start; }
+#line 1046 "src/parser.c"
+yy81:
                        ++P->cur;
-#line 289 "src/parser.re"
-                       {RETURN(PSI_T_TILDE);}
-#line 998 "src/parser.c"
-yy82:
+#line 323 "src/parser.re"
+                       { NEWTOKEN(PSI_T_RBRACE); goto start; }
+#line 1051 "src/parser.c"
+yy83:
                        ++P->cur;
-#line 283 "src/parser.re"
-                       {RETURN(PSI_T_CMP_NE);}
-#line 1003 "src/parser.c"
-yy84:
+#line 332 "src/parser.re"
+                       { NEWTOKEN(PSI_T_TILDE); goto start; }
+#line 1056 "src/parser.c"
+yy85:
                        ++P->cur;
-                       if (P->lim <= P->cur) { if (!psi_parser_fill(P,1)) RETURN(PSI_T_EOF); };
-                       yych = *P->cur;
-                       switch (yych) {
-                       case '"':       goto yy153;
-                       default:        goto yy84;
-                       }
-yy86:
+#line 326 "src/parser.re"
+                       { NEWTOKEN(PSI_T_CMP_NE); goto start; }
+#line 1061 "src/parser.c"
+yy87:
                        ++P->cur;
-                       if (P->lim <= P->cur) { if (!psi_parser_fill(P,1)) RETURN(PSI_T_EOF); };
+                       if (P->lim <= P->cur) if (P->cur >= P->lim) goto done;;
                        yych = *P->cur;
-yy87:
                        switch (yych) {
-                       case '\n':      goto yy88;
-                       default:        goto yy86;
+                       case '"':       goto yy160;
+                       default:        goto yy87;
                        }
-yy88:
+yy89:
                        ++P->cur;
-#line 273 "src/parser.re"
-                       { NEWLINE(nextline); }
-#line 1025 "src/parser.c"
-yy90:
-                       ++P->cur;
-                       if (P->lim <= P->cur) { if (!psi_parser_fill(P,1)) RETURN(PSI_T_EOF); };
+                       if (P->lim <= P->cur) if (P->cur >= P->lim) goto done;;
                        yych = *P->cur;
                        switch (yych) {
                        case '0':
@@ -1089,19 +1133,19 @@ yy90:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy90;
-                       default:        goto yy92;
+                       case 'z':       goto yy89;
+                       default:        goto yy91;
                        }
+yy91:
+#line 422 "src/parser.re"
+                       { NEWTOKEN(PSI_T_DOLLAR_NAME); goto start; }
+#line 1143 "src/parser.c"
 yy92:
-#line 369 "src/parser.re"
-                       {RETURN(PSI_T_DOLLAR_NAME);}
-#line 1099 "src/parser.c"
-yy93:
                        ++P->cur;
-#line 285 "src/parser.re"
-                       {RETURN(PSI_T_AND);}
-#line 1104 "src/parser.c"
-yy95:
+#line 328 "src/parser.re"
+                       { NEWTOKEN(PSI_T_AND); goto start; }
+#line 1148 "src/parser.c"
+yy94:
                        yych = *++P->cur;
                        switch (yych) {
                        case '0':
@@ -1113,89 +1157,99 @@ yy95:
                        case '6':
                        case '7':
                        case '8':
-                       case '9':       goto yy98;
-                       default:        goto yy96;
+                       case '9':       goto yy97;
+                       default:        goto yy95;
                        }
-yy96:
+yy95:
                        P->cur = P->mrk;
                        switch (yyaccept) {
                        case 0:         goto yy3;
-                       case 1:         goto yy25;
-                       case 2:         goto yy29;
-                       case 3:         goto yy32;
-                       case 4:         goto yy35;
-                       case 5:         goto yy47;
-                       case 6:         goto yy150;
-                       case 7:         goto yy173;
-                       case 8:         goto yy175;
-                       case 9:         goto yy177;
-                       case 10:        goto yy187;
-                       case 11:        goto yy204;
-                       case 12:        goto yy207;
-                       case 13:        goto yy212;
-                       case 14:        goto yy216;
-                       case 15:        goto yy224;
-                       case 16:        goto yy227;
-                       case 17:        goto yy242;
-                       case 18:        goto yy250;
-                       case 19:        goto yy256;
-                       case 20:        goto yy258;
-                       case 21:        goto yy260;
-                       case 22:        goto yy267;
-                       case 23:        goto yy269;
-                       case 24:        goto yy272;
-                       case 25:        goto yy274;
-                       case 26:        goto yy282;
-                       case 27:        goto yy290;
-                       case 28:        goto yy309;
-                       case 29:        goto yy312;
-                       case 30:        goto yy317;
-                       case 31:        goto yy319;
-                       case 32:        goto yy326;
-                       case 33:        goto yy328;
-                       case 34:        goto yy330;
-                       case 35:        goto yy332;
-                       case 36:        goto yy337;
-                       case 37:        goto yy339;
-                       case 38:        goto yy341;
-                       case 39:        goto yy343;
-                       case 40:        goto yy345;
-                       case 41:        goto yy347;
-                       case 42:        goto yy349;
-                       case 43:        goto yy354;
-                       case 44:        goto yy364;
-                       case 45:        goto yy370;
-                       case 46:        goto yy372;
-                       case 47:        goto yy374;
-                       case 48:        goto yy376;
-                       case 49:        goto yy381;
-                       case 50:        goto yy386;
-                       case 51:        goto yy391;
-                       case 52:        goto yy394;
-                       case 53:        goto yy396;
-                       case 54:        goto yy398;
-                       case 55:        goto yy400;
-                       case 56:        goto yy404;
-                       case 57:        goto yy406;
-                       case 58:        goto yy410;
-                       case 59:        goto yy412;
-                       case 60:        goto yy414;
-                       case 61:        goto yy416;
-                       case 62:        goto yy420;
-                       case 63:        goto yy422;
-                       case 64:        goto yy425;
-                       default:        goto yy427;
+                       case 1:         goto yy26;
+                       case 2:         goto yy30;
+                       case 3:         goto yy36;
+                       case 4:         goto yy48;
+                       case 5:         goto yy130;
+                       case 6:         goto yy157;
+                       case 7:         goto yy187;
+                       case 8:         goto yy189;
+                       case 9:         goto yy191;
+                       case 10:        goto yy201;
+                       case 11:        goto yy220;
+                       case 12:        goto yy223;
+                       case 13:        goto yy229;
+                       case 14:        goto yy231;
+                       case 15:        goto yy234;
+                       case 16:        goto yy239;
+                       case 17:        goto yy249;
+                       case 18:        goto yy252;
+                       case 19:        goto yy267;
+                       case 20:        goto yy275;
+                       case 21:        goto yy282;
+                       case 22:        goto yy285;
+                       case 23:        goto yy287;
+                       case 24:        goto yy294;
+                       case 25:        goto yy296;
+                       case 26:        goto yy300;
+                       case 27:        goto yy302;
+                       case 28:        goto yy304;
+                       case 29:        goto yy306;
+                       case 30:        goto yy309;
+                       case 31:        goto yy317;
+                       case 32:        goto yy325;
+                       case 33:        goto yy344;
+                       case 34:        goto yy346;
+                       case 35:        goto yy350;
+                       case 36:        goto yy355;
+                       case 37:        goto yy357;
+                       case 38:        goto yy359;
+                       case 39:        goto yy363;
+                       case 40:        goto yy368;
+                       case 41:        goto yy370;
+                       case 42:        goto yy372;
+                       case 43:        goto yy374;
+                       case 44:        goto yy379;
+                       case 45:        goto yy381;
+                       case 46:        goto yy383;
+                       case 47:        goto yy385;
+                       case 48:        goto yy387;
+                       case 49:        goto yy389;
+                       case 50:        goto yy391;
+                       case 51:        goto yy396;
+                       case 52:        goto yy407;
+                       case 53:        goto yy411;
+                       case 54:        goto yy415;
+                       case 55:        goto yy417;
+                       case 56:        goto yy419;
+                       case 57:        goto yy421;
+                       case 58:        goto yy426;
+                       case 59:        goto yy431;
+                       case 60:        goto yy436;
+                       case 61:        goto yy439;
+                       case 62:        goto yy441;
+                       case 63:        goto yy443;
+                       case 64:        goto yy445;
+                       case 65:        goto yy447;
+                       case 66:        goto yy451;
+                       case 67:        goto yy453;
+                       case 68:        goto yy457;
+                       case 69:        goto yy459;
+                       case 70:        goto yy461;
+                       case 71:        goto yy463;
+                       case 72:        goto yy467;
+                       case 73:        goto yy469;
+                       case 74:        goto yy472;
+                       default:        goto yy474;
                        }
-yy97:
+yy96:
                        yych = *++P->cur;
                        switch (yych) {
-                       case '.':       goto yy155;
-                       default:        goto yy96;
+                       case '.':       goto yy162;
+                       default:        goto yy95;
                        }
-yy98:
-                       yyaccept = 4;
+yy97:
+                       yyaccept = 3;
                        P->mrk = ++P->cur;
-                       if ((P->lim - P->cur) < 3) { if (!psi_parser_fill(P,3)) RETURN(PSI_T_EOF); };
+                       if ((P->lim - P->cur) < 3) if (P->cur >= P->lim) goto done;;
                        yych = *P->cur;
                        switch (yych) {
                        case '0':
@@ -1207,21 +1261,26 @@ yy98:
                        case '6':
                        case '7':
                        case '8':
-                       case '9':       goto yy98;
+                       case '9':       goto yy97;
                        case 'E':
-                       case 'e':       goto yy102;
-                       default:        goto yy35;
+                       case 'e':       goto yy103;
+                       default:        goto yy36;
                        }
-yy100:
+yy99:
                        ++P->cur;
-#line 272 "src/parser.re"
+#line 314 "src/parser.re"
                        { goto comment; }
-#line 1220 "src/parser.c"
-yy102:
+#line 1274 "src/parser.c"
+yy101:
+                       ++P->cur;
+#line 315 "src/parser.re"
+                       { goto comment_sl; }
+#line 1279 "src/parser.c"
+yy103:
                        yych = *++P->cur;
                        switch (yych) {
                        case '+':
-                       case '-':       goto yy157;
+                       case '-':       goto yy164;
                        case '0':
                        case '1':
                        case '2':
@@ -1231,45 +1290,45 @@ yy102:
                        case '6':
                        case '7':
                        case '8':
-                       case '9':       goto yy158;
-                       default:        goto yy96;
+                       case '9':       goto yy165;
+                       default:        goto yy95;
                        }
-yy103:
+yy104:
                        ++P->cur;
-#line 298 "src/parser.re"
-                       {RETURN(PSI_T_LSHIFT);}
-#line 1242 "src/parser.c"
-yy105:
+#line 342 "src/parser.re"
+                       { NEWTOKEN(PSI_T_LSHIFT); goto start; }
+#line 1301 "src/parser.c"
+yy106:
                        ++P->cur;
-#line 300 "src/parser.re"
-                       {RETURN(PSI_T_CMP_LE);}
-#line 1247 "src/parser.c"
-yy107:
+#line 344 "src/parser.re"
+                       { NEWTOKEN(PSI_T_CMP_LE); goto start; }
+#line 1306 "src/parser.c"
+yy108:
                        ++P->cur;
-#line 284 "src/parser.re"
-                       {RETURN(PSI_T_CMP_EQ);}
-#line 1252 "src/parser.c"
-yy109:
+#line 327 "src/parser.re"
+                       { NEWTOKEN(PSI_T_CMP_EQ); goto start; }
+#line 1311 "src/parser.c"
+yy110:
                        ++P->cur;
-#line 301 "src/parser.re"
-                       {RETURN(PSI_T_CMP_GE);}
-#line 1257 "src/parser.c"
-yy111:
+#line 345 "src/parser.re"
+                       { NEWTOKEN(PSI_T_CMP_GE); goto start; }
+#line 1316 "src/parser.c"
+yy112:
                        ++P->cur;
-#line 299 "src/parser.re"
-                       {RETURN(PSI_T_RSHIFT);}
-#line 1262 "src/parser.c"
-yy113:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
+#line 343 "src/parser.re"
+                       { NEWTOKEN(PSI_T_RSHIFT); goto start; }
+#line 1321 "src/parser.c"
+yy114:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'R':
-                       case 'r':       goto yy160;
-                       default:        goto yy54;
+                       case 'r':       goto yy167;
+                       default:        goto yy55;
                        }
-yy114:
+yy115:
                        ++P->cur;
-                       if (P->lim <= P->cur) { if (!psi_parser_fill(P,1)) RETURN(PSI_T_EOF); };
+                       if (P->lim <= P->cur) if (P->cur >= P->lim) goto done;;
                        yych = *P->cur;
                        switch (yych) {
                        case 'A':
@@ -1324,282 +1383,394 @@ yy114:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy148;
-                       default:        goto yy96;
+                       case 'z':       goto yy155;
+                       default:        goto yy95;
                        }
-yy115:
-                       yyaccept = 5;
+yy116:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'O':
-                       case 'o':       goto yy161;
-                       default:        goto yy54;
+                       case 'o':       goto yy168;
+                       default:        goto yy55;
                        }
-yy116:
-                       yyaccept = 5;
+yy117:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'L':
-                       case 'l':       goto yy162;
-                       default:        goto yy54;
+                       case 'l':       goto yy169;
+                       default:        goto yy55;
                        }
-yy117:
-                       yyaccept = 5;
+yy118:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'A':
-                       case 'a':       goto yy163;
-                       default:        goto yy54;
+                       case 'a':       goto yy170;
+                       default:        goto yy55;
                        }
-yy118:
-                       yyaccept = 5;
+yy119:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'N':
-                       case 'n':       goto yy164;
+                       case 'n':       goto yy171;
                        case 'U':
-                       case 'u':       goto yy165;
-                       default:        goto yy54;
+                       case 'u':       goto yy172;
+                       default:        goto yy55;
                        }
-yy119:
-                       yyaccept = 5;
+yy120:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'F':
+                       case 'f':       goto yy173;
+                       default:        goto yy55;
+                       }
+yy121:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'U':
-                       case 'u':       goto yy166;
-                       default:        goto yy54;
+                       case 'u':       goto yy174;
+                       default:        goto yy55;
                        }
-yy120:
-                       yyaccept = 5;
+yy122:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'I':
+                       case 'i':       goto yy175;
+                       case 'S':
+                       case 's':       goto yy176;
+                       default:        goto yy55;
+                       }
+yy123:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
+                       case 'D':
+                       case 'd':       goto yy177;
                        case 'U':
-                       case 'u':       goto yy167;
-                       default:        goto yy54;
+                       case 'u':       goto yy178;
+                       default:        goto yy55;
                        }
-yy121:
-                       yyaccept = 5;
+yy124:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'R':
+                       case 'r':       goto yy179;
+                       default:        goto yy55;
+                       }
+yy125:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'L':
-                       case 'l':       goto yy168;
-                       default:        goto yy54;
+                       case 'l':       goto yy180;
+                       default:        goto yy55;
                        }
-yy122:
-                       yyaccept = 5;
+yy126:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'O':
-                       case 'o':       goto yy169;
-                       default:        goto yy54;
+                       case 'o':       goto yy181;
+                       default:        goto yy55;
                        }
-yy123:
-                       yyaccept = 5;
+yy127:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'E':
-                       case 'e':       goto yy170;
-                       default:        goto yy54;
+                       case 'e':       goto yy182;
+                       default:        goto yy55;
                        }
-yy124:
-                       yyaccept = 5;
+yy128:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'N':
-                       case 'n':       goto yy171;
-                       default:        goto yy54;
+                       case 'n':       goto yy183;
+                       default:        goto yy55;
                        }
-yy125:
+yy129:
                        yyaccept = 5;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
+                       case '0':
+                       case '1':
+                       case '2':
+                       case '3':
+                       case '4':
+                       case '5':
+                       case '6':
+                       case '7':
+                       case '8':
+                       case '9':
+                       case 'A':
+                       case 'B':
+                       case 'C':
+                       case 'E':
+                       case 'F':
+                       case 'G':
+                       case 'H':
+                       case 'I':
+                       case 'J':
+                       case 'K':
+                       case 'L':
+                       case 'M':
+                       case 'O':
+                       case 'P':
+                       case 'Q':
+                       case 'R':
+                       case 'S':
+                       case 'T':
+                       case 'U':
+                       case 'V':
+                       case 'W':
+                       case 'X':
+                       case 'Y':
+                       case 'Z':
+                       case '_':
+                       case 'a':
+                       case 'b':
+                       case 'c':
+                       case 'e':
+                       case 'f':
+                       case 'g':
+                       case 'h':
+                       case 'i':
+                       case 'j':
+                       case 'k':
+                       case 'l':
+                       case 'm':
+                       case 'o':
+                       case 'p':
+                       case 'q':
+                       case 'r':
+                       case 's':
+                       case 't':
+                       case 'u':
+                       case 'v':
+                       case 'w':
+                       case 'x':
+                       case 'y':
+                       case 'z':       goto yy54;
+                       case 'D':
+                       case 'd':       goto yy184;
+                       case 'N':
+                       case 'n':       goto yy185;
+                       case '\\':      goto yy115;
+                       default:        goto yy130;
+                       }
+yy130:
+#line 349 "src/parser.re"
+                       { NEWTOKEN(PSI_T_IF); goto start; }
+#line 1573 "src/parser.c"
+yy131:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
                        case 'T':
-                       case 't':       goto yy172;
-                       default:        goto yy54;
+                       case 't':       goto yy186;
+                       default:        goto yy55;
                        }
-yy126:
-                       yyaccept = 5;
+yy132:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'T':
-                       case 't':       goto yy174;
-                       default:        goto yy54;
+                       case 't':       goto yy188;
+                       default:        goto yy55;
                        }
-yy127:
-                       yyaccept = 5;
+yy133:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'B':
-                       case 'b':       goto yy176;
-                       default:        goto yy54;
+                       case 'b':       goto yy190;
+                       default:        goto yy55;
                        }
-yy128:
-                       yyaccept = 5;
+yy134:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'N':
-                       case 'n':       goto yy178;
-                       default:        goto yy54;
+                       case 'n':       goto yy192;
+                       default:        goto yy55;
                        }
-yy129:
-                       yyaccept = 5;
+yy135:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'X':
-                       case 'x':       goto yy179;
-                       default:        goto yy54;
+                       case 'x':       goto yy193;
+                       default:        goto yy55;
                        }
-yy130:
-                       yyaccept = 5;
+yy136:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'L':
-                       case 'l':       goto yy180;
-                       default:        goto yy54;
+                       case 'l':       goto yy194;
+                       default:        goto yy55;
                        }
-yy131:
-                       yyaccept = 5;
+yy137:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'J':
-                       case 'j':       goto yy181;
-                       default:        goto yy54;
+                       case 'j':       goto yy195;
+                       default:        goto yy55;
                        }
-yy132:
-                       yyaccept = 5;
+yy138:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'T':
-                       case 't':       goto yy182;
-                       default:        goto yy54;
+                       case 't':       goto yy196;
+                       default:        goto yy55;
                        }
-yy133:
-                       yyaccept = 5;
+yy139:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'S':
-                       case 's':       goto yy183;
-                       default:        goto yy54;
+                       case 's':       goto yy197;
+                       default:        goto yy55;
                        }
-yy134:
-                       yyaccept = 5;
+yy140:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'E':
-                       case 'e':       goto yy184;
-                       default:        goto yy54;
+                       case 'e':       goto yy198;
+                       default:        goto yy55;
                        }
-yy135:
-                       yyaccept = 5;
+yy141:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'T':
-                       case 't':       goto yy185;
-                       default:        goto yy54;
+                       case 't':       goto yy199;
+                       default:        goto yy55;
                        }
-yy136:
-                       yyaccept = 5;
+yy142:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'T':
-                       case 't':       goto yy186;
-                       default:        goto yy54;
+                       case 't':       goto yy200;
+                       default:        goto yy55;
                        }
-yy137:
-                       yyaccept = 5;
+yy143:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'O':
-                       case 'o':       goto yy188;
-                       default:        goto yy54;
+                       case 'o':       goto yy202;
+                       default:        goto yy55;
                        }
-yy138:
-                       yyaccept = 5;
+yy144:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'G':
-                       case 'g':       goto yy189;
-                       default:        goto yy54;
+                       case 'g':       goto yy203;
+                       default:        goto yy55;
                        }
-yy139:
-                       yyaccept = 5;
+yy145:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'A':
-                       case 'a':       goto yy190;
+                       case 'a':       goto yy204;
                        case 'R':
-                       case 'r':       goto yy191;
-                       default:        goto yy54;
+                       case 'r':       goto yy205;
+                       default:        goto yy55;
                        }
-yy140:
-                       yyaccept = 5;
+yy146:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'M':
-                       case 'm':       goto yy192;
-                       default:        goto yy54;
+                       case 'm':       goto yy206;
+                       default:        goto yy55;
                        }
-yy141:
-                       yyaccept = 5;
+yy147:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
-                       case '_':       goto yy193;
-                       default:        goto yy54;
+                       case '_':       goto yy207;
+                       default:        goto yy55;
                        }
-yy142:
-                       yyaccept = 5;
+yy148:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'U':
-                       case 'u':       goto yy194;
-                       default:        goto yy54;
+                       case 'u':       goto yy208;
+                       default:        goto yy55;
                        }
-yy143:
-                       yyaccept = 5;
+yy149:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'P':
-                       case 'p':       goto yy195;
-                       default:        goto yy54;
+                       case 'p':       goto yy209;
+                       default:        goto yy55;
                        }
-yy144:
-                       yyaccept = 5;
+yy150:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'N':
-                       case 'n':       goto yy196;
-                       default:        goto yy54;
+                       case 'n':       goto yy210;
+                       default:        goto yy55;
                        }
-yy145:
-                       yyaccept = 5;
+yy151:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
+                       case 'D':
+                       case 'd':       goto yy211;
                        case 'I':
-                       case 'i':       goto yy197;
+                       case 'i':       goto yy212;
                        case 'S':
-                       case 's':       goto yy198;
-                       default:        goto yy54;
+                       case 's':       goto yy213;
+                       default:        goto yy55;
                        }
-yy146:
-                       yyaccept = 5;
+yy152:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'I':
-                       case 'i':       goto yy199;
-                       default:        goto yy54;
+                       case 'i':       goto yy214;
+                       default:        goto yy55;
                        }
-yy147:
-                       yyaccept = 5;
+yy153:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'R':
+                       case 'r':       goto yy215;
+                       default:        goto yy55;
+                       }
+yy154:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'A':
-                       case 'a':       goto yy200;
-                       default:        goto yy54;
+                       case 'a':       goto yy216;
+                       default:        goto yy55;
                        }
-yy148:
+yy155:
                        yyaccept = 6;
                        P->mrk = ++P->cur;
-                       if (P->lim <= P->cur) { if (!psi_parser_fill(P,1)) RETURN(PSI_T_EOF); };
+                       if (P->lim <= P->cur) if (P->cur >= P->lim) goto done;;
                        yych = *P->cur;
                        switch (yych) {
                        case '0':
@@ -1664,30 +1835,30 @@ yy148:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy148;
-                       case '\\':      goto yy114;
-                       default:        goto yy150;
+                       case 'z':       goto yy155;
+                       case '\\':      goto yy115;
+                       default:        goto yy157;
                        }
-yy150:
-#line 368 "src/parser.re"
-                       {RETURN(PSI_T_NSNAME);}
-#line 1675 "src/parser.c"
-yy151:
+yy157:
+#line 421 "src/parser.re"
+                       { NEWTOKEN(PSI_T_NSNAME); goto start; }
+#line 1846 "src/parser.c"
+yy158:
                        ++P->cur;
-#line 286 "src/parser.re"
-                       {RETURN(PSI_T_OR);}
-#line 1680 "src/parser.c"
-yy153:
+#line 329 "src/parser.re"
+                       { NEWTOKEN(PSI_T_OR); goto start; }
+#line 1851 "src/parser.c"
+yy160:
                        ++P->cur;
-#line 370 "src/parser.re"
-                       {RETURN(PSI_T_QUOTED_STRING);}
-#line 1685 "src/parser.c"
-yy155:
+#line 423 "src/parser.re"
+                       { NEWTOKEN(PSI_T_QUOTED_STRING); goto start; }
+#line 1856 "src/parser.c"
+yy162:
                        ++P->cur;
-#line 304 "src/parser.re"
-                       {RETURN(PSI_T_ELLIPSIS);}
-#line 1690 "src/parser.c"
-yy157:
+#line 348 "src/parser.re"
+                       { NEWTOKEN(PSI_T_ELLIPSIS); goto start; }
+#line 1861 "src/parser.c"
+yy164:
                        yych = *++P->cur;
                        switch (yych) {
                        case '0':
@@ -1699,12 +1870,12 @@ yy157:
                        case '6':
                        case '7':
                        case '8':
-                       case '9':       goto yy158;
-                       default:        goto yy96;
+                       case '9':       goto yy165;
+                       default:        goto yy95;
                        }
-yy158:
+yy165:
                        ++P->cur;
-                       if (P->lim <= P->cur) { if (!psi_parser_fill(P,1)) RETURN(PSI_T_EOF); };
+                       if (P->lim <= P->cur) if (P->cur >= P->lim) goto done;;
                        yych = *P->cur;
                        switch (yych) {
                        case '0':
@@ -1716,108 +1887,164 @@ yy158:
                        case '6':
                        case '7':
                        case '8':
-                       case '9':       goto yy158;
-                       default:        goto yy35;
+                       case '9':       goto yy165;
+                       default:        goto yy36;
                        }
-yy160:
-                       yyaccept = 5;
+yy167:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'A':
-                       case 'a':       goto yy201;
+                       case 'a':       goto yy217;
                        case 'V':
-                       case 'v':       goto yy202;
-                       default:        goto yy54;
+                       case 'v':       goto yy218;
+                       default:        goto yy55;
                        }
-yy161:
-                       yyaccept = 5;
+yy168:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'L':
-                       case 'l':       goto yy203;
-                       default:        goto yy54;
+                       case 'l':       goto yy219;
+                       default:        goto yy55;
                        }
-yy162:
-                       yyaccept = 5;
+yy169:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'L':
-                       case 'l':       goto yy205;
-                       default:        goto yy54;
+                       case 'l':       goto yy221;
+                       default:        goto yy55;
                        }
-yy163:
-                       yyaccept = 5;
+yy170:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'R':
-                       case 'r':       goto yy206;
-                       default:        goto yy54;
+                       case 'r':       goto yy222;
+                       default:        goto yy55;
                        }
-yy164:
-                       yyaccept = 5;
+yy171:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'S':
-                       case 's':       goto yy208;
-                       default:        goto yy54;
+                       case 's':       goto yy224;
+                       default:        goto yy55;
                        }
-yy165:
-                       yyaccept = 5;
+yy172:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'N':
-                       case 'n':       goto yy209;
-                       default:        goto yy54;
+                       case 'n':       goto yy225;
+                       default:        goto yy55;
                        }
-yy166:
-                       yyaccept = 5;
+yy173:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'I':
+                       case 'i':       goto yy226;
+                       default:        goto yy55;
+                       }
+yy174:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'B':
-                       case 'b':       goto yy210;
-                       default:        goto yy54;
+                       case 'b':       goto yy227;
+                       default:        goto yy55;
                        }
-yy167:
-                       yyaccept = 5;
+yy175:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'F':
+                       case 'f':       goto yy228;
+                       default:        goto yy55;
+                       }
+yy176:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'E':
+                       case 'e':       goto yy230;
+                       default:        goto yy55;
+                       }
+yy177:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'I':
+                       case 'i':       goto yy232;
+                       default:        goto yy55;
+                       }
+yy178:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'M':
-                       case 'm':       goto yy211;
-                       default:        goto yy54;
+                       case 'm':       goto yy233;
+                       default:        goto yy55;
                        }
-yy168:
-                       yyaccept = 5;
+yy179:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'O':
+                       case 'o':       goto yy235;
+                       default:        goto yy55;
+                       }
+yy180:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'S':
-                       case 's':       goto yy213;
-                       default:        goto yy54;
+                       case 's':       goto yy236;
+                       default:        goto yy55;
                        }
-yy169:
-                       yyaccept = 5;
+yy181:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'A':
-                       case 'a':       goto yy214;
-                       default:        goto yy54;
+                       case 'a':       goto yy237;
+                       default:        goto yy55;
                        }
-yy170:
-                       yyaccept = 5;
+yy182:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'E':
-                       case 'e':       goto yy215;
-                       default:        goto yy54;
+                       case 'e':       goto yy238;
+                       default:        goto yy55;
                        }
-yy171:
-                       yyaccept = 5;
+yy183:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'C':
-                       case 'c':       goto yy217;
-                       default:        goto yy54;
+                       case 'c':       goto yy240;
+                       default:        goto yy55;
                        }
-yy172:
+yy184:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'E':
+                       case 'e':       goto yy241;
+                       default:        goto yy55;
+                       }
+yy185:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'D':
+                       case 'd':       goto yy242;
+                       default:        goto yy55;
+                       }
+yy186:
                        yyaccept = 7;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
@@ -1877,21 +2104,21 @@ yy172:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '1':       goto yy218;
-                       case '3':       goto yy219;
-                       case '6':       goto yy220;
-                       case '8':       goto yy221;
+                       case 'z':       goto yy54;
+                       case '1':       goto yy243;
+                       case '3':       goto yy244;
+                       case '6':       goto yy245;
+                       case '8':       goto yy246;
                        case 'V':
-                       case 'v':       goto yy222;
-                       case '\\':      goto yy114;
-                       default:        goto yy173;
+                       case 'v':       goto yy247;
+                       case '\\':      goto yy115;
+                       default:        goto yy187;
                        }
-yy173:
-#line 316 "src/parser.re"
-                       {RETURN(PSI_T_INT);}
-#line 1894 "src/parser.c"
-yy174:
+yy187:
+#line 369 "src/parser.re"
+                       { NEWTOKEN(PSI_T_INT); goto start; }
+#line 2121 "src/parser.c"
+yy188:
                        yyaccept = 8;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
@@ -1957,15 +2184,15 @@ yy174:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy175;
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy189;
                        }
-yy175:
-#line 342 "src/parser.re"
-                       {RETURN(PSI_T_LET);}
-#line 1968 "src/parser.c"
-yy176:
+yy189:
+#line 395 "src/parser.re"
+                       { NEWTOKEN(PSI_T_LET); goto start; }
+#line 2195 "src/parser.c"
+yy190:
                        yyaccept = 9;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
@@ -2031,81 +2258,1268 @@ yy176:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy177;
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy191;
                        }
-yy177:
-#line 341 "src/parser.re"
-                       {RETURN(PSI_T_LIB);}
-#line 2042 "src/parser.c"
-yy178:
-                       yyaccept = 5;
+yy191:
+#line 394 "src/parser.re"
+                       { NEWTOKEN(PSI_T_LIB); goto start; }
+#line 2269 "src/parser.c"
+yy192:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'G':
-                       case 'g':       goto yy223;
-                       default:        goto yy54;
+                       case 'g':       goto yy248;
+                       default:        goto yy55;
                        }
-yy179:
-                       yyaccept = 5;
+yy193:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'E':
-                       case 'e':       goto yy225;
-                       default:        goto yy54;
+                       case 'e':       goto yy250;
+                       default:        goto yy55;
                        }
-yy180:
-                       yyaccept = 5;
+yy194:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'L':
-                       case 'l':       goto yy226;
-                       default:        goto yy54;
+                       case 'l':       goto yy251;
+                       default:        goto yy55;
                        }
-yy181:
-                       yyaccept = 5;
+yy195:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'E':
+                       case 'e':       goto yy253;
+                       case 'V':
+                       case 'v':       goto yy254;
+                       default:        goto yy55;
+                       }
+yy196:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'H':
+                       case 'h':       goto yy255;
+                       default:        goto yy55;
+                       }
+yy197:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'T':
+                       case 't':       goto yy256;
+                       default:        goto yy55;
+                       }
+yy198:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case '_':       goto yy257;
+                       default:        goto yy55;
+                       }
+yy199:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'U':
+                       case 'u':       goto yy258;
+                       default:        goto yy55;
+                       }
+yy200:
+                       yyaccept = 10;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case '0':
+                       case '1':
+                       case '2':
+                       case '3':
+                       case '4':
+                       case '5':
+                       case '6':
+                       case '7':
+                       case '8':
+                       case '9':
+                       case 'A':
+                       case 'B':
+                       case 'C':
+                       case 'D':
+                       case 'E':
+                       case 'F':
+                       case 'G':
+                       case 'H':
+                       case 'I':
+                       case 'J':
+                       case 'K':
+                       case 'L':
+                       case 'M':
+                       case 'N':
+                       case 'O':
+                       case 'P':
+                       case 'Q':
+                       case 'R':
+                       case 'S':
+                       case 'T':
+                       case 'U':
+                       case 'V':
+                       case 'W':
+                       case 'X':
+                       case 'Y':
+                       case 'Z':
+                       case '_':
+                       case 'a':
+                       case 'b':
+                       case 'c':
+                       case 'd':
+                       case 'e':
+                       case 'f':
+                       case 'g':
+                       case 'h':
+                       case 'i':
+                       case 'j':
+                       case 'k':
+                       case 'l':
+                       case 'm':
+                       case 'n':
+                       case 'o':
+                       case 'p':
+                       case 'q':
+                       case 'r':
+                       case 's':
+                       case 't':
+                       case 'u':
+                       case 'v':
+                       case 'w':
+                       case 'x':
+                       case 'y':
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy201;
+                       }
+yy201:
+#line 396 "src/parser.re"
+                       { NEWTOKEN(PSI_T_SET); goto start; }
+#line 2408 "src/parser.c"
+yy202:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'R':
+                       case 'r':       goto yy259;
+                       default:        goto yy55;
+                       }
+yy203:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'N':
+                       case 'n':       goto yy260;
+                       default:        goto yy55;
+                       }
+yy204:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'T':
+                       case 't':       goto yy261;
+                       default:        goto yy55;
+                       }
+yy205:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'I':
+                       case 'i':       goto yy262;
+                       case 'L':
+                       case 'l':       goto yy263;
+                       case 'U':
+                       case 'u':       goto yy264;
+                       case 'V':
+                       case 'v':       goto yy265;
+                       default:        goto yy55;
+                       }
+yy206:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'P':
+                       case 'p':       goto yy266;
+                       default:        goto yy55;
+                       }
+yy207:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'A':
+                       case 'a':       goto yy268;
+                       case 'B':
+                       case 'b':       goto yy269;
+                       case 'F':
+                       case 'f':       goto yy270;
+                       case 'I':
+                       case 'i':       goto yy271;
+                       case 'O':
+                       case 'o':       goto yy272;
+                       case 'S':
+                       case 's':       goto yy273;
+                       default:        goto yy55;
+                       }
+yy208:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'E':
+                       case 'e':       goto yy274;
+                       default:        goto yy55;
+                       }
+yy209:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'E':
+                       case 'e':       goto yy276;
+                       default:        goto yy55;
+                       }
+yy210:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'T':
+                       case 't':       goto yy277;
+                       default:        goto yy55;
+                       }
+yy211:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'E':
+                       case 'e':       goto yy278;
+                       default:        goto yy55;
+                       }
+yy212:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'O':
+                       case 'o':       goto yy279;
+                       default:        goto yy55;
+                       }
+yy213:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'I':
+                       case 'i':       goto yy280;
+                       default:        goto yy55;
+                       }
+yy214:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'D':
+                       case 'd':       goto yy281;
+                       default:        goto yy55;
+                       }
+yy215:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'N':
+                       case 'n':       goto yy283;
+                       default:        goto yy55;
+                       }
+yy216:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'L':
+                       case 'l':       goto yy284;
+                       default:        goto yy55;
+                       }
+yy217:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'Y':
+                       case 'y':       goto yy286;
+                       default:        goto yy55;
+                       }
+yy218:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'A':
+                       case 'a':       goto yy288;
+                       default:        goto yy55;
+                       }
+yy219:
+                       yyaccept = 11;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case '0':
+                       case '1':
+                       case '2':
+                       case '3':
+                       case '4':
+                       case '5':
+                       case '6':
+                       case '7':
+                       case '8':
+                       case '9':
+                       case 'A':
+                       case 'B':
+                       case 'C':
+                       case 'D':
+                       case 'E':
+                       case 'F':
+                       case 'G':
+                       case 'H':
+                       case 'I':
+                       case 'J':
+                       case 'K':
+                       case 'L':
+                       case 'M':
+                       case 'N':
+                       case 'O':
+                       case 'P':
+                       case 'Q':
+                       case 'R':
+                       case 'S':
+                       case 'T':
+                       case 'U':
+                       case 'W':
+                       case 'X':
+                       case 'Y':
+                       case 'Z':
+                       case '_':
+                       case 'a':
+                       case 'b':
+                       case 'c':
+                       case 'd':
+                       case 'e':
+                       case 'f':
+                       case 'g':
+                       case 'h':
+                       case 'i':
+                       case 'j':
+                       case 'k':
+                       case 'l':
+                       case 'm':
+                       case 'n':
+                       case 'o':
+                       case 'p':
+                       case 'q':
+                       case 'r':
+                       case 's':
+                       case 't':
+                       case 'u':
+                       case 'w':
+                       case 'x':
+                       case 'y':
+                       case 'z':       goto yy54;
+                       case 'V':
+                       case 'v':       goto yy289;
+                       case '\\':      goto yy115;
+                       default:        goto yy220;
+                       }
+yy220:
+#line 366 "src/parser.re"
+                       { NEWTOKEN(PSI_T_BOOL); goto start; }
+#line 2634 "src/parser.c"
+yy221:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'A':
+                       case 'a':       goto yy290;
+                       case 'B':
+                       case 'b':       goto yy291;
+                       case 'O':
+                       case 'o':       goto yy292;
+                       default:        goto yy55;
+                       }
+yy222:
+                       yyaccept = 12;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case '0':
+                       case '1':
+                       case '2':
+                       case '3':
+                       case '4':
+                       case '5':
+                       case '6':
+                       case '7':
+                       case '8':
+                       case '9':
+                       case 'A':
+                       case 'B':
+                       case 'C':
+                       case 'D':
+                       case 'E':
+                       case 'F':
+                       case 'G':
+                       case 'H':
+                       case 'I':
+                       case 'J':
+                       case 'K':
+                       case 'L':
+                       case 'M':
+                       case 'N':
+                       case 'O':
+                       case 'P':
+                       case 'Q':
+                       case 'R':
+                       case 'S':
+                       case 'T':
+                       case 'U':
+                       case 'V':
+                       case 'W':
+                       case 'X':
+                       case 'Y':
+                       case 'Z':
+                       case '_':
+                       case 'a':
+                       case 'b':
+                       case 'c':
+                       case 'd':
+                       case 'e':
+                       case 'f':
+                       case 'g':
+                       case 'h':
+                       case 'i':
+                       case 'j':
+                       case 'k':
+                       case 'l':
+                       case 'm':
+                       case 'n':
+                       case 'o':
+                       case 'p':
+                       case 'q':
+                       case 'r':
+                       case 's':
+                       case 't':
+                       case 'u':
+                       case 'v':
+                       case 'w':
+                       case 'x':
+                       case 'y':
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy223;
+                       }
+yy223:
+#line 367 "src/parser.re"
+                       { NEWTOKEN(PSI_T_CHAR); goto start; }
+#line 2720 "src/parser.c"
+yy224:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'T':
+                       case 't':       goto yy293;
+                       default:        goto yy55;
+                       }
+yy225:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'T':
+                       case 't':       goto yy295;
+                       default:        goto yy55;
+                       }
+yy226:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'N':
+                       case 'n':       goto yy297;
+                       default:        goto yy55;
+                       }
+yy227:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'L':
+                       case 'l':       goto yy298;
+                       default:        goto yy55;
+                       }
+yy228:
+                       yyaccept = 13;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case '0':
+                       case '1':
+                       case '2':
+                       case '3':
+                       case '4':
+                       case '5':
+                       case '6':
+                       case '7':
+                       case '8':
+                       case '9':
+                       case 'A':
+                       case 'B':
+                       case 'C':
+                       case 'D':
+                       case 'E':
+                       case 'F':
+                       case 'G':
+                       case 'H':
+                       case 'I':
+                       case 'J':
+                       case 'K':
+                       case 'L':
+                       case 'M':
+                       case 'N':
+                       case 'O':
+                       case 'P':
+                       case 'Q':
+                       case 'R':
+                       case 'S':
+                       case 'T':
+                       case 'U':
+                       case 'V':
+                       case 'W':
+                       case 'X':
+                       case 'Y':
+                       case 'Z':
+                       case '_':
+                       case 'a':
+                       case 'b':
+                       case 'c':
+                       case 'd':
+                       case 'e':
+                       case 'f':
+                       case 'g':
+                       case 'h':
+                       case 'i':
+                       case 'j':
+                       case 'k':
+                       case 'l':
+                       case 'm':
+                       case 'n':
+                       case 'o':
+                       case 'p':
+                       case 'q':
+                       case 'r':
+                       case 's':
+                       case 't':
+                       case 'u':
+                       case 'v':
+                       case 'w':
+                       case 'x':
+                       case 'y':
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy229;
+                       }
+yy229:
+#line 353 "src/parser.re"
+                       { NEWTOKEN(PSI_T_ELIF); goto start; }
+#line 2826 "src/parser.c"
+yy230:
+                       yyaccept = 14;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case '0':
+                       case '1':
+                       case '2':
+                       case '3':
+                       case '4':
+                       case '5':
+                       case '6':
+                       case '7':
+                       case '8':
+                       case '9':
+                       case 'A':
+                       case 'B':
+                       case 'C':
+                       case 'D':
+                       case 'E':
+                       case 'F':
+                       case 'G':
+                       case 'H':
+                       case 'I':
+                       case 'J':
+                       case 'K':
+                       case 'L':
+                       case 'M':
+                       case 'N':
+                       case 'O':
+                       case 'P':
+                       case 'Q':
+                       case 'R':
+                       case 'S':
+                       case 'T':
+                       case 'U':
+                       case 'V':
+                       case 'W':
+                       case 'X':
+                       case 'Y':
+                       case 'Z':
+                       case '_':
+                       case 'a':
+                       case 'b':
+                       case 'c':
+                       case 'd':
+                       case 'e':
+                       case 'f':
+                       case 'g':
+                       case 'h':
+                       case 'i':
+                       case 'j':
+                       case 'k':
+                       case 'l':
+                       case 'm':
+                       case 'n':
+                       case 'o':
+                       case 'p':
+                       case 'q':
+                       case 'r':
+                       case 's':
+                       case 't':
+                       case 'u':
+                       case 'v':
+                       case 'w':
+                       case 'x':
+                       case 'y':
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy231;
+                       }
+yy231:
+#line 352 "src/parser.re"
+                       { NEWTOKEN(PSI_T_ELSE); goto start; }
+#line 2900 "src/parser.c"
+yy232:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'F':
+                       case 'f':       goto yy299;
+                       default:        goto yy55;
+                       }
+yy233:
+                       yyaccept = 15;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case '0':
+                       case '1':
+                       case '2':
+                       case '3':
+                       case '4':
+                       case '5':
+                       case '6':
+                       case '7':
+                       case '8':
+                       case '9':
+                       case 'A':
+                       case 'B':
+                       case 'C':
+                       case 'D':
+                       case 'E':
+                       case 'F':
+                       case 'G':
+                       case 'H':
+                       case 'I':
+                       case 'J':
+                       case 'K':
+                       case 'L':
+                       case 'M':
+                       case 'N':
+                       case 'O':
+                       case 'P':
+                       case 'Q':
+                       case 'R':
+                       case 'S':
+                       case 'T':
+                       case 'U':
+                       case 'V':
+                       case 'W':
+                       case 'X':
+                       case 'Y':
+                       case 'Z':
+                       case '_':
+                       case 'a':
+                       case 'b':
+                       case 'c':
+                       case 'd':
+                       case 'e':
+                       case 'f':
+                       case 'g':
+                       case 'h':
+                       case 'i':
+                       case 'j':
+                       case 'k':
+                       case 'l':
+                       case 'm':
+                       case 'n':
+                       case 'o':
+                       case 'p':
+                       case 'q':
+                       case 'r':
+                       case 's':
+                       case 't':
+                       case 'u':
+                       case 'v':
+                       case 'w':
+                       case 'x':
+                       case 'y':
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy234;
+                       }
+yy234:
+#line 392 "src/parser.re"
+                       { NEWTOKEN(PSI_T_ENUM); goto start; }
+#line 2982 "src/parser.c"
+yy235:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'R':
+                       case 'r':       goto yy301;
+                       default:        goto yy55;
+                       }
+yy236:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'E':
+                       case 'e':       goto yy303;
+                       default:        goto yy55;
+                       }
+yy237:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'T':
+                       case 't':       goto yy305;
+                       default:        goto yy55;
+                       }
+yy238:
+                       yyaccept = 16;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case '0':
+                       case '1':
+                       case '2':
+                       case '3':
+                       case '4':
+                       case '5':
+                       case '6':
+                       case '7':
+                       case '8':
+                       case '9':
+                       case 'A':
+                       case 'B':
+                       case 'C':
+                       case 'D':
+                       case 'E':
+                       case 'F':
+                       case 'G':
+                       case 'H':
+                       case 'I':
+                       case 'J':
+                       case 'K':
+                       case 'L':
+                       case 'M':
+                       case 'N':
+                       case 'O':
+                       case 'P':
+                       case 'Q':
+                       case 'R':
+                       case 'S':
+                       case 'T':
+                       case 'U':
+                       case 'V':
+                       case 'W':
+                       case 'X':
+                       case 'Y':
+                       case 'Z':
+                       case '_':
+                       case 'a':
+                       case 'b':
+                       case 'c':
+                       case 'd':
+                       case 'e':
+                       case 'f':
+                       case 'g':
+                       case 'h':
+                       case 'i':
+                       case 'j':
+                       case 'k':
+                       case 'l':
+                       case 'm':
+                       case 'n':
+                       case 'o':
+                       case 'p':
+                       case 'q':
+                       case 'r':
+                       case 's':
+                       case 't':
+                       case 'u':
+                       case 'v':
+                       case 'w':
+                       case 'x':
+                       case 'y':
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy239;
+                       }
+yy239:
+#line 400 "src/parser.re"
+                       { NEWTOKEN(PSI_T_FREE); goto start; }
+#line 3080 "src/parser.c"
+yy240:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'T':
+                       case 't':       goto yy307;
+                       default:        goto yy55;
+                       }
+yy241:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'F':
+                       case 'f':       goto yy308;
+                       default:        goto yy55;
+                       }
+yy242:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'E':
+                       case 'e':       goto yy310;
+                       default:        goto yy55;
+                       }
+yy243:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case '6':       goto yy311;
+                       default:        goto yy55;
+                       }
+yy244:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case '2':       goto yy312;
+                       default:        goto yy55;
+                       }
+yy245:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case '4':       goto yy313;
+                       default:        goto yy55;
+                       }
+yy246:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case '_':       goto yy314;
+                       default:        goto yy55;
+                       }
+yy247:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'A':
+                       case 'a':       goto yy315;
+                       default:        goto yy55;
+                       }
+yy248:
+                       yyaccept = 17;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case '0':
+                       case '1':
+                       case '2':
+                       case '3':
+                       case '4':
+                       case '5':
+                       case '6':
+                       case '7':
+                       case '8':
+                       case '9':
+                       case 'A':
+                       case 'B':
+                       case 'C':
+                       case 'D':
+                       case 'E':
+                       case 'F':
+                       case 'G':
+                       case 'H':
+                       case 'I':
+                       case 'J':
+                       case 'K':
+                       case 'L':
+                       case 'M':
+                       case 'N':
+                       case 'O':
+                       case 'P':
+                       case 'Q':
+                       case 'R':
+                       case 'S':
+                       case 'T':
+                       case 'U':
+                       case 'V':
+                       case 'W':
+                       case 'X':
+                       case 'Y':
+                       case 'Z':
+                       case '_':
+                       case 'a':
+                       case 'b':
+                       case 'c':
+                       case 'd':
+                       case 'e':
+                       case 'f':
+                       case 'g':
+                       case 'h':
+                       case 'i':
+                       case 'j':
+                       case 'k':
+                       case 'l':
+                       case 'm':
+                       case 'n':
+                       case 'o':
+                       case 'p':
+                       case 'q':
+                       case 'r':
+                       case 's':
+                       case 't':
+                       case 'u':
+                       case 'v':
+                       case 'w':
+                       case 'x':
+                       case 'y':
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy249;
+                       }
+yy249:
+#line 370 "src/parser.re"
+                       { NEWTOKEN(PSI_T_LONG); goto start; }
+#line 3214 "src/parser.c"
+yy250:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'D':
+                       case 'd':       goto yy316;
+                       default:        goto yy55;
+                       }
+yy251:
+                       yyaccept = 18;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case '0':
+                       case '1':
+                       case '2':
+                       case '3':
+                       case '4':
+                       case '5':
+                       case '6':
+                       case '7':
+                       case '8':
+                       case '9':
+                       case 'A':
+                       case 'B':
+                       case 'C':
+                       case 'D':
+                       case 'E':
+                       case 'F':
+                       case 'G':
+                       case 'H':
+                       case 'I':
+                       case 'J':
+                       case 'K':
+                       case 'L':
+                       case 'M':
+                       case 'N':
+                       case 'O':
+                       case 'P':
+                       case 'Q':
+                       case 'R':
+                       case 'S':
+                       case 'T':
+                       case 'U':
+                       case 'V':
+                       case 'W':
+                       case 'X':
+                       case 'Y':
+                       case 'Z':
+                       case '_':
+                       case 'a':
+                       case 'b':
+                       case 'c':
+                       case 'd':
+                       case 'e':
+                       case 'f':
+                       case 'g':
+                       case 'h':
+                       case 'i':
+                       case 'j':
+                       case 'k':
+                       case 'l':
+                       case 'm':
+                       case 'n':
+                       case 'o':
+                       case 'p':
+                       case 'q':
+                       case 'r':
+                       case 's':
+                       case 't':
+                       case 'u':
+                       case 'v':
+                       case 'w':
+                       case 'x':
+                       case 'y':
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy252;
+                       }
+yy252:
+#line 362 "src/parser.re"
+                       { NEWTOKEN(PSI_T_NULL); goto start; }
+#line 3296 "src/parser.c"
+yy253:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'C':
+                       case 'c':       goto yy318;
+                       default:        goto yy55;
+                       }
+yy254:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'A':
+                       case 'a':       goto yy319;
+                       default:        goto yy55;
+                       }
+yy255:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'V':
+                       case 'v':       goto yy320;
+                       default:        goto yy55;
+                       }
+yy256:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case '_':       goto yy321;
+                       default:        goto yy55;
+                       }
+yy257:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'A':
+                       case 'a':       goto yy322;
+                       default:        goto yy55;
+                       }
+yy258:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'R':
+                       case 'r':       goto yy323;
+                       default:        goto yy55;
+                       }
+yy259:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'T':
+                       case 't':       goto yy324;
+                       default:        goto yy55;
+                       }
+yy260:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'E':
+                       case 'e':       goto yy326;
+                       default:        goto yy55;
+                       }
+yy261:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'I':
+                       case 'i':       goto yy327;
+                       default:        goto yy55;
+                       }
+yy262:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'N':
+                       case 'n':       goto yy328;
+                       default:        goto yy55;
+                       }
+yy263:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'E':
+                       case 'e':       goto yy329;
+                       default:        goto yy55;
+                       }
+yy264:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'C':
+                       case 'c':       goto yy330;
+                       default:        goto yy55;
+                       }
+yy265:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'A':
+                       case 'a':       goto yy331;
+                       default:        goto yy55;
+                       }
+yy266:
+                       yyaccept = 19;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case '0':
+                       case '1':
+                       case '2':
+                       case '3':
+                       case '4':
+                       case '5':
+                       case '6':
+                       case '7':
+                       case '8':
+                       case '9':
+                       case 'A':
+                       case 'B':
+                       case 'C':
+                       case 'D':
+                       case 'E':
+                       case 'F':
+                       case 'G':
+                       case 'H':
+                       case 'I':
+                       case 'J':
+                       case 'K':
+                       case 'L':
+                       case 'M':
+                       case 'N':
+                       case 'O':
+                       case 'P':
+                       case 'Q':
+                       case 'R':
+                       case 'S':
+                       case 'T':
+                       case 'U':
+                       case 'V':
+                       case 'W':
+                       case 'X':
+                       case 'Y':
+                       case 'Z':
+                       case '_':
+                       case 'a':
+                       case 'b':
+                       case 'c':
+                       case 'd':
+                       case 'e':
+                       case 'f':
+                       case 'g':
+                       case 'h':
+                       case 'i':
+                       case 'j':
+                       case 'k':
+                       case 'l':
+                       case 'm':
+                       case 'n':
+                       case 'o':
+                       case 'p':
+                       case 'q':
+                       case 'r':
+                       case 's':
+                       case 't':
+                       case 'u':
+                       case 'v':
+                       case 'w':
+                       case 'x':
+                       case 'y':
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy267;
+                       }
+yy267:
+#line 401 "src/parser.re"
+                       { NEWTOKEN(PSI_T_TEMP); goto start; }
+#line 3473 "src/parser.c"
+yy268:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'R':
+                       case 'r':       goto yy332;
+                       default:        goto yy55;
+                       }
+yy269:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
-                       case 'E':
-                       case 'e':       goto yy228;
-                       case 'V':
-                       case 'v':       goto yy229;
-                       default:        goto yy54;
+                       case 'O':
+                       case 'o':       goto yy333;
+                       default:        goto yy55;
                        }
-yy182:
-                       yyaccept = 5;
+yy270:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
-                       case 'H':
-                       case 'h':       goto yy230;
-                       default:        goto yy54;
+                       case 'L':
+                       case 'l':       goto yy334;
+                       default:        goto yy55;
                        }
-yy183:
-                       yyaccept = 5;
+yy271:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
-                       case 'T':
-                       case 't':       goto yy231;
-                       default:        goto yy54;
+                       case 'N':
+                       case 'n':       goto yy335;
+                       default:        goto yy55;
                        }
-yy184:
-                       yyaccept = 5;
+yy272:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
-                       case '_':       goto yy232;
-                       default:        goto yy54;
+                       case 'B':
+                       case 'b':       goto yy336;
+                       default:        goto yy55;
                        }
-yy185:
-                       yyaccept = 5;
+yy273:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
-                       case 'U':
-                       case 'u':       goto yy233;
-                       default:        goto yy54;
+                       case 'T':
+                       case 't':       goto yy337;
+                       default:        goto yy55;
                        }
-yy186:
-                       yyaccept = 10;
+yy274:
+                       yyaccept = 20;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -2170,152 +3584,58 @@ yy186:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy187;
-                       }
-yy187:
-#line 343 "src/parser.re"
-                       {RETURN(PSI_T_SET);}
-#line 2181 "src/parser.c"
-yy188:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'R':
-                       case 'r':       goto yy234;
-                       default:        goto yy54;
-                       }
-yy189:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'N':
-                       case 'n':       goto yy235;
-                       default:        goto yy54;
-                       }
-yy190:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'T':
-                       case 't':       goto yy236;
-                       default:        goto yy54;
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy275;
                        }
-yy191:
-                       yyaccept = 5;
+yy275:
+#line 360 "src/parser.re"
+                       { NEWTOKEN(PSI_T_TRUE); goto start; }
+#line 3595 "src/parser.c"
+yy276:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
-                       case 'I':
-                       case 'i':       goto yy237;
-                       case 'L':
-                       case 'l':       goto yy238;
-                       case 'U':
-                       case 'u':       goto yy239;
-                       case 'V':
-                       case 'v':       goto yy240;
-                       default:        goto yy54;
+                       case 'D':
+                       case 'd':       goto yy338;
+                       default:        goto yy55;
                        }
-yy192:
-                       yyaccept = 5;
+yy277:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
-                       case 'P':
-                       case 'p':       goto yy241;
-                       default:        goto yy54;
+                       case '1':       goto yy339;
+                       case '3':       goto yy340;
+                       case '6':       goto yy341;
+                       case '8':       goto yy342;
+                       default:        goto yy55;
                        }
-yy193:
-                       yyaccept = 5;
+yy278:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
-                       case 'A':
-                       case 'a':       goto yy243;
-                       case 'B':
-                       case 'b':       goto yy244;
                        case 'F':
-                       case 'f':       goto yy245;
-                       case 'I':
-                       case 'i':       goto yy246;
-                       case 'O':
-                       case 'o':       goto yy247;
-                       case 'S':
-                       case 's':       goto yy248;
-                       default:        goto yy54;
-                       }
-yy194:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'E':
-                       case 'e':       goto yy249;
-                       default:        goto yy54;
-                       }
-yy195:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'E':
-                       case 'e':       goto yy251;
-                       default:        goto yy54;
-                       }
-yy196:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'T':
-                       case 't':       goto yy252;
-                       default:        goto yy54;
-                       }
-yy197:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'O':
-                       case 'o':       goto yy253;
-                       default:        goto yy54;
-                       }
-yy198:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'I':
-                       case 'i':       goto yy254;
-                       default:        goto yy54;
-                       }
-yy199:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'D':
-                       case 'd':       goto yy255;
-                       default:        goto yy54;
-                       }
-yy200:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'L':
-                       case 'l':       goto yy257;
-                       default:        goto yy54;
+                       case 'f':       goto yy343;
+                       default:        goto yy55;
                        }
-yy201:
-                       yyaccept = 5;
+yy279:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
-                       case 'Y':
-                       case 'y':       goto yy259;
-                       default:        goto yy54;
+                       case 'N':
+                       case 'n':       goto yy345;
+                       default:        goto yy55;
                        }
-yy202:
-                       yyaccept = 5;
+yy280:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
-                       case 'A':
-                       case 'a':       goto yy261;
-                       default:        goto yy54;
+                       case 'G':
+                       case 'g':       goto yy347;
+                       default:        goto yy55;
                        }
-yy203:
-                       yyaccept = 11;
+yy281:
+                       yyaccept = 21;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -2349,6 +3669,7 @@ yy203:
                        case 'S':
                        case 'T':
                        case 'U':
+                       case 'V':
                        case 'W':
                        case 'X':
                        case 'Y':
@@ -2375,33 +3696,28 @@ yy203:
                        case 's':
                        case 't':
                        case 'u':
+                       case 'v':
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case 'V':
-                       case 'v':       goto yy262;
-                       case '\\':      goto yy114;
-                       default:        goto yy204;
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy282;
                        }
-yy204:
-#line 313 "src/parser.re"
-                       {RETURN(PSI_T_BOOL);}
-#line 2391 "src/parser.c"
-yy205:
-                       yyaccept = 5;
+yy282:
+#line 365 "src/parser.re"
+                       { NEWTOKEN(PSI_T_VOID); goto start; }
+#line 3711 "src/parser.c"
+yy283:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
-                       case 'A':
-                       case 'a':       goto yy263;
-                       case 'B':
-                       case 'b':       goto yy264;
-                       case 'O':
-                       case 'o':       goto yy265;
-                       default:        goto yy54;
+                       case 'I':
+                       case 'i':       goto yy348;
+                       default:        goto yy55;
                        }
-yy206:
-                       yyaccept = 12;
+yy284:
+                       yyaccept = 22;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -2466,40 +3782,16 @@ yy206:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy207;
-                       }
-yy207:
-#line 314 "src/parser.re"
-                       {RETURN(PSI_T_CHAR);}
-#line 2477 "src/parser.c"
-yy208:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'T':
-                       case 't':       goto yy266;
-                       default:        goto yy54;
-                       }
-yy209:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'T':
-                       case 't':       goto yy268;
-                       default:        goto yy54;
-                       }
-yy210:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'L':
-                       case 'l':       goto yy270;
-                       default:        goto yy54;
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy285;
                        }
-yy211:
-                       yyaccept = 13;
+yy285:
+#line 410 "src/parser.re"
+                       { NEWTOKEN(PSI_T_ZVAL); goto start; }
+#line 3793 "src/parser.c"
+yy286:
+                       yyaccept = 23;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -2564,32 +3856,56 @@ yy211:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy212;
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy287;
                        }
-yy212:
-#line 339 "src/parser.re"
-                       {RETURN(PSI_T_ENUM);}
-#line 2575 "src/parser.c"
-yy213:
-                       yyaccept = 5;
+yy287:
+#line 384 "src/parser.re"
+                       { NEWTOKEN(PSI_T_ARRAY); goto start; }
+#line 3867 "src/parser.c"
+yy288:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
-                       case 'E':
-                       case 'e':       goto yy271;
-                       default:        goto yy54;
+                       case 'L':
+                       case 'l':       goto yy349;
+                       default:        goto yy55;
                        }
-yy214:
-                       yyaccept = 5;
+yy289:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
-                       case 'T':
-                       case 't':       goto yy273;
-                       default:        goto yy54;
+                       case 'A':
+                       case 'a':       goto yy351;
+                       default:        goto yy55;
                        }
-yy215:
-                       yyaccept = 14;
+yy290:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'B':
+                       case 'b':       goto yy352;
+                       default:        goto yy55;
+                       }
+yy291:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'A':
+                       case 'a':       goto yy353;
+                       default:        goto yy55;
+                       }
+yy292:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'C':
+                       case 'c':       goto yy354;
+                       default:        goto yy55;
+                       }
+yy293:
+                       yyaccept = 24;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -2654,60 +3970,16 @@ yy215:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy216;
-                       }
-yy216:
-#line 347 "src/parser.re"
-                       {RETURN(PSI_T_FREE);}
-#line 2665 "src/parser.c"
-yy217:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'T':
-                       case 't':       goto yy275;
-                       default:        goto yy54;
-                       }
-yy218:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case '6':       goto yy276;
-                       default:        goto yy54;
-                       }
-yy219:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case '2':       goto yy277;
-                       default:        goto yy54;
-                       }
-yy220:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case '4':       goto yy278;
-                       default:        goto yy54;
-                       }
-yy221:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case '_':       goto yy279;
-                       default:        goto yy54;
-                       }
-yy222:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'A':
-                       case 'a':       goto yy280;
-                       default:        goto yy54;
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy294;
                        }
-yy223:
-                       yyaccept = 15;
+yy294:
+#line 393 "src/parser.re"
+                       { NEWTOKEN(PSI_T_CONST); goto start; }
+#line 3981 "src/parser.c"
+yy295:
+                       yyaccept = 25;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -2772,24 +4044,32 @@ yy223:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy224;
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy296;
                        }
-yy224:
-#line 317 "src/parser.re"
-                       {RETURN(PSI_T_LONG);}
-#line 2783 "src/parser.c"
-yy225:
-                       yyaccept = 5;
+yy296:
+#line 411 "src/parser.re"
+                       { NEWTOKEN(PSI_T_COUNT); goto start; }
+#line 4055 "src/parser.c"
+yy297:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
-                       case 'D':
-                       case 'd':       goto yy281;
-                       default:        goto yy54;
+                       case 'E':
+                       case 'e':       goto yy356;
+                       default:        goto yy55;
                        }
-yy226:
-                       yyaccept = 16;
+yy298:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'E':
+                       case 'e':       goto yy358;
+                       default:        goto yy55;
+                       }
+yy299:
+                       yyaccept = 26;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -2854,119 +4134,16 @@ yy226:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy227;
-                       }
-yy227:
-#line 309 "src/parser.re"
-                       {RETURN(PSI_T_NULL);}
-#line 2865 "src/parser.c"
-yy228:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'C':
-                       case 'c':       goto yy283;
-                       default:        goto yy54;
-                       }
-yy229:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'A':
-                       case 'a':       goto yy284;
-                       default:        goto yy54;
-                       }
-yy230:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'V':
-                       case 'v':       goto yy285;
-                       default:        goto yy54;
-                       }
-yy231:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case '_':       goto yy286;
-                       default:        goto yy54;
-                       }
-yy232:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'A':
-                       case 'a':       goto yy287;
-                       default:        goto yy54;
-                       }
-yy233:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'R':
-                       case 'r':       goto yy288;
-                       default:        goto yy54;
-                       }
-yy234:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'T':
-                       case 't':       goto yy289;
-                       default:        goto yy54;
-                       }
-yy235:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'E':
-                       case 'e':       goto yy291;
-                       default:        goto yy54;
-                       }
-yy236:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'I':
-                       case 'i':       goto yy292;
-                       default:        goto yy54;
-                       }
-yy237:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'N':
-                       case 'n':       goto yy293;
-                       default:        goto yy54;
-                       }
-yy238:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'E':
-                       case 'e':       goto yy294;
-                       default:        goto yy54;
-                       }
-yy239:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'C':
-                       case 'c':       goto yy295;
-                       default:        goto yy54;
-                       }
-yy240:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'A':
-                       case 'a':       goto yy296;
-                       default:        goto yy54;
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy300;
                        }
-yy241:
-                       yyaccept = 17;
+yy300:
+#line 354 "src/parser.re"
+                       { NEWTOKEN(PSI_T_ENDIF); goto start; }
+#line 4145 "src/parser.c"
+yy301:
+                       yyaccept = 27;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -3031,64 +4208,16 @@ yy241:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy242;
-                       }
-yy242:
-#line 348 "src/parser.re"
-                       {RETURN(PSI_T_TEMP);}
-#line 3042 "src/parser.c"
-yy243:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'R':
-                       case 'r':       goto yy297;
-                       default:        goto yy54;
-                       }
-yy244:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'O':
-                       case 'o':       goto yy298;
-                       default:        goto yy54;
-                       }
-yy245:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'L':
-                       case 'l':       goto yy299;
-                       default:        goto yy54;
-                       }
-yy246:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'N':
-                       case 'n':       goto yy300;
-                       default:        goto yy54;
-                       }
-yy247:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'B':
-                       case 'b':       goto yy301;
-                       default:        goto yy54;
-                       }
-yy248:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'T':
-                       case 't':       goto yy302;
-                       default:        goto yy54;
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy302;
                        }
-yy249:
-                       yyaccept = 18;
+yy302:
+#line 359 "src/parser.re"
+                       { NEWTOKEN(PSI_T_ERROR); goto start; }
+#line 4219 "src/parser.c"
+yy303:
+                       yyaccept = 28;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -3153,50 +4282,16 @@ yy249:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy250;
-                       }
-yy250:
-#line 307 "src/parser.re"
-                       {RETURN(PSI_T_TRUE);}
-#line 3164 "src/parser.c"
-yy251:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'D':
-                       case 'd':       goto yy303;
-                       default:        goto yy54;
-                       }
-yy252:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case '1':       goto yy304;
-                       case '3':       goto yy305;
-                       case '6':       goto yy306;
-                       case '8':       goto yy307;
-                       default:        goto yy54;
-                       }
-yy253:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'N':
-                       case 'n':       goto yy308;
-                       default:        goto yy54;
-                       }
-yy254:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'G':
-                       case 'g':       goto yy310;
-                       default:        goto yy54;
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy304;
                        }
-yy255:
-                       yyaccept = 19;
+yy304:
+#line 361 "src/parser.re"
+                       { NEWTOKEN(PSI_T_FALSE); goto start; }
+#line 4293 "src/parser.c"
+yy305:
+                       yyaccept = 29;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -3230,7 +4325,6 @@ yy255:
                        case 'S':
                        case 'T':
                        case 'U':
-                       case 'V':
                        case 'W':
                        case 'X':
                        case 'Y':
@@ -3257,20 +4351,29 @@ yy255:
                        case 's':
                        case 't':
                        case 'u':
-                       case 'v':
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy256;
+                       case 'z':       goto yy54;
+                       case 'V':
+                       case 'v':       goto yy360;
+                       case '\\':      goto yy115;
+                       default:        goto yy306;
                        }
-yy256:
-#line 312 "src/parser.re"
-                       {RETURN(PSI_T_VOID);}
-#line 3272 "src/parser.c"
-yy257:
-                       yyaccept = 20;
+yy306:
+#line 371 "src/parser.re"
+                       { NEWTOKEN(PSI_T_FLOAT); goto start; }
+#line 4367 "src/parser.c"
+yy307:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'I':
+                       case 'i':       goto yy361;
+                       default:        goto yy55;
+                       }
+yy308:
+                       yyaccept = 30;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -3335,16 +4438,61 @@ yy257:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy258;
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy309;
                        }
-yy258:
-#line 357 "src/parser.re"
-                       {RETURN(PSI_T_ZVAL);}
-#line 3346 "src/parser.c"
-yy259:
-                       yyaccept = 21;
+yy309:
+#line 350 "src/parser.re"
+                       { NEWTOKEN(PSI_T_IFDEF); goto start; }
+#line 4449 "src/parser.c"
+yy310:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'F':
+                       case 'f':       goto yy362;
+                       default:        goto yy55;
+                       }
+yy311:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case '_':       goto yy364;
+                       default:        goto yy55;
+                       }
+yy312:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case '_':       goto yy365;
+                       default:        goto yy55;
+                       }
+yy313:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case '_':       goto yy366;
+                       default:        goto yy55;
+                       }
+yy314:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'T':
+                       case 't':       goto yy367;
+                       default:        goto yy55;
+                       }
+yy315:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'L':
+                       case 'l':       goto yy369;
+                       default:        goto yy55;
+                       }
+yy316:
+                       yyaccept = 31;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -3409,56 +4557,64 @@ yy259:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy260;
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy317;
                        }
-yy260:
-#line 331 "src/parser.re"
-                       {RETURN(PSI_T_ARRAY);}
-#line 3420 "src/parser.c"
-yy261:
-                       yyaccept = 5;
+yy317:
+#line 363 "src/parser.re"
+                       { NEWTOKEN(PSI_T_MIXED); goto start; }
+#line 4568 "src/parser.c"
+yy318:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'T':
+                       case 't':       goto yy371;
+                       default:        goto yy55;
+                       }
+yy319:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'L':
-                       case 'l':       goto yy311;
-                       default:        goto yy54;
+                       case 'l':       goto yy373;
+                       default:        goto yy55;
                        }
-yy262:
-                       yyaccept = 5;
+yy320:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'A':
-                       case 'a':       goto yy313;
-                       default:        goto yy54;
+                       case 'a':       goto yy375;
+                       default:        goto yy55;
                        }
-yy263:
-                       yyaccept = 5;
+yy321:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
-                       case 'B':
-                       case 'b':       goto yy314;
-                       default:        goto yy54;
+                       case 'A':
+                       case 'a':       goto yy376;
+                       default:        goto yy55;
                        }
-yy264:
-                       yyaccept = 5;
+yy322:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
-                       case 'A':
-                       case 'a':       goto yy315;
-                       default:        goto yy54;
+                       case 'S':
+                       case 's':       goto yy377;
+                       default:        goto yy55;
                        }
-yy265:
-                       yyaccept = 5;
+yy323:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
-                       case 'C':
-                       case 'c':       goto yy316;
-                       default:        goto yy54;
+                       case 'N':
+                       case 'n':       goto yy378;
+                       default:        goto yy55;
                        }
-yy266:
-                       yyaccept = 22;
+yy324:
+                       yyaccept = 32;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -3523,16 +4679,148 @@ yy266:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy267;
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy325;
                        }
-yy267:
-#line 340 "src/parser.re"
-                       {RETURN(PSI_T_CONST);}
-#line 3534 "src/parser.c"
-yy268:
-                       yyaccept = 23;
+yy325:
+#line 368 "src/parser.re"
+                       { NEWTOKEN(PSI_T_SHORT); goto start; }
+#line 4690 "src/parser.c"
+yy326:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'D':
+                       case 'd':       goto yy380;
+                       default:        goto yy55;
+                       }
+yy327:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'C':
+                       case 'c':       goto yy382;
+                       default:        goto yy55;
+                       }
+yy328:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'G':
+                       case 'g':       goto yy384;
+                       default:        goto yy55;
+                       }
+yy329:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'N':
+                       case 'n':       goto yy386;
+                       default:        goto yy55;
+                       }
+yy330:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'T':
+                       case 't':       goto yy388;
+                       default:        goto yy55;
+                       }
+yy331:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'L':
+                       case 'l':       goto yy390;
+                       default:        goto yy55;
+                       }
+yy332:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'R':
+                       case 'r':       goto yy392;
+                       default:        goto yy55;
+                       }
+yy333:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'O':
+                       case 'o':       goto yy393;
+                       default:        goto yy55;
+                       }
+yy334:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'O':
+                       case 'o':       goto yy394;
+                       default:        goto yy55;
+                       }
+yy335:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'T':
+                       case 't':       goto yy395;
+                       default:        goto yy55;
+                       }
+yy336:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'J':
+                       case 'j':       goto yy397;
+                       default:        goto yy55;
+                       }
+yy337:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'R':
+                       case 'r':       goto yy398;
+                       default:        goto yy55;
+                       }
+yy338:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'E':
+                       case 'e':       goto yy399;
+                       default:        goto yy55;
+                       }
+yy339:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case '6':       goto yy400;
+                       default:        goto yy55;
+                       }
+yy340:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case '2':       goto yy401;
+                       default:        goto yy55;
+                       }
+yy341:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case '4':       goto yy402;
+                       default:        goto yy55;
+                       }
+yy342:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case '_':       goto yy403;
+                       default:        goto yy55;
+                       }
+yy343:
+                       yyaccept = 33;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -3597,24 +4885,16 @@ yy268:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy269;
-                       }
-yy269:
-#line 358 "src/parser.re"
-                       {RETURN(PSI_T_COUNT);}
-#line 3608 "src/parser.c"
-yy270:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'E':
-                       case 'e':       goto yy318;
-                       default:        goto yy54;
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy344;
                        }
-yy271:
-                       yyaccept = 24;
+yy344:
+#line 357 "src/parser.re"
+                       { NEWTOKEN(PSI_T_UNDEF); goto start; }
+#line 4896 "src/parser.c"
+yy345:
+                       yyaccept = 34;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -3679,16 +4959,32 @@ yy271:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy272;
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy346;
                        }
-yy272:
-#line 308 "src/parser.re"
-                       {RETURN(PSI_T_FALSE);}
-#line 3690 "src/parser.c"
-yy273:
-                       yyaccept = 25;
+yy346:
+#line 391 "src/parser.re"
+                       { NEWTOKEN(PSI_T_UNION); goto start; }
+#line 4970 "src/parser.c"
+yy347:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'N':
+                       case 'n':       goto yy404;
+                       default:        goto yy55;
+                       }
+yy348:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'N':
+                       case 'n':       goto yy405;
+                       default:        goto yy55;
+                       }
+yy349:
+                       yyaccept = 35;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -3722,6 +5018,7 @@ yy273:
                        case 'S':
                        case 'T':
                        case 'U':
+                       case 'V':
                        case 'W':
                        case 'X':
                        case 'Y':
@@ -3748,66 +5045,44 @@ yy273:
                        case 's':
                        case 't':
                        case 'u':
+                       case 'v':
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case 'V':
-                       case 'v':       goto yy320;
-                       case '\\':      goto yy114;
-                       default:        goto yy274;
-                       }
-yy274:
-#line 318 "src/parser.re"
-                       {RETURN(PSI_T_FLOAT);}
-#line 3764 "src/parser.c"
-yy275:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'I':
-                       case 'i':       goto yy321;
-                       default:        goto yy54;
-                       }
-yy276:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case '_':       goto yy322;
-                       default:        goto yy54;
-                       }
-yy277:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case '_':       goto yy323;
-                       default:        goto yy54;
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy350;
                        }
-yy278:
-                       yyaccept = 5;
+yy350:
+#line 408 "src/parser.re"
+                       { NEWTOKEN(PSI_T_ARRVAL); goto start; }
+#line 5060 "src/parser.c"
+yy351:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
-                       case '_':       goto yy324;
-                       default:        goto yy54;
+                       case 'L':
+                       case 'l':       goto yy406;
+                       default:        goto yy55;
                        }
-yy279:
-                       yyaccept = 5;
+yy352:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
-                       case 'T':
-                       case 't':       goto yy325;
-                       default:        goto yy54;
+                       case 'L':
+                       case 'l':       goto yy408;
+                       default:        goto yy55;
                        }
-yy280:
-                       yyaccept = 5;
+yy353:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
-                       case 'L':
-                       case 'l':       goto yy327;
-                       default:        goto yy54;
+                       case 'C':
+                       case 'c':       goto yy409;
+                       default:        goto yy55;
                        }
-yy281:
-                       yyaccept = 26;
+yy354:
+                       yyaccept = 36;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -3863,73 +5138,25 @@ yy281:
                        case 'n':
                        case 'o':
                        case 'p':
-                       case 'q':
-                       case 'r':
-                       case 's':
-                       case 't':
-                       case 'u':
-                       case 'v':
-                       case 'w':
-                       case 'x':
-                       case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy282;
-                       }
-yy282:
-#line 310 "src/parser.re"
-                       {RETURN(PSI_T_MIXED);}
-#line 3883 "src/parser.c"
-yy283:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'T':
-                       case 't':       goto yy329;
-                       default:        goto yy54;
-                       }
-yy284:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'L':
-                       case 'l':       goto yy331;
-                       default:        goto yy54;
-                       }
-yy285:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'A':
-                       case 'a':       goto yy333;
-                       default:        goto yy54;
-                       }
-yy286:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'A':
-                       case 'a':       goto yy334;
-                       default:        goto yy54;
-                       }
-yy287:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'S':
-                       case 's':       goto yy335;
-                       default:        goto yy54;
-                       }
-yy288:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'N':
-                       case 'n':       goto yy336;
-                       default:        goto yy54;
+                       case 'q':
+                       case 'r':
+                       case 's':
+                       case 't':
+                       case 'u':
+                       case 'v':
+                       case 'w':
+                       case 'x':
+                       case 'y':
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy355;
                        }
-yy289:
-                       yyaccept = 27;
+yy355:
+#line 412 "src/parser.re"
+                       { NEWTOKEN(PSI_T_CALLOC); goto start; }
+#line 5158 "src/parser.c"
+yy356:
+                       yyaccept = 37;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -3945,7 +5172,6 @@ yy289:
                        case 'A':
                        case 'B':
                        case 'C':
-                       case 'D':
                        case 'E':
                        case 'F':
                        case 'G':
@@ -3972,7 +5198,6 @@ yy289:
                        case 'a':
                        case 'b':
                        case 'c':
-                       case 'd':
                        case 'e':
                        case 'f':
                        case 'g':
@@ -3994,148 +5219,18 @@ yy289:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy290;
-                       }
-yy290:
-#line 315 "src/parser.re"
-                       {RETURN(PSI_T_SHORT);}
-#line 4005 "src/parser.c"
-yy291:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
+                       case 'z':       goto yy54;
                        case 'D':
-                       case 'd':       goto yy338;
-                       default:        goto yy54;
-                       }
-yy292:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'C':
-                       case 'c':       goto yy340;
-                       default:        goto yy54;
-                       }
-yy293:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'G':
-                       case 'g':       goto yy342;
-                       default:        goto yy54;
-                       }
-yy294:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'N':
-                       case 'n':       goto yy344;
-                       default:        goto yy54;
-                       }
-yy295:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'T':
-                       case 't':       goto yy346;
-                       default:        goto yy54;
-                       }
-yy296:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'L':
-                       case 'l':       goto yy348;
-                       default:        goto yy54;
-                       }
-yy297:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'R':
-                       case 'r':       goto yy350;
-                       default:        goto yy54;
-                       }
-yy298:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'O':
-                       case 'o':       goto yy351;
-                       default:        goto yy54;
-                       }
-yy299:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'O':
-                       case 'o':       goto yy352;
-                       default:        goto yy54;
-                       }
-yy300:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'T':
-                       case 't':       goto yy353;
-                       default:        goto yy54;
-                       }
-yy301:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'J':
-                       case 'j':       goto yy355;
-                       default:        goto yy54;
-                       }
-yy302:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'R':
-                       case 'r':       goto yy356;
-                       default:        goto yy54;
-                       }
-yy303:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'E':
-                       case 'e':       goto yy357;
-                       default:        goto yy54;
+                       case 'd':       goto yy410;
+                       case '\\':      goto yy115;
+                       default:        goto yy357;
                        }
-yy304:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case '6':       goto yy358;
-                       default:        goto yy54;
-                       }
-yy305:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case '2':       goto yy359;
-                       default:        goto yy54;
-                       }
-yy306:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case '4':       goto yy360;
-                       default:        goto yy54;
-                       }
-yy307:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case '_':       goto yy361;
-                       default:        goto yy54;
-                       }
-yy308:
-                       yyaccept = 28;
+yy357:
+#line 355 "src/parser.re"
+                       { NEWTOKEN(PSI_T_DEFINE); goto start; }
+#line 5232 "src/parser.c"
+yy358:
+                       yyaccept = 38;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -4200,24 +5295,32 @@ yy308:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy309;
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy359;
                        }
-yy309:
-#line 338 "src/parser.re"
-                       {RETURN(PSI_T_UNION);}
-#line 4211 "src/parser.c"
-yy310:
-                       yyaccept = 5;
+yy359:
+#line 372 "src/parser.re"
+                       { NEWTOKEN(PSI_T_DOUBLE); goto start; }
+#line 5306 "src/parser.c"
+yy360:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
-                       case 'N':
-                       case 'n':       goto yy362;
-                       default:        goto yy54;
+                       case 'A':
+                       case 'a':       goto yy412;
+                       default:        goto yy55;
                        }
-yy311:
-                       yyaccept = 29;
+yy361:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'O':
+                       case 'o':       goto yy413;
+                       default:        goto yy55;
+                       }
+yy362:
+                       yyaccept = 39;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -4282,40 +5385,40 @@ yy311:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy312;
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy363;
                        }
-yy312:
-#line 355 "src/parser.re"
-                       {RETURN(PSI_T_ARRVAL);}
-#line 4293 "src/parser.c"
-yy313:
-                       yyaccept = 5;
+yy363:
+#line 351 "src/parser.re"
+                       { NEWTOKEN(PSI_T_IFNDEF); goto start; }
+#line 5396 "src/parser.c"
+yy364:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
-                       case 'L':
-                       case 'l':       goto yy363;
-                       default:        goto yy54;
+                       case 'T':
+                       case 't':       goto yy414;
+                       default:        goto yy55;
                        }
-yy314:
-                       yyaccept = 5;
+yy365:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
-                       case 'L':
-                       case 'l':       goto yy365;
-                       default:        goto yy54;
+                       case 'T':
+                       case 't':       goto yy416;
+                       default:        goto yy55;
                        }
-yy315:
-                       yyaccept = 5;
+yy366:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
-                       case 'C':
-                       case 'c':       goto yy366;
-                       default:        goto yy54;
+                       case 'T':
+                       case 't':       goto yy418;
+                       default:        goto yy55;
                        }
-yy316:
-                       yyaccept = 30;
+yy367:
+                       yyaccept = 40;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -4380,16 +5483,16 @@ yy316:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy317;
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy368;
                        }
-yy317:
-#line 359 "src/parser.re"
-                       {RETURN(PSI_T_CALLOC);}
-#line 4391 "src/parser.c"
-yy318:
-                       yyaccept = 31;
+yy368:
+#line 373 "src/parser.re"
+                       { NEWTOKEN(PSI_T_INT8); goto start; }
+#line 5494 "src/parser.c"
+yy369:
+                       yyaccept = 41;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -4454,56 +5557,16 @@ yy318:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy319;
-                       }
-yy319:
-#line 319 "src/parser.re"
-                       {RETURN(PSI_T_DOUBLE);}
-#line 4465 "src/parser.c"
-yy320:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'A':
-                       case 'a':       goto yy367;
-                       default:        goto yy54;
-                       }
-yy321:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'O':
-                       case 'o':       goto yy368;
-                       default:        goto yy54;
-                       }
-yy322:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'T':
-                       case 't':       goto yy369;
-                       default:        goto yy54;
-                       }
-yy323:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'T':
-                       case 't':       goto yy371;
-                       default:        goto yy54;
-                       }
-yy324:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'T':
-                       case 't':       goto yy373;
-                       default:        goto yy54;
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy370;
                        }
-yy325:
-                       yyaccept = 32;
+yy370:
+#line 405 "src/parser.re"
+                       { NEWTOKEN(PSI_T_INTVAL); goto start; }
+#line 5568 "src/parser.c"
+yy371:
+                       yyaccept = 42;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -4568,16 +5631,16 @@ yy325:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy326;
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy372;
                        }
-yy326:
-#line 320 "src/parser.re"
-                       {RETURN(PSI_T_INT8);}
-#line 4579 "src/parser.c"
-yy327:
-                       yyaccept = 33;
+yy372:
+#line 385 "src/parser.re"
+                       { NEWTOKEN(PSI_T_OBJECT); goto start; }
+#line 5642 "src/parser.c"
+yy373:
+                       yyaccept = 43;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -4642,16 +5705,40 @@ yy327:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy328;
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy374;
                        }
-yy328:
-#line 352 "src/parser.re"
-                       {RETURN(PSI_T_INTVAL);}
-#line 4653 "src/parser.c"
-yy329:
-                       yyaccept = 34;
+yy374:
+#line 409 "src/parser.re"
+                       { NEWTOKEN(PSI_T_OBJVAL); goto start; }
+#line 5716 "src/parser.c"
+yy375:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'L':
+                       case 'l':       goto yy420;
+                       default:        goto yy55;
+                       }
+yy376:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'S':
+                       case 's':       goto yy422;
+                       default:        goto yy55;
+                       }
+yy377:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'S':
+                       case 's':       goto yy423;
+                       default:        goto yy55;
+                       }
+yy378:
+                       yyaccept = 44;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -4716,16 +5803,16 @@ yy329:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy330;
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy379;
                        }
-yy330:
-#line 332 "src/parser.re"
-                       {RETURN(PSI_T_OBJECT);}
-#line 4727 "src/parser.c"
-yy331:
-                       yyaccept = 35;
+yy379:
+#line 399 "src/parser.re"
+                       { NEWTOKEN(PSI_T_RETURN); goto start; }
+#line 5814 "src/parser.c"
+yy380:
+                       yyaccept = 45;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -4790,40 +5877,16 @@ yy331:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy332;
-                       }
-yy332:
-#line 356 "src/parser.re"
-                       {RETURN(PSI_T_OBJVAL);}
-#line 4801 "src/parser.c"
-yy333:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'L':
-                       case 'l':       goto yy375;
-                       default:        goto yy54;
-                       }
-yy334:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'S':
-                       case 's':       goto yy377;
-                       default:        goto yy54;
-                       }
-yy335:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'S':
-                       case 's':       goto yy378;
-                       default:        goto yy54;
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy381;
                        }
-yy336:
-                       yyaccept = 36;
+yy381:
+#line 382 "src/parser.re"
+                       { NEWTOKEN(PSI_T_SIGNED); goto start; }
+#line 5888 "src/parser.c"
+yy382:
+                       yyaccept = 46;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -4888,16 +5951,16 @@ yy336:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy337;
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy383;
                        }
-yy337:
-#line 346 "src/parser.re"
-                       {RETURN(PSI_T_RETURN);}
-#line 4899 "src/parser.c"
-yy338:
-                       yyaccept = 37;
+yy383:
+#line 387 "src/parser.re"
+                       { NEWTOKEN(PSI_T_STATIC); goto start; }
+#line 5962 "src/parser.c"
+yy384:
+                       yyaccept = 47;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -4962,16 +6025,16 @@ yy338:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy339;
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy385;
                        }
-yy339:
-#line 329 "src/parser.re"
-                       {RETURN(PSI_T_SIGNED);}
-#line 4973 "src/parser.c"
-yy340:
-                       yyaccept = 38;
+yy385:
+#line 383 "src/parser.re"
+                       { NEWTOKEN(PSI_T_STRING); goto start; }
+#line 6036 "src/parser.c"
+yy386:
+                       yyaccept = 48;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -5036,16 +6099,16 @@ yy340:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy341;
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy387;
                        }
-yy341:
-#line 334 "src/parser.re"
-                       {RETURN(PSI_T_STATIC);}
-#line 5047 "src/parser.c"
-yy342:
-                       yyaccept = 39;
+yy387:
+#line 402 "src/parser.re"
+                       { NEWTOKEN(PSI_T_STRLEN); goto start; }
+#line 6110 "src/parser.c"
+yy388:
+                       yyaccept = 49;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -5110,16 +6173,16 @@ yy342:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy343;
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy389;
                        }
-yy343:
-#line 330 "src/parser.re"
-                       {RETURN(PSI_T_STRING);}
-#line 5121 "src/parser.c"
-yy344:
-                       yyaccept = 40;
+yy389:
+#line 390 "src/parser.re"
+                       { NEWTOKEN(PSI_T_STRUCT); goto start; }
+#line 6184 "src/parser.c"
+yy390:
+                       yyaccept = 50;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -5184,16 +6247,40 @@ yy344:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy345;
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy391;
                        }
-yy345:
-#line 349 "src/parser.re"
-                       {RETURN(PSI_T_STRLEN);}
-#line 5195 "src/parser.c"
-yy346:
-                       yyaccept = 41;
+yy391:
+#line 403 "src/parser.re"
+                       { NEWTOKEN(PSI_T_STRVAL); goto start; }
+#line 6258 "src/parser.c"
+yy392:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'A':
+                       case 'a':       goto yy424;
+                       default:        goto yy55;
+                       }
+yy393:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'L':
+                       case 'l':       goto yy425;
+                       default:        goto yy55;
+                       }
+yy394:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'A':
+                       case 'a':       goto yy427;
+                       default:        goto yy55;
+                       }
+yy395:
+                       yyaccept = 51;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -5258,16 +6345,85 @@ yy346:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy347;
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy396;
                        }
-yy347:
-#line 337 "src/parser.re"
-                       {RETURN(PSI_T_STRUCT);}
-#line 5269 "src/parser.c"
-yy348:
-                       yyaccept = 42;
+yy396:
+#line 416 "src/parser.re"
+                       { NEWTOKEN(PSI_T_TO_INT); goto start; }
+#line 6356 "src/parser.c"
+yy397:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'E':
+                       case 'e':       goto yy428;
+                       default:        goto yy55;
+                       }
+yy398:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'I':
+                       case 'i':       goto yy429;
+                       default:        goto yy55;
+                       }
+yy399:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'F':
+                       case 'f':       goto yy430;
+                       default:        goto yy55;
+                       }
+yy400:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case '_':       goto yy432;
+                       default:        goto yy55;
+                       }
+yy401:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case '_':       goto yy433;
+                       default:        goto yy55;
+                       }
+yy402:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case '_':       goto yy434;
+                       default:        goto yy55;
+                       }
+yy403:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'T':
+                       case 't':       goto yy435;
+                       default:        goto yy55;
+                       }
+yy404:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'E':
+                       case 'e':       goto yy437;
+                       default:        goto yy55;
+                       }
+yy405:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'G':
+                       case 'g':       goto yy438;
+                       default:        goto yy55;
+                       }
+yy406:
+                       yyaccept = 52;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -5332,40 +6488,32 @@ yy348:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy349;
-                       }
-yy349:
-#line 350 "src/parser.re"
-                       {RETURN(PSI_T_STRVAL);}
-#line 5343 "src/parser.c"
-yy350:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'A':
-                       case 'a':       goto yy379;
-                       default:        goto yy54;
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy407;
                        }
-yy351:
-                       yyaccept = 5;
+yy407:
+#line 407 "src/parser.re"
+                       { NEWTOKEN(PSI_T_BOOLVAL); goto start; }
+#line 6499 "src/parser.c"
+yy408:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
-                       case 'L':
-                       case 'l':       goto yy380;
-                       default:        goto yy54;
+                       case 'E':
+                       case 'e':       goto yy440;
+                       default:        goto yy55;
                        }
-yy352:
-                       yyaccept = 5;
+yy409:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
-                       case 'A':
-                       case 'a':       goto yy382;
-                       default:        goto yy54;
+                       case 'K':
+                       case 'k':       goto yy442;
+                       default:        goto yy55;
                        }
-yy353:
-                       yyaccept = 43;
+yy410:
+                       yyaccept = 53;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -5430,77 +6578,32 @@ yy353:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy354;
-                       }
-yy354:
-#line 363 "src/parser.re"
-                       {RETURN(PSI_T_TO_INT);}
-#line 5441 "src/parser.c"
-yy355:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'E':
-                       case 'e':       goto yy383;
-                       default:        goto yy54;
-                       }
-yy356:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'I':
-                       case 'i':       goto yy384;
-                       default:        goto yy54;
-                       }
-yy357:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'F':
-                       case 'f':       goto yy385;
-                       default:        goto yy54;
-                       }
-yy358:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case '_':       goto yy387;
-                       default:        goto yy54;
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy411;
                        }
-yy359:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case '_':       goto yy388;
-                       default:        goto yy54;
-                       }
-yy360:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case '_':       goto yy389;
-                       default:        goto yy54;
-                       }
-yy361:
-                       yyaccept = 5;
+yy411:
+#line 356 "src/parser.re"
+                       { NEWTOKEN(PSI_T_DEFINED); goto start; }
+#line 6589 "src/parser.c"
+yy412:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
-                       case 'T':
-                       case 't':       goto yy390;
-                       default:        goto yy54;
+                       case 'L':
+                       case 'l':       goto yy444;
+                       default:        goto yy55;
                        }
-yy362:
-                       yyaccept = 5;
+yy413:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
-                       case 'E':
-                       case 'e':       goto yy392;
-                       default:        goto yy54;
+                       case 'N':
+                       case 'n':       goto yy446;
+                       default:        goto yy55;
                        }
-yy363:
-                       yyaccept = 44;
+yy414:
+                       yyaccept = 54;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -5555,58 +6658,26 @@ yy363:
                        case 'm':
                        case 'n':
                        case 'o':
-                       case 'p':
-                       case 'q':
-                       case 'r':
-                       case 's':
-                       case 't':
-                       case 'u':
-                       case 'v':
-                       case 'w':
-                       case 'x':
-                       case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy364;
-                       }
-yy364:
-#line 354 "src/parser.re"
-                       {RETURN(PSI_T_BOOLVAL);}
-#line 5576 "src/parser.c"
-yy365:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'E':
-                       case 'e':       goto yy393;
-                       default:        goto yy54;
-                       }
-yy366:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'K':
-                       case 'k':       goto yy395;
-                       default:        goto yy54;
-                       }
-yy367:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'L':
-                       case 'l':       goto yy397;
-                       default:        goto yy54;
-                       }
-yy368:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'N':
-                       case 'n':       goto yy399;
-                       default:        goto yy54;
+                       case 'p':
+                       case 'q':
+                       case 'r':
+                       case 's':
+                       case 't':
+                       case 'u':
+                       case 'v':
+                       case 'w':
+                       case 'x':
+                       case 'y':
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy415;
                        }
-yy369:
-                       yyaccept = 45;
+yy415:
+#line 375 "src/parser.re"
+                       { NEWTOKEN(PSI_T_INT16); goto start; }
+#line 6679 "src/parser.c"
+yy416:
+                       yyaccept = 55;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -5671,16 +6742,16 @@ yy369:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy370;
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy417;
                        }
-yy370:
-#line 322 "src/parser.re"
-                       {RETURN(PSI_T_INT16);}
-#line 5682 "src/parser.c"
-yy371:
-                       yyaccept = 46;
+yy417:
+#line 377 "src/parser.re"
+                       { NEWTOKEN(PSI_T_INT32); goto start; }
+#line 6753 "src/parser.c"
+yy418:
+                       yyaccept = 56;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -5745,16 +6816,16 @@ yy371:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy372;
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy419;
                        }
-yy372:
-#line 324 "src/parser.re"
-                       {RETURN(PSI_T_INT32);}
-#line 5756 "src/parser.c"
-yy373:
-                       yyaccept = 47;
+yy419:
+#line 379 "src/parser.re"
+                       { NEWTOKEN(PSI_T_INT64); goto start; }
+#line 6827 "src/parser.c"
+yy420:
+                       yyaccept = 57;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -5819,16 +6890,40 @@ yy373:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy374;
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy421;
                        }
-yy374:
-#line 326 "src/parser.re"
-                       {RETURN(PSI_T_INT64);}
-#line 5830 "src/parser.c"
-yy375:
-                       yyaccept = 48;
+yy421:
+#line 404 "src/parser.re"
+                       { NEWTOKEN(PSI_T_PATHVAL); goto start; }
+#line 6901 "src/parser.c"
+yy422:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'S':
+                       case 's':       goto yy448;
+                       default:        goto yy55;
+                       }
+yy423:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'E':
+                       case 'e':       goto yy449;
+                       default:        goto yy55;
+                       }
+yy424:
+                       yyaccept = 4;
+                       yych = *(P->mrk = ++P->cur);
+                       switch (yych) {
+                       case 'Y':
+                       case 'y':       goto yy450;
+                       default:        goto yy55;
+                       }
+yy425:
+                       yyaccept = 58;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -5893,40 +6988,40 @@ yy375:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy376;
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy426;
                        }
-yy376:
-#line 351 "src/parser.re"
-                       {RETURN(PSI_T_PATHVAL);}
-#line 5904 "src/parser.c"
-yy377:
-                       yyaccept = 5;
+yy426:
+#line 418 "src/parser.re"
+                       { NEWTOKEN(PSI_T_TO_BOOL); goto start; }
+#line 6999 "src/parser.c"
+yy427:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
-                       case 'S':
-                       case 's':       goto yy401;
-                       default:        goto yy54;
+                       case 'T':
+                       case 't':       goto yy452;
+                       default:        goto yy55;
                        }
-yy378:
-                       yyaccept = 5;
+yy428:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
-                       case 'E':
-                       case 'e':       goto yy402;
-                       default:        goto yy54;
+                       case 'C':
+                       case 'c':       goto yy454;
+                       default:        goto yy55;
                        }
-yy379:
-                       yyaccept = 5;
+yy429:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
-                       case 'Y':
-                       case 'y':       goto yy403;
-                       default:        goto yy54;
+                       case 'N':
+                       case 'n':       goto yy455;
+                       default:        goto yy55;
                        }
-yy380:
-                       yyaccept = 49;
+yy430:
+                       yyaccept = 59;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -5991,40 +7086,40 @@ yy380:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy381;
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy431;
                        }
-yy381:
-#line 365 "src/parser.re"
-                       {RETURN(PSI_T_TO_BOOL);}
-#line 6002 "src/parser.c"
-yy382:
-                       yyaccept = 5;
+yy431:
+#line 389 "src/parser.re"
+                       { NEWTOKEN(PSI_T_TYPEDEF); goto start; }
+#line 7097 "src/parser.c"
+yy432:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'T':
-                       case 't':       goto yy405;
-                       default:        goto yy54;
+                       case 't':       goto yy456;
+                       default:        goto yy55;
                        }
-yy383:
-                       yyaccept = 5;
+yy433:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
-                       case 'C':
-                       case 'c':       goto yy407;
-                       default:        goto yy54;
+                       case 'T':
+                       case 't':       goto yy458;
+                       default:        goto yy55;
                        }
-yy384:
-                       yyaccept = 5;
+yy434:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
-                       case 'N':
-                       case 'n':       goto yy408;
-                       default:        goto yy54;
+                       case 'T':
+                       case 't':       goto yy460;
+                       default:        goto yy55;
                        }
-yy385:
-                       yyaccept = 50;
+yy435:
+                       yyaccept = 60;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -6089,40 +7184,24 @@ yy385:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy386;
-                       }
-yy386:
-#line 336 "src/parser.re"
-                       {RETURN(PSI_T_TYPEDEF);}
-#line 6100 "src/parser.c"
-yy387:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'T':
-                       case 't':       goto yy409;
-                       default:        goto yy54;
-                       }
-yy388:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'T':
-                       case 't':       goto yy411;
-                       default:        goto yy54;
-                       }
-yy389:
-                       yyaccept = 5;
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy436;
+                       }
+yy436:
+#line 374 "src/parser.re"
+                       { NEWTOKEN(PSI_T_UINT8); goto start; }
+#line 7195 "src/parser.c"
+yy437:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
-                       case 'T':
-                       case 't':       goto yy413;
-                       default:        goto yy54;
+                       case 'D':
+                       case 'd':       goto yy462;
+                       default:        goto yy55;
                        }
-yy390:
-                       yyaccept = 51;
+yy438:
+                       yyaccept = 61;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -6187,24 +7266,16 @@ yy390:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy391;
-                       }
-yy391:
-#line 321 "src/parser.re"
-                       {RETURN(PSI_T_UINT8);}
-#line 6198 "src/parser.c"
-yy392:
-                       yyaccept = 5;
-                       yych = *(P->mrk = ++P->cur);
-                       switch (yych) {
-                       case 'D':
-                       case 'd':       goto yy415;
-                       default:        goto yy54;
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy439;
                        }
-yy393:
-                       yyaccept = 52;
+yy439:
+#line 358 "src/parser.re"
+                       { NEWTOKEN(PSI_T_WARNING); goto start; }
+#line 7277 "src/parser.c"
+yy440:
+                       yyaccept = 62;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -6269,16 +7340,16 @@ yy393:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy394;
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy441;
                        }
-yy394:
-#line 311 "src/parser.re"
-                       {RETURN(PSI_T_CALLABLE);}
-#line 6280 "src/parser.c"
-yy395:
-                       yyaccept = 53;
+yy441:
+#line 364 "src/parser.re"
+                       { NEWTOKEN(PSI_T_CALLABLE); goto start; }
+#line 7351 "src/parser.c"
+yy442:
+                       yyaccept = 63;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -6343,16 +7414,16 @@ yy395:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy396;
-                       }
-yy396:
-#line 333 "src/parser.re"
-                       {RETURN(PSI_T_CALLBACK);}
-#line 6354 "src/parser.c"
-yy397:
-                       yyaccept = 54;
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy443;
+                       }
+yy443:
+#line 386 "src/parser.re"
+                       { NEWTOKEN(PSI_T_CALLBACK); goto start; }
+#line 7425 "src/parser.c"
+yy444:
+                       yyaccept = 64;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -6417,16 +7488,16 @@ yy397:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy398;
-                       }
-yy398:
-#line 353 "src/parser.re"
-                       {RETURN(PSI_T_FLOATVAL);}
-#line 6428 "src/parser.c"
-yy399:
-                       yyaccept = 55;
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy445;
+                       }
+yy445:
+#line 406 "src/parser.re"
+                       { NEWTOKEN(PSI_T_FLOATVAL); goto start; }
+#line 7499 "src/parser.c"
+yy446:
+                       yyaccept = 65;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -6491,32 +7562,32 @@ yy399:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy400;
-                       }
-yy400:
-#line 335 "src/parser.re"
-                       {RETURN(PSI_T_FUNCTION);}
-#line 6502 "src/parser.c"
-yy401:
-                       yyaccept = 5;
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy447;
+                       }
+yy447:
+#line 388 "src/parser.re"
+                       { NEWTOKEN(PSI_T_FUNCTION); goto start; }
+#line 7573 "src/parser.c"
+yy448:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'E':
-                       case 'e':       goto yy417;
-                       default:        goto yy54;
+                       case 'e':       goto yy464;
+                       default:        goto yy55;
                        }
-yy402:
-                       yyaccept = 5;
+yy449:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'R':
-                       case 'r':       goto yy418;
-                       default:        goto yy54;
+                       case 'r':       goto yy465;
+                       default:        goto yy55;
                        }
-yy403:
-                       yyaccept = 56;
+yy450:
+                       yyaccept = 66;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -6581,16 +7652,16 @@ yy403:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy404;
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy451;
                        }
-yy404:
-#line 361 "src/parser.re"
-                       {RETURN(PSI_T_TO_ARRAY);}
-#line 6592 "src/parser.c"
-yy405:
-                       yyaccept = 57;
+yy451:
+#line 414 "src/parser.re"
+                       { NEWTOKEN(PSI_T_TO_ARRAY); goto start; }
+#line 7663 "src/parser.c"
+yy452:
+                       yyaccept = 67;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -6655,32 +7726,32 @@ yy405:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy406;
-                       }
-yy406:
-#line 364 "src/parser.re"
-                       {RETURN(PSI_T_TO_FLOAT);}
-#line 6666 "src/parser.c"
-yy407:
-                       yyaccept = 5;
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy453;
+                       }
+yy453:
+#line 417 "src/parser.re"
+                       { NEWTOKEN(PSI_T_TO_FLOAT); goto start; }
+#line 7737 "src/parser.c"
+yy454:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'T':
-                       case 't':       goto yy419;
-                       default:        goto yy54;
+                       case 't':       goto yy466;
+                       default:        goto yy55;
                        }
-yy408:
-                       yyaccept = 5;
+yy455:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'G':
-                       case 'g':       goto yy421;
-                       default:        goto yy54;
+                       case 'g':       goto yy468;
+                       default:        goto yy55;
                        }
-yy409:
-                       yyaccept = 58;
+yy456:
+                       yyaccept = 68;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -6745,16 +7816,16 @@ yy409:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy410;
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy457;
                        }
-yy410:
-#line 323 "src/parser.re"
-                       {RETURN(PSI_T_UINT16);}
-#line 6756 "src/parser.c"
-yy411:
-                       yyaccept = 59;
+yy457:
+#line 376 "src/parser.re"
+                       { NEWTOKEN(PSI_T_UINT16); goto start; }
+#line 7827 "src/parser.c"
+yy458:
+                       yyaccept = 69;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -6819,16 +7890,16 @@ yy411:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy412;
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy459;
                        }
-yy412:
-#line 325 "src/parser.re"
-                       {RETURN(PSI_T_UINT32);}
-#line 6830 "src/parser.c"
-yy413:
-                       yyaccept = 60;
+yy459:
+#line 378 "src/parser.re"
+                       { NEWTOKEN(PSI_T_UINT32); goto start; }
+#line 7901 "src/parser.c"
+yy460:
+                       yyaccept = 70;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -6893,16 +7964,16 @@ yy413:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy414;
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy461;
                        }
-yy414:
-#line 327 "src/parser.re"
-                       {RETURN(PSI_T_UINT64);}
-#line 6904 "src/parser.c"
-yy415:
-                       yyaccept = 61;
+yy461:
+#line 380 "src/parser.re"
+                       { NEWTOKEN(PSI_T_UINT64); goto start; }
+#line 7975 "src/parser.c"
+yy462:
+                       yyaccept = 71;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -6967,32 +8038,32 @@ yy415:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy416;
-                       }
-yy416:
-#line 328 "src/parser.re"
-                       {RETURN(PSI_T_UNSIGNED);}
-#line 6978 "src/parser.c"
-yy417:
-                       yyaccept = 5;
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy463;
+                       }
+yy463:
+#line 381 "src/parser.re"
+                       { NEWTOKEN(PSI_T_UNSIGNED); goto start; }
+#line 8049 "src/parser.c"
+yy464:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'R':
-                       case 'r':       goto yy423;
-                       default:        goto yy54;
+                       case 'r':       goto yy470;
+                       default:        goto yy55;
                        }
-yy418:
-                       yyaccept = 5;
+yy465:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'T':
-                       case 't':       goto yy424;
-                       default:        goto yy54;
+                       case 't':       goto yy471;
+                       default:        goto yy55;
                        }
-yy419:
-                       yyaccept = 62;
+yy466:
+                       yyaccept = 72;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -7057,16 +8128,16 @@ yy419:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy420;
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy467;
                        }
-yy420:
-#line 360 "src/parser.re"
-                       {RETURN(PSI_T_TO_OBJECT);}
-#line 7068 "src/parser.c"
-yy421:
-                       yyaccept = 63;
+yy467:
+#line 413 "src/parser.re"
+                       { NEWTOKEN(PSI_T_TO_OBJECT); goto start; }
+#line 8139 "src/parser.c"
+yy468:
+                       yyaccept = 73;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -7131,24 +8202,24 @@ yy421:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy422;
-                       }
-yy422:
-#line 362 "src/parser.re"
-                       {RETURN(PSI_T_TO_STRING);}
-#line 7142 "src/parser.c"
-yy423:
-                       yyaccept = 5;
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy469;
+                       }
+yy469:
+#line 415 "src/parser.re"
+                       { NEWTOKEN(PSI_T_TO_STRING); goto start; }
+#line 8213 "src/parser.c"
+yy470:
+                       yyaccept = 4;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case 'T':
-                       case 't':       goto yy426;
-                       default:        goto yy54;
+                       case 't':       goto yy473;
+                       default:        goto yy55;
                        }
-yy424:
-                       yyaccept = 64;
+yy471:
+                       yyaccept = 74;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -7213,16 +8284,16 @@ yy424:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy425;
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy472;
                        }
-yy425:
-#line 344 "src/parser.re"
-                       {RETURN(PSI_T_PRE_ASSERT);}
-#line 7224 "src/parser.c"
-yy426:
-                       yyaccept = 65;
+yy472:
+#line 397 "src/parser.re"
+                       { NEWTOKEN(PSI_T_PRE_ASSERT); goto start; }
+#line 8295 "src/parser.c"
+yy473:
+                       yyaccept = 75;
                        yych = *(P->mrk = ++P->cur);
                        switch (yych) {
                        case '0':
@@ -7287,56 +8358,85 @@ yy426:
                        case 'w':
                        case 'x':
                        case 'y':
-                       case 'z':       goto yy53;
-                       case '\\':      goto yy114;
-                       default:        goto yy427;
-                       }
-yy427:
-#line 345 "src/parser.re"
-                       {RETURN(PSI_T_POST_ASSERT);}
-#line 7298 "src/parser.c"
+                       case 'z':       goto yy54;
+                       case '\\':      goto yy115;
+                       default:        goto yy474;
+                       }
+yy474:
+#line 398 "src/parser.re"
+                       { NEWTOKEN(PSI_T_POST_ASSERT); goto start; }
+#line 8369 "src/parser.c"
                }
-#line 372 "src/parser.re"
+#line 428 "src/parser.re"
 
 
-       comment:
-               P->tok = P->cur;
+       comment: ;
                
-#line 7306 "src/parser.c"
+#line 8376 "src/parser.c"
                {
                        unsigned char yych;
-                       if ((P->lim - P->cur) < 2) { if (!psi_parser_fill(P,2)) RETURN(PSI_T_EOF); };
+                       if ((P->lim - P->cur) < 2) if (P->cur >= P->lim) goto done;;
                        yych = *P->cur;
                        switch (yych) {
-                       case '\n':      goto yy432;
-                       case '*':       goto yy434;
-                       default:        goto yy430;
+                       case '\n':
+                       case '\r':      goto yy479;
+                       case '*':       goto yy481;
+                       default:        goto yy477;
                        }
-yy430:
+yy477:
                        ++P->cur;
-yy431:
-#line 379 "src/parser.re"
+yy478:
+#line 435 "src/parser.re"
                        { goto comment; }
-#line 7321 "src/parser.c"
-yy432:
+#line 8392 "src/parser.c"
+yy479:
                        ++P->cur;
-#line 377 "src/parser.re"
-                       { NEWLINE(comment); }
-#line 7326 "src/parser.c"
-yy434:
+#line 433 "src/parser.re"
+                       { NEWLINE(); goto comment; }
+#line 8397 "src/parser.c"
+yy481:
                        yych = *++P->cur;
                        switch (yych) {
-                       case '/':       goto yy435;
-                       default:        goto yy431;
+                       case '/':       goto yy482;
+                       default:        goto yy478;
                        }
-yy435:
+yy482:
                        ++P->cur;
-#line 378 "src/parser.re"
-                       { continue; }
-#line 7337 "src/parser.c"
+#line 434 "src/parser.re"
+                       { NEWTOKEN(PSI_T_COMMENT); goto start; }
+#line 8408 "src/parser.c"
                }
-#line 380 "src/parser.re"
+#line 437 "src/parser.re"
 
-       }
-       return -1;
+
+       comment_sl: ;
+               
+#line 8415 "src/parser.c"
+               {
+                       unsigned char yych;
+                       if (P->lim <= P->cur) if (P->cur >= P->lim) goto done;;
+                       yych = *P->cur;
+                       switch (yych) {
+                       case '\n':
+                       case '\r':      goto yy488;
+                       default:        goto yy486;
+                       }
+yy486:
+                       ++P->cur;
+#line 443 "src/parser.re"
+                       { goto comment_sl; }
+#line 8429 "src/parser.c"
+yy488:
+                       ++P->cur;
+#line 442 "src/parser.re"
+                       { NEWTOKEN(PSI_T_COMMENT); NEWLINE(); goto start; }
+#line 8434 "src/parser.c"
+               }
+#line 445 "src/parser.re"
+
+error:
+       psi_plist_free(tokens);
+       return NULL;
+done:
+       return tokens;
 }
index f75fc8b2e4cee8a9c3ac087fce772c408f651559..07dc563908085b119f7aa4c64e1edeb9bc0f43b2 100644 (file)
 #ifndef PSI_PARSER_H
 #define PSI_PARSER_H
 
-#include <stdarg.h>
-
-#define BSIZE 256
-
 #include "token.h"
 #include "types.h"
 #include "data.h"
+#include "cpp.h"
 
 struct psi_parser {
        PSI_DATA_MEMBERS;
        token_t num;
        unsigned line, col;
-       char *cur, *tok, *lim, *eof, *ctx, *mrk;
+       char *cur, *tok, *lim, *ctx, *mrk;
 
        /* internals */
        void *proc;
 
+       struct psi_cpp_data cpp;
        struct {
-               HashTable defs;
-               unsigned level;
-               unsigned skip;
-       } cpp;
-
-       struct {
-               enum psi_parser_input_type {
-                       PSI_PARSE_FILE = 1,
-                       PSI_PARSE_STRING
-               } type;
-
-               union {
-                       struct {
-                               FILE *handle;
-                               char *buffer;
-#if HAVE_MMAP
-                               size_t length;
-#endif
-                       } file;
-                       struct {
-                               char *buffer;
-                               size_t length;
-                       } string;
-               } data;
+               char *buffer;
+               size_t length;
        } input;
 };
 
 struct psi_parser *psi_parser_init(struct psi_parser *P, psi_error_cb error, unsigned flags);
 bool psi_parser_open_file(struct psi_parser *P, const char *filename);
 bool psi_parser_open_string(struct psi_parser *P, const char *string, size_t length);
-token_t psi_parser_scan(struct psi_parser *P);
-void psi_parser_parse(struct psi_parser *P, struct psi_token *src);
+struct psi_plist *psi_parser_scan(struct psi_parser *P);
+void psi_parser_parse(struct psi_parser *P);
 void psi_parser_dtor(struct psi_parser *P);
 void psi_parser_free(struct psi_parser **P);
 
+void *psi_parser_proc_init(void);
+void psi_parser_proc_free(void **parser_proc);
+void psi_parser_proc_parse(void *parser_proc, token_t r, struct psi_token *token, struct psi_parser *parser);
+void psi_parser_proc_trace(FILE *out, char *prefix);
+
 #endif
index 07ad1229f423622e17c905e277d9438926cfab0d..707d201764ef36e6a8e9a50b95c1d9dce6dbf7cc 100644 (file)
 
 #include "parser.h"
 
-void *psi_parser_proc_init(void);
-void psi_parser_proc_free(void **parser_proc);
-void psi_parser_proc_parse(void *parser_proc, token_t r, struct psi_token *token, struct psi_parser *parser);
-void psi_parser_proc_trace(FILE *out, char *prefix);
+/*!max:re2c*/
+#ifndef YYMAXFILL
+# define YYMAXFILL 256
+#endif
+/*!re2c
+
+re2c:indent:top = 2;
+re2c:define:YYCTYPE = "unsigned char";
+re2c:define:YYCURSOR = P->cur;
+re2c:define:YYLIMIT = P->lim;
+re2c:define:YYMARKER = P->mrk;
+re2c:define:YYFILL = "if (P->cur >= P->lim) goto done;";
+re2c:yyfill:parameter = 0;
+
+B = [^a-zA-Z0-9_];
+W = [a-zA-Z0-9_];
+SP = [ \t];
+EOL = [\r\n];
+NAME = [a-zA-Z_]W*;
+NSNAME = (NAME)? ("\\" NAME)+;
+DOLLAR_NAME = '$' W+;
+QUOTED_STRING = "\"" ([^"])+ "\"";
+NUMBER = [+-]? [0-9]* "."? [0-9]+ ([eE] [+-]? [0-9]+)?;
+
+*/
+
+static void free_cpp_def(zval *p)
+{
+       if (Z_TYPE_P(p) == IS_PTR) {
+               psi_cpp_macro_decl_free((void *) &Z_PTR_P(p));
+       } else if (Z_REFCOUNTED_P(p)) {
+               zval_ptr_dtor(p);
+       }
+}
 
 struct psi_parser *psi_parser_init(struct psi_parser *P, psi_error_cb error, unsigned flags)
 {
@@ -48,7 +78,7 @@ struct psi_parser *psi_parser_init(struct psi_parser *P, psi_error_cb error, uns
        P->line = 1;
        P->proc = psi_parser_proc_init();
 
-       ZEND_INIT_SYMTABLE(&P->cpp.defs);
+       zend_hash_init(&P->cpp.defs, 0, NULL, free_cpp_def, 1);
        zval tmp;
        ZVAL_ARR(&tmp, &P->cpp.defs);
        add_assoc_string(&tmp, "PHP_OS", PHP_OS);
@@ -60,158 +90,177 @@ struct psi_parser *psi_parser_init(struct psi_parser *P, psi_error_cb error, uns
        return P;
 }
 
+void psi_parser_reset(struct psi_parser *P)
+{
+       P->cur = P->tok = P->mrk = P->input.buffer;
+       P->lim = P->input.buffer + P->input.length;
+}
+
 bool psi_parser_open_file(struct psi_parser *P, const char *filename)
 {
-       FILE *fp = fopen(filename, "r");
+       struct stat sb;
+       FILE *fp;
+       char *fb;
 
-       if (!fp) {
+       if (stat(filename, &sb)) {
                P->error(PSI_DATA(P), NULL, PSI_WARNING,
-                               "Could not open '%s' for reading: %s",
+                               "Could not stat '%s': %s",
                                filename, strerror(errno));
                return false;
        }
 
-       P->input.type = PSI_PARSE_FILE;
-       P->input.data.file.handle = fp;
-
-#if HAVE_MMAP
-       struct stat sb;
-       int fd = fileno(fp);
+       if (!(fb = malloc(sb.st_size + YYMAXFILL))) {
+               P->error(PSI_DATA(P), NULL, PSI_WARNING,
+                               "Could not allocate %zu bytes for reading '%s': %s",
+                               sb.st_size + YYMAXFILL, filename, strerror(errno));
+               return false;
+       }
 
-       if (fstat(fd, &sb)) {
+       if (!(fp = fopen(filename, "r"))) {
+               free(fb);
                P->error(PSI_DATA(P), NULL, PSI_WARNING,
-                               "Could not stat '%s': %s",
+                               "Could not open '%s' for reading: %s",
                                filename, strerror(errno));
                return false;
        }
 
-       P->input.data.file.buffer = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fd, 0);
-       if (MAP_FAILED == P->input.data.file.buffer) {
+       if (sb.st_size != fread(fb, 1, sb.st_size, fp)) {
+               free(fb);
+               fclose(fp);
                P->error(PSI_DATA(P), NULL, PSI_WARNING,
-                               "Could not map '%s' for reading: %s",
-                               filename, strerror(errno));
+                               "Could not read %zu bytes from '%s': %s",
+                               sb.st_size + YYMAXFILL, filename, strerror(errno));
                return false;
        }
-       P->input.data.file.length = sb.st_size;
-#else
-       P->input.data.file.buffer = malloc(BSIZE);
-#endif
+       memset(fb + sb.st_size, 0, YYMAXFILL);
+
+       if (P->input.buffer) {
+               free(P->input.buffer);
+       }
+       P->input.buffer = fb;
+       P->input.length = sb.st_size;
 
        P->file.fn = strdup(filename);
 
+       psi_parser_reset(P);
+
        return true;
 }
 
 bool psi_parser_open_string(struct psi_parser *P, const char *string, size_t length)
 {
-       P->input.type = PSI_PARSE_STRING;
-       P->input.data.string.length = length;
-       if (!(P->input.data.string.buffer = strndup(string, length))) {
+       char *sb;
+
+       if (!(sb = malloc(length + YYMAXFILL))) {
+               P->error(PSI_DATA(P), NULL, PSI_WARNING,
+                               "Could not allocate %zu bytes: %s",
+                               length + YYMAXFILL, strerror(errno));
                return false;
        }
 
+       memcpy(sb, string, length);
+       memset(sb + length, 0, YYMAXFILL);
+
+       if (P->input.buffer) {
+               free(P->input.buffer);
+       }
+       P->input.buffer = sb;
+       P->input.length = length;
+
        P->file.fn = strdup("<input>");
 
+       psi_parser_reset(P);
+
        return true;
 }
 
-static ssize_t psi_parser_fill(struct psi_parser *P, size_t n)
+#if 0
+static void psi_parser_register_constants(struct psi_parser *P)
 {
-       PSI_DEBUG_PRINT(P, "PSI< Fill: n=%zu (input.type=%d)\n", n, P->input.type);
-
-       /* init if n==0 */
-       if (!n) {
-               switch (P->input.type) {
-               case PSI_PARSE_FILE:
-                       P->cur = P->tok = P->mrk = P->input.data.file.buffer;
-#if HAVE_MMAP
-                       P->eof = P->input.data.file.buffer + P->input.data.file.length;
-                       P->lim = P->eof;
-#else
-                       P->eof = NULL;
-                       P->lim = P->input.data.file.buffer;
-#endif
+       zend_string *key;
+       zval *val;
+
+       ZEND_HASH_FOREACH_STR_KEY_VAL(&P->cpp.defs, key, val)
+       {
+               struct psi_impl_def_val *iv;
+               struct psi_const_type *ct;
+               struct psi_const *c;
+               const char *ctn;
+               token_t ctt;
+               impl_val tmp;
+               zend_string *str;
+
+               ZVAL_DEREF(val);
+               switch (Z_TYPE_P(val)) {
+               case IS_TRUE:
+               case IS_FALSE:
+                       ctt = PSI_T_BOOL;
+                       ctn = "bool";
+                       tmp.zend.bval = Z_TYPE_P(val) == IS_TRUE;
                        break;
-
-               case PSI_PARSE_STRING:
-                       P->cur = P->tok = P->mrk = P->input.data.string.buffer;
-                       P->eof = P->input.data.string.buffer + P->input.data.string.length;
-                       P->lim = P->eof;
+               case IS_LONG:
+                       ctt = PSI_T_INT;
+                       ctn = "int";
+                       tmp.zend.lval = Z_LVAL_P(val);
+                       break;
+               case IS_DOUBLE:
+                       ctt = PSI_T_FLOAT;
+                       ctn = "float";
+                       tmp.dval = Z_DVAL_P(val);
+                       break;
+               default:
+                       ctt = PSI_T_STRING;
+                       ctn = "string";
+                       str = zval_get_string(val);
+                       tmp.zend.str = zend_string_dup(str, 1);
+                       zend_string_release(str);
                        break;
                }
 
-               PSI_DEBUG_PRINT(P, "PSI< Fill: cur=%p lim=%p eof=%p\n", P->cur, P->lim, P->eof);
-       }
-
-       switch (P->input.type) {
-       case PSI_PARSE_STRING:
-               break;
-
-       case PSI_PARSE_FILE:
-#if !HAVE_MMAP
-               if (!P->eof) {
-                       size_t consumed = P->tok - P->buf;
-                       size_t reserved = P->lim - P->tok;
-                       size_t available = BSIZE - reserved;
-                       size_t didread;
-
-                       if (consumed) {
-                               memmove(P->buf, P->tok, reserved);
-                               P->tok -= consumed;
-                               P->cur -= consumed;
-                               P->lim -= consumed;
-                               P->mrk -= consumed;
-                       }
-
-                       didread = fread(P->lim, 1, available, P->fp);
-                       P->lim += didread;
-                       if (didread < available) {
-                               P->eof = P->lim;
-                       }
-                       PSI_DEBUG_PRINT(P, "PSI< Fill: consumed=%zu reserved=%zu available=%zu didread=%zu\n",
-                                       consumed, reserved, available, didread);
+               iv = psi_impl_def_val_init(ctt, NULL);
+               iv->ival = tmp;
+               ct = psi_const_type_init(ctt, ctn);
+               c = psi_const_init(ct, key->val, iv);
+               if (!P->consts) {
+                       P->consts = psi_plist_init((psi_plist_dtor) psi_const_free);
                }
-#endif
-               break;
+               P->consts = psi_plist_add(P->consts, &c);
        }
-
-       PSI_DEBUG_PRINT(P, "PSI< Fill: avail=%td\n", P->lim - P->cur);
-
-       return P->lim - P->cur;
+       ZEND_HASH_FOREACH_END();
 }
+#endif
 
-void psi_parser_parse(struct psi_parser *P, struct psi_token *T)
+void psi_parser_parse(struct psi_parser *P)
 {
-       if (T) {
-               psi_parser_proc_parse(P->proc, T->type, T, P);
-       } else {
+       size_t i = 0;
+       struct psi_token *T;
+
+       P->cpp.tokens = psi_parser_scan(P);
+
+       psi_cpp_preprocess(P, &P->cpp);
+
+       if (psi_plist_count(P->cpp.tokens)) {
+               while (psi_plist_get(P->cpp.tokens, i++, &T)) {
+                       if (P->flags & PSI_DEBUG) {
+                               fprintf(stderr, "PSI> ");
+                               psi_token_dump(2, T);
+                       }
+                       psi_parser_proc_parse(P->proc, T->type, T, P);
+               }
                psi_parser_proc_parse(P->proc, 0, NULL, P);
        }
+
+       psi_plist_free(P->cpp.tokens);
+       P->cpp.tokens = NULL;
 }
 
 void psi_parser_dtor(struct psi_parser *P)
 {
        psi_parser_proc_free(&P->proc);
 
-       switch (P->input.type) {
-       case PSI_PARSE_FILE:
-               if (P->input.data.file.buffer) {
-#if HAVE_MMAP
-                       munmap(P->input.data.file.buffer, P->input.data.file.length);
-#else
-                       free(P->input.data.file.buffer);
-#endif
-               }
-               if (P->input.data.file.handle) {
-                       fclose(P->input.data.file.handle);
-               }
-               break;
-
-       case PSI_PARSE_STRING:
-               if (P->input.data.string.buffer) {
-                       free(P->input.data.string.buffer);
-               }
-               break;
+       if (P->input.buffer) {
+               free(P->input.buffer);
+               P->input.buffer = NULL;
        }
 
        psi_data_dtor(PSI_DATA(P));
@@ -230,533 +279,173 @@ void psi_parser_free(struct psi_parser **P)
        }
 }
 
-static bool cpp_truth(struct psi_parser *P);
-static bool cpp_defined(struct psi_parser *P);
-static zval *cpp_define_var(struct psi_parser *P);
-static void cpp_define_val(struct psi_parser *P, token_t typ, zval *val);
-static void cpp_undefine(struct psi_parser *P);
-static void cpp_error(struct psi_parser *P, const char *msg, ...);
-
-/*!max:re2c*/
-#if BSIZE < YYMAXFILL
-# error BSIZE must be greater than YYMAXFILL
-#endif
+#define NEWLINE() \
+       P->col = 1; \
+       ++P->line
 
-#define RETURN(t) do { \
+#define NEWTOKEN(t) \
        P->num = t; \
-       PSI_DEBUG_PRINT(P, "PSI< TOKEN: %d %.*s (EOF=%d %s:%u:%u)\n", \
-                               P->num, (int) (P->cur-P->tok), P->tok, P->num == PSI_T_EOF, \
-                               P->file.fn, P->line, P->col); \
-       return t; \
-} while(1)
+       token = psi_token_alloc(P); \
+       tokens = psi_plist_add(tokens, &token); \
+       P->col += P->cur - P->tok; \
+       if (P->flags & PSI_DEBUG) { \
+               fprintf(stderr, "PSI< "); \
+               psi_token_dump(2, token); \
+       } \
+       token = NULL
 
-#define NEWLINE(label) \
-       P->col = 1; \
-       ++P->line; \
-       goto label
 
-token_t psi_parser_scan(struct psi_parser *P)
+struct psi_plist *psi_parser_scan(struct psi_parser *P)
 {
+       struct psi_plist *tokens;
+       struct psi_token *token;
+
        if (!P->cur) {
-               psi_parser_fill(P, 0);
+               return NULL;
        }
-       for (;;) {
-               if (P->cpp.skip) {
-                       /* we might come from EOL, so just go to cpp instead of cpp_skip */
-                       goto cpp;
-               }
 
-               P->col += P->cur - P->tok;
+       tokens = psi_plist_init(NULL);
 
-       nextline: ;
+       start: ;
                P->tok = P->cur;
-               /*!re2c
-               re2c:indent:top = 2;
-               re2c:define:YYCTYPE = "unsigned char";
-               re2c:define:YYCURSOR = P->cur;
-               re2c:define:YYLIMIT = P->lim;
-               re2c:define:YYMARKER = P->mrk;
-               re2c:define:YYFILL = "{ if (!psi_parser_fill(P,@@)) RETURN(PSI_T_EOF); }";
-               re2c:yyfill:parameter = 0;
-
-               B = [^a-zA-Z0-9_];
-               W = [a-zA-Z0-9_];
-               NAME = [a-zA-Z_]W*;
-               NSNAME = (NAME)? ("\\" NAME)+;
-               DOLLAR_NAME = '$' W+;
-               QUOTED_STRING = "\"" ([^\"])+ "\"";
-               NUMBER = [+-]? [0-9]* "."? [0-9]+ ([eE] [+-]? [0-9]+)?;
-
-               "#" { --P->cur; goto cpp; }
-               "/*" { goto comment; }
-               "//" .* "\n" { NEWLINE(nextline); }
-               "(" {RETURN(PSI_T_LPAREN);}
-               ")" {RETURN(PSI_T_RPAREN);}
-               ";" {RETURN(PSI_T_EOS);}
-               "," {RETURN(PSI_T_COMMA);}
-               ":" {RETURN(PSI_T_COLON);}
-               "{" {RETURN(PSI_T_LBRACE);}
-               "}" {RETURN(PSI_T_RBRACE);}
-               "[" {RETURN(PSI_T_LBRACKET);}
-               "]" {RETURN(PSI_T_RBRACKET);}
-               "!=" {RETURN(PSI_T_CMP_NE);}
-               "==" {RETURN(PSI_T_CMP_EQ);}
-               "&&" {RETURN(PSI_T_AND);}
-               "||" {RETURN(PSI_T_OR);}
-               "=" {RETURN(PSI_T_EQUALS);}
-               "*" {RETURN(PSI_T_ASTERISK);}
-               "~" {RETURN(PSI_T_TILDE);}
-               "!" {RETURN(PSI_T_NOT);}
-               "%" {RETURN(PSI_T_MODULO);}
-               "&" {RETURN(PSI_T_AMPERSAND);}
-               "+" {RETURN(PSI_T_PLUS);}
-               "-" {RETURN(PSI_T_MINUS);}
-               "/" {RETURN(PSI_T_SLASH);}
-               "|" {RETURN(PSI_T_PIPE);}
-               "^" {RETURN(PSI_T_CARET);}
-               "<<" {RETURN(PSI_T_LSHIFT);}
-               ">>" {RETURN(PSI_T_RSHIFT);}
-               "<=" {RETURN(PSI_T_CMP_LE);}
-               ">=" {RETURN(PSI_T_CMP_GE);}
-               "<" {RETURN(PSI_T_LCHEVR);}
-               ">" {RETURN(PSI_T_RCHEVR);}
-               "..." {RETURN(PSI_T_ELLIPSIS);}
-               [\r\n] { NEWLINE(nextline); }
-               [\t ]+ { continue; }
-               'TRUE' {RETURN(PSI_T_TRUE);}
-               'FALSE' {RETURN(PSI_T_FALSE);}
-               'NULL' {RETURN(PSI_T_NULL);}
-               'MIXED' {RETURN(PSI_T_MIXED);}
-               'CALLABLE' {RETURN(PSI_T_CALLABLE);}
-               'VOID' {RETURN(PSI_T_VOID);}
-               'BOOL' {RETURN(PSI_T_BOOL);}
-               'CHAR' {RETURN(PSI_T_CHAR);}
-               'SHORT' {RETURN(PSI_T_SHORT);}
-               'INT' {RETURN(PSI_T_INT);}
-               'LONG' {RETURN(PSI_T_LONG);}
-               'FLOAT' {RETURN(PSI_T_FLOAT);}
-               'DOUBLE' {RETURN(PSI_T_DOUBLE);}
-               'INT8_T' {RETURN(PSI_T_INT8);}
-               'UINT8_T' {RETURN(PSI_T_UINT8);}
-               'INT16_T' {RETURN(PSI_T_INT16);}
-               'UINT16_T' {RETURN(PSI_T_UINT16);}
-               'INT32_T' {RETURN(PSI_T_INT32);}
-               'UINT32_T' {RETURN(PSI_T_UINT32);}
-               'INT64_T' {RETURN(PSI_T_INT64);}
-               'UINT64_T' {RETURN(PSI_T_UINT64);}
-               'UNSIGNED' {RETURN(PSI_T_UNSIGNED);}
-               'SIGNED' {RETURN(PSI_T_SIGNED);}
-               'STRING' {RETURN(PSI_T_STRING);}
-               'ARRAY' {RETURN(PSI_T_ARRAY);}
-               'OBJECT' {RETURN(PSI_T_OBJECT);}
-               'CALLBACK' {RETURN(PSI_T_CALLBACK);}
-               'STATIC' {RETURN(PSI_T_STATIC);}
-               'FUNCTION' {RETURN(PSI_T_FUNCTION);}
-               'TYPEDEF' {RETURN(PSI_T_TYPEDEF);}
-               'STRUCT' {RETURN(PSI_T_STRUCT);}
-               'UNION' {RETURN(PSI_T_UNION);}
-               'ENUM' {RETURN(PSI_T_ENUM);}
-               'CONST' {RETURN(PSI_T_CONST);}
-               'LIB' {RETURN(PSI_T_LIB);}
-               'LET' {RETURN(PSI_T_LET);}
-               'SET' {RETURN(PSI_T_SET);}
-               'PRE_ASSERT' {RETURN(PSI_T_PRE_ASSERT);}
-               'POST_ASSERT' {RETURN(PSI_T_POST_ASSERT);}
-               'RETURN' {RETURN(PSI_T_RETURN);}
-               'FREE' {RETURN(PSI_T_FREE);}
-               'TEMP' {RETURN(PSI_T_TEMP);}
-               'STRLEN' {RETURN(PSI_T_STRLEN);}
-               'STRVAL' {RETURN(PSI_T_STRVAL);}
-               'PATHVAL' {RETURN(PSI_T_PATHVAL);}
-               'INTVAL' {RETURN(PSI_T_INTVAL);}
-               'FLOATVAL' {RETURN(PSI_T_FLOATVAL);}
-               'BOOLVAL' {RETURN(PSI_T_BOOLVAL);}
-               'ARRVAL' {RETURN(PSI_T_ARRVAL);}
-               'OBJVAL' {RETURN(PSI_T_OBJVAL);}
-               'ZVAL' {RETURN(PSI_T_ZVAL);}
-               'COUNT' {RETURN(PSI_T_COUNT);}
-               'CALLOC' {RETURN(PSI_T_CALLOC);}
-               'TO_OBJECT' {RETURN(PSI_T_TO_OBJECT);}
-               'TO_ARRAY' {RETURN(PSI_T_TO_ARRAY);}
-               'TO_STRING' {RETURN(PSI_T_TO_STRING);}
-               'TO_INT' {RETURN(PSI_T_TO_INT);}
-               'TO_FLOAT' {RETURN(PSI_T_TO_FLOAT);}
-               'TO_BOOL' {RETURN(PSI_T_TO_BOOL);}
-               NUMBER {RETURN(PSI_T_NUMBER);}
-               NAME {RETURN(PSI_T_NAME);}
-               NSNAME {RETURN(PSI_T_NSNAME);}
-               DOLLAR_NAME {RETURN(PSI_T_DOLLAR_NAME);}
-               QUOTED_STRING {RETURN(PSI_T_QUOTED_STRING);}
-               [^] {break;}
-               */
 
-       comment: ;
-               P->tok = P->cur;
                /*!re2c
-               "\n"    { NEWLINE(comment); }
-               "*" "/" { continue; }
-               [^]             { goto comment; }
-               */
 
-#define PSI_DEBUG_CPP(P, msg, ...) do { \
-       if (PSI_DATA(P)->flags & PSI_DEBUG) { \
-               fprintf(stderr, "PSI> CPP %.*s line=%u level=%u skip=%u ", \
-                               (int) strcspn(P->tok, "\r\n"), P->tok, \
-                               P->line, P->cpp.level, P->cpp.skip); \
-               fprintf(stderr, msg, __VA_ARGS__); \
-       } \
-} while(0)
+               "/*"                    { goto comment; }
+               "//"                    { goto comment_sl; }
+               "#"                             { NEWTOKEN(PSI_T_HASH); goto start; }
+               "("                             { NEWTOKEN(PSI_T_LPAREN); goto start; }
+               ")"                             { NEWTOKEN(PSI_T_RPAREN); goto start; }
+               ";"                             { NEWTOKEN(PSI_T_EOS); goto start; }
+               ","                             { NEWTOKEN(PSI_T_COMMA); goto start; }
+               ":"                             { NEWTOKEN(PSI_T_COLON); goto start; }
+               "{"                             { NEWTOKEN(PSI_T_LBRACE); goto start; }
+               "}"                             { NEWTOKEN(PSI_T_RBRACE); goto start; }
+               "["                             { NEWTOKEN(PSI_T_LBRACKET); goto start; }
+               "]"                             { NEWTOKEN(PSI_T_RBRACKET); goto start; }
+               "!="                    { NEWTOKEN(PSI_T_CMP_NE); goto start; }
+               "=="                    { NEWTOKEN(PSI_T_CMP_EQ); goto start; }
+               "&&"                    { NEWTOKEN(PSI_T_AND); goto start; }
+               "||"                    { NEWTOKEN(PSI_T_OR); goto start; }
+               "="                             { NEWTOKEN(PSI_T_EQUALS); goto start; }
+               "*"                             { NEWTOKEN(PSI_T_ASTERISK); goto start; }
+               "~"                             { NEWTOKEN(PSI_T_TILDE); goto start; }
+               "!"                             { NEWTOKEN(PSI_T_NOT); goto start; }
+               "%"                             { NEWTOKEN(PSI_T_MODULO); goto start; }
+               "&"                             { NEWTOKEN(PSI_T_AMPERSAND); goto start; }
+               "+"                             { NEWTOKEN(PSI_T_PLUS); goto start; }
+               "-"                             { NEWTOKEN(PSI_T_MINUS); goto start; }
+               "/"                             { NEWTOKEN(PSI_T_SLASH); goto start; }
+               "\\"                    { NEWTOKEN(PSI_T_BSLASH); goto start; }
+               "|"                             { NEWTOKEN(PSI_T_PIPE); goto start; }
+               "^"                             { NEWTOKEN(PSI_T_CARET); goto start; }
+               "<<"                    { NEWTOKEN(PSI_T_LSHIFT); goto start; }
+               ">>"                    { NEWTOKEN(PSI_T_RSHIFT); goto start; }
+               "<="                    { NEWTOKEN(PSI_T_CMP_LE); goto start; }
+               ">="                    { NEWTOKEN(PSI_T_CMP_GE); goto start; }
+               "<"                             { NEWTOKEN(PSI_T_LCHEVR); goto start; }
+               ">"                             { NEWTOKEN(PSI_T_RCHEVR); goto start; }
+               "..."                   { NEWTOKEN(PSI_T_ELLIPSIS); goto start; }
+               'IF'                    { NEWTOKEN(PSI_T_IF); goto start; }
+               'IFDEF'                 { NEWTOKEN(PSI_T_IFDEF); goto start; }
+               'IFNDEF'                { NEWTOKEN(PSI_T_IFNDEF); goto start; }
+               'ELSE'                  { NEWTOKEN(PSI_T_ELSE); goto start; }
+               'ELIF'                  { NEWTOKEN(PSI_T_ELIF); goto start; }
+               'ENDIF'                 { NEWTOKEN(PSI_T_ENDIF); goto start; }
+               'DEFINE'                { NEWTOKEN(PSI_T_DEFINE); goto start; }
+               'DEFINED'               { NEWTOKEN(PSI_T_DEFINED); goto start; }
+               'UNDEF'                 { NEWTOKEN(PSI_T_UNDEF); goto start; }
+               'WARNING'               { NEWTOKEN(PSI_T_WARNING); goto start; }
+               'ERROR'                 { NEWTOKEN(PSI_T_ERROR); goto start; }
+               'TRUE'                  { NEWTOKEN(PSI_T_TRUE); goto start; }
+               'FALSE'                 { NEWTOKEN(PSI_T_FALSE); goto start; }
+               'NULL'                  { NEWTOKEN(PSI_T_NULL); goto start; }
+               'MIXED'                 { NEWTOKEN(PSI_T_MIXED); goto start; }
+               'CALLABLE'              { NEWTOKEN(PSI_T_CALLABLE); goto start; }
+               'VOID'                  { NEWTOKEN(PSI_T_VOID); goto start; }
+               'BOOL'                  { NEWTOKEN(PSI_T_BOOL); goto start; }
+               'CHAR'                  { NEWTOKEN(PSI_T_CHAR); goto start; }
+               'SHORT'                 { NEWTOKEN(PSI_T_SHORT); goto start; }
+               'INT'                   { NEWTOKEN(PSI_T_INT); goto start; }
+               'LONG'                  { NEWTOKEN(PSI_T_LONG); goto start; }
+               'FLOAT'                 { NEWTOKEN(PSI_T_FLOAT); goto start; }
+               'DOUBLE'                { NEWTOKEN(PSI_T_DOUBLE); goto start; }
+               'INT8_T'                { NEWTOKEN(PSI_T_INT8); goto start; }
+               'UINT8_T'               { NEWTOKEN(PSI_T_UINT8); goto start; }
+               'INT16_T'               { NEWTOKEN(PSI_T_INT16); goto start; }
+               'UINT16_T'              { NEWTOKEN(PSI_T_UINT16); goto start; }
+               'INT32_T'               { NEWTOKEN(PSI_T_INT32); goto start; }
+               'UINT32_T'              { NEWTOKEN(PSI_T_UINT32); goto start; }
+               'INT64_T'               { NEWTOKEN(PSI_T_INT64); goto start; }
+               'UINT64_T'              { NEWTOKEN(PSI_T_UINT64); goto start; }
+               'UNSIGNED'              { NEWTOKEN(PSI_T_UNSIGNED); goto start; }
+               'SIGNED'                { NEWTOKEN(PSI_T_SIGNED); goto start; }
+               'STRING'                { NEWTOKEN(PSI_T_STRING); goto start; }
+               'ARRAY'                 { NEWTOKEN(PSI_T_ARRAY); goto start; }
+               'OBJECT'                { NEWTOKEN(PSI_T_OBJECT); goto start; }
+               'CALLBACK'              { NEWTOKEN(PSI_T_CALLBACK); goto start; }
+               'STATIC'                { NEWTOKEN(PSI_T_STATIC); goto start; }
+               'FUNCTION'              { NEWTOKEN(PSI_T_FUNCTION); goto start; }
+               'TYPEDEF'               { NEWTOKEN(PSI_T_TYPEDEF); goto start; }
+               'STRUCT'                { NEWTOKEN(PSI_T_STRUCT); goto start; }
+               'UNION'                 { NEWTOKEN(PSI_T_UNION); goto start; }
+               'ENUM'                  { NEWTOKEN(PSI_T_ENUM); goto start; }
+               'CONST'                 { NEWTOKEN(PSI_T_CONST); goto start; }
+               'LIB'                   { NEWTOKEN(PSI_T_LIB); goto start; }
+               'LET'                   { NEWTOKEN(PSI_T_LET); goto start; }
+               'SET'                   { NEWTOKEN(PSI_T_SET); goto start; }
+               'PRE_ASSERT'    { NEWTOKEN(PSI_T_PRE_ASSERT); goto start; }
+               'POST_ASSERT'   { NEWTOKEN(PSI_T_POST_ASSERT); goto start; }
+               'RETURN'                { NEWTOKEN(PSI_T_RETURN); goto start; }
+               'FREE'                  { NEWTOKEN(PSI_T_FREE); goto start; }
+               'TEMP'                  { NEWTOKEN(PSI_T_TEMP); goto start; }
+               'STRLEN'                { NEWTOKEN(PSI_T_STRLEN); goto start; }
+               'STRVAL'                { NEWTOKEN(PSI_T_STRVAL); goto start; }
+               'PATHVAL'               { NEWTOKEN(PSI_T_PATHVAL); goto start; }
+               'INTVAL'                { NEWTOKEN(PSI_T_INTVAL); goto start; }
+               'FLOATVAL'              { NEWTOKEN(PSI_T_FLOATVAL); goto start; }
+               'BOOLVAL'               { NEWTOKEN(PSI_T_BOOLVAL); goto start; }
+               'ARRVAL'                { NEWTOKEN(PSI_T_ARRVAL); goto start; }
+               'OBJVAL'                { NEWTOKEN(PSI_T_OBJVAL); goto start; }
+               'ZVAL'                  { NEWTOKEN(PSI_T_ZVAL); goto start; }
+               'COUNT'                 { NEWTOKEN(PSI_T_COUNT); goto start; }
+               'CALLOC'                { NEWTOKEN(PSI_T_CALLOC); goto start; }
+               'TO_OBJECT'             { NEWTOKEN(PSI_T_TO_OBJECT); goto start; }
+               'TO_ARRAY'              { NEWTOKEN(PSI_T_TO_ARRAY); goto start; }
+               'TO_STRING'             { NEWTOKEN(PSI_T_TO_STRING); goto start; }
+               'TO_INT'                { NEWTOKEN(PSI_T_TO_INT); goto start; }
+               'TO_FLOAT'              { NEWTOKEN(PSI_T_TO_FLOAT); goto start; }
+               'TO_BOOL'               { NEWTOKEN(PSI_T_TO_BOOL); goto start; }
+               NUMBER                  { NEWTOKEN(PSI_T_NUMBER); goto start; }
+               NAME                    { NEWTOKEN(PSI_T_NAME); goto start; }
+               NSNAME                  { NEWTOKEN(PSI_T_NSNAME); goto start; }
+               DOLLAR_NAME             { NEWTOKEN(PSI_T_DOLLAR_NAME); goto start; }
+               QUOTED_STRING   { NEWTOKEN(PSI_T_QUOTED_STRING); goto start; }
+               EOL                             { NEWTOKEN(PSI_T_EOL); NEWLINE(); goto start; }
+               SP+                             { NEWTOKEN(PSI_T_WHITESPACE); goto start; }
+               *                               { goto error; }
 
-       cpp: ;
-               P->tok = P->cur;
-               /*!re2c
-               [\t ]                           {goto cpp;}
-               "#" [\t ]* "if"         { goto cpp_if; }
-               "#" [\t ]* "ifdef"      { goto cpp_ifdef; }
-               "#" [\t ]* "ifndef"     { goto cpp_ifndef; }
-               "#" [\t ]* "else"       { goto cpp_else; }
-               "#" [\t ]* "endif"      { goto cpp_endif; }
-               "#" [\t ]* "define"     { goto cpp_define; }
-               "#" [\t ]* "undef"      { goto cpp_undef; }
-               "#" [\t ]* "error"      { goto cpp_error; }
-               [^]                             { goto cpp_default; }
                */
 
-       cpp_default: ;
-               if (P->cpp.skip) {
-                       goto cpp_skip;
-               } else {
-                       assert(0);
-                       break;
-               }
-
-       cpp_skip: ;
-               P->tok = P->cur;
-               /*!re2c
-               [\r\n]  { goto cpp_skip_eol; }
-               [^]             { goto cpp_skip; }
-               */
-
-       cpp_skip_eol:
-               PSI_DEBUG_PRINT(P, "PSI> CPP skip line %u\n", P->line);
-               NEWLINE(cpp);
-
-       cpp_if: ;
-               PSI_DEBUG_CPP(P, "%s\n", "");
-
-               ++P->cpp.level;
-
-       cpp_if_cont: ;
-               if (P->cpp.skip) {
-                       goto cpp_skip;
-               }
-
-               P->tok = P->cur;
-
-               /*!re2c
-               [\t ]+                                                          { goto cpp_if_cont; }
-               "!" [\t ]* "defined" [\t ]* "("?        { goto cpp_ifndef_cont; }
-               "defined" [ \t]* "("?                           { goto cpp_ifdef_cont; }
-               NAME [\t ]* [\r\n]                                      { goto cpp_if_name_eol; }
-               [^]                                                                     { goto cpp_if_default;  }
-               */
-
-       cpp_if_default: ;
-               cpp_error(P, "PSI syntax error: invalid #if");
-               continue;
-
-       cpp_if_name_eol: ;
-               if (cpp_truth(P)) {
-                       NEWLINE(nextline);
-               } else {
-                       P->cpp.skip = P->cpp.level;
-                       NEWLINE(cpp);
-               }
-
-       cpp_ifdef: ;
-               PSI_DEBUG_CPP(P, "%s\n", "");
-
-               ++P->cpp.level;
-
-       cpp_ifdef_cont: ;
-               if (P->cpp.skip) {
-                       goto cpp_skip;
-               }
-
-               P->tok = P->cur;
-
+       comment: ;
                /*!re2c
-               [\t ]+                                                  { goto cpp_ifdef_cont; }
-               NAME [\t ]* ")"? [\t ]* [\r\n]  { goto cpp_ifdef_name_eol; }
-               [^]                                                             { goto cpp_ifdef_default; }
-               */
-
-       cpp_ifdef_default: ;
-               cpp_error(P, "PSI syntax error: invalid #ifdef");
-               continue;
-
-       cpp_ifdef_name_eol: ;
-               if (cpp_defined(P)) {
-                       NEWLINE(nextline);
-               } else {
-                       P->cpp.skip = P->cpp.level;
-                       NEWLINE(cpp);
-               }
 
-       cpp_ifndef: ;
-               PSI_DEBUG_CPP(P, "%s\n", "");
+               EOL             { NEWLINE(); goto comment; }
+               "*" "/" { NEWTOKEN(PSI_T_COMMENT); goto start; }
+                *              { goto comment; }
 
-               ++P->cpp.level;
-
-       cpp_ifndef_cont:
-               if (P->cpp.skip) {
-                       goto cpp_skip;
-               }
-
-               P->tok = P->cur;
-
-               /*!re2c
-               [\t ]+                                                  { goto cpp_ifndef_cont; }
-               NAME [\t ]* ")"? [\t ]* [\r\n]  { goto cpp_ifndef_name_eol; }
-               [^]                                                             { goto cpp_ifndef_default; }
                */
 
-       cpp_ifndef_default: ;
-               cpp_error(P, "PSI syntax error: invalid #ifndef");
-               continue;
-
-       cpp_ifndef_name_eol: ;
-               if (!cpp_defined(P)) {
-                       NEWLINE(nextline);
-               } else {
-                       P->cpp.skip = P->cpp.level;
-                       NEWLINE(cpp_skip);
-               }
-
-       cpp_else: ;
-               PSI_DEBUG_CPP(P, "%s\n", "");
-
-               P->tok = P->cur;
-
-               if (!P->cpp.level) {
-                       cpp_error(P, "PSI syntax error: ignoring lone #else");
-                       continue;
-               }
-               if (!P->cpp.skip) {
-                       P->cpp.skip = P->cpp.level;
-                       goto cpp_skip;
-               } else if (P->cpp.skip == P->cpp.level) {
-                       P->cpp.skip = 0;
-               }
-               continue;
-
-       cpp_endif: ;
-               PSI_DEBUG_CPP(P, "%s\n", "");
-
-               P->tok = P->cur;
-               if (!P->cpp.level) {
-                       cpp_error(P, "PSI syntax_error: ignoring lone #endif");
-                       continue;
-               } else if (P->cpp.skip == P->cpp.level) {
-                       P->cpp.skip = 0;
-               }
-               --P->cpp.level;
-               continue;
-
-       cpp_define: ;
-               PSI_DEBUG_CPP(P, "%s\n", "");
-
-               zval *val = NULL;
-
-               if (P->cpp.skip) {
-                       goto cpp_skip;
-               }
-
-       cpp_define_cont: ;
-               P->tok = P->cur;
-
+       comment_sl: ;
                /*!re2c
-               [\t ]+                  { goto cpp_define_cont; }
-               [\r\n]                  { goto cpp_define_eol; }
-               NAME                    { goto cpp_define_name; }
-               QUOTED_STRING   { goto cpp_define_quoted_string; }
-               NUMBER                  { goto cpp_define_number; }
-               [^]                             { goto cpp_define_default; }
-               */
-
-       cpp_define_default: ;
-               cpp_error(P, "PSI syntax error: invalid #ifndef");
-               continue;
 
-       cpp_define_eol: ;
-               if (!val) {
-                       cpp_error(P, "PSI syntax error: ignoring lone #define");
-                       continue;
-               }
-               NEWLINE(nextline);
+               EOL     { NEWTOKEN(PSI_T_COMMENT); NEWLINE(); goto start; }
+               *       { goto comment_sl; }
 
-       cpp_define_name: ;
-               if (val) {
-                       if (Z_TYPE_P(val) != IS_TRUE) {
-                               cpp_error(P, "PSI syntax error: invalid #define");
-                               continue;
-                       }
-                       cpp_define_val(P, PSI_T_NAME, val);
-               } else {
-                       val = cpp_define_var(P);
-               }
-               goto cpp_define_cont;
-
-       cpp_define_quoted_string: ;
-               if (!val) {
-                       cpp_error(P, "PSI syntax error: invalid quoted string in #define");
-                       continue;
-               } else {
-                       cpp_define_val(P, PSI_T_QUOTED_STRING, val);
-               }
-               goto cpp_define_cont;
-
-       cpp_define_number: ;
-               if (!val) {
-                       cpp_error(P, "PSI syntax error: invalid quoted string in #define");
-                       continue;
-               } else {
-                       cpp_define_val(P, PSI_T_NUMBER, val);
-               }
-               goto cpp_define_cont;
-
-       cpp_undef: ;
-               PSI_DEBUG_CPP(P, "%s\n", "");
-
-               if (P->cpp.skip) {
-                       goto cpp_skip;
-               }
-
-       cpp_undef_cont: ;
-               P->tok = P->cur;
-
-               /*!re2c
-               [\t ]+                          { goto cpp_undef_cont; }
-               NAME [\t ]* [\r\n]      { goto cpp_undef_name_eol; }
-               [^]                                     { goto cpp_undef_default; }
                */
-
-       cpp_undef_default: ;
-               cpp_error(P, "PSI syntax error: invalid #undef");
-               continue;
-
-       cpp_undef_name_eol: ;
-               cpp_undefine(P);
-               NEWLINE(nextline);
-
-       cpp_error: ;
-               size_t len = strcspn(P->cur, "\r\n");
-
-               if (P->cpp.skip) {
-                       P->tok = P->cur + len;
-                       NEWLINE(cpp_skip);
-               } else {
-                       cpp_error(P, "%.*s", (int) len, P->cur);
-                       break;
-               }
-       }
-       return -1;
-}
-
-#include <ctype.h>
-
-static bool cpp_truth(struct psi_parser *P)
-{
-       size_t len = P->cur - P->tok;
-
-       while (len && isspace(P->tok[len - 1])) {
-               --len;
-       }
-
-       zval *val = zend_symtable_str_find(&P->cpp.defs, P->tok, len);
-       bool truth = val ? zend_is_true(val) : false;
-
-       PSI_DEBUG_PRINT(P, "PSI> CPP truth(%.*s)=%s\n",
-                       (int) len, P->tok, truth ? "true" : "false");
-
-       return truth;
-}
-
-static bool cpp_defined(struct psi_parser *P)
-{
-       size_t len = P->cur - P->tok;
-
-       while (len && isspace(P->tok[len - 1])) {
-               --len;
-       }
-
-
-       bool defined = zend_symtable_str_exists(&P->cpp.defs, P->tok, len);
-       PSI_DEBUG_PRINT(P, "PSI> CPP defined(%.*s)=%s\n",
-                       (int) len, P->tok, defined ? "true" : "false");
-       return defined;
-}
-
-static zval *cpp_define_var(struct psi_parser *P)
-{
-       if (cpp_defined(P)) {
-               psi_error(PSI_WARNING, P->file.fn, P->line, "PSI syntax error: Unexpected end of input");
-       }
-       size_t len = P->cur - P->tok;
-
-       while (len && isspace(P->tok[len - 1])) {
-               --len;
-       }
-
-       PSI_DEBUG_PRINT(P, "PSI> CPP define %.*s\n", (int) len, P->tok);
-
-       if (zend_symtable_str_exists(&P->cpp.defs, P->tok, len)) {
-               cpp_error(P, "Redefinition of %.*s", (int) len, P->tok);
-       }
-
-       zval val;
-       ZVAL_TRUE(&val);
-       return zend_symtable_str_update(&P->cpp.defs, P->tok, len, &val);
-}
-
-static void cpp_define_val(struct psi_parser *P, token_t typ, zval *val) {
-       size_t len = P->cur - P->tok;
-
-       while (len && isspace(P->tok[len - 1])) {
-               --len;
-       }
-
-       PSI_DEBUG_PRINT(P, "PSI> define = %.*s\n", (int) len, P->tok);
-
-       switch (typ) {
-       case PSI_T_QUOTED_STRING:
-               ZVAL_STRINGL(val, P->tok + 1, len - 2);
-               break;
-       case PSI_T_NUMBER:
-               ZVAL_STRINGL(val, P->tok, len);
-               convert_scalar_to_number(val);
-               break;
-       default:
-               assert(0);
-       }
-}
-
-static void cpp_undefine(struct psi_parser *P)
-{
-       size_t len = P->cur - P->tok;
-
-       while (len && isspace(P->tok[len - 1])) {
-               --len;
-       }
-
-       zend_symtable_str_del(&P->cpp.defs, P->tok, len);
-}
-
-static void cpp_error(struct psi_parser *P, const char *msg, ...)
-{
-       va_list argv;
-
-       va_start(argv, msg);
-       psi_verror(PSI_WARNING, P->file.fn, P->line, msg, argv);
-       va_end(argv);
+error:
+       psi_plist_free(tokens);
+       return NULL;
+done:
+       return tokens;
 }
index 293fdb8462d6ae50f146c1a56fb9d2f434da44e6..013974818f08baadc76047c863df6e92835652b5 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************
- Copyright (c) 2016, Michael Wallner <mike@php.net>.
+ Copyright (c) 2017, Michael Wallner <mike@php.net>.
  All rights reserved.
 
  Redistribution and use in source and binary forms, with or without
@@ -23,6 +23,9 @@
  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *******************************************************************************/
 
+#ifndef PSI_PARSER_INC
+#define PSI_PARSER_INC
+
 #define CONCAT2(x,y) x##y
 #define CONCAT1(x,y) CONCAT2(x,y)
 #define COUNTED(x) CONCAT1(parse_ ##x## _, __LINE__)
 # define TOKEN_CLASS(type, tokens) static token_t type##_token[] = { tokens 0 };
 #endif
 
-DEF(%token_prefix, CONCAT1(TOKEN_PREFIX,_))
-DEF(%token_type, {TOKEN_STRUCT})
-DEF(%token_destructor, {free($$);})
-DEF(%default_destructor, {(void)P;})
-DEF(%extra_argument, {struct psi_parser *P})
-
-/* TOKEN is defined inside syntax_error */
-DEF(%syntax_error, {
-       ++P->errors;
-       if (TOKEN && TOKEN->type != PSI_T_EOF) {
-               psi_error(PSI_WARNING, TOKEN->file, TOKEN->line, "PSI syntax error: Unexpected token '%s' at pos %u", TOKEN->text, TOKEN->col);
-       } else {
-               psi_error(PSI_WARNING, P->file.fn, P->line, "PSI syntax error: Unexpected end of input");
-       }
-})
-
-TOKEN_CLASS(const_type, T(BOOL) T(INT) T(FLOAT) T(STRING))
-TOKEN_CLASS(decl_type, T(FLOAT) T(DOUBLE) T(INT8) T(UINT8) T(INT16) T(UINT16) T(INT32) T(UINT32) T(INT64) T(UINT64) T(NAME))
-TOKEN_CLASS(impl_def_val, T(NULL) T(NUMBER) T(TRUE) T(FALSE) T(QUOTED_STRING))
-TOKEN_CLASS(number, T(NUMBER) T(NSNAME))
-TOKEN_CLASS(binary_op, T(PIPE) T(CARET) T(AMPERSAND) T(LSHIFT) T(RSHIFT) T(PLUS) T(MINUS) T(ASTERISK) T(SLASH) T(MODULO) T(RCHEVR) T(LCHEVR) T(CMP_GE) T(CMP_LE) T(OR) T(AND) T(CMP_EQ) T(CMP_NE))
-TOKEN_CLASS(unary_op, T(TILDE) T(NOT) T(PLUS) T(MINUS))
-TOKEN_CLASS(let_func, T(ZVAL) T(OBJVAL) T(ARRVAL) T(PATHVAL) T(STRLEN) T(STRVAL) T(FLOATVAL) T(INTVAL) T(BOOLVAL) T(COUNT))
-TOKEN_CLASS(set_func, T(TO_OBJECT) T(TO_ARRAY) T(TO_STRING) T(TO_INT) T(TO_FLOAT) T(TO_BOOL) T(ZVAL) T(VOID))
-TOKEN_CLASS(impl_type, T(VOID) T(MIXED) T(BOOL) T(INT) T(FLOAT) T(STRING) T(ARRAY) T(OBJECT) T(CALLABLE))
-TOKEN_CLASS(assert_stmt, T(PRE_ASSERT) T(POST_ASSERT))
-
-DEF(%nonassoc, NAME.)
-DEF(%right, NOT TILDE.)
-DEF(%left, AND OR.)
-DEF(%left, PIPE.)
-DEF(%left, CARET.)
-DEF(%left, AMPERSAND.)
-DEF(%left, CMP_EQ CMP_NE.)
-DEF(%left, LCHEVR CMP_LE RCHEVR CMP_GE.)
-DEF(%left, LSHIFT RSHIFT.)
-DEF(%left, PLUS MINUS.)
-DEF(%left, ASTERISK SLASH MODULO.)
-
-DEF(%fallback, NAME TEMP FREE SET LET RETURN CALLOC CALLBACK ZVAL LIB STRING COUNT.)
-
-TOKEN_TYPE(decl_enum, struct psi_decl_enum *)
-TOKEN_DTOR(decl_enum, psi_decl_enum_free(&$$);)
-TOKEN_TYPE(decl_enum_items, struct psi_plist*)
-TOKEN_DTOR(decl_enum_items, psi_plist_free($$);)
-TOKEN_TYPE(decl_enum_item, struct psi_decl_enum_item*)
-TOKEN_DTOR(decl_enum_item, psi_decl_enum_item_free(&$$);)
-TOKEN_TYPE(decl_struct_args_block, struct psi_plist*)
-TOKEN_DTOR(decl_struct_args_block, psi_plist_free($$);) /* there was a typo */
-TOKEN_TYPE(decl_struct_args, struct psi_plist*)
-TOKEN_DTOR(decl_struct_args, psi_plist_free($$);)
-TOKEN_TYPE(decl_struct, struct psi_decl_struct*)
-TOKEN_DTOR(decl_struct, psi_decl_struct_free(&$$);)
-TOKEN_TYPE(align_and_size, struct psi_layout)
-TOKEN_TYPE(decl_union, struct psi_decl_union*)
-TOKEN_DTOR(decl_union, psi_decl_union_free(&$$);)
-TOKEN_TYPE(const_type, struct psi_const_type*)
-TOKEN_DTOR(const_type, psi_const_type_free(&$$);)
-TOKEN_TYPE(constant, struct psi_const*)
-TOKEN_DTOR(constant, psi_const_free(&$$);)
-TOKEN_TYPE(decl_typedef, struct psi_decl_arg*)
-TOKEN_DTOR(decl_typedef, psi_decl_arg_free(&$$);)
-TOKEN_TYPE(decl_typedef_body_ex, struct psi_decl_arg*)
-TOKEN_DTOR(decl_typedef_body_ex, psi_decl_arg_free(&$$);)
-TOKEN_TYPE(decl_typedef_body, struct psi_decl_arg*)
-TOKEN_DTOR(decl_typedef_body, psi_decl_arg_free(&$$);)
-TOKEN_TYPE(decl_typedef_body_fn_args, struct psi_plist*)
-TOKEN_DTOR(decl_typedef_body_fn_args, psi_plist_free($$);)
-TOKEN_TYPE(decl, struct psi_decl*)
-TOKEN_DTOR(decl, psi_decl_free(&$$);)
-TOKEN_TYPE(decl_func, struct psi_decl_arg*)
-TOKEN_DTOR(decl_func, psi_decl_arg_free(&$$);)
-TOKEN_TYPE(decl_abi, struct psi_decl_abi*)
-TOKEN_DTOR(decl_abi, psi_decl_abi_free(&$$);)
-TOKEN_TYPE(decl_var, struct psi_decl_var*)
-TOKEN_DTOR(decl_var, psi_decl_var_free(&$$);)
-TOKEN_TYPE(decl_vars, struct psi_plist*)
-TOKEN_DTOR(decl_vars, psi_plist_free($$);)
-TOKEN_TYPE(decl_arg, struct psi_decl_arg*)
-TOKEN_DTOR(decl_arg, psi_decl_arg_free(&$$);)
-TOKEN_TYPE(decl_args, struct psi_plist*)
-TOKEN_DTOR(decl_args, psi_plist_free($$);)
-TOKEN_TYPE(struct_args, struct psi_plist*)
-TOKEN_DTOR(struct_args, psi_plist_free($$);)
-TOKEN_TYPE(struct_arg, struct psi_decl_arg*)
-TOKEN_DTOR(struct_arg, psi_decl_arg_free(&$$);)
-TOKEN_TYPE(decl_layout, struct psi_layout*)
-TOKEN_DTOR(decl_layout, psi_layout_free(&$$);)
-TOKEN_TYPE(decl_type, struct psi_decl_type*)
-TOKEN_DTOR(decl_type, psi_decl_type_free(&$$);)
-TOKEN_TYPE(const_decl_type, struct psi_decl_type*)
-TOKEN_DTOR(const_decl_type, psi_decl_type_free(&$$);)
-TOKEN_TYPE(impl, struct psi_impl*)
-TOKEN_DTOR(impl, psi_impl_free(&$$);)
-TOKEN_TYPE(impl_func, struct psi_impl_func*)
-TOKEN_DTOR(impl_func, psi_impl_func_free(&$$);)
-TOKEN_TYPE(impl_def_val, struct psi_impl_def_val*)
-TOKEN_DTOR(impl_def_val, psi_impl_def_val_free(&$$);)
-TOKEN_TYPE(impl_var, struct psi_impl_var*)
-TOKEN_DTOR(impl_var, psi_impl_var_free(&$$);)
-TOKEN_TYPE(impl_arg, struct psi_impl_arg*)
-TOKEN_DTOR(impl_arg, psi_impl_arg_free(&$$);)
-TOKEN_TYPE(impl_args, struct psi_plist*)
-TOKEN_DTOR(impl_args, psi_plist_free($$);)
-TOKEN_TYPE(impl_vararg, struct psi_impl_arg*)
-TOKEN_DTOR(impl_vararg, psi_impl_arg_free(&$$);)
-TOKEN_TYPE(impl_stmts, struct psi_plist*)
-TOKEN_DTOR(impl_stmts, psi_plist_free($$);)
-TOKEN_TYPE(impl_stmt, struct psi_token**)
-TOKEN_DTOR(impl_stmt, psi_impl_stmt_free(&$$);)
-TOKEN_TYPE(number, struct psi_number*)
-TOKEN_DTOR(number, psi_number_free(&$$);)
-TOKEN_TYPE(num_exp, struct psi_num_exp*)
-TOKEN_DTOR(num_exp, psi_num_exp_free(&$$);)
-TOKEN_TYPE(let_stmt, struct psi_let_stmt*)
-TOKEN_DTOR(let_stmt, psi_let_stmt_free(&$$);)
-TOKEN_TYPE(let_calloc, struct psi_let_calloc*)
-TOKEN_DTOR(let_calloc, psi_let_calloc_free(&$$);)
-TOKEN_TYPE(let_func, struct psi_let_func*)
-TOKEN_DTOR(let_func, psi_let_func_free(&$$);)
-TOKEN_TYPE(callback_arg_list, struct psi_plist *)
-TOKEN_DTOR(callback_arg_list, psi_plist_free($$);)
-TOKEN_TYPE(callback_args, struct psi_plist *)
-TOKEN_DTOR(callback_args, psi_plist_free($$);)
-TOKEN_TYPE(let_callback, struct psi_let_callback*)
-TOKEN_DTOR(let_callback, psi_let_callback_free(&$$);)
-TOKEN_TYPE(let_exp, struct psi_let_exp*)
-TOKEN_DTOR(let_exp, psi_let_exp_free(&$$);)
-TOKEN_TYPE(let_exps, struct psi_plist*)
-TOKEN_DTOR(let_exps, psi_plist_free($$);)
-TOKEN_TYPE(assert_stmt, struct psi_assert_stmt*)
-TOKEN_DTOR(assert_stmt, psi_assert_stmt_free(&$$);)
-TOKEN_TYPE(set_stmt, struct psi_set_stmt*)
-TOKEN_DTOR(set_stmt, psi_set_stmt_free(&$$);)
-TOKEN_TYPE(set_exp, struct psi_set_exp*)
-TOKEN_DTOR(set_exp, psi_set_exp_free(&$$);)
-TOKEN_TYPE(set_exps, struct psi_plist*)
-TOKEN_DTOR(set_exps, psi_plist_free($$);)
-TOKEN_TYPE(set_func, struct psi_set_func*)
-TOKEN_DTOR(set_func, psi_set_func_free(&$$);)
-TOKEN_TYPE(return_stmt, struct psi_return_stmt*)
-TOKEN_DTOR(return_stmt, psi_return_stmt_free(&$$);)
-TOKEN_TYPE(free_stmt, struct psi_free_stmt*)
-TOKEN_DTOR(free_stmt, psi_free_stmt_free(&$$);)
-TOKEN_TYPE(free_exps, struct psi_plist*)
-TOKEN_DTOR(free_exps, psi_plist_free($$);)
-TOKEN_TYPE(free_exp, struct psi_free_exp*)
-TOKEN_DTOR(free_exp, psi_free_exp_free(&$$);)
-TOKEN_TYPE(impl_type, struct psi_impl_type*)
-TOKEN_DTOR(impl_type, psi_impl_type_free(&$$);)
-TOKEN_TYPE(reference, bool)
-TOKEN_TYPE(indirection, unsigned)
-TOKEN_TYPE(pointers, unsigned)
-
-PASS(file, blocks)
-PASS(blocks, block)
-PASS(blocks, blocks block)
-
-PASS(block, EOF)
-PASS(block, EOS)
-
-/*
- * lib: LIB "soname" ;
- */
-PARSE(block, NAMED(LIB, token) NAMED(QUOTED_STRING, libname) TOKEN(EOS)) {
-       if (P->file.ln) {
-               P->error(PSI_DATA(P), token, PSI_WARNING, "Extra 'lib %s' statement has no effect", libname->text);
-       } else {
-               P->file.ln = strndup(libname->text + 1, libname->size - 2);
-       }
-       free(libname);
-       free(token);
-}
-
-PARSE(block, TYPED(decl, decl)) {
-       if (!P->decls) {
-               P->decls = psi_plist_init((psi_plist_dtor) psi_decl_free);
-       }
-       P->decls = psi_plist_add(P->decls, &decl);
-}
-
-PARSE(block, TYPED(impl, impl)) {
-       if (!P->impls) {
-               P->impls = psi_plist_init((psi_plist_dtor) psi_impl_free);
-       }
-       P->impls = psi_plist_add(P->impls, &impl);
-}
-
-PARSE(block, TYPED(decl_typedef, def)) {
-       if (!P->types) {
-               P->types = psi_plist_init((psi_plist_dtor) psi_decl_arg_free);
-       }
-       P->types = psi_plist_add(P->types, &def);
-
-       switch (def->type->type) {
-       case PSI_T_STRUCT:
-               if (def->type->real.strct) {
-                       if (!P->structs) {
-                               P->structs = psi_plist_init((psi_plist_dtor) psi_decl_struct_free);
-                       }
-                       P->structs = psi_plist_add(P->structs, &def->type->real.strct);
-               }
-               break;
-       case PSI_T_UNION:
-               if (def->type->real.unn) {
-                       if (!P->unions) {
-                               P->unions = psi_plist_init((psi_plist_dtor) psi_decl_union_free);
-                       }
-                       P->unions = psi_plist_add(P->unions, &def->type->real.unn);
-               }
-               break;
-       case PSI_T_ENUM:
-               if (def->type->real.enm) {
-                       if (!P->enums) {
-                               P->enums = psi_plist_init((psi_plist_dtor) psi_decl_enum_free);
-                       }
-                       P->enums = psi_plist_add(P->enums, &def->type->real.enm);
-               }
-               break;
-       }
-}
-
-PARSE(block, TYPED(constant, constant)) {
-       if (!P->consts) {
-               P->consts = psi_plist_init((psi_plist_dtor) psi_const_free);
-       }
-       P->consts = psi_plist_add(P->consts, &constant);
-}
-
-PARSE(block, TYPED(decl_struct, strct)) {
-       if (!P->structs) {
-               P->structs = psi_plist_init((psi_plist_dtor) psi_decl_struct_free);
-       }
-       P->structs = psi_plist_add(P->structs, &strct);
-}
-
-PARSE(block, TYPED(decl_union, u)) {
-       if (!P->unions) {
-               P->unions = psi_plist_init((psi_plist_dtor) psi_decl_union_free);
-       }
-       P->unions = psi_plist_add(P->unions, &u);
-}
-
-PARSE(block, TYPED(decl_enum, e)) {
-       if (!P->enums) {
-               P->enums = psi_plist_init((psi_plist_dtor) psi_decl_enum_free);
-       }
-       P->enums = psi_plist_add(P->enums, &e);
-}
-
-/*
- * optional_name: <empty>
- */
-PARSE_NAMED(optional_name, n, ) {
-       n = NULL;
-}
-
-/*
- * optional_name: NAME
- */
-PARSE_NAMED(optional_name, n,
-               NAMED(NAME, N)) {
-       n = N;
-}
-
-/*
- * align_and_size: <empty>
- */
-PARSE_TYPED(align_and_size, as, ) {
-       as.pos = 0;
-       as.len = 0;
-}
-
-/*
- * align_and_size: :: ( NUMBER , NUMBER )
- */
-PARSE_TYPED(align_and_size, as,
-               TOKEN(COLON)
-               TOKEN(COLON)
-               TOKEN(LPAREN)
-               NAMED(NUMBER, A)
-               TOKEN(COMMA)
-               NAMED(NUMBER, S)
-               TOKEN(RPAREN)) {
-       as.pos = atol(A->text);
-       as.len = atol(S->text);
-       free(A);
-       free(S);
-}
-
-/*
- * enum_name: ENUM optional_name
- */
-PARSE_NAMED(enum_name, n,
-               NAMED(ENUM, E)
-               NAMED(optional_name, N)) {
-       if (N) {
-               n = N;
-               free(E);
-       } else {
-               char digest[17];
-
-               psi_token_hash(E, digest);
-               n = psi_token_translit(psi_token_append(E, 1, digest), " ", "@");
-       }
-}
-
-/*
- * struct_name: STRUCT optional_name
- */
-PARSE_NAMED(struct_name, n,
-               NAMED(STRUCT, S)
-               NAMED(optional_name, N)) {
-       if (N) {
-               n = N;
-               free(S);
-       } else {
-               char digest[17];
-
-               psi_token_hash(S, digest);
-               n = psi_token_translit(psi_token_append(S, 1, digest), " ", "@");
-       }
-}
-
-/*
- * union_name: UNION optional_name
- */
-PARSE_NAMED(union_name, n,
-               NAMED(UNION, U)
-               NAMED(optional_name, N)) {
-       if (N) {
-               n = N;
-               free(U);
-       } else {
-               char digest[17];
-
-               psi_token_hash(U, digest);
-               n = psi_token_translit(psi_token_append(U, 1, digest), " ", "@");
-       }
-}
-
-/*
- * decl_enum: enum_name { items }
- */
-PARSE_TYPED(decl_enum, e,
-               NAMED(enum_name, N)
-               TOKEN(LBRACE)
-               TYPED(decl_enum_items, list)
-               TOKEN(RBRACE)) {
-       e = psi_decl_enum_init(N->text, list);
-       e->token = N;
-}
-
-/*
- * decl_enum_items: item
- */
-PARSE_TYPED(decl_enum_items, l,
-               TYPED(decl_enum_item, i)) {
-       l = psi_plist_add(psi_plist_init((psi_plist_dtor) psi_decl_enum_item_free),
-                       &i);
-}
-
-/*
- * decl_enum_items: items , item
- */
-PARSE_TYPED(decl_enum_items, l,
-               TYPED(decl_enum_items, l_)
-               TOKEN(COMMA)
-               TYPED(decl_enum_item, i)) {
-       l = psi_plist_add(l_, &i);
-}
-
-/*
- * decl_enum_item: name = num_exp
- */
-PARSE_TYPED(decl_enum_item, i,
-               NAMED(NAME, N)
-               TOKEN(EQUALS)
-               TYPED(num_exp, num)) {
-       i = psi_decl_enum_item_init(N->text, num);
-       i->token = N;
-}
-
-/*
- * decl_enum_item: name
- */
-PARSE_TYPED(decl_enum_item, i,
-               NAMED(NAME, N)) {
-       i = psi_decl_enum_item_init(N->text, NULL);
-       i->token = N;
-}
-
-
-/*
- * decl_struct_args_block: { args }
- */
-PARSE_TYPED(decl_struct_args_block, args_,
-               TOKEN(LBRACE)
-               TYPED(struct_args, args)
-               TOKEN(RBRACE)) {
-       args_ = args;
-}
-
-/*
- * decl_struct_args: args_block
- */
-PARSE_TYPED(decl_struct_args, args_,
-               TYPED(decl_struct_args_block, args)) {
-       args_ = args;
-}
-
-/*
- * decl_struct_args: ;
- */
-PARSE_TYPED(decl_struct_args, args_,
-               TOKEN(EOS)) {
-       args_ = psi_plist_init((psi_plist_dtor) psi_decl_arg_free);
-}
-
-/*
- * decl_struct: STRUCT name align_and_size struct_args
- */
-PARSE_TYPED(decl_struct, strct,
-               TOKEN(STRUCT)
-               NAMED(NAME, N)
-               TYPED(align_and_size, as)
-               TYPED(decl_struct_args, args)) {
-       strct = psi_decl_struct_init(N->text, args);
-       strct->align = as.pos;
-       strct->size = as.len;
-       strct->token = N;
-}
-
-/*
- * decl_union: UNION name align_and_size struct_args
- */
-PARSE_TYPED(decl_union, u,
-               TOKEN(UNION)
-               NAMED(NAME, N)
-               TYPED(align_and_size, as)
-               TYPED(decl_struct_args, args)) {
-       u = psi_decl_union_init(N->text, args);
-       u->align = as.pos;
-       u->size = as.len;
-       u->token = N;
-}
-
-/*
- * const_type: const_type_token
- */
-PARSE_TYPED(const_type, type_,
-               NAMED(const_type_token, T)) {
-       type_ = psi_const_type_init(T->type, T->text);
-       free(T);
-}
-
-/*
- * constant: CONST const_type NSNAME = def_val ;
- */
-PARSE_TYPED(constant, constant,
-               TOKEN(CONST)
-               TYPED(const_type, type)
-               NAMED(NSNAME, T)
-               TOKEN(EQUALS)
-               TYPED(impl_def_val, val)
-               TOKEN(EOS)) {
-       constant = psi_const_init(type, T->text, val);
-       constant->token = T;
-}
-
-/*
- * decl_typdef: TYPEDEF typedef_body ;
- */
-PARSE_TYPED(decl_typedef, def,
-               NAMED(TYPEDEF, T)
-               TYPED(decl_typedef_body, def_)
-               TOKEN(EOS)) {
-       def = def_;
-       def->token = T;
-}
-
-/*
- * decl_typedef_body_ex: struct_name align_and_size struct_args_block decl_var
- */
-PARSE_TYPED(decl_typedef_body_ex, def,
-               NAMED(struct_name, N)
-               TYPED(align_and_size, as)
-               TYPED(decl_struct_args_block, args)
-               TYPED(decl_var, var)) {
-       def = psi_decl_arg_init(psi_decl_type_init(PSI_T_STRUCT, N->text), var);
-       def->type->token = psi_token_copy(N);
-       def->type->real.strct = psi_decl_struct_init(N->text, args);
-       def->type->real.strct->token = N;
-       def->type->real.strct->align = as.pos;
-       def->type->real.strct->size = as.len;
-}
-
-/*
- * decl_typedef_body_ex: union_name align_and_size struct_args_block decl_var
- */
-PARSE_TYPED(decl_typedef_body_ex, def,
-               NAMED(union_name, N)
-               TYPED(align_and_size, as)
-               TYPED(decl_struct_args_block, args)
-               TYPED(decl_var, var)) {
-       def = psi_decl_arg_init(psi_decl_type_init(PSI_T_UNION, N->text), var);
-       def->type->token = psi_token_copy(N);
-       def->type->real.unn = psi_decl_union_init(N->text, args);
-       def->type->real.unn->token = N;
-       def->type->real.unn->align = as.pos;
-       def->type->real.unn->size = as.len;
-}
-
-/*
- * decl_typedef_body_ex: decl_enum NAME
- */
-PARSE_TYPED(decl_typedef_body_ex, def,
-               TYPED(decl_enum, e)
-               NAMED(NAME, ALIAS)) {
-       def = psi_decl_arg_init(psi_decl_type_init(PSI_T_ENUM, e->name), psi_decl_var_init(ALIAS->text, 0, 0));
-       def->var->token = ALIAS;
-       def->type->token = psi_token_copy(e->token);
-       def->type->real.enm = e;
-}
-
-/*
- * decl_typedef_body: decl_typedef_body_ex
- */
-PARSE_TYPED(decl_typedef_body, def,
-               TYPED(decl_typedef_body_ex, def_)) {
-       def = def_;
-}
-
-/*
- * decl_typedef_body_fn_args: ( decl_args )
- */
-PARSE_TYPED(decl_typedef_body_fn_args, args,
-               TOKEN(LPAREN)
-               TYPED(decl_args, args_)
-               TOKEN(RPAREN)) {
-       args = args_;
-}
-
-/*
- * decl_typedef_body: decl_func decl_typedef_body_fn_args
- */
-PARSE_TYPED(decl_typedef_body, def,
-               TYPED(decl_func, func_)
-               TYPED(decl_typedef_body_fn_args, args)) {
-       def = psi_decl_arg_init(psi_decl_type_init(PSI_T_FUNCTION, func_->var->name), psi_decl_var_copy(func_->var));
-       def->type->token = psi_token_copy(func_->token);
-       def->type->real.func = psi_decl_init(psi_decl_abi_init("default"), func_, args);
-}
-
-/*
- * decl_typedef_body: decl_arg
- */
-PARSE_TYPED(decl_typedef_body, def,
-               TYPED(decl_arg, arg)) {
-       def = arg;
-}
-
-/*
- * decl: decl_abi decl_func ( decl_args ) ;
- */
-PARSE_TYPED(decl, decl,
-               TYPED(decl_abi, abi)
-               TYPED(decl_func, func)
-               TOKEN(LPAREN)
-               TYPED(decl_args, args)
-               TOKEN(RPAREN)
-               TOKEN(EOS)) {
-       decl = psi_decl_init(abi, func, args);
-}
-
-/*
- * decl: decl_abi decl_func ( decl_args , ... ) ;
- */
-PARSE_TYPED(decl, decl,
-               TYPED(decl_abi, abi)
-               TYPED(decl_func, func)
-               TOKEN(LPAREN)
-               TYPED(decl_args, args)
-               TOKEN(COMMA)
-               TOKEN(ELLIPSIS)
-               TOKEN(RPAREN)
-               TOKEN(EOS)) {
-       decl = psi_decl_init(abi, func, args);
-       decl->varargs = 1;
-}
-
-/*
- * decl_func: decl_arg
- */
-PARSE_TYPED(decl_func, func,
-               TYPED(decl_arg, arg)) {
-       func = arg;
-}
-
-/* special case for void functions */
-/*
- * decl_func: VOID NAME
- */
-PARSE_TYPED(decl_func, func,
-               NAMED(VOID, T)
-               NAMED(NAME, N)) {
-       func = psi_decl_arg_init(
-               psi_decl_type_init(T->type, T->text),
-               psi_decl_var_init(N->text, 0, 0)
-       );
-       func->type->token = T;
-       func->var->token = N;
-       func->token = N;
-}
-
-/*
- * decl_typedef_body: VOID indirection ( indirection NAME ) decl_typedef_body_fn_args
- */
-PARSE_TYPED(decl_typedef_body, def,
-               NAMED(VOID, T)
-               TYPED(indirection, decl_i)
-               TOKEN(LPAREN)
-               TYPED(indirection, type_i)
-               NAMED(NAME, N)
-               TOKEN(RPAREN)
-               TYPED(decl_typedef_body_fn_args, args)) {
-       struct psi_decl_arg *func_ = psi_decl_arg_init(
-               psi_decl_type_init(T->type, T->text),
-               psi_decl_var_init(N->text, decl_i, 0)
-       );
-       func_->type->token = T;
-       func_->var->token = N;
-       func_->token = N;
-
-       def = psi_decl_arg_init(
-               psi_decl_type_init(PSI_T_FUNCTION, func_->var->name),
-               psi_decl_var_copy(func_->var)
-       );
-       def->var->pointer_level = type_i;
-       def->type->token = psi_token_copy(func_->token);
-       def->type->real.func = psi_decl_init(psi_decl_abi_init("default"), func_, args);
-}
-
-/*
- * decl_typedef_body: CONST VOID pointers ( indirection NAME ) decl_typdef_body_fn_args
- */
-PARSE_TYPED(decl_typedef_body, def,
-               TOKEN(CONST)
-               NAMED(VOID, T)
-               TYPED(pointers, decl_i)
-               TOKEN(LPAREN)
-               TYPED(indirection, type_i)
-               NAMED(NAME, N)
-               TOKEN(RPAREN)
-               TYPED(decl_typedef_body_fn_args, args)) {
-       struct psi_decl_arg *func_ = psi_decl_arg_init(
-               psi_decl_type_init(T->type, T->text),
-               psi_decl_var_init(N->text, decl_i, 0)
-       );
-       func_->type->token = T;
-       func_->var->token = N;
-       func_->token = N;
-
-       def = psi_decl_arg_init(
-               psi_decl_type_init(PSI_T_FUNCTION, func_->var->name),
-               psi_decl_var_copy(func_->var)
-       );
-       def->var->pointer_level = type_i;
-       def->type->token = psi_token_copy(func_->token);
-       def->type->real.func = psi_decl_init(psi_decl_abi_init("default"), func_, args);
-}
-
-/*
- * decl_abi: NAME
- */
-PARSE_TYPED(decl_abi, abi,
-               NAMED(NAME, T)) {
-       abi = psi_decl_abi_init(T->text);
-       abi->token = T;
-}
-
-/*
- * decl_var_array_size: <empty>
- */
-PARSE_NAMED(decl_var_array_size, as, ) {
-       as = NULL;
-}
-
-/*
- * decl_var_array_size: [ NUMBER ]
- */
-PARSE_NAMED(decl_var_array_size, as,
-               TOKEN(LBRACKET)
-               NAMED(NUMBER, D)
-               TOKEN(RBRACKET)) {
-       as = D;
-}
-
-/*
- * decl_var: NAME decl_var_array_size
- */
-PARSE_TYPED(decl_var, var,
-               NAMED(NAME, T)
-               NAMED(decl_var_array_size, as)) {
-       var = psi_decl_var_init(T->text, 0, as?atol(as->text):0);
-       var->token = T;
-       if (as) {
-               free(as);
-       }
-}
-
-/*
- * decl_var: pointers NAME
- */
-PARSE_TYPED(decl_var, var,
-               TYPED(pointers, p)
-               NAMED(NAME, T)
-               NAMED(decl_var_array_size, as)) {
-       var = psi_decl_var_init(T->text, p+!!as, as?atol(as->text):0);
-       var->token = T;
-       if (as) {
-               free(as);
-       }
-}
-
-/*
- * decl_vars: decl_var
- */
-PARSE_TYPED(decl_vars, vars,
-               TYPED(decl_var, var)) {
-       vars = psi_plist_add(psi_plist_init((psi_plist_dtor) psi_decl_var_free),
-                       &var);
-}
-
-/*
- * decl_vars: decl_vars , decl_var
- */
-PARSE_TYPED(decl_vars, vars,
-               TYPED(decl_vars, vars_)
-               TOKEN(COMMA)
-               TYPED(decl_var, var)) {
-       vars = psi_plist_add(vars_, &var);
-}
-
-/*
- * decl_arg: const_decl_type decl_var
- */
-PARSE_TYPED(decl_arg, arg_,
-               TYPED(const_decl_type, type)
-               TYPED(decl_var, var)) {
-       arg_ = psi_decl_arg_init(type, var);
-}
-
-/*
- * decl_typedef_body: const_decl_type indirection ( indirection NAME ) decl_typedef_body_fn_args
- */
-PARSE_TYPED(decl_typedef_body, def,
-               TYPED(const_decl_type, type_)
-               TYPED(indirection, decl_i)
-               TOKEN(LPAREN)
-               TYPED(indirection, type_i)
-               NAMED(NAME, N)
-               TOKEN(RPAREN)
-               TYPED(decl_typedef_body_fn_args, args)) {
-       struct psi_decl_arg *func_ = psi_decl_arg_init(
-               type_,
-               psi_decl_var_init(N->text, decl_i, 0)
-       );
-       func_->var->token = N;
-       func_->token = N;
-
-       def = psi_decl_arg_init(
-               psi_decl_type_init(PSI_T_FUNCTION, func_->var->name),
-               psi_decl_var_copy(func_->var)
-       );
-       def->var->pointer_level = type_i;
-       def->type->token = psi_token_copy(func_->token);
-       def->type->real.func = psi_decl_init(psi_decl_abi_init("default"), func_, args);
-}
-
-/* void pointers need a specific rule */
-/*
- * decl_arg: VOID pointers NAME
- */
-PARSE_TYPED(decl_arg, arg_,
-               NAMED(VOID, T)
-               TYPED(pointers, p)
-               NAMED(NAME, N)) {
-       arg_ = psi_decl_arg_init(
-               psi_decl_type_init(T->type, T->text),
-               psi_decl_var_init(N->text, p, 0)
-       );
-       arg_->type->token = T;
-       arg_->var->token = N;
-       arg_->token = N;
-}
-
-/*
- * decl_args: CONST VOID pointers NAME
- */
-PARSE_TYPED(decl_arg, arg_,
-               TOKEN(CONST)
-               NAMED(VOID, T)
-               TYPED(pointers, p)
-               NAMED(NAME, N)) {
-       arg_ = psi_decl_arg_init(
-               psi_decl_type_init(T->type, T->text),
-               psi_decl_var_init(N->text, p, 0)
-       );
-       arg_->type->token = T;
-       arg_->var->token = N;
-       arg_->token = N;
-}
-
-/*
- * decl_args: <empty>
- */
-PARSE_TYPED(decl_args, args, ) {
-       args = NULL;
-}
-
-/*
- * decl_args: VOID
- */
-PARSE_TYPED(decl_args, args,
-               TOKEN(VOID)) {
-       args = NULL;
-}
-
-/*
- * decl_args: decl_arg
- */
-PARSE_TYPED(decl_args, args,
-               TYPED(decl_arg, arg)) {
-       args = psi_plist_add(psi_plist_init((psi_plist_dtor) psi_decl_arg_free),
-                       &arg);
-}
-
-/*
- * decl_args: decl_args , decl_arg
- */
-PARSE_TYPED(decl_args, args,
-               TYPED(decl_args, args_)
-               TOKEN(COMMA)
-               TYPED(decl_arg, arg)) {
-       args = psi_plist_add(args_, &arg);
-}
-
-/*
- * struct_args: struct_arg
- */
-PARSE_TYPED(struct_args, args,
-               TYPED(struct_arg, arg)) {
-       args = psi_plist_add(psi_plist_init((psi_plist_dtor) psi_decl_arg_free),
-                       &arg);
-}
-
-/*
- * struct_args: struct_args , struct_arg
- */
-PARSE_TYPED(struct_args, args,
-               TYPED(struct_args, args_)
-               TYPED(struct_arg, arg)) {
-       args = psi_plist_add(args_, &arg);
-}
-
-/*
- * struct_arg: decl_typedef_body_ex ;
- */
-PARSE_TYPED(struct_arg, arg_,
-               TYPED(decl_typedef_body_ex, def)
-               TOKEN(EOS)) {
-       arg_ = def;
-       switch (def->type->type) {
-       case PSI_T_STRUCT:
-               if (def->type->real.strct) {
-                       if (!P->structs) {
-                               P->structs = psi_plist_init((psi_plist_dtor) psi_decl_struct_free);
-                       }
-                       P->structs = psi_plist_add(P->structs, &def->type->real.strct);
-               }
-               break;
-       case PSI_T_UNION:
-               if (def->type->real.unn) {
-                       if (!P->unions) {
-                               P->unions = psi_plist_init((psi_plist_dtor) psi_decl_union_free);
-                       }
-                       P->unions = psi_plist_add(P->unions, &def->type->real.unn);
-               }
-               break;
-       case PSI_T_ENUM:
-               if (def->type->real.enm) {
-                       if (!P->enums) {
-                               P->enums = psi_plist_init((psi_plist_dtor) psi_decl_enum_free);
-                       }
-                       P->enums = psi_plist_add(P->enums, &def->type->real.enm);
-               }
-               break;
-       }
-}
-
-/*
- * struct_arg: decl_arg decl_layout ;
- */
-PARSE_TYPED(struct_arg, arg,
-               TYPED(decl_arg, arg_)
-               TYPED(decl_layout, layout_)
-               TOKEN(EOS)) {
-       arg_->layout = layout_;
-       arg = arg_;
-}
-
-/*
- * decl_layout: <empty>
- */
-PARSE_TYPED(decl_layout, layout, ) {
-       layout = NULL;
-}
-
-/*
- * decl_layout: :: ( NUMBER , NUMBER )
- */
-PARSE_TYPED(decl_layout, layout,
-               TOKEN(COLON)
-               TOKEN(COLON)
-               TOKEN(LPAREN)
-               NAMED(NUMBER, POS)
-               TOKEN(COMMA)
-               NAMED(NUMBER, SIZ)
-               TOKEN(RPAREN)) {
-       layout = psi_layout_init(atol(POS->text), atol(SIZ->text));
-       free(POS);
-       free(SIZ);
-}
 
-/* un/signed, urgh */
-/*
- * decl_scalar_type: CHAR
- */
-PARSE_NAMED(decl_scalar_type, type_,
-               NAMED(CHAR, C)) {
-       type_ = C;
-}
-
-/*
- * decl_scalar_type: SHORT decl_scalar_type_short
- */
-PARSE_NAMED(decl_scalar_type, type_,
-               NAMED(SHORT, S)
-               NAMED(decl_scalar_type_short, s)) {
-       if (s) {
-               type_ = psi_token_cat(2, S, s);
-               free(S);
-               free(s);
-       } else {
-               type_ = S;
-       }
-}
-
-/*
- * decl_scalar_type_short: <empty>
- */
-PARSE_NAMED(decl_scalar_type_short, s, ) {
-       s = NULL;
-}
-
-/*
- * decl_scalar_type_short: INT
- */
-PARSE_NAMED(decl_scalar_type_short, s,
-               NAMED(INT, I)) {
-       s = I;
-}
-
-/*
- * decl_sclara_type: INT
- */
-PARSE_NAMED(decl_scalar_type, type_,
-               NAMED(INT, I)) {
-       type_ = I;
-}
-
-/*
- * decl_scalar_type: LONG decl_scalar_type_long
- */
-PARSE_NAMED(decl_scalar_type, type_,
-               NAMED(LONG, L)
-               NAMED(decl_scalar_type_long, l)) {
-       if (l) {
-               type_ = psi_token_cat(2, L, l);
-               free(L);
-               free(l);
-       } else {
-               type_ = L;
-       }
-}
-
-/*
- * decl_scalar_type_long: <empty>
- */
-PARSE_NAMED(decl_scalar_type_long, l, ) {
-       l = NULL;
-}
-
-/*
- * decl_scalar_type_long: DOUBLE
- */
-PARSE_NAMED(decl_scalar_type_long, l,
-               NAMED(DOUBLE, D)) {
-       l = D;
-}
-
-/*
- * decl_scalar_type_long: LONG decl_scalar_type_long_long
- */
-PARSE_NAMED(decl_scalar_type_long, l,
-               NAMED(LONG, L)
-               NAMED(decl_scalar_type_long_long, ll)) {
-       if (ll) {
-               l = psi_token_cat(2, L, ll);
-               free(L);
-               free(ll);
-       } else {
-               l = L;
-       }
-}
-
-/*
- * decl_scalar_type_long_long: <empty>
- */
-PARSE_NAMED(decl_scalar_type_long_long, ll, ) {
-       ll = NULL;
-}
-
-/*
- * decl_scalar_type_long_long: INT
- */
-PARSE_NAMED(decl_scalar_type_long_long, ll,
-               NAMED(INT, I)) {
-       ll = I;
-}
-
-/*
- * decl_type: UNSIGNED decl_scalar_type
- */
-PARSE_TYPED(decl_type, type_,
-               NAMED(UNSIGNED, U)
-               NAMED(decl_scalar_type, N)) {
-       struct psi_token *T = psi_token_cat(2, U, N);
-       type_ = psi_decl_type_init(T->type, T->text);
-       type_->token = T;
-       free(U);
-       free(N);
-}
-
-/*
- * decl_type: SIGNED decl_scalar_type
- */
-PARSE_TYPED(decl_type, type_,
-               NAMED(SIGNED, S)
-               NAMED(decl_scalar_type, N)) {
-       struct psi_token *T = psi_token_cat(2, S, N);
-       type_ = psi_decl_type_init(T->type, T->text);
-       type_->token = T;
-       free(S);
-       free(N);
-}
-
-/*
- * decl_type: UNSIGNED
- */
-PARSE_TYPED(decl_type, type_,
-               NAMED(UNSIGNED, U)) {
-       type_ = psi_decl_type_init(PSI_T_NAME, U->text);
-       type_->token = U;
-}
-
-/*
- * decl_type: SIGNED
- */
-PARSE_TYPED(decl_type, type_,
-               NAMED(SIGNED, S)) {
-       type_ = psi_decl_type_init(PSI_T_NAME, S->text);
-       type_->token = S;
-}
-
-/*
- * decl_type: decl_scalar_type
- */
-PARSE_TYPED(decl_type, type_,
-               NAMED(decl_scalar_type, N)) {
-       type_ = psi_decl_type_init(N->type, N->text);
-       type_->token = N;
-}
-
-/* structs ! */
-/*
- * decl_type: STRUCT NAME
- */
-PARSE_TYPED(decl_type, type_,
-               NAMED(STRUCT, S)
-               NAMED(NAME, T)) {
-       type_ = psi_decl_type_init(S->type, T->text);
-       type_->token = T;
-       free(S);
-}
-
-/*
- * decl_type: UNION NAME
- */
-PARSE_TYPED(decl_type, type_,
-               NAMED(UNION, U)
-               NAMED(NAME, T)) {
-       type_ = psi_decl_type_init(U->type, T->text);
-       type_->token = T;
-       free(U);
-}
-
-/*
- * decl_type: ENUM NAME
- */
-PARSE_TYPED(decl_type, type_,
-               NAMED(ENUM, E)
-               NAMED(NAME, T)) {
-       type_ = psi_decl_type_init(E->type, T->text);
-       type_->token = T;
-       free(E);
-}
-
-/*
- * decl_type: decl_type_token
- */
-PARSE_TYPED(decl_type, type_,
-               NAMED(decl_type_token, T)) {
-       type_ = psi_decl_type_init(T->type, T->text);
-       type_->token = T;
-}
-
-/*
- * const_decl_type: decl_type
- */
-PARSE_TYPED(const_decl_type, type,
-               TYPED(decl_type, type_)) {
-       type = type_;
-}
-
-/*
- * const_decl_type: CONST decl_type
- */
-PARSE_TYPED(const_decl_type, type,
-               TOKEN(CONST)
-               TYPED(decl_type, type_)) {
-       type = type_;
-}
-
-/*
- * impl: impl_func { impl_stmts }
- */
-PARSE_TYPED(impl, impl,
-               TYPED(impl_func, func)
-               TOKEN(LBRACE)
-               TYPED(impl_stmts, stmts)
-               TOKEN(RBRACE)) {
-       impl = psi_impl_init(func, stmts);
-}
-
-/*
- * impl: STATIC impl_func { impl_stmts }
- */
-PARSE_TYPED(impl, impl,
-               TOKEN(STATIC)
-               TYPED(impl_func, func)
-               TOKEN(LBRACE)
-               TYPED(impl_stmts, stmts)
-               TOKEN(RBRACE)) {
-       func->static_memory = 1;
-       impl = psi_impl_init(func, stmts);
-}
-
-/*
- * impl_func: FUNCTION reference NSNAME ( ) : impl_type
- */
-PARSE_TYPED(impl_func, func,
-               TOKEN(FUNCTION)
-               TYPED(reference, r)
-               NAMED(NSNAME, NAME)
-               TOKEN(LPAREN)
-               TOKEN(RPAREN)
-               TOKEN(COLON)
-               TYPED(impl_type, type)) {
-       func = psi_impl_func_init(NAME->text, NULL, type);
-       func->token = NAME;
-       func->return_reference = r;
-}
-
-/*
- * impl_func: FUNCTION reference NSNAME ( impl_args ) : impl_type
- */
-PARSE_TYPED(impl_func, func,
-               TOKEN(FUNCTION)
-               TYPED(reference, r)
-               NAMED(NSNAME, NAME)
-               TOKEN(LPAREN)
-               TYPED(impl_args, args)
-               TOKEN(RPAREN)
-               TOKEN(COLON)
-               TYPED(impl_type, type)) {
-       func = psi_impl_func_init(NAME->text, args, type);
-       func->token = NAME;
-       func->return_reference = r;
-}
-
-/*
- * impl_func: FUNCTION reference NSNAME ( impl_args , impl_type reference ... DOLLAR_NAME ) : impl_type
- */
-PARSE_TYPED(impl_func, func,
-               TOKEN(FUNCTION)
-               TYPED(reference, func_r)
-               NAMED(NSNAME, NAME)
-               TOKEN(LPAREN)
-               TYPED(impl_args, args)
-               TOKEN(COMMA)
-               TYPED(impl_type, va_type)
-               TYPED(reference, va_r)
-               TOKEN(ELLIPSIS)
-               NAMED(DOLLAR_NAME, T)
-               TOKEN(RPAREN)
-               TOKEN(COLON)
-               TYPED(impl_type, func_type)) {
-       func = psi_impl_func_init(NAME->text, args, func_type);
-       func->token = NAME;
-       func->return_reference = func_r;
-       func->vararg = psi_impl_arg_init(va_type, psi_impl_var_init(T->text, va_r), NULL);
-       free(T);
-}
-
-/*
- * impl_def_val: impl_def_val_token
- */
-PARSE_TYPED(impl_def_val, def,
-               NAMED(impl_def_val_token, T)) {
-       def = psi_impl_def_val_init(T->type, T->text);
-       def->token = T;
-}
-
-/*
- * impl_var: reference DOLLAR_NAME
- */
-PARSE_TYPED(impl_var, var,
-               TYPED(reference, r)
-               NAMED(DOLLAR_NAME, T)) {
-       var = psi_impl_var_init(T->text, r);
-       var->token = T;
-}
-
-/*
- * impl_type: impl_type_token
- */
-PARSE_TYPED(impl_type, type_,
-               NAMED(impl_type_token, T)) {
-       type_ = psi_impl_type_init(T->type, T->text);
-       free(T);
-}
-
-/*
- * impl_arg: impl_type impl_var
- */
-PARSE_TYPED(impl_arg, arg,
-               TYPED(impl_type, type)
-               TYPED(impl_var, var)) {
-       arg = psi_impl_arg_init(type, var, NULL);
-}
-
-/*
- * impl_arg: impl_type impl_var = impl_def_val
- */
-PARSE_TYPED(impl_arg, arg,
-               TYPED(impl_type, type)
-               TYPED(impl_var, var)
-               TOKEN(EQUALS)
-               TYPED(impl_def_val, def)) {
-       arg = psi_impl_arg_init(type, var, def);
-}
-
-/*
- * impl_args: impl_arg
- */
-PARSE_TYPED(impl_args, args,
-               TYPED(impl_arg, arg)) {
-       args = psi_plist_add(psi_plist_init((psi_plist_dtor) psi_impl_arg_free),
-                       &arg);
-}
-
-/*
- * impl_args: impl_args , impl_arg
- */
-PARSE_TYPED(impl_args, args,
-               TYPED(impl_args, args_)
-               TOKEN(COMMA)
-               TYPED(impl_arg, arg)) {
-       args = psi_plist_add(args_, &arg);
-}
-
-/*
- * impl_stmts: impl_stmt
- */
-PARSE_TYPED(impl_stmts, stmts,
-               TYPED(impl_stmt, stmt)) {
-       stmts = psi_plist_add(psi_plist_init((psi_plist_dtor) psi_impl_stmt_free),
-                       &stmt);
-}
-
-/*
- * impl_stmts: impl_stmts , impl_stmt
- */
-PARSE_TYPED(impl_stmts, stmts,
-               TYPED(impl_stmts, stmts_)
-               TYPED(impl_stmt, stmt)) {
-       stmts = psi_plist_add(stmts_, &stmt);
-}
-
-/*
- * impl_stmt: return_stmt
- */
-PARSE_TYPED(impl_stmt, i,
-               TYPED(return_stmt, r)) {
-       i = (struct psi_token**) r;
-}
-
-/*
- * impl_stmt: let_stmt
- */
-PARSE_TYPED(impl_stmt, i,
-               TYPED(let_stmt, l)) {
-       i = (struct psi_token**) l;
-}
-
-/*
- * impl_stmt: set_stmt
- */
-PARSE_TYPED(impl_stmt, i,
-               TYPED(set_stmt, s)) {
-       i = (struct psi_token**) s;
-}
-
-/*
- * impl_stmt: assert_stmt
- */
-PARSE_TYPED(impl_stmt, i,
-               TYPED(assert_stmt, s)) {
-       i = (struct psi_token **) s;
-}
-
-/*
- * impl_stmt: free_stmt
- */
-PARSE_TYPED(impl_stmt, i,
-               TYPED(free_stmt, f)) {
-       i = (struct psi_token**) f;
-}
-
-/*
- * number: number_token
- */
-PARSE_TYPED(number, exp,
-               NAMED(number_token, tok)) {
-       exp = psi_number_init(tok->type, tok->text);
-       exp->token = tok;
-}
-
-/*
- * number: decl_var
- */
-PARSE_TYPED(number, exp,
-               TYPED(decl_var, var)) {
-       exp = psi_number_init(PSI_T_NAME, var);
-       exp->token = psi_token_copy(var->token);
-}
-
-/*
- * num_exp: number
- */
-PARSE_TYPED(num_exp, exp,
-               TYPED(number, num)) {
-       exp = psi_num_exp_init_num(num);
-       exp->token = psi_token_copy(num->token);
-}
-
-/*
- * num_exp: ( num_exp )
- */
-PARSE_TYPED(num_exp, exp,
-               NAMED(LPAREN, L)
-               TYPED(num_exp, exp_)
-               TOKEN(RPAREN)) {
-       exp = psi_num_exp_init_unary(PSI_T_LPAREN, exp_);
-       exp->token = L;
-}
-
-/*
- * num_exp: num_exp binary_op_token num_exp
- */
-PARSE_TYPED(num_exp, exp,
-               TYPED(num_exp, lhs_)
-               NAMED(binary_op_token, OP)
-               TYPED(num_exp, rhs_)) {
-       exp = psi_num_exp_init_binary(OP->type, lhs_, rhs_);
-       exp->token = OP;
-}
-
-/*
- * num_exp: unary_op_token num_exp
- */
-PARSE_TYPED(num_exp, exp,
-               NAMED(unary_op_token, OP)
-               TYPED(num_exp, exp_)) {
-       exp = psi_num_exp_init_unary(OP->type, exp_);
-       exp->token = OP;
-}
-
-/*
- * let_exp: NULL
- */
-PARSE_TYPED(let_exp, val,
-               TOKEN(NULL)) {
-       val = psi_let_exp_init(PSI_LET_NULL, NULL);
-}
-
-/*
- * let_exp: & NULL
- */
-PARSE_TYPED(let_exp, val,
-               TOKEN(AMPERSAND)
-               TOKEN(NULL)) {
-       val = psi_let_exp_init(PSI_LET_NULL, NULL);
-       val->is_reference = 1;
-}
-
-/*
- * let_exp: callback
- */
-PARSE_TYPED(let_exp, val,
-               TYPED(let_callback, cb)) {
-       val = psi_let_exp_init(PSI_LET_CALLBACK, cb);
-}
-
-/*
- * let_exp: calloc
- */
-PARSE_TYPED(let_exp, val,
-               TYPED(let_calloc, ca)) {
-       val = psi_let_exp_init(PSI_LET_CALLOC, ca);
-}
-
-/*
- * let_exp: & calloc
- */
-PARSE_TYPED(let_exp, val,
-               TOKEN(AMPERSAND)
-               TYPED(let_calloc, ca)) {
-       val = psi_let_exp_init(PSI_LET_CALLOC, ca);
-       val->is_reference = 1;
-}
-
-/*
- * let_exp: func
- */
-PARSE_TYPED(let_exp, val,
-               TYPED(let_func, fn)) {
-       val = psi_let_exp_init_ex(NULL, PSI_LET_FUNC, fn);
-}
-
-/*
- * let_exp: & func
- */
-PARSE_TYPED(let_exp, val,
-               TOKEN(AMPERSAND)
-               TYPED(let_func, fn)) {
-       val = psi_let_exp_init_ex(NULL, PSI_LET_FUNC, fn);
-       val->is_reference = 1;
-}
-
-/*
- * let_exp: num_exp
- */
-PARSE_TYPED(let_exp, val,
-               TYPED(num_exp, exp)) {
-       val = psi_let_exp_init_ex(NULL, PSI_LET_NUMEXP, exp);
-}
-
-/*
- * let_exp: & num_exp
- */
-PARSE_TYPED(let_exp, val,
-               TOKEN(AMPERSAND)
-               TYPED(num_exp, exp)) {
-       val = psi_let_exp_init_ex(NULL, PSI_LET_NUMEXP, exp);
-       val->is_reference = 1;
-}
-
-/* FIXME
- * let_exp: decl_var = let_exp
- */
-PARSE_TYPED(let_exp, exp,
-               TYPED(decl_var, var_)
-               TOKEN(EQUALS)
-               TYPED(let_exp, val)) {
-       exp = val;
-       exp->var = var_;
-}
-
-/*
- * let_stmt: LET let_exp ;
- */
-PARSE_TYPED(let_stmt, let,
-               NAMED(LET, T)
-               TYPED(let_exp, val)
-               TOKEN(EOS)) {
-       let = psi_let_stmt_init(val);
-       let->token = T;
-}
-
-/*
- * let_stmt: TEMP decl_var = reference decl_var ;
- */
-PARSE_TYPED(let_stmt, let,
-               NAMED(TEMP, T)
-               TYPED(decl_var, var)
-               TOKEN(EQUALS)
-               TYPED(reference, r)
-               TYPED(decl_var, val_)
-               TOKEN(EOS)) {
-       let = psi_let_stmt_init(psi_let_exp_init_ex(var, PSI_LET_TMP, val_));
-       let->token = T;
-       let->exp->is_reference = r ? 1 : 0;
-}
-
-/*
- * let_callback: CALLBACK callback_rval ( impl_var ( callback_arg_lists ) )
- */
-PARSE_TYPED(let_callback, cb,
-               NAMED(CALLBACK, T)
-               NAMED(callback_rval, F)
-               TOKEN(LPAREN)
-               TYPED(impl_var, var)
-               TOKEN(LPAREN)
-               TYPED(callback_arg_list, args_)
-               TOKEN(RPAREN)
-               TOKEN(RPAREN)) {
-       cb = psi_let_callback_init(psi_let_func_init(F->type, F->text, var), args_);
-       cb->token = T;
-       free(F);
-}
-
-/*
- * let_calloc: CALLOC ( num_exp , num_exp )
- */
-PARSE_TYPED(let_calloc, alloc,
-               NAMED(CALLOC, T)
-               TOKEN(LPAREN)
-               TYPED(num_exp, nmemb)
-               TOKEN(COMMA)
-               TYPED(num_exp, size)
-               TOKEN(RPAREN)) {
-       alloc = psi_let_calloc_init(nmemb, size);
-       alloc->token = T;
-}
-
-/*
- * let_func: let_func_token ( impl_var )
- */
-PARSE_TYPED(let_func, func,
-               NAMED(let_func_token, T)
-               TOKEN(LPAREN)
-               TYPED(impl_var, var)
-               TOKEN(RPAREN)) {
-       func = psi_let_func_init(T->type, T->text, var);
-       func->token = T;
-}
-/*
- * let_func: let_func_token ( impl_var , let_exps )
- */
-PARSE_TYPED(let_func, func,
-               NAMED(let_func_token, T)
-               TOKEN(LPAREN)
-               TYPED(impl_var, var)
-               TOKEN(COMMA)
-               TYPED(let_exps, vals)
-               TOKEN(RPAREN)) {
-       func = psi_let_func_init(T->type, T->text, var);
-       func->token = T;
-       func->inner = vals;
-}
-/*
- * let_exps: let_exp
- */
-PARSE_TYPED(let_exps, exps,
-               TYPED(let_exp, exp)) {
-       exps = psi_plist_add(psi_plist_init((psi_plist_dtor) psi_let_exp_free),
-                       &exp);
-}
-/*
- * let_exps: let_exps , let_exp
- */
-PARSE_TYPED(let_exps, exps,
-               TYPED(let_exps, exps_)
-               TOKEN(COMMA)
-               TYPED(let_exp, exp)) {
-       exps = psi_plist_add(exps_, &exp);
-}
-
-/*
- * callback_arg_list: <empty>
- */
-PARSE_TYPED(callback_arg_list, args, ) {
-       args = NULL;
-}
-
-/*
- * callback_arg_list: callback_args
- */
-PARSE_TYPED(callback_arg_list, args,
-               TYPED(callback_args, args_)) {
-       args = args_;
-}
-
-/*
- * callback_args: set_exp
- */
-PARSE_TYPED(callback_args, args,
-               TYPED(set_exp, val)) {
-       args = psi_plist_add(psi_plist_init((psi_plist_dtor) psi_set_exp_free),
-                       &val);
-}
-
-/*
- * callback_args: callback_args , set_exp
- */
-PARSE_TYPED(callback_args, args,
-               TYPED(callback_args, args_)
-               TOKEN(COMMA)
-               TYPED(set_exp, val)) {
-       args = psi_plist_add(args_, &val);
-}
-
-/*
- * callback_rval: let_func_token
- */
-PARSE_NAMED(callback_rval, rval,
-               NAMED(let_func_token, F)) {
-       rval = F;
-}
-
-/*
- * callback_rval: VOID
- */
-PARSE_NAMED(callback_rval, rval,
-               NAMED(VOID, V)) {
-       rval = V;
-}
-
-
-/*
- * set_func: set_func_token ( decl_var )
- */
-PARSE_TYPED(set_func, func,
-               NAMED(set_func_token, T)
-               TOKEN(LPAREN)
-               TYPED(decl_var, var)
-               TOKEN(RPAREN)) {
-       func = psi_set_func_init(T->type, T->text, var);
-       func->token = T;
-}
-
-/*
- * set_func: set_func_token ( decl_var , set_exps )
- */
-PARSE_TYPED(set_func, func,
-               NAMED(set_func_token, T)
-               TOKEN(LPAREN)
-               TYPED(decl_var, var)
-               TOKEN(COMMA)
-               TYPED(set_exps, vals)
-               TOKEN(RPAREN)) {
-       func = psi_set_func_init(T->type, T->text, var);
-       func->token = T;
-       func->inner = vals;
-}
-
-/*
- * set_func: set_func_token ( decl_var , ... )
- */
-PARSE_TYPED(set_func, func,
-               NAMED(set_func_token, T)
-               TOKEN(LPAREN)
-               TYPED(decl_var, var)
-               TOKEN(COMMA)
-               TOKEN(ELLIPSIS)
-               TOKEN(RPAREN)) {
-       func = psi_set_func_init(T->type, T->text, var);
-       func->token = T;
-       func->recursive = 1;
-}
-
-/*
- * set_exp: set_func
- */
-PARSE_TYPED(set_exp, val,
-               TYPED(set_func, fn)) {
-       val = psi_set_exp_init(PSI_SET_FUNC, fn);
-}
-
-/*
- * set_exp: num_exp
- */
-PARSE_TYPED(set_exp, val,
-               TYPED(num_exp, num)) {
-       val = psi_set_exp_init(PSI_SET_NUMEXP, num);
-}
-
-/*
- * set_exps: set_exp
- */
-PARSE_TYPED(set_exps, exps,
-               TYPED(set_exp, exp)) {
-       exps = psi_plist_add(psi_plist_init((psi_plist_dtor) psi_set_exp_free),
-                       &exp);
-}
-
-/*
- * set_exps: set_exps , set_exp
- */
-PARSE_TYPED(set_exps, exps,
-               TYPED(set_exps, exps_)
-               TOKEN(COMMA)
-               TYPED(set_exp, exp)) {
-       exps = psi_plist_add(exps_, &exp);
-}
-
-/* FIXME
- * set_exp: impl_var = set_exp
- */
-PARSE_TYPED(set_exp, exp,
-               TYPED(impl_var, var_)
-               TOKEN(EQUALS)
-               TYPED(set_exp, val)) {
-       exp = val;
-       exp->var = var_;
-}
-
-/*
- * set_stmt: SET set_exp ;
- */
-PARSE_TYPED(set_stmt, set,
-               NAMED(SET, T)
-               TYPED(set_exp, exp)
-               TOKEN(EOS)) {
-       set = psi_set_stmt_init(exp);
-       set->token = T;
-}
-
-/*
- * return_stmt: RETURN set_exp ;
- */
-PARSE_TYPED(return_stmt, ret,
-               NAMED(RETURN, T)
-               TYPED(set_func, func)
-               TOKEN(EOS)) {
-       ret = psi_return_stmt_init(psi_set_exp_init(PSI_SET_FUNC, func));
-       ret->token = T;
-}
-
-/*
- * free_stmt: FREE free_exps ;
- */
-PARSE_TYPED(free_stmt, free,
-               NAMED(FREE, T)
-               TYPED(free_exps, calls)
-               TOKEN(EOS)) {
-       free = psi_free_stmt_init(calls);
-       free->token = T;
-}
-
-/*
- * free_exps: free_exp
- */
-PARSE_TYPED(free_exps, calls,
-               TYPED(free_exp, call)) {
-       calls = psi_plist_add(psi_plist_init((psi_plist_dtor) psi_free_exp_free),
-                       &call);
-}
-
-/*
- * free_exps: free_exps , free_exp
- */
-PARSE_TYPED(free_exps, calls,
-               TYPED(free_exps, calls_)
-               TOKEN(COMMA)
-               TYPED(free_exp, call)) {
-       calls = psi_plist_add(calls_, &call);
-}
-
-/*
- * free_exp: NAME ( decl_vars )
- */
-PARSE_TYPED(free_exp, call,
-               NAMED(NAME, F)
-               TOKEN(LPAREN)
-               TYPED(decl_vars, vars)
-               TOKEN(RPAREN)) {
-       call = psi_free_exp_init(F->text, vars);
-       call->token = F;
-}
-
-/*
- * assert_stmt: assert_stmt_token num_exp ;
- */
-PARSE_TYPED(assert_stmt, ass,
-               NAMED(assert_stmt_token, T)
-               TYPED(num_exp, exp)
-               TOKEN(EOS)) {
-       ass = psi_assert_stmt_init(T->type, exp);
-       ass->token = T;
-}
-
-/*
- * reference: <empty>
- */
-PARSE_TYPED(reference, r, ) {
-       r = false;
-}
-
-/*
- * reference: &
- */
-PARSE_TYPED(reference, r,
-               TOKEN(AMPERSAND)) {
-       r = true;
-}
-
-/*
- * indirection: <empty>
- */
-PARSE_TYPED(indirection, i, ){
-       i = 0;
-}
-
-/*
- * indirection: pointers
- */
-PARSE_TYPED(indirection, i,
-               TYPED(pointers, p)) {
-       i = p;
-}
-
-/*
- * pointers: *
- */
-PARSE_TYPED(pointers, p,
-               TOKEN(ASTERISK)) {
-       p = 1;
-}
-
-/*
- * pointers: pointers *
- */
-PARSE_TYPED(pointers, p,
-               TYPED(pointers, p_)
-               TOKEN(ASTERISK)) {
-       p = p_+1;
-}
+#endif
index 7780561bec21c71dc3e730b44da82e4e3a4c3184..a3b6119b12d2b6b6a63ae43eab741d2df4406b26 100644 (file)
@@ -118,50 +118,53 @@ void psi_parser_proc_free(void **parser_proc)
 #endif
 /************* Begin control #defines *****************************************/
 #define YYCODETYPE unsigned char
-#define YYNOCODE 170
+#define YYNOCODE 193
 #define YYACTIONTYPE unsigned short int
+#define YYWILDCARD 74
 #define ParseTOKENTYPE struct psi_token *
 typedef union {
   int yyinit;
   ParseTOKENTYPE yy0;
-  struct psi_plist* yy7;
-  struct psi_decl* yy17;
-  struct psi_impl_type* yy40;
-  struct psi_decl_union* yy47;
-  struct psi_impl_arg* yy56;
-  struct psi_decl_arg* yy64;
-  struct psi_number* yy66;
-  struct psi_let_callback* yy76;
-  struct psi_decl_enum * yy87;
-  struct psi_free_stmt* yy102;
-  struct psi_decl_enum_item* yy109;
-  struct psi_set_exp* yy113;
-  struct psi_free_exp* yy114;
-  struct psi_impl_var* yy123;
-  struct psi_num_exp* yy124;
-  struct psi_decl_var* yy131;
-  struct psi_let_func* yy133;
-  struct psi_decl_struct* yy137;
-  struct psi_let_stmt* yy138;
-  struct psi_assert_stmt* yy146;
-  struct psi_decl_abi* yy180;
-  struct psi_const_type* yy181;
-  struct psi_decl_type* yy182;
-  struct psi_let_exp* yy196;
-  struct psi_layout yy207;
-  struct psi_layout* yy221;
-  struct psi_impl_func* yy226;
-  struct psi_let_calloc* yy227;
-  bool yy247;
-  struct psi_return_stmt* yy258;
-  struct psi_token** yy282;
-  unsigned yy296;
-  struct psi_set_stmt* yy300;
-  struct psi_impl* yy303;
-  struct psi_plist * yy304;
-  struct psi_impl_def_val* yy319;
-  struct psi_set_func* yy324;
-  struct psi_const* yy336;
+  struct psi_decl_union* yy15;
+  struct psi_decl_abi* yy26;
+  struct psi_impl_arg* yy34;
+  struct psi_const* yy38;
+  struct psi_let_calloc* yy45;
+  struct psi_impl* yy49;
+  struct psi_impl_func* yy56;
+  struct psi_number* yy57;
+  struct psi_let_func* yy67;
+  bool yy89;
+  struct psi_let_callback* yy120;
+  struct psi_cpp_macro_decl* yy134;
+  struct psi_impl_def_val* yy145;
+  struct psi_free_exp* yy146;
+  struct psi_decl_enum_item* yy169;
+  struct psi_decl_type* yy172;
+  struct psi_plist* yy179;
+  struct psi_set_exp* yy180;
+  struct psi_let_exp* yy200;
+  struct psi_assert_stmt* yy201;
+  struct psi_num_exp* yy207;
+  struct psi_free_stmt* yy220;
+  struct psi_token** yy238;
+  struct psi_layout yy239;
+  struct psi_plist * yy243;
+  struct psi_impl_type* yy246;
+  struct psi_decl_var* yy271;
+  struct psi_cpp_exp* yy274;
+  struct psi_decl* yy303;
+  struct psi_let_stmt* yy319;
+  struct psi_decl_arg* yy320;
+  struct psi_decl_enum * yy323;
+  struct psi_decl_struct* yy324;
+  struct psi_return_stmt* yy342;
+  struct psi_const_type* yy351;
+  struct psi_set_stmt* yy358;
+  struct psi_set_func* yy362;
+  struct psi_layout* yy369;
+  struct psi_impl_var* yy370;
+  unsigned yy382;
 } YYMINORTYPE;
 #ifndef YYSTACKDEPTH
 #define YYSTACKDEPTH 100
@@ -171,16 +174,16 @@ typedef union {
 #define ParseARG_FETCH struct psi_parser *P = yypParser->P
 #define ParseARG_STORE yypParser->P = P
 #define YYFALLBACK 1
-#define YYNSTATE             199
-#define YYNRULE              159
-#define YY_MAX_SHIFT         198
-#define YY_MIN_SHIFTREDUCE   332
-#define YY_MAX_SHIFTREDUCE   490
-#define YY_MIN_REDUCE        491
-#define YY_MAX_REDUCE        649
-#define YY_ERROR_ACTION      650
-#define YY_ACCEPT_ACTION     651
-#define YY_NO_ACTION         652
+#define YYNSTATE             233
+#define YYNRULE              191
+#define YY_MAX_SHIFT         232
+#define YY_MIN_SHIFTREDUCE   385
+#define YY_MAX_SHIFTREDUCE   575
+#define YY_MIN_REDUCE        576
+#define YY_MAX_REDUCE        766
+#define YY_ERROR_ACTION      767
+#define YY_ACCEPT_ACTION     768
+#define YY_NO_ACTION         769
 /************* End control #defines *******************************************/
 
 /* Define the yytestcase() macro to be a no-op if is not already defined
@@ -252,280 +255,311 @@ typedef union {
 **  yy_default[]       Default action for each state.
 **
 *********** Begin parsing tables **********************************************/
-#define YY_ACTTAB_COUNT (1029)
+#define YY_ACTTAB_COUNT (1132)
 static const YYACTIONTYPE yy_action[] = {
- /*     0 */   398,  413,  481,  413,  413,  413,  413,  413,  413,  413,
- /*    10 */   413,  413,  413,   94,  441,  435,  378,  110,  398,  435,
- /*    20 */   380,  415,   17,  386,  116,   28,   28,  484,  414,   44,
- /*    30 */    25,   25,   40,   50,   11,   10,   61,  427,   28,   28,
- /*    40 */   150,  150,  150,  150,  150,  150,  150,  150,  150,  150,
- /*    50 */   417,  357,  357,  357,  357,   84,  124,  339,   94,  160,
- /*    60 */   117,   49,  337,  409,  338,  370,  336,  335,  151,   57,
- /*    70 */   409,  333,  484,   21,   29,  379,   91,   90,   89,  484,
- /*    80 */   352,  138,   36,  334,  153,  426,  109,  394,   82,   68,
- /*    90 */    66,   65,  398,  413,  126,  413,  413,  413,  413,  413,
- /*   100 */   413,  413,  413,  413,  413,  394,   82,   68,  152,   48,
- /*   110 */    94,  442,  435,  135,  383,  124,  435,  488,  195,  196,
- /*   120 */   149,  124,   28,   28,  484,  484,  437,  103,  485,  444,
- /*   130 */   446,  148,  139,  443,  458,   28,   28,  150,  150,  150,
- /*   140 */   150,  150,  150,  150,  150,  150,  150,   84,  124,  401,
- /*   150 */   398,  413,  420,  413,  413,  413,  413,  413,  413,  413,
- /*   160 */   413,  413,  413,  114,  380,  151,  166,  118,  181,  183,
- /*   170 */   182,   29,  124,  419,   36,   54,  155,  353,  356,  394,
- /*   180 */    82,   68,   66,   65,   30,   30,   30,   30,   30,   30,
- /*   190 */    30,   30,   30,   30,   30,   30,   30,   30,   30,   30,
- /*   200 */    30,   30,  354,  124,  124,   42,  353,  355,  398,  413,
- /*   210 */     2,  413,  413,  413,  413,  413,  413,  413,  413,  413,
- /*   220 */   413,  361,  360,  111,  476,   95,   91,   90,   89,  159,
- /*   230 */   163,  347,   35,  162,  163,   81,  479,  394,   82,   68,
- /*   240 */    66,   65,   30,   30,   30,   30,   30,   30,   30,   30,
- /*   250 */    30,   30,   30,   30,   30,   30,   30,   30,   30,   30,
- /*   260 */   418,  124,  124,   84,  136,  126,  398,  413,  147,  413,
- /*   270 */   413,  413,  413,  413,  413,  413,  413,  413,  413,  165,
- /*   280 */   163,  373,  125,  348,   91,   90,   89,  115,   37,  130,
- /*   290 */    36,  108,   38,  478,  149,  394,   82,   68,   66,   65,
- /*   300 */    30,   30,   30,   30,   30,   30,   30,   30,   30,   30,
- /*   310 */    30,   30,   30,  149,  425,   30,   30,  423,  423,  423,
- /*   320 */   423,   77,  169,  475,  398,  413,   71,  413,  413,  413,
- /*   330 */   413,  413,  413,  413,  413,  413,  413,  171,  198,  489,
- /*   340 */   490,  406,  181,  183,  182,   96,  192,  172,   36,  129,
- /*   350 */   405,   64,    1,  394,   82,   68,   66,   65,  121,  422,
- /*   360 */   399,   70,   69,  133,   25,   25,   40,   50,   11,   10,
- /*   370 */    61,    8,  456,  423,  423,  423,  423,  423,   69,   67,
- /*   380 */    13,  466,  398,  413,  416,  413,  413,  413,  413,  413,
- /*   390 */   413,  413,  413,  413,  413,    7,  465,  134,  477,  184,
- /*   400 */   181,  183,  182,    6,  455,   93,   36,   23,  156,   39,
- /*   410 */   180,  394,   82,   68,   66,   65,  143,   22,   80,  485,
- /*   420 */     4,  388,  381,  414,   44,  382,  143,  143,  143,  143,
- /*   430 */   143,  143,  143,   24,  364,  372,  436,   84,  191,  485,
- /*   440 */   398,  413,  107,  413,  413,  413,  413,  413,  413,  413,
- /*   450 */   413,  413,  413,   43,  437,   97,  436,  371,  181,  183,
- /*   460 */   182,  196,   88,   86,   36,  409,  365,  178,  142,  394,
- /*   470 */    82,   68,   66,   65,  437,  101,  124,  383,  404,  146,
- /*   480 */   144,  421,  421,  421,  421,  421,  461,  179,  468,  397,
- /*   490 */   500,  485,  402,  395,  149,   75,  124,  500,  398,  413,
- /*   500 */   184,  413,  413,  413,  413,  413,  413,  413,  413,  413,
- /*   510 */   413,  363,  168,  120,    2,   78,  181,  183,  182,  167,
- /*   520 */    45,   85,   46,  122,  414,   34,   87,  394,   82,   68,
- /*   530 */    66,   65,   25,   25,   40,   50,   11,   10,   61,  123,
- /*   540 */   346,  463,  463,  463,  463,  463,  463,  463,  463,  463,
- /*   550 */   463,  339,  185,   83,  345,  344,  337,  464,  338,   47,
- /*   560 */   336,  335,  196,   88,   86,  333,  409,   21,  194,  377,
- /*   570 */   376,  349,  341,   62,  181,  183,  182,  334,  153,  436,
- /*   580 */    58,  127,  128,   32,   59,  394,   82,   68,   66,   65,
- /*   590 */    94,   60,  435,  132,   15,   33,  435,  437,   98,  481,
- /*   600 */   387,  184,   28,   28,  484,  414,   44,  474,  473,  651,
- /*   610 */     3,    3,  180,  196,  452,   28,   28,  143,  451,  124,
- /*   620 */    80,  467,   72,  389,   41,  414,   44,  143,  143,  143,
- /*   630 */   143,  143,  143,  143,  423,  423,  423,  423,   12,   14,
- /*   640 */    16,  453,  145,   94,    5,  435,   51,  409,   94,  435,
- /*   650 */   435,   29,  481,  422,  435,   28,   28,  484,   52,   27,
- /*   660 */    28,   28,  484,  196,   88,   86,  368,  409,   28,   28,
- /*   670 */   143,    9,  639,   28,   28,  154,  367,  152,   73,   20,
- /*   680 */   143,  143,  143,  143,  143,  143,  143,  158,   53,   74,
- /*   690 */   423,  423,  423,  423,  423,  437,  103,  161,  444,  446,
- /*   700 */   485,   76,  443,  450,   29,  164,   55,  528,  359,   29,
- /*   710 */   131,  358,  170,   63,   79,  141,  393,  124,  173,  386,
- /*   720 */   119,  174,  175,  176,  414,   44,   30,   30,   30,   30,
+ /*     0 */   482,  497,  520,  497,  497,  497,  497,  497,  497,  497,
+ /*    10 */   497,  497,  497,  104,  525,  519,  189,  136,  565,  519,
+ /*    20 */   521,  114,   17,  529,  531,   28,   28,  568,   25,   25,
+ /*    30 */   510,  127,   42,   52,   11,   10,   70,  104,   28,   28,
+ /*    40 */   173,  173,  173,  173,  173,  173,  173,  173,  173,  173,
+ /*    50 */   142,  568,   25,   25,   50,   94,   42,   52,   11,   10,
+ /*    60 */    70,  568,  511,  501,  505,  505,  505,  505,  505,  438,
+ /*    70 */   174,   59,   30,   30,   30,   30,   30,   30,   30,   30,
+ /*    80 */    30,   30,   30,   30,   30,   29,   51,   30,   30,  171,
+ /*    90 */     2,  101,  100,   99,  499,  436,  158,   37,  401,  401,
+ /*   100 */   584,  585,  478,   92,   77,   75,   74,  482,  497,  226,
+ /*   110 */   497,  497,  497,  497,  497,  497,  497,  497,  497,  497,
+ /*   120 */   120,  104,  526,  519,  144,  504,  166,  519,  441,  441,
+ /*   130 */   441,  441,  559,   28,   28,  568,  166,  166,  166,  166,
+ /*   140 */   166,  166,  166,  218,  493,   81,   28,   28,  173,  173,
+ /*   150 */   173,  173,  173,  173,  173,  173,  173,  173,  392,  146,
+ /*   160 */   485,   78,   94,  437,  440,  482,  497,  464,  497,  497,
+ /*   170 */   497,  497,  497,  497,  497,  497,  497,  497,  174,   68,
+ /*   180 */    68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+ /*   190 */    68,   68,  482,   29,   68,   68,  232,  471,  204,  206,
+ /*   200 */   205,  503,  498,   46,   37,  513,  178,  502,  515,  478,
+ /*   210 */    92,   77,   75,   74,  183,  135,  517,  516,  462,  128,
+ /*   220 */    44,  514,  518,  482,  497,  463,  497,  497,  497,  497,
+ /*   230 */   497,  497,  497,  497,  497,  497,  467,  423,  457,  180,
+ /*   240 */   129,  560,  421,  453,  422,  149,  420,  419,  498,   46,
+ /*   250 */   569,  417,  493,   21,  470,  134,  101,  100,   99,  498,
+ /*   260 */    46,   91,   36,  418,  176,  161,  142,  478,   92,   77,
+ /*   270 */    75,   74,  118,  142,  437,  439,  149,  119,   94,  172,
+ /*   280 */   121,  482,  497,  162,  497,  497,  497,  497,  497,  497,
+ /*   290 */   497,  497,  497,  497,  478,   92,   77,  221,  493,  573,
+ /*   300 */   574,  575,   60,  768,    3,    3,  132,  219,   56,  493,
+ /*   310 */   126,  112,  152,  142,  101,  100,   99,  106,  215,  195,
+ /*   320 */    37,  454,  506,   73,    1,  478,   92,   77,   75,   74,
+ /*   330 */   170,  142,  124,   80,   79,  568,   87,  182,  186,  482,
+ /*   340 */   497,  207,  497,  497,  497,  497,  497,  497,  497,  497,
+ /*   350 */   497,  497,  447,  191,  142,  104,   88,  519,   18,  512,
+ /*   360 */   190,  519,  515,  122,  172,  498,   35,   28,   28,  568,
+ /*   370 */   517,  516,  204,  206,  205,  514,  518,  520,   37,  105,
+ /*   380 */    28,   28,  133,  478,   92,   77,   75,   74,  431,  464,
+ /*   390 */   445,  444,  185,  186,   76,  521,  108,  482,  497,  207,
+ /*   400 */   497,  497,  497,  497,  497,  497,  497,  497,  497,  497,
+ /*   410 */   203,  219,   98,   96,  103,  493,  172,  402,   90,  591,
+ /*   420 */     4,  472,  509,  498,   46,  142,  466,   29,  569,  520,
+ /*   430 */   204,  206,  205,  188,  186,  520,   37,  142,  142,  142,
+ /*   440 */   569,  478,   92,   77,   75,   74,  159,  521,  109,  143,
+ /*   450 */   432,  192,   94,  521,  110,  482,  497,  207,  497,  497,
+ /*   460 */   497,  497,  497,  497,  497,  497,  497,  497,  203,  219,
+ /*   470 */    98,   96,  194,  493,  153,   38,   90,  142,  520,  473,
+ /*   480 */   490,  498,   46,  142,  562,   40,  175,  489,  204,  206,
+ /*   490 */   205,  540,    8,  402,   37,  586,  521,  116,  139,  478,
+ /*   500 */    92,   77,   75,   74,  521,  115,  483,  528,  530,  148,
+ /*   510 */    85,  527,  542,  482,  497,   79,  497,  497,  497,  497,
+ /*   520 */   497,  497,  497,  497,  497,  497,  142,  219,   98,   96,
+ /*   530 */   156,  493,  550,   13,  142,  408,  547,  547,  547,  547,
+ /*   540 */   547,  547,  547,  547,  547,  547,  204,  206,  205,  549,
+ /*   550 */     7,  520,  548,  467,  520,  539,    6,  478,   92,   77,
+ /*   560 */    75,   74,  157,  520,  179,   23,  165,  569,   93,  521,
+ /*   570 */   111,   22,  521,  113,  470,  137,  561,  169,  167,  498,
+ /*   580 */    46,  521,  123,  104,  545,  519,  552,  448,   24,  519,
+ /*   590 */   412,   65,  565,   41,  520,   28,   28,  568,  465,  142,
+ /*   600 */   172,  456,  142,  125,  204,  206,  205,  224,   28,   28,
+ /*   610 */   166,  142,  521,  117,  455,  478,   92,   77,   75,   74,
+ /*   620 */   166,  166,  166,  166,  166,  166,  166,  396,  225,  493,
+ /*   630 */   616,  104,  449,  519,  616,   19,  512,  519,  214,  515,
+ /*   640 */   565,   45,  142,   28,   28,  568,  201,  517,  516,  202,
+ /*   650 */   488,  486,  514,  518,  481,   29,   28,   28,  166,  479,
+ /*   660 */   175,  138,    2,   47,   95,   48,  430,   97,  166,  166,
+ /*   670 */   166,  166,  166,  166,  166,  231,  231,  140,  521,  115,
+ /*   680 */   755,  528,  530,  141,  429,  527,  541,  130,  208,  428,
+ /*   690 */   230,  229,  389,  390,  228,  227,   49,  423,  217,  425,
+ /*   700 */    69,   64,  421,   29,  422,  461,  420,  419,  142,  460,
+ /*   710 */   433,  417,  398,   21,  147,   61,   71,  150,  164,  151,
+ /*   720 */    62,   63,   32,  418,  176,   30,   30,   30,   30,   30,
  /*   730 */    30,   30,   30,   30,   30,   30,   30,   30,   30,   30,
- /*   740 */    30,   30,   30,   30,  177,  412,  411,  391,   30,   30,
+ /*   740 */    30,   30,   30,  507,  507,  507,  507,   30,   30,   30,
  /*   750 */    30,   30,   30,   30,   30,   30,   30,   30,   30,   30,
- /*   760 */    30,   30,   30,   30,   30,   30,  409,  390,  157,  410,
- /*   770 */   362,  500,  369,  343,  186,  188,  189,  414,   44,  187,
- /*   780 */    92,  190,  454,   30,   30,   30,   30,   30,   30,   30,
- /*   790 */    30,   30,   30,   30,   30,   30,   30,   30,   30,   30,
- /*   800 */    30,  645,  375,   26,   94,  193,  435,   31,  436,   56,
- /*   810 */   435,  332,  493,  481,  436,  373,   28,   28,  484,  409,
- /*   820 */   493,  197,  493,  493,  493,  493,  437,   99,  493,   28,
- /*   830 */    28,  143,  437,  102,  493,  445,  447,  493,  493,  438,
- /*   840 */   493,  143,  143,  143,  143,  143,  143,  143,  124,   18,
- /*   850 */   428,  493,  436,  431,  124,  493,  493,  493,  493,  436,
- /*   860 */   493,  433,  432,  493,  142,   29,  430,  434,  493,  493,
- /*   870 */   437,  101,  198,  489,  490,  436,  493,  437,  104,   96,
- /*   880 */   192,  172,  470,  113,  468,   64,    1,  142,  493,  493,
- /*   890 */   149,  493,  124,  437,  101,   70,   69,  493,  152,  124,
- /*   900 */   493,  493,  493,  493,  493,  137,  493,  468,  152,  493,
- /*   910 */   493,  493,  493,  149,  493,  124,  437,  103,  493,  444,
- /*   920 */   446,  493,  436,  443,  457,  112,  437,  103,  493,  444,
- /*   930 */   446,  436,  493,  443,  140,  436,  493,  493,  124,  493,
- /*   940 */   437,  100,  493,  142,  493,  493,  436,  493,  124,  437,
- /*   950 */   101,  493,  493,  437,  106,  436,  493,  493,  142,  493,
- /*   960 */   493,  472,  124,  468,  437,  101,  493,  142,  493,  149,
- /*   970 */   493,  124,  493,  437,  101,  124,  471,  493,  468,   19,
- /*   980 */   428,  493,  493,  431,  149,  462,  124,  468,  436,  493,
- /*   990 */   493,  433,  432,  149,  493,  124,  430,  434,  429,  493,
- /*  1000 */   493,  431,  493,  493,  493,  493,  437,  105,  493,  433,
- /*  1010 */   432,  493,  493,  493,  430,  434,  493,  493,  493,  493,
- /*  1020 */   493,  493,  493,  493,  493,  493,  493,  493,  124,
+ /*   760 */    30,   30,   30,   30,   30,  572,  155,  219,   15,   25,
+ /*   770 */    25,  558,   34,   42,   52,   11,   10,   70,  557,  563,
+ /*   780 */    30,   30,   30,   30,   30,   30,   30,   30,   30,   30,
+ /*   790 */    30,   30,   30,   30,   30,   30,   30,   30,  536,  507,
+ /*   800 */   507,  507,  507,  507,  500,  535,   82,  551,   12,   14,
+ /*   810 */    43,  506,  537,  538,   30,   30,   30,   30,   30,   30,
+ /*   820 */    30,   30,   30,   30,   30,   30,   30,   30,   30,   30,
+ /*   830 */    30,   30,  168,    5,   53,   54,   27,    9,  452,   16,
+ /*   840 */   177,  451,   20,  181,   83,   84,   55,   26,   68,   68,
+ /*   850 */    68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+ /*   860 */    68,   68,   68,   68,   68,   68,  184,  520,  569,  104,
+ /*   870 */    86,  519,  187,   57,  644,  519,  443,  442,  565,  165,
+ /*   880 */   522,   28,   28,  568,   72,  521,  113,  193,   89,  196,
+ /*   890 */   477,  198,  197,  199,   28,   28,  166,  554,  131,  552,
+ /*   900 */   200,  475,  496,  474,  495,  494,  166,  166,  166,  166,
+ /*   910 */   166,  166,  166,  172,  405,  142,   30,   30,   30,   30,
+ /*   920 */    30,   30,   30,   30,   30,   30,   30,   30,   30,   30,
+ /*   930 */    30,   30,   30,   30,  507,  507,  507,  507,  446,  616,
+ /*   940 */   427,   29,   68,   68,   68,   68,   68,   68,   68,   68,
+ /*   950 */    68,   68,   68,   68,   68,   68,   68,   68,   68,   68,
+ /*   960 */   761,  209,  211,  212,  210,  102,  459,   31,  216,  416,
+ /*   970 */   222,  213,  410,  220,  457,   39,  410,   58,  223,  175,
+ /*   980 */   409,  399,   66,   66,  107,   33,  391,  388,  387,  386,
+ /*   990 */   507,  507,  507,  507,  507,   66,   66,  521,  115,  385,
+ /*  1000 */   528,  530,  578,  578,  527,  534,  578,  578,  578,  578,
+ /*  1010 */   578,  578,  578,  578,  578,  578,  578,  578,  578,  578,
+ /*  1020 */   154,  578,  578,  578,  578,  578,  578,  142,  578,  578,
+ /*  1030 */   578,  578,  578,  221,  578,  573,  574,  575,   60,  578,
+ /*  1040 */   578,  578,   67,  578,  520,  578,  175,  145,  578,  578,
+ /*  1050 */   578,  578,  578,  106,  215,  195,  165,  578,  578,   73,
+ /*  1060 */     1,  520,  521,  113,  521,  115,  520,  528,  530,   80,
+ /*  1070 */    79,  527,  163,  165,  160,  578,  552,  578,  165,  521,
+ /*  1080 */   113,  578,  578,  520,  521,  113,  578,  578,  578,  578,
+ /*  1090 */   172,  556,  142,  552,  142,  165,  555,  578,  552,  578,
+ /*  1100 */   578,  521,  113,  578,  578,  578,  578,  172,  578,  142,
+ /*  1110 */   578,  578,  172,  546,  142,  552,  578,  578,  578,  578,
+ /*  1120 */   578,  578,  578,  578,  578,  578,  578,  578,  578,  172,
+ /*  1130 */   578,  142,
 };
 static const YYCODETYPE yy_lookahead[] = {
- /*     0 */     2,    3,   23,    5,    6,    7,    8,    9,   10,   11,
- /*    10 */    12,   13,   14,   14,   15,   16,  115,  116,    2,   20,
- /*    20 */   115,  122,   23,  117,  118,   26,   27,   28,  122,  123,
- /*    30 */    62,   63,   64,   65,   66,   67,   68,  128,   39,   40,
+ /*     0 */     2,    3,  130,    5,    6,    7,    8,    9,   10,   11,
+ /*    10 */    12,   13,   14,   14,   15,   16,  177,  178,   23,   20,
+ /*    20 */   148,  149,   23,  151,  152,   26,   27,   28,   62,   63,
+ /*    30 */   143,  144,   66,   67,   68,   69,   70,   14,   39,   40,
  /*    40 */    41,   42,   43,   44,   45,   46,   47,   48,   49,   50,
- /*    50 */    82,    1,    2,    3,    4,   57,  155,   98,   14,  154,
- /*    60 */   155,  152,  103,  164,  105,   14,  107,  108,   69,   70,
- /*    70 */   164,  112,   28,  114,   75,  115,   78,   79,   80,   28,
- /*    80 */    82,  115,   84,  124,  125,  128,  129,   89,   90,   91,
- /*    90 */    92,   93,    2,    3,  127,    5,    6,    7,    8,    9,
- /*   100 */    10,   11,   12,   13,   14,   89,   90,   91,  115,  152,
- /*   110 */    14,   15,   16,   14,   14,  155,   20,  158,   14,  160,
- /*   120 */   153,  155,   26,   27,   28,   28,  133,  134,   28,  136,
- /*   130 */   137,  168,  115,  140,  141,   39,   40,   41,   42,   43,
- /*   140 */    44,   45,   46,   47,   48,   49,   50,   57,  155,    5,
- /*   150 */     2,    3,  152,    5,    6,    7,    8,    9,   10,   11,
- /*   160 */    12,   13,   14,  115,  115,   69,  154,  155,   78,   79,
- /*   170 */    80,   75,  155,  152,   84,   75,   86,  101,  102,   89,
- /*   180 */    90,   91,   92,   93,   21,   22,   23,   24,   25,   26,
- /*   190 */    27,   28,   29,   30,   31,   32,   33,   34,   35,   36,
- /*   200 */    37,   38,   73,  155,  155,   57,  101,  102,    2,    3,
- /*   210 */    81,    5,    6,    7,    8,    9,   10,   11,   12,   13,
- /*   220 */    14,  115,  115,  150,  151,   76,   78,   79,   80,  154,
- /*   230 */   155,   82,   84,  154,  155,   91,   73,   89,   90,   91,
- /*   240 */    92,   93,   21,   22,   23,   24,   25,   26,   27,   28,
- /*   250 */    29,   30,   31,   32,   33,   34,   35,   36,   37,   38,
- /*   260 */   152,  155,  155,   57,  147,  127,    2,    3,  127,    5,
- /*   270 */     6,    7,    8,    9,   10,   11,   12,   13,   14,  154,
- /*   280 */   155,   14,   99,  100,   78,   79,   80,  127,   76,   77,
- /*   290 */    84,  153,   76,   77,  153,   89,   90,   91,   92,   93,
- /*   300 */    22,   23,   24,   25,   26,   27,   28,   29,   30,   31,
- /*   310 */    32,   33,   34,  153,  126,   37,   38,    1,    2,    3,
- /*   320 */     4,   57,  126,   73,    2,    3,   76,    5,    6,    7,
- /*   330 */     8,    9,   10,   11,   12,   13,   14,  106,   71,   72,
- /*   340 */    73,  164,   78,   79,   80,   78,   79,   80,   84,   86,
- /*   350 */   164,   84,   85,   89,   90,   91,   92,   93,  155,   96,
- /*   360 */   166,   94,   95,  153,   62,   63,   64,   65,   66,   67,
- /*   370 */    68,   76,   77,   57,   58,   59,   60,   61,   95,   57,
- /*   380 */    76,   77,    2,    3,   82,    5,    6,    7,    8,    9,
- /*   390 */    10,   11,   12,   13,   14,   76,   77,  125,  151,   98,
- /*   400 */    78,   79,   80,   76,   77,   14,   84,   76,   77,  153,
- /*   410 */   109,   89,   90,   91,   92,   93,   41,   75,  117,   28,
- /*   420 */   119,  120,  111,  122,  123,   14,   51,   52,   53,   54,
- /*   430 */    55,   56,   57,   76,   77,  111,  115,   57,   74,   28,
- /*   440 */     2,    3,  155,    5,    6,    7,    8,    9,   10,   11,
- /*   450 */    12,   13,   14,  104,  133,  134,  115,  111,   78,   79,
- /*   460 */    80,  160,  161,  162,   84,  164,  111,   74,  127,   89,
- /*   470 */    90,   91,   92,   93,  133,  134,  155,   14,    2,  138,
- /*   480 */   139,   15,   16,   17,   18,   19,  145,  121,  147,    2,
- /*   490 */    74,   28,  167,  165,  153,   57,  155,   81,    2,    3,
- /*   500 */    98,    5,    6,    7,    8,    9,   10,   11,   12,   13,
- /*   510 */    14,  109,  110,  155,   81,  113,   78,   79,   80,  117,
- /*   520 */   101,  104,  101,   14,  122,  123,  104,   89,   90,   91,
- /*   530 */    92,   93,   62,   63,   64,   65,   66,   67,   68,   14,
- /*   540 */   159,   41,   42,   43,   44,   45,   46,   47,   48,   49,
- /*   550 */    50,   98,   14,   57,  159,  159,  103,   57,  105,  104,
- /*   560 */   107,  108,  160,  161,  162,  112,  164,  114,   87,  163,
- /*   570 */   163,  100,   14,   83,   78,   79,   80,  124,  125,  115,
- /*   580 */    74,   77,   96,   75,   74,   89,   90,   91,   92,   93,
- /*   590 */    14,   74,   16,   20,   81,   75,   20,  133,  134,   23,
- /*   600 */   117,   98,   26,   27,   28,  122,  123,   73,   73,  156,
- /*   610 */   157,  158,  109,  160,   73,   39,   40,   41,   73,  155,
- /*   620 */   117,   77,   83,  120,   75,  122,  123,   51,   52,   53,
- /*   630 */    54,   55,   56,   57,    1,    2,    3,    4,   83,   76,
- /*   640 */    81,   77,   77,   14,   75,   16,   75,  164,   14,   20,
- /*   650 */    16,   75,   23,   96,   20,   26,   27,   28,   75,   75,
- /*   660 */    26,   27,   28,  160,  161,  162,   73,  164,   39,   40,
- /*   670 */    41,   83,   96,   39,   40,   77,   73,  115,   77,   75,
- /*   680 */    51,   52,   53,   54,   55,   56,   57,   14,   75,   77,
- /*   690 */    57,   58,   59,   60,   61,  133,  134,   14,  136,  137,
- /*   700 */    28,   77,  140,  141,   75,   14,   75,   75,   73,   75,
- /*   710 */    77,   73,   20,   83,   14,   86,   77,  155,   16,  117,
- /*   720 */   118,   76,   16,   75,  122,  123,   21,   22,   23,   24,
- /*   730 */    25,   26,   27,   28,   29,   30,   31,   32,   33,   34,
- /*   740 */    35,   36,   37,   38,   74,   14,   14,   73,   21,   22,
- /*   750 */    23,   24,   25,   26,   27,   28,   29,   30,   31,   32,
- /*   760 */    33,   34,   35,   36,   37,   38,  164,   73,  113,   14,
- /*   770 */    14,   81,  117,   77,   16,   16,   75,  122,  123,   76,
- /*   780 */    14,   74,   77,   21,   22,   23,   24,   25,   26,   27,
- /*   790 */    28,   29,   30,   31,   32,   33,   34,   35,   36,   37,
- /*   800 */    38,    0,   88,   76,   14,   16,   16,   83,  115,   81,
- /*   810 */    20,   73,  169,   23,  115,   14,   26,   27,   28,  164,
- /*   820 */   169,   19,  169,  169,  169,  169,  133,  134,  169,   39,
- /*   830 */    40,   41,  133,  134,  169,  136,  137,  169,  169,   77,
- /*   840 */   169,   51,   52,   53,   54,   55,   56,   57,  155,  131,
- /*   850 */   132,  169,  115,  135,  155,  169,  169,  169,  169,  115,
- /*   860 */   169,  143,  144,  169,  127,   75,  148,  149,  169,  169,
- /*   870 */   133,  134,   71,   72,   73,  115,  169,  133,  134,   78,
- /*   880 */    79,   80,  145,  146,  147,   84,   85,  127,  169,  169,
- /*   890 */   153,  169,  155,  133,  134,   94,   95,  169,  115,  155,
- /*   900 */   169,  169,  169,  169,  169,  145,  169,  147,  115,  169,
- /*   910 */   169,  169,  169,  153,  169,  155,  133,  134,  169,  136,
- /*   920 */   137,  169,  115,  140,  141,  142,  133,  134,  169,  136,
- /*   930 */   137,  115,  169,  140,  141,  115,  169,  169,  155,  169,
- /*   940 */   133,  134,  169,  127,  169,  169,  115,  169,  155,  133,
- /*   950 */   134,  169,  169,  133,  134,  115,  169,  169,  127,  169,
- /*   960 */   169,  145,  155,  147,  133,  134,  169,  127,  169,  153,
- /*   970 */   169,  155,  169,  133,  134,  155,  145,  169,  147,  131,
- /*   980 */   132,  169,  169,  135,  153,  145,  155,  147,  115,  169,
- /*   990 */   169,  143,  144,  153,  169,  155,  148,  149,  132,  169,
- /*  1000 */   169,  135,  169,  169,  169,  169,  133,  134,  169,  143,
- /*  1010 */   144,  169,  169,  169,  148,  149,  169,  169,  169,  169,
- /*  1020 */   169,  169,  169,  169,  169,  169,  169,  169,  155,
+ /*    50 */   178,   28,   62,   63,  167,   57,   66,   67,   68,   69,
+ /*    60 */    70,   28,  143,   97,   15,   16,   17,   18,   19,   75,
+ /*    70 */    71,   72,   22,   23,   24,   25,   26,   27,   28,   29,
+ /*    80 */    30,   31,   32,   33,   34,   86,  167,   37,   38,  191,
+ /*    90 */    96,   93,   94,   95,  137,   97,   14,   99,   74,   74,
+ /*   100 */    76,   76,  104,  105,  106,  107,  108,    2,    3,   85,
+ /*   110 */     5,    6,    7,    8,    9,   10,   11,   12,   13,   14,
+ /*   120 */   171,   14,   15,   16,  175,  167,   41,   20,    1,    2,
+ /*   130 */     3,    4,   75,   26,   27,   28,   51,   52,   53,   54,
+ /*   140 */    55,   56,   57,   14,  187,   88,   39,   40,   41,   42,
+ /*   150 */    43,   44,   45,   46,   47,   48,   49,   50,  169,  170,
+ /*   160 */     5,  172,   57,  116,  117,    2,    3,  130,    5,    6,
+ /*   170 */     7,    8,    9,   10,   11,   12,   13,   14,   71,   22,
+ /*   180 */    23,   24,   25,   26,   27,   28,   29,   30,   31,   32,
+ /*   190 */    33,   34,    2,   86,   37,   38,  168,  132,   93,   94,
+ /*   200 */    95,  167,  137,  138,   99,  147,  101,  167,  150,  104,
+ /*   210 */   105,  106,  107,  108,  177,  178,  158,  159,  130,  131,
+ /*   220 */    57,  163,  164,    2,    3,  130,    5,    6,    7,    8,
+ /*   230 */     9,   10,   11,   12,   13,   14,   14,  113,   14,  128,
+ /*   240 */   165,  166,  118,  132,  120,  142,  122,  123,  137,  138,
+ /*   250 */    28,  127,  187,  129,  132,  133,   93,   94,   95,  137,
+ /*   260 */   138,  106,   99,  139,  140,  130,  178,  104,  105,  106,
+ /*   270 */   107,  108,  171,  178,  116,  117,  142,  171,   57,  176,
+ /*   280 */   171,    2,    3,  130,    5,    6,    7,    8,    9,   10,
+ /*   290 */    11,   12,   13,   14,  104,  105,  106,   73,  187,   75,
+ /*   300 */    76,   77,   78,  179,  180,  181,  130,  183,   86,  187,
+ /*   310 */   176,  171,  101,  178,   93,   94,   95,   93,   94,   95,
+ /*   320 */    99,   14,  111,   99,  100,  104,  105,  106,  107,  108,
+ /*   330 */   142,  178,  171,  109,  110,   28,   57,  177,  178,    2,
+ /*   340 */     3,  113,    5,    6,    7,    8,    9,   10,   11,   12,
+ /*   350 */    13,   14,  124,  125,  178,   14,  128,   16,  146,  147,
+ /*   360 */   132,   20,  150,  171,  176,  137,  138,   26,   27,   28,
+ /*   370 */   158,  159,   93,   94,   95,  163,  164,  130,   99,   88,
+ /*   380 */    39,   40,  142,  104,  105,  106,  107,  108,   97,  130,
+ /*   390 */   130,  130,  177,  178,   57,  148,  149,    2,    3,  113,
+ /*   400 */     5,    6,    7,    8,    9,   10,   11,   12,   13,   14,
+ /*   410 */   124,  183,  184,  185,   14,  187,  176,   74,  132,   76,
+ /*   420 */   134,  135,  141,  137,  138,  178,   14,   86,   28,  130,
+ /*   430 */    93,   94,   95,  177,  178,  130,   99,  178,  178,  178,
+ /*   440 */    28,  104,  105,  106,  107,  108,  162,  148,  149,  114,
+ /*   450 */   115,  141,   57,  148,  149,    2,    3,  113,    5,    6,
+ /*   460 */     7,    8,    9,   10,   11,   12,   13,   14,  124,  183,
+ /*   470 */   184,  185,  121,  187,   87,   88,  132,  178,  130,  135,
+ /*   480 */   187,  137,  138,  178,   87,   88,  130,  187,   93,   94,
+ /*   490 */    95,   87,   88,   74,   99,   76,  148,  149,  178,  104,
+ /*   500 */   105,  106,  107,  108,  148,  149,  189,  151,  152,  170,
+ /*   510 */    57,  155,  156,    2,    3,  110,    5,    6,    7,    8,
+ /*   520 */     9,   10,   11,   12,   13,   14,  178,  183,  184,  185,
+ /*   530 */   176,  187,   87,   88,  178,   14,   41,   42,   43,   44,
+ /*   540 */    45,   46,   47,   48,   49,   50,   93,   94,   95,   87,
+ /*   550 */    88,  130,   57,   14,  130,   87,   88,  104,  105,  106,
+ /*   560 */   107,  108,  140,  130,   87,   88,  142,   28,   57,  148,
+ /*   570 */   149,   86,  148,  149,  132,  133,  166,  153,  154,  137,
+ /*   580 */   138,  148,  149,   14,  160,   16,  162,   87,   88,   20,
+ /*   590 */    87,   88,   23,  176,  130,   26,   27,   28,  126,  178,
+ /*   600 */   176,  126,  178,  178,   93,   94,   95,   86,   39,   40,
+ /*   610 */    41,  178,  148,  149,  126,  104,  105,  106,  107,  108,
+ /*   620 */    51,   52,   53,   54,   55,   56,   57,   87,   88,  187,
+ /*   630 */    92,   14,  126,   16,   96,  146,  147,   20,   92,  150,
+ /*   640 */    23,  119,  178,   26,   27,   28,   92,  158,  159,  136,
+ /*   650 */     2,  190,  163,  164,    2,   86,   39,   40,   41,  188,
+ /*   660 */   130,  178,   96,  116,  119,  116,  182,  119,   51,   52,
+ /*   670 */    53,   54,   55,   56,   57,   64,   65,   14,  148,  149,
+ /*   680 */   111,  151,  152,   14,  182,  155,  156,  157,   14,  182,
+ /*   690 */    79,   80,   81,   82,   83,   84,  119,  113,  102,   14,
+ /*   700 */    89,   90,  118,   86,  120,  186,  122,  123,  178,  186,
+ /*   710 */   115,  127,   14,  129,  173,   92,   98,   87,  101,  111,
+ /*   720 */    92,   92,   86,  139,  140,   21,   22,   23,   24,   25,
+ /*   730 */    26,   27,   28,   29,   30,   31,   32,   33,   34,   35,
+ /*   740 */    36,   37,   38,    1,    2,    3,    4,   21,   22,   23,
+ /*   750 */    24,   25,   26,   27,   28,   29,   30,   31,   32,   33,
+ /*   760 */    34,   35,   36,   37,   38,  181,   20,  183,   96,   62,
+ /*   770 */    63,   75,   86,   66,   67,   68,   69,   70,   75,   75,
+ /*   780 */    21,   22,   23,   24,   25,   26,   27,   28,   29,   30,
+ /*   790 */    31,   32,   33,   34,   35,   36,   37,   38,   75,   57,
+ /*   800 */    58,   59,   60,   61,   97,   75,   98,   87,   98,   88,
+ /*   810 */    86,  111,   87,   87,   21,   22,   23,   24,   25,   26,
+ /*   820 */    27,   28,   29,   30,   31,   32,   33,   34,   35,   36,
+ /*   830 */    37,   38,   87,   86,   86,   86,   86,   98,   75,   96,
+ /*   840 */    87,   75,   86,   14,   87,   87,   86,   88,   21,   22,
+ /*   850 */    23,   24,   25,   26,   27,   28,   29,   30,   31,   32,
+ /*   860 */    33,   34,   35,   36,   37,   38,   14,  130,   28,   14,
+ /*   870 */    87,   16,   14,   86,   86,   20,   75,   75,   23,  142,
+ /*   880 */    87,   26,   27,   28,   98,  148,  149,   20,   14,   16,
+ /*   890 */    87,   16,   88,   86,   39,   40,   41,  160,  161,  162,
+ /*   900 */    92,   75,   14,   75,   14,   14,   51,   52,   53,   54,
+ /*   910 */    55,   56,   57,  176,   87,  178,   21,   22,   23,   24,
+ /*   920 */    25,   26,   27,   28,   29,   30,   31,   32,   33,   34,
+ /*   930 */    35,   36,   37,   38,    1,    2,    3,    4,   14,   96,
+ /*   940 */    87,   86,   21,   22,   23,   24,   25,   26,   27,   28,
+ /*   950 */    29,   30,   31,   32,   33,   34,   35,   36,   37,   38,
+ /*   960 */     0,   16,   16,   86,   88,   14,  103,   98,   16,   75,
+ /*   970 */    14,   92,   16,   19,   14,   86,   20,   96,   14,  130,
+ /*   980 */    87,   14,   26,   27,   86,   14,   14,   14,   14,   19,
+ /*   990 */    57,   58,   59,   60,   61,   39,   40,  148,  149,   76,
+ /*  1000 */   151,  152,  192,  192,  155,  156,  192,  192,  192,  192,
+ /*  1010 */   192,  192,  192,  192,  192,  192,  192,  192,  192,  192,
+ /*  1020 */    87,  192,  192,  192,  192,  192,  192,  178,  192,  192,
+ /*  1030 */   192,  192,  192,   73,  192,   75,   76,   77,   78,  192,
+ /*  1040 */   192,  192,   86,  192,  130,  192,  130,   91,  192,  192,
+ /*  1050 */   192,  192,  192,   93,   94,   95,  142,  192,  192,   99,
+ /*  1060 */   100,  130,  148,  149,  148,  149,  130,  151,  152,  109,
+ /*  1070 */   110,  155,  156,  142,  160,  192,  162,  192,  142,  148,
+ /*  1080 */   149,  192,  192,  130,  148,  149,  192,  192,  192,  192,
+ /*  1090 */   176,  160,  178,  162,  178,  142,  160,  192,  162,  192,
+ /*  1100 */   192,  148,  149,  192,  192,  192,  192,  176,  192,  178,
+ /*  1110 */   192,  192,  176,  160,  178,  162,  192,  192,  192,  192,
+ /*  1120 */   192,  192,  192,  192,  192,  192,  192,  192,  192,  176,
+ /*  1130 */   192,  178,
 };
-#define YY_SHIFT_USE_DFLT (1029)
-#define YY_SHIFT_COUNT    (198)
-#define YY_SHIFT_MIN      (-32)
-#define YY_SHIFT_MAX      (802)
+#define YY_SHIFT_USE_DFLT (1132)
+#define YY_SHIFT_COUNT    (232)
+#define YY_SHIFT_MIN      (-34)
+#define YY_SHIFT_MAX      (974)
 static const short yy_shift_ofst[] = {
- /*     0 */   267,  148,  206,  801,   -2,  576,   -1,  629,   -1,   -1,
- /*    10 */    -1,  790,  790,  790,  790,  470,  470,   96,  -32,  302,
- /*    20 */   264,  322,  264,   90,  380,  634,  634,  634,  634,  634,
- /*    30 */   634,  634,  633,   44,   44,  438,  496,  316,   44,   44,
- /*    40 */    44,   44,   51,  129,   44,   44,   44,  129,  -21,  -21,
- /*    50 */    99,  -21,  -21,   97,   97,   97,  104,  500,  316,  316,
- /*    60 */   316,  375,  466,  466,   50,   16,   16,   51,  144,  -21,
- /*    70 */   283,   99,  -21,  342,  342,   97,  342,   97,  342,  364,
- /*    80 */   393,  476,  487,   97,   97,  433,  364,  433,  364,  509,
- /*    90 */   525,  538,  364,  481,  481,  104,  558,  163,  705,  727,
- /*   100 */   762,  221,  221,  221,  221,  221,  278,  100,  263,  212,
- /*   110 */   216,  250,  295,  304,  319,  327,  331,  391,  411,  357,
- /*   120 */   463,  411,  416,  416,  391,  149,  490,  506,  504,  486,
- /*   130 */   510,  517,  508,  573,  513,  520,  534,  535,  541,  539,
- /*   140 */   545,  544,  555,  549,  563,  564,  565,  569,  571,  557,
- /*   150 */   583,  584,  588,  559,  593,  598,  603,  604,  601,  673,
- /*   160 */   613,  612,  683,  672,  624,  691,  631,  632,  635,  638,
- /*   170 */   630,  692,  700,  639,  702,  645,  706,  648,  670,  674,
- /*   180 */   694,  731,  732,  755,  756,  690,  696,  758,  703,  759,
- /*   190 */   701,  707,  766,  714,  789,  724,  728,  738,  802,
+ /*     0 */   224,  163,  221,  960,   -2,  569,   -1,  617,   -1,   -1,
+ /*    10 */    -1,  855,  855,  855,  855,  -10,  -10,  107,  -34,  707,
+ /*    20 */   279,  337,  279,  105,  395,  341,  341,  341,  341,  341,
+ /*    30 */   341,  341,  933,   24,   23,   23,  453,  511,  742,  956,
+ /*    40 */    23,   23,   23,   23,  307,   -6,   23,   23,   23,   -6,
+ /*    50 */    -5,   -5,   82,   -5,   -5,   33,   33,   33,  129,  495,
+ /*    60 */   611,  742,  742,  742,  956,  956,  956,  956,  956,  956,
+ /*    70 */    85,   49,   49,  127,  190,  190,  307,  155,   25,   -5,
+ /*    80 */   405,   82,   -5,  485,  485,   33,  485,   33,  485,  546,
+ /*    90 */   554,  648,  652,   33,   33,  566,  546,  566,  546,  663,
+ /*   100 */   669,  674,  546,  596,  596,  129,  685,  698,  704,  726,
+ /*   110 */   759,  793,  827,  895,  895,  895,  895,  895,  921,  921,
+ /*   120 */   921,  921,  921,   50,  157,  222,  211,  387,  397,   57,
+ /*   130 */   404,  445,  462,  468,  477,  400,  412,  500,  539,  412,
+ /*   140 */   538,  538,  400,  291,  503,  521,  343,  540,  419,  618,
+ /*   150 */   623,  630,  608,  628,  629,  636,  746,  672,  686,  696,
+ /*   160 */   703,  723,  708,  730,  720,  710,  724,  721,  725,  745,
+ /*   170 */   747,  748,  700,  749,  750,  739,  743,  763,  753,  766,
+ /*   180 */   756,  757,  829,  760,  758,  852,  840,  783,  858,  787,
+ /*   190 */   788,  801,  802,  786,  867,  874,  803,  873,  804,  875,
+ /*   200 */   807,  808,  826,  828,  888,  890,  891,  924,  843,  853,
+ /*   210 */   945,  876,  946,  877,  879,  951,  863,  952,  869,  881,
+ /*   220 */   894,  954,  889,  893,  964,  967,  898,  971,  972,  973,
+ /*   230 */   974,  970,  923,
 };
-#define YY_REDUCE_USE_DFLT (-102)
-#define YY_REDUCE_COUNT (96)
-#define YY_REDUCE_MIN   (-101)
-#define YY_REDUCE_MAX   (873)
+#define YY_REDUCE_USE_DFLT (-162)
+#define YY_REDUCE_COUNT (107)
+#define YY_REDUCE_MIN   (-161)
+#define YY_REDUCE_MAX   (953)
 static const short yy_reduce_ofst[] = {
- /*     0 */   453,  402,  301,  -41,  503,  341,  783,  737,   -7,  562,
- /*    10 */   793,  760,  816,  831,  840,  718,  848,  699,  866,  866,
- /*    20 */   -94,  655,  602,  483,  483,  321,  464,  693,  744,  807,
- /*    30 */   820,  873,  -43,  -99,  -95, -101, -101,  -91,  -40,  -34,
- /*    40 */    17,   48,   12,   76,   49,  106,  107,  105,  -33,  138,
- /*    50 */    73,  141,  160,   75,   79,  125,  183,  -37,    0,   21,
- /*    60 */   108,  117,  188,  196,  231,  177,  186,  203,  194,  210,
- /*    70 */   272,  247,  256,  311,  324,  287,  346,  203,  355,  349,
- /*    80 */   366,  325,  328,  358,  203,  419,  417,  421,  422,  381,
- /*    90 */   395,  396,  455,  406,  407,  471,  396,
+ /*     0 */   124,  228,  286,  584,  344,  424,  530,  737,  356,  849,
+ /*    10 */   916,  914,  931,  936,  953,  212,  489, -128,   58,   58,
+ /*    20 */   122,  111,  442,   65,   65,  247,  299,  305,  348,  421,
+ /*    30 */   433,  464, -113,  -11,   88,   37,  -43,  -43,  -81,  -51,
+ /*    40 */    95,  135,  153,  176, -161,   47,  259,  260,  261,  158,
+ /*    50 */   103,  134,   75,  188,  240,  160,  215,  256,  335, -102,
+ /*    60 */    28,  -42,   34,   40,  101,  106,  109,  140,  161,  192,
+ /*    70 */   284,  281,  310,  351,  293,  300,  320,  317,  339,  354,
+ /*    80 */   422,  410,  417,  472,  475,  425,  488,  320,  506,  522,
+ /*    90 */   513,  461,  471,  483,  320,  547,  545,  549,  548,  484,
+ /*   100 */   502,  507,  577,  519,  523,  595,  507,  541,
 };
 static const YYACTIONTYPE yy_default[] = {
- /*     0 */   650,  650,  650,  650,  650,  618,  650,  639,  650,  650,
- /*    10 */   650,  639,  639,  639,  639,  650,  650,  650,  650,  650,
- /*    20 */   543,  650,  543,  650,  650,  650,  650,  650,  650,  650,
- /*    30 */   650,  650,  650,  650,  641,  650,  650,  650,  650,  650,
- /*    40 */   650,  650,  641,  650,  650,  650,  650,  650,  639,  639,
- /*    50 */   650,  639,  639,  641,  641,  641,  650,  650,  650,  650,
- /*    60 */   650,  650,  650,  650,  650,  567,  566,  650,  559,  639,
- /*    70 */   650,  650,  639,  650,  650,  650,  650,  544,  650,  501,
- /*    80 */   551,  562,  555,  650,  650,  650,  501,  650,  501,  499,
- /*    90 */   499,  499,  501,  533,  533,  650,  499,  650,  650,  650,
- /*   100 */   650,  628,  608,  607,  599,  509,  598,  650,  650,  650,
- /*   110 */   650,  650,  650,  650,  650,  650,  650,  642,  642,  650,
- /*   120 */   650,  650,  570,  569,  650,  650,  583,  650,  650,  650,
- /*   130 */   650,  650,  650,  650,  650,  650,  650,  650,  650,  650,
- /*   140 */   650,  650,  650,  650,  619,  650,  650,  650,  650,  650,
- /*   150 */   650,  650,  595,  650,  650,  650,  650,  650,  650,  650,
- /*   160 */   650,  650,  650,  642,  650,  650,  650,  525,  650,  650,
- /*   170 */   650,  650,  650,  650,  650,  650,  650,  650,  650,  650,
- /*   180 */   650,  650,  650,  650,  650,  571,  650,  650,  650,  650,
- /*   190 */   650,  650,  650,  650,  650,  510,  650,  650,  650,
+ /*     0 */   767,  767,  767,  767,  767,  734,  767,  755,  767,  767,
+ /*    10 */   767,  755,  755,  755,  755,  767,  767,  767,  767,  767,
+ /*    20 */   659,  767,  659,  767,  767,  767,  767,  767,  767,  767,
+ /*    30 */   767,  767,  767,  767,  767,  757,  767,  767,  767,  604,
+ /*    40 */   767,  767,  767,  767,  757,  767,  767,  767,  767,  767,
+ /*    50 */   755,  755,  767,  755,  755,  757,  757,  757,  767,  767,
+ /*    60 */   767,  767,  767,  767,  767,  767,  767,  767,  767,  767,
+ /*    70 */   767,  767,  767,  767,  683,  682,  767,  675,  767,  755,
+ /*    80 */   767,  767,  755,  767,  767,  767,  767,  660,  767,  617,
+ /*    90 */   667,  678,  671,  767,  767,  767,  617,  767,  617,  615,
+ /*   100 */   615,  615,  617,  649,  649,  767,  615,  588,  767,  767,
+ /*   110 */   767,  767,  767,  744,  724,  723,  715,  625,  595,  606,
+ /*   120 */   605,  597,  594,  714,  598,  767,  767,  767,  767,  767,
+ /*   130 */   767,  767,  767,  767,  767,  758,  758,  767,  767,  767,
+ /*   140 */   686,  685,  767,  767,  767,  767,  767,  767,  767,  699,
+ /*   150 */   767,  767,  767,  767,  767,  767,  767,  767,  767,  767,
+ /*   160 */   767,  767,  767,  767,  767,  767,  767,  735,  767,  767,
+ /*   170 */   767,  767,  767,  767,  767,  711,  767,  767,  767,  767,
+ /*   180 */   767,  767,  767,  767,  767,  767,  758,  767,  767,  767,
+ /*   190 */   641,  767,  767,  767,  767,  767,  767,  767,  767,  767,
+ /*   200 */   767,  767,  767,  767,  767,  767,  767,  767,  687,  767,
+ /*   210 */   767,  767,  767,  767,  767,  767,  767,  767,  626,  767,
+ /*   220 */   767,  767,  602,  767,  767,  767,  767,  767,  767,  767,
+ /*   230 */   767,  767,  767,
 };
 /********** End of lemon-generated parsing tables *****************************/
 
@@ -609,6 +643,8 @@ static const YYCODETYPE yyFallback[] = {
     0,  /*   CALLABLE => nothing */
     0,  /* PRE_ASSERT => nothing */
     0,  /* POST_ASSERT => nothing */
+    0,  /*      ERROR => nothing */
+    0,  /*    WARNING => nothing */
    14,  /*       TEMP => NAME */
    14,  /*       FREE => NAME */
    14,  /*        SET => NAME */
@@ -718,33 +754,38 @@ static const char *const yyTokenName[] = {
   "TO_ARRAY",      "TO_STRING",     "TO_INT",        "TO_FLOAT",    
   "TO_BOOL",       "VOID",          "MIXED",         "ARRAY",       
   "OBJECT",        "CALLABLE",      "PRE_ASSERT",    "POST_ASSERT", 
-  "TEMP",          "FREE",          "SET",           "LET",         
-  "RETURN",        "CALLOC",        "CALLBACK",      "LIB",         
-  "EOF",           "EOS",           "COLON",         "LPAREN",      
-  "COMMA",         "RPAREN",        "ENUM",          "STRUCT",      
-  "UNION",         "LBRACE",        "RBRACE",        "EQUALS",      
-  "CONST",         "TYPEDEF",       "ELLIPSIS",      "LBRACKET",    
-  "RBRACKET",      "CHAR",          "SHORT",         "LONG",        
-  "UNSIGNED",      "SIGNED",        "STATIC",        "FUNCTION",    
-  "DOLLAR_NAME",   "error",         "decl_enum",     "decl_enum_items",
-  "decl_enum_item",  "decl_struct_args_block",  "decl_struct_args",  "decl_struct", 
-  "align_and_size",  "decl_union",    "const_type",    "constant",    
-  "decl_typedef",  "decl_typedef_body_ex",  "decl_typedef_body",  "decl_typedef_body_fn_args",
-  "decl",          "decl_func",     "decl_abi",      "decl_var",    
-  "decl_vars",     "decl_arg",      "decl_args",     "struct_args", 
-  "struct_arg",    "decl_layout",   "decl_type",     "const_decl_type",
-  "impl",          "impl_func",     "impl_def_val",  "impl_var",    
-  "impl_arg",      "impl_args",     "impl_vararg",   "impl_stmts",  
-  "impl_stmt",     "number",        "num_exp",       "let_stmt",    
-  "let_calloc",    "let_func",      "callback_arg_list",  "callback_args",
-  "let_callback",  "let_exp",       "let_exps",      "assert_stmt", 
-  "set_stmt",      "set_exp",       "set_exps",      "set_func",    
-  "return_stmt",   "free_stmt",     "free_exps",     "free_exp",    
-  "impl_type",     "reference",     "indirection",   "pointers",    
-  "file",          "blocks",        "block",         "optional_name",
-  "enum_name",     "struct_name",   "union_name",    "decl_var_array_size",
-  "decl_scalar_type",  "decl_scalar_type_short",  "decl_scalar_type_long",  "decl_scalar_type_long_long",
-  "callback_rval",
+  "ERROR",         "WARNING",       "TEMP",          "FREE",        
+  "SET",           "LET",           "RETURN",        "CALLOC",      
+  "CALLBACK",      "LIB",           "ANY",           "EOS",         
+  "EOL",           "COMMENT",       "HASH",          "IFDEF",       
+  "IFNDEF",        "ENDIF",         "ELSE",          "UNDEF",       
+  "DEFINE",        "NO_WHITESPACE",  "LPAREN",        "RPAREN",      
+  "COMMA",         "IF",            "ELIF",          "DEFINED",     
+  "COLON",         "ENUM",          "STRUCT",        "UNION",       
+  "LBRACE",        "RBRACE",        "EQUALS",        "CONST",       
+  "TYPEDEF",       "ELLIPSIS",      "LBRACKET",      "RBRACKET",    
+  "CHAR",          "SHORT",         "LONG",          "UNSIGNED",    
+  "SIGNED",        "STATIC",        "FUNCTION",      "DOLLAR_NAME", 
+  "error",         "decl_enum",     "decl_enum_items",  "decl_enum_item",
+  "decl_struct_args_block",  "decl_struct_args",  "decl_struct",   "align_and_size",
+  "decl_union",    "const_type",    "constant",      "decl_typedef",
+  "decl_typedef_body_ex",  "decl_typedef_body",  "decl_typedef_body_fn_args",  "decl",        
+  "decl_func",     "decl_abi",      "decl_var",      "decl_vars",   
+  "decl_arg",      "decl_args",     "struct_args",   "struct_arg",  
+  "decl_layout",   "decl_type",     "const_decl_type",  "impl",        
+  "impl_func",     "impl_def_val",  "impl_var",      "impl_arg",    
+  "impl_args",     "impl_vararg",   "impl_stmts",    "impl_stmt",   
+  "number",        "num_exp",       "let_stmt",      "let_calloc",  
+  "let_func",      "callback_arg_list",  "callback_args",  "let_callback",
+  "let_exp",       "let_exps",      "assert_stmt",   "set_stmt",    
+  "set_exp",       "set_exps",      "set_func",      "return_stmt", 
+  "free_stmt",     "free_exps",     "free_exp",      "impl_type",   
+  "cpp_exp",       "cpp_macro_decl",  "cpp_macro_decl_tokens",  "cpp_macro_exp",
+  "cpp_macro_sig",  "cpp_macro_sig_args",  "cpp_macro_call",  "cpp_macro_call_args",
+  "reference",     "indirection",   "pointers",      "file",        
+  "blocks",        "block",         "optional_name",  "enum_name",   
+  "struct_name",   "union_name",    "decl_var_array_size",  "decl_scalar_type",
+  "decl_scalar_type_short",  "decl_scalar_type_long",  "decl_scalar_type_long_long",  "callback_rval",
 };
 #endif /* NDEBUG */
 
@@ -752,165 +793,197 @@ static const char *const yyTokenName[] = {
 /* For tracing reduce actions, the names of all rules are required.
 */
 static const char *const yyRuleName[] = {
- /*   0 */ "block ::= LIB QUOTED_STRING EOS",
- /*   1 */ "block ::= decl",
- /*   2 */ "block ::= impl",
- /*   3 */ "block ::= decl_typedef",
- /*   4 */ "block ::= constant",
- /*   5 */ "block ::= decl_struct",
- /*   6 */ "block ::= decl_union",
- /*   7 */ "block ::= decl_enum",
- /*   8 */ "optional_name ::=",
- /*   9 */ "optional_name ::= NAME",
- /*  10 */ "align_and_size ::=",
- /*  11 */ "align_and_size ::= COLON COLON LPAREN NUMBER COMMA NUMBER RPAREN",
- /*  12 */ "enum_name ::= ENUM optional_name",
- /*  13 */ "struct_name ::= STRUCT optional_name",
- /*  14 */ "union_name ::= UNION optional_name",
- /*  15 */ "decl_enum ::= enum_name LBRACE decl_enum_items RBRACE",
- /*  16 */ "decl_enum_items ::= decl_enum_item",
- /*  17 */ "decl_enum_items ::= decl_enum_items COMMA decl_enum_item",
- /*  18 */ "decl_enum_item ::= NAME EQUALS num_exp",
- /*  19 */ "decl_enum_item ::= NAME",
- /*  20 */ "decl_struct_args_block ::= LBRACE struct_args RBRACE",
- /*  21 */ "decl_struct_args ::= decl_struct_args_block",
- /*  22 */ "decl_struct_args ::= EOS",
- /*  23 */ "decl_struct ::= STRUCT NAME align_and_size decl_struct_args",
- /*  24 */ "decl_union ::= UNION NAME align_and_size decl_struct_args",
- /*  25 */ "const_type ::= BOOL|INT|FLOAT|STRING",
- /*  26 */ "constant ::= CONST const_type NSNAME EQUALS impl_def_val EOS",
- /*  27 */ "decl_typedef ::= TYPEDEF decl_typedef_body EOS",
- /*  28 */ "decl_typedef_body_ex ::= struct_name align_and_size decl_struct_args_block decl_var",
- /*  29 */ "decl_typedef_body_ex ::= union_name align_and_size decl_struct_args_block decl_var",
- /*  30 */ "decl_typedef_body_ex ::= decl_enum NAME",
- /*  31 */ "decl_typedef_body ::= decl_typedef_body_ex",
- /*  32 */ "decl_typedef_body_fn_args ::= LPAREN decl_args RPAREN",
- /*  33 */ "decl_typedef_body ::= decl_func decl_typedef_body_fn_args",
- /*  34 */ "decl_typedef_body ::= decl_arg",
- /*  35 */ "decl ::= decl_abi decl_func LPAREN decl_args RPAREN EOS",
- /*  36 */ "decl ::= decl_abi decl_func LPAREN decl_args COMMA ELLIPSIS RPAREN EOS",
- /*  37 */ "decl_func ::= decl_arg",
- /*  38 */ "decl_func ::= VOID NAME",
- /*  39 */ "decl_typedef_body ::= VOID indirection LPAREN indirection NAME RPAREN decl_typedef_body_fn_args",
- /*  40 */ "decl_typedef_body ::= CONST VOID pointers LPAREN indirection NAME RPAREN decl_typedef_body_fn_args",
- /*  41 */ "decl_abi ::= NAME",
- /*  42 */ "decl_var_array_size ::=",
- /*  43 */ "decl_var_array_size ::= LBRACKET NUMBER RBRACKET",
- /*  44 */ "decl_var ::= NAME decl_var_array_size",
- /*  45 */ "decl_var ::= pointers NAME decl_var_array_size",
- /*  46 */ "decl_vars ::= decl_var",
- /*  47 */ "decl_vars ::= decl_vars COMMA decl_var",
- /*  48 */ "decl_arg ::= const_decl_type decl_var",
- /*  49 */ "decl_typedef_body ::= const_decl_type indirection LPAREN indirection NAME RPAREN decl_typedef_body_fn_args",
- /*  50 */ "decl_arg ::= VOID pointers NAME",
- /*  51 */ "decl_arg ::= CONST VOID pointers NAME",
- /*  52 */ "decl_args ::=",
- /*  53 */ "decl_args ::= VOID",
- /*  54 */ "decl_args ::= decl_arg",
- /*  55 */ "decl_args ::= decl_args COMMA decl_arg",
- /*  56 */ "struct_args ::= struct_arg",
- /*  57 */ "struct_args ::= struct_args struct_arg",
- /*  58 */ "struct_arg ::= decl_typedef_body_ex EOS",
- /*  59 */ "struct_arg ::= decl_arg decl_layout EOS",
- /*  60 */ "decl_layout ::=",
- /*  61 */ "decl_layout ::= COLON COLON LPAREN NUMBER COMMA NUMBER RPAREN",
- /*  62 */ "decl_scalar_type ::= CHAR",
- /*  63 */ "decl_scalar_type ::= SHORT decl_scalar_type_short",
- /*  64 */ "decl_scalar_type_short ::=",
- /*  65 */ "decl_scalar_type_short ::= INT",
- /*  66 */ "decl_scalar_type ::= INT",
- /*  67 */ "decl_scalar_type ::= LONG decl_scalar_type_long",
- /*  68 */ "decl_scalar_type_long ::=",
- /*  69 */ "decl_scalar_type_long ::= DOUBLE",
- /*  70 */ "decl_scalar_type_long ::= LONG decl_scalar_type_long_long",
- /*  71 */ "decl_scalar_type_long_long ::=",
- /*  72 */ "decl_scalar_type_long_long ::= INT",
- /*  73 */ "decl_type ::= UNSIGNED decl_scalar_type",
- /*  74 */ "decl_type ::= SIGNED decl_scalar_type",
- /*  75 */ "decl_type ::= UNSIGNED",
- /*  76 */ "decl_type ::= SIGNED",
- /*  77 */ "decl_type ::= decl_scalar_type",
- /*  78 */ "decl_type ::= STRUCT NAME",
- /*  79 */ "decl_type ::= UNION NAME",
- /*  80 */ "decl_type ::= ENUM NAME",
- /*  81 */ "decl_type ::= FLOAT|DOUBLE|INT8|UINT8|INT16|UINT16|INT32|UINT32|INT64|UINT64|NAME",
- /*  82 */ "const_decl_type ::= decl_type",
- /*  83 */ "const_decl_type ::= CONST decl_type",
- /*  84 */ "impl ::= impl_func LBRACE impl_stmts RBRACE",
- /*  85 */ "impl ::= STATIC impl_func LBRACE impl_stmts RBRACE",
- /*  86 */ "impl_func ::= FUNCTION reference NSNAME LPAREN RPAREN COLON impl_type",
- /*  87 */ "impl_func ::= FUNCTION reference NSNAME LPAREN impl_args RPAREN COLON impl_type",
- /*  88 */ "impl_func ::= FUNCTION reference NSNAME LPAREN impl_args COMMA impl_type reference ELLIPSIS DOLLAR_NAME RPAREN COLON impl_type",
- /*  89 */ "impl_def_val ::= NULL|NUMBER|TRUE|FALSE|QUOTED_STRING",
- /*  90 */ "impl_var ::= reference DOLLAR_NAME",
- /*  91 */ "impl_type ::= VOID|MIXED|BOOL|INT|FLOAT|STRING|ARRAY|OBJECT|CALLABLE",
- /*  92 */ "impl_arg ::= impl_type impl_var",
- /*  93 */ "impl_arg ::= impl_type impl_var EQUALS impl_def_val",
- /*  94 */ "impl_args ::= impl_arg",
- /*  95 */ "impl_args ::= impl_args COMMA impl_arg",
- /*  96 */ "impl_stmts ::= impl_stmt",
- /*  97 */ "impl_stmts ::= impl_stmts impl_stmt",
- /*  98 */ "impl_stmt ::= return_stmt",
- /*  99 */ "impl_stmt ::= let_stmt",
- /* 100 */ "impl_stmt ::= set_stmt",
- /* 101 */ "impl_stmt ::= assert_stmt",
- /* 102 */ "impl_stmt ::= free_stmt",
- /* 103 */ "number ::= NUMBER|NSNAME",
- /* 104 */ "number ::= decl_var",
- /* 105 */ "num_exp ::= number",
- /* 106 */ "num_exp ::= LPAREN num_exp RPAREN",
- /* 107 */ "num_exp ::= num_exp PIPE|CARET|AMPERSAND|LSHIFT|RSHIFT|PLUS|MINUS|ASTERISK|SLASH|MODULO|RCHEVR|LCHEVR|CMP_GE|CMP_LE|OR|AND|CMP_EQ|CMP_NE num_exp",
- /* 108 */ "num_exp ::= TILDE|NOT|PLUS|MINUS num_exp",
- /* 109 */ "let_exp ::= NULL",
- /* 110 */ "let_exp ::= AMPERSAND NULL",
- /* 111 */ "let_exp ::= let_callback",
- /* 112 */ "let_exp ::= let_calloc",
- /* 113 */ "let_exp ::= AMPERSAND let_calloc",
- /* 114 */ "let_exp ::= let_func",
- /* 115 */ "let_exp ::= AMPERSAND let_func",
- /* 116 */ "let_exp ::= num_exp",
- /* 117 */ "let_exp ::= AMPERSAND num_exp",
- /* 118 */ "let_exp ::= decl_var EQUALS let_exp",
- /* 119 */ "let_stmt ::= LET let_exp EOS",
- /* 120 */ "let_stmt ::= TEMP decl_var EQUALS reference decl_var EOS",
- /* 121 */ "let_callback ::= CALLBACK callback_rval LPAREN impl_var LPAREN callback_arg_list RPAREN RPAREN",
- /* 122 */ "let_calloc ::= CALLOC LPAREN num_exp COMMA num_exp RPAREN",
- /* 123 */ "let_func ::= ZVAL|OBJVAL|ARRVAL|PATHVAL|STRLEN|STRVAL|FLOATVAL|INTVAL|BOOLVAL|COUNT LPAREN impl_var RPAREN",
- /* 124 */ "let_func ::= ZVAL|OBJVAL|ARRVAL|PATHVAL|STRLEN|STRVAL|FLOATVAL|INTVAL|BOOLVAL|COUNT LPAREN impl_var COMMA let_exps RPAREN",
- /* 125 */ "let_exps ::= let_exp",
- /* 126 */ "let_exps ::= let_exps COMMA let_exp",
- /* 127 */ "callback_arg_list ::=",
- /* 128 */ "callback_arg_list ::= callback_args",
- /* 129 */ "callback_args ::= set_exp",
- /* 130 */ "callback_args ::= callback_args COMMA set_exp",
- /* 131 */ "callback_rval ::= ZVAL|OBJVAL|ARRVAL|PATHVAL|STRLEN|STRVAL|FLOATVAL|INTVAL|BOOLVAL|COUNT",
- /* 132 */ "callback_rval ::= VOID",
- /* 133 */ "set_func ::= TO_OBJECT|TO_ARRAY|TO_STRING|TO_INT|TO_FLOAT|TO_BOOL|ZVAL|VOID LPAREN decl_var RPAREN",
- /* 134 */ "set_func ::= TO_OBJECT|TO_ARRAY|TO_STRING|TO_INT|TO_FLOAT|TO_BOOL|ZVAL|VOID LPAREN decl_var COMMA set_exps RPAREN",
- /* 135 */ "set_func ::= TO_OBJECT|TO_ARRAY|TO_STRING|TO_INT|TO_FLOAT|TO_BOOL|ZVAL|VOID LPAREN decl_var COMMA ELLIPSIS RPAREN",
- /* 136 */ "set_exp ::= set_func",
- /* 137 */ "set_exp ::= num_exp",
- /* 138 */ "set_exps ::= set_exp",
- /* 139 */ "set_exps ::= set_exps COMMA set_exp",
- /* 140 */ "set_exp ::= impl_var EQUALS set_exp",
- /* 141 */ "set_stmt ::= SET set_exp EOS",
- /* 142 */ "return_stmt ::= RETURN set_func EOS",
- /* 143 */ "free_stmt ::= FREE free_exps EOS",
- /* 144 */ "free_exps ::= free_exp",
- /* 145 */ "free_exps ::= free_exps COMMA free_exp",
- /* 146 */ "free_exp ::= NAME LPAREN decl_vars RPAREN",
- /* 147 */ "assert_stmt ::= PRE_ASSERT|POST_ASSERT num_exp EOS",
- /* 148 */ "reference ::=",
- /* 149 */ "reference ::= AMPERSAND",
- /* 150 */ "indirection ::=",
- /* 151 */ "indirection ::= pointers",
- /* 152 */ "pointers ::= ASTERISK",
- /* 153 */ "pointers ::= pointers ASTERISK",
- /* 154 */ "file ::= blocks",
- /* 155 */ "blocks ::= block",
- /* 156 */ "blocks ::= blocks block",
- /* 157 */ "block ::= EOF",
- /* 158 */ "block ::= EOS",
+ /*   0 */ "block ::= HASH cpp_exp EOL",
+ /*   1 */ "cpp_exp ::= ERROR|WARNING QUOTED_STRING",
+ /*   2 */ "cpp_exp ::= IFDEF NAME",
+ /*   3 */ "cpp_exp ::= IFNDEF NAME",
+ /*   4 */ "cpp_exp ::= ENDIF",
+ /*   5 */ "cpp_exp ::= ELSE",
+ /*   6 */ "cpp_exp ::= UNDEF NAME",
+ /*   7 */ "cpp_exp ::= DEFINE NAME cpp_macro_decl",
+ /*   8 */ "cpp_macro_decl ::=",
+ /*   9 */ "cpp_macro_decl ::= cpp_macro_sig",
+ /*  10 */ "cpp_macro_decl ::= cpp_macro_sig cpp_macro_decl_tokens",
+ /*  11 */ "cpp_macro_sig ::= NO_WHITESPACE LPAREN cpp_macro_sig_args RPAREN",
+ /*  12 */ "cpp_macro_sig_args ::=",
+ /*  13 */ "cpp_macro_sig_args ::= NAME",
+ /*  14 */ "cpp_macro_sig_args ::= cpp_macro_sig_args COMMA NAME",
+ /*  15 */ "cpp_macro_decl ::= cpp_macro_decl_tokens",
+ /*  16 */ "cpp_macro_decl_tokens ::= ANY",
+ /*  17 */ "cpp_macro_decl_tokens ::= cpp_macro_decl_tokens ANY",
+ /*  18 */ "cpp_exp ::= IF cpp_macro_exp",
+ /*  19 */ "cpp_exp ::= ELIF cpp_macro_exp",
+ /*  20 */ "cpp_macro_exp ::= LPAREN cpp_macro_exp RPAREN",
+ /*  21 */ "cpp_macro_exp ::= TILDE|NOT|PLUS|MINUS cpp_macro_exp",
+ /*  22 */ "cpp_macro_exp ::= cpp_macro_exp PIPE|CARET|AMPERSAND|LSHIFT|RSHIFT|PLUS|MINUS|ASTERISK|SLASH|MODULO|RCHEVR|LCHEVR|CMP_GE|CMP_LE|OR|AND|CMP_EQ|CMP_NE cpp_macro_exp",
+ /*  23 */ "cpp_macro_exp ::= DEFINED NAME",
+ /*  24 */ "cpp_macro_exp ::= DEFINED LPAREN NAME RPAREN",
+ /*  25 */ "cpp_macro_exp ::= NUMBER|NSNAME",
+ /*  26 */ "cpp_macro_exp ::= NAME",
+ /*  27 */ "cpp_macro_exp ::= NAME LPAREN cpp_macro_call_args RPAREN",
+ /*  28 */ "cpp_macro_call_args ::=",
+ /*  29 */ "cpp_macro_call_args ::= cpp_macro_exp",
+ /*  30 */ "cpp_macro_call_args ::= cpp_macro_call_args COMMA cpp_macro_exp",
+ /*  31 */ "block ::= LIB QUOTED_STRING EOS",
+ /*  32 */ "block ::= decl",
+ /*  33 */ "block ::= impl",
+ /*  34 */ "block ::= decl_typedef",
+ /*  35 */ "block ::= constant",
+ /*  36 */ "block ::= decl_struct",
+ /*  37 */ "block ::= decl_union",
+ /*  38 */ "block ::= decl_enum",
+ /*  39 */ "optional_name ::=",
+ /*  40 */ "optional_name ::= NAME",
+ /*  41 */ "align_and_size ::=",
+ /*  42 */ "align_and_size ::= COLON COLON LPAREN NUMBER COMMA NUMBER RPAREN",
+ /*  43 */ "enum_name ::= ENUM optional_name",
+ /*  44 */ "struct_name ::= STRUCT optional_name",
+ /*  45 */ "union_name ::= UNION optional_name",
+ /*  46 */ "decl_enum ::= enum_name LBRACE decl_enum_items RBRACE",
+ /*  47 */ "decl_enum_items ::= decl_enum_item",
+ /*  48 */ "decl_enum_items ::= decl_enum_items COMMA decl_enum_item",
+ /*  49 */ "decl_enum_item ::= NAME EQUALS num_exp",
+ /*  50 */ "decl_enum_item ::= NAME",
+ /*  51 */ "decl_struct_args_block ::= LBRACE struct_args RBRACE",
+ /*  52 */ "decl_struct_args ::= decl_struct_args_block",
+ /*  53 */ "decl_struct_args ::= EOS",
+ /*  54 */ "decl_struct ::= STRUCT NAME align_and_size decl_struct_args",
+ /*  55 */ "decl_union ::= UNION NAME align_and_size decl_struct_args",
+ /*  56 */ "const_type ::= BOOL|INT|FLOAT|STRING",
+ /*  57 */ "constant ::= CONST const_type NSNAME EQUALS impl_def_val EOS",
+ /*  58 */ "decl_typedef ::= TYPEDEF decl_typedef_body EOS",
+ /*  59 */ "decl_typedef_body_ex ::= struct_name align_and_size decl_struct_args_block decl_var",
+ /*  60 */ "decl_typedef_body_ex ::= union_name align_and_size decl_struct_args_block decl_var",
+ /*  61 */ "decl_typedef_body_ex ::= decl_enum NAME",
+ /*  62 */ "decl_typedef_body ::= decl_typedef_body_ex",
+ /*  63 */ "decl_typedef_body_fn_args ::= LPAREN decl_args RPAREN",
+ /*  64 */ "decl_typedef_body ::= decl_func decl_typedef_body_fn_args",
+ /*  65 */ "decl_typedef_body ::= decl_arg",
+ /*  66 */ "decl ::= decl_abi decl_func LPAREN decl_args RPAREN EOS",
+ /*  67 */ "decl ::= decl_abi decl_func LPAREN decl_args COMMA ELLIPSIS RPAREN EOS",
+ /*  68 */ "decl_func ::= decl_arg",
+ /*  69 */ "decl_func ::= VOID NAME",
+ /*  70 */ "decl_typedef_body ::= VOID indirection LPAREN indirection NAME RPAREN decl_typedef_body_fn_args",
+ /*  71 */ "decl_typedef_body ::= CONST VOID pointers LPAREN indirection NAME RPAREN decl_typedef_body_fn_args",
+ /*  72 */ "decl_abi ::= NAME",
+ /*  73 */ "decl_var_array_size ::=",
+ /*  74 */ "decl_var_array_size ::= LBRACKET NUMBER RBRACKET",
+ /*  75 */ "decl_var ::= NAME decl_var_array_size",
+ /*  76 */ "decl_var ::= pointers NAME decl_var_array_size",
+ /*  77 */ "decl_vars ::= decl_var",
+ /*  78 */ "decl_vars ::= decl_vars COMMA decl_var",
+ /*  79 */ "decl_arg ::= const_decl_type decl_var",
+ /*  80 */ "decl_typedef_body ::= const_decl_type indirection LPAREN indirection NAME RPAREN decl_typedef_body_fn_args",
+ /*  81 */ "decl_arg ::= VOID pointers NAME",
+ /*  82 */ "decl_arg ::= CONST VOID pointers NAME",
+ /*  83 */ "decl_args ::=",
+ /*  84 */ "decl_args ::= VOID",
+ /*  85 */ "decl_args ::= decl_arg",
+ /*  86 */ "decl_args ::= decl_args COMMA decl_arg",
+ /*  87 */ "struct_args ::= struct_arg",
+ /*  88 */ "struct_args ::= struct_args struct_arg",
+ /*  89 */ "struct_arg ::= decl_typedef_body_ex EOS",
+ /*  90 */ "struct_arg ::= decl_arg decl_layout EOS",
+ /*  91 */ "decl_layout ::=",
+ /*  92 */ "decl_layout ::= COLON COLON LPAREN NUMBER COMMA NUMBER RPAREN",
+ /*  93 */ "decl_scalar_type ::= CHAR",
+ /*  94 */ "decl_scalar_type ::= SHORT decl_scalar_type_short",
+ /*  95 */ "decl_scalar_type_short ::=",
+ /*  96 */ "decl_scalar_type_short ::= INT",
+ /*  97 */ "decl_scalar_type ::= INT",
+ /*  98 */ "decl_scalar_type ::= LONG decl_scalar_type_long",
+ /*  99 */ "decl_scalar_type_long ::=",
+ /* 100 */ "decl_scalar_type_long ::= DOUBLE",
+ /* 101 */ "decl_scalar_type_long ::= LONG decl_scalar_type_long_long",
+ /* 102 */ "decl_scalar_type_long_long ::=",
+ /* 103 */ "decl_scalar_type_long_long ::= INT",
+ /* 104 */ "decl_type ::= UNSIGNED decl_scalar_type",
+ /* 105 */ "decl_type ::= SIGNED decl_scalar_type",
+ /* 106 */ "decl_type ::= UNSIGNED",
+ /* 107 */ "decl_type ::= SIGNED",
+ /* 108 */ "decl_type ::= decl_scalar_type",
+ /* 109 */ "decl_type ::= STRUCT NAME",
+ /* 110 */ "decl_type ::= UNION NAME",
+ /* 111 */ "decl_type ::= ENUM NAME",
+ /* 112 */ "decl_type ::= FLOAT|DOUBLE|INT8|UINT8|INT16|UINT16|INT32|UINT32|INT64|UINT64|NAME",
+ /* 113 */ "const_decl_type ::= decl_type",
+ /* 114 */ "const_decl_type ::= CONST decl_type",
+ /* 115 */ "impl ::= impl_func LBRACE impl_stmts RBRACE",
+ /* 116 */ "impl ::= STATIC impl_func LBRACE impl_stmts RBRACE",
+ /* 117 */ "impl_func ::= FUNCTION reference NSNAME LPAREN RPAREN COLON impl_type",
+ /* 118 */ "impl_func ::= FUNCTION reference NSNAME LPAREN impl_args RPAREN COLON impl_type",
+ /* 119 */ "impl_func ::= FUNCTION reference NSNAME LPAREN impl_args COMMA impl_type reference ELLIPSIS DOLLAR_NAME RPAREN COLON impl_type",
+ /* 120 */ "impl_def_val ::= NULL|NUMBER|TRUE|FALSE|QUOTED_STRING",
+ /* 121 */ "impl_var ::= reference DOLLAR_NAME",
+ /* 122 */ "impl_type ::= VOID|MIXED|BOOL|INT|FLOAT|STRING|ARRAY|OBJECT|CALLABLE",
+ /* 123 */ "impl_arg ::= impl_type impl_var",
+ /* 124 */ "impl_arg ::= impl_type impl_var EQUALS impl_def_val",
+ /* 125 */ "impl_args ::= impl_arg",
+ /* 126 */ "impl_args ::= impl_args COMMA impl_arg",
+ /* 127 */ "impl_stmts ::= impl_stmt",
+ /* 128 */ "impl_stmts ::= impl_stmts impl_stmt",
+ /* 129 */ "impl_stmt ::= return_stmt",
+ /* 130 */ "impl_stmt ::= let_stmt",
+ /* 131 */ "impl_stmt ::= set_stmt",
+ /* 132 */ "impl_stmt ::= assert_stmt",
+ /* 133 */ "impl_stmt ::= free_stmt",
+ /* 134 */ "number ::= NUMBER|NSNAME",
+ /* 135 */ "number ::= decl_var",
+ /* 136 */ "num_exp ::= number",
+ /* 137 */ "num_exp ::= LPAREN num_exp RPAREN",
+ /* 138 */ "num_exp ::= num_exp PIPE|CARET|AMPERSAND|LSHIFT|RSHIFT|PLUS|MINUS|ASTERISK|SLASH|MODULO|RCHEVR|LCHEVR|CMP_GE|CMP_LE|OR|AND|CMP_EQ|CMP_NE num_exp",
+ /* 139 */ "num_exp ::= TILDE|NOT|PLUS|MINUS num_exp",
+ /* 140 */ "let_exp ::= NULL",
+ /* 141 */ "let_exp ::= AMPERSAND NULL",
+ /* 142 */ "let_exp ::= let_callback",
+ /* 143 */ "let_exp ::= let_calloc",
+ /* 144 */ "let_exp ::= AMPERSAND let_calloc",
+ /* 145 */ "let_exp ::= let_func",
+ /* 146 */ "let_exp ::= AMPERSAND let_func",
+ /* 147 */ "let_exp ::= num_exp",
+ /* 148 */ "let_exp ::= AMPERSAND num_exp",
+ /* 149 */ "let_exp ::= decl_var EQUALS let_exp",
+ /* 150 */ "let_stmt ::= LET let_exp EOS",
+ /* 151 */ "let_stmt ::= TEMP decl_var EQUALS reference decl_var EOS",
+ /* 152 */ "let_callback ::= CALLBACK callback_rval LPAREN impl_var LPAREN callback_arg_list RPAREN RPAREN",
+ /* 153 */ "let_calloc ::= CALLOC LPAREN num_exp COMMA num_exp RPAREN",
+ /* 154 */ "let_func ::= ZVAL|OBJVAL|ARRVAL|PATHVAL|STRLEN|STRVAL|FLOATVAL|INTVAL|BOOLVAL|COUNT LPAREN impl_var RPAREN",
+ /* 155 */ "let_func ::= ZVAL|OBJVAL|ARRVAL|PATHVAL|STRLEN|STRVAL|FLOATVAL|INTVAL|BOOLVAL|COUNT LPAREN impl_var COMMA let_exps RPAREN",
+ /* 156 */ "let_exps ::= let_exp",
+ /* 157 */ "let_exps ::= let_exps COMMA let_exp",
+ /* 158 */ "callback_arg_list ::=",
+ /* 159 */ "callback_arg_list ::= callback_args",
+ /* 160 */ "callback_args ::= set_exp",
+ /* 161 */ "callback_args ::= callback_args COMMA set_exp",
+ /* 162 */ "callback_rval ::= ZVAL|OBJVAL|ARRVAL|PATHVAL|STRLEN|STRVAL|FLOATVAL|INTVAL|BOOLVAL|COUNT",
+ /* 163 */ "callback_rval ::= VOID",
+ /* 164 */ "set_func ::= TO_OBJECT|TO_ARRAY|TO_STRING|TO_INT|TO_FLOAT|TO_BOOL|ZVAL|VOID LPAREN decl_var RPAREN",
+ /* 165 */ "set_func ::= TO_OBJECT|TO_ARRAY|TO_STRING|TO_INT|TO_FLOAT|TO_BOOL|ZVAL|VOID LPAREN decl_var COMMA set_exps RPAREN",
+ /* 166 */ "set_func ::= TO_OBJECT|TO_ARRAY|TO_STRING|TO_INT|TO_FLOAT|TO_BOOL|ZVAL|VOID LPAREN decl_var COMMA ELLIPSIS RPAREN",
+ /* 167 */ "set_exp ::= set_func",
+ /* 168 */ "set_exp ::= num_exp",
+ /* 169 */ "set_exps ::= set_exp",
+ /* 170 */ "set_exps ::= set_exps COMMA set_exp",
+ /* 171 */ "set_exp ::= impl_var EQUALS set_exp",
+ /* 172 */ "set_stmt ::= SET set_exp EOS",
+ /* 173 */ "return_stmt ::= RETURN set_func EOS",
+ /* 174 */ "free_stmt ::= FREE free_exps EOS",
+ /* 175 */ "free_exps ::= free_exp",
+ /* 176 */ "free_exps ::= free_exps COMMA free_exp",
+ /* 177 */ "free_exp ::= NAME LPAREN decl_vars RPAREN",
+ /* 178 */ "assert_stmt ::= PRE_ASSERT|POST_ASSERT num_exp EOS",
+ /* 179 */ "reference ::=",
+ /* 180 */ "reference ::= AMPERSAND",
+ /* 181 */ "indirection ::=",
+ /* 182 */ "indirection ::= pointers",
+ /* 183 */ "pointers ::= ASTERISK",
+ /* 184 */ "pointers ::= pointers ASTERISK",
+ /* 185 */ "file ::= blocks",
+ /* 186 */ "blocks ::= block",
+ /* 187 */ "blocks ::= blocks block",
+ /* 188 */ "block ::= EOS",
+ /* 189 */ "block ::= EOL",
+ /* 190 */ "block ::= COMMENT",
 };
 #endif /* NDEBUG */
 
@@ -1092,332 +1165,367 @@ static void yy_destructor(
     case 61: /* CALLABLE */
     case 62: /* PRE_ASSERT */
     case 63: /* POST_ASSERT */
-    case 64: /* TEMP */
-    case 65: /* FREE */
-    case 66: /* SET */
-    case 67: /* LET */
-    case 68: /* RETURN */
-    case 69: /* CALLOC */
-    case 70: /* CALLBACK */
-    case 71: /* LIB */
-    case 72: /* EOF */
-    case 73: /* EOS */
-    case 74: /* COLON */
-    case 75: /* LPAREN */
-    case 76: /* COMMA */
-    case 77: /* RPAREN */
-    case 78: /* ENUM */
-    case 79: /* STRUCT */
-    case 80: /* UNION */
-    case 81: /* LBRACE */
-    case 82: /* RBRACE */
-    case 83: /* EQUALS */
-    case 84: /* CONST */
-    case 85: /* TYPEDEF */
-    case 86: /* ELLIPSIS */
-    case 87: /* LBRACKET */
-    case 88: /* RBRACKET */
-    case 89: /* CHAR */
-    case 90: /* SHORT */
-    case 91: /* LONG */
-    case 92: /* UNSIGNED */
-    case 93: /* SIGNED */
-    case 94: /* STATIC */
-    case 95: /* FUNCTION */
-    case 96: /* DOLLAR_NAME */
+    case 64: /* ERROR */
+    case 65: /* WARNING */
+    case 66: /* TEMP */
+    case 67: /* FREE */
+    case 68: /* SET */
+    case 69: /* LET */
+    case 70: /* RETURN */
+    case 71: /* CALLOC */
+    case 72: /* CALLBACK */
+    case 73: /* LIB */
+    case 74: /* ANY */
+    case 75: /* EOS */
+    case 76: /* EOL */
+    case 77: /* COMMENT */
+    case 78: /* HASH */
+    case 79: /* IFDEF */
+    case 80: /* IFNDEF */
+    case 81: /* ENDIF */
+    case 82: /* ELSE */
+    case 83: /* UNDEF */
+    case 84: /* DEFINE */
+    case 85: /* NO_WHITESPACE */
+    case 86: /* LPAREN */
+    case 87: /* RPAREN */
+    case 88: /* COMMA */
+    case 89: /* IF */
+    case 90: /* ELIF */
+    case 91: /* DEFINED */
+    case 92: /* COLON */
+    case 93: /* ENUM */
+    case 94: /* STRUCT */
+    case 95: /* UNION */
+    case 96: /* LBRACE */
+    case 97: /* RBRACE */
+    case 98: /* EQUALS */
+    case 99: /* CONST */
+    case 100: /* TYPEDEF */
+    case 101: /* ELLIPSIS */
+    case 102: /* LBRACKET */
+    case 103: /* RBRACKET */
+    case 104: /* CHAR */
+    case 105: /* SHORT */
+    case 106: /* LONG */
+    case 107: /* UNSIGNED */
+    case 108: /* SIGNED */
+    case 109: /* STATIC */
+    case 110: /* FUNCTION */
+    case 111: /* DOLLAR_NAME */
 {
 #line 37 "src/parser_proc.y"
 free((yypminor->yy0));
-#line 1132 "src/parser_proc.c"
+#line 1220 "src/parser_proc.c"
 }
       break;
       /* Default NON-TERMINAL Destructor */
-    case 97: /* error */
-    case 104: /* align_and_size */
-    case 153: /* reference */
-    case 154: /* indirection */
-    case 155: /* pointers */
-    case 156: /* file */
-    case 157: /* blocks */
-    case 158: /* block */
-    case 159: /* optional_name */
-    case 160: /* enum_name */
-    case 161: /* struct_name */
-    case 162: /* union_name */
-    case 163: /* decl_var_array_size */
-    case 164: /* decl_scalar_type */
-    case 165: /* decl_scalar_type_short */
-    case 166: /* decl_scalar_type_long */
-    case 167: /* decl_scalar_type_long_long */
-    case 168: /* callback_rval */
+    case 112: /* error */
+    case 119: /* align_and_size */
+    case 176: /* reference */
+    case 177: /* indirection */
+    case 178: /* pointers */
+    case 179: /* file */
+    case 180: /* blocks */
+    case 181: /* block */
+    case 182: /* optional_name */
+    case 183: /* enum_name */
+    case 184: /* struct_name */
+    case 185: /* union_name */
+    case 186: /* decl_var_array_size */
+    case 187: /* decl_scalar_type */
+    case 188: /* decl_scalar_type_short */
+    case 189: /* decl_scalar_type_long */
+    case 190: /* decl_scalar_type_long_long */
+    case 191: /* callback_rval */
 {
 #line 38 "src/parser_proc.y"
 (void)P;
-#line 1157 "src/parser_proc.c"
+#line 1245 "src/parser_proc.c"
 }
       break;
-    case 98: /* decl_enum */
-{
-#line 64 "src/parser_proc.y"
-psi_decl_enum_free(&(yypminor->yy87));
-#line 1164 "src/parser_proc.c"
-}
-      break;
-    case 99: /* decl_enum_items */
-    case 101: /* decl_struct_args_block */
-    case 102: /* decl_struct_args */
-    case 111: /* decl_typedef_body_fn_args */
-    case 116: /* decl_vars */
-    case 118: /* decl_args */
-    case 119: /* struct_args */
-    case 129: /* impl_args */
-    case 131: /* impl_stmts */
-    case 142: /* let_exps */
-    case 146: /* set_exps */
-    case 150: /* free_exps */
+    case 113: /* decl_enum */
 {
 #line 66 "src/parser_proc.y"
-psi_plist_free((yypminor->yy7));
-#line 1182 "src/parser_proc.c"
+psi_decl_enum_free(&(yypminor->yy323));
+#line 1252 "src/parser_proc.c"
 }
       break;
-    case 100: /* decl_enum_item */
+    case 114: /* decl_enum_items */
+    case 116: /* decl_struct_args_block */
+    case 117: /* decl_struct_args */
+    case 126: /* decl_typedef_body_fn_args */
+    case 131: /* decl_vars */
+    case 133: /* decl_args */
+    case 134: /* struct_args */
+    case 144: /* impl_args */
+    case 146: /* impl_stmts */
+    case 157: /* let_exps */
+    case 161: /* set_exps */
+    case 165: /* free_exps */
+    case 170: /* cpp_macro_decl_tokens */
+    case 172: /* cpp_macro_sig */
+    case 173: /* cpp_macro_sig_args */
+    case 174: /* cpp_macro_call */
+    case 175: /* cpp_macro_call_args */
 {
 #line 68 "src/parser_proc.y"
-psi_decl_enum_item_free(&(yypminor->yy109));
-#line 1189 "src/parser_proc.c"
+psi_plist_free((yypminor->yy179));
+#line 1275 "src/parser_proc.c"
 }
       break;
-    case 103: /* decl_struct */
+    case 115: /* decl_enum_item */
 {
-#line 74 "src/parser_proc.y"
-psi_decl_struct_free(&(yypminor->yy137));
-#line 1196 "src/parser_proc.c"
+#line 70 "src/parser_proc.y"
+psi_decl_enum_item_free(&(yypminor->yy169));
+#line 1282 "src/parser_proc.c"
 }
       break;
-    case 105: /* decl_union */
+    case 118: /* decl_struct */
 {
-#line 77 "src/parser_proc.y"
-psi_decl_union_free(&(yypminor->yy47));
-#line 1203 "src/parser_proc.c"
+#line 76 "src/parser_proc.y"
+psi_decl_struct_free(&(yypminor->yy324));
+#line 1289 "src/parser_proc.c"
 }
       break;
-    case 106: /* const_type */
+    case 120: /* decl_union */
 {
 #line 79 "src/parser_proc.y"
-psi_const_type_free(&(yypminor->yy181));
-#line 1210 "src/parser_proc.c"
+psi_decl_union_free(&(yypminor->yy15));
+#line 1296 "src/parser_proc.c"
 }
       break;
-    case 107: /* constant */
+    case 121: /* const_type */
 {
 #line 81 "src/parser_proc.y"
-psi_const_free(&(yypminor->yy336));
-#line 1217 "src/parser_proc.c"
+psi_const_type_free(&(yypminor->yy351));
+#line 1303 "src/parser_proc.c"
 }
       break;
-    case 108: /* decl_typedef */
-    case 109: /* decl_typedef_body_ex */
-    case 110: /* decl_typedef_body */
-    case 113: /* decl_func */
-    case 117: /* decl_arg */
-    case 120: /* struct_arg */
+    case 122: /* constant */
 {
 #line 83 "src/parser_proc.y"
-psi_decl_arg_free(&(yypminor->yy64));
-#line 1229 "src/parser_proc.c"
+psi_const_free(&(yypminor->yy38));
+#line 1310 "src/parser_proc.c"
 }
       break;
-    case 112: /* decl */
-{
-#line 91 "src/parser_proc.y"
-psi_decl_free(&(yypminor->yy17));
-#line 1236 "src/parser_proc.c"
+    case 123: /* decl_typedef */
+    case 124: /* decl_typedef_body_ex */
+    case 125: /* decl_typedef_body */
+    case 128: /* decl_func */
+    case 132: /* decl_arg */
+    case 135: /* struct_arg */
+{
+#line 85 "src/parser_proc.y"
+psi_decl_arg_free(&(yypminor->yy320));
+#line 1322 "src/parser_proc.c"
 }
       break;
-    case 114: /* decl_abi */
+    case 127: /* decl */
 {
-#line 95 "src/parser_proc.y"
-psi_decl_abi_free(&(yypminor->yy180));
-#line 1243 "src/parser_proc.c"
+#line 93 "src/parser_proc.y"
+psi_decl_free(&(yypminor->yy303));
+#line 1329 "src/parser_proc.c"
 }
       break;
-    case 115: /* decl_var */
+    case 129: /* decl_abi */
 {
 #line 97 "src/parser_proc.y"
-psi_decl_var_free(&(yypminor->yy131));
-#line 1250 "src/parser_proc.c"
+psi_decl_abi_free(&(yypminor->yy26));
+#line 1336 "src/parser_proc.c"
 }
       break;
-    case 121: /* decl_layout */
+    case 130: /* decl_var */
 {
-#line 109 "src/parser_proc.y"
-psi_layout_free(&(yypminor->yy221));
-#line 1257 "src/parser_proc.c"
+#line 99 "src/parser_proc.y"
+psi_decl_var_free(&(yypminor->yy271));
+#line 1343 "src/parser_proc.c"
 }
       break;
-    case 122: /* decl_type */
-    case 123: /* const_decl_type */
+    case 136: /* decl_layout */
 {
 #line 111 "src/parser_proc.y"
-psi_decl_type_free(&(yypminor->yy182));
-#line 1265 "src/parser_proc.c"
+psi_layout_free(&(yypminor->yy369));
+#line 1350 "src/parser_proc.c"
 }
       break;
-    case 124: /* impl */
+    case 137: /* decl_type */
+    case 138: /* const_decl_type */
 {
-#line 115 "src/parser_proc.y"
-psi_impl_free(&(yypminor->yy303));
-#line 1272 "src/parser_proc.c"
+#line 113 "src/parser_proc.y"
+psi_decl_type_free(&(yypminor->yy172));
+#line 1358 "src/parser_proc.c"
 }
       break;
-    case 125: /* impl_func */
+    case 139: /* impl */
 {
 #line 117 "src/parser_proc.y"
-psi_impl_func_free(&(yypminor->yy226));
-#line 1279 "src/parser_proc.c"
+psi_impl_free(&(yypminor->yy49));
+#line 1365 "src/parser_proc.c"
 }
       break;
-    case 126: /* impl_def_val */
+    case 140: /* impl_func */
 {
 #line 119 "src/parser_proc.y"
-psi_impl_def_val_free(&(yypminor->yy319));
-#line 1286 "src/parser_proc.c"
+psi_impl_func_free(&(yypminor->yy56));
+#line 1372 "src/parser_proc.c"
 }
       break;
-    case 127: /* impl_var */
+    case 141: /* impl_def_val */
 {
 #line 121 "src/parser_proc.y"
-psi_impl_var_free(&(yypminor->yy123));
-#line 1293 "src/parser_proc.c"
+psi_impl_def_val_free(&(yypminor->yy145));
+#line 1379 "src/parser_proc.c"
 }
       break;
-    case 128: /* impl_arg */
-    case 130: /* impl_vararg */
+    case 142: /* impl_var */
 {
 #line 123 "src/parser_proc.y"
-psi_impl_arg_free(&(yypminor->yy56));
-#line 1301 "src/parser_proc.c"
+psi_impl_var_free(&(yypminor->yy370));
+#line 1386 "src/parser_proc.c"
 }
       break;
-    case 132: /* impl_stmt */
+    case 143: /* impl_arg */
+    case 145: /* impl_vararg */
 {
-#line 131 "src/parser_proc.y"
-psi_impl_stmt_free(&(yypminor->yy282));
-#line 1308 "src/parser_proc.c"
+#line 125 "src/parser_proc.y"
+psi_impl_arg_free(&(yypminor->yy34));
+#line 1394 "src/parser_proc.c"
 }
       break;
-    case 133: /* number */
+    case 147: /* impl_stmt */
 {
 #line 133 "src/parser_proc.y"
-psi_number_free(&(yypminor->yy66));
-#line 1315 "src/parser_proc.c"
+psi_impl_stmt_free(&(yypminor->yy238));
+#line 1401 "src/parser_proc.c"
 }
       break;
-    case 134: /* num_exp */
+    case 148: /* number */
 {
 #line 135 "src/parser_proc.y"
-psi_num_exp_free(&(yypminor->yy124));
-#line 1322 "src/parser_proc.c"
+psi_number_free(&(yypminor->yy57));
+#line 1408 "src/parser_proc.c"
 }
       break;
-    case 135: /* let_stmt */
+    case 149: /* num_exp */
+    case 171: /* cpp_macro_exp */
 {
 #line 137 "src/parser_proc.y"
-psi_let_stmt_free(&(yypminor->yy138));
-#line 1329 "src/parser_proc.c"
+psi_num_exp_free(&(yypminor->yy207));
+#line 1416 "src/parser_proc.c"
 }
       break;
-    case 136: /* let_calloc */
+    case 150: /* let_stmt */
 {
 #line 139 "src/parser_proc.y"
-psi_let_calloc_free(&(yypminor->yy227));
-#line 1336 "src/parser_proc.c"
+psi_let_stmt_free(&(yypminor->yy319));
+#line 1423 "src/parser_proc.c"
 }
       break;
-    case 137: /* let_func */
+    case 151: /* let_calloc */
 {
 #line 141 "src/parser_proc.y"
-psi_let_func_free(&(yypminor->yy133));
-#line 1343 "src/parser_proc.c"
+psi_let_calloc_free(&(yypminor->yy45));
+#line 1430 "src/parser_proc.c"
 }
       break;
-    case 138: /* callback_arg_list */
-    case 139: /* callback_args */
+    case 152: /* let_func */
 {
 #line 143 "src/parser_proc.y"
-psi_plist_free((yypminor->yy304));
-#line 1351 "src/parser_proc.c"
+psi_let_func_free(&(yypminor->yy67));
+#line 1437 "src/parser_proc.c"
 }
       break;
-    case 140: /* let_callback */
+    case 153: /* callback_arg_list */
+    case 154: /* callback_args */
 {
-#line 147 "src/parser_proc.y"
-psi_let_callback_free(&(yypminor->yy76));
-#line 1358 "src/parser_proc.c"
+#line 145 "src/parser_proc.y"
+psi_plist_free((yypminor->yy243));
+#line 1445 "src/parser_proc.c"
 }
       break;
-    case 141: /* let_exp */
+    case 155: /* let_callback */
 {
 #line 149 "src/parser_proc.y"
-psi_let_exp_free(&(yypminor->yy196));
-#line 1365 "src/parser_proc.c"
+psi_let_callback_free(&(yypminor->yy120));
+#line 1452 "src/parser_proc.c"
 }
       break;
-    case 143: /* assert_stmt */
+    case 156: /* let_exp */
 {
-#line 153 "src/parser_proc.y"
-psi_assert_stmt_free(&(yypminor->yy146));
-#line 1372 "src/parser_proc.c"
+#line 151 "src/parser_proc.y"
+psi_let_exp_free(&(yypminor->yy200));
+#line 1459 "src/parser_proc.c"
 }
       break;
-    case 144: /* set_stmt */
+    case 158: /* assert_stmt */
 {
 #line 155 "src/parser_proc.y"
-psi_set_stmt_free(&(yypminor->yy300));
-#line 1379 "src/parser_proc.c"
+psi_assert_stmt_free(&(yypminor->yy201));
+#line 1466 "src/parser_proc.c"
 }
       break;
-    case 145: /* set_exp */
+    case 159: /* set_stmt */
 {
 #line 157 "src/parser_proc.y"
-psi_set_exp_free(&(yypminor->yy113));
-#line 1386 "src/parser_proc.c"
+psi_set_stmt_free(&(yypminor->yy358));
+#line 1473 "src/parser_proc.c"
 }
       break;
-    case 147: /* set_func */
+    case 160: /* set_exp */
 {
-#line 161 "src/parser_proc.y"
-psi_set_func_free(&(yypminor->yy324));
-#line 1393 "src/parser_proc.c"
+#line 159 "src/parser_proc.y"
+psi_set_exp_free(&(yypminor->yy180));
+#line 1480 "src/parser_proc.c"
 }
       break;
-    case 148: /* return_stmt */
+    case 162: /* set_func */
 {
 #line 163 "src/parser_proc.y"
-psi_return_stmt_free(&(yypminor->yy258));
-#line 1400 "src/parser_proc.c"
+psi_set_func_free(&(yypminor->yy362));
+#line 1487 "src/parser_proc.c"
 }
       break;
-    case 149: /* free_stmt */
+    case 163: /* return_stmt */
 {
 #line 165 "src/parser_proc.y"
-psi_free_stmt_free(&(yypminor->yy102));
-#line 1407 "src/parser_proc.c"
+psi_return_stmt_free(&(yypminor->yy342));
+#line 1494 "src/parser_proc.c"
 }
       break;
-    case 151: /* free_exp */
+    case 164: /* free_stmt */
 {
-#line 169 "src/parser_proc.y"
-psi_free_exp_free(&(yypminor->yy114));
-#line 1414 "src/parser_proc.c"
+#line 167 "src/parser_proc.y"
+psi_free_stmt_free(&(yypminor->yy220));
+#line 1501 "src/parser_proc.c"
 }
       break;
-    case 152: /* impl_type */
+    case 166: /* free_exp */
 {
 #line 171 "src/parser_proc.y"
-psi_impl_type_free(&(yypminor->yy40));
-#line 1421 "src/parser_proc.c"
+psi_free_exp_free(&(yypminor->yy146));
+#line 1508 "src/parser_proc.c"
+}
+      break;
+    case 167: /* impl_type */
+{
+#line 173 "src/parser_proc.y"
+psi_impl_type_free(&(yypminor->yy246));
+#line 1515 "src/parser_proc.c"
+}
+      break;
+    case 168: /* cpp_exp */
+{
+#line 175 "src/parser_proc.y"
+psi_cpp_exp_free(&(yypminor->yy274));
+#line 1522 "src/parser_proc.c"
+}
+      break;
+    case 169: /* cpp_macro_decl */
+{
+#line 177 "src/parser_proc.y"
+psi_cpp_macro_decl_free(&(yypminor->yy134));
+#line 1529 "src/parser_proc.c"
 }
       break;
 /********* End destructor definitions *****************************************/
@@ -1669,165 +1777,197 @@ static const struct {
   YYCODETYPE lhs;         /* Symbol on the left-hand side of the rule */
   unsigned char nrhs;     /* Number of right-hand side symbols in the rule */
 } yyRuleInfo[] = {
-  { 158, 3 },
-  { 158, 1 },
-  { 158, 1 },
-  { 158, 1 },
-  { 158, 1 },
-  { 158, 1 },
-  { 158, 1 },
-  { 158, 1 },
-  { 159, 0 },
-  { 159, 1 },
-  { 104, 0 },
-  { 104, 7 },
-  { 160, 2 },
-  { 161, 2 },
-  { 162, 2 },
-  { 98, 4 },
-  { 99, 1 },
-  { 99, 3 },
-  { 100, 3 },
-  { 100, 1 },
-  { 101, 3 },
-  { 102, 1 },
-  { 102, 1 },
-  { 103, 4 },
-  { 105, 4 },
-  { 106, 1 },
-  { 107, 6 },
-  { 108, 3 },
-  { 109, 4 },
-  { 109, 4 },
-  { 109, 2 },
-  { 110, 1 },
-  { 111, 3 },
-  { 110, 2 },
-  { 110, 1 },
-  { 112, 6 },
-  { 112, 8 },
-  { 113, 1 },
-  { 113, 2 },
-  { 110, 7 },
-  { 110, 8 },
+  { 181, 3 },
+  { 168, 2 },
+  { 168, 2 },
+  { 168, 2 },
+  { 168, 1 },
+  { 168, 1 },
+  { 168, 2 },
+  { 168, 3 },
+  { 169, 0 },
+  { 169, 1 },
+  { 169, 2 },
+  { 172, 4 },
+  { 173, 0 },
+  { 173, 1 },
+  { 173, 3 },
+  { 169, 1 },
+  { 170, 1 },
+  { 170, 2 },
+  { 168, 2 },
+  { 168, 2 },
+  { 171, 3 },
+  { 171, 2 },
+  { 171, 3 },
+  { 171, 2 },
+  { 171, 4 },
+  { 171, 1 },
+  { 171, 1 },
+  { 171, 4 },
+  { 175, 0 },
+  { 175, 1 },
+  { 175, 3 },
+  { 181, 3 },
+  { 181, 1 },
+  { 181, 1 },
+  { 181, 1 },
+  { 181, 1 },
+  { 181, 1 },
+  { 181, 1 },
+  { 181, 1 },
+  { 182, 0 },
+  { 182, 1 },
+  { 119, 0 },
+  { 119, 7 },
+  { 183, 2 },
+  { 184, 2 },
+  { 185, 2 },
+  { 113, 4 },
   { 114, 1 },
-  { 163, 0 },
-  { 163, 3 },
-  { 115, 2 },
+  { 114, 3 },
   { 115, 3 },
-  { 116, 1 },
+  { 115, 1 },
   { 116, 3 },
-  { 117, 2 },
-  { 110, 7 },
-  { 117, 3 },
-  { 117, 4 },
-  { 118, 0 },
-  { 118, 1 },
-  { 118, 1 },
-  { 118, 3 },
-  { 119, 1 },
-  { 119, 2 },
-  { 120, 2 },
-  { 120, 3 },
-  { 121, 0 },
-  { 121, 7 },
-  { 164, 1 },
-  { 164, 2 },
-  { 165, 0 },
-  { 165, 1 },
-  { 164, 1 },
-  { 164, 2 },
-  { 166, 0 },
-  { 166, 1 },
-  { 166, 2 },
-  { 167, 0 },
-  { 167, 1 },
-  { 122, 2 },
-  { 122, 2 },
-  { 122, 1 },
-  { 122, 1 },
-  { 122, 1 },
-  { 122, 2 },
-  { 122, 2 },
-  { 122, 2 },
-  { 122, 1 },
-  { 123, 1 },
-  { 123, 2 },
+  { 117, 1 },
+  { 117, 1 },
+  { 118, 4 },
+  { 120, 4 },
+  { 121, 1 },
+  { 122, 6 },
+  { 123, 3 },
+  { 124, 4 },
   { 124, 4 },
-  { 124, 5 },
+  { 124, 2 },
+  { 125, 1 },
+  { 126, 3 },
+  { 125, 2 },
+  { 125, 1 },
+  { 127, 6 },
+  { 127, 8 },
+  { 128, 1 },
+  { 128, 2 },
   { 125, 7 },
   { 125, 8 },
-  { 125, 13 },
-  { 126, 1 },
-  { 127, 2 },
-  { 152, 1 },
-  { 128, 2 },
-  { 128, 4 },
   { 129, 1 },
-  { 129, 3 },
+  { 186, 0 },
+  { 186, 3 },
+  { 130, 2 },
+  { 130, 3 },
   { 131, 1 },
-  { 131, 2 },
-  { 132, 1 },
-  { 132, 1 },
-  { 132, 1 },
-  { 132, 1 },
-  { 132, 1 },
+  { 131, 3 },
+  { 132, 2 },
+  { 125, 7 },
+  { 132, 3 },
+  { 132, 4 },
+  { 133, 0 },
   { 133, 1 },
   { 133, 1 },
+  { 133, 3 },
   { 134, 1 },
-  { 134, 3 },
-  { 134, 3 },
   { 134, 2 },
-  { 141, 1 },
-  { 141, 2 },
-  { 141, 1 },
-  { 141, 1 },
-  { 141, 2 },
-  { 141, 1 },
-  { 141, 2 },
-  { 141, 1 },
-  { 141, 2 },
-  { 141, 3 },
+  { 135, 2 },
   { 135, 3 },
-  { 135, 6 },
-  { 140, 8 },
-  { 136, 6 },
-  { 137, 4 },
-  { 137, 6 },
-  { 142, 1 },
-  { 142, 3 },
-  { 138, 0 },
+  { 136, 0 },
+  { 136, 7 },
+  { 187, 1 },
+  { 187, 2 },
+  { 188, 0 },
+  { 188, 1 },
+  { 187, 1 },
+  { 187, 2 },
+  { 189, 0 },
+  { 189, 1 },
+  { 189, 2 },
+  { 190, 0 },
+  { 190, 1 },
+  { 137, 2 },
+  { 137, 2 },
+  { 137, 1 },
+  { 137, 1 },
+  { 137, 1 },
+  { 137, 2 },
+  { 137, 2 },
+  { 137, 2 },
+  { 137, 1 },
   { 138, 1 },
-  { 139, 1 },
-  { 139, 3 },
-  { 168, 1 },
-  { 168, 1 },
-  { 147, 4 },
-  { 147, 6 },
-  { 147, 6 },
-  { 145, 1 },
-  { 145, 1 },
-  { 146, 1 },
-  { 146, 3 },
-  { 145, 3 },
+  { 138, 2 },
+  { 139, 4 },
+  { 139, 5 },
+  { 140, 7 },
+  { 140, 8 },
+  { 140, 13 },
+  { 141, 1 },
+  { 142, 2 },
+  { 167, 1 },
+  { 143, 2 },
+  { 143, 4 },
+  { 144, 1 },
   { 144, 3 },
-  { 148, 3 },
+  { 146, 1 },
+  { 146, 2 },
+  { 147, 1 },
+  { 147, 1 },
+  { 147, 1 },
+  { 147, 1 },
+  { 147, 1 },
+  { 148, 1 },
+  { 148, 1 },
+  { 149, 1 },
   { 149, 3 },
-  { 150, 1 },
+  { 149, 3 },
+  { 149, 2 },
+  { 156, 1 },
+  { 156, 2 },
+  { 156, 1 },
+  { 156, 1 },
+  { 156, 2 },
+  { 156, 1 },
+  { 156, 2 },
+  { 156, 1 },
+  { 156, 2 },
+  { 156, 3 },
   { 150, 3 },
-  { 151, 4 },
-  { 143, 3 },
+  { 150, 6 },
+  { 155, 8 },
+  { 151, 6 },
+  { 152, 4 },
+  { 152, 6 },
+  { 157, 1 },
+  { 157, 3 },
   { 153, 0 },
   { 153, 1 },
-  { 154, 0 },
   { 154, 1 },
-  { 155, 1 },
-  { 155, 2 },
-  { 156, 1 },
-  { 157, 1 },
-  { 157, 2 },
-  { 158, 1 },
-  { 158, 1 },
+  { 154, 3 },
+  { 191, 1 },
+  { 191, 1 },
+  { 162, 4 },
+  { 162, 6 },
+  { 162, 6 },
+  { 160, 1 },
+  { 160, 1 },
+  { 161, 1 },
+  { 161, 3 },
+  { 160, 3 },
+  { 159, 3 },
+  { 163, 3 },
+  { 164, 3 },
+  { 165, 1 },
+  { 165, 3 },
+  { 166, 4 },
+  { 158, 3 },
+  { 176, 0 },
+  { 176, 1 },
+  { 177, 0 },
+  { 177, 1 },
+  { 178, 1 },
+  { 178, 2 },
+  { 179, 1 },
+  { 180, 1 },
+  { 180, 2 },
+  { 181, 1 },
+  { 181, 1 },
+  { 181, 1 },
 };
 
 static void yy_accept(yyParser*);  /* Forward Declaration */
@@ -1891,8 +2031,244 @@ static void yy_reduce(
   */
 /********** Begin reduce actions **********************************************/
         YYMINORTYPE yylhsminor;
-      case 0: /* block ::= LIB QUOTED_STRING EOS */
-#line 180 "src/parser_proc.y"
+      case 0: /* block ::= HASH cpp_exp EOL */
+{  yy_destructor(yypParser,78,&yymsp[-2].minor);
+#line 199 "src/parser_proc.y"
+{
+ P->cpp.exp = yymsp[-1].minor.yy274;
+}
+#line 2041 "src/parser_proc.c"
+  yy_destructor(yypParser,76,&yymsp[0].minor);
+}
+        break;
+      case 1: /* cpp_exp ::= ERROR|WARNING QUOTED_STRING */
+      case 2: /* cpp_exp ::= IFDEF NAME */ yytestcase(yyruleno==2);
+      case 3: /* cpp_exp ::= IFNDEF NAME */ yytestcase(yyruleno==3);
+      case 6: /* cpp_exp ::= UNDEF NAME */ yytestcase(yyruleno==6);
+#line 202 "src/parser_proc.y"
+{
+ yylhsminor.yy274 = psi_cpp_exp_init(yymsp[-1].minor.yy0->type, yymsp[0].minor.yy0);
+ yylhsminor.yy274->token = yymsp[-1].minor.yy0;
+}
+#line 2054 "src/parser_proc.c"
+  yymsp[-1].minor.yy274 = yylhsminor.yy274;
+        break;
+      case 4: /* cpp_exp ::= ENDIF */
+      case 5: /* cpp_exp ::= ELSE */ yytestcase(yyruleno==5);
+#line 214 "src/parser_proc.y"
+{
+ yylhsminor.yy274 = psi_cpp_exp_init(yymsp[0].minor.yy0->type, NULL);
+ yylhsminor.yy274->token = yymsp[0].minor.yy0;
+}
+#line 2064 "src/parser_proc.c"
+  yymsp[0].minor.yy274 = yylhsminor.yy274;
+        break;
+      case 7: /* cpp_exp ::= DEFINE NAME cpp_macro_decl */
+#line 226 "src/parser_proc.y"
+{
+ yylhsminor.yy274 = psi_cpp_exp_init(yymsp[-2].minor.yy0->type, yymsp[0].minor.yy134);
+ yylhsminor.yy274->token = yymsp[-2].minor.yy0;
+ yymsp[0].minor.yy134->token = yymsp[-1].minor.yy0;
+}
+#line 2074 "src/parser_proc.c"
+  yymsp[-2].minor.yy274 = yylhsminor.yy274;
+        break;
+      case 8: /* cpp_macro_decl ::= */
+#line 231 "src/parser_proc.y"
+{
+ yymsp[1].minor.yy134 = psi_cpp_macro_decl_init(NULL, NULL, NULL);
+}
+#line 2082 "src/parser_proc.c"
+        break;
+      case 9: /* cpp_macro_decl ::= cpp_macro_sig */
+#line 234 "src/parser_proc.y"
+{
+ yylhsminor.yy134 = psi_cpp_macro_decl_init(yymsp[0].minor.yy179, NULL, NULL);
+}
+#line 2089 "src/parser_proc.c"
+  yymsp[0].minor.yy134 = yylhsminor.yy134;
+        break;
+      case 10: /* cpp_macro_decl ::= cpp_macro_sig cpp_macro_decl_tokens */
+#line 237 "src/parser_proc.y"
+{
+ yylhsminor.yy134 = psi_cpp_macro_decl_init(yymsp[-1].minor.yy179, yymsp[0].minor.yy179, NULL);
+}
+#line 2097 "src/parser_proc.c"
+  yymsp[-1].minor.yy134 = yylhsminor.yy134;
+        break;
+      case 11: /* cpp_macro_sig ::= NO_WHITESPACE LPAREN cpp_macro_sig_args RPAREN */
+{  yy_destructor(yypParser,85,&yymsp[-3].minor);
+#line 240 "src/parser_proc.y"
+{
+ yymsp[-3].minor.yy179 = yymsp[-1].minor.yy179;
+}
+#line 2106 "src/parser_proc.c"
+  yy_destructor(yypParser,86,&yymsp[-2].minor);
+  yy_destructor(yypParser,87,&yymsp[0].minor);
+}
+        break;
+      case 12: /* cpp_macro_sig_args ::= */
+      case 28: /* cpp_macro_call_args ::= */ yytestcase(yyruleno==28);
+      case 83: /* decl_args ::= */ yytestcase(yyruleno==83);
+#line 243 "src/parser_proc.y"
+{
+ yymsp[1].minor.yy179 = NULL;
+}
+#line 2118 "src/parser_proc.c"
+        break;
+      case 13: /* cpp_macro_sig_args ::= NAME */
+      case 16: /* cpp_macro_decl_tokens ::= ANY */ yytestcase(yyruleno==16);
+#line 246 "src/parser_proc.y"
+{
+ yylhsminor.yy179 = psi_plist_add(psi_plist_init((void (*)(void *)) psi_token_free), &yymsp[0].minor.yy0);
+}
+#line 2126 "src/parser_proc.c"
+  yymsp[0].minor.yy179 = yylhsminor.yy179;
+        break;
+      case 14: /* cpp_macro_sig_args ::= cpp_macro_sig_args COMMA NAME */
+#line 249 "src/parser_proc.y"
+{
+ yylhsminor.yy179 = psi_plist_add(yymsp[-2].minor.yy179, &yymsp[0].minor.yy0);
+}
+#line 2134 "src/parser_proc.c"
+  yy_destructor(yypParser,88,&yymsp[-1].minor);
+  yymsp[-2].minor.yy179 = yylhsminor.yy179;
+        break;
+      case 15: /* cpp_macro_decl ::= cpp_macro_decl_tokens */
+#line 252 "src/parser_proc.y"
+{
+ yylhsminor.yy134 = psi_cpp_macro_decl_init(NULL, yymsp[0].minor.yy179, NULL);
+}
+#line 2143 "src/parser_proc.c"
+  yymsp[0].minor.yy134 = yylhsminor.yy134;
+        break;
+      case 17: /* cpp_macro_decl_tokens ::= cpp_macro_decl_tokens ANY */
+#line 258 "src/parser_proc.y"
+{
+ yylhsminor.yy179 = psi_plist_add(yymsp[-1].minor.yy179, &yymsp[0].minor.yy0);
+}
+#line 2151 "src/parser_proc.c"
+  yymsp[-1].minor.yy179 = yylhsminor.yy179;
+        break;
+      case 18: /* cpp_exp ::= IF cpp_macro_exp */
+      case 19: /* cpp_exp ::= ELIF cpp_macro_exp */ yytestcase(yyruleno==19);
+#line 261 "src/parser_proc.y"
+{
+ yylhsminor.yy274 = psi_cpp_exp_init(yymsp[-1].minor.yy0->type, yymsp[0].minor.yy207);
+ yylhsminor.yy274->token = yymsp[-1].minor.yy0;
+}
+#line 2161 "src/parser_proc.c"
+  yymsp[-1].minor.yy274 = yylhsminor.yy274;
+        break;
+      case 20: /* cpp_macro_exp ::= LPAREN cpp_macro_exp RPAREN */
+#line 269 "src/parser_proc.y"
+{
+ yylhsminor.yy207 = psi_num_exp_init_unary(yymsp[-2].minor.yy0->type, yymsp[-1].minor.yy207);
+ yylhsminor.yy207->token = yymsp[-2].minor.yy0;
+}
+#line 2170 "src/parser_proc.c"
+  yy_destructor(yypParser,87,&yymsp[0].minor);
+  yymsp[-2].minor.yy207 = yylhsminor.yy207;
+        break;
+      case 21: /* cpp_macro_exp ::= TILDE|NOT|PLUS|MINUS cpp_macro_exp */
+      case 139: /* num_exp ::= TILDE|NOT|PLUS|MINUS num_exp */ yytestcase(yyruleno==139);
+#line 273 "src/parser_proc.y"
+{
+ yylhsminor.yy207 = psi_num_exp_init_unary(yymsp[-1].minor.yy0->type, yymsp[0].minor.yy207);
+ yylhsminor.yy207->token = yymsp[-1].minor.yy0;
+}
+#line 2181 "src/parser_proc.c"
+  yymsp[-1].minor.yy207 = yylhsminor.yy207;
+        break;
+      case 22: /* cpp_macro_exp ::= cpp_macro_exp PIPE|CARET|AMPERSAND|LSHIFT|RSHIFT|PLUS|MINUS|ASTERISK|SLASH|MODULO|RCHEVR|LCHEVR|CMP_GE|CMP_LE|OR|AND|CMP_EQ|CMP_NE cpp_macro_exp */
+      case 138: /* num_exp ::= num_exp PIPE|CARET|AMPERSAND|LSHIFT|RSHIFT|PLUS|MINUS|ASTERISK|SLASH|MODULO|RCHEVR|LCHEVR|CMP_GE|CMP_LE|OR|AND|CMP_EQ|CMP_NE num_exp */ yytestcase(yyruleno==138);
+#line 277 "src/parser_proc.y"
+{
+ yylhsminor.yy207 = psi_num_exp_init_binary(yymsp[-1].minor.yy0->type, yymsp[-2].minor.yy207, yymsp[0].minor.yy207);
+ yylhsminor.yy207->token = yymsp[-1].minor.yy0;
+}
+#line 2191 "src/parser_proc.c"
+  yymsp[-2].minor.yy207 = yylhsminor.yy207;
+        break;
+      case 23: /* cpp_macro_exp ::= DEFINED NAME */
+{  yy_destructor(yypParser,91,&yymsp[-1].minor);
+#line 281 "src/parser_proc.y"
+{
+ {
+  uint8_t exists = zend_hash_str_exists(&P->cpp.defs, yymsp[0].minor.yy0->text, yymsp[0].minor.yy0->size);
+  yymsp[-1].minor.yy207 = psi_num_exp_init_num(psi_number_init(PSI_T_UINT8, &exists));
+  yymsp[-1].minor.yy207->token = yymsp[0].minor.yy0;
+ }
+}
+#line 2204 "src/parser_proc.c"
+}
+        break;
+      case 24: /* cpp_macro_exp ::= DEFINED LPAREN NAME RPAREN */
+{  yy_destructor(yypParser,91,&yymsp[-3].minor);
+#line 288 "src/parser_proc.y"
+{
+ {
+  uint8_t exists = zend_hash_str_exists(&P->cpp.defs, yymsp[-1].minor.yy0->text, yymsp[-1].minor.yy0->size);
+  yymsp[-3].minor.yy207 = psi_num_exp_init_num(psi_number_init(PSI_T_UINT8, &exists));
+  yymsp[-3].minor.yy207->token = yymsp[-1].minor.yy0;
+ }
+}
+#line 2217 "src/parser_proc.c"
+  yy_destructor(yypParser,86,&yymsp[-2].minor);
+  yy_destructor(yypParser,87,&yymsp[0].minor);
+}
+        break;
+      case 25: /* cpp_macro_exp ::= NUMBER|NSNAME */
+#line 295 "src/parser_proc.y"
+{
+ yylhsminor.yy207 = psi_num_exp_init_num(psi_number_init(yymsp[0].minor.yy0->type, yymsp[0].minor.yy0->text));
+ yylhsminor.yy207->token = yymsp[0].minor.yy0;
+ yylhsminor.yy207->data.n->token = psi_token_copy(yymsp[0].minor.yy0);
+}
+#line 2229 "src/parser_proc.c"
+  yymsp[0].minor.yy207 = yylhsminor.yy207;
+        break;
+      case 26: /* cpp_macro_exp ::= NAME */
+#line 300 "src/parser_proc.y"
+{
+ yylhsminor.yy207 = psi_num_exp_init_num(psi_number_init(PSI_T_DEFINE, yymsp[0].minor.yy0->text));
+ yylhsminor.yy207->token = yymsp[0].minor.yy0;
+ yylhsminor.yy207->data.n->token = psi_token_copy(yymsp[0].minor.yy0);
+}
+#line 2239 "src/parser_proc.c"
+  yymsp[0].minor.yy207 = yylhsminor.yy207;
+        break;
+      case 27: /* cpp_macro_exp ::= NAME LPAREN cpp_macro_call_args RPAREN */
+#line 305 "src/parser_proc.y"
+{
+ yylhsminor.yy207 = psi_num_exp_init_num(psi_number_init(PSI_T_FUNCTION,
+   psi_cpp_macro_call_init(yymsp[-3].minor.yy0->text, yymsp[-1].minor.yy179)));
+ yylhsminor.yy207->token = yymsp[-3].minor.yy0;
+}
+#line 2249 "src/parser_proc.c"
+  yy_destructor(yypParser,86,&yymsp[-2].minor);
+  yy_destructor(yypParser,87,&yymsp[0].minor);
+  yymsp[-3].minor.yy207 = yylhsminor.yy207;
+        break;
+      case 29: /* cpp_macro_call_args ::= cpp_macro_exp */
+#line 313 "src/parser_proc.y"
+{
+ yylhsminor.yy179 = psi_plist_add(psi_plist_init((void (*)(void *)) psi_num_exp_free), &yymsp[0].minor.yy207);
+}
+#line 2259 "src/parser_proc.c"
+  yymsp[0].minor.yy179 = yylhsminor.yy179;
+        break;
+      case 30: /* cpp_macro_call_args ::= cpp_macro_call_args COMMA cpp_macro_exp */
+#line 316 "src/parser_proc.y"
+{
+ yylhsminor.yy179 = psi_plist_add(yymsp[-2].minor.yy179, &yymsp[0].minor.yy207);
+}
+#line 2267 "src/parser_proc.c"
+  yy_destructor(yypParser,88,&yymsp[-1].minor);
+  yymsp[-2].minor.yy179 = yylhsminor.yy179;
+        break;
+      case 31: /* block ::= LIB QUOTED_STRING EOS */
+#line 319 "src/parser_proc.y"
 {
  if (P->file.ln) {
   P->error(PSI_DATA(P), yymsp[-2].minor.yy0, PSI_WARNING, "Extra 'lib %s' statement has no effect", yymsp[-1].minor.yy0->text);
@@ -1902,159 +2278,159 @@ static void yy_reduce(
  free(yymsp[-1].minor.yy0);
  free(yymsp[-2].minor.yy0);
 }
-#line 1906 "src/parser_proc.c"
-  yy_destructor(yypParser,73,&yymsp[0].minor);
+#line 2282 "src/parser_proc.c"
+  yy_destructor(yypParser,75,&yymsp[0].minor);
         break;
-      case 1: /* block ::= decl */
-#line 189 "src/parser_proc.y"
+      case 32: /* block ::= decl */
+#line 328 "src/parser_proc.y"
 {
  if (!P->decls) {
   P->decls = psi_plist_init((psi_plist_dtor) psi_decl_free);
  }
- P->decls = psi_plist_add(P->decls, &yymsp[0].minor.yy17);
+ P->decls = psi_plist_add(P->decls, &yymsp[0].minor.yy303);
 }
-#line 1917 "src/parser_proc.c"
+#line 2293 "src/parser_proc.c"
         break;
-      case 2: /* block ::= impl */
-#line 195 "src/parser_proc.y"
+      case 33: /* block ::= impl */
+#line 334 "src/parser_proc.y"
 {
  if (!P->impls) {
   P->impls = psi_plist_init((psi_plist_dtor) psi_impl_free);
  }
- P->impls = psi_plist_add(P->impls, &yymsp[0].minor.yy303);
+ P->impls = psi_plist_add(P->impls, &yymsp[0].minor.yy49);
 }
-#line 1927 "src/parser_proc.c"
+#line 2303 "src/parser_proc.c"
         break;
-      case 3: /* block ::= decl_typedef */
-#line 201 "src/parser_proc.y"
+      case 34: /* block ::= decl_typedef */
+#line 340 "src/parser_proc.y"
 {
  if (!P->types) {
   P->types = psi_plist_init((psi_plist_dtor) psi_decl_arg_free);
  }
- P->types = psi_plist_add(P->types, &yymsp[0].minor.yy64);
- switch (yymsp[0].minor.yy64->type->type) {
+ P->types = psi_plist_add(P->types, &yymsp[0].minor.yy320);
+ switch (yymsp[0].minor.yy320->type->type) {
  case PSI_T_STRUCT:
-  if (yymsp[0].minor.yy64->type->real.strct) {
+  if (yymsp[0].minor.yy320->type->real.strct) {
    if (!P->structs) {
     P->structs = psi_plist_init((psi_plist_dtor) psi_decl_struct_free);
    }
-   P->structs = psi_plist_add(P->structs, &yymsp[0].minor.yy64->type->real.strct);
+   P->structs = psi_plist_add(P->structs, &yymsp[0].minor.yy320->type->real.strct);
   }
   break;
  case PSI_T_UNION:
-  if (yymsp[0].minor.yy64->type->real.unn) {
+  if (yymsp[0].minor.yy320->type->real.unn) {
    if (!P->unions) {
     P->unions = psi_plist_init((psi_plist_dtor) psi_decl_union_free);
    }
-   P->unions = psi_plist_add(P->unions, &yymsp[0].minor.yy64->type->real.unn);
+   P->unions = psi_plist_add(P->unions, &yymsp[0].minor.yy320->type->real.unn);
   }
   break;
  case PSI_T_ENUM:
-  if (yymsp[0].minor.yy64->type->real.enm) {
+  if (yymsp[0].minor.yy320->type->real.enm) {
    if (!P->enums) {
     P->enums = psi_plist_init((psi_plist_dtor) psi_decl_enum_free);
    }
-   P->enums = psi_plist_add(P->enums, &yymsp[0].minor.yy64->type->real.enm);
+   P->enums = psi_plist_add(P->enums, &yymsp[0].minor.yy320->type->real.enm);
   }
   break;
  }
 }
-#line 1963 "src/parser_proc.c"
+#line 2339 "src/parser_proc.c"
         break;
-      case 4: /* block ::= constant */
-#line 233 "src/parser_proc.y"
+      case 35: /* block ::= constant */
+#line 372 "src/parser_proc.y"
 {
  if (!P->consts) {
   P->consts = psi_plist_init((psi_plist_dtor) psi_const_free);
  }
- P->consts = psi_plist_add(P->consts, &yymsp[0].minor.yy336);
+ P->consts = psi_plist_add(P->consts, &yymsp[0].minor.yy38);
 }
-#line 1973 "src/parser_proc.c"
+#line 2349 "src/parser_proc.c"
         break;
-      case 5: /* block ::= decl_struct */
-#line 239 "src/parser_proc.y"
+      case 36: /* block ::= decl_struct */
+#line 378 "src/parser_proc.y"
 {
  if (!P->structs) {
   P->structs = psi_plist_init((psi_plist_dtor) psi_decl_struct_free);
  }
- P->structs = psi_plist_add(P->structs, &yymsp[0].minor.yy137);
+ P->structs = psi_plist_add(P->structs, &yymsp[0].minor.yy324);
 }
-#line 1983 "src/parser_proc.c"
+#line 2359 "src/parser_proc.c"
         break;
-      case 6: /* block ::= decl_union */
-#line 245 "src/parser_proc.y"
+      case 37: /* block ::= decl_union */
+#line 384 "src/parser_proc.y"
 {
  if (!P->unions) {
   P->unions = psi_plist_init((psi_plist_dtor) psi_decl_union_free);
  }
- P->unions = psi_plist_add(P->unions, &yymsp[0].minor.yy47);
+ P->unions = psi_plist_add(P->unions, &yymsp[0].minor.yy15);
 }
-#line 1993 "src/parser_proc.c"
+#line 2369 "src/parser_proc.c"
         break;
-      case 7: /* block ::= decl_enum */
-#line 251 "src/parser_proc.y"
+      case 38: /* block ::= decl_enum */
+#line 390 "src/parser_proc.y"
 {
  if (!P->enums) {
   P->enums = psi_plist_init((psi_plist_dtor) psi_decl_enum_free);
  }
- P->enums = psi_plist_add(P->enums, &yymsp[0].minor.yy87);
+ P->enums = psi_plist_add(P->enums, &yymsp[0].minor.yy323);
 }
-#line 2003 "src/parser_proc.c"
+#line 2379 "src/parser_proc.c"
         break;
-      case 8: /* optional_name ::= */
-      case 42: /* decl_var_array_size ::= */ yytestcase(yyruleno==42);
-      case 64: /* decl_scalar_type_short ::= */ yytestcase(yyruleno==64);
-      case 68: /* decl_scalar_type_long ::= */ yytestcase(yyruleno==68);
-      case 71: /* decl_scalar_type_long_long ::= */ yytestcase(yyruleno==71);
-#line 257 "src/parser_proc.y"
+      case 39: /* optional_name ::= */
+      case 73: /* decl_var_array_size ::= */ yytestcase(yyruleno==73);
+      case 95: /* decl_scalar_type_short ::= */ yytestcase(yyruleno==95);
+      case 99: /* decl_scalar_type_long ::= */ yytestcase(yyruleno==99);
+      case 102: /* decl_scalar_type_long_long ::= */ yytestcase(yyruleno==102);
+#line 396 "src/parser_proc.y"
 {
  yymsp[1].minor.yy0 = NULL;
 }
-#line 2014 "src/parser_proc.c"
+#line 2390 "src/parser_proc.c"
         break;
-      case 9: /* optional_name ::= NAME */
-      case 62: /* decl_scalar_type ::= CHAR */ yytestcase(yyruleno==62);
-      case 65: /* decl_scalar_type_short ::= INT */ yytestcase(yyruleno==65);
-      case 66: /* decl_scalar_type ::= INT */ yytestcase(yyruleno==66);
-      case 69: /* decl_scalar_type_long ::= DOUBLE */ yytestcase(yyruleno==69);
-      case 72: /* decl_scalar_type_long_long ::= INT */ yytestcase(yyruleno==72);
-      case 131: /* callback_rval ::= ZVAL|OBJVAL|ARRVAL|PATHVAL|STRLEN|STRVAL|FLOATVAL|INTVAL|BOOLVAL|COUNT */ yytestcase(yyruleno==131);
-      case 132: /* callback_rval ::= VOID */ yytestcase(yyruleno==132);
-#line 260 "src/parser_proc.y"
+      case 40: /* optional_name ::= NAME */
+      case 93: /* decl_scalar_type ::= CHAR */ yytestcase(yyruleno==93);
+      case 96: /* decl_scalar_type_short ::= INT */ yytestcase(yyruleno==96);
+      case 97: /* decl_scalar_type ::= INT */ yytestcase(yyruleno==97);
+      case 100: /* decl_scalar_type_long ::= DOUBLE */ yytestcase(yyruleno==100);
+      case 103: /* decl_scalar_type_long_long ::= INT */ yytestcase(yyruleno==103);
+      case 162: /* callback_rval ::= ZVAL|OBJVAL|ARRVAL|PATHVAL|STRLEN|STRVAL|FLOATVAL|INTVAL|BOOLVAL|COUNT */ yytestcase(yyruleno==162);
+      case 163: /* callback_rval ::= VOID */ yytestcase(yyruleno==163);
+#line 399 "src/parser_proc.y"
 {
  yylhsminor.yy0 = yymsp[0].minor.yy0;
 }
-#line 2028 "src/parser_proc.c"
+#line 2404 "src/parser_proc.c"
   yymsp[0].minor.yy0 = yylhsminor.yy0;
         break;
-      case 10: /* align_and_size ::= */
-#line 263 "src/parser_proc.y"
+      case 41: /* align_and_size ::= */
+#line 402 "src/parser_proc.y"
 {
- yymsp[1].minor.yy207.pos = 0;
- yymsp[1].minor.yy207.len = 0;
+ yymsp[1].minor.yy239.pos = 0;
+ yymsp[1].minor.yy239.len = 0;
 }
-#line 2037 "src/parser_proc.c"
+#line 2413 "src/parser_proc.c"
         break;
-      case 11: /* align_and_size ::= COLON COLON LPAREN NUMBER COMMA NUMBER RPAREN */
-{  yy_destructor(yypParser,74,&yymsp[-6].minor);
-#line 267 "src/parser_proc.y"
+      case 42: /* align_and_size ::= COLON COLON LPAREN NUMBER COMMA NUMBER RPAREN */
+{  yy_destructor(yypParser,92,&yymsp[-6].minor);
+#line 406 "src/parser_proc.y"
 {
- yymsp[-6].minor.yy207.pos = atol(yymsp[-3].minor.yy0->text);
- yymsp[-6].minor.yy207.len = atol(yymsp[-1].minor.yy0->text);
+ yymsp[-6].minor.yy239.pos = atol(yymsp[-3].minor.yy0->text);
+ yymsp[-6].minor.yy239.len = atol(yymsp[-1].minor.yy0->text);
  free(yymsp[-3].minor.yy0);
  free(yymsp[-1].minor.yy0);
 }
-#line 2048 "src/parser_proc.c"
-  yy_destructor(yypParser,74,&yymsp[-5].minor);
-  yy_destructor(yypParser,75,&yymsp[-4].minor);
-  yy_destructor(yypParser,76,&yymsp[-2].minor);
-  yy_destructor(yypParser,77,&yymsp[0].minor);
+#line 2424 "src/parser_proc.c"
+  yy_destructor(yypParser,92,&yymsp[-5].minor);
+  yy_destructor(yypParser,86,&yymsp[-4].minor);
+  yy_destructor(yypParser,88,&yymsp[-2].minor);
+  yy_destructor(yypParser,87,&yymsp[0].minor);
 }
         break;
-      case 12: /* enum_name ::= ENUM optional_name */
-      case 13: /* struct_name ::= STRUCT optional_name */ yytestcase(yyruleno==13);
-      case 14: /* union_name ::= UNION optional_name */ yytestcase(yyruleno==14);
-#line 273 "src/parser_proc.y"
+      case 43: /* enum_name ::= ENUM optional_name */
+      case 44: /* struct_name ::= STRUCT optional_name */ yytestcase(yyruleno==44);
+      case 45: /* union_name ::= UNION optional_name */ yytestcase(yyruleno==45);
+#line 412 "src/parser_proc.y"
 {
  if (yymsp[0].minor.yy0) {
   yylhsminor.yy0 = yymsp[0].minor.yy0;
@@ -2065,526 +2441,519 @@ static void yy_reduce(
   yylhsminor.yy0 = psi_token_translit(psi_token_append(yymsp[-1].minor.yy0, 1, digest), " ", "@");
  }
 }
-#line 2069 "src/parser_proc.c"
+#line 2445 "src/parser_proc.c"
   yymsp[-1].minor.yy0 = yylhsminor.yy0;
         break;
-      case 15: /* decl_enum ::= enum_name LBRACE decl_enum_items RBRACE */
-#line 303 "src/parser_proc.y"
+      case 46: /* decl_enum ::= enum_name LBRACE decl_enum_items RBRACE */
+#line 442 "src/parser_proc.y"
 {
- yylhsminor.yy87 = psi_decl_enum_init(yymsp[-3].minor.yy0->text, yymsp[-1].minor.yy7);
- yylhsminor.yy87->token = yymsp[-3].minor.yy0;
+ yylhsminor.yy323 = psi_decl_enum_init(yymsp[-3].minor.yy0->text, yymsp[-1].minor.yy179);
+ yylhsminor.yy323->token = yymsp[-3].minor.yy0;
 }
-#line 2078 "src/parser_proc.c"
-  yy_destructor(yypParser,81,&yymsp[-2].minor);
-  yy_destructor(yypParser,82,&yymsp[0].minor);
-  yymsp[-3].minor.yy87 = yylhsminor.yy87;
+#line 2454 "src/parser_proc.c"
+  yy_destructor(yypParser,96,&yymsp[-2].minor);
+  yy_destructor(yypParser,97,&yymsp[0].minor);
+  yymsp[-3].minor.yy323 = yylhsminor.yy323;
         break;
-      case 16: /* decl_enum_items ::= decl_enum_item */
-#line 307 "src/parser_proc.y"
+      case 47: /* decl_enum_items ::= decl_enum_item */
+#line 446 "src/parser_proc.y"
 {
- yylhsminor.yy7 = psi_plist_add(psi_plist_init((psi_plist_dtor) psi_decl_enum_item_free),
-   &yymsp[0].minor.yy109);
+ yylhsminor.yy179 = psi_plist_add(psi_plist_init((psi_plist_dtor) psi_decl_enum_item_free),
+   &yymsp[0].minor.yy169);
 }
-#line 2089 "src/parser_proc.c"
-  yymsp[0].minor.yy7 = yylhsminor.yy7;
+#line 2465 "src/parser_proc.c"
+  yymsp[0].minor.yy179 = yylhsminor.yy179;
         break;
-      case 17: /* decl_enum_items ::= decl_enum_items COMMA decl_enum_item */
-#line 311 "src/parser_proc.y"
+      case 48: /* decl_enum_items ::= decl_enum_items COMMA decl_enum_item */
+#line 450 "src/parser_proc.y"
 {
- yylhsminor.yy7 = psi_plist_add(yymsp[-2].minor.yy7, &yymsp[0].minor.yy109);
+ yylhsminor.yy179 = psi_plist_add(yymsp[-2].minor.yy179, &yymsp[0].minor.yy169);
 }
-#line 2097 "src/parser_proc.c"
-  yy_destructor(yypParser,76,&yymsp[-1].minor);
-  yymsp[-2].minor.yy7 = yylhsminor.yy7;
+#line 2473 "src/parser_proc.c"
+  yy_destructor(yypParser,88,&yymsp[-1].minor);
+  yymsp[-2].minor.yy179 = yylhsminor.yy179;
         break;
-      case 18: /* decl_enum_item ::= NAME EQUALS num_exp */
-#line 314 "src/parser_proc.y"
+      case 49: /* decl_enum_item ::= NAME EQUALS num_exp */
+#line 453 "src/parser_proc.y"
 {
- yylhsminor.yy109 = psi_decl_enum_item_init(yymsp[-2].minor.yy0->text, yymsp[0].minor.yy124);
- yylhsminor.yy109->token = yymsp[-2].minor.yy0;
+ yylhsminor.yy169 = psi_decl_enum_item_init(yymsp[-2].minor.yy0->text, yymsp[0].minor.yy207);
+ yylhsminor.yy169->token = yymsp[-2].minor.yy0;
 }
-#line 2107 "src/parser_proc.c"
-  yy_destructor(yypParser,83,&yymsp[-1].minor);
-  yymsp[-2].minor.yy109 = yylhsminor.yy109;
+#line 2483 "src/parser_proc.c"
+  yy_destructor(yypParser,98,&yymsp[-1].minor);
+  yymsp[-2].minor.yy169 = yylhsminor.yy169;
         break;
-      case 19: /* decl_enum_item ::= NAME */
-#line 318 "src/parser_proc.y"
+      case 50: /* decl_enum_item ::= NAME */
+#line 457 "src/parser_proc.y"
 {
- yylhsminor.yy109 = psi_decl_enum_item_init(yymsp[0].minor.yy0->text, NULL);
- yylhsminor.yy109->token = yymsp[0].minor.yy0;
+ yylhsminor.yy169 = psi_decl_enum_item_init(yymsp[0].minor.yy0->text, NULL);
+ yylhsminor.yy169->token = yymsp[0].minor.yy0;
 }
-#line 2117 "src/parser_proc.c"
-  yymsp[0].minor.yy109 = yylhsminor.yy109;
+#line 2493 "src/parser_proc.c"
+  yymsp[0].minor.yy169 = yylhsminor.yy169;
         break;
-      case 20: /* decl_struct_args_block ::= LBRACE struct_args RBRACE */
-{  yy_destructor(yypParser,81,&yymsp[-2].minor);
-#line 322 "src/parser_proc.y"
+      case 51: /* decl_struct_args_block ::= LBRACE struct_args RBRACE */
+{  yy_destructor(yypParser,96,&yymsp[-2].minor);
+#line 461 "src/parser_proc.y"
 {
- yymsp[-2].minor.yy7 = yymsp[-1].minor.yy7;
+ yymsp[-2].minor.yy179 = yymsp[-1].minor.yy179;
 }
-#line 2126 "src/parser_proc.c"
-  yy_destructor(yypParser,82,&yymsp[0].minor);
+#line 2502 "src/parser_proc.c"
+  yy_destructor(yypParser,97,&yymsp[0].minor);
 }
         break;
-      case 21: /* decl_struct_args ::= decl_struct_args_block */
-#line 325 "src/parser_proc.y"
+      case 52: /* decl_struct_args ::= decl_struct_args_block */
+#line 464 "src/parser_proc.y"
 {
- yylhsminor.yy7 = yymsp[0].minor.yy7;
+ yylhsminor.yy179 = yymsp[0].minor.yy179;
 }
-#line 2135 "src/parser_proc.c"
-  yymsp[0].minor.yy7 = yylhsminor.yy7;
+#line 2511 "src/parser_proc.c"
+  yymsp[0].minor.yy179 = yylhsminor.yy179;
         break;
-      case 22: /* decl_struct_args ::= EOS */
-{  yy_destructor(yypParser,73,&yymsp[0].minor);
-#line 328 "src/parser_proc.y"
+      case 53: /* decl_struct_args ::= EOS */
+{  yy_destructor(yypParser,75,&yymsp[0].minor);
+#line 467 "src/parser_proc.y"
 {
- yymsp[0].minor.yy7 = psi_plist_init((psi_plist_dtor) psi_decl_arg_free);
+ yymsp[0].minor.yy179 = psi_plist_init((psi_plist_dtor) psi_decl_arg_free);
 }
-#line 2144 "src/parser_proc.c"
+#line 2520 "src/parser_proc.c"
 }
         break;
-      case 23: /* decl_struct ::= STRUCT NAME align_and_size decl_struct_args */
-{  yy_destructor(yypParser,79,&yymsp[-3].minor);
-#line 331 "src/parser_proc.y"
+      case 54: /* decl_struct ::= STRUCT NAME align_and_size decl_struct_args */
+{  yy_destructor(yypParser,94,&yymsp[-3].minor);
+#line 470 "src/parser_proc.y"
 {
- yymsp[-3].minor.yy137 = psi_decl_struct_init(yymsp[-2].minor.yy0->text, yymsp[0].minor.yy7);
- yymsp[-3].minor.yy137->align = yymsp[-1].minor.yy207.pos;
- yymsp[-3].minor.yy137->size = yymsp[-1].minor.yy207.len;
- yymsp[-3].minor.yy137->token = yymsp[-2].minor.yy0;
+ yymsp[-3].minor.yy324 = psi_decl_struct_init(yymsp[-2].minor.yy0->text, yymsp[0].minor.yy179);
+ yymsp[-3].minor.yy324->align = yymsp[-1].minor.yy239.pos;
+ yymsp[-3].minor.yy324->size = yymsp[-1].minor.yy239.len;
+ yymsp[-3].minor.yy324->token = yymsp[-2].minor.yy0;
 }
-#line 2156 "src/parser_proc.c"
+#line 2532 "src/parser_proc.c"
 }
         break;
-      case 24: /* decl_union ::= UNION NAME align_and_size decl_struct_args */
-{  yy_destructor(yypParser,80,&yymsp[-3].minor);
-#line 337 "src/parser_proc.y"
+      case 55: /* decl_union ::= UNION NAME align_and_size decl_struct_args */
+{  yy_destructor(yypParser,95,&yymsp[-3].minor);
+#line 476 "src/parser_proc.y"
 {
- yymsp[-3].minor.yy47 = psi_decl_union_init(yymsp[-2].minor.yy0->text, yymsp[0].minor.yy7);
- yymsp[-3].minor.yy47->align = yymsp[-1].minor.yy207.pos;
- yymsp[-3].minor.yy47->size = yymsp[-1].minor.yy207.len;
- yymsp[-3].minor.yy47->token = yymsp[-2].minor.yy0;
+ yymsp[-3].minor.yy15 = psi_decl_union_init(yymsp[-2].minor.yy0->text, yymsp[0].minor.yy179);
+ yymsp[-3].minor.yy15->align = yymsp[-1].minor.yy239.pos;
+ yymsp[-3].minor.yy15->size = yymsp[-1].minor.yy239.len;
+ yymsp[-3].minor.yy15->token = yymsp[-2].minor.yy0;
 }
-#line 2168 "src/parser_proc.c"
+#line 2544 "src/parser_proc.c"
 }
         break;
-      case 25: /* const_type ::= BOOL|INT|FLOAT|STRING */
-#line 343 "src/parser_proc.y"
+      case 56: /* const_type ::= BOOL|INT|FLOAT|STRING */
+#line 482 "src/parser_proc.y"
 {
- yylhsminor.yy181 = psi_const_type_init(yymsp[0].minor.yy0->type, yymsp[0].minor.yy0->text);
+ yylhsminor.yy351 = psi_const_type_init(yymsp[0].minor.yy0->type, yymsp[0].minor.yy0->text);
  free(yymsp[0].minor.yy0);
 }
-#line 2177 "src/parser_proc.c"
-  yymsp[0].minor.yy181 = yylhsminor.yy181;
+#line 2553 "src/parser_proc.c"
+  yymsp[0].minor.yy351 = yylhsminor.yy351;
         break;
-      case 26: /* constant ::= CONST const_type NSNAME EQUALS impl_def_val EOS */
-{  yy_destructor(yypParser,84,&yymsp[-5].minor);
-#line 347 "src/parser_proc.y"
+      case 57: /* constant ::= CONST const_type NSNAME EQUALS impl_def_val EOS */
+{  yy_destructor(yypParser,99,&yymsp[-5].minor);
+#line 486 "src/parser_proc.y"
 {
- yymsp[-5].minor.yy336 = psi_const_init(yymsp[-4].minor.yy181, yymsp[-3].minor.yy0->text, yymsp[-1].minor.yy319);
- yymsp[-5].minor.yy336->token = yymsp[-3].minor.yy0;
+ yymsp[-5].minor.yy38 = psi_const_init(yymsp[-4].minor.yy351, yymsp[-3].minor.yy0->text, yymsp[-1].minor.yy145);
+ yymsp[-5].minor.yy38->token = yymsp[-3].minor.yy0;
 }
-#line 2187 "src/parser_proc.c"
-  yy_destructor(yypParser,83,&yymsp[-2].minor);
-  yy_destructor(yypParser,73,&yymsp[0].minor);
+#line 2563 "src/parser_proc.c"
+  yy_destructor(yypParser,98,&yymsp[-2].minor);
+  yy_destructor(yypParser,75,&yymsp[0].minor);
 }
         break;
-      case 27: /* decl_typedef ::= TYPEDEF decl_typedef_body EOS */
-#line 351 "src/parser_proc.y"
+      case 58: /* decl_typedef ::= TYPEDEF decl_typedef_body EOS */
+#line 490 "src/parser_proc.y"
 {
- yylhsminor.yy64 = yymsp[-1].minor.yy64;
- yylhsminor.yy64->token = yymsp[-2].minor.yy0;
+ yylhsminor.yy320 = yymsp[-1].minor.yy320;
+ yylhsminor.yy320->token = yymsp[-2].minor.yy0;
 }
-#line 2198 "src/parser_proc.c"
-  yy_destructor(yypParser,73,&yymsp[0].minor);
-  yymsp[-2].minor.yy64 = yylhsminor.yy64;
+#line 2574 "src/parser_proc.c"
+  yy_destructor(yypParser,75,&yymsp[0].minor);
+  yymsp[-2].minor.yy320 = yylhsminor.yy320;
         break;
-      case 28: /* decl_typedef_body_ex ::= struct_name align_and_size decl_struct_args_block decl_var */
-#line 355 "src/parser_proc.y"
+      case 59: /* decl_typedef_body_ex ::= struct_name align_and_size decl_struct_args_block decl_var */
+#line 494 "src/parser_proc.y"
 {
- yylhsminor.yy64 = psi_decl_arg_init(psi_decl_type_init(PSI_T_STRUCT, yymsp[-3].minor.yy0->text), yymsp[0].minor.yy131);
- yylhsminor.yy64->type->token = psi_token_copy(yymsp[-3].minor.yy0);
- yylhsminor.yy64->type->real.strct = psi_decl_struct_init(yymsp[-3].minor.yy0->text, yymsp[-1].minor.yy7);
- yylhsminor.yy64->type->real.strct->token = yymsp[-3].minor.yy0;
- yylhsminor.yy64->type->real.strct->align = yymsp[-2].minor.yy207.pos;
- yylhsminor.yy64->type->real.strct->size = yymsp[-2].minor.yy207.len;
+ yylhsminor.yy320 = psi_decl_arg_init(psi_decl_type_init(PSI_T_STRUCT, yymsp[-3].minor.yy0->text), yymsp[0].minor.yy271);
+ yylhsminor.yy320->type->token = psi_token_copy(yymsp[-3].minor.yy0);
+ yylhsminor.yy320->type->real.strct = psi_decl_struct_init(yymsp[-3].minor.yy0->text, yymsp[-1].minor.yy179);
+ yylhsminor.yy320->type->real.strct->token = yymsp[-3].minor.yy0;
+ yylhsminor.yy320->type->real.strct->align = yymsp[-2].minor.yy239.pos;
+ yylhsminor.yy320->type->real.strct->size = yymsp[-2].minor.yy239.len;
 }
-#line 2212 "src/parser_proc.c"
-  yymsp[-3].minor.yy64 = yylhsminor.yy64;
+#line 2588 "src/parser_proc.c"
+  yymsp[-3].minor.yy320 = yylhsminor.yy320;
         break;
-      case 29: /* decl_typedef_body_ex ::= union_name align_and_size decl_struct_args_block decl_var */
-#line 363 "src/parser_proc.y"
+      case 60: /* decl_typedef_body_ex ::= union_name align_and_size decl_struct_args_block decl_var */
+#line 502 "src/parser_proc.y"
 {
- yylhsminor.yy64 = psi_decl_arg_init(psi_decl_type_init(PSI_T_UNION, yymsp[-3].minor.yy0->text), yymsp[0].minor.yy131);
- yylhsminor.yy64->type->token = psi_token_copy(yymsp[-3].minor.yy0);
- yylhsminor.yy64->type->real.unn = psi_decl_union_init(yymsp[-3].minor.yy0->text, yymsp[-1].minor.yy7);
- yylhsminor.yy64->type->real.unn->token = yymsp[-3].minor.yy0;
- yylhsminor.yy64->type->real.unn->align = yymsp[-2].minor.yy207.pos;
- yylhsminor.yy64->type->real.unn->size = yymsp[-2].minor.yy207.len;
+ yylhsminor.yy320 = psi_decl_arg_init(psi_decl_type_init(PSI_T_UNION, yymsp[-3].minor.yy0->text), yymsp[0].minor.yy271);
+ yylhsminor.yy320->type->token = psi_token_copy(yymsp[-3].minor.yy0);
+ yylhsminor.yy320->type->real.unn = psi_decl_union_init(yymsp[-3].minor.yy0->text, yymsp[-1].minor.yy179);
+ yylhsminor.yy320->type->real.unn->token = yymsp[-3].minor.yy0;
+ yylhsminor.yy320->type->real.unn->align = yymsp[-2].minor.yy239.pos;
+ yylhsminor.yy320->type->real.unn->size = yymsp[-2].minor.yy239.len;
 }
-#line 2225 "src/parser_proc.c"
-  yymsp[-3].minor.yy64 = yylhsminor.yy64;
+#line 2601 "src/parser_proc.c"
+  yymsp[-3].minor.yy320 = yylhsminor.yy320;
         break;
-      case 30: /* decl_typedef_body_ex ::= decl_enum NAME */
-#line 371 "src/parser_proc.y"
+      case 61: /* decl_typedef_body_ex ::= decl_enum NAME */
+#line 510 "src/parser_proc.y"
 {
- yylhsminor.yy64 = psi_decl_arg_init(psi_decl_type_init(PSI_T_ENUM, yymsp[-1].minor.yy87->name), psi_decl_var_init(yymsp[0].minor.yy0->text, 0, 0));
- yylhsminor.yy64->var->token = yymsp[0].minor.yy0;
- yylhsminor.yy64->type->token = psi_token_copy(yymsp[-1].minor.yy87->token);
- yylhsminor.yy64->type->real.enm = yymsp[-1].minor.yy87;
+ yylhsminor.yy320 = psi_decl_arg_init(psi_decl_type_init(PSI_T_ENUM, yymsp[-1].minor.yy323->name), psi_decl_var_init(yymsp[0].minor.yy0->text, 0, 0));
+ yylhsminor.yy320->var->token = yymsp[0].minor.yy0;
+ yylhsminor.yy320->type->token = psi_token_copy(yymsp[-1].minor.yy323->token);
+ yylhsminor.yy320->type->real.enm = yymsp[-1].minor.yy323;
 }
-#line 2236 "src/parser_proc.c"
-  yymsp[-1].minor.yy64 = yylhsminor.yy64;
+#line 2612 "src/parser_proc.c"
+  yymsp[-1].minor.yy320 = yylhsminor.yy320;
         break;
-      case 31: /* decl_typedef_body ::= decl_typedef_body_ex */
-      case 34: /* decl_typedef_body ::= decl_arg */ yytestcase(yyruleno==34);
-      case 37: /* decl_func ::= decl_arg */ yytestcase(yyruleno==37);
-#line 377 "src/parser_proc.y"
+      case 62: /* decl_typedef_body ::= decl_typedef_body_ex */
+      case 65: /* decl_typedef_body ::= decl_arg */ yytestcase(yyruleno==65);
+      case 68: /* decl_func ::= decl_arg */ yytestcase(yyruleno==68);
+#line 516 "src/parser_proc.y"
 {
- yylhsminor.yy64 = yymsp[0].minor.yy64;
+ yylhsminor.yy320 = yymsp[0].minor.yy320;
 }
-#line 2246 "src/parser_proc.c"
-  yymsp[0].minor.yy64 = yylhsminor.yy64;
+#line 2622 "src/parser_proc.c"
+  yymsp[0].minor.yy320 = yylhsminor.yy320;
         break;
-      case 32: /* decl_typedef_body_fn_args ::= LPAREN decl_args RPAREN */
-{  yy_destructor(yypParser,75,&yymsp[-2].minor);
-#line 380 "src/parser_proc.y"
+      case 63: /* decl_typedef_body_fn_args ::= LPAREN decl_args RPAREN */
+{  yy_destructor(yypParser,86,&yymsp[-2].minor);
+#line 519 "src/parser_proc.y"
 {
- yymsp[-2].minor.yy7 = yymsp[-1].minor.yy7;
+ yymsp[-2].minor.yy179 = yymsp[-1].minor.yy179;
 }
-#line 2255 "src/parser_proc.c"
-  yy_destructor(yypParser,77,&yymsp[0].minor);
+#line 2631 "src/parser_proc.c"
+  yy_destructor(yypParser,87,&yymsp[0].minor);
 }
         break;
-      case 33: /* decl_typedef_body ::= decl_func decl_typedef_body_fn_args */
-#line 383 "src/parser_proc.y"
+      case 64: /* decl_typedef_body ::= decl_func decl_typedef_body_fn_args */
+#line 522 "src/parser_proc.y"
 {
- yylhsminor.yy64 = psi_decl_arg_init(psi_decl_type_init(PSI_T_FUNCTION, yymsp[-1].minor.yy64->var->name), psi_decl_var_copy(yymsp[-1].minor.yy64->var));
- yylhsminor.yy64->type->token = psi_token_copy(yymsp[-1].minor.yy64->token);
- yylhsminor.yy64->type->real.func = psi_decl_init(psi_decl_abi_init("default"), yymsp[-1].minor.yy64, yymsp[0].minor.yy7);
+ yylhsminor.yy320 = psi_decl_arg_init(psi_decl_type_init(PSI_T_FUNCTION, yymsp[-1].minor.yy320->var->name), psi_decl_var_copy(yymsp[-1].minor.yy320->var));
+ yylhsminor.yy320->type->token = psi_token_copy(yymsp[-1].minor.yy320->token);
+ yylhsminor.yy320->type->real.func = psi_decl_init(psi_decl_abi_init("default"), yymsp[-1].minor.yy320, yymsp[0].minor.yy179);
 }
-#line 2266 "src/parser_proc.c"
-  yymsp[-1].minor.yy64 = yylhsminor.yy64;
+#line 2642 "src/parser_proc.c"
+  yymsp[-1].minor.yy320 = yylhsminor.yy320;
         break;
-      case 35: /* decl ::= decl_abi decl_func LPAREN decl_args RPAREN EOS */
-#line 391 "src/parser_proc.y"
+      case 66: /* decl ::= decl_abi decl_func LPAREN decl_args RPAREN EOS */
+#line 530 "src/parser_proc.y"
 {
- yylhsminor.yy17 = psi_decl_init(yymsp[-5].minor.yy180, yymsp[-4].minor.yy64, yymsp[-2].minor.yy7);
+ yylhsminor.yy303 = psi_decl_init(yymsp[-5].minor.yy26, yymsp[-4].minor.yy320, yymsp[-2].minor.yy179);
 }
-#line 2274 "src/parser_proc.c"
-  yy_destructor(yypParser,75,&yymsp[-3].minor);
-  yy_destructor(yypParser,77,&yymsp[-1].minor);
-  yy_destructor(yypParser,73,&yymsp[0].minor);
-  yymsp[-5].minor.yy17 = yylhsminor.yy17;
+#line 2650 "src/parser_proc.c"
+  yy_destructor(yypParser,86,&yymsp[-3].minor);
+  yy_destructor(yypParser,87,&yymsp[-1].minor);
+  yy_destructor(yypParser,75,&yymsp[0].minor);
+  yymsp[-5].minor.yy303 = yylhsminor.yy303;
         break;
-      case 36: /* decl ::= decl_abi decl_func LPAREN decl_args COMMA ELLIPSIS RPAREN EOS */
-#line 394 "src/parser_proc.y"
+      case 67: /* decl ::= decl_abi decl_func LPAREN decl_args COMMA ELLIPSIS RPAREN EOS */
+#line 533 "src/parser_proc.y"
 {
- yylhsminor.yy17 = psi_decl_init(yymsp[-7].minor.yy180, yymsp[-6].minor.yy64, yymsp[-4].minor.yy7);
- yylhsminor.yy17->varargs = 1;
+ yylhsminor.yy303 = psi_decl_init(yymsp[-7].minor.yy26, yymsp[-6].minor.yy320, yymsp[-4].minor.yy179);
+ yylhsminor.yy303->varargs = 1;
 }
-#line 2286 "src/parser_proc.c"
-  yy_destructor(yypParser,75,&yymsp[-5].minor);
-  yy_destructor(yypParser,76,&yymsp[-3].minor);
-  yy_destructor(yypParser,86,&yymsp[-2].minor);
-  yy_destructor(yypParser,77,&yymsp[-1].minor);
-  yy_destructor(yypParser,73,&yymsp[0].minor);
-  yymsp[-7].minor.yy17 = yylhsminor.yy17;
+#line 2662 "src/parser_proc.c"
+  yy_destructor(yypParser,86,&yymsp[-5].minor);
+  yy_destructor(yypParser,88,&yymsp[-3].minor);
+  yy_destructor(yypParser,101,&yymsp[-2].minor);
+  yy_destructor(yypParser,87,&yymsp[-1].minor);
+  yy_destructor(yypParser,75,&yymsp[0].minor);
+  yymsp[-7].minor.yy303 = yylhsminor.yy303;
         break;
-      case 38: /* decl_func ::= VOID NAME */
-#line 401 "src/parser_proc.y"
+      case 69: /* decl_func ::= VOID NAME */
+#line 540 "src/parser_proc.y"
 {
- yylhsminor.yy64 = psi_decl_arg_init(
+ yylhsminor.yy320 = psi_decl_arg_init(
   psi_decl_type_init(yymsp[-1].minor.yy0->type, yymsp[-1].minor.yy0->text),
   psi_decl_var_init(yymsp[0].minor.yy0->text, 0, 0)
  );
- yylhsminor.yy64->type->token = yymsp[-1].minor.yy0;
- yylhsminor.yy64->var->token = yymsp[0].minor.yy0;
- yylhsminor.yy64->token = yymsp[0].minor.yy0;
+ yylhsminor.yy320->type->token = yymsp[-1].minor.yy0;
+ yylhsminor.yy320->var->token = yymsp[0].minor.yy0;
+ yylhsminor.yy320->token = yymsp[0].minor.yy0;
 }
-#line 2305 "src/parser_proc.c"
-  yymsp[-1].minor.yy64 = yylhsminor.yy64;
+#line 2681 "src/parser_proc.c"
+  yymsp[-1].minor.yy320 = yylhsminor.yy320;
         break;
-      case 39: /* decl_typedef_body ::= VOID indirection LPAREN indirection NAME RPAREN decl_typedef_body_fn_args */
-#line 410 "src/parser_proc.y"
+      case 70: /* decl_typedef_body ::= VOID indirection LPAREN indirection NAME RPAREN decl_typedef_body_fn_args */
+#line 549 "src/parser_proc.y"
 {
  struct psi_decl_arg *func_ = psi_decl_arg_init(
   psi_decl_type_init(yymsp[-6].minor.yy0->type, yymsp[-6].minor.yy0->text),
-  psi_decl_var_init(yymsp[-2].minor.yy0->text, yymsp[-5].minor.yy296, 0)
+  psi_decl_var_init(yymsp[-2].minor.yy0->text, yymsp[-5].minor.yy382, 0)
  );
  func_->type->token = yymsp[-6].minor.yy0;
  func_->var->token = yymsp[-2].minor.yy0;
  func_->token = yymsp[-2].minor.yy0;
- yylhsminor.yy64 = psi_decl_arg_init(
+ yylhsminor.yy320 = psi_decl_arg_init(
   psi_decl_type_init(PSI_T_FUNCTION, func_->var->name),
   psi_decl_var_copy(func_->var)
  );
- yylhsminor.yy64->var->pointer_level = yymsp[-3].minor.yy296;
- yylhsminor.yy64->type->token = psi_token_copy(func_->token);
- yylhsminor.yy64->type->real.func = psi_decl_init(psi_decl_abi_init("default"), func_, yymsp[0].minor.yy7);
+ yylhsminor.yy320->var->pointer_level = yymsp[-3].minor.yy382;
+ yylhsminor.yy320->type->token = psi_token_copy(func_->token);
+ yylhsminor.yy320->type->real.func = psi_decl_init(psi_decl_abi_init("default"), func_, yymsp[0].minor.yy179);
 }
-#line 2326 "src/parser_proc.c"
-  yy_destructor(yypParser,75,&yymsp[-4].minor);
-  yy_destructor(yypParser,77,&yymsp[-1].minor);
-  yymsp[-6].minor.yy64 = yylhsminor.yy64;
+#line 2702 "src/parser_proc.c"
+  yy_destructor(yypParser,86,&yymsp[-4].minor);
+  yy_destructor(yypParser,87,&yymsp[-1].minor);
+  yymsp[-6].minor.yy320 = yylhsminor.yy320;
         break;
-      case 40: /* decl_typedef_body ::= CONST VOID pointers LPAREN indirection NAME RPAREN decl_typedef_body_fn_args */
-{  yy_destructor(yypParser,84,&yymsp[-7].minor);
-#line 426 "src/parser_proc.y"
+      case 71: /* decl_typedef_body ::= CONST VOID pointers LPAREN indirection NAME RPAREN decl_typedef_body_fn_args */
+{  yy_destructor(yypParser,99,&yymsp[-7].minor);
+#line 565 "src/parser_proc.y"
 {
  struct psi_decl_arg *func_ = psi_decl_arg_init(
   psi_decl_type_init(yymsp[-6].minor.yy0->type, yymsp[-6].minor.yy0->text),
-  psi_decl_var_init(yymsp[-2].minor.yy0->text, yymsp[-5].minor.yy296, 0)
+  psi_decl_var_init(yymsp[-2].minor.yy0->text, yymsp[-5].minor.yy382, 0)
  );
  func_->type->token = yymsp[-6].minor.yy0;
  func_->var->token = yymsp[-2].minor.yy0;
  func_->token = yymsp[-2].minor.yy0;
- yymsp[-7].minor.yy64 = psi_decl_arg_init(
+ yymsp[-7].minor.yy320 = psi_decl_arg_init(
   psi_decl_type_init(PSI_T_FUNCTION, func_->var->name),
   psi_decl_var_copy(func_->var)
  );
- yymsp[-7].minor.yy64->var->pointer_level = yymsp[-3].minor.yy296;
- yymsp[-7].minor.yy64->type->token = psi_token_copy(func_->token);
- yymsp[-7].minor.yy64->type->real.func = psi_decl_init(psi_decl_abi_init("default"), func_, yymsp[0].minor.yy7);
+ yymsp[-7].minor.yy320->var->pointer_level = yymsp[-3].minor.yy382;
+ yymsp[-7].minor.yy320->type->token = psi_token_copy(func_->token);
+ yymsp[-7].minor.yy320->type->real.func = psi_decl_init(psi_decl_abi_init("default"), func_, yymsp[0].minor.yy179);
 }
-#line 2350 "src/parser_proc.c"
-  yy_destructor(yypParser,75,&yymsp[-4].minor);
-  yy_destructor(yypParser,77,&yymsp[-1].minor);
+#line 2726 "src/parser_proc.c"
+  yy_destructor(yypParser,86,&yymsp[-4].minor);
+  yy_destructor(yypParser,87,&yymsp[-1].minor);
 }
         break;
-      case 41: /* decl_abi ::= NAME */
-#line 442 "src/parser_proc.y"
+      case 72: /* decl_abi ::= NAME */
+#line 581 "src/parser_proc.y"
 {
- yylhsminor.yy180 = psi_decl_abi_init(yymsp[0].minor.yy0->text);
- yylhsminor.yy180->token = yymsp[0].minor.yy0;
+ yylhsminor.yy26 = psi_decl_abi_init(yymsp[0].minor.yy0->text);
+ yylhsminor.yy26->token = yymsp[0].minor.yy0;
 }
-#line 2361 "src/parser_proc.c"
-  yymsp[0].minor.yy180 = yylhsminor.yy180;
+#line 2737 "src/parser_proc.c"
+  yymsp[0].minor.yy26 = yylhsminor.yy26;
         break;
-      case 43: /* decl_var_array_size ::= LBRACKET NUMBER RBRACKET */
-{  yy_destructor(yypParser,87,&yymsp[-2].minor);
-#line 449 "src/parser_proc.y"
+      case 74: /* decl_var_array_size ::= LBRACKET NUMBER RBRACKET */
+{  yy_destructor(yypParser,102,&yymsp[-2].minor);
+#line 588 "src/parser_proc.y"
 {
  yymsp[-2].minor.yy0 = yymsp[-1].minor.yy0;
 }
-#line 2370 "src/parser_proc.c"
-  yy_destructor(yypParser,88,&yymsp[0].minor);
+#line 2746 "src/parser_proc.c"
+  yy_destructor(yypParser,103,&yymsp[0].minor);
 }
         break;
-      case 44: /* decl_var ::= NAME decl_var_array_size */
-#line 452 "src/parser_proc.y"
+      case 75: /* decl_var ::= NAME decl_var_array_size */
+#line 591 "src/parser_proc.y"
 {
- yylhsminor.yy131 = psi_decl_var_init(yymsp[-1].minor.yy0->text, 0, yymsp[0].minor.yy0?atol(yymsp[0].minor.yy0->text):0);
- yylhsminor.yy131->token = yymsp[-1].minor.yy0;
+ yylhsminor.yy271 = psi_decl_var_init(yymsp[-1].minor.yy0->text, 0, yymsp[0].minor.yy0?atol(yymsp[0].minor.yy0->text):0);
+ yylhsminor.yy271->token = yymsp[-1].minor.yy0;
  if (yymsp[0].minor.yy0) {
   free(yymsp[0].minor.yy0);
  }
 }
-#line 2383 "src/parser_proc.c"
-  yymsp[-1].minor.yy131 = yylhsminor.yy131;
+#line 2759 "src/parser_proc.c"
+  yymsp[-1].minor.yy271 = yylhsminor.yy271;
         break;
-      case 45: /* decl_var ::= pointers NAME decl_var_array_size */
-#line 459 "src/parser_proc.y"
+      case 76: /* decl_var ::= pointers NAME decl_var_array_size */
+#line 598 "src/parser_proc.y"
 {
- yylhsminor.yy131 = psi_decl_var_init(yymsp[-1].minor.yy0->text, yymsp[-2].minor.yy296+!!yymsp[0].minor.yy0, yymsp[0].minor.yy0?atol(yymsp[0].minor.yy0->text):0);
- yylhsminor.yy131->token = yymsp[-1].minor.yy0;
+ yylhsminor.yy271 = psi_decl_var_init(yymsp[-1].minor.yy0->text, yymsp[-2].minor.yy382+!!yymsp[0].minor.yy0, yymsp[0].minor.yy0?atol(yymsp[0].minor.yy0->text):0);
+ yylhsminor.yy271->token = yymsp[-1].minor.yy0;
  if (yymsp[0].minor.yy0) {
   free(yymsp[0].minor.yy0);
  }
 }
-#line 2395 "src/parser_proc.c"
-  yymsp[-2].minor.yy131 = yylhsminor.yy131;
+#line 2771 "src/parser_proc.c"
+  yymsp[-2].minor.yy271 = yylhsminor.yy271;
         break;
-      case 46: /* decl_vars ::= decl_var */
-#line 466 "src/parser_proc.y"
+      case 77: /* decl_vars ::= decl_var */
+#line 605 "src/parser_proc.y"
 {
- yylhsminor.yy7 = psi_plist_add(psi_plist_init((psi_plist_dtor) psi_decl_var_free),
-   &yymsp[0].minor.yy131);
+ yylhsminor.yy179 = psi_plist_add(psi_plist_init((psi_plist_dtor) psi_decl_var_free),
+   &yymsp[0].minor.yy271);
 }
-#line 2404 "src/parser_proc.c"
-  yymsp[0].minor.yy7 = yylhsminor.yy7;
+#line 2780 "src/parser_proc.c"
+  yymsp[0].minor.yy179 = yylhsminor.yy179;
         break;
-      case 47: /* decl_vars ::= decl_vars COMMA decl_var */
-#line 470 "src/parser_proc.y"
+      case 78: /* decl_vars ::= decl_vars COMMA decl_var */
+#line 609 "src/parser_proc.y"
 {
- yylhsminor.yy7 = psi_plist_add(yymsp[-2].minor.yy7, &yymsp[0].minor.yy131);
+ yylhsminor.yy179 = psi_plist_add(yymsp[-2].minor.yy179, &yymsp[0].minor.yy271);
 }
-#line 2412 "src/parser_proc.c"
-  yy_destructor(yypParser,76,&yymsp[-1].minor);
-  yymsp[-2].minor.yy7 = yylhsminor.yy7;
+#line 2788 "src/parser_proc.c"
+  yy_destructor(yypParser,88,&yymsp[-1].minor);
+  yymsp[-2].minor.yy179 = yylhsminor.yy179;
         break;
-      case 48: /* decl_arg ::= const_decl_type decl_var */
-#line 473 "src/parser_proc.y"
+      case 79: /* decl_arg ::= const_decl_type decl_var */
+#line 612 "src/parser_proc.y"
 {
- yylhsminor.yy64 = psi_decl_arg_init(yymsp[-1].minor.yy182, yymsp[0].minor.yy131);
+ yylhsminor.yy320 = psi_decl_arg_init(yymsp[-1].minor.yy172, yymsp[0].minor.yy271);
 }
-#line 2421 "src/parser_proc.c"
-  yymsp[-1].minor.yy64 = yylhsminor.yy64;
+#line 2797 "src/parser_proc.c"
+  yymsp[-1].minor.yy320 = yylhsminor.yy320;
         break;
-      case 49: /* decl_typedef_body ::= const_decl_type indirection LPAREN indirection NAME RPAREN decl_typedef_body_fn_args */
-#line 476 "src/parser_proc.y"
+      case 80: /* decl_typedef_body ::= const_decl_type indirection LPAREN indirection NAME RPAREN decl_typedef_body_fn_args */
+#line 615 "src/parser_proc.y"
 {
  struct psi_decl_arg *func_ = psi_decl_arg_init(
-  yymsp[-6].minor.yy182,
-  psi_decl_var_init(yymsp[-2].minor.yy0->text, yymsp[-5].minor.yy296, 0)
+  yymsp[-6].minor.yy172,
+  psi_decl_var_init(yymsp[-2].minor.yy0->text, yymsp[-5].minor.yy382, 0)
  );
  func_->var->token = yymsp[-2].minor.yy0;
  func_->token = yymsp[-2].minor.yy0;
- yylhsminor.yy64 = psi_decl_arg_init(
+ yylhsminor.yy320 = psi_decl_arg_init(
   psi_decl_type_init(PSI_T_FUNCTION, func_->var->name),
   psi_decl_var_copy(func_->var)
  );
- yylhsminor.yy64->var->pointer_level = yymsp[-3].minor.yy296;
- yylhsminor.yy64->type->token = psi_token_copy(func_->token);
- yylhsminor.yy64->type->real.func = psi_decl_init(psi_decl_abi_init("default"), func_, yymsp[0].minor.yy7);
+ yylhsminor.yy320->var->pointer_level = yymsp[-3].minor.yy382;
+ yylhsminor.yy320->type->token = psi_token_copy(func_->token);
+ yylhsminor.yy320->type->real.func = psi_decl_init(psi_decl_abi_init("default"), func_, yymsp[0].minor.yy179);
 }
-#line 2441 "src/parser_proc.c"
-  yy_destructor(yypParser,75,&yymsp[-4].minor);
-  yy_destructor(yypParser,77,&yymsp[-1].minor);
-  yymsp[-6].minor.yy64 = yylhsminor.yy64;
+#line 2817 "src/parser_proc.c"
+  yy_destructor(yypParser,86,&yymsp[-4].minor);
+  yy_destructor(yypParser,87,&yymsp[-1].minor);
+  yymsp[-6].minor.yy320 = yylhsminor.yy320;
         break;
-      case 50: /* decl_arg ::= VOID pointers NAME */
-#line 491 "src/parser_proc.y"
+      case 81: /* decl_arg ::= VOID pointers NAME */
+#line 630 "src/parser_proc.y"
 {
- yylhsminor.yy64 = psi_decl_arg_init(
+ yylhsminor.yy320 = psi_decl_arg_init(
   psi_decl_type_init(yymsp[-2].minor.yy0->type, yymsp[-2].minor.yy0->text),
-  psi_decl_var_init(yymsp[0].minor.yy0->text, yymsp[-1].minor.yy296, 0)
+  psi_decl_var_init(yymsp[0].minor.yy0->text, yymsp[-1].minor.yy382, 0)
  );
- yylhsminor.yy64->type->token = yymsp[-2].minor.yy0;
- yylhsminor.yy64->var->token = yymsp[0].minor.yy0;
- yylhsminor.yy64->token = yymsp[0].minor.yy0;
+ yylhsminor.yy320->type->token = yymsp[-2].minor.yy0;
+ yylhsminor.yy320->var->token = yymsp[0].minor.yy0;
+ yylhsminor.yy320->token = yymsp[0].minor.yy0;
 }
-#line 2457 "src/parser_proc.c"
-  yymsp[-2].minor.yy64 = yylhsminor.yy64;
+#line 2833 "src/parser_proc.c"
+  yymsp[-2].minor.yy320 = yylhsminor.yy320;
         break;
-      case 51: /* decl_arg ::= CONST VOID pointers NAME */
-{  yy_destructor(yypParser,84,&yymsp[-3].minor);
-#line 500 "src/parser_proc.y"
+      case 82: /* decl_arg ::= CONST VOID pointers NAME */
+{  yy_destructor(yypParser,99,&yymsp[-3].minor);
+#line 639 "src/parser_proc.y"
 {
- yymsp[-3].minor.yy64 = psi_decl_arg_init(
+ yymsp[-3].minor.yy320 = psi_decl_arg_init(
   psi_decl_type_init(yymsp[-2].minor.yy0->type, yymsp[-2].minor.yy0->text),
-  psi_decl_var_init(yymsp[0].minor.yy0->text, yymsp[-1].minor.yy296, 0)
+  psi_decl_var_init(yymsp[0].minor.yy0->text, yymsp[-1].minor.yy382, 0)
  );
- yymsp[-3].minor.yy64->type->token = yymsp[-2].minor.yy0;
- yymsp[-3].minor.yy64->var->token = yymsp[0].minor.yy0;
- yymsp[-3].minor.yy64->token = yymsp[0].minor.yy0;
+ yymsp[-3].minor.yy320->type->token = yymsp[-2].minor.yy0;
+ yymsp[-3].minor.yy320->var->token = yymsp[0].minor.yy0;
+ yymsp[-3].minor.yy320->token = yymsp[0].minor.yy0;
 }
-#line 2472 "src/parser_proc.c"
+#line 2848 "src/parser_proc.c"
 }
         break;
-      case 52: /* decl_args ::= */
-#line 509 "src/parser_proc.y"
-{
- yymsp[1].minor.yy7 = NULL;
-}
-#line 2480 "src/parser_proc.c"
-        break;
-      case 53: /* decl_args ::= VOID */
+      case 84: /* decl_args ::= VOID */
 {  yy_destructor(yypParser,57,&yymsp[0].minor);
-#line 512 "src/parser_proc.y"
+#line 651 "src/parser_proc.y"
 {
- yymsp[0].minor.yy7 = NULL;
+ yymsp[0].minor.yy179 = NULL;
 }
-#line 2488 "src/parser_proc.c"
+#line 2857 "src/parser_proc.c"
 }
         break;
-      case 54: /* decl_args ::= decl_arg */
-      case 56: /* struct_args ::= struct_arg */ yytestcase(yyruleno==56);
-#line 515 "src/parser_proc.y"
+      case 85: /* decl_args ::= decl_arg */
+      case 87: /* struct_args ::= struct_arg */ yytestcase(yyruleno==87);
+#line 654 "src/parser_proc.y"
 {
- yylhsminor.yy7 = psi_plist_add(psi_plist_init((psi_plist_dtor) psi_decl_arg_free),
-   &yymsp[0].minor.yy64);
+ yylhsminor.yy179 = psi_plist_add(psi_plist_init((psi_plist_dtor) psi_decl_arg_free),
+   &yymsp[0].minor.yy320);
 }
-#line 2498 "src/parser_proc.c"
-  yymsp[0].minor.yy7 = yylhsminor.yy7;
+#line 2867 "src/parser_proc.c"
+  yymsp[0].minor.yy179 = yylhsminor.yy179;
         break;
-      case 55: /* decl_args ::= decl_args COMMA decl_arg */
-#line 519 "src/parser_proc.y"
+      case 86: /* decl_args ::= decl_args COMMA decl_arg */
+#line 658 "src/parser_proc.y"
 {
- yylhsminor.yy7 = psi_plist_add(yymsp[-2].minor.yy7, &yymsp[0].minor.yy64);
+ yylhsminor.yy179 = psi_plist_add(yymsp[-2].minor.yy179, &yymsp[0].minor.yy320);
 }
-#line 2506 "src/parser_proc.c"
-  yy_destructor(yypParser,76,&yymsp[-1].minor);
-  yymsp[-2].minor.yy7 = yylhsminor.yy7;
+#line 2875 "src/parser_proc.c"
+  yy_destructor(yypParser,88,&yymsp[-1].minor);
+  yymsp[-2].minor.yy179 = yylhsminor.yy179;
         break;
-      case 57: /* struct_args ::= struct_args struct_arg */
-#line 526 "src/parser_proc.y"
+      case 88: /* struct_args ::= struct_args struct_arg */
+#line 665 "src/parser_proc.y"
 {
- yylhsminor.yy7 = psi_plist_add(yymsp[-1].minor.yy7, &yymsp[0].minor.yy64);
+ yylhsminor.yy179 = psi_plist_add(yymsp[-1].minor.yy179, &yymsp[0].minor.yy320);
 }
-#line 2515 "src/parser_proc.c"
-  yymsp[-1].minor.yy7 = yylhsminor.yy7;
+#line 2884 "src/parser_proc.c"
+  yymsp[-1].minor.yy179 = yylhsminor.yy179;
         break;
-      case 58: /* struct_arg ::= decl_typedef_body_ex EOS */
-#line 529 "src/parser_proc.y"
+      case 89: /* struct_arg ::= decl_typedef_body_ex EOS */
+#line 668 "src/parser_proc.y"
 {
- yylhsminor.yy64 = yymsp[-1].minor.yy64;
- switch (yymsp[-1].minor.yy64->type->type) {
+ yylhsminor.yy320 = yymsp[-1].minor.yy320;
+ switch (yymsp[-1].minor.yy320->type->type) {
  case PSI_T_STRUCT:
-  if (yymsp[-1].minor.yy64->type->real.strct) {
+  if (yymsp[-1].minor.yy320->type->real.strct) {
    if (!P->structs) {
     P->structs = psi_plist_init((psi_plist_dtor) psi_decl_struct_free);
    }
-   P->structs = psi_plist_add(P->structs, &yymsp[-1].minor.yy64->type->real.strct);
+   P->structs = psi_plist_add(P->structs, &yymsp[-1].minor.yy320->type->real.strct);
   }
   break;
  case PSI_T_UNION:
-  if (yymsp[-1].minor.yy64->type->real.unn) {
+  if (yymsp[-1].minor.yy320->type->real.unn) {
    if (!P->unions) {
     P->unions = psi_plist_init((psi_plist_dtor) psi_decl_union_free);
    }
-   P->unions = psi_plist_add(P->unions, &yymsp[-1].minor.yy64->type->real.unn);
+   P->unions = psi_plist_add(P->unions, &yymsp[-1].minor.yy320->type->real.unn);
   }
   break;
  case PSI_T_ENUM:
-  if (yymsp[-1].minor.yy64->type->real.enm) {
+  if (yymsp[-1].minor.yy320->type->real.enm) {
    if (!P->enums) {
     P->enums = psi_plist_init((psi_plist_dtor) psi_decl_enum_free);
    }
-   P->enums = psi_plist_add(P->enums, &yymsp[-1].minor.yy64->type->real.enm);
+   P->enums = psi_plist_add(P->enums, &yymsp[-1].minor.yy320->type->real.enm);
   }
   break;
  }
 }
-#line 2549 "src/parser_proc.c"
-  yy_destructor(yypParser,73,&yymsp[0].minor);
-  yymsp[-1].minor.yy64 = yylhsminor.yy64;
+#line 2918 "src/parser_proc.c"
+  yy_destructor(yypParser,75,&yymsp[0].minor);
+  yymsp[-1].minor.yy320 = yylhsminor.yy320;
         break;
-      case 59: /* struct_arg ::= decl_arg decl_layout EOS */
-#line 558 "src/parser_proc.y"
+      case 90: /* struct_arg ::= decl_arg decl_layout EOS */
+#line 697 "src/parser_proc.y"
 {
- yymsp[-2].minor.yy64->layout = yymsp[-1].minor.yy221;
- yylhsminor.yy64 = yymsp[-2].minor.yy64;
+ yymsp[-2].minor.yy320->layout = yymsp[-1].minor.yy369;
+ yylhsminor.yy320 = yymsp[-2].minor.yy320;
 }
-#line 2559 "src/parser_proc.c"
-  yy_destructor(yypParser,73,&yymsp[0].minor);
-  yymsp[-2].minor.yy64 = yylhsminor.yy64;
+#line 2928 "src/parser_proc.c"
+  yy_destructor(yypParser,75,&yymsp[0].minor);
+  yymsp[-2].minor.yy320 = yylhsminor.yy320;
         break;
-      case 60: /* decl_layout ::= */
-#line 562 "src/parser_proc.y"
+      case 91: /* decl_layout ::= */
+#line 701 "src/parser_proc.y"
 {
- yymsp[1].minor.yy221 = NULL;
+ yymsp[1].minor.yy369 = NULL;
 }
-#line 2568 "src/parser_proc.c"
+#line 2937 "src/parser_proc.c"
         break;
-      case 61: /* decl_layout ::= COLON COLON LPAREN NUMBER COMMA NUMBER RPAREN */
-{  yy_destructor(yypParser,74,&yymsp[-6].minor);
-#line 565 "src/parser_proc.y"
+      case 92: /* decl_layout ::= COLON COLON LPAREN NUMBER COMMA NUMBER RPAREN */
+{  yy_destructor(yypParser,92,&yymsp[-6].minor);
+#line 704 "src/parser_proc.y"
 {
- yymsp[-6].minor.yy221 = psi_layout_init(atol(yymsp[-3].minor.yy0->text), atol(yymsp[-1].minor.yy0->text));
+ yymsp[-6].minor.yy369 = psi_layout_init(atol(yymsp[-3].minor.yy0->text), atol(yymsp[-1].minor.yy0->text));
  free(yymsp[-3].minor.yy0);
  free(yymsp[-1].minor.yy0);
 }
-#line 2578 "src/parser_proc.c"
-  yy_destructor(yypParser,74,&yymsp[-5].minor);
-  yy_destructor(yypParser,75,&yymsp[-4].minor);
-  yy_destructor(yypParser,76,&yymsp[-2].minor);
-  yy_destructor(yypParser,77,&yymsp[0].minor);
+#line 2947 "src/parser_proc.c"
+  yy_destructor(yypParser,92,&yymsp[-5].minor);
+  yy_destructor(yypParser,86,&yymsp[-4].minor);
+  yy_destructor(yypParser,88,&yymsp[-2].minor);
+  yy_destructor(yypParser,87,&yymsp[0].minor);
 }
         break;
-      case 63: /* decl_scalar_type ::= SHORT decl_scalar_type_short */
-      case 67: /* decl_scalar_type ::= LONG decl_scalar_type_long */ yytestcase(yyruleno==67);
-      case 70: /* decl_scalar_type_long ::= LONG decl_scalar_type_long_long */ yytestcase(yyruleno==70);
-#line 573 "src/parser_proc.y"
+      case 94: /* decl_scalar_type ::= SHORT decl_scalar_type_short */
+      case 98: /* decl_scalar_type ::= LONG decl_scalar_type_long */ yytestcase(yyruleno==98);
+      case 101: /* decl_scalar_type_long ::= LONG decl_scalar_type_long_long */ yytestcase(yyruleno==101);
+#line 712 "src/parser_proc.y"
 {
  if (yymsp[0].minor.yy0) {
   yylhsminor.yy0 = psi_token_cat(2, yymsp[-1].minor.yy0, yymsp[0].minor.yy0);
@@ -2594,767 +2963,757 @@ static void yy_reduce(
   yylhsminor.yy0 = yymsp[-1].minor.yy0;
  }
 }
-#line 2598 "src/parser_proc.c"
+#line 2967 "src/parser_proc.c"
   yymsp[-1].minor.yy0 = yylhsminor.yy0;
         break;
-      case 73: /* decl_type ::= UNSIGNED decl_scalar_type */
-      case 74: /* decl_type ::= SIGNED decl_scalar_type */ yytestcase(yyruleno==74);
-#line 621 "src/parser_proc.y"
+      case 104: /* decl_type ::= UNSIGNED decl_scalar_type */
+      case 105: /* decl_type ::= SIGNED decl_scalar_type */ yytestcase(yyruleno==105);
+#line 760 "src/parser_proc.y"
 {
  struct psi_token *T = psi_token_cat(2, yymsp[-1].minor.yy0, yymsp[0].minor.yy0);
- yylhsminor.yy182 = psi_decl_type_init(T->type, T->text);
- yylhsminor.yy182->token = T;
+ yylhsminor.yy172 = psi_decl_type_init(T->type, T->text);
+ yylhsminor.yy172->token = T;
  free(yymsp[-1].minor.yy0);
  free(yymsp[0].minor.yy0);
 }
-#line 2611 "src/parser_proc.c"
-  yymsp[-1].minor.yy182 = yylhsminor.yy182;
+#line 2980 "src/parser_proc.c"
+  yymsp[-1].minor.yy172 = yylhsminor.yy172;
         break;
-      case 75: /* decl_type ::= UNSIGNED */
-      case 76: /* decl_type ::= SIGNED */ yytestcase(yyruleno==76);
-#line 635 "src/parser_proc.y"
+      case 106: /* decl_type ::= UNSIGNED */
+      case 107: /* decl_type ::= SIGNED */ yytestcase(yyruleno==107);
+#line 774 "src/parser_proc.y"
 {
- yylhsminor.yy182 = psi_decl_type_init(PSI_T_NAME, yymsp[0].minor.yy0->text);
- yylhsminor.yy182->token = yymsp[0].minor.yy0;
+ yylhsminor.yy172 = psi_decl_type_init(PSI_T_NAME, yymsp[0].minor.yy0->text);
+ yylhsminor.yy172->token = yymsp[0].minor.yy0;
 }
-#line 2621 "src/parser_proc.c"
-  yymsp[0].minor.yy182 = yylhsminor.yy182;
+#line 2990 "src/parser_proc.c"
+  yymsp[0].minor.yy172 = yylhsminor.yy172;
         break;
-      case 77: /* decl_type ::= decl_scalar_type */
-      case 81: /* decl_type ::= FLOAT|DOUBLE|INT8|UINT8|INT16|UINT16|INT32|UINT32|INT64|UINT64|NAME */ yytestcase(yyruleno==81);
-#line 643 "src/parser_proc.y"
+      case 108: /* decl_type ::= decl_scalar_type */
+      case 112: /* decl_type ::= FLOAT|DOUBLE|INT8|UINT8|INT16|UINT16|INT32|UINT32|INT64|UINT64|NAME */ yytestcase(yyruleno==112);
+#line 782 "src/parser_proc.y"
 {
- yylhsminor.yy182 = psi_decl_type_init(yymsp[0].minor.yy0->type, yymsp[0].minor.yy0->text);
- yylhsminor.yy182->token = yymsp[0].minor.yy0;
+ yylhsminor.yy172 = psi_decl_type_init(yymsp[0].minor.yy0->type, yymsp[0].minor.yy0->text);
+ yylhsminor.yy172->token = yymsp[0].minor.yy0;
 }
-#line 2631 "src/parser_proc.c"
-  yymsp[0].minor.yy182 = yylhsminor.yy182;
+#line 3000 "src/parser_proc.c"
+  yymsp[0].minor.yy172 = yylhsminor.yy172;
         break;
-      case 78: /* decl_type ::= STRUCT NAME */
-      case 79: /* decl_type ::= UNION NAME */ yytestcase(yyruleno==79);
-      case 80: /* decl_type ::= ENUM NAME */ yytestcase(yyruleno==80);
-#line 647 "src/parser_proc.y"
+      case 109: /* decl_type ::= STRUCT NAME */
+      case 110: /* decl_type ::= UNION NAME */ yytestcase(yyruleno==110);
+      case 111: /* decl_type ::= ENUM NAME */ yytestcase(yyruleno==111);
+#line 786 "src/parser_proc.y"
 {
- yylhsminor.yy182 = psi_decl_type_init(yymsp[-1].minor.yy0->type, yymsp[0].minor.yy0->text);
- yylhsminor.yy182->token = yymsp[0].minor.yy0;
+ yylhsminor.yy172 = psi_decl_type_init(yymsp[-1].minor.yy0->type, yymsp[0].minor.yy0->text);
+ yylhsminor.yy172->token = yymsp[0].minor.yy0;
  free(yymsp[-1].minor.yy0);
 }
-#line 2643 "src/parser_proc.c"
-  yymsp[-1].minor.yy182 = yylhsminor.yy182;
+#line 3012 "src/parser_proc.c"
+  yymsp[-1].minor.yy172 = yylhsminor.yy172;
         break;
-      case 82: /* const_decl_type ::= decl_type */
-#line 666 "src/parser_proc.y"
+      case 113: /* const_decl_type ::= decl_type */
+#line 805 "src/parser_proc.y"
 {
- yylhsminor.yy182 = yymsp[0].minor.yy182;
+ yylhsminor.yy172 = yymsp[0].minor.yy172;
 }
-#line 2651 "src/parser_proc.c"
-  yymsp[0].minor.yy182 = yylhsminor.yy182;
+#line 3020 "src/parser_proc.c"
+  yymsp[0].minor.yy172 = yylhsminor.yy172;
         break;
-      case 83: /* const_decl_type ::= CONST decl_type */
-{  yy_destructor(yypParser,84,&yymsp[-1].minor);
-#line 669 "src/parser_proc.y"
+      case 114: /* const_decl_type ::= CONST decl_type */
+{  yy_destructor(yypParser,99,&yymsp[-1].minor);
+#line 808 "src/parser_proc.y"
 {
- yymsp[-1].minor.yy182 = yymsp[0].minor.yy182;
+ yymsp[-1].minor.yy172 = yymsp[0].minor.yy172;
 }
-#line 2660 "src/parser_proc.c"
+#line 3029 "src/parser_proc.c"
 }
         break;
-      case 84: /* impl ::= impl_func LBRACE impl_stmts RBRACE */
-#line 672 "src/parser_proc.y"
+      case 115: /* impl ::= impl_func LBRACE impl_stmts RBRACE */
+#line 811 "src/parser_proc.y"
 {
- yylhsminor.yy303 = psi_impl_init(yymsp[-3].minor.yy226, yymsp[-1].minor.yy7);
+ yylhsminor.yy49 = psi_impl_init(yymsp[-3].minor.yy56, yymsp[-1].minor.yy179);
 }
-#line 2668 "src/parser_proc.c"
-  yy_destructor(yypParser,81,&yymsp[-2].minor);
-  yy_destructor(yypParser,82,&yymsp[0].minor);
-  yymsp[-3].minor.yy303 = yylhsminor.yy303;
+#line 3037 "src/parser_proc.c"
+  yy_destructor(yypParser,96,&yymsp[-2].minor);
+  yy_destructor(yypParser,97,&yymsp[0].minor);
+  yymsp[-3].minor.yy49 = yylhsminor.yy49;
         break;
-      case 85: /* impl ::= STATIC impl_func LBRACE impl_stmts RBRACE */
-{  yy_destructor(yypParser,94,&yymsp[-4].minor);
-#line 675 "src/parser_proc.y"
+      case 116: /* impl ::= STATIC impl_func LBRACE impl_stmts RBRACE */
+{  yy_destructor(yypParser,109,&yymsp[-4].minor);
+#line 814 "src/parser_proc.y"
 {
- yymsp[-3].minor.yy226->static_memory = 1;
- yymsp[-4].minor.yy303 = psi_impl_init(yymsp[-3].minor.yy226, yymsp[-1].minor.yy7);
+ yymsp[-3].minor.yy56->static_memory = 1;
+ yymsp[-4].minor.yy49 = psi_impl_init(yymsp[-3].minor.yy56, yymsp[-1].minor.yy179);
 }
-#line 2680 "src/parser_proc.c"
-  yy_destructor(yypParser,81,&yymsp[-2].minor);
-  yy_destructor(yypParser,82,&yymsp[0].minor);
+#line 3049 "src/parser_proc.c"
+  yy_destructor(yypParser,96,&yymsp[-2].minor);
+  yy_destructor(yypParser,97,&yymsp[0].minor);
 }
         break;
-      case 86: /* impl_func ::= FUNCTION reference NSNAME LPAREN RPAREN COLON impl_type */
-{  yy_destructor(yypParser,95,&yymsp[-6].minor);
-#line 679 "src/parser_proc.y"
+      case 117: /* impl_func ::= FUNCTION reference NSNAME LPAREN RPAREN COLON impl_type */
+{  yy_destructor(yypParser,110,&yymsp[-6].minor);
+#line 818 "src/parser_proc.y"
 {
- yymsp[-6].minor.yy226 = psi_impl_func_init(yymsp[-4].minor.yy0->text, NULL, yymsp[0].minor.yy40);
- yymsp[-6].minor.yy226->token = yymsp[-4].minor.yy0;
- yymsp[-6].minor.yy226->return_reference = yymsp[-5].minor.yy247;
+ yymsp[-6].minor.yy56 = psi_impl_func_init(yymsp[-4].minor.yy0->text, NULL, yymsp[0].minor.yy246);
+ yymsp[-6].minor.yy56->token = yymsp[-4].minor.yy0;
+ yymsp[-6].minor.yy56->return_reference = yymsp[-5].minor.yy89;
 }
-#line 2693 "src/parser_proc.c"
-  yy_destructor(yypParser,75,&yymsp[-3].minor);
-  yy_destructor(yypParser,77,&yymsp[-2].minor);
-  yy_destructor(yypParser,74,&yymsp[-1].minor);
+#line 3062 "src/parser_proc.c"
+  yy_destructor(yypParser,86,&yymsp[-3].minor);
+  yy_destructor(yypParser,87,&yymsp[-2].minor);
+  yy_destructor(yypParser,92,&yymsp[-1].minor);
 }
         break;
-      case 87: /* impl_func ::= FUNCTION reference NSNAME LPAREN impl_args RPAREN COLON impl_type */
-{  yy_destructor(yypParser,95,&yymsp[-7].minor);
-#line 684 "src/parser_proc.y"
+      case 118: /* impl_func ::= FUNCTION reference NSNAME LPAREN impl_args RPAREN COLON impl_type */
+{  yy_destructor(yypParser,110,&yymsp[-7].minor);
+#line 823 "src/parser_proc.y"
 {
- yymsp[-7].minor.yy226 = psi_impl_func_init(yymsp[-5].minor.yy0->text, yymsp[-3].minor.yy7, yymsp[0].minor.yy40);
- yymsp[-7].minor.yy226->token = yymsp[-5].minor.yy0;
- yymsp[-7].minor.yy226->return_reference = yymsp[-6].minor.yy247;
+ yymsp[-7].minor.yy56 = psi_impl_func_init(yymsp[-5].minor.yy0->text, yymsp[-3].minor.yy179, yymsp[0].minor.yy246);
+ yymsp[-7].minor.yy56->token = yymsp[-5].minor.yy0;
+ yymsp[-7].minor.yy56->return_reference = yymsp[-6].minor.yy89;
 }
-#line 2707 "src/parser_proc.c"
-  yy_destructor(yypParser,75,&yymsp[-4].minor);
-  yy_destructor(yypParser,77,&yymsp[-2].minor);
-  yy_destructor(yypParser,74,&yymsp[-1].minor);
+#line 3076 "src/parser_proc.c"
+  yy_destructor(yypParser,86,&yymsp[-4].minor);
+  yy_destructor(yypParser,87,&yymsp[-2].minor);
+  yy_destructor(yypParser,92,&yymsp[-1].minor);
 }
         break;
-      case 88: /* impl_func ::= FUNCTION reference NSNAME LPAREN impl_args COMMA impl_type reference ELLIPSIS DOLLAR_NAME RPAREN COLON impl_type */
-{  yy_destructor(yypParser,95,&yymsp[-12].minor);
-#line 689 "src/parser_proc.y"
+      case 119: /* impl_func ::= FUNCTION reference NSNAME LPAREN impl_args COMMA impl_type reference ELLIPSIS DOLLAR_NAME RPAREN COLON impl_type */
+{  yy_destructor(yypParser,110,&yymsp[-12].minor);
+#line 828 "src/parser_proc.y"
 {
- yymsp[-12].minor.yy226 = psi_impl_func_init(yymsp[-10].minor.yy0->text, yymsp[-8].minor.yy7, yymsp[0].minor.yy40);
- yymsp[-12].minor.yy226->token = yymsp[-10].minor.yy0;
- yymsp[-12].minor.yy226->return_reference = yymsp[-11].minor.yy247;
- yymsp[-12].minor.yy226->vararg = psi_impl_arg_init(yymsp[-6].minor.yy40, psi_impl_var_init(yymsp[-3].minor.yy0->text, yymsp[-5].minor.yy247), NULL);
+ yymsp[-12].minor.yy56 = psi_impl_func_init(yymsp[-10].minor.yy0->text, yymsp[-8].minor.yy179, yymsp[0].minor.yy246);
+ yymsp[-12].minor.yy56->token = yymsp[-10].minor.yy0;
+ yymsp[-12].minor.yy56->return_reference = yymsp[-11].minor.yy89;
+ yymsp[-12].minor.yy56->vararg = psi_impl_arg_init(yymsp[-6].minor.yy246, psi_impl_var_init(yymsp[-3].minor.yy0->text, yymsp[-5].minor.yy89), NULL);
  free(yymsp[-3].minor.yy0);
 }
-#line 2723 "src/parser_proc.c"
-  yy_destructor(yypParser,75,&yymsp[-9].minor);
-  yy_destructor(yypParser,76,&yymsp[-7].minor);
-  yy_destructor(yypParser,86,&yymsp[-4].minor);
-  yy_destructor(yypParser,77,&yymsp[-2].minor);
-  yy_destructor(yypParser,74,&yymsp[-1].minor);
+#line 3092 "src/parser_proc.c"
+  yy_destructor(yypParser,86,&yymsp[-9].minor);
+  yy_destructor(yypParser,88,&yymsp[-7].minor);
+  yy_destructor(yypParser,101,&yymsp[-4].minor);
+  yy_destructor(yypParser,87,&yymsp[-2].minor);
+  yy_destructor(yypParser,92,&yymsp[-1].minor);
 }
         break;
-      case 89: /* impl_def_val ::= NULL|NUMBER|TRUE|FALSE|QUOTED_STRING */
-#line 696 "src/parser_proc.y"
+      case 120: /* impl_def_val ::= NULL|NUMBER|TRUE|FALSE|QUOTED_STRING */
+#line 835 "src/parser_proc.y"
 {
- yylhsminor.yy319 = psi_impl_def_val_init(yymsp[0].minor.yy0->type, yymsp[0].minor.yy0->text);
- yylhsminor.yy319->token = yymsp[0].minor.yy0;
+ yylhsminor.yy145 = psi_impl_def_val_init(yymsp[0].minor.yy0->type, yymsp[0].minor.yy0->text);
+ yylhsminor.yy145->token = yymsp[0].minor.yy0;
 }
-#line 2737 "src/parser_proc.c"
-  yymsp[0].minor.yy319 = yylhsminor.yy319;
+#line 3106 "src/parser_proc.c"
+  yymsp[0].minor.yy145 = yylhsminor.yy145;
         break;
-      case 90: /* impl_var ::= reference DOLLAR_NAME */
-#line 700 "src/parser_proc.y"
+      case 121: /* impl_var ::= reference DOLLAR_NAME */
+#line 839 "src/parser_proc.y"
 {
- yylhsminor.yy123 = psi_impl_var_init(yymsp[0].minor.yy0->text, yymsp[-1].minor.yy247);
- yylhsminor.yy123->token = yymsp[0].minor.yy0;
+ yylhsminor.yy370 = psi_impl_var_init(yymsp[0].minor.yy0->text, yymsp[-1].minor.yy89);
+ yylhsminor.yy370->token = yymsp[0].minor.yy0;
 }
-#line 2746 "src/parser_proc.c"
-  yymsp[-1].minor.yy123 = yylhsminor.yy123;
+#line 3115 "src/parser_proc.c"
+  yymsp[-1].minor.yy370 = yylhsminor.yy370;
         break;
-      case 91: /* impl_type ::= VOID|MIXED|BOOL|INT|FLOAT|STRING|ARRAY|OBJECT|CALLABLE */
-#line 704 "src/parser_proc.y"
+      case 122: /* impl_type ::= VOID|MIXED|BOOL|INT|FLOAT|STRING|ARRAY|OBJECT|CALLABLE */
+#line 843 "src/parser_proc.y"
 {
- yylhsminor.yy40 = psi_impl_type_init(yymsp[0].minor.yy0->type, yymsp[0].minor.yy0->text);
+ yylhsminor.yy246 = psi_impl_type_init(yymsp[0].minor.yy0->type, yymsp[0].minor.yy0->text);
  free(yymsp[0].minor.yy0);
 }
-#line 2755 "src/parser_proc.c"
-  yymsp[0].minor.yy40 = yylhsminor.yy40;
-        break;
-      case 92: /* impl_arg ::= impl_type impl_var */
-#line 708 "src/parser_proc.y"
-{
- yylhsminor.yy56 = psi_impl_arg_init(yymsp[-1].minor.yy40, yymsp[0].minor.yy123, NULL);
-}
-#line 2763 "src/parser_proc.c"
-  yymsp[-1].minor.yy56 = yylhsminor.yy56;
-        break;
-      case 93: /* impl_arg ::= impl_type impl_var EQUALS impl_def_val */
-#line 711 "src/parser_proc.y"
-{
- yylhsminor.yy56 = psi_impl_arg_init(yymsp[-3].minor.yy40, yymsp[-2].minor.yy123, yymsp[0].minor.yy319);
-}
-#line 2771 "src/parser_proc.c"
-  yy_destructor(yypParser,83,&yymsp[-1].minor);
-  yymsp[-3].minor.yy56 = yylhsminor.yy56;
+#line 3124 "src/parser_proc.c"
+  yymsp[0].minor.yy246 = yylhsminor.yy246;
         break;
-      case 94: /* impl_args ::= impl_arg */
-#line 714 "src/parser_proc.y"
+      case 123: /* impl_arg ::= impl_type impl_var */
+#line 847 "src/parser_proc.y"
 {
- yylhsminor.yy7 = psi_plist_add(psi_plist_init((psi_plist_dtor) psi_impl_arg_free),
-   &yymsp[0].minor.yy56);
+ yylhsminor.yy34 = psi_impl_arg_init(yymsp[-1].minor.yy246, yymsp[0].minor.yy370, NULL);
 }
-#line 2781 "src/parser_proc.c"
-  yymsp[0].minor.yy7 = yylhsminor.yy7;
+#line 3132 "src/parser_proc.c"
+  yymsp[-1].minor.yy34 = yylhsminor.yy34;
         break;
-      case 95: /* impl_args ::= impl_args COMMA impl_arg */
-#line 718 "src/parser_proc.y"
+      case 124: /* impl_arg ::= impl_type impl_var EQUALS impl_def_val */
+#line 850 "src/parser_proc.y"
 {
- yylhsminor.yy7 = psi_plist_add(yymsp[-2].minor.yy7, &yymsp[0].minor.yy56);
+ yylhsminor.yy34 = psi_impl_arg_init(yymsp[-3].minor.yy246, yymsp[-2].minor.yy370, yymsp[0].minor.yy145);
 }
-#line 2789 "src/parser_proc.c"
-  yy_destructor(yypParser,76,&yymsp[-1].minor);
-  yymsp[-2].minor.yy7 = yylhsminor.yy7;
+#line 3140 "src/parser_proc.c"
+  yy_destructor(yypParser,98,&yymsp[-1].minor);
+  yymsp[-3].minor.yy34 = yylhsminor.yy34;
         break;
-      case 96: /* impl_stmts ::= impl_stmt */
-#line 721 "src/parser_proc.y"
+      case 125: /* impl_args ::= impl_arg */
+#line 853 "src/parser_proc.y"
 {
- yylhsminor.yy7 = psi_plist_add(psi_plist_init((psi_plist_dtor) psi_impl_stmt_free),
-   &yymsp[0].minor.yy282);
+ yylhsminor.yy179 = psi_plist_add(psi_plist_init((psi_plist_dtor) psi_impl_arg_free),
+   &yymsp[0].minor.yy34);
 }
-#line 2799 "src/parser_proc.c"
-  yymsp[0].minor.yy7 = yylhsminor.yy7;
+#line 3150 "src/parser_proc.c"
+  yymsp[0].minor.yy179 = yylhsminor.yy179;
         break;
-      case 97: /* impl_stmts ::= impl_stmts impl_stmt */
-#line 725 "src/parser_proc.y"
+      case 126: /* impl_args ::= impl_args COMMA impl_arg */
+#line 857 "src/parser_proc.y"
 {
- yylhsminor.yy7 = psi_plist_add(yymsp[-1].minor.yy7, &yymsp[0].minor.yy282);
+ yylhsminor.yy179 = psi_plist_add(yymsp[-2].minor.yy179, &yymsp[0].minor.yy34);
 }
-#line 2807 "src/parser_proc.c"
-  yymsp[-1].minor.yy7 = yylhsminor.yy7;
+#line 3158 "src/parser_proc.c"
+  yy_destructor(yypParser,88,&yymsp[-1].minor);
+  yymsp[-2].minor.yy179 = yylhsminor.yy179;
         break;
-      case 98: /* impl_stmt ::= return_stmt */
-#line 728 "src/parser_proc.y"
+      case 127: /* impl_stmts ::= impl_stmt */
+#line 860 "src/parser_proc.y"
 {
- yylhsminor.yy282 = (struct psi_token**) yymsp[0].minor.yy258;
+ yylhsminor.yy179 = psi_plist_add(psi_plist_init((psi_plist_dtor) psi_impl_stmt_free),
+   &yymsp[0].minor.yy238);
 }
-#line 2815 "src/parser_proc.c"
-  yymsp[0].minor.yy282 = yylhsminor.yy282;
+#line 3168 "src/parser_proc.c"
+  yymsp[0].minor.yy179 = yylhsminor.yy179;
         break;
-      case 99: /* impl_stmt ::= let_stmt */
-#line 731 "src/parser_proc.y"
+      case 128: /* impl_stmts ::= impl_stmts impl_stmt */
+#line 864 "src/parser_proc.y"
 {
- yylhsminor.yy282 = (struct psi_token**) yymsp[0].minor.yy138;
+ yylhsminor.yy179 = psi_plist_add(yymsp[-1].minor.yy179, &yymsp[0].minor.yy238);
 }
-#line 2823 "src/parser_proc.c"
-  yymsp[0].minor.yy282 = yylhsminor.yy282;
+#line 3176 "src/parser_proc.c"
+  yymsp[-1].minor.yy179 = yylhsminor.yy179;
         break;
-      case 100: /* impl_stmt ::= set_stmt */
-#line 734 "src/parser_proc.y"
+      case 129: /* impl_stmt ::= return_stmt */
+#line 867 "src/parser_proc.y"
 {
- yylhsminor.yy282 = (struct psi_token**) yymsp[0].minor.yy300;
+ yylhsminor.yy238 = (struct psi_token**) yymsp[0].minor.yy342;
 }
-#line 2831 "src/parser_proc.c"
-  yymsp[0].minor.yy282 = yylhsminor.yy282;
+#line 3184 "src/parser_proc.c"
+  yymsp[0].minor.yy238 = yylhsminor.yy238;
         break;
-      case 101: /* impl_stmt ::= assert_stmt */
-#line 737 "src/parser_proc.y"
+      case 130: /* impl_stmt ::= let_stmt */
+#line 870 "src/parser_proc.y"
 {
- yylhsminor.yy282 = (struct psi_token **) yymsp[0].minor.yy146;
+ yylhsminor.yy238 = (struct psi_token**) yymsp[0].minor.yy319;
 }
-#line 2839 "src/parser_proc.c"
-  yymsp[0].minor.yy282 = yylhsminor.yy282;
+#line 3192 "src/parser_proc.c"
+  yymsp[0].minor.yy238 = yylhsminor.yy238;
         break;
-      case 102: /* impl_stmt ::= free_stmt */
-#line 740 "src/parser_proc.y"
+      case 131: /* impl_stmt ::= set_stmt */
+#line 873 "src/parser_proc.y"
 {
- yylhsminor.yy282 = (struct psi_token**) yymsp[0].minor.yy102;
+ yylhsminor.yy238 = (struct psi_token**) yymsp[0].minor.yy358;
 }
-#line 2847 "src/parser_proc.c"
-  yymsp[0].minor.yy282 = yylhsminor.yy282;
+#line 3200 "src/parser_proc.c"
+  yymsp[0].minor.yy238 = yylhsminor.yy238;
         break;
-      case 103: /* number ::= NUMBER|NSNAME */
-#line 743 "src/parser_proc.y"
+      case 132: /* impl_stmt ::= assert_stmt */
+#line 876 "src/parser_proc.y"
 {
- yylhsminor.yy66 = psi_number_init(yymsp[0].minor.yy0->type, yymsp[0].minor.yy0->text);
- yylhsminor.yy66->token = yymsp[0].minor.yy0;
+ yylhsminor.yy238 = (struct psi_token **) yymsp[0].minor.yy201;
 }
-#line 2856 "src/parser_proc.c"
-  yymsp[0].minor.yy66 = yylhsminor.yy66;
+#line 3208 "src/parser_proc.c"
+  yymsp[0].minor.yy238 = yylhsminor.yy238;
         break;
-      case 104: /* number ::= decl_var */
-#line 747 "src/parser_proc.y"
+      case 133: /* impl_stmt ::= free_stmt */
+#line 879 "src/parser_proc.y"
 {
- yylhsminor.yy66 = psi_number_init(PSI_T_NAME, yymsp[0].minor.yy131);
- yylhsminor.yy66->token = psi_token_copy(yymsp[0].minor.yy131->token);
+ yylhsminor.yy238 = (struct psi_token**) yymsp[0].minor.yy220;
 }
-#line 2865 "src/parser_proc.c"
-  yymsp[0].minor.yy66 = yylhsminor.yy66;
+#line 3216 "src/parser_proc.c"
+  yymsp[0].minor.yy238 = yylhsminor.yy238;
         break;
-      case 105: /* num_exp ::= number */
-#line 751 "src/parser_proc.y"
+      case 134: /* number ::= NUMBER|NSNAME */
+#line 882 "src/parser_proc.y"
 {
- yylhsminor.yy124 = psi_num_exp_init_num(yymsp[0].minor.yy66);
- yylhsminor.yy124->token = psi_token_copy(yymsp[0].minor.yy66->token);
+ yylhsminor.yy57 = psi_number_init(yymsp[0].minor.yy0->type, yymsp[0].minor.yy0->text);
+ yylhsminor.yy57->token = yymsp[0].minor.yy0;
 }
-#line 2874 "src/parser_proc.c"
-  yymsp[0].minor.yy124 = yylhsminor.yy124;
+#line 3225 "src/parser_proc.c"
+  yymsp[0].minor.yy57 = yylhsminor.yy57;
         break;
-      case 106: /* num_exp ::= LPAREN num_exp RPAREN */
-#line 755 "src/parser_proc.y"
+      case 135: /* number ::= decl_var */
+#line 886 "src/parser_proc.y"
 {
- yylhsminor.yy124 = psi_num_exp_init_unary(PSI_T_LPAREN, yymsp[-1].minor.yy124);
- yylhsminor.yy124->token = yymsp[-2].minor.yy0;
+ yylhsminor.yy57 = psi_number_init(PSI_T_NAME, yymsp[0].minor.yy271);
+ yylhsminor.yy57->token = psi_token_copy(yymsp[0].minor.yy271->token);
 }
-#line 2883 "src/parser_proc.c"
-  yy_destructor(yypParser,77,&yymsp[0].minor);
-  yymsp[-2].minor.yy124 = yylhsminor.yy124;
+#line 3234 "src/parser_proc.c"
+  yymsp[0].minor.yy57 = yylhsminor.yy57;
         break;
-      case 107: /* num_exp ::= num_exp PIPE|CARET|AMPERSAND|LSHIFT|RSHIFT|PLUS|MINUS|ASTERISK|SLASH|MODULO|RCHEVR|LCHEVR|CMP_GE|CMP_LE|OR|AND|CMP_EQ|CMP_NE num_exp */
-#line 759 "src/parser_proc.y"
+      case 136: /* num_exp ::= number */
+#line 890 "src/parser_proc.y"
 {
- yylhsminor.yy124 = psi_num_exp_init_binary(yymsp[-1].minor.yy0->type, yymsp[-2].minor.yy124, yymsp[0].minor.yy124);
- yylhsminor.yy124->token = yymsp[-1].minor.yy0;
+ yylhsminor.yy207 = psi_num_exp_init_num(yymsp[0].minor.yy57);
+ yylhsminor.yy207->token = psi_token_copy(yymsp[0].minor.yy57->token);
 }
-#line 2893 "src/parser_proc.c"
-  yymsp[-2].minor.yy124 = yylhsminor.yy124;
+#line 3243 "src/parser_proc.c"
+  yymsp[0].minor.yy207 = yylhsminor.yy207;
         break;
-      case 108: /* num_exp ::= TILDE|NOT|PLUS|MINUS num_exp */
-#line 763 "src/parser_proc.y"
+      case 137: /* num_exp ::= LPAREN num_exp RPAREN */
+#line 894 "src/parser_proc.y"
 {
- yylhsminor.yy124 = psi_num_exp_init_unary(yymsp[-1].minor.yy0->type, yymsp[0].minor.yy124);
- yylhsminor.yy124->token = yymsp[-1].minor.yy0;
+ yylhsminor.yy207 = psi_num_exp_init_unary(PSI_T_LPAREN, yymsp[-1].minor.yy207);
+ yylhsminor.yy207->token = yymsp[-2].minor.yy0;
 }
-#line 2902 "src/parser_proc.c"
-  yymsp[-1].minor.yy124 = yylhsminor.yy124;
+#line 3252 "src/parser_proc.c"
+  yy_destructor(yypParser,87,&yymsp[0].minor);
+  yymsp[-2].minor.yy207 = yylhsminor.yy207;
         break;
-      case 109: /* let_exp ::= NULL */
+      case 140: /* let_exp ::= NULL */
 {  yy_destructor(yypParser,15,&yymsp[0].minor);
-#line 767 "src/parser_proc.y"
+#line 906 "src/parser_proc.y"
 {
- yymsp[0].minor.yy196 = psi_let_exp_init(PSI_LET_NULL, NULL);
+ yymsp[0].minor.yy200 = psi_let_exp_init(PSI_LET_NULL, NULL);
 }
-#line 2911 "src/parser_proc.c"
+#line 3262 "src/parser_proc.c"
 }
         break;
-      case 110: /* let_exp ::= AMPERSAND NULL */
+      case 141: /* let_exp ::= AMPERSAND NULL */
 {  yy_destructor(yypParser,23,&yymsp[-1].minor);
-#line 770 "src/parser_proc.y"
+#line 909 "src/parser_proc.y"
 {
- yymsp[-1].minor.yy196 = psi_let_exp_init(PSI_LET_NULL, NULL);
- yymsp[-1].minor.yy196->is_reference = 1;
+ yymsp[-1].minor.yy200 = psi_let_exp_init(PSI_LET_NULL, NULL);
+ yymsp[-1].minor.yy200->is_reference = 1;
 }
-#line 2921 "src/parser_proc.c"
+#line 3272 "src/parser_proc.c"
   yy_destructor(yypParser,15,&yymsp[0].minor);
 }
         break;
-      case 111: /* let_exp ::= let_callback */
-#line 774 "src/parser_proc.y"
+      case 142: /* let_exp ::= let_callback */
+#line 913 "src/parser_proc.y"
 {
- yylhsminor.yy196 = psi_let_exp_init(PSI_LET_CALLBACK, yymsp[0].minor.yy76);
+ yylhsminor.yy200 = psi_let_exp_init(PSI_LET_CALLBACK, yymsp[0].minor.yy120);
 }
-#line 2930 "src/parser_proc.c"
-  yymsp[0].minor.yy196 = yylhsminor.yy196;
+#line 3281 "src/parser_proc.c"
+  yymsp[0].minor.yy200 = yylhsminor.yy200;
         break;
-      case 112: /* let_exp ::= let_calloc */
-#line 777 "src/parser_proc.y"
+      case 143: /* let_exp ::= let_calloc */
+#line 916 "src/parser_proc.y"
 {
- yylhsminor.yy196 = psi_let_exp_init(PSI_LET_CALLOC, yymsp[0].minor.yy227);
+ yylhsminor.yy200 = psi_let_exp_init(PSI_LET_CALLOC, yymsp[0].minor.yy45);
 }
-#line 2938 "src/parser_proc.c"
-  yymsp[0].minor.yy196 = yylhsminor.yy196;
+#line 3289 "src/parser_proc.c"
+  yymsp[0].minor.yy200 = yylhsminor.yy200;
         break;
-      case 113: /* let_exp ::= AMPERSAND let_calloc */
+      case 144: /* let_exp ::= AMPERSAND let_calloc */
 {  yy_destructor(yypParser,23,&yymsp[-1].minor);
-#line 780 "src/parser_proc.y"
+#line 919 "src/parser_proc.y"
 {
- yymsp[-1].minor.yy196 = psi_let_exp_init(PSI_LET_CALLOC, yymsp[0].minor.yy227);
- yymsp[-1].minor.yy196->is_reference = 1;
+ yymsp[-1].minor.yy200 = psi_let_exp_init(PSI_LET_CALLOC, yymsp[0].minor.yy45);
+ yymsp[-1].minor.yy200->is_reference = 1;
 }
-#line 2948 "src/parser_proc.c"
+#line 3299 "src/parser_proc.c"
 }
         break;
-      case 114: /* let_exp ::= let_func */
-#line 784 "src/parser_proc.y"
+      case 145: /* let_exp ::= let_func */
+#line 923 "src/parser_proc.y"
 {
- yylhsminor.yy196 = psi_let_exp_init_ex(NULL, PSI_LET_FUNC, yymsp[0].minor.yy133);
+ yylhsminor.yy200 = psi_let_exp_init_ex(NULL, PSI_LET_FUNC, yymsp[0].minor.yy67);
 }
-#line 2956 "src/parser_proc.c"
-  yymsp[0].minor.yy196 = yylhsminor.yy196;
+#line 3307 "src/parser_proc.c"
+  yymsp[0].minor.yy200 = yylhsminor.yy200;
         break;
-      case 115: /* let_exp ::= AMPERSAND let_func */
+      case 146: /* let_exp ::= AMPERSAND let_func */
 {  yy_destructor(yypParser,23,&yymsp[-1].minor);
-#line 787 "src/parser_proc.y"
+#line 926 "src/parser_proc.y"
 {
- yymsp[-1].minor.yy196 = psi_let_exp_init_ex(NULL, PSI_LET_FUNC, yymsp[0].minor.yy133);
- yymsp[-1].minor.yy196->is_reference = 1;
+ yymsp[-1].minor.yy200 = psi_let_exp_init_ex(NULL, PSI_LET_FUNC, yymsp[0].minor.yy67);
+ yymsp[-1].minor.yy200->is_reference = 1;
 }
-#line 2966 "src/parser_proc.c"
+#line 3317 "src/parser_proc.c"
 }
         break;
-      case 116: /* let_exp ::= num_exp */
-#line 791 "src/parser_proc.y"
+      case 147: /* let_exp ::= num_exp */
+#line 930 "src/parser_proc.y"
 {
- yylhsminor.yy196 = psi_let_exp_init_ex(NULL, PSI_LET_NUMEXP, yymsp[0].minor.yy124);
+ yylhsminor.yy200 = psi_let_exp_init_ex(NULL, PSI_LET_NUMEXP, yymsp[0].minor.yy207);
 }
-#line 2974 "src/parser_proc.c"
-  yymsp[0].minor.yy196 = yylhsminor.yy196;
+#line 3325 "src/parser_proc.c"
+  yymsp[0].minor.yy200 = yylhsminor.yy200;
         break;
-      case 117: /* let_exp ::= AMPERSAND num_exp */
+      case 148: /* let_exp ::= AMPERSAND num_exp */
 {  yy_destructor(yypParser,23,&yymsp[-1].minor);
-#line 794 "src/parser_proc.y"
+#line 933 "src/parser_proc.y"
 {
- yymsp[-1].minor.yy196 = psi_let_exp_init_ex(NULL, PSI_LET_NUMEXP, yymsp[0].minor.yy124);
- yymsp[-1].minor.yy196->is_reference = 1;
+ yymsp[-1].minor.yy200 = psi_let_exp_init_ex(NULL, PSI_LET_NUMEXP, yymsp[0].minor.yy207);
+ yymsp[-1].minor.yy200->is_reference = 1;
 }
-#line 2984 "src/parser_proc.c"
+#line 3335 "src/parser_proc.c"
 }
         break;
-      case 118: /* let_exp ::= decl_var EQUALS let_exp */
-#line 798 "src/parser_proc.y"
+      case 149: /* let_exp ::= decl_var EQUALS let_exp */
+#line 937 "src/parser_proc.y"
 {
- yylhsminor.yy196 = yymsp[0].minor.yy196;
- yylhsminor.yy196->var = yymsp[-2].minor.yy131;
+ yylhsminor.yy200 = yymsp[0].minor.yy200;
+ yylhsminor.yy200->var = yymsp[-2].minor.yy271;
 }
-#line 2993 "src/parser_proc.c"
-  yy_destructor(yypParser,83,&yymsp[-1].minor);
-  yymsp[-2].minor.yy196 = yylhsminor.yy196;
+#line 3344 "src/parser_proc.c"
+  yy_destructor(yypParser,98,&yymsp[-1].minor);
+  yymsp[-2].minor.yy200 = yylhsminor.yy200;
         break;
-      case 119: /* let_stmt ::= LET let_exp EOS */
-#line 802 "src/parser_proc.y"
+      case 150: /* let_stmt ::= LET let_exp EOS */
+#line 941 "src/parser_proc.y"
 {
- yylhsminor.yy138 = psi_let_stmt_init(yymsp[-1].minor.yy196);
- yylhsminor.yy138->token = yymsp[-2].minor.yy0;
+ yylhsminor.yy319 = psi_let_stmt_init(yymsp[-1].minor.yy200);
+ yylhsminor.yy319->token = yymsp[-2].minor.yy0;
 }
-#line 3003 "src/parser_proc.c"
-  yy_destructor(yypParser,73,&yymsp[0].minor);
-  yymsp[-2].minor.yy138 = yylhsminor.yy138;
+#line 3354 "src/parser_proc.c"
+  yy_destructor(yypParser,75,&yymsp[0].minor);
+  yymsp[-2].minor.yy319 = yylhsminor.yy319;
         break;
-      case 120: /* let_stmt ::= TEMP decl_var EQUALS reference decl_var EOS */
-#line 806 "src/parser_proc.y"
+      case 151: /* let_stmt ::= TEMP decl_var EQUALS reference decl_var EOS */
+#line 945 "src/parser_proc.y"
 {
- yylhsminor.yy138 = psi_let_stmt_init(psi_let_exp_init_ex(yymsp[-4].minor.yy131, PSI_LET_TMP, yymsp[-1].minor.yy131));
- yylhsminor.yy138->token = yymsp[-5].minor.yy0;
- yylhsminor.yy138->exp->is_reference = yymsp[-2].minor.yy247 ? 1 : 0;
+ yylhsminor.yy319 = psi_let_stmt_init(psi_let_exp_init_ex(yymsp[-4].minor.yy271, PSI_LET_TMP, yymsp[-1].minor.yy271));
+ yylhsminor.yy319->token = yymsp[-5].minor.yy0;
+ yylhsminor.yy319->exp->is_reference = yymsp[-2].minor.yy89 ? 1 : 0;
 }
-#line 3014 "src/parser_proc.c"
-  yy_destructor(yypParser,83,&yymsp[-3].minor);
-  yy_destructor(yypParser,73,&yymsp[0].minor);
-  yymsp[-5].minor.yy138 = yylhsminor.yy138;
+#line 3365 "src/parser_proc.c"
+  yy_destructor(yypParser,98,&yymsp[-3].minor);
+  yy_destructor(yypParser,75,&yymsp[0].minor);
+  yymsp[-5].minor.yy319 = yylhsminor.yy319;
         break;
-      case 121: /* let_callback ::= CALLBACK callback_rval LPAREN impl_var LPAREN callback_arg_list RPAREN RPAREN */
-#line 811 "src/parser_proc.y"
+      case 152: /* let_callback ::= CALLBACK callback_rval LPAREN impl_var LPAREN callback_arg_list RPAREN RPAREN */
+#line 950 "src/parser_proc.y"
 {
- yylhsminor.yy76 = psi_let_callback_init(psi_let_func_init(yymsp[-6].minor.yy0->type, yymsp[-6].minor.yy0->text, yymsp[-4].minor.yy123), yymsp[-2].minor.yy304);
- yylhsminor.yy76->token = yymsp[-7].minor.yy0;
+ yylhsminor.yy120 = psi_let_callback_init(psi_let_func_init(yymsp[-6].minor.yy0->type, yymsp[-6].minor.yy0->text, yymsp[-4].minor.yy370), yymsp[-2].minor.yy243);
+ yylhsminor.yy120->token = yymsp[-7].minor.yy0;
  free(yymsp[-6].minor.yy0);
 }
-#line 3026 "src/parser_proc.c"
-  yy_destructor(yypParser,75,&yymsp[-5].minor);
-  yy_destructor(yypParser,75,&yymsp[-3].minor);
-  yy_destructor(yypParser,77,&yymsp[-1].minor);
-  yy_destructor(yypParser,77,&yymsp[0].minor);
-  yymsp[-7].minor.yy76 = yylhsminor.yy76;
+#line 3377 "src/parser_proc.c"
+  yy_destructor(yypParser,86,&yymsp[-5].minor);
+  yy_destructor(yypParser,86,&yymsp[-3].minor);
+  yy_destructor(yypParser,87,&yymsp[-1].minor);
+  yy_destructor(yypParser,87,&yymsp[0].minor);
+  yymsp[-7].minor.yy120 = yylhsminor.yy120;
         break;
-      case 122: /* let_calloc ::= CALLOC LPAREN num_exp COMMA num_exp RPAREN */
-#line 816 "src/parser_proc.y"
+      case 153: /* let_calloc ::= CALLOC LPAREN num_exp COMMA num_exp RPAREN */
+#line 955 "src/parser_proc.y"
 {
- yylhsminor.yy227 = psi_let_calloc_init(yymsp[-3].minor.yy124, yymsp[-1].minor.yy124);
- yylhsminor.yy227->token = yymsp[-5].minor.yy0;
+ yylhsminor.yy45 = psi_let_calloc_init(yymsp[-3].minor.yy207, yymsp[-1].minor.yy207);
+ yylhsminor.yy45->token = yymsp[-5].minor.yy0;
 }
-#line 3039 "src/parser_proc.c"
-  yy_destructor(yypParser,75,&yymsp[-4].minor);
-  yy_destructor(yypParser,76,&yymsp[-2].minor);
-  yy_destructor(yypParser,77,&yymsp[0].minor);
-  yymsp[-5].minor.yy227 = yylhsminor.yy227;
+#line 3390 "src/parser_proc.c"
+  yy_destructor(yypParser,86,&yymsp[-4].minor);
+  yy_destructor(yypParser,88,&yymsp[-2].minor);
+  yy_destructor(yypParser,87,&yymsp[0].minor);
+  yymsp[-5].minor.yy45 = yylhsminor.yy45;
         break;
-      case 123: /* let_func ::= ZVAL|OBJVAL|ARRVAL|PATHVAL|STRLEN|STRVAL|FLOATVAL|INTVAL|BOOLVAL|COUNT LPAREN impl_var RPAREN */
-#line 820 "src/parser_proc.y"
+      case 154: /* let_func ::= ZVAL|OBJVAL|ARRVAL|PATHVAL|STRLEN|STRVAL|FLOATVAL|INTVAL|BOOLVAL|COUNT LPAREN impl_var RPAREN */
+#line 959 "src/parser_proc.y"
 {
- yylhsminor.yy133 = psi_let_func_init(yymsp[-3].minor.yy0->type, yymsp[-3].minor.yy0->text, yymsp[-1].minor.yy123);
- yylhsminor.yy133->token = yymsp[-3].minor.yy0;
+ yylhsminor.yy67 = psi_let_func_init(yymsp[-3].minor.yy0->type, yymsp[-3].minor.yy0->text, yymsp[-1].minor.yy370);
+ yylhsminor.yy67->token = yymsp[-3].minor.yy0;
 }
-#line 3051 "src/parser_proc.c"
-  yy_destructor(yypParser,75,&yymsp[-2].minor);
-  yy_destructor(yypParser,77,&yymsp[0].minor);
-  yymsp[-3].minor.yy133 = yylhsminor.yy133;
+#line 3402 "src/parser_proc.c"
+  yy_destructor(yypParser,86,&yymsp[-2].minor);
+  yy_destructor(yypParser,87,&yymsp[0].minor);
+  yymsp[-3].minor.yy67 = yylhsminor.yy67;
         break;
-      case 124: /* let_func ::= ZVAL|OBJVAL|ARRVAL|PATHVAL|STRLEN|STRVAL|FLOATVAL|INTVAL|BOOLVAL|COUNT LPAREN impl_var COMMA let_exps RPAREN */
-#line 824 "src/parser_proc.y"
+      case 155: /* let_func ::= ZVAL|OBJVAL|ARRVAL|PATHVAL|STRLEN|STRVAL|FLOATVAL|INTVAL|BOOLVAL|COUNT LPAREN impl_var COMMA let_exps RPAREN */
+#line 963 "src/parser_proc.y"
 {
- yylhsminor.yy133 = psi_let_func_init(yymsp[-5].minor.yy0->type, yymsp[-5].minor.yy0->text, yymsp[-3].minor.yy123);
- yylhsminor.yy133->token = yymsp[-5].minor.yy0;
- yylhsminor.yy133->inner = yymsp[-1].minor.yy7;
+ yylhsminor.yy67 = psi_let_func_init(yymsp[-5].minor.yy0->type, yymsp[-5].minor.yy0->text, yymsp[-3].minor.yy370);
+ yylhsminor.yy67->token = yymsp[-5].minor.yy0;
+ yylhsminor.yy67->inner = yymsp[-1].minor.yy179;
 }
-#line 3063 "src/parser_proc.c"
-  yy_destructor(yypParser,75,&yymsp[-4].minor);
-  yy_destructor(yypParser,76,&yymsp[-2].minor);
-  yy_destructor(yypParser,77,&yymsp[0].minor);
-  yymsp[-5].minor.yy133 = yylhsminor.yy133;
+#line 3414 "src/parser_proc.c"
+  yy_destructor(yypParser,86,&yymsp[-4].minor);
+  yy_destructor(yypParser,88,&yymsp[-2].minor);
+  yy_destructor(yypParser,87,&yymsp[0].minor);
+  yymsp[-5].minor.yy67 = yylhsminor.yy67;
         break;
-      case 125: /* let_exps ::= let_exp */
-#line 829 "src/parser_proc.y"
+      case 156: /* let_exps ::= let_exp */
+#line 968 "src/parser_proc.y"
 {
- yylhsminor.yy7 = psi_plist_add(psi_plist_init((psi_plist_dtor) psi_let_exp_free),
-   &yymsp[0].minor.yy196);
+ yylhsminor.yy179 = psi_plist_add(psi_plist_init((psi_plist_dtor) psi_let_exp_free),
+   &yymsp[0].minor.yy200);
 }
-#line 3075 "src/parser_proc.c"
-  yymsp[0].minor.yy7 = yylhsminor.yy7;
+#line 3426 "src/parser_proc.c"
+  yymsp[0].minor.yy179 = yylhsminor.yy179;
         break;
-      case 126: /* let_exps ::= let_exps COMMA let_exp */
-#line 833 "src/parser_proc.y"
+      case 157: /* let_exps ::= let_exps COMMA let_exp */
+#line 972 "src/parser_proc.y"
 {
- yylhsminor.yy7 = psi_plist_add(yymsp[-2].minor.yy7, &yymsp[0].minor.yy196);
+ yylhsminor.yy179 = psi_plist_add(yymsp[-2].minor.yy179, &yymsp[0].minor.yy200);
 }
-#line 3083 "src/parser_proc.c"
-  yy_destructor(yypParser,76,&yymsp[-1].minor);
-  yymsp[-2].minor.yy7 = yylhsminor.yy7;
+#line 3434 "src/parser_proc.c"
+  yy_destructor(yypParser,88,&yymsp[-1].minor);
+  yymsp[-2].minor.yy179 = yylhsminor.yy179;
         break;
-      case 127: /* callback_arg_list ::= */
-#line 836 "src/parser_proc.y"
+      case 158: /* callback_arg_list ::= */
+#line 975 "src/parser_proc.y"
 {
- yymsp[1].minor.yy304 = NULL;
+ yymsp[1].minor.yy243 = NULL;
 }
-#line 3092 "src/parser_proc.c"
+#line 3443 "src/parser_proc.c"
         break;
-      case 128: /* callback_arg_list ::= callback_args */
-#line 839 "src/parser_proc.y"
+      case 159: /* callback_arg_list ::= callback_args */
+#line 978 "src/parser_proc.y"
 {
- yylhsminor.yy304 = yymsp[0].minor.yy304;
+ yylhsminor.yy243 = yymsp[0].minor.yy243;
 }
-#line 3099 "src/parser_proc.c"
-  yymsp[0].minor.yy304 = yylhsminor.yy304;
+#line 3450 "src/parser_proc.c"
+  yymsp[0].minor.yy243 = yylhsminor.yy243;
         break;
-      case 129: /* callback_args ::= set_exp */
-#line 842 "src/parser_proc.y"
+      case 160: /* callback_args ::= set_exp */
+#line 981 "src/parser_proc.y"
 {
- yylhsminor.yy304 = psi_plist_add(psi_plist_init((psi_plist_dtor) psi_set_exp_free),
-   &yymsp[0].minor.yy113);
+ yylhsminor.yy243 = psi_plist_add(psi_plist_init((psi_plist_dtor) psi_set_exp_free),
+   &yymsp[0].minor.yy180);
 }
-#line 3108 "src/parser_proc.c"
-  yymsp[0].minor.yy304 = yylhsminor.yy304;
+#line 3459 "src/parser_proc.c"
+  yymsp[0].minor.yy243 = yylhsminor.yy243;
         break;
-      case 130: /* callback_args ::= callback_args COMMA set_exp */
-#line 846 "src/parser_proc.y"
+      case 161: /* callback_args ::= callback_args COMMA set_exp */
+#line 985 "src/parser_proc.y"
 {
- yylhsminor.yy304 = psi_plist_add(yymsp[-2].minor.yy304, &yymsp[0].minor.yy113);
+ yylhsminor.yy243 = psi_plist_add(yymsp[-2].minor.yy243, &yymsp[0].minor.yy180);
 }
-#line 3116 "src/parser_proc.c"
-  yy_destructor(yypParser,76,&yymsp[-1].minor);
-  yymsp[-2].minor.yy304 = yylhsminor.yy304;
+#line 3467 "src/parser_proc.c"
+  yy_destructor(yypParser,88,&yymsp[-1].minor);
+  yymsp[-2].minor.yy243 = yylhsminor.yy243;
         break;
-      case 133: /* set_func ::= TO_OBJECT|TO_ARRAY|TO_STRING|TO_INT|TO_FLOAT|TO_BOOL|ZVAL|VOID LPAREN decl_var RPAREN */
-#line 855 "src/parser_proc.y"
+      case 164: /* set_func ::= TO_OBJECT|TO_ARRAY|TO_STRING|TO_INT|TO_FLOAT|TO_BOOL|ZVAL|VOID LPAREN decl_var RPAREN */
+#line 994 "src/parser_proc.y"
 {
- yylhsminor.yy324 = psi_set_func_init(yymsp[-3].minor.yy0->type, yymsp[-3].minor.yy0->text, yymsp[-1].minor.yy131);
- yylhsminor.yy324->token = yymsp[-3].minor.yy0;
+ yylhsminor.yy362 = psi_set_func_init(yymsp[-3].minor.yy0->type, yymsp[-3].minor.yy0->text, yymsp[-1].minor.yy271);
+ yylhsminor.yy362->token = yymsp[-3].minor.yy0;
 }
-#line 3126 "src/parser_proc.c"
-  yy_destructor(yypParser,75,&yymsp[-2].minor);
-  yy_destructor(yypParser,77,&yymsp[0].minor);
-  yymsp[-3].minor.yy324 = yylhsminor.yy324;
+#line 3477 "src/parser_proc.c"
+  yy_destructor(yypParser,86,&yymsp[-2].minor);
+  yy_destructor(yypParser,87,&yymsp[0].minor);
+  yymsp[-3].minor.yy362 = yylhsminor.yy362;
         break;
-      case 134: /* set_func ::= TO_OBJECT|TO_ARRAY|TO_STRING|TO_INT|TO_FLOAT|TO_BOOL|ZVAL|VOID LPAREN decl_var COMMA set_exps RPAREN */
-#line 859 "src/parser_proc.y"
+      case 165: /* set_func ::= TO_OBJECT|TO_ARRAY|TO_STRING|TO_INT|TO_FLOAT|TO_BOOL|ZVAL|VOID LPAREN decl_var COMMA set_exps RPAREN */
+#line 998 "src/parser_proc.y"
 {
- yylhsminor.yy324 = psi_set_func_init(yymsp[-5].minor.yy0->type, yymsp[-5].minor.yy0->text, yymsp[-3].minor.yy131);
- yylhsminor.yy324->token = yymsp[-5].minor.yy0;
- yylhsminor.yy324->inner = yymsp[-1].minor.yy7;
+ yylhsminor.yy362 = psi_set_func_init(yymsp[-5].minor.yy0->type, yymsp[-5].minor.yy0->text, yymsp[-3].minor.yy271);
+ yylhsminor.yy362->token = yymsp[-5].minor.yy0;
+ yylhsminor.yy362->inner = yymsp[-1].minor.yy179;
 }
-#line 3138 "src/parser_proc.c"
-  yy_destructor(yypParser,75,&yymsp[-4].minor);
-  yy_destructor(yypParser,76,&yymsp[-2].minor);
-  yy_destructor(yypParser,77,&yymsp[0].minor);
-  yymsp[-5].minor.yy324 = yylhsminor.yy324;
+#line 3489 "src/parser_proc.c"
+  yy_destructor(yypParser,86,&yymsp[-4].minor);
+  yy_destructor(yypParser,88,&yymsp[-2].minor);
+  yy_destructor(yypParser,87,&yymsp[0].minor);
+  yymsp[-5].minor.yy362 = yylhsminor.yy362;
         break;
-      case 135: /* set_func ::= TO_OBJECT|TO_ARRAY|TO_STRING|TO_INT|TO_FLOAT|TO_BOOL|ZVAL|VOID LPAREN decl_var COMMA ELLIPSIS RPAREN */
-#line 864 "src/parser_proc.y"
+      case 166: /* set_func ::= TO_OBJECT|TO_ARRAY|TO_STRING|TO_INT|TO_FLOAT|TO_BOOL|ZVAL|VOID LPAREN decl_var COMMA ELLIPSIS RPAREN */
+#line 1003 "src/parser_proc.y"
 {
- yylhsminor.yy324 = psi_set_func_init(yymsp[-5].minor.yy0->type, yymsp[-5].minor.yy0->text, yymsp[-3].minor.yy131);
- yylhsminor.yy324->token = yymsp[-5].minor.yy0;
- yylhsminor.yy324->recursive = 1;
+ yylhsminor.yy362 = psi_set_func_init(yymsp[-5].minor.yy0->type, yymsp[-5].minor.yy0->text, yymsp[-3].minor.yy271);
+ yylhsminor.yy362->token = yymsp[-5].minor.yy0;
+ yylhsminor.yy362->recursive = 1;
 }
-#line 3151 "src/parser_proc.c"
-  yy_destructor(yypParser,75,&yymsp[-4].minor);
-  yy_destructor(yypParser,76,&yymsp[-2].minor);
-  yy_destructor(yypParser,86,&yymsp[-1].minor);
-  yy_destructor(yypParser,77,&yymsp[0].minor);
-  yymsp[-5].minor.yy324 = yylhsminor.yy324;
+#line 3502 "src/parser_proc.c"
+  yy_destructor(yypParser,86,&yymsp[-4].minor);
+  yy_destructor(yypParser,88,&yymsp[-2].minor);
+  yy_destructor(yypParser,101,&yymsp[-1].minor);
+  yy_destructor(yypParser,87,&yymsp[0].minor);
+  yymsp[-5].minor.yy362 = yylhsminor.yy362;
         break;
-      case 136: /* set_exp ::= set_func */
-#line 869 "src/parser_proc.y"
+      case 167: /* set_exp ::= set_func */
+#line 1008 "src/parser_proc.y"
 {
- yylhsminor.yy113 = psi_set_exp_init(PSI_SET_FUNC, yymsp[0].minor.yy324);
+ yylhsminor.yy180 = psi_set_exp_init(PSI_SET_FUNC, yymsp[0].minor.yy362);
 }
-#line 3163 "src/parser_proc.c"
-  yymsp[0].minor.yy113 = yylhsminor.yy113;
+#line 3514 "src/parser_proc.c"
+  yymsp[0].minor.yy180 = yylhsminor.yy180;
         break;
-      case 137: /* set_exp ::= num_exp */
-#line 872 "src/parser_proc.y"
+      case 168: /* set_exp ::= num_exp */
+#line 1011 "src/parser_proc.y"
 {
- yylhsminor.yy113 = psi_set_exp_init(PSI_SET_NUMEXP, yymsp[0].minor.yy124);
+ yylhsminor.yy180 = psi_set_exp_init(PSI_SET_NUMEXP, yymsp[0].minor.yy207);
 }
-#line 3171 "src/parser_proc.c"
-  yymsp[0].minor.yy113 = yylhsminor.yy113;
+#line 3522 "src/parser_proc.c"
+  yymsp[0].minor.yy180 = yylhsminor.yy180;
         break;
-      case 138: /* set_exps ::= set_exp */
-#line 875 "src/parser_proc.y"
+      case 169: /* set_exps ::= set_exp */
+#line 1014 "src/parser_proc.y"
 {
- yylhsminor.yy7 = psi_plist_add(psi_plist_init((psi_plist_dtor) psi_set_exp_free),
-   &yymsp[0].minor.yy113);
+ yylhsminor.yy179 = psi_plist_add(psi_plist_init((psi_plist_dtor) psi_set_exp_free),
+   &yymsp[0].minor.yy180);
 }
-#line 3180 "src/parser_proc.c"
-  yymsp[0].minor.yy7 = yylhsminor.yy7;
+#line 3531 "src/parser_proc.c"
+  yymsp[0].minor.yy179 = yylhsminor.yy179;
         break;
-      case 139: /* set_exps ::= set_exps COMMA set_exp */
-#line 879 "src/parser_proc.y"
+      case 170: /* set_exps ::= set_exps COMMA set_exp */
+#line 1018 "src/parser_proc.y"
 {
- yylhsminor.yy7 = psi_plist_add(yymsp[-2].minor.yy7, &yymsp[0].minor.yy113);
+ yylhsminor.yy179 = psi_plist_add(yymsp[-2].minor.yy179, &yymsp[0].minor.yy180);
 }
-#line 3188 "src/parser_proc.c"
-  yy_destructor(yypParser,76,&yymsp[-1].minor);
-  yymsp[-2].minor.yy7 = yylhsminor.yy7;
+#line 3539 "src/parser_proc.c"
+  yy_destructor(yypParser,88,&yymsp[-1].minor);
+  yymsp[-2].minor.yy179 = yylhsminor.yy179;
         break;
-      case 140: /* set_exp ::= impl_var EQUALS set_exp */
-#line 882 "src/parser_proc.y"
+      case 171: /* set_exp ::= impl_var EQUALS set_exp */
+#line 1021 "src/parser_proc.y"
 {
- yylhsminor.yy113 = yymsp[0].minor.yy113;
- yylhsminor.yy113->var = yymsp[-2].minor.yy123;
+ yylhsminor.yy180 = yymsp[0].minor.yy180;
+ yylhsminor.yy180->var = yymsp[-2].minor.yy370;
 }
-#line 3198 "src/parser_proc.c"
-  yy_destructor(yypParser,83,&yymsp[-1].minor);
-  yymsp[-2].minor.yy113 = yylhsminor.yy113;
+#line 3549 "src/parser_proc.c"
+  yy_destructor(yypParser,98,&yymsp[-1].minor);
+  yymsp[-2].minor.yy180 = yylhsminor.yy180;
         break;
-      case 141: /* set_stmt ::= SET set_exp EOS */
-#line 886 "src/parser_proc.y"
+      case 172: /* set_stmt ::= SET set_exp EOS */
+#line 1025 "src/parser_proc.y"
 {
- yylhsminor.yy300 = psi_set_stmt_init(yymsp[-1].minor.yy113);
- yylhsminor.yy300->token = yymsp[-2].minor.yy0;
+ yylhsminor.yy358 = psi_set_stmt_init(yymsp[-1].minor.yy180);
+ yylhsminor.yy358->token = yymsp[-2].minor.yy0;
 }
-#line 3208 "src/parser_proc.c"
-  yy_destructor(yypParser,73,&yymsp[0].minor);
-  yymsp[-2].minor.yy300 = yylhsminor.yy300;
+#line 3559 "src/parser_proc.c"
+  yy_destructor(yypParser,75,&yymsp[0].minor);
+  yymsp[-2].minor.yy358 = yylhsminor.yy358;
         break;
-      case 142: /* return_stmt ::= RETURN set_func EOS */
-#line 890 "src/parser_proc.y"
+      case 173: /* return_stmt ::= RETURN set_func EOS */
+#line 1029 "src/parser_proc.y"
 {
- yylhsminor.yy258 = psi_return_stmt_init(psi_set_exp_init(PSI_SET_FUNC, yymsp[-1].minor.yy324));
- yylhsminor.yy258->token = yymsp[-2].minor.yy0;
+ yylhsminor.yy342 = psi_return_stmt_init(psi_set_exp_init(PSI_SET_FUNC, yymsp[-1].minor.yy362));
+ yylhsminor.yy342->token = yymsp[-2].minor.yy0;
 }
-#line 3218 "src/parser_proc.c"
-  yy_destructor(yypParser,73,&yymsp[0].minor);
-  yymsp[-2].minor.yy258 = yylhsminor.yy258;
+#line 3569 "src/parser_proc.c"
+  yy_destructor(yypParser,75,&yymsp[0].minor);
+  yymsp[-2].minor.yy342 = yylhsminor.yy342;
         break;
-      case 143: /* free_stmt ::= FREE free_exps EOS */
-#line 894 "src/parser_proc.y"
+      case 174: /* free_stmt ::= FREE free_exps EOS */
+#line 1033 "src/parser_proc.y"
 {
- yylhsminor.yy102 = psi_free_stmt_init(yymsp[-1].minor.yy7);
- yylhsminor.yy102->token = yymsp[-2].minor.yy0;
+ yylhsminor.yy220 = psi_free_stmt_init(yymsp[-1].minor.yy179);
+ yylhsminor.yy220->token = yymsp[-2].minor.yy0;
 }
-#line 3228 "src/parser_proc.c"
-  yy_destructor(yypParser,73,&yymsp[0].minor);
-  yymsp[-2].minor.yy102 = yylhsminor.yy102;
+#line 3579 "src/parser_proc.c"
+  yy_destructor(yypParser,75,&yymsp[0].minor);
+  yymsp[-2].minor.yy220 = yylhsminor.yy220;
         break;
-      case 144: /* free_exps ::= free_exp */
-#line 898 "src/parser_proc.y"
+      case 175: /* free_exps ::= free_exp */
+#line 1037 "src/parser_proc.y"
 {
- yylhsminor.yy7 = psi_plist_add(psi_plist_init((psi_plist_dtor) psi_free_exp_free),
-   &yymsp[0].minor.yy114);
+ yylhsminor.yy179 = psi_plist_add(psi_plist_init((psi_plist_dtor) psi_free_exp_free),
+   &yymsp[0].minor.yy146);
 }
-#line 3238 "src/parser_proc.c"
-  yymsp[0].minor.yy7 = yylhsminor.yy7;
+#line 3589 "src/parser_proc.c"
+  yymsp[0].minor.yy179 = yylhsminor.yy179;
         break;
-      case 145: /* free_exps ::= free_exps COMMA free_exp */
-#line 902 "src/parser_proc.y"
+      case 176: /* free_exps ::= free_exps COMMA free_exp */
+#line 1041 "src/parser_proc.y"
 {
- yylhsminor.yy7 = psi_plist_add(yymsp[-2].minor.yy7, &yymsp[0].minor.yy114);
+ yylhsminor.yy179 = psi_plist_add(yymsp[-2].minor.yy179, &yymsp[0].minor.yy146);
 }
-#line 3246 "src/parser_proc.c"
-  yy_destructor(yypParser,76,&yymsp[-1].minor);
-  yymsp[-2].minor.yy7 = yylhsminor.yy7;
+#line 3597 "src/parser_proc.c"
+  yy_destructor(yypParser,88,&yymsp[-1].minor);
+  yymsp[-2].minor.yy179 = yylhsminor.yy179;
         break;
-      case 146: /* free_exp ::= NAME LPAREN decl_vars RPAREN */
-#line 905 "src/parser_proc.y"
+      case 177: /* free_exp ::= NAME LPAREN decl_vars RPAREN */
+#line 1044 "src/parser_proc.y"
 {
- yylhsminor.yy114 = psi_free_exp_init(yymsp[-3].minor.yy0->text, yymsp[-1].minor.yy7);
- yylhsminor.yy114->token = yymsp[-3].minor.yy0;
+ yylhsminor.yy146 = psi_free_exp_init(yymsp[-3].minor.yy0->text, yymsp[-1].minor.yy179);
+ yylhsminor.yy146->token = yymsp[-3].minor.yy0;
 }
-#line 3256 "src/parser_proc.c"
-  yy_destructor(yypParser,75,&yymsp[-2].minor);
-  yy_destructor(yypParser,77,&yymsp[0].minor);
-  yymsp[-3].minor.yy114 = yylhsminor.yy114;
+#line 3607 "src/parser_proc.c"
+  yy_destructor(yypParser,86,&yymsp[-2].minor);
+  yy_destructor(yypParser,87,&yymsp[0].minor);
+  yymsp[-3].minor.yy146 = yylhsminor.yy146;
         break;
-      case 147: /* assert_stmt ::= PRE_ASSERT|POST_ASSERT num_exp EOS */
-#line 909 "src/parser_proc.y"
+      case 178: /* assert_stmt ::= PRE_ASSERT|POST_ASSERT num_exp EOS */
+#line 1048 "src/parser_proc.y"
 {
- yylhsminor.yy146 = psi_assert_stmt_init(yymsp[-2].minor.yy0->type, yymsp[-1].minor.yy124);
- yylhsminor.yy146->token = yymsp[-2].minor.yy0;
+ yylhsminor.yy201 = psi_assert_stmt_init(yymsp[-2].minor.yy0->type, yymsp[-1].minor.yy207);
+ yylhsminor.yy201->token = yymsp[-2].minor.yy0;
 }
-#line 3267 "src/parser_proc.c"
-  yy_destructor(yypParser,73,&yymsp[0].minor);
-  yymsp[-2].minor.yy146 = yylhsminor.yy146;
+#line 3618 "src/parser_proc.c"
+  yy_destructor(yypParser,75,&yymsp[0].minor);
+  yymsp[-2].minor.yy201 = yylhsminor.yy201;
         break;
-      case 148: /* reference ::= */
-#line 913 "src/parser_proc.y"
+      case 179: /* reference ::= */
+#line 1052 "src/parser_proc.y"
 {
- yymsp[1].minor.yy247 = false;
+ yymsp[1].minor.yy89 = false;
 }
-#line 3276 "src/parser_proc.c"
+#line 3627 "src/parser_proc.c"
         break;
-      case 149: /* reference ::= AMPERSAND */
+      case 180: /* reference ::= AMPERSAND */
 {  yy_destructor(yypParser,23,&yymsp[0].minor);
-#line 916 "src/parser_proc.y"
+#line 1055 "src/parser_proc.y"
 {
- yymsp[0].minor.yy247 = true;
+ yymsp[0].minor.yy89 = true;
 }
-#line 3284 "src/parser_proc.c"
+#line 3635 "src/parser_proc.c"
 }
         break;
-      case 150: /* indirection ::= */
-#line 919 "src/parser_proc.y"
+      case 181: /* indirection ::= */
+#line 1058 "src/parser_proc.y"
 {
- yymsp[1].minor.yy296 = 0;
+ yymsp[1].minor.yy382 = 0;
 }
-#line 3292 "src/parser_proc.c"
+#line 3643 "src/parser_proc.c"
         break;
-      case 151: /* indirection ::= pointers */
-#line 922 "src/parser_proc.y"
+      case 182: /* indirection ::= pointers */
+#line 1061 "src/parser_proc.y"
 {
- yylhsminor.yy296 = yymsp[0].minor.yy296;
+ yylhsminor.yy382 = yymsp[0].minor.yy382;
 }
-#line 3299 "src/parser_proc.c"
-  yymsp[0].minor.yy296 = yylhsminor.yy296;
+#line 3650 "src/parser_proc.c"
+  yymsp[0].minor.yy382 = yylhsminor.yy382;
         break;
-      case 152: /* pointers ::= ASTERISK */
+      case 183: /* pointers ::= ASTERISK */
 {  yy_destructor(yypParser,28,&yymsp[0].minor);
-#line 925 "src/parser_proc.y"
+#line 1064 "src/parser_proc.y"
 {
- yymsp[0].minor.yy296 = 1;
+ yymsp[0].minor.yy382 = 1;
 }
-#line 3308 "src/parser_proc.c"
+#line 3659 "src/parser_proc.c"
 }
         break;
-      case 153: /* pointers ::= pointers ASTERISK */
-#line 928 "src/parser_proc.y"
+      case 184: /* pointers ::= pointers ASTERISK */
+#line 1067 "src/parser_proc.y"
 {
- yylhsminor.yy296 = yymsp[-1].minor.yy296+1;
+ yylhsminor.yy382 = yymsp[-1].minor.yy382+1;
 }
-#line 3316 "src/parser_proc.c"
+#line 3667 "src/parser_proc.c"
   yy_destructor(yypParser,28,&yymsp[0].minor);
-  yymsp[-1].minor.yy296 = yylhsminor.yy296;
+  yymsp[-1].minor.yy382 = yylhsminor.yy382;
         break;
-      case 154: /* file ::= blocks */
-{  yy_destructor(yypParser,157,&yymsp[0].minor);
-#line 175 "src/parser_proc.y"
+      case 185: /* file ::= blocks */
+{  yy_destructor(yypParser,180,&yymsp[0].minor);
+#line 193 "src/parser_proc.y"
 {
 }
-#line 3325 "src/parser_proc.c"
+#line 3676 "src/parser_proc.c"
 }
         break;
-      case 155: /* blocks ::= block */
-{  yy_destructor(yypParser,158,&yymsp[0].minor);
-#line 176 "src/parser_proc.y"
+      case 186: /* blocks ::= block */
+{  yy_destructor(yypParser,181,&yymsp[0].minor);
+#line 194 "src/parser_proc.y"
 {
 }
-#line 3333 "src/parser_proc.c"
+#line 3684 "src/parser_proc.c"
 }
         break;
-      case 156: /* blocks ::= blocks block */
-{  yy_destructor(yypParser,157,&yymsp[-1].minor);
-#line 177 "src/parser_proc.y"
+      case 187: /* blocks ::= blocks block */
+{  yy_destructor(yypParser,180,&yymsp[-1].minor);
+#line 195 "src/parser_proc.y"
+{
+}
+#line 3692 "src/parser_proc.c"
+  yy_destructor(yypParser,181,&yymsp[0].minor);
+}
+        break;
+      case 188: /* block ::= EOS */
+{  yy_destructor(yypParser,75,&yymsp[0].minor);
+#line 196 "src/parser_proc.y"
 {
 }
-#line 3341 "src/parser_proc.c"
-  yy_destructor(yypParser,158,&yymsp[0].minor);
+#line 3701 "src/parser_proc.c"
 }
         break;
-      case 157: /* block ::= EOF */
-{  yy_destructor(yypParser,72,&yymsp[0].minor);
-#line 178 "src/parser_proc.y"
+      case 189: /* block ::= EOL */
+{  yy_destructor(yypParser,76,&yymsp[0].minor);
+#line 197 "src/parser_proc.y"
 {
 }
-#line 3350 "src/parser_proc.c"
+#line 3709 "src/parser_proc.c"
 }
         break;
-      case 158: /* block ::= EOS */
-{  yy_destructor(yypParser,73,&yymsp[0].minor);
-#line 179 "src/parser_proc.y"
+      case 190: /* block ::= COMMENT */
+{  yy_destructor(yypParser,77,&yymsp[0].minor);
+#line 198 "src/parser_proc.y"
 {
 }
-#line 3358 "src/parser_proc.c"
+#line 3717 "src/parser_proc.c"
 }
         break;
       default:
@@ -3415,8 +3774,8 @@ static void yy_syntax_error(
 #define TOKEN yyminor
 /************ Begin %syntax_error code ****************************************/
 #line 40 "src/parser_proc.y"
- ++P->errors; if (TOKEN && TOKEN->type != PSI_T_EOF) { psi_error(PSI_WARNING, TOKEN->file, TOKEN->line, "PSI syntax error: Unexpected token '%s' at pos %u", TOKEN->text, TOKEN->col); } else { psi_error(PSI_WARNING, P->file.fn, P->line, "PSI syntax error: Unexpected end of input"); } 
-#line 3420 "src/parser_proc.c"
+ ++P->errors; if (TOKEN) { psi_error(PSI_WARNING, TOKEN->file, TOKEN->line, "PSI syntax error: Unexpected token '%s' at pos %u", TOKEN->text, TOKEN->col); } else { psi_error(PSI_WARNING, P->file.fn, P->line, "PSI syntax error: Unexpected end of input"); } 
+#line 3779 "src/parser_proc.c"
 /************ End %syntax_error code ******************************************/
   ParseARG_STORE; /* Suppress warning about unused %extra_argument variable */
 }
index 0da603695f09d61d3cf053c32342fed81be6c6de..1adda480d00c4e550063eff19403570e8a565713 100644 (file)
 #define PSI_T_CALLABLE                        61
 #define PSI_T_PRE_ASSERT                      62
 #define PSI_T_POST_ASSERT                     63
-#define PSI_T_TEMP                            64
-#define PSI_T_FREE                            65
-#define PSI_T_SET                             66
-#define PSI_T_LET                             67
-#define PSI_T_RETURN                          68
-#define PSI_T_CALLOC                          69
-#define PSI_T_CALLBACK                        70
-#define PSI_T_LIB                             71
-#define PSI_T_EOF                             72
-#define PSI_T_EOS                             73
-#define PSI_T_COLON                           74
-#define PSI_T_LPAREN                          75
-#define PSI_T_COMMA                           76
-#define PSI_T_RPAREN                          77
-#define PSI_T_ENUM                            78
-#define PSI_T_STRUCT                          79
-#define PSI_T_UNION                           80
-#define PSI_T_LBRACE                          81
-#define PSI_T_RBRACE                          82
-#define PSI_T_EQUALS                          83
-#define PSI_T_CONST                           84
-#define PSI_T_TYPEDEF                         85
-#define PSI_T_ELLIPSIS                        86
-#define PSI_T_LBRACKET                        87
-#define PSI_T_RBRACKET                        88
-#define PSI_T_CHAR                            89
-#define PSI_T_SHORT                           90
-#define PSI_T_LONG                            91
-#define PSI_T_UNSIGNED                        92
-#define PSI_T_SIGNED                          93
-#define PSI_T_STATIC                          94
-#define PSI_T_FUNCTION                        95
-#define PSI_T_DOLLAR_NAME                     96
+#define PSI_T_ERROR                           64
+#define PSI_T_WARNING                         65
+#define PSI_T_TEMP                            66
+#define PSI_T_FREE                            67
+#define PSI_T_SET                             68
+#define PSI_T_LET                             69
+#define PSI_T_RETURN                          70
+#define PSI_T_CALLOC                          71
+#define PSI_T_CALLBACK                        72
+#define PSI_T_LIB                             73
+#define PSI_T_ANY                             74
+#define PSI_T_EOS                             75
+#define PSI_T_EOL                             76
+#define PSI_T_COMMENT                         77
+#define PSI_T_HASH                            78
+#define PSI_T_IFDEF                           79
+#define PSI_T_IFNDEF                          80
+#define PSI_T_ENDIF                           81
+#define PSI_T_ELSE                            82
+#define PSI_T_UNDEF                           83
+#define PSI_T_DEFINE                          84
+#define PSI_T_NO_WHITESPACE                   85
+#define PSI_T_LPAREN                          86
+#define PSI_T_RPAREN                          87
+#define PSI_T_COMMA                           88
+#define PSI_T_IF                              89
+#define PSI_T_ELIF                            90
+#define PSI_T_DEFINED                         91
+#define PSI_T_COLON                           92
+#define PSI_T_ENUM                            93
+#define PSI_T_STRUCT                          94
+#define PSI_T_UNION                           95
+#define PSI_T_LBRACE                          96
+#define PSI_T_RBRACE                          97
+#define PSI_T_EQUALS                          98
+#define PSI_T_CONST                           99
+#define PSI_T_TYPEDEF                        100
+#define PSI_T_ELLIPSIS                       101
+#define PSI_T_LBRACKET                       102
+#define PSI_T_RBRACKET                       103
+#define PSI_T_CHAR                           104
+#define PSI_T_SHORT                          105
+#define PSI_T_LONG                           106
+#define PSI_T_UNSIGNED                       107
+#define PSI_T_SIGNED                         108
+#define PSI_T_STATIC                         109
+#define PSI_T_FUNCTION                       110
+#define PSI_T_DOLLAR_NAME                    111
index 8c6018fc4d3f784ab1fc41d7a8e86dcb96325274..4dab6c9cd72cf613bc22f98451b364eead419e75 100644 (file)
@@ -37,7 +37,7 @@ void psi_parser_proc_free(void **parser_proc)
 %token_destructor {free($$);}
 %default_destructor {(void)P;}
 %extra_argument {struct psi_parser *P}
-%syntax_error { ++P->errors; if (TOKEN && TOKEN->type != PSI_T_EOF) { psi_error(PSI_WARNING, TOKEN->file, TOKEN->line, "PSI syntax error: Unexpected token '%s' at pos %u", TOKEN->text, TOKEN->col); } else { psi_error(PSI_WARNING, P->file.fn, P->line, "PSI syntax error: Unexpected end of input"); } }
+%syntax_error { ++P->errors; if (TOKEN) { psi_error(PSI_WARNING, TOKEN->file, TOKEN->line, "PSI syntax error: Unexpected token '%s' at pos %u", TOKEN->text, TOKEN->col); } else { psi_error(PSI_WARNING, P->file.fn, P->line, "PSI syntax error: Unexpected end of input"); } }
 %token_class const_type_token BOOL INT FLOAT STRING .
 %token_class decl_type_token FLOAT DOUBLE INT8 UINT8 INT16 UINT16 INT32 UINT32 INT64 UINT64 NAME .
 %token_class impl_def_val_token NULL NUMBER TRUE FALSE QUOTED_STRING .
@@ -48,6 +48,7 @@ void psi_parser_proc_free(void **parser_proc)
 %token_class set_func_token TO_OBJECT TO_ARRAY TO_STRING TO_INT TO_FLOAT TO_BOOL ZVAL VOID .
 %token_class impl_type_token VOID MIXED BOOL INT FLOAT STRING ARRAY OBJECT CALLABLE .
 %token_class assert_stmt_token PRE_ASSERT POST_ASSERT .
+%token_class cpp_message_token ERROR WARNING .
 %nonassoc NAME.
 %right NOT TILDE.
 %left AND OR.
@@ -60,6 +61,7 @@ void psi_parser_proc_free(void **parser_proc)
 %left PLUS MINUS.
 %left ASTERISK SLASH MODULO.
 %fallback NAME TEMP FREE SET LET RETURN CALLOC CALLBACK ZVAL LIB STRING COUNT.
+%wildcard ANY.
 %type decl_enum {struct psi_decl_enum *}
 %destructor decl_enum {psi_decl_enum_free(&$$);}
 %type decl_enum_items {struct psi_plist*}
@@ -169,14 +171,151 @@ void psi_parser_proc_free(void **parser_proc)
 %destructor free_exp {psi_free_exp_free(&$$);}
 %type impl_type {struct psi_impl_type*}
 %destructor impl_type {psi_impl_type_free(&$$);}
+%type cpp_exp {struct psi_cpp_exp*}
+%destructor cpp_exp {psi_cpp_exp_free(&$$);}
+%type cpp_macro_decl {struct psi_cpp_macro_decl*}
+%destructor cpp_macro_decl {psi_cpp_macro_decl_free(&$$);}
+%type cpp_macro_decl_tokens {struct psi_plist*}
+%destructor cpp_macro_decl_tokens {psi_plist_free($$);}
+%type cpp_macro_exp {struct psi_num_exp*}
+%destructor cpp_macro_exp {psi_num_exp_free(&$$);}
+%type cpp_macro_sig {struct psi_plist*}
+%destructor cpp_macro_sig {psi_plist_free($$);}
+%type cpp_macro_sig_args {struct psi_plist*}
+%destructor cpp_macro_sig_args {psi_plist_free($$);}
+%type cpp_macro_call {struct psi_plist*}
+%destructor cpp_macro_call {psi_plist_free($$);}
+%type cpp_macro_call_args {struct psi_plist*}
+%destructor cpp_macro_call_args {psi_plist_free($$);}
 %type reference {bool}
 %type indirection {unsigned}
 %type pointers {unsigned}
 file ::= blocks.
 blocks ::= block.
 blocks ::= blocks block.
-block ::= EOF.
 block ::= EOS.
+block ::= EOL.
+block ::= COMMENT.
+block ::= HASH cpp_exp(exp_) EOL. {
+ P->cpp.exp = exp_;
+}
+cpp_exp(exp) ::= cpp_message_token(T) QUOTED_STRING(S). {
+ exp = psi_cpp_exp_init(T->type, S);
+ exp->token = T;
+}
+cpp_exp(exp) ::= IFDEF(T) NAME(N). {
+ exp = psi_cpp_exp_init(T->type, N);
+ exp->token = T;
+}
+cpp_exp(exp) ::= IFNDEF(T) NAME(N). {
+ exp = psi_cpp_exp_init(T->type, N);
+ exp->token = T;
+}
+cpp_exp(exp) ::= ENDIF(T). {
+ exp = psi_cpp_exp_init(T->type, NULL);
+ exp->token = T;
+}
+cpp_exp(exp) ::= ELSE(T). {
+ exp = psi_cpp_exp_init(T->type, NULL);
+ exp->token = T;
+}
+cpp_exp(exp) ::= UNDEF(T) NAME(N). {
+ exp = psi_cpp_exp_init(T->type, N);
+ exp->token = T;
+}
+cpp_exp(exp) ::= DEFINE(T) NAME(N) cpp_macro_decl(macro). {
+ exp = psi_cpp_exp_init(T->type, macro);
+ exp->token = T;
+ macro->token = N;
+}
+cpp_macro_decl(macro) ::= . {
+ macro = psi_cpp_macro_decl_init(NULL, NULL, NULL);
+}
+cpp_macro_decl(macro) ::= cpp_macro_sig(sig). {
+ macro = psi_cpp_macro_decl_init(sig, NULL, NULL);
+}
+cpp_macro_decl(macro) ::= cpp_macro_sig(sig) cpp_macro_decl_tokens(tokens). {
+ macro = psi_cpp_macro_decl_init(sig, tokens, NULL);
+}
+cpp_macro_sig(sig) ::= NO_WHITESPACE LPAREN cpp_macro_sig_args(args) RPAREN. {
+ sig = args;
+}
+cpp_macro_sig_args(args) ::= . {
+ args = NULL;
+}
+cpp_macro_sig_args(args) ::= NAME(arg). {
+ args = psi_plist_add(psi_plist_init((void (*)(void *)) psi_token_free), &arg);
+}
+cpp_macro_sig_args(args) ::= cpp_macro_sig_args(args_) COMMA NAME(arg). {
+ args = psi_plist_add(args_, &arg);
+}
+cpp_macro_decl(macro) ::= cpp_macro_decl_tokens(tokens). {
+ macro = psi_cpp_macro_decl_init(NULL, tokens, NULL);
+}
+cpp_macro_decl_tokens(tokens) ::= ANY(T). {
+ tokens = psi_plist_add(psi_plist_init((void (*)(void *)) psi_token_free), &T);
+}
+cpp_macro_decl_tokens(tokens) ::= cpp_macro_decl_tokens(tokens_) ANY(T). {
+ tokens = psi_plist_add(tokens_, &T);
+}
+cpp_exp(exp) ::= IF(T) cpp_macro_exp(macro). {
+ exp = psi_cpp_exp_init(T->type, macro);
+ exp->token = T;
+}
+cpp_exp(exp) ::= ELIF(T) cpp_macro_exp(macro). {
+ exp = psi_cpp_exp_init(T->type, macro);
+ exp->token = T;
+}
+cpp_macro_exp(exp) ::= LPAREN(L) cpp_macro_exp(exp_) RPAREN. {
+ exp = psi_num_exp_init_unary(L->type, exp_);
+ exp->token = L;
+}
+cpp_macro_exp(exp) ::= unary_op_token(OP) cpp_macro_exp(exp_). {
+ exp = psi_num_exp_init_unary(OP->type, exp_);
+ exp->token = OP;
+}
+cpp_macro_exp(exp) ::= cpp_macro_exp(lhs) binary_op_token(OP) cpp_macro_exp(rhs). {
+ exp = psi_num_exp_init_binary(OP->type, lhs, rhs);
+ exp->token = OP;
+}
+cpp_macro_exp(exp) ::= DEFINED NAME(N). {
+ {
+  uint8_t exists = zend_hash_str_exists(&P->cpp.defs, N->text, N->size);
+  exp = psi_num_exp_init_num(psi_number_init(PSI_T_UINT8, &exists));
+  exp->token = N;
+ }
+}
+cpp_macro_exp(exp) ::= DEFINED LPAREN NAME(N) RPAREN. {
+ {
+  uint8_t exists = zend_hash_str_exists(&P->cpp.defs, N->text, N->size);
+  exp = psi_num_exp_init_num(psi_number_init(PSI_T_UINT8, &exists));
+  exp->token = N;
+ }
+}
+cpp_macro_exp(exp) ::= number_token(tok). {
+ exp = psi_num_exp_init_num(psi_number_init(tok->type, tok->text));
+ exp->token = tok;
+ exp->data.n->token = psi_token_copy(tok);
+}
+cpp_macro_exp(exp) ::= NAME(N). {
+ exp = psi_num_exp_init_num(psi_number_init(PSI_T_DEFINE, N->text));
+ exp->token = N;
+ exp->data.n->token = psi_token_copy(N);
+}
+cpp_macro_exp(exp) ::= NAME(N) LPAREN cpp_macro_call_args(args) RPAREN. {
+ exp = psi_num_exp_init_num(psi_number_init(PSI_T_FUNCTION,
+   psi_cpp_macro_call_init(N->text, args)));
+ exp->token = N;
+}
+cpp_macro_call_args(args) ::= . {
+ args = NULL;
+}
+cpp_macro_call_args(args) ::= cpp_macro_exp(arg). {
+ args = psi_plist_add(psi_plist_init((void (*)(void *)) psi_num_exp_free), &arg);
+}
+cpp_macro_call_args(args) ::= cpp_macro_call_args(args_) COMMA cpp_macro_exp(arg). {
+ args = psi_plist_add(args_, &arg);
+}
 block ::= LIB(token) QUOTED_STRING(libname) EOS. {
  if (P->file.ln) {
   P->error(PSI_DATA(P), token, PSI_WARNING, "Extra 'lib %s' statement has no effect", libname->text);
diff --git a/src/parser_proc_def.h b/src/parser_proc_def.h
new file mode 100644 (file)
index 0000000..bee1bc4
--- /dev/null
@@ -0,0 +1,2218 @@
+/*******************************************************************************
+ Copyright (c) 2016, Michael Wallner <mike@php.net>.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+     * Redistributions of source code must retain the above copyright notice,
+       this list of conditions and the following disclaimer.
+     * Redistributions in binary form must reproduce the above copyright
+       notice, this list of conditions and the following disclaimer in the
+       documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+#include "parser_def.h"
+
+DEF(%token_prefix, CONCAT1(TOKEN_PREFIX,_))
+DEF(%token_type, {TOKEN_STRUCT})
+DEF(%token_destructor, {free($$);})
+DEF(%default_destructor, {(void)P;})
+DEF(%extra_argument, {struct psi_parser *P})
+
+/* TOKEN is defined inside syntax_error */
+DEF(%syntax_error, {
+       ++P->errors;
+       if (TOKEN) {
+               psi_error(PSI_WARNING, TOKEN->file, TOKEN->line, "PSI syntax error: Unexpected token '%s' at pos %u", TOKEN->text, TOKEN->col);
+       } else {
+               psi_error(PSI_WARNING, P->file.fn, P->line, "PSI syntax error: Unexpected end of input");
+       }
+})
+
+TOKEN_CLASS(const_type, T(BOOL) T(INT) T(FLOAT) T(STRING))
+TOKEN_CLASS(decl_type, T(FLOAT) T(DOUBLE) T(INT8) T(UINT8) T(INT16) T(UINT16) T(INT32) T(UINT32) T(INT64) T(UINT64) T(NAME))
+TOKEN_CLASS(impl_def_val, T(NULL) T(NUMBER) T(TRUE) T(FALSE) T(QUOTED_STRING))
+TOKEN_CLASS(number, T(NUMBER) T(NSNAME))
+TOKEN_CLASS(binary_op, T(PIPE) T(CARET) T(AMPERSAND) T(LSHIFT) T(RSHIFT) T(PLUS) T(MINUS) T(ASTERISK) T(SLASH) T(MODULO) T(RCHEVR) T(LCHEVR) T(CMP_GE) T(CMP_LE) T(OR) T(AND) T(CMP_EQ) T(CMP_NE))
+TOKEN_CLASS(unary_op, T(TILDE) T(NOT) T(PLUS) T(MINUS))
+TOKEN_CLASS(let_func, T(ZVAL) T(OBJVAL) T(ARRVAL) T(PATHVAL) T(STRLEN) T(STRVAL) T(FLOATVAL) T(INTVAL) T(BOOLVAL) T(COUNT))
+TOKEN_CLASS(set_func, T(TO_OBJECT) T(TO_ARRAY) T(TO_STRING) T(TO_INT) T(TO_FLOAT) T(TO_BOOL) T(ZVAL) T(VOID))
+TOKEN_CLASS(impl_type, T(VOID) T(MIXED) T(BOOL) T(INT) T(FLOAT) T(STRING) T(ARRAY) T(OBJECT) T(CALLABLE))
+TOKEN_CLASS(assert_stmt, T(PRE_ASSERT) T(POST_ASSERT))
+TOKEN_CLASS(cpp_message, T(ERROR) T(WARNING))
+
+DEF(%nonassoc, NAME.)
+DEF(%right, NOT TILDE.)
+DEF(%left, AND OR.)
+DEF(%left, PIPE.)
+DEF(%left, CARET.)
+DEF(%left, AMPERSAND.)
+DEF(%left, CMP_EQ CMP_NE.)
+DEF(%left, LCHEVR CMP_LE RCHEVR CMP_GE.)
+DEF(%left, LSHIFT RSHIFT.)
+DEF(%left, PLUS MINUS.)
+DEF(%left, ASTERISK SLASH MODULO.)
+
+DEF(%fallback, NAME TEMP FREE SET LET RETURN CALLOC CALLBACK ZVAL LIB STRING COUNT.)
+DEF(%wildcard, ANY.)
+
+TOKEN_TYPE(decl_enum, struct psi_decl_enum *)
+TOKEN_DTOR(decl_enum, psi_decl_enum_free(&$$);)
+TOKEN_TYPE(decl_enum_items, struct psi_plist*)
+TOKEN_DTOR(decl_enum_items, psi_plist_free($$);)
+TOKEN_TYPE(decl_enum_item, struct psi_decl_enum_item*)
+TOKEN_DTOR(decl_enum_item, psi_decl_enum_item_free(&$$);)
+TOKEN_TYPE(decl_struct_args_block, struct psi_plist*)
+TOKEN_DTOR(decl_struct_args_block, psi_plist_free($$);) /* there was a typo */
+TOKEN_TYPE(decl_struct_args, struct psi_plist*)
+TOKEN_DTOR(decl_struct_args, psi_plist_free($$);)
+TOKEN_TYPE(decl_struct, struct psi_decl_struct*)
+TOKEN_DTOR(decl_struct, psi_decl_struct_free(&$$);)
+TOKEN_TYPE(align_and_size, struct psi_layout)
+TOKEN_TYPE(decl_union, struct psi_decl_union*)
+TOKEN_DTOR(decl_union, psi_decl_union_free(&$$);)
+TOKEN_TYPE(const_type, struct psi_const_type*)
+TOKEN_DTOR(const_type, psi_const_type_free(&$$);)
+TOKEN_TYPE(constant, struct psi_const*)
+TOKEN_DTOR(constant, psi_const_free(&$$);)
+TOKEN_TYPE(decl_typedef, struct psi_decl_arg*)
+TOKEN_DTOR(decl_typedef, psi_decl_arg_free(&$$);)
+TOKEN_TYPE(decl_typedef_body_ex, struct psi_decl_arg*)
+TOKEN_DTOR(decl_typedef_body_ex, psi_decl_arg_free(&$$);)
+TOKEN_TYPE(decl_typedef_body, struct psi_decl_arg*)
+TOKEN_DTOR(decl_typedef_body, psi_decl_arg_free(&$$);)
+TOKEN_TYPE(decl_typedef_body_fn_args, struct psi_plist*)
+TOKEN_DTOR(decl_typedef_body_fn_args, psi_plist_free($$);)
+TOKEN_TYPE(decl, struct psi_decl*)
+TOKEN_DTOR(decl, psi_decl_free(&$$);)
+TOKEN_TYPE(decl_func, struct psi_decl_arg*)
+TOKEN_DTOR(decl_func, psi_decl_arg_free(&$$);)
+TOKEN_TYPE(decl_abi, struct psi_decl_abi*)
+TOKEN_DTOR(decl_abi, psi_decl_abi_free(&$$);)
+TOKEN_TYPE(decl_var, struct psi_decl_var*)
+TOKEN_DTOR(decl_var, psi_decl_var_free(&$$);)
+TOKEN_TYPE(decl_vars, struct psi_plist*)
+TOKEN_DTOR(decl_vars, psi_plist_free($$);)
+TOKEN_TYPE(decl_arg, struct psi_decl_arg*)
+TOKEN_DTOR(decl_arg, psi_decl_arg_free(&$$);)
+TOKEN_TYPE(decl_args, struct psi_plist*)
+TOKEN_DTOR(decl_args, psi_plist_free($$);)
+TOKEN_TYPE(struct_args, struct psi_plist*)
+TOKEN_DTOR(struct_args, psi_plist_free($$);)
+TOKEN_TYPE(struct_arg, struct psi_decl_arg*)
+TOKEN_DTOR(struct_arg, psi_decl_arg_free(&$$);)
+TOKEN_TYPE(decl_layout, struct psi_layout*)
+TOKEN_DTOR(decl_layout, psi_layout_free(&$$);)
+TOKEN_TYPE(decl_type, struct psi_decl_type*)
+TOKEN_DTOR(decl_type, psi_decl_type_free(&$$);)
+TOKEN_TYPE(const_decl_type, struct psi_decl_type*)
+TOKEN_DTOR(const_decl_type, psi_decl_type_free(&$$);)
+TOKEN_TYPE(impl, struct psi_impl*)
+TOKEN_DTOR(impl, psi_impl_free(&$$);)
+TOKEN_TYPE(impl_func, struct psi_impl_func*)
+TOKEN_DTOR(impl_func, psi_impl_func_free(&$$);)
+TOKEN_TYPE(impl_def_val, struct psi_impl_def_val*)
+TOKEN_DTOR(impl_def_val, psi_impl_def_val_free(&$$);)
+TOKEN_TYPE(impl_var, struct psi_impl_var*)
+TOKEN_DTOR(impl_var, psi_impl_var_free(&$$);)
+TOKEN_TYPE(impl_arg, struct psi_impl_arg*)
+TOKEN_DTOR(impl_arg, psi_impl_arg_free(&$$);)
+TOKEN_TYPE(impl_args, struct psi_plist*)
+TOKEN_DTOR(impl_args, psi_plist_free($$);)
+TOKEN_TYPE(impl_vararg, struct psi_impl_arg*)
+TOKEN_DTOR(impl_vararg, psi_impl_arg_free(&$$);)
+TOKEN_TYPE(impl_stmts, struct psi_plist*)
+TOKEN_DTOR(impl_stmts, psi_plist_free($$);)
+TOKEN_TYPE(impl_stmt, struct psi_token**)
+TOKEN_DTOR(impl_stmt, psi_impl_stmt_free(&$$);)
+TOKEN_TYPE(number, struct psi_number*)
+TOKEN_DTOR(number, psi_number_free(&$$);)
+TOKEN_TYPE(num_exp, struct psi_num_exp*)
+TOKEN_DTOR(num_exp, psi_num_exp_free(&$$);)
+TOKEN_TYPE(let_stmt, struct psi_let_stmt*)
+TOKEN_DTOR(let_stmt, psi_let_stmt_free(&$$);)
+TOKEN_TYPE(let_calloc, struct psi_let_calloc*)
+TOKEN_DTOR(let_calloc, psi_let_calloc_free(&$$);)
+TOKEN_TYPE(let_func, struct psi_let_func*)
+TOKEN_DTOR(let_func, psi_let_func_free(&$$);)
+TOKEN_TYPE(callback_arg_list, struct psi_plist *)
+TOKEN_DTOR(callback_arg_list, psi_plist_free($$);)
+TOKEN_TYPE(callback_args, struct psi_plist *)
+TOKEN_DTOR(callback_args, psi_plist_free($$);)
+TOKEN_TYPE(let_callback, struct psi_let_callback*)
+TOKEN_DTOR(let_callback, psi_let_callback_free(&$$);)
+TOKEN_TYPE(let_exp, struct psi_let_exp*)
+TOKEN_DTOR(let_exp, psi_let_exp_free(&$$);)
+TOKEN_TYPE(let_exps, struct psi_plist*)
+TOKEN_DTOR(let_exps, psi_plist_free($$);)
+TOKEN_TYPE(assert_stmt, struct psi_assert_stmt*)
+TOKEN_DTOR(assert_stmt, psi_assert_stmt_free(&$$);)
+TOKEN_TYPE(set_stmt, struct psi_set_stmt*)
+TOKEN_DTOR(set_stmt, psi_set_stmt_free(&$$);)
+TOKEN_TYPE(set_exp, struct psi_set_exp*)
+TOKEN_DTOR(set_exp, psi_set_exp_free(&$$);)
+TOKEN_TYPE(set_exps, struct psi_plist*)
+TOKEN_DTOR(set_exps, psi_plist_free($$);)
+TOKEN_TYPE(set_func, struct psi_set_func*)
+TOKEN_DTOR(set_func, psi_set_func_free(&$$);)
+TOKEN_TYPE(return_stmt, struct psi_return_stmt*)
+TOKEN_DTOR(return_stmt, psi_return_stmt_free(&$$);)
+TOKEN_TYPE(free_stmt, struct psi_free_stmt*)
+TOKEN_DTOR(free_stmt, psi_free_stmt_free(&$$);)
+TOKEN_TYPE(free_exps, struct psi_plist*)
+TOKEN_DTOR(free_exps, psi_plist_free($$);)
+TOKEN_TYPE(free_exp, struct psi_free_exp*)
+TOKEN_DTOR(free_exp, psi_free_exp_free(&$$);)
+TOKEN_TYPE(impl_type, struct psi_impl_type*)
+TOKEN_DTOR(impl_type, psi_impl_type_free(&$$);)
+TOKEN_TYPE(cpp_exp, struct psi_cpp_exp*)
+TOKEN_DTOR(cpp_exp, psi_cpp_exp_free(&$$);)
+TOKEN_TYPE(cpp_macro_decl, struct psi_cpp_macro_decl*)
+TOKEN_DTOR(cpp_macro_decl, psi_cpp_macro_decl_free(&$$);)
+TOKEN_TYPE(cpp_macro_decl_tokens, struct psi_plist*)
+TOKEN_DTOR(cpp_macro_decl_tokens, psi_plist_free($$);)
+TOKEN_TYPE(cpp_macro_exp, struct psi_num_exp*)
+TOKEN_DTOR(cpp_macro_exp, psi_num_exp_free(&$$);)
+TOKEN_TYPE(cpp_macro_sig, struct psi_plist*)
+TOKEN_DTOR(cpp_macro_sig, psi_plist_free($$);)
+TOKEN_TYPE(cpp_macro_sig_args, struct psi_plist*)
+TOKEN_DTOR(cpp_macro_sig_args, psi_plist_free($$);)
+TOKEN_TYPE(cpp_macro_call, struct psi_plist*)
+TOKEN_DTOR(cpp_macro_call, psi_plist_free($$);)
+TOKEN_TYPE(cpp_macro_call_args, struct psi_plist*)
+TOKEN_DTOR(cpp_macro_call_args, psi_plist_free($$);)
+
+TOKEN_TYPE(reference, bool)
+TOKEN_TYPE(indirection, unsigned)
+TOKEN_TYPE(pointers, unsigned)
+
+PASS(file, blocks)
+PASS(blocks, block)
+PASS(blocks, blocks block)
+
+PASS(block, EOS)
+PASS(block, EOL)
+PASS(block, COMMENT)
+
+/*
+ * cpp: # cpp_exp EOL
+ */
+PARSE(block, TOKEN(HASH) TYPED(cpp_exp, exp_) TOKEN(EOL)) {
+       P->cpp.exp = exp_;
+}
+
+/*
+ * cpp_exp: cpp_message_token QUOTED_STRING
+ */
+PARSE_TYPED(cpp_exp, exp,
+               NAMED(cpp_message_token, T)
+               NAMED(QUOTED_STRING, S)) {
+       exp = psi_cpp_exp_init(T->type, S);
+       exp->token = T;
+}
+
+/*
+ * cpp_exp: IFDEF NAME
+ */
+PARSE_TYPED(cpp_exp, exp,
+               NAMED(IFDEF, T)
+               NAMED(NAME, N)) {
+       exp = psi_cpp_exp_init(T->type, N);
+       exp->token = T;
+}
+
+/*
+ * cpp_exp: IFNDEF NAME
+ */
+PARSE_TYPED(cpp_exp, exp,
+               NAMED(IFNDEF, T)
+               NAMED(NAME, N)) {
+       exp = psi_cpp_exp_init(T->type, N);
+       exp->token = T;
+}
+
+/*
+ * cpp_exp: ENDIF
+ */
+PARSE_TYPED(cpp_exp, exp,
+               NAMED(ENDIF, T)) {
+       exp = psi_cpp_exp_init(T->type, NULL);
+       exp->token = T;
+}
+
+/*
+ * cpp_exp: ELSE
+ */
+PARSE_TYPED(cpp_exp, exp,
+               NAMED(ELSE, T)) {
+       exp = psi_cpp_exp_init(T->type, NULL);
+       exp->token = T;
+}
+
+/*
+ * cpp_exp: UNDEF NAME
+ */
+PARSE_TYPED(cpp_exp, exp,
+               NAMED(UNDEF, T)
+               NAMED(NAME, N)) {
+       exp = psi_cpp_exp_init(T->type, N);
+       exp->token = T;
+}
+
+/*
+ * cpp_exp: DEFINE NAME cpp_macro_decl
+ */
+PARSE_TYPED(cpp_exp, exp,
+               NAMED(DEFINE, T)
+               NAMED(NAME, N)
+               TYPED(cpp_macro_decl, macro)) {
+       exp = psi_cpp_exp_init(T->type, macro);
+       exp->token = T;
+       macro->token = N;
+}
+
+/*
+ * cpp_macro_decl: <empty>
+ */
+PARSE_TYPED(cpp_macro_decl, macro, ) {
+       macro = psi_cpp_macro_decl_init(NULL, NULL, NULL);
+}
+
+/*
+ * cpp_macro_decl: cpp_macro_sig
+ */
+PARSE_TYPED(cpp_macro_decl, macro,
+               TYPED(cpp_macro_sig, sig)) {
+       macro = psi_cpp_macro_decl_init(sig, NULL, NULL);
+}
+
+/*
+ * cpp_macro_decl: cpp_macro_sig cpp_macro_decl_tokens
+ */
+PARSE_TYPED(cpp_macro_decl, macro,
+               TYPED(cpp_macro_sig, sig)
+               TYPED(cpp_macro_decl_tokens, tokens)) {
+       macro = psi_cpp_macro_decl_init(sig, tokens, NULL);
+}
+
+/*
+ * cpp_macro_sig: NO_WHITESPACE LPAREN cpp_macro_sig_args RPAREN
+ */
+PARSE_TYPED(cpp_macro_sig, sig,
+               TOKEN(NO_WHITESPACE)
+               TOKEN(LPAREN)
+               TYPED(cpp_macro_sig_args, args)
+               TOKEN(RPAREN)) {
+       sig = args;
+}
+
+/*
+ * cpp_macro_sig_args: <empty>
+ */
+PARSE_TYPED(cpp_macro_sig_args, args, ) {
+       args = NULL;
+}
+
+/*
+ * cpp_macro_sig_args: NAME
+ */
+PARSE_TYPED(cpp_macro_sig_args, args,
+               NAMED(NAME, arg)) {
+       args = psi_plist_add(psi_plist_init((void (*)(void *)) psi_token_free), &arg);
+}
+
+/*
+ * cpp_macro_sig_args: cpp_macro_sig_args , NAME
+ */
+PARSE_TYPED(cpp_macro_sig_args, args,
+               TYPED(cpp_macro_sig_args, args_)
+               TOKEN(COMMA)
+               NAMED(NAME, arg)) {
+       args = psi_plist_add(args_, &arg);
+}
+
+/*
+ * cpp_macro_decl: cpp_macro_decl_tokens
+ */
+PARSE_TYPED(cpp_macro_decl, macro,
+               TYPED(cpp_macro_decl_tokens, tokens)) {
+       macro = psi_cpp_macro_decl_init(NULL, tokens, NULL);
+}
+
+/*
+ * cpp_macro_decl_tokens: ANY
+ */
+PARSE_TYPED(cpp_macro_decl_tokens, tokens,
+               NAMED(ANY, T)) {
+       tokens = psi_plist_add(psi_plist_init((void (*)(void *)) psi_token_free), &T);
+}
+
+/*
+ * cpp_macro_decl_tokens: cpp_macro_decl_tokens ANY
+ */
+PARSE_TYPED(cpp_macro_decl_tokens, tokens,
+               TYPED(cpp_macro_decl_tokens, tokens_)
+               NAMED(ANY, T)) {
+       tokens = psi_plist_add(tokens_, &T);
+}
+
+/*
+ * cpp_exp: IF cpp_macro_exp
+ */
+PARSE_TYPED(cpp_exp, exp,
+               NAMED(IF, T)
+               TYPED(cpp_macro_exp, macro)) {
+       exp = psi_cpp_exp_init(T->type, macro);
+       exp->token = T;
+}
+
+/*
+ * cpp_exp: ELIF cpp_macro_exp
+ */
+PARSE_TYPED(cpp_exp, exp,
+               NAMED(ELIF, T)
+               TYPED(cpp_macro_exp, macro)) {
+       exp = psi_cpp_exp_init(T->type, macro);
+       exp->token = T;
+}
+
+/*
+ * cpp_macro_exp: ( cpp_macro_exp )
+ */
+PARSE_TYPED(cpp_macro_exp, exp,
+               NAMED(LPAREN, L)
+               TYPED(cpp_macro_exp, exp_)
+               TOKEN(RPAREN)) {
+       exp = psi_num_exp_init_unary(L->type, exp_);
+       exp->token = L;
+}
+
+/*
+ * cpp_macro_exp: unary_op cpp_macro_exp
+ */
+PARSE_TYPED(cpp_macro_exp, exp,
+               NAMED(unary_op_token, OP)
+               TYPED(cpp_macro_exp, exp_)) {
+       exp = psi_num_exp_init_unary(OP->type, exp_);
+       exp->token = OP;
+}
+
+/*
+ * cpp_macro_exp: cpp_macro_exp binary_op cpp_macro_exp
+ */
+PARSE_TYPED(cpp_macro_exp, exp,
+               TYPED(cpp_macro_exp, lhs)
+               NAMED(binary_op_token, OP)
+               TYPED(cpp_macro_exp, rhs)) {
+       exp = psi_num_exp_init_binary(OP->type, lhs, rhs);
+       exp->token = OP;
+}
+
+/*
+ * cpp_macro_exp: DEFINED NAME
+ */
+PARSE_TYPED(cpp_macro_exp, exp,
+               TOKEN(DEFINED)
+               NAMED(NAME, N)) {
+       {
+               uint8_t exists = zend_hash_str_exists(&P->cpp.defs, N->text, N->size);
+               exp = psi_num_exp_init_num(psi_number_init(PSI_T_UINT8, &exists));
+               exp->token = N;
+       }
+}
+
+/*
+ * cpp_macro_exp: DEFINED ( NAME )
+ */
+PARSE_TYPED(cpp_macro_exp, exp,
+               TOKEN(DEFINED)
+               TOKEN(LPAREN)
+               NAMED(NAME, N)
+               TOKEN(RPAREN)) {
+       {
+               uint8_t exists = zend_hash_str_exists(&P->cpp.defs, N->text, N->size);
+               exp = psi_num_exp_init_num(psi_number_init(PSI_T_UINT8, &exists));
+               exp->token = N;
+       }
+}
+
+/*
+ * cpp_macro_exp: number
+ */
+PARSE_TYPED(cpp_macro_exp, exp,
+               NAMED(number_token, tok)) {
+       exp = psi_num_exp_init_num(psi_number_init(tok->type, tok->text));
+       exp->token = tok;
+       exp->data.n->token = psi_token_copy(tok);
+}
+
+/*
+ * cpp_macro_exp: NAME
+ */
+PARSE_TYPED(cpp_macro_exp, exp,
+               NAMED(NAME, N)) {
+       exp = psi_num_exp_init_num(psi_number_init(PSI_T_DEFINE, N->text));
+       exp->token = N;
+       exp->data.n->token = psi_token_copy(N);
+}
+
+/*
+ * cpp_macro_exp: NAME ( cpp_macro_call_args )
+ */
+PARSE_TYPED(cpp_macro_exp, exp,
+               NAMED(NAME, N)
+               TOKEN(LPAREN)
+               TYPED(cpp_macro_call_args, args)
+               TOKEN(RPAREN)) {
+       exp = psi_num_exp_init_num(psi_number_init(PSI_T_FUNCTION,
+                       psi_cpp_macro_call_init(N->text, args)));
+       exp->token = N;
+}
+
+/*
+ * cpp_macro_call_args: <empty>
+ */
+PARSE_TYPED(cpp_macro_call_args, args,) {
+       args = NULL;
+}
+
+/*
+ * cpp_macro_call_args: cpp_macro_exp
+ */
+PARSE_TYPED(cpp_macro_call_args, args,
+               TYPED(cpp_macro_exp, arg)) {
+       args = psi_plist_add(psi_plist_init((void (*)(void *)) psi_num_exp_free), &arg);
+}
+
+/*
+ * cpp_macro_call_args: cpp_macro_call_args , cpp_macro_exp
+ */
+PARSE_TYPED(cpp_macro_call_args, args,
+               TYPED(cpp_macro_call_args, args_)
+               TOKEN(COMMA)
+               TYPED(cpp_macro_exp, arg)) {
+       args = psi_plist_add(args_, &arg);
+}
+
+/*
+ * lib: LIB "soname" ;
+ */
+PARSE(block, NAMED(LIB, token) NAMED(QUOTED_STRING, libname) TOKEN(EOS)) {
+       if (P->file.ln) {
+               P->error(PSI_DATA(P), token, PSI_WARNING, "Extra 'lib %s' statement has no effect", libname->text);
+       } else {
+               P->file.ln = strndup(libname->text + 1, libname->size - 2);
+       }
+       free(libname);
+       free(token);
+}
+
+PARSE(block, TYPED(decl, decl)) {
+       if (!P->decls) {
+               P->decls = psi_plist_init((psi_plist_dtor) psi_decl_free);
+       }
+       P->decls = psi_plist_add(P->decls, &decl);
+}
+
+PARSE(block, TYPED(impl, impl)) {
+       if (!P->impls) {
+               P->impls = psi_plist_init((psi_plist_dtor) psi_impl_free);
+       }
+       P->impls = psi_plist_add(P->impls, &impl);
+}
+
+PARSE(block, TYPED(decl_typedef, def)) {
+       if (!P->types) {
+               P->types = psi_plist_init((psi_plist_dtor) psi_decl_arg_free);
+       }
+       P->types = psi_plist_add(P->types, &def);
+
+       switch (def->type->type) {
+       case PSI_T_STRUCT:
+               if (def->type->real.strct) {
+                       if (!P->structs) {
+                               P->structs = psi_plist_init((psi_plist_dtor) psi_decl_struct_free);
+                       }
+                       P->structs = psi_plist_add(P->structs, &def->type->real.strct);
+               }
+               break;
+       case PSI_T_UNION:
+               if (def->type->real.unn) {
+                       if (!P->unions) {
+                               P->unions = psi_plist_init((psi_plist_dtor) psi_decl_union_free);
+                       }
+                       P->unions = psi_plist_add(P->unions, &def->type->real.unn);
+               }
+               break;
+       case PSI_T_ENUM:
+               if (def->type->real.enm) {
+                       if (!P->enums) {
+                               P->enums = psi_plist_init((psi_plist_dtor) psi_decl_enum_free);
+                       }
+                       P->enums = psi_plist_add(P->enums, &def->type->real.enm);
+               }
+               break;
+       }
+}
+
+PARSE(block, TYPED(constant, constant)) {
+       if (!P->consts) {
+               P->consts = psi_plist_init((psi_plist_dtor) psi_const_free);
+       }
+       P->consts = psi_plist_add(P->consts, &constant);
+}
+
+PARSE(block, TYPED(decl_struct, strct)) {
+       if (!P->structs) {
+               P->structs = psi_plist_init((psi_plist_dtor) psi_decl_struct_free);
+       }
+       P->structs = psi_plist_add(P->structs, &strct);
+}
+
+PARSE(block, TYPED(decl_union, u)) {
+       if (!P->unions) {
+               P->unions = psi_plist_init((psi_plist_dtor) psi_decl_union_free);
+       }
+       P->unions = psi_plist_add(P->unions, &u);
+}
+
+PARSE(block, TYPED(decl_enum, e)) {
+       if (!P->enums) {
+               P->enums = psi_plist_init((psi_plist_dtor) psi_decl_enum_free);
+       }
+       P->enums = psi_plist_add(P->enums, &e);
+}
+
+/*
+ * optional_name: <empty>
+ */
+PARSE_NAMED(optional_name, n, ) {
+       n = NULL;
+}
+
+/*
+ * optional_name: NAME
+ */
+PARSE_NAMED(optional_name, n,
+               NAMED(NAME, N)) {
+       n = N;
+}
+
+/*
+ * align_and_size: <empty>
+ */
+PARSE_TYPED(align_and_size, as, ) {
+       as.pos = 0;
+       as.len = 0;
+}
+
+/*
+ * align_and_size: :: ( NUMBER , NUMBER )
+ */
+PARSE_TYPED(align_and_size, as,
+               TOKEN(COLON)
+               TOKEN(COLON)
+               TOKEN(LPAREN)
+               NAMED(NUMBER, A)
+               TOKEN(COMMA)
+               NAMED(NUMBER, S)
+               TOKEN(RPAREN)) {
+       as.pos = atol(A->text);
+       as.len = atol(S->text);
+       free(A);
+       free(S);
+}
+
+/*
+ * enum_name: ENUM optional_name
+ */
+PARSE_NAMED(enum_name, n,
+               NAMED(ENUM, E)
+               NAMED(optional_name, N)) {
+       if (N) {
+               n = N;
+               free(E);
+       } else {
+               char digest[17];
+
+               psi_token_hash(E, digest);
+               n = psi_token_translit(psi_token_append(E, 1, digest), " ", "@");
+       }
+}
+
+/*
+ * struct_name: STRUCT optional_name
+ */
+PARSE_NAMED(struct_name, n,
+               NAMED(STRUCT, S)
+               NAMED(optional_name, N)) {
+       if (N) {
+               n = N;
+               free(S);
+       } else {
+               char digest[17];
+
+               psi_token_hash(S, digest);
+               n = psi_token_translit(psi_token_append(S, 1, digest), " ", "@");
+       }
+}
+
+/*
+ * union_name: UNION optional_name
+ */
+PARSE_NAMED(union_name, n,
+               NAMED(UNION, U)
+               NAMED(optional_name, N)) {
+       if (N) {
+               n = N;
+               free(U);
+       } else {
+               char digest[17];
+
+               psi_token_hash(U, digest);
+               n = psi_token_translit(psi_token_append(U, 1, digest), " ", "@");
+       }
+}
+
+/*
+ * decl_enum: enum_name { items }
+ */
+PARSE_TYPED(decl_enum, e,
+               NAMED(enum_name, N)
+               TOKEN(LBRACE)
+               TYPED(decl_enum_items, list)
+               TOKEN(RBRACE)) {
+       e = psi_decl_enum_init(N->text, list);
+       e->token = N;
+}
+
+/*
+ * decl_enum_items: item
+ */
+PARSE_TYPED(decl_enum_items, l,
+               TYPED(decl_enum_item, i)) {
+       l = psi_plist_add(psi_plist_init((psi_plist_dtor) psi_decl_enum_item_free),
+                       &i);
+}
+
+/*
+ * decl_enum_items: items , item
+ */
+PARSE_TYPED(decl_enum_items, l,
+               TYPED(decl_enum_items, l_)
+               TOKEN(COMMA)
+               TYPED(decl_enum_item, i)) {
+       l = psi_plist_add(l_, &i);
+}
+
+/*
+ * decl_enum_item: name = num_exp
+ */
+PARSE_TYPED(decl_enum_item, i,
+               NAMED(NAME, N)
+               TOKEN(EQUALS)
+               TYPED(num_exp, num)) {
+       i = psi_decl_enum_item_init(N->text, num);
+       i->token = N;
+}
+
+/*
+ * decl_enum_item: name
+ */
+PARSE_TYPED(decl_enum_item, i,
+               NAMED(NAME, N)) {
+       i = psi_decl_enum_item_init(N->text, NULL);
+       i->token = N;
+}
+
+
+/*
+ * decl_struct_args_block: { args }
+ */
+PARSE_TYPED(decl_struct_args_block, args_,
+               TOKEN(LBRACE)
+               TYPED(struct_args, args)
+               TOKEN(RBRACE)) {
+       args_ = args;
+}
+
+/*
+ * decl_struct_args: args_block
+ */
+PARSE_TYPED(decl_struct_args, args_,
+               TYPED(decl_struct_args_block, args)) {
+       args_ = args;
+}
+
+/*
+ * decl_struct_args: ;
+ */
+PARSE_TYPED(decl_struct_args, args_,
+               TOKEN(EOS)) {
+       args_ = psi_plist_init((psi_plist_dtor) psi_decl_arg_free);
+}
+
+/*
+ * decl_struct: STRUCT name align_and_size struct_args
+ */
+PARSE_TYPED(decl_struct, strct,
+               TOKEN(STRUCT)
+               NAMED(NAME, N)
+               TYPED(align_and_size, as)
+               TYPED(decl_struct_args, args)) {
+       strct = psi_decl_struct_init(N->text, args);
+       strct->align = as.pos;
+       strct->size = as.len;
+       strct->token = N;
+}
+
+/*
+ * decl_union: UNION name align_and_size struct_args
+ */
+PARSE_TYPED(decl_union, u,
+               TOKEN(UNION)
+               NAMED(NAME, N)
+               TYPED(align_and_size, as)
+               TYPED(decl_struct_args, args)) {
+       u = psi_decl_union_init(N->text, args);
+       u->align = as.pos;
+       u->size = as.len;
+       u->token = N;
+}
+
+/*
+ * const_type: const_type_token
+ */
+PARSE_TYPED(const_type, type_,
+               NAMED(const_type_token, T)) {
+       type_ = psi_const_type_init(T->type, T->text);
+       free(T);
+}
+
+/*
+ * constant: CONST const_type NSNAME = def_val ;
+ */
+PARSE_TYPED(constant, constant,
+               TOKEN(CONST)
+               TYPED(const_type, type)
+               NAMED(NSNAME, T)
+               TOKEN(EQUALS)
+               TYPED(impl_def_val, val)
+               TOKEN(EOS)) {
+       constant = psi_const_init(type, T->text, val);
+       constant->token = T;
+}
+
+/*
+ * decl_typdef: TYPEDEF typedef_body ;
+ */
+PARSE_TYPED(decl_typedef, def,
+               NAMED(TYPEDEF, T)
+               TYPED(decl_typedef_body, def_)
+               TOKEN(EOS)) {
+       def = def_;
+       def->token = T;
+}
+
+/*
+ * decl_typedef_body_ex: struct_name align_and_size struct_args_block decl_var
+ */
+PARSE_TYPED(decl_typedef_body_ex, def,
+               NAMED(struct_name, N)
+               TYPED(align_and_size, as)
+               TYPED(decl_struct_args_block, args)
+               TYPED(decl_var, var)) {
+       def = psi_decl_arg_init(psi_decl_type_init(PSI_T_STRUCT, N->text), var);
+       def->type->token = psi_token_copy(N);
+       def->type->real.strct = psi_decl_struct_init(N->text, args);
+       def->type->real.strct->token = N;
+       def->type->real.strct->align = as.pos;
+       def->type->real.strct->size = as.len;
+}
+
+/*
+ * decl_typedef_body_ex: union_name align_and_size struct_args_block decl_var
+ */
+PARSE_TYPED(decl_typedef_body_ex, def,
+               NAMED(union_name, N)
+               TYPED(align_and_size, as)
+               TYPED(decl_struct_args_block, args)
+               TYPED(decl_var, var)) {
+       def = psi_decl_arg_init(psi_decl_type_init(PSI_T_UNION, N->text), var);
+       def->type->token = psi_token_copy(N);
+       def->type->real.unn = psi_decl_union_init(N->text, args);
+       def->type->real.unn->token = N;
+       def->type->real.unn->align = as.pos;
+       def->type->real.unn->size = as.len;
+}
+
+/*
+ * decl_typedef_body_ex: decl_enum NAME
+ */
+PARSE_TYPED(decl_typedef_body_ex, def,
+               TYPED(decl_enum, e)
+               NAMED(NAME, ALIAS)) {
+       def = psi_decl_arg_init(psi_decl_type_init(PSI_T_ENUM, e->name), psi_decl_var_init(ALIAS->text, 0, 0));
+       def->var->token = ALIAS;
+       def->type->token = psi_token_copy(e->token);
+       def->type->real.enm = e;
+}
+
+/*
+ * decl_typedef_body: decl_typedef_body_ex
+ */
+PARSE_TYPED(decl_typedef_body, def,
+               TYPED(decl_typedef_body_ex, def_)) {
+       def = def_;
+}
+
+/*
+ * decl_typedef_body_fn_args: ( decl_args )
+ */
+PARSE_TYPED(decl_typedef_body_fn_args, args,
+               TOKEN(LPAREN)
+               TYPED(decl_args, args_)
+               TOKEN(RPAREN)) {
+       args = args_;
+}
+
+/*
+ * decl_typedef_body: decl_func decl_typedef_body_fn_args
+ */
+PARSE_TYPED(decl_typedef_body, def,
+               TYPED(decl_func, func_)
+               TYPED(decl_typedef_body_fn_args, args)) {
+       def = psi_decl_arg_init(psi_decl_type_init(PSI_T_FUNCTION, func_->var->name), psi_decl_var_copy(func_->var));
+       def->type->token = psi_token_copy(func_->token);
+       def->type->real.func = psi_decl_init(psi_decl_abi_init("default"), func_, args);
+}
+
+/*
+ * decl_typedef_body: decl_arg
+ */
+PARSE_TYPED(decl_typedef_body, def,
+               TYPED(decl_arg, arg)) {
+       def = arg;
+}
+
+/*
+ * decl: decl_abi decl_func ( decl_args ) ;
+ */
+PARSE_TYPED(decl, decl,
+               TYPED(decl_abi, abi)
+               TYPED(decl_func, func)
+               TOKEN(LPAREN)
+               TYPED(decl_args, args)
+               TOKEN(RPAREN)
+               TOKEN(EOS)) {
+       decl = psi_decl_init(abi, func, args);
+}
+
+/*
+ * decl: decl_abi decl_func ( decl_args , ... ) ;
+ */
+PARSE_TYPED(decl, decl,
+               TYPED(decl_abi, abi)
+               TYPED(decl_func, func)
+               TOKEN(LPAREN)
+               TYPED(decl_args, args)
+               TOKEN(COMMA)
+               TOKEN(ELLIPSIS)
+               TOKEN(RPAREN)
+               TOKEN(EOS)) {
+       decl = psi_decl_init(abi, func, args);
+       decl->varargs = 1;
+}
+
+/*
+ * decl_func: decl_arg
+ */
+PARSE_TYPED(decl_func, func,
+               TYPED(decl_arg, arg)) {
+       func = arg;
+}
+
+/* special case for void functions */
+/*
+ * decl_func: VOID NAME
+ */
+PARSE_TYPED(decl_func, func,
+               NAMED(VOID, T)
+               NAMED(NAME, N)) {
+       func = psi_decl_arg_init(
+               psi_decl_type_init(T->type, T->text),
+               psi_decl_var_init(N->text, 0, 0)
+       );
+       func->type->token = T;
+       func->var->token = N;
+       func->token = N;
+}
+
+/*
+ * decl_typedef_body: VOID indirection ( indirection NAME ) decl_typedef_body_fn_args
+ */
+PARSE_TYPED(decl_typedef_body, def,
+               NAMED(VOID, T)
+               TYPED(indirection, decl_i)
+               TOKEN(LPAREN)
+               TYPED(indirection, type_i)
+               NAMED(NAME, N)
+               TOKEN(RPAREN)
+               TYPED(decl_typedef_body_fn_args, args)) {
+       struct psi_decl_arg *func_ = psi_decl_arg_init(
+               psi_decl_type_init(T->type, T->text),
+               psi_decl_var_init(N->text, decl_i, 0)
+       );
+       func_->type->token = T;
+       func_->var->token = N;
+       func_->token = N;
+
+       def = psi_decl_arg_init(
+               psi_decl_type_init(PSI_T_FUNCTION, func_->var->name),
+               psi_decl_var_copy(func_->var)
+       );
+       def->var->pointer_level = type_i;
+       def->type->token = psi_token_copy(func_->token);
+       def->type->real.func = psi_decl_init(psi_decl_abi_init("default"), func_, args);
+}
+
+/*
+ * decl_typedef_body: CONST VOID pointers ( indirection NAME ) decl_typdef_body_fn_args
+ */
+PARSE_TYPED(decl_typedef_body, def,
+               TOKEN(CONST)
+               NAMED(VOID, T)
+               TYPED(pointers, decl_i)
+               TOKEN(LPAREN)
+               TYPED(indirection, type_i)
+               NAMED(NAME, N)
+               TOKEN(RPAREN)
+               TYPED(decl_typedef_body_fn_args, args)) {
+       struct psi_decl_arg *func_ = psi_decl_arg_init(
+               psi_decl_type_init(T->type, T->text),
+               psi_decl_var_init(N->text, decl_i, 0)
+       );
+       func_->type->token = T;
+       func_->var->token = N;
+       func_->token = N;
+
+       def = psi_decl_arg_init(
+               psi_decl_type_init(PSI_T_FUNCTION, func_->var->name),
+               psi_decl_var_copy(func_->var)
+       );
+       def->var->pointer_level = type_i;
+       def->type->token = psi_token_copy(func_->token);
+       def->type->real.func = psi_decl_init(psi_decl_abi_init("default"), func_, args);
+}
+
+/*
+ * decl_abi: NAME
+ */
+PARSE_TYPED(decl_abi, abi,
+               NAMED(NAME, T)) {
+       abi = psi_decl_abi_init(T->text);
+       abi->token = T;
+}
+
+/*
+ * decl_var_array_size: <empty>
+ */
+PARSE_NAMED(decl_var_array_size, as, ) {
+       as = NULL;
+}
+
+/*
+ * decl_var_array_size: [ NUMBER ]
+ */
+PARSE_NAMED(decl_var_array_size, as,
+               TOKEN(LBRACKET)
+               NAMED(NUMBER, D)
+               TOKEN(RBRACKET)) {
+       as = D;
+}
+
+/*
+ * decl_var: NAME decl_var_array_size
+ */
+PARSE_TYPED(decl_var, var,
+               NAMED(NAME, T)
+               NAMED(decl_var_array_size, as)) {
+       var = psi_decl_var_init(T->text, 0, as?atol(as->text):0);
+       var->token = T;
+       if (as) {
+               free(as);
+       }
+}
+
+/*
+ * decl_var: pointers NAME
+ */
+PARSE_TYPED(decl_var, var,
+               TYPED(pointers, p)
+               NAMED(NAME, T)
+               NAMED(decl_var_array_size, as)) {
+       var = psi_decl_var_init(T->text, p+!!as, as?atol(as->text):0);
+       var->token = T;
+       if (as) {
+               free(as);
+       }
+}
+
+/*
+ * decl_vars: decl_var
+ */
+PARSE_TYPED(decl_vars, vars,
+               TYPED(decl_var, var)) {
+       vars = psi_plist_add(psi_plist_init((psi_plist_dtor) psi_decl_var_free),
+                       &var);
+}
+
+/*
+ * decl_vars: decl_vars , decl_var
+ */
+PARSE_TYPED(decl_vars, vars,
+               TYPED(decl_vars, vars_)
+               TOKEN(COMMA)
+               TYPED(decl_var, var)) {
+       vars = psi_plist_add(vars_, &var);
+}
+
+/*
+ * decl_arg: const_decl_type decl_var
+ */
+PARSE_TYPED(decl_arg, arg_,
+               TYPED(const_decl_type, type)
+               TYPED(decl_var, var)) {
+       arg_ = psi_decl_arg_init(type, var);
+}
+
+/*
+ * decl_typedef_body: const_decl_type indirection ( indirection NAME ) decl_typedef_body_fn_args
+ */
+PARSE_TYPED(decl_typedef_body, def,
+               TYPED(const_decl_type, type_)
+               TYPED(indirection, decl_i)
+               TOKEN(LPAREN)
+               TYPED(indirection, type_i)
+               NAMED(NAME, N)
+               TOKEN(RPAREN)
+               TYPED(decl_typedef_body_fn_args, args)) {
+       struct psi_decl_arg *func_ = psi_decl_arg_init(
+               type_,
+               psi_decl_var_init(N->text, decl_i, 0)
+       );
+       func_->var->token = N;
+       func_->token = N;
+
+       def = psi_decl_arg_init(
+               psi_decl_type_init(PSI_T_FUNCTION, func_->var->name),
+               psi_decl_var_copy(func_->var)
+       );
+       def->var->pointer_level = type_i;
+       def->type->token = psi_token_copy(func_->token);
+       def->type->real.func = psi_decl_init(psi_decl_abi_init("default"), func_, args);
+}
+
+/* void pointers need a specific rule */
+/*
+ * decl_arg: VOID pointers NAME
+ */
+PARSE_TYPED(decl_arg, arg_,
+               NAMED(VOID, T)
+               TYPED(pointers, p)
+               NAMED(NAME, N)) {
+       arg_ = psi_decl_arg_init(
+               psi_decl_type_init(T->type, T->text),
+               psi_decl_var_init(N->text, p, 0)
+       );
+       arg_->type->token = T;
+       arg_->var->token = N;
+       arg_->token = N;
+}
+
+/*
+ * decl_args: CONST VOID pointers NAME
+ */
+PARSE_TYPED(decl_arg, arg_,
+               TOKEN(CONST)
+               NAMED(VOID, T)
+               TYPED(pointers, p)
+               NAMED(NAME, N)) {
+       arg_ = psi_decl_arg_init(
+               psi_decl_type_init(T->type, T->text),
+               psi_decl_var_init(N->text, p, 0)
+       );
+       arg_->type->token = T;
+       arg_->var->token = N;
+       arg_->token = N;
+}
+
+/*
+ * decl_args: <empty>
+ */
+PARSE_TYPED(decl_args, args, ) {
+       args = NULL;
+}
+
+/*
+ * decl_args: VOID
+ */
+PARSE_TYPED(decl_args, args,
+               TOKEN(VOID)) {
+       args = NULL;
+}
+
+/*
+ * decl_args: decl_arg
+ */
+PARSE_TYPED(decl_args, args,
+               TYPED(decl_arg, arg)) {
+       args = psi_plist_add(psi_plist_init((psi_plist_dtor) psi_decl_arg_free),
+                       &arg);
+}
+
+/*
+ * decl_args: decl_args , decl_arg
+ */
+PARSE_TYPED(decl_args, args,
+               TYPED(decl_args, args_)
+               TOKEN(COMMA)
+               TYPED(decl_arg, arg)) {
+       args = psi_plist_add(args_, &arg);
+}
+
+/*
+ * struct_args: struct_arg
+ */
+PARSE_TYPED(struct_args, args,
+               TYPED(struct_arg, arg)) {
+       args = psi_plist_add(psi_plist_init((psi_plist_dtor) psi_decl_arg_free),
+                       &arg);
+}
+
+/*
+ * struct_args: struct_args , struct_arg
+ */
+PARSE_TYPED(struct_args, args,
+               TYPED(struct_args, args_)
+               TYPED(struct_arg, arg)) {
+       args = psi_plist_add(args_, &arg);
+}
+
+/*
+ * struct_arg: decl_typedef_body_ex ;
+ */
+PARSE_TYPED(struct_arg, arg_,
+               TYPED(decl_typedef_body_ex, def)
+               TOKEN(EOS)) {
+       arg_ = def;
+       switch (def->type->type) {
+       case PSI_T_STRUCT:
+               if (def->type->real.strct) {
+                       if (!P->structs) {
+                               P->structs = psi_plist_init((psi_plist_dtor) psi_decl_struct_free);
+                       }
+                       P->structs = psi_plist_add(P->structs, &def->type->real.strct);
+               }
+               break;
+       case PSI_T_UNION:
+               if (def->type->real.unn) {
+                       if (!P->unions) {
+                               P->unions = psi_plist_init((psi_plist_dtor) psi_decl_union_free);
+                       }
+                       P->unions = psi_plist_add(P->unions, &def->type->real.unn);
+               }
+               break;
+       case PSI_T_ENUM:
+               if (def->type->real.enm) {
+                       if (!P->enums) {
+                               P->enums = psi_plist_init((psi_plist_dtor) psi_decl_enum_free);
+                       }
+                       P->enums = psi_plist_add(P->enums, &def->type->real.enm);
+               }
+               break;
+       }
+}
+
+/*
+ * struct_arg: decl_arg decl_layout ;
+ */
+PARSE_TYPED(struct_arg, arg,
+               TYPED(decl_arg, arg_)
+               TYPED(decl_layout, layout_)
+               TOKEN(EOS)) {
+       arg_->layout = layout_;
+       arg = arg_;
+}
+
+/*
+ * decl_layout: <empty>
+ */
+PARSE_TYPED(decl_layout, layout, ) {
+       layout = NULL;
+}
+
+/*
+ * decl_layout: :: ( NUMBER , NUMBER )
+ */
+PARSE_TYPED(decl_layout, layout,
+               TOKEN(COLON)
+               TOKEN(COLON)
+               TOKEN(LPAREN)
+               NAMED(NUMBER, POS)
+               TOKEN(COMMA)
+               NAMED(NUMBER, SIZ)
+               TOKEN(RPAREN)) {
+       layout = psi_layout_init(atol(POS->text), atol(SIZ->text));
+       free(POS);
+       free(SIZ);
+}
+
+/* un/signed, urgh */
+/*
+ * decl_scalar_type: CHAR
+ */
+PARSE_NAMED(decl_scalar_type, type_,
+               NAMED(CHAR, C)) {
+       type_ = C;
+}
+
+/*
+ * decl_scalar_type: SHORT decl_scalar_type_short
+ */
+PARSE_NAMED(decl_scalar_type, type_,
+               NAMED(SHORT, S)
+               NAMED(decl_scalar_type_short, s)) {
+       if (s) {
+               type_ = psi_token_cat(2, S, s);
+               free(S);
+               free(s);
+       } else {
+               type_ = S;
+       }
+}
+
+/*
+ * decl_scalar_type_short: <empty>
+ */
+PARSE_NAMED(decl_scalar_type_short, s, ) {
+       s = NULL;
+}
+
+/*
+ * decl_scalar_type_short: INT
+ */
+PARSE_NAMED(decl_scalar_type_short, s,
+               NAMED(INT, I)) {
+       s = I;
+}
+
+/*
+ * decl_sclara_type: INT
+ */
+PARSE_NAMED(decl_scalar_type, type_,
+               NAMED(INT, I)) {
+       type_ = I;
+}
+
+/*
+ * decl_scalar_type: LONG decl_scalar_type_long
+ */
+PARSE_NAMED(decl_scalar_type, type_,
+               NAMED(LONG, L)
+               NAMED(decl_scalar_type_long, l)) {
+       if (l) {
+               type_ = psi_token_cat(2, L, l);
+               free(L);
+               free(l);
+       } else {
+               type_ = L;
+       }
+}
+
+/*
+ * decl_scalar_type_long: <empty>
+ */
+PARSE_NAMED(decl_scalar_type_long, l, ) {
+       l = NULL;
+}
+
+/*
+ * decl_scalar_type_long: DOUBLE
+ */
+PARSE_NAMED(decl_scalar_type_long, l,
+               NAMED(DOUBLE, D)) {
+       l = D;
+}
+
+/*
+ * decl_scalar_type_long: LONG decl_scalar_type_long_long
+ */
+PARSE_NAMED(decl_scalar_type_long, l,
+               NAMED(LONG, L)
+               NAMED(decl_scalar_type_long_long, ll)) {
+       if (ll) {
+               l = psi_token_cat(2, L, ll);
+               free(L);
+               free(ll);
+       } else {
+               l = L;
+       }
+}
+
+/*
+ * decl_scalar_type_long_long: <empty>
+ */
+PARSE_NAMED(decl_scalar_type_long_long, ll, ) {
+       ll = NULL;
+}
+
+/*
+ * decl_scalar_type_long_long: INT
+ */
+PARSE_NAMED(decl_scalar_type_long_long, ll,
+               NAMED(INT, I)) {
+       ll = I;
+}
+
+/*
+ * decl_type: UNSIGNED decl_scalar_type
+ */
+PARSE_TYPED(decl_type, type_,
+               NAMED(UNSIGNED, U)
+               NAMED(decl_scalar_type, N)) {
+       struct psi_token *T = psi_token_cat(2, U, N);
+       type_ = psi_decl_type_init(T->type, T->text);
+       type_->token = T;
+       free(U);
+       free(N);
+}
+
+/*
+ * decl_type: SIGNED decl_scalar_type
+ */
+PARSE_TYPED(decl_type, type_,
+               NAMED(SIGNED, S)
+               NAMED(decl_scalar_type, N)) {
+       struct psi_token *T = psi_token_cat(2, S, N);
+       type_ = psi_decl_type_init(T->type, T->text);
+       type_->token = T;
+       free(S);
+       free(N);
+}
+
+/*
+ * decl_type: UNSIGNED
+ */
+PARSE_TYPED(decl_type, type_,
+               NAMED(UNSIGNED, U)) {
+       type_ = psi_decl_type_init(PSI_T_NAME, U->text);
+       type_->token = U;
+}
+
+/*
+ * decl_type: SIGNED
+ */
+PARSE_TYPED(decl_type, type_,
+               NAMED(SIGNED, S)) {
+       type_ = psi_decl_type_init(PSI_T_NAME, S->text);
+       type_->token = S;
+}
+
+/*
+ * decl_type: decl_scalar_type
+ */
+PARSE_TYPED(decl_type, type_,
+               NAMED(decl_scalar_type, N)) {
+       type_ = psi_decl_type_init(N->type, N->text);
+       type_->token = N;
+}
+
+/* structs ! */
+/*
+ * decl_type: STRUCT NAME
+ */
+PARSE_TYPED(decl_type, type_,
+               NAMED(STRUCT, S)
+               NAMED(NAME, T)) {
+       type_ = psi_decl_type_init(S->type, T->text);
+       type_->token = T;
+       free(S);
+}
+
+/*
+ * decl_type: UNION NAME
+ */
+PARSE_TYPED(decl_type, type_,
+               NAMED(UNION, U)
+               NAMED(NAME, T)) {
+       type_ = psi_decl_type_init(U->type, T->text);
+       type_->token = T;
+       free(U);
+}
+
+/*
+ * decl_type: ENUM NAME
+ */
+PARSE_TYPED(decl_type, type_,
+               NAMED(ENUM, E)
+               NAMED(NAME, T)) {
+       type_ = psi_decl_type_init(E->type, T->text);
+       type_->token = T;
+       free(E);
+}
+
+/*
+ * decl_type: decl_type_token
+ */
+PARSE_TYPED(decl_type, type_,
+               NAMED(decl_type_token, T)) {
+       type_ = psi_decl_type_init(T->type, T->text);
+       type_->token = T;
+}
+
+/*
+ * const_decl_type: decl_type
+ */
+PARSE_TYPED(const_decl_type, type,
+               TYPED(decl_type, type_)) {
+       type = type_;
+}
+
+/*
+ * const_decl_type: CONST decl_type
+ */
+PARSE_TYPED(const_decl_type, type,
+               TOKEN(CONST)
+               TYPED(decl_type, type_)) {
+       type = type_;
+}
+
+/*
+ * impl: impl_func { impl_stmts }
+ */
+PARSE_TYPED(impl, impl,
+               TYPED(impl_func, func)
+               TOKEN(LBRACE)
+               TYPED(impl_stmts, stmts)
+               TOKEN(RBRACE)) {
+       impl = psi_impl_init(func, stmts);
+}
+
+/*
+ * impl: STATIC impl_func { impl_stmts }
+ */
+PARSE_TYPED(impl, impl,
+               TOKEN(STATIC)
+               TYPED(impl_func, func)
+               TOKEN(LBRACE)
+               TYPED(impl_stmts, stmts)
+               TOKEN(RBRACE)) {
+       func->static_memory = 1;
+       impl = psi_impl_init(func, stmts);
+}
+
+/*
+ * impl_func: FUNCTION reference NSNAME ( ) : impl_type
+ */
+PARSE_TYPED(impl_func, func,
+               TOKEN(FUNCTION)
+               TYPED(reference, r)
+               NAMED(NSNAME, NAME)
+               TOKEN(LPAREN)
+               TOKEN(RPAREN)
+               TOKEN(COLON)
+               TYPED(impl_type, type)) {
+       func = psi_impl_func_init(NAME->text, NULL, type);
+       func->token = NAME;
+       func->return_reference = r;
+}
+
+/*
+ * impl_func: FUNCTION reference NSNAME ( impl_args ) : impl_type
+ */
+PARSE_TYPED(impl_func, func,
+               TOKEN(FUNCTION)
+               TYPED(reference, r)
+               NAMED(NSNAME, NAME)
+               TOKEN(LPAREN)
+               TYPED(impl_args, args)
+               TOKEN(RPAREN)
+               TOKEN(COLON)
+               TYPED(impl_type, type)) {
+       func = psi_impl_func_init(NAME->text, args, type);
+       func->token = NAME;
+       func->return_reference = r;
+}
+
+/*
+ * impl_func: FUNCTION reference NSNAME ( impl_args , impl_type reference ... DOLLAR_NAME ) : impl_type
+ */
+PARSE_TYPED(impl_func, func,
+               TOKEN(FUNCTION)
+               TYPED(reference, func_r)
+               NAMED(NSNAME, NAME)
+               TOKEN(LPAREN)
+               TYPED(impl_args, args)
+               TOKEN(COMMA)
+               TYPED(impl_type, va_type)
+               TYPED(reference, va_r)
+               TOKEN(ELLIPSIS)
+               NAMED(DOLLAR_NAME, T)
+               TOKEN(RPAREN)
+               TOKEN(COLON)
+               TYPED(impl_type, func_type)) {
+       func = psi_impl_func_init(NAME->text, args, func_type);
+       func->token = NAME;
+       func->return_reference = func_r;
+       func->vararg = psi_impl_arg_init(va_type, psi_impl_var_init(T->text, va_r), NULL);
+       free(T);
+}
+
+/*
+ * impl_def_val: impl_def_val_token
+ */
+PARSE_TYPED(impl_def_val, def,
+               NAMED(impl_def_val_token, T)) {
+       def = psi_impl_def_val_init(T->type, T->text);
+       def->token = T;
+}
+
+/*
+ * impl_var: reference DOLLAR_NAME
+ */
+PARSE_TYPED(impl_var, var,
+               TYPED(reference, r)
+               NAMED(DOLLAR_NAME, T)) {
+       var = psi_impl_var_init(T->text, r);
+       var->token = T;
+}
+
+/*
+ * impl_type: impl_type_token
+ */
+PARSE_TYPED(impl_type, type_,
+               NAMED(impl_type_token, T)) {
+       type_ = psi_impl_type_init(T->type, T->text);
+       free(T);
+}
+
+/*
+ * impl_arg: impl_type impl_var
+ */
+PARSE_TYPED(impl_arg, arg,
+               TYPED(impl_type, type)
+               TYPED(impl_var, var)) {
+       arg = psi_impl_arg_init(type, var, NULL);
+}
+
+/*
+ * impl_arg: impl_type impl_var = impl_def_val
+ */
+PARSE_TYPED(impl_arg, arg,
+               TYPED(impl_type, type)
+               TYPED(impl_var, var)
+               TOKEN(EQUALS)
+               TYPED(impl_def_val, def)) {
+       arg = psi_impl_arg_init(type, var, def);
+}
+
+/*
+ * impl_args: impl_arg
+ */
+PARSE_TYPED(impl_args, args,
+               TYPED(impl_arg, arg)) {
+       args = psi_plist_add(psi_plist_init((psi_plist_dtor) psi_impl_arg_free),
+                       &arg);
+}
+
+/*
+ * impl_args: impl_args , impl_arg
+ */
+PARSE_TYPED(impl_args, args,
+               TYPED(impl_args, args_)
+               TOKEN(COMMA)
+               TYPED(impl_arg, arg)) {
+       args = psi_plist_add(args_, &arg);
+}
+
+/*
+ * impl_stmts: impl_stmt
+ */
+PARSE_TYPED(impl_stmts, stmts,
+               TYPED(impl_stmt, stmt)) {
+       stmts = psi_plist_add(psi_plist_init((psi_plist_dtor) psi_impl_stmt_free),
+                       &stmt);
+}
+
+/*
+ * impl_stmts: impl_stmts , impl_stmt
+ */
+PARSE_TYPED(impl_stmts, stmts,
+               TYPED(impl_stmts, stmts_)
+               TYPED(impl_stmt, stmt)) {
+       stmts = psi_plist_add(stmts_, &stmt);
+}
+
+/*
+ * impl_stmt: return_stmt
+ */
+PARSE_TYPED(impl_stmt, i,
+               TYPED(return_stmt, r)) {
+       i = (struct psi_token**) r;
+}
+
+/*
+ * impl_stmt: let_stmt
+ */
+PARSE_TYPED(impl_stmt, i,
+               TYPED(let_stmt, l)) {
+       i = (struct psi_token**) l;
+}
+
+/*
+ * impl_stmt: set_stmt
+ */
+PARSE_TYPED(impl_stmt, i,
+               TYPED(set_stmt, s)) {
+       i = (struct psi_token**) s;
+}
+
+/*
+ * impl_stmt: assert_stmt
+ */
+PARSE_TYPED(impl_stmt, i,
+               TYPED(assert_stmt, s)) {
+       i = (struct psi_token **) s;
+}
+
+/*
+ * impl_stmt: free_stmt
+ */
+PARSE_TYPED(impl_stmt, i,
+               TYPED(free_stmt, f)) {
+       i = (struct psi_token**) f;
+}
+
+/*
+ * number: number_token
+ */
+PARSE_TYPED(number, exp,
+               NAMED(number_token, tok)) {
+       exp = psi_number_init(tok->type, tok->text);
+       exp->token = tok;
+}
+
+/*
+ * number: decl_var
+ */
+PARSE_TYPED(number, exp,
+               TYPED(decl_var, var)) {
+       exp = psi_number_init(PSI_T_NAME, var);
+       exp->token = psi_token_copy(var->token);
+}
+
+/*
+ * num_exp: number
+ */
+PARSE_TYPED(num_exp, exp,
+               TYPED(number, num)) {
+       exp = psi_num_exp_init_num(num);
+       exp->token = psi_token_copy(num->token);
+}
+
+/*
+ * num_exp: ( num_exp )
+ */
+PARSE_TYPED(num_exp, exp,
+               NAMED(LPAREN, L)
+               TYPED(num_exp, exp_)
+               TOKEN(RPAREN)) {
+       exp = psi_num_exp_init_unary(PSI_T_LPAREN, exp_);
+       exp->token = L;
+}
+
+/*
+ * num_exp: num_exp binary_op_token num_exp
+ */
+PARSE_TYPED(num_exp, exp,
+               TYPED(num_exp, lhs_)
+               NAMED(binary_op_token, OP)
+               TYPED(num_exp, rhs_)) {
+       exp = psi_num_exp_init_binary(OP->type, lhs_, rhs_);
+       exp->token = OP;
+}
+
+/*
+ * num_exp: unary_op_token num_exp
+ */
+PARSE_TYPED(num_exp, exp,
+               NAMED(unary_op_token, OP)
+               TYPED(num_exp, exp_)) {
+       exp = psi_num_exp_init_unary(OP->type, exp_);
+       exp->token = OP;
+}
+
+/*
+ * let_exp: NULL
+ */
+PARSE_TYPED(let_exp, val,
+               TOKEN(NULL)) {
+       val = psi_let_exp_init(PSI_LET_NULL, NULL);
+}
+
+/*
+ * let_exp: & NULL
+ */
+PARSE_TYPED(let_exp, val,
+               TOKEN(AMPERSAND)
+               TOKEN(NULL)) {
+       val = psi_let_exp_init(PSI_LET_NULL, NULL);
+       val->is_reference = 1;
+}
+
+/*
+ * let_exp: callback
+ */
+PARSE_TYPED(let_exp, val,
+               TYPED(let_callback, cb)) {
+       val = psi_let_exp_init(PSI_LET_CALLBACK, cb);
+}
+
+/*
+ * let_exp: calloc
+ */
+PARSE_TYPED(let_exp, val,
+               TYPED(let_calloc, ca)) {
+       val = psi_let_exp_init(PSI_LET_CALLOC, ca);
+}
+
+/*
+ * let_exp: & calloc
+ */
+PARSE_TYPED(let_exp, val,
+               TOKEN(AMPERSAND)
+               TYPED(let_calloc, ca)) {
+       val = psi_let_exp_init(PSI_LET_CALLOC, ca);
+       val->is_reference = 1;
+}
+
+/*
+ * let_exp: func
+ */
+PARSE_TYPED(let_exp, val,
+               TYPED(let_func, fn)) {
+       val = psi_let_exp_init_ex(NULL, PSI_LET_FUNC, fn);
+}
+
+/*
+ * let_exp: & func
+ */
+PARSE_TYPED(let_exp, val,
+               TOKEN(AMPERSAND)
+               TYPED(let_func, fn)) {
+       val = psi_let_exp_init_ex(NULL, PSI_LET_FUNC, fn);
+       val->is_reference = 1;
+}
+
+/*
+ * let_exp: num_exp
+ */
+PARSE_TYPED(let_exp, val,
+               TYPED(num_exp, exp)) {
+       val = psi_let_exp_init_ex(NULL, PSI_LET_NUMEXP, exp);
+}
+
+/*
+ * let_exp: & num_exp
+ */
+PARSE_TYPED(let_exp, val,
+               TOKEN(AMPERSAND)
+               TYPED(num_exp, exp)) {
+       val = psi_let_exp_init_ex(NULL, PSI_LET_NUMEXP, exp);
+       val->is_reference = 1;
+}
+
+/* FIXME
+ * let_exp: decl_var = let_exp
+ */
+PARSE_TYPED(let_exp, exp,
+               TYPED(decl_var, var_)
+               TOKEN(EQUALS)
+               TYPED(let_exp, val)) {
+       exp = val;
+       exp->var = var_;
+}
+
+/*
+ * let_stmt: LET let_exp ;
+ */
+PARSE_TYPED(let_stmt, let,
+               NAMED(LET, T)
+               TYPED(let_exp, val)
+               TOKEN(EOS)) {
+       let = psi_let_stmt_init(val);
+       let->token = T;
+}
+
+/*
+ * let_stmt: TEMP decl_var = reference decl_var ;
+ */
+PARSE_TYPED(let_stmt, let,
+               NAMED(TEMP, T)
+               TYPED(decl_var, var)
+               TOKEN(EQUALS)
+               TYPED(reference, r)
+               TYPED(decl_var, val_)
+               TOKEN(EOS)) {
+       let = psi_let_stmt_init(psi_let_exp_init_ex(var, PSI_LET_TMP, val_));
+       let->token = T;
+       let->exp->is_reference = r ? 1 : 0;
+}
+
+/*
+ * let_callback: CALLBACK callback_rval ( impl_var ( callback_arg_lists ) )
+ */
+PARSE_TYPED(let_callback, cb,
+               NAMED(CALLBACK, T)
+               NAMED(callback_rval, F)
+               TOKEN(LPAREN)
+               TYPED(impl_var, var)
+               TOKEN(LPAREN)
+               TYPED(callback_arg_list, args_)
+               TOKEN(RPAREN)
+               TOKEN(RPAREN)) {
+       cb = psi_let_callback_init(psi_let_func_init(F->type, F->text, var), args_);
+       cb->token = T;
+       free(F);
+}
+
+/*
+ * let_calloc: CALLOC ( num_exp , num_exp )
+ */
+PARSE_TYPED(let_calloc, alloc,
+               NAMED(CALLOC, T)
+               TOKEN(LPAREN)
+               TYPED(num_exp, nmemb)
+               TOKEN(COMMA)
+               TYPED(num_exp, size)
+               TOKEN(RPAREN)) {
+       alloc = psi_let_calloc_init(nmemb, size);
+       alloc->token = T;
+}
+
+/*
+ * let_func: let_func_token ( impl_var )
+ */
+PARSE_TYPED(let_func, func,
+               NAMED(let_func_token, T)
+               TOKEN(LPAREN)
+               TYPED(impl_var, var)
+               TOKEN(RPAREN)) {
+       func = psi_let_func_init(T->type, T->text, var);
+       func->token = T;
+}
+/*
+ * let_func: let_func_token ( impl_var , let_exps )
+ */
+PARSE_TYPED(let_func, func,
+               NAMED(let_func_token, T)
+               TOKEN(LPAREN)
+               TYPED(impl_var, var)
+               TOKEN(COMMA)
+               TYPED(let_exps, vals)
+               TOKEN(RPAREN)) {
+       func = psi_let_func_init(T->type, T->text, var);
+       func->token = T;
+       func->inner = vals;
+}
+/*
+ * let_exps: let_exp
+ */
+PARSE_TYPED(let_exps, exps,
+               TYPED(let_exp, exp)) {
+       exps = psi_plist_add(psi_plist_init((psi_plist_dtor) psi_let_exp_free),
+                       &exp);
+}
+/*
+ * let_exps: let_exps , let_exp
+ */
+PARSE_TYPED(let_exps, exps,
+               TYPED(let_exps, exps_)
+               TOKEN(COMMA)
+               TYPED(let_exp, exp)) {
+       exps = psi_plist_add(exps_, &exp);
+}
+
+/*
+ * callback_arg_list: <empty>
+ */
+PARSE_TYPED(callback_arg_list, args, ) {
+       args = NULL;
+}
+
+/*
+ * callback_arg_list: callback_args
+ */
+PARSE_TYPED(callback_arg_list, args,
+               TYPED(callback_args, args_)) {
+       args = args_;
+}
+
+/*
+ * callback_args: set_exp
+ */
+PARSE_TYPED(callback_args, args,
+               TYPED(set_exp, val)) {
+       args = psi_plist_add(psi_plist_init((psi_plist_dtor) psi_set_exp_free),
+                       &val);
+}
+
+/*
+ * callback_args: callback_args , set_exp
+ */
+PARSE_TYPED(callback_args, args,
+               TYPED(callback_args, args_)
+               TOKEN(COMMA)
+               TYPED(set_exp, val)) {
+       args = psi_plist_add(args_, &val);
+}
+
+/*
+ * callback_rval: let_func_token
+ */
+PARSE_NAMED(callback_rval, rval,
+               NAMED(let_func_token, F)) {
+       rval = F;
+}
+
+/*
+ * callback_rval: VOID
+ */
+PARSE_NAMED(callback_rval, rval,
+               NAMED(VOID, V)) {
+       rval = V;
+}
+
+
+/*
+ * set_func: set_func_token ( decl_var )
+ */
+PARSE_TYPED(set_func, func,
+               NAMED(set_func_token, T)
+               TOKEN(LPAREN)
+               TYPED(decl_var, var)
+               TOKEN(RPAREN)) {
+       func = psi_set_func_init(T->type, T->text, var);
+       func->token = T;
+}
+
+/*
+ * set_func: set_func_token ( decl_var , set_exps )
+ */
+PARSE_TYPED(set_func, func,
+               NAMED(set_func_token, T)
+               TOKEN(LPAREN)
+               TYPED(decl_var, var)
+               TOKEN(COMMA)
+               TYPED(set_exps, vals)
+               TOKEN(RPAREN)) {
+       func = psi_set_func_init(T->type, T->text, var);
+       func->token = T;
+       func->inner = vals;
+}
+
+/*
+ * set_func: set_func_token ( decl_var , ... )
+ */
+PARSE_TYPED(set_func, func,
+               NAMED(set_func_token, T)
+               TOKEN(LPAREN)
+               TYPED(decl_var, var)
+               TOKEN(COMMA)
+               TOKEN(ELLIPSIS)
+               TOKEN(RPAREN)) {
+       func = psi_set_func_init(T->type, T->text, var);
+       func->token = T;
+       func->recursive = 1;
+}
+
+/*
+ * set_exp: set_func
+ */
+PARSE_TYPED(set_exp, val,
+               TYPED(set_func, fn)) {
+       val = psi_set_exp_init(PSI_SET_FUNC, fn);
+}
+
+/*
+ * set_exp: num_exp
+ */
+PARSE_TYPED(set_exp, val,
+               TYPED(num_exp, num)) {
+       val = psi_set_exp_init(PSI_SET_NUMEXP, num);
+}
+
+/*
+ * set_exps: set_exp
+ */
+PARSE_TYPED(set_exps, exps,
+               TYPED(set_exp, exp)) {
+       exps = psi_plist_add(psi_plist_init((psi_plist_dtor) psi_set_exp_free),
+                       &exp);
+}
+
+/*
+ * set_exps: set_exps , set_exp
+ */
+PARSE_TYPED(set_exps, exps,
+               TYPED(set_exps, exps_)
+               TOKEN(COMMA)
+               TYPED(set_exp, exp)) {
+       exps = psi_plist_add(exps_, &exp);
+}
+
+/* FIXME
+ * set_exp: impl_var = set_exp
+ */
+PARSE_TYPED(set_exp, exp,
+               TYPED(impl_var, var_)
+               TOKEN(EQUALS)
+               TYPED(set_exp, val)) {
+       exp = val;
+       exp->var = var_;
+}
+
+/*
+ * set_stmt: SET set_exp ;
+ */
+PARSE_TYPED(set_stmt, set,
+               NAMED(SET, T)
+               TYPED(set_exp, exp)
+               TOKEN(EOS)) {
+       set = psi_set_stmt_init(exp);
+       set->token = T;
+}
+
+/*
+ * return_stmt: RETURN set_exp ;
+ */
+PARSE_TYPED(return_stmt, ret,
+               NAMED(RETURN, T)
+               TYPED(set_func, func)
+               TOKEN(EOS)) {
+       ret = psi_return_stmt_init(psi_set_exp_init(PSI_SET_FUNC, func));
+       ret->token = T;
+}
+
+/*
+ * free_stmt: FREE free_exps ;
+ */
+PARSE_TYPED(free_stmt, free,
+               NAMED(FREE, T)
+               TYPED(free_exps, calls)
+               TOKEN(EOS)) {
+       free = psi_free_stmt_init(calls);
+       free->token = T;
+}
+
+/*
+ * free_exps: free_exp
+ */
+PARSE_TYPED(free_exps, calls,
+               TYPED(free_exp, call)) {
+       calls = psi_plist_add(psi_plist_init((psi_plist_dtor) psi_free_exp_free),
+                       &call);
+}
+
+/*
+ * free_exps: free_exps , free_exp
+ */
+PARSE_TYPED(free_exps, calls,
+               TYPED(free_exps, calls_)
+               TOKEN(COMMA)
+               TYPED(free_exp, call)) {
+       calls = psi_plist_add(calls_, &call);
+}
+
+/*
+ * free_exp: NAME ( decl_vars )
+ */
+PARSE_TYPED(free_exp, call,
+               NAMED(NAME, F)
+               TOKEN(LPAREN)
+               TYPED(decl_vars, vars)
+               TOKEN(RPAREN)) {
+       call = psi_free_exp_init(F->text, vars);
+       call->token = F;
+}
+
+/*
+ * assert_stmt: assert_stmt_token num_exp ;
+ */
+PARSE_TYPED(assert_stmt, ass,
+               NAMED(assert_stmt_token, T)
+               TYPED(num_exp, exp)
+               TOKEN(EOS)) {
+       ass = psi_assert_stmt_init(T->type, exp);
+       ass->token = T;
+}
+
+/*
+ * reference: <empty>
+ */
+PARSE_TYPED(reference, r, ) {
+       r = false;
+}
+
+/*
+ * reference: &
+ */
+PARSE_TYPED(reference, r,
+               TOKEN(AMPERSAND)) {
+       r = true;
+}
+
+/*
+ * indirection: <empty>
+ */
+PARSE_TYPED(indirection, i, ){
+       i = 0;
+}
+
+/*
+ * indirection: pointers
+ */
+PARSE_TYPED(indirection, i,
+               TYPED(pointers, p)) {
+       i = p;
+}
+
+/*
+ * pointers: *
+ */
+PARSE_TYPED(pointers, p,
+               TOKEN(ASTERISK)) {
+       p = 1;
+}
+
+/*
+ * pointers: pointers *
+ */
+PARSE_TYPED(pointers, p,
+               TYPED(pointers, p_)
+               TOKEN(ASTERISK)) {
+       p = p_+1;
+}
index 2c00c4a1f71d9a08af43ef59d88645621d90f7e9..7b298be4541525a163e701f70c96c53eaaef2dd1 100644 (file)
@@ -37,12 +37,17 @@ struct psi_plist {
 #define PLIST_ELE(l, i) (((char *)(l)->list) + (l)->size * (i))
 #define PLIST_CPY(list, dest, src) do { \
        if (list->size == sizeof(void *)) { \
-               *(void **)dest = *(void **)src; \
+               *(void **)(dest) = *(void **)(src); \
        } else { \
                memcpy(dest, src, list->size); \
        } \
 } while (0)
-#define PLIST_MOV(l, i) memmove(PLIST_ELE(l, i), PLIST_ELE(l, i + 1), (l)->size * ((l)->count - i))
+/* !!! adjust list->count prior reduction */
+#define PLIST_MOV_REDUCE(l, i) PLIST_MOV_REDUCE_EX(l, i, 1)
+#define PLIST_MOV_REDUCE_EX(l, i, n) memmove(PLIST_ELE(l, i), PLIST_ELE(l, i + n), (l)->size * ((l)->count - i))
+/* !!! adjust list->count after expansion */
+#define PLIST_MOV_EXPAND(l, i) PLIST_MOV_EXPAND_EX(l, i, 1)
+#define PLIST_MOV_EXPAND_EX(l, i, n) memmove(PLIST_ELE(l, i + n), PLIST_ELE(l, i), (l)->size * ((l)->count - i))
 
 struct psi_plist *psi_plist_init(void (*dtor)(void *)) {
        return psi_plist_init_ex(0, dtor);
@@ -70,10 +75,32 @@ void psi_plist_free(struct psi_plist *list) {
        free(list);
 }
 
+struct psi_plist *psi_plist_copy(struct psi_plist *list, void (*ctor)(void *))
+{
+       size_t i;
+       struct psi_plist *copy = calloc(1, sizeof(*list) + list->size + list->count * list->size);
+
+       *copy = *list;
+       if (list->count) {
+               memcpy(copy->list, list->list, list->size * list->count);
+       }
+       if (ctor) {
+               for (i = 0; i < list->count; ++i) {
+                       void *ptr = PLIST_ELE(copy, i);
+                       ctor(ptr);
+               }
+       }
+       return copy;
+}
+
 size_t psi_plist_count(struct psi_plist *list) {
        return list ? list->count : 0;
 }
 
+void **psi_plist_eles(struct psi_plist *list) {
+       return list ? list->list : NULL;
+}
+
 struct psi_plist *psi_plist_add(struct psi_plist *list, void *ptr) {
        if (list && list->count) {
                list = realloc(list, sizeof(*list) + list->size + list->count * list->size);
@@ -98,20 +125,75 @@ bool psi_plist_del(struct psi_plist *list, size_t index, void *ptr) {
                        PLIST_CPY(list, ptr, PLIST_ELE(list, index));
                }
                if (--list->count > index) {
-                       PLIST_MOV(list, index);
+                       PLIST_MOV_REDUCE(list, index);
                }
                return true;
        }
        return false;
 }
 
+bool psi_plist_del_range(struct psi_plist *list, size_t offset_start, size_t num_eles, void **eles) {
+       if (list) {
+               size_t offset_end = offset_start + num_eles - 1;
+
+               if (list->count <= offset_end) {
+                       offset_end = list->count - 1;
+               }
+               if (offset_end >= offset_start) {
+                       num_eles = 1 + offset_end - offset_start;
+
+                       if (eles) {
+                               memcpy(eles, PLIST_ELE(list, offset_start), num_eles * list->size);
+                       }
+
+                       if ((list->count -= num_eles)) {
+                               PLIST_MOV_REDUCE_EX(list, offset_start, num_eles);
+                       }
+                       return true;
+               }
+       }
+       return false;
+}
+
+struct psi_plist *psi_plist_ins(struct psi_plist *list, size_t index, void *ptr) {
+       size_t new_count = MAX(list->count + 1, index);
+
+       if (list && new_count) {
+               list = realloc(list, sizeof(*list) + list->size + new_count * list->size);
+       }
+       if (list) {
+               PLIST_MOV_EXPAND(list, index);
+               PLIST_CPY(list, PLIST_ELE(list, index), ptr);
+               list->count = new_count;
+       }
+       return list;
+}
+
+struct psi_plist *psi_plist_ins_range(struct psi_plist *list, size_t offset_start, size_t num_eles, void **eles) {
+       size_t new_count = MAX(offset_start, list->count) + num_eles;
+
+       if (list && new_count) {
+               list = realloc(list, sizeof(*list) + list->size + new_count * list->size);
+       }
+       if (list) {
+               size_t e;
+
+               PLIST_MOV_EXPAND_EX(list, offset_start, num_eles);
+               for (e = 0; e < num_eles; ++e) {
+                       PLIST_CPY(list, PLIST_ELE(list, offset_start + e), &eles[e]);
+               }
+               list->count = new_count;
+       }
+       return list;
+}
+
 bool psi_plist_shift(struct psi_plist *list, void *ptr) {
        if (list && list->count) {
                if (ptr) {
                        PLIST_CPY(list, ptr, PLIST_ELE(list, 0));
                }
                if (--list->count) {
-                       PLIST_MOV(list, 0);
+                       PLIST_MOV_REDUCE(list, 0);
                }
                return true;
        }
@@ -153,4 +235,3 @@ void psi_plist_sort(struct psi_plist *list, compare_func_t cmp, swap_func_t swp)
        assert(swp);
        zend_insert_sort((void *) list->list, list->count, list->size, cmp, swp);
 }
-
index 676ce41b36b3e03ec4c389868fd78ebfee78975a..bca0d85ded589454114d025d8cd0b9f50aebb75f 100644 (file)
@@ -33,12 +33,18 @@ typedef void (*psi_plist_dtor)(void *);
 struct psi_plist *psi_plist_init(void (*dtor)(void *));
 struct psi_plist *psi_plist_init_ex(size_t size, void (*dtor)(void *));
 void psi_plist_free(struct psi_plist *list);
+struct psi_plist *psi_plist_copy(struct psi_plist *list, void (*ctor)(void *));
 
 size_t psi_plist_count(struct psi_plist *list);
+void **psi_plist_eles(struct psi_plist *list);
 
 struct psi_plist *psi_plist_add(struct psi_plist *list, void *ptr);
 bool psi_plist_get(struct psi_plist *list, size_t index, void *ptr);
 bool psi_plist_del(struct psi_plist *list, size_t index, void *ptr);
+bool psi_plist_del_range(struct psi_plist *list, size_t offset_start, size_t offset_end, void **eles);
+struct psi_plist *psi_plist_ins(struct psi_plist *list, size_t index, void *ptr);
+struct psi_plist *psi_plist_ins_range(struct psi_plist *list, size_t offset_start, size_t num_eles, void **eles);
+
 bool psi_plist_shift(struct psi_plist *list, void *ptr);
 bool psi_plist_pop(struct psi_plist *list, void *ptr);
 bool psi_plist_top(struct psi_plist *list, void *ptr);
index 01c45f10e0b1932e5a5bbcdf5920c290c0fe6fab..ec8c4e93ca764c182ad38e73d9be1fa9a1cb1e2f 100644 (file)
@@ -25,6 +25,8 @@
 
 #include "php_psi_stdinc.h"
 
+#include <ctype.h>
+
 #include "token.h"
 #include "parser.h"
 
@@ -59,6 +61,15 @@ struct psi_token *psi_token_alloc(struct psi_parser *P) {
        return T;
 }
 
+void psi_token_free(struct psi_token **token_ptr) {
+       if (*token_ptr) {
+               struct psi_token *token = *token_ptr;
+
+               *token_ptr = NULL;
+               free(token);
+       }
+}
+
 struct psi_token *psi_token_copy(struct psi_token *src) {
        size_t strct_len = psi_token_alloc_size(src->size, strlen(src->file));
        struct psi_token *ptr = malloc(strct_len);
@@ -71,6 +82,10 @@ struct psi_token *psi_token_copy(struct psi_token *src) {
        return ptr;
 }
 
+void psi_token_copy_ctor(struct psi_token **tok) {
+       *tok = psi_token_copy(*tok);
+}
+
 struct psi_token *psi_token_cat(unsigned argc, ...) {
        va_list argv;
        unsigned i;
@@ -162,3 +177,49 @@ uint64_t psi_token_hash(struct psi_token *t, char *digest_buf) {
        sprintf(loc_buf, "%u%u", t->line, t->col);
        return psi_hash(digest_buf, t->file, loc_buf, (char *) NULL);
 }
+
+void psi_token_dump(int fd, struct psi_token *t)
+{
+       size_t i;
+
+       dprintf(fd, "TOKEN %p (%d) \"", t, t->type);
+       for (i = 0; i < MIN(t->size, 16); ++i) {
+               switch (t->text[i]) {
+               case '\0':
+                       dprintf(fd, "\\0");
+                       break;
+               case '\a':
+                       dprintf(fd, "\\a");
+                       break;
+               case '\b':
+                       dprintf(fd, "\\b");
+                       break;
+               case '\f':
+                       dprintf(fd, "\\f");
+                       break;
+               case '\n':
+                       dprintf(fd, "\\n");
+                       break;
+               case '\r':
+                       dprintf(fd, "\\r");
+                       break;
+               case '\t':
+                       dprintf(fd, "\\t");
+                       break;
+               case '\v':
+                       dprintf(fd, "\\v");
+                       break;
+               case '"':
+                       dprintf(fd, "\\\"");
+                       break;
+               default:
+                       if (isprint(t->text[i])) {
+                               dprintf(fd, "%c", t->text[i]);
+                       } else {
+                               dprintf(fd, "\\%03hho", t->text[i]);
+                       }
+                       break;
+               }
+       }
+       dprintf(fd, "\" at col %u in %s on line %u\n", t->col, t->file, t->line);
+}
index 5062bc5d8eb42b3ffbe64d1f35daac03a0d138f9..93625daef0270e654f32e8bc12e08a18636fedbd 100644 (file)
@@ -48,6 +48,8 @@ static inline size_t psi_offset_padding(size_t diff, size_t alignment) {
 
 #define PSI_T_POINTER PSI_T_ASTERISK
 #define PSI_T_LONG_DOUBLE (PSI_T_DOUBLE << 16)
+#define PSI_T_BSLASH (PSI_T_SLASH << 16)
+#define PSI_T_WHITESPACE -PSI_T_NO_WHITESPACE
 
 typedef int token_t;
 
@@ -137,9 +139,12 @@ struct psi_parser;
 struct psi_token *psi_token_alloc(struct psi_parser *P);
 size_t psi_token_alloc_size(size_t token_len, size_t fname_len);
 struct psi_token *psi_token_copy(struct psi_token *src);
+void psi_token_copy_ctor(struct psi_token **src);
 struct psi_token *psi_token_cat(unsigned argc, ...);
 struct psi_token *psi_token_append(struct psi_token *T, unsigned argc, ...);
 struct psi_token *psi_token_translit(struct psi_token *T, char *from, char *to);
 uint64_t psi_token_hash(struct psi_token *t, char *digest_buf);
+void psi_token_dump(int fd, struct psi_token *t);
+void psi_token_free(struct psi_token **token);
 
 #endif
index 5497880fb60b7c1f99ffc936dde6dd592477ab87..58a50f55e4697d60d4bf9a9831bdfa12889f6b3a 100644 (file)
@@ -62,6 +62,9 @@
 #include "types/free_stmt.h"
 #include "types/assert_stmt.h"
 #include "types/layout.h"
+#include "types/cpp_exp.h"
+#include "types/cpp_macro_call.h"
+#include "types/cpp_macro_decl.h"
 
 static inline impl_val *deref_impl_val(impl_val *ret_val, struct psi_decl_var *var) {
        unsigned i;
index 084f9fc192431803b12d1c99d8875bf27fe4b93f..ba86758d70254cc18c32b826d0b38e0b11cc93f3 100644 (file)
@@ -62,7 +62,7 @@ void psi_assert_stmt_dump(int fd, struct psi_assert_stmt *stmt)
 bool psi_assert_stmt_exec(struct psi_assert_stmt *stmt, struct psi_call_frame *frame)
 {
        impl_val res, chk;
-       token_t res_type = psi_num_exp_exec(stmt->exp, &res, frame);
+       token_t res_type = psi_num_exp_exec(stmt->exp, &res, frame, NULL);
 
        psi_calc_cast(res_type, &res, PSI_T_UINT8, &chk);
        return chk.u8;
diff --git a/src/types/cpp_exp.c b/src/types/cpp_exp.c
new file mode 100644 (file)
index 0000000..f2a29bc
--- /dev/null
@@ -0,0 +1,120 @@
+/*******************************************************************************
+ Copyright (c) 2017, Michael Wallner <mike@php.net>.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+     * Redistributions of source code must retain the above copyright notice,
+       this list of conditions and the following disclaimer.
+     * Redistributions in binary form must reproduce the above copyright
+       notice, this list of conditions and the following disclaimer in the
+       documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+#include "php_psi_stdinc.h"
+
+#include <assert.h>
+
+#include "data.h"
+
+struct psi_cpp_exp *psi_cpp_exp_init(token_t type, void *data)
+{
+       struct psi_cpp_exp *exp = calloc(1, sizeof(*exp));
+
+       switch ((exp->type = type)) {
+       case PSI_T_WARNING:
+       case PSI_T_ERROR:
+       case PSI_T_IFDEF:
+       case PSI_T_IFNDEF:
+               exp->data.tok = data;
+               break;
+       case PSI_T_DEFINE:
+               exp->data.decl = data;
+               break;
+       case PSI_T_IF:
+       case PSI_T_ELIF:
+               exp->data.num = data;
+               break;
+       case PSI_T_ENDIF:
+       case PSI_T_ELSE:
+               break;
+       default:
+               assert(0);
+               break;
+       }
+       return exp;
+}
+
+void psi_cpp_exp_free(struct psi_cpp_exp **exp_ptr)
+{
+       if (*exp_ptr) {
+               struct psi_cpp_exp *exp = *exp_ptr;
+
+               *exp_ptr = NULL;
+               switch (exp->type) {
+               case PSI_T_WARNING:
+               case PSI_T_ERROR:
+               case PSI_T_IFDEF:
+               case PSI_T_IFNDEF:
+                       free(exp->data.tok);
+                       exp->data.tok = NULL;
+                       break;
+               case PSI_T_DEFINE:
+                       psi_cpp_macro_decl_free(&exp->data.decl);
+                       break;
+               case PSI_T_IF:
+               case PSI_T_ELIF:
+                       psi_num_exp_free(&exp->data.num);
+                       break;
+               case PSI_T_ENDIF:
+               case PSI_T_ELSE:
+                       break;
+               default:
+                       assert(0);
+                       break;
+               }
+               if (exp->token) {
+                       free(exp->token);
+               }
+               free(exp);
+       }
+}
+
+void psi_cpp_exp_dump(int fd, struct psi_cpp_exp *exp)
+{
+       dprintf(fd, "#%s ", exp->token->text);
+       switch (exp->type) {
+       case PSI_T_WARNING:
+       case PSI_T_ERROR:
+       case PSI_T_IFDEF:
+       case PSI_T_IFNDEF:
+               dprintf(fd, "%s", exp->data.tok->text);
+               break;
+       case PSI_T_DEFINE:
+               psi_cpp_macro_decl_dump(fd, exp->data.decl);
+               break;
+       case PSI_T_IF:
+       case PSI_T_ELIF:
+               psi_num_exp_dump(fd, exp->data.num);
+               break;
+       case PSI_T_ENDIF:
+       case PSI_T_ELSE:
+               break;
+       default:
+               assert(0);
+               break;
+       }
+       dprintf(fd, "\n");
+}
diff --git a/src/types/cpp_exp.h b/src/types/cpp_exp.h
new file mode 100644 (file)
index 0000000..e66c218
--- /dev/null
@@ -0,0 +1,49 @@
+/*******************************************************************************
+ Copyright (c) 2017, Michael Wallner <mike@php.net>.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+     * Redistributions of source code must retain the above copyright notice,
+       this list of conditions and the following disclaimer.
+     * Redistributions in binary form must reproduce the above copyright
+       notice, this list of conditions and the following disclaimer in the
+       documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+#ifndef PSI_TYPES_CPP_EXP_H
+#define PSI_TYPES_CPP_EXP_H
+
+#include "token.h"
+
+struct psi_cpp_macro_decl;
+struct psi_cpp_macro_call;
+struct psi_num_exp;
+
+struct psi_cpp_exp {
+       struct psi_token *token;
+       token_t type;
+       union {
+               struct psi_cpp_macro_decl *decl;
+               struct psi_num_exp *num;
+               struct psi_token *tok;
+       } data;
+};
+
+struct psi_cpp_exp *psi_cpp_exp_init(token_t type, void *data);
+void psi_cpp_exp_free(struct psi_cpp_exp **exp_ptr);
+void psi_cpp_exp_dump(int fd, struct psi_cpp_exp *exp);
+
+#endif
diff --git a/src/types/cpp_macro_call.c b/src/types/cpp_macro_call.c
new file mode 100644 (file)
index 0000000..0df9adb
--- /dev/null
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ Copyright (c) 2017, Michael Wallner <mike@php.net>.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+     * Redistributions of source code must retain the above copyright notice,
+       this list of conditions and the following disclaimer.
+     * Redistributions in binary form must reproduce the above copyright
+       notice, this list of conditions and the following disclaimer in the
+       documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+#include "php_psi_stdinc.h"
+
+#include "cpp.h"
+#include "data.h"
+
+struct psi_cpp_macro_call *psi_cpp_macro_call_init(const char *name,
+               struct psi_plist *args)
+{
+       struct psi_cpp_macro_call *call = calloc(1, sizeof(*call));
+       call->name = strdup(name);
+       call->args = args;
+       return call;
+}
+
+struct psi_cpp_macro_call *psi_cpp_macro_call_copy(
+               struct psi_cpp_macro_call *call)
+{
+       struct psi_cpp_macro_call *copy = calloc(1, sizeof(*copy));
+       copy->name = strdup(call->name);
+       if (call->token) {
+               copy->token = psi_token_copy(call->token);
+       }
+       if (call->args) {
+               copy->args = psi_plist_copy(call->args,
+                               (void (*)(void*)) psi_token_copy_ctor);
+       }
+       return copy;
+}
+
+void psi_cpp_macro_call_free(struct psi_cpp_macro_call **call_ptr)
+{
+       if (*call_ptr) {
+               struct psi_cpp_macro_call *call = *call_ptr;
+
+               *call_ptr = NULL;
+
+               free(call->name);
+               if (call->args) {
+                       psi_plist_free(call->args);
+               }
+               if (call->token) {
+                       free(call->token);
+               }
+               free(call);
+       }
+}
+
diff --git a/src/types/cpp_macro_call.h b/src/types/cpp_macro_call.h
new file mode 100644 (file)
index 0000000..5c8d9a8
--- /dev/null
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ Copyright (c) 2017, Michael Wallner <mike@php.net>.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+     * Redistributions of source code must retain the above copyright notice,
+       this list of conditions and the following disclaimer.
+     * Redistributions in binary form must reproduce the above copyright
+       notice, this list of conditions and the following disclaimer in the
+       documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+#ifndef CPP_MACRO_CALL_H
+#define CPP_MACRO_CALL_H
+
+struct psi_token;
+struct psi_plist;
+
+struct psi_cpp_macro_call {
+       struct psi_token *token;
+       char *name;
+       struct psi_plist *args;
+};
+
+struct psi_cpp_macro_call *psi_cpp_macro_call_init(const char *name,
+               struct psi_plist *args);
+struct psi_cpp_macro_call *psi_cpp_macro_call_copy(
+               struct psi_cpp_macro_call *call);
+void psi_cpp_macro_call_free(struct psi_cpp_macro_call **call_ptr);
+
+#endif
diff --git a/src/types/cpp_macro_decl.c b/src/types/cpp_macro_decl.c
new file mode 100644 (file)
index 0000000..bfa230c
--- /dev/null
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ Copyright (c) 2017, Michael Wallner <mike@php.net>.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+     * Redistributions of source code must retain the above copyright notice,
+       this list of conditions and the following disclaimer.
+     * Redistributions in binary form must reproduce the above copyright
+       notice, this list of conditions and the following disclaimer in the
+       documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+#include "php_psi_stdinc.h"
+
+#include "cpp.h"
+#include "data.h"
+
+struct psi_cpp_macro_decl *psi_cpp_macro_decl_init(struct psi_plist *sig,
+               struct psi_plist *tokens, struct psi_num_exp *exp)
+{
+       struct psi_cpp_macro_decl *macro = calloc(1, sizeof(*macro));
+       macro->exp = exp;
+       macro->sig = sig;
+       macro->tokens = tokens;
+       return macro;
+}
+
+void psi_cpp_macro_decl_free(struct psi_cpp_macro_decl **macro_ptr)
+{
+       if (*macro_ptr) {
+               struct psi_cpp_macro_decl *macro = *macro_ptr;
+
+               *macro_ptr = NULL;
+               if (macro->token) {
+                       free(macro->token);
+               }
+               if (macro->exp) {
+                       psi_num_exp_free(&macro->exp);
+               }
+               if (macro->sig) {
+                       psi_plist_free(macro->sig);
+               }
+               if (macro->tokens) {
+                       psi_plist_free(macro->tokens);
+               }
+               free(macro);
+       }
+}
+
+void psi_cpp_macro_decl_dump(int fd, struct psi_cpp_macro_decl *macro)
+{
+       dprintf(fd, "%s", macro->token->text);
+
+       if (macro->sig) {
+               size_t i = 0;
+               struct psi_token *tok;
+
+               dprintf(fd, "(");
+               while (psi_plist_get(macro->sig, i++, &tok)) {
+                       dprintf(fd, "%s%s", i>1?",":"", tok->text);
+               }
+               dprintf(fd, ")");
+       }
+}
diff --git a/src/types/cpp_macro_decl.h b/src/types/cpp_macro_decl.h
new file mode 100644 (file)
index 0000000..993d280
--- /dev/null
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ Copyright (c) 2017, Michael Wallner <mike@php.net>.
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+     * Redistributions of source code must retain the above copyright notice,
+       this list of conditions and the following disclaimer.
+     * Redistributions in binary form must reproduce the above copyright
+       notice, this list of conditions and the following disclaimer in the
+       documentation and/or other materials provided with the distribution.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*******************************************************************************/
+
+#ifndef PSI_TYPES_CPP_MACRO_DECL_H
+#define PSI_TYPES_CPP_MACRO_DECL_H
+
+struct psi_token;
+struct psi_plist;
+struct psi_num_exp;
+
+struct psi_cpp_macro_decl {
+       struct psi_token *token;
+       struct psi_num_exp *exp;
+       struct psi_plist *sig;
+       struct psi_plist *tokens;
+};
+
+struct psi_cpp_macro_decl *psi_cpp_macro_decl_init(struct psi_plist *sig,
+               struct psi_plist *tokens, struct psi_num_exp *exp);
+void psi_cpp_macro_decl_free(struct psi_cpp_macro_decl **macro_ptr);
+void psi_cpp_macro_decl_dump(int fd, struct psi_cpp_macro_decl *decl);
+
+#endif
index e39f0b071837e03843b9a04c320ba69074b8c109..32533e2c3343334fd59ba0ed15d3aaadece577d4 100644 (file)
@@ -100,7 +100,7 @@ bool psi_decl_enum_item_validate(struct psi_data *data,
                return false;
        }
 
-       item->val = psi_long_num_exp(item->num, NULL);
+       item->val = psi_long_num_exp(item->num, NULL, NULL);
 
        return true;
 }
index e24b4c28fd38ea19c3ddf75078088374bb288c40..cadefe23db5b848404043ee83429312b31207bbe 100644 (file)
@@ -96,6 +96,9 @@ bool psi_impl_def_val_validate(struct psi_data *data,
 
 void psi_impl_def_val_dump(int fd, struct psi_impl_def_val *val) {
        switch (val->type) {
+       case PSI_T_BOOL:
+               dprintf(fd, "%s", val->ival.zend.bval ? "true" : "false");
+               break;
        case PSI_T_INT:
                dprintf(fd, "%ld", val->ival.zend.lval);
                break;
index a9de6443ab198dbd9cbdc06ea312aa46e1e040d5..4600abfe37568ebce796de9e4a4dbc339d5695a1 100644 (file)
@@ -248,8 +248,8 @@ void *psi_let_exp_exec(struct psi_let_exp *val, struct psi_decl_arg *darg,
 
        case PSI_LET_CALLOC:
                {
-                       zend_long n = psi_long_num_exp(val->data.alloc->nmemb, frame);
-                       zend_long s = psi_long_num_exp(val->data.alloc->size, frame);
+                       zend_long n = psi_long_num_exp(val->data.alloc->nmemb, frame, NULL);
+                       zend_long s = psi_long_num_exp(val->data.alloc->size, frame, NULL);
                        void *tmp = *psi_call_frame_push_auto(frame,
                                        safe_emalloc(n, s, sizeof(void *)));
 
@@ -262,7 +262,7 @@ void *psi_let_exp_exec(struct psi_let_exp *val, struct psi_decl_arg *darg,
                {
                        impl_val res;
                        token_t val_type = psi_decl_type_get_real(val->var->arg->type)->type;
-                       token_t res_type = psi_num_exp_exec(val->data.num, &res, frame);
+                       token_t res_type = psi_num_exp_exec(val->data.num, &res, frame, NULL);
 
                        if (val_type == res_type) {
                                frame_sym->temp_val = res;
index 20a09c6900c6cdc09dfc7899d3dd257b2dd7bb02..9718cede62ba0fb56e1426f148036818e79061b3 100644 (file)
@@ -439,7 +439,7 @@ static inline void psi_num_exp_verify_result(token_t t, impl_val *res, struct ps
 }
 
 static void psi_num_exp_reduce(struct psi_num_exp *exp, struct psi_plist **output_ptr,
-               struct psi_plist **input_ptr, struct psi_call_frame *frame)
+               struct psi_plist **input_ptr, struct psi_call_frame *frame, HashTable *defs)
 {
        struct psi_plist *output = *output_ptr, *input = *input_ptr;
        struct element {
@@ -452,14 +452,14 @@ static void psi_num_exp_reduce(struct psi_num_exp *exp, struct psi_plist **outpu
 
        switch (exp->op) {
        case 0:
-               entry.type = psi_number_eval(exp->data.n, &entry.data.value, frame);
+               entry.type = psi_number_eval(exp->data.n, &entry.data.value, frame, defs);
                output = psi_plist_add(output, &entry);
                break;
 
        case PSI_T_LPAREN:
                entry.type = exp->op;
                input = psi_plist_add(input, &entry);
-               psi_num_exp_reduce(exp->data.u, &output, &input, frame);
+               psi_num_exp_reduce(exp->data.u, &output, &input, frame, defs);
                while (psi_plist_pop(input, &entry)) {
                        if (entry.type == PSI_T_LPAREN) {
                                break;
@@ -483,11 +483,11 @@ static void psi_num_exp_reduce(struct psi_num_exp *exp, struct psi_plist **outpu
                entry.type = exp->op;
                entry.data.calc = exp->calc;
                input = psi_plist_add(input, &entry);
-               psi_num_exp_reduce(exp->data.u, &output, &input, frame);
+               psi_num_exp_reduce(exp->data.u, &output, &input, frame, defs);
                break;
 
        default:
-               psi_num_exp_reduce(exp->data.b.lhs, &output, &input, frame);
+               psi_num_exp_reduce(exp->data.b.lhs, &output, &input, frame, defs);
                while (psi_plist_top(input, &entry)) {
                        /* bail out if exp->op > entry.type */
                        if (psi_calc_oper(exp->op, entry.type) == -1) {
@@ -500,7 +500,7 @@ static void psi_num_exp_reduce(struct psi_num_exp *exp, struct psi_plist **outpu
                entry.type = exp->op;
                entry.data.calc = exp->calc;
                input = psi_plist_add(input, &entry);
-               psi_num_exp_reduce(exp->data.b.rhs, &output, &input, frame);
+               psi_num_exp_reduce(exp->data.b.rhs, &output, &input, frame, defs);
                break;
        }
 
@@ -509,7 +509,7 @@ static void psi_num_exp_reduce(struct psi_num_exp *exp, struct psi_plist **outpu
 }
 
 token_t psi_num_exp_exec(struct psi_num_exp *exp, impl_val *res,
-               struct psi_call_frame *frame)
+               struct psi_call_frame *frame, HashTable *defs)
 {
        struct psi_plist *output, *input;
        struct element {
@@ -523,7 +523,7 @@ token_t psi_num_exp_exec(struct psi_num_exp *exp, impl_val *res,
        output = psi_plist_init_ex(sizeof(entry), NULL);
        input = psi_plist_init_ex(sizeof(entry), NULL);
 
-       psi_num_exp_reduce(exp, &output, &input, frame);
+       psi_num_exp_reduce(exp, &output, &input, frame, defs);
 
        while (psi_plist_pop(input, &entry)) {
                if (frame) PSI_DEBUG_PRINT(frame->context, " %s", psi_num_exp_op_tok(entry.type));
index ba44807020a44edbcf28febacc2648bd927cba2a..6e122bb867d665aacdc1f507a7fae7148e15aa3b 100644 (file)
@@ -66,14 +66,16 @@ bool psi_num_exp_validate(struct psi_data *data, struct psi_num_exp *exp,
                struct psi_let_exp *current_let, struct psi_set_exp *current_set,
                struct psi_decl_enum *current_enum);
 
-token_t psi_num_exp_exec(struct psi_num_exp *exp, impl_val *res, struct psi_call_frame *frame);
+token_t psi_num_exp_exec(struct psi_num_exp *exp, impl_val *res,
+               struct psi_call_frame *frame, HashTable *defs);
 
 #include <assert.h>
 
-static inline zend_long psi_long_num_exp(struct psi_num_exp *exp, struct psi_call_frame *frame) {
+static inline zend_long psi_long_num_exp(struct psi_num_exp *exp,
+               struct psi_call_frame *frame, HashTable *defs) {
        impl_val val = {0};
 
-       switch (psi_num_exp_exec(exp, &val, frame)) {
+       switch (psi_num_exp_exec(exp, &val, frame, defs)) {
        case PSI_T_UINT8:       return val.u8;
        case PSI_T_UINT16:      return val.u16;
        case PSI_T_UINT32:      return val.u32;
index bed5a249c79f3da70655d7c7577b648d8295fd63..aab8151c4d121406f92bdc94aa8f7dcca9937bbd 100644 (file)
@@ -30,7 +30,7 @@
 #include "data.h"
 #include "calc.h"
 #include "call.h"
-
+#include "parser.h"
 
 struct psi_number *psi_number_init(token_t t, void *num)
 {
@@ -69,11 +69,15 @@ struct psi_number *psi_number_init(token_t t, void *num)
                break;
        case PSI_T_NUMBER:
        case PSI_T_NSNAME:
+       case PSI_T_DEFINE:
                exp->data.numb = strdup(num);
                break;
        case PSI_T_NAME:
                exp->data.dvar = num;
                break;
+       case PSI_T_FUNCTION:
+               exp->data.call = num;
+               break;
        default:
                assert(0);
        }
@@ -98,11 +102,15 @@ struct psi_number *psi_number_copy(struct psi_number *exp)
                break;
        case PSI_T_NUMBER:
        case PSI_T_NSNAME:
+       case PSI_T_DEFINE:
                num->data.numb = strdup(num->data.numb);
                break;
        case PSI_T_NAME:
                num->data.dvar = psi_decl_var_copy(num->data.dvar);
                break;
+       case PSI_T_FUNCTION:
+               num->data.call = psi_cpp_macro_call_copy(num->data.call);
+               break;
        default:
                assert(0);
        }
@@ -124,8 +132,12 @@ void psi_number_free(struct psi_number **exp_ptr)
                case PSI_T_ENUM:
                case PSI_T_CONST:
                        break;
+               case PSI_T_FUNCTION:
+                       psi_cpp_macro_call_free(&exp->data.call);
+                       break;
                case PSI_T_NSNAME:
                case PSI_T_NUMBER:
+               case PSI_T_DEFINE:
                        free(exp->data.numb);
                        break;
                case PSI_T_NAME:
@@ -149,6 +161,7 @@ void psi_number_dump(int fd, struct psi_number *exp)
                break;
        case PSI_T_NUMBER:
        case PSI_T_NSNAME:
+       case PSI_T_DEFINE:
                dprintf(fd, "%s", exp->data.numb);
                break;
        case PSI_T_CONST:
@@ -197,6 +210,8 @@ bool psi_number_validate(struct psi_data *data, struct psi_number *exp,
        case PSI_T_INT64:
        case PSI_T_DOUBLE:
        case PSI_T_ENUM:
+       case PSI_T_DEFINE:
+       case PSI_T_FUNCTION:
                return true;
 
        case PSI_T_NAME:
@@ -302,7 +317,18 @@ static inline token_t psi_number_eval_decl_var(struct psi_number *exp,
        return real->type;
 }
 
-token_t psi_number_eval(struct psi_number *exp, impl_val *res, struct psi_call_frame *frame)
+static inline token_t psi_number_eval_define(struct psi_number *exp,
+               impl_val *res, HashTable *defs)
+{
+       struct psi_cpp_macro_decl *macro = zend_hash_str_find_ptr(defs, exp->data.numb, strlen(exp->data.numb));
+
+       //WHATT?
+
+       res->u8 = 0;
+       return PSI_T_UINT8;
+}
+
+token_t psi_number_eval(struct psi_number *exp, impl_val *res, struct psi_call_frame *frame, HashTable *defs)
 {
        switch (exp->type) {
        case PSI_T_INT64:
@@ -322,11 +348,16 @@ token_t psi_number_eval(struct psi_number *exp, impl_val *res, struct psi_call_f
 
        case PSI_T_CONST:
                return psi_number_eval_constant(exp, res, frame);
-               break;
 
        case PSI_T_NAME:
                return psi_number_eval_decl_var(exp, res, frame);
-               break;
+
+       case PSI_T_DEFINE:
+               return psi_number_eval_define(exp, res, defs);
+
+       case PSI_T_FUNCTION:
+               res->u8 = 0;
+               return PSI_T_UINT8;
 
        default:
                assert(0);
index e3d02e62504abb00b22d5d67975a885081029517..d7fa150e09e3de29cadcb3a16c9d0f066c0f6f0d 100644 (file)
@@ -35,6 +35,7 @@ struct psi_decl_enum_item;
 struct psi_let_exp;
 struct psi_set_exp;
 struct psi_call_frame;
+struct psi_cpp_macro_call;
 
 struct psi_number {
        struct psi_token *token;
@@ -45,6 +46,7 @@ struct psi_number {
                struct psi_const *cnst;
                struct psi_decl_var *dvar;
                struct psi_decl_enum_item *enm;
+               struct psi_cpp_macro_call *call;
        } data;
 };
 
@@ -58,6 +60,7 @@ bool psi_number_validate(struct psi_data *data, struct psi_number *exp,
                struct psi_let_exp *current_let, struct psi_set_exp *current_set,
                struct psi_decl_enum *current_enum);
 
-token_t psi_number_eval(struct psi_number *exp, impl_val *res, struct psi_call_frame *frame);
+token_t psi_number_eval(struct psi_number *exp, impl_val *res,
+               struct psi_call_frame *frame, HashTable *defs);
 
 #endif
index 4ae7a45f48ae1bc944b01b77e411cd575d4fb631..bbd7d8064b8b3c54daad6fe8457f86d8ffc34d47 100644 (file)
@@ -75,7 +75,7 @@ void psi_set_exp_exec_ex(struct psi_set_exp *val, zval *zv, impl_val *iv,
                val->data.func->handler(zv, val, iv, frame);
                break;
        case PSI_SET_NUMEXP:
-               switch (psi_num_exp_exec(val->data.num, iv, frame)) {
+               switch (psi_num_exp_exec(val->data.num, iv, frame, NULL)) {
                case PSI_T_FLOAT:
                case PSI_T_DOUBLE:
                case PSI_T_LONG_DOUBLE:
index 7c585b793bb7c89ff6c0302813a7f6166845c948..b8f3602205127f09558c98358d76e43e100e0706 100644 (file)
@@ -1,7 +1,7 @@
-# libidn
+// libidn
 lib "idn";
 
-# IDNA errors
+// IDNA errors
 const int \IDNA_SUCCESS = 0;
 const int \IDNA_STRINGPREP_ERROR = 1;
 const int \IDNA_PUNYCODE_ERROR = 2;
@@ -15,7 +15,7 @@ const int \IDNA_CONTAINS_ACE_PREFIX = 8;
 const int \IDNA_ICONV_ERROR = 9;
 const int \IDNA_MALLOC_ERROR = 201;
 const int \IDNA_DLOPEN_ERROR = 202;
-# IDNA flags
+// IDNA flags
 const int \IDNA_ALLOW_UNASSIGNED = 1;
 const int \IDNA_USE_STD3_ASCII_RULES = 2;
 
diff --git a/tests/parser/cpp/define001.psi b/tests/parser/cpp/define001.psi
new file mode 100644 (file)
index 0000000..875d447
--- /dev/null
@@ -0,0 +1,51 @@
+#define FOO
+#ifndef FOO
+# error FOO is not defined
+#endif
+
+#ifdef FOO
+# define BAR 1
+#else
+no error #here, yay!
+#endif
+
+#if BAR
+#      define BAZ
+#endif
+
+#ifndef BAZ
+error
+#endif
+
+#undef BAZ
+#ifdef BAZ
+#      error BAZ is defined
+#endif
+
+#ifndef _1
+# ifndef _2
+#  ifndef _3
+#  else
+    error 3
+#  endif
+# else
+   error 2
+# endif
+#else
+  error 1
+#endif
+
+
+#ifndef _1
+# ifdef _2
+   error 2
+# else
+
+enum a{b};
+
+# endif
+#else
+ error 1
+#endif
+
+enum b{a=b};
\ No newline at end of file