/* expression-parser.c generated by valac 0.56.19, the Vala compiler
 * generated from expression-parser.vala, do not modify */

/*
 * Copyright (c) 2024-2025 focus-timer contributors
 *
 * SPDX-License-Identifier: GPL-3.0-or-later
 *
 * Authors: Kamil Prusko <kamilprusko@gmail.com>
 */

#include "ft_core.h"
#include <glib-object.h>
#include <glib.h>
#include <stdlib.h>
#include <string.h>

#define FT_EXPRESSION_PARSER_BASE_OPERATOR_PRECEDENCE 1000U
#if !defined(VALA_STRICT_C)
#if !defined(__clang__) && defined(__GNUC__) && (__GNUC__ >= 14)
#pragma GCC diagnostic warning "-Wincompatible-pointer-types"
#elif defined(__clang__) && (__clang_major__ >= 16)
#pragma clang diagnostic ignored "-Wincompatible-function-pointer-types"
#pragma clang diagnostic ignored "-Wincompatible-pointer-types"
#endif
#endif

typedef enum  {
	FT_TOKEN_TYPE_INVALID,
	FT_TOKEN_TYPE_STRING_LITERAL,
	FT_TOKEN_TYPE_NUMERIC_LITERAL,
	FT_TOKEN_TYPE_IDENTIFIER,
	FT_TOKEN_TYPE_OPERATOR,
	FT_TOKEN_TYPE_PARENTHESIS
} FtTokenType;

#define FT_TYPE_TOKEN_TYPE (ft_token_type_get_type ())
typedef struct _FtToken FtToken;
#define _g_free0(var) (var = (g_free (var), NULL))
typedef struct _FtExpressionParser FtExpressionParser;
#define _g_hash_table_unref0(var) ((var == NULL) ? NULL : (var = (g_hash_table_unref (var), NULL)))
#define _g_string_free0(var) ((var == NULL) ? NULL : (var = (g_string_free (var, TRUE), NULL)))
#define _ft_token_free0(var) ((var == NULL) ? NULL : (var = (ft_token_free (var), NULL)))
#define _g_array_unref0(var) ((var == NULL) ? NULL : (var = (g_array_unref (var), NULL)))
#define _ft_value_unref0(var) ((var == NULL) ? NULL : (var = (ft_value_unref (var), NULL)))
#define _ft_expression_unref0(var) ((var == NULL) ? NULL : (var = (ft_expression_unref (var), NULL)))
#define _vala_assert(expr, msg) if G_LIKELY (expr) ; else g_assertion_message_expr (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);
#define _vala_return_if_fail(expr, msg) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return; }
#define _vala_return_val_if_fail(expr, msg, val) if G_LIKELY (expr) ; else { g_return_if_fail_warning (G_LOG_DOMAIN, G_STRFUNC, msg); return val; }
#define _vala_warn_if_fail(expr, msg) if G_LIKELY (expr) ; else g_warn_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, msg);

struct _FtToken {
	FtTokenType type;
	gint span_start;
	gint span_end;
	gchar* text;
	FtToken* prev;
	FtToken* next;
	FtToken* parent;
	FtToken* children;
	guint precedence;
	FtToken* matching_token;
};

struct _FtExpressionParser {
	GHashTable* operators;
};

VALA_EXTERN GType ft_token_type_get_type (void) G_GNUC_CONST ;
VALA_EXTERN void ft_token_free (FtToken * self);
static void ft_token_instance_init (FtToken * self);
VALA_EXTERN guint ft_token_n_children (FtToken* self);
VALA_EXTERN FtToken* ft_token_get_root (FtToken* self);
VALA_EXTERN void ft_token_append (FtToken* self,
                      FtToken* token);
VALA_EXTERN void ft_token_append_child (FtToken* self,
                            FtToken* token);
VALA_EXTERN void ft_token_insert_parent (FtToken* self,
                             FtToken* token);
VALA_EXTERN FtToken* ft_token_new (void);
VALA_EXTERN void ft_expression_parser_free (FtExpressionParser * self);
static void ft_expression_parser_instance_init (FtExpressionParser * self);
VALA_EXTERN FtExpressionParser* ft_expression_parser_new (void);
static void _g_free0_ (gpointer var);
static void __lambda60_ (FtExpressionParser* self,
                  FtOperator operator);
static void ___lambda60__gfunc (gconstpointer data,
                         gpointer self);
static gchar* ft_expression_parser_format_error_context (const gchar* text,
                                                  gint index,
                                                  guint limit);
static FtToken* ft_expression_parser_tokenize_string_literal (FtExpressionParser* self,
                                                       const gchar* text,
                                                       gint* index,
                                                       GError** error);
static FtToken* ft_expression_parser_tokenize_identifier (FtExpressionParser* self,
                                                   const gchar* text,
                                                   gint* index);
static FtToken* ft_expression_parser_tokenize_operator (FtExpressionParser* self,
                                                 const gchar* text,
                                                 gint* index,
                                                 GError** error);
static FtToken* ft_expression_parser_tokenize_numeric_literal (FtExpressionParser* self,
                                                        const gchar* text,
                                                        gint* index);
static GArray* ft_expression_parser_tokenize (FtExpressionParser* self,
                                       const gchar* text,
                                       GError** error);
static void _ft_token_free0_ (gpointer var);
static void _vala_FtToken_free_function_content_of (gpointer data);
static inline FtToken* ft_expression_parser_find_open_parenthesis (FtExpressionParser* self,
                                                     FtToken* token);
static inline gboolean ft_expression_parser_is_valid_token (FtExpressionParser* self,
                                              FtToken* token,
                                              FtToken* previous_token);
static inline gboolean ft_expression_parser_is_valid_expression (FtExpressionParser* self,
                                                   FtToken* last_token);
static inline guint ft_expression_parser_determine_precedence (FtExpressionParser* self,
                                                 FtToken* token,
                                                 FtToken* previous_token);
VALA_EXTERN guint ft_operator_get_precedence (FtOperator self);
static inline FtToken* ft_expression_parser_link_tokens (FtExpressionParser* self,
                                           FtToken* token,
                                           FtToken* previous_token);
VALA_EXTERN FtToken* ft_expression_parser_build_token_tree (FtExpressionParser* self,
                                                GArray* tokens,
                                                GError** error);
static inline FtValue* ft_expression_parser_cast_string_literal (FtExpressionParser* self,
                                                   const gchar* text);
static inline FtValue* ft_expression_parser_cast_numeric_literal (FtExpressionParser* self,
                                                    const gchar* text);
static inline FtExpression* ft_expression_parser_interpret_identifier (FtExpressionParser* self,
                                                         FtToken* token,
                                                         GError** error);
static inline FtExpression* ft_expression_parser_interpret_operator (FtExpressionParser* self,
                                                       FtToken* token,
                                                       GError** error);
static FtExpression* ft_expression_parser_interpret (FtExpressionParser* self,
                                              FtToken* token,
                                              GError** error);
static FtExpression** _vala_array_dup11 (FtExpression** self,
                                  gssize length);
VALA_EXTERN FtExpression* ft_expression_parser_parse (FtExpressionParser* self,
                                          const gchar* text,
                                          GError** error);
static void _vala_array_destroy (gpointer array,
                          gssize array_length,
                          GDestroyNotify destroy_func);
static void _vala_array_free (gpointer array,
                       gssize array_length,
                       GDestroyNotify destroy_func);
static inline gpointer _vala_memdup2 (gconstpointer mem,
                        gsize byte_size);

GQuark
ft_expression_parser_error_quark (void)
{
	return g_quark_from_static_string ("ft-expression-parser-error-quark");
}

static GType
ft_expression_parser_error_get_type_once (void)
{
	static const GEnumValue values[] = {{FT_EXPRESSION_PARSER_ERROR_SYNTAX_ERROR, "FT_EXPRESSION_PARSER_ERROR_SYNTAX_ERROR", "syntax-error"}, {FT_EXPRESSION_PARSER_ERROR_UNKNOWN_IDENTIFIER, "FT_EXPRESSION_PARSER_ERROR_UNKNOWN_IDENTIFIER", "unknown-identifier"}, {0, NULL, NULL}};
	GType ft_expression_parser_error_type_id;
	ft_expression_parser_error_type_id = g_enum_register_static ("FtExpressionParserError", values);
	return ft_expression_parser_error_type_id;
}

GType
ft_expression_parser_error_get_type (void)
{
	static volatile gsize ft_expression_parser_error_type_id__once = 0;
	if (g_once_init_enter (&ft_expression_parser_error_type_id__once)) {
		GType ft_expression_parser_error_type_id;
		ft_expression_parser_error_type_id = ft_expression_parser_error_get_type_once ();
		g_once_init_leave (&ft_expression_parser_error_type_id__once, ft_expression_parser_error_type_id);
	}
	return ft_expression_parser_error_type_id__once;
}

static GType
ft_token_type_get_type_once (void)
{
	static const GEnumValue values[] = {{FT_TOKEN_TYPE_INVALID, "FT_TOKEN_TYPE_INVALID", "invalid"}, {FT_TOKEN_TYPE_STRING_LITERAL, "FT_TOKEN_TYPE_STRING_LITERAL", "string-literal"}, {FT_TOKEN_TYPE_NUMERIC_LITERAL, "FT_TOKEN_TYPE_NUMERIC_LITERAL", "numeric-literal"}, {FT_TOKEN_TYPE_IDENTIFIER, "FT_TOKEN_TYPE_IDENTIFIER", "identifier"}, {FT_TOKEN_TYPE_OPERATOR, "FT_TOKEN_TYPE_OPERATOR", "operator"}, {FT_TOKEN_TYPE_PARENTHESIS, "FT_TOKEN_TYPE_PARENTHESIS", "parenthesis"}, {0, NULL, NULL}};
	GType ft_token_type_type_id;
	ft_token_type_type_id = g_enum_register_static ("FtTokenType", values);
	return ft_token_type_type_id;
}

GType
ft_token_type_get_type (void)
{
	static volatile gsize ft_token_type_type_id__once = 0;
	if (g_once_init_enter (&ft_token_type_type_id__once)) {
		GType ft_token_type_type_id;
		ft_token_type_type_id = ft_token_type_get_type_once ();
		g_once_init_leave (&ft_token_type_type_id__once, ft_token_type_type_id);
	}
	return ft_token_type_type_id__once;
}

guint
ft_token_n_children (FtToken* self)
{
	FtToken* child = NULL;
	FtToken* _tmp0_;
	guint n_children = 0U;
	guint result;
	g_return_val_if_fail (self != NULL, 0U);
	_tmp0_ = self->children;
	child = _tmp0_;
	n_children = 0U;
	while (TRUE) {
		FtToken* _tmp1_;
		FtToken* _tmp2_;
		FtToken* _tmp3_;
		guint _tmp4_;
		_tmp1_ = child;
		if (!(_tmp1_ != NULL)) {
			break;
		}
		_tmp2_ = child;
		_tmp3_ = _tmp2_->next;
		child = _tmp3_;
		_tmp4_ = n_children;
		n_children = _tmp4_ + 1;
	}
	result = n_children;
	return result;
}

FtToken*
ft_token_get_root (FtToken* self)
{
	FtToken* root = NULL;
	FtToken* _tmp4_;
	FtToken* result;
	g_return_val_if_fail (self != NULL, NULL);
	root = self;
	while (TRUE) {
		FtToken* _tmp0_;
		FtToken* _tmp1_;
		FtToken* _tmp2_;
		FtToken* _tmp3_;
		_tmp0_ = root;
		_tmp1_ = _tmp0_->parent;
		if (!(_tmp1_ != NULL)) {
			break;
		}
		_tmp2_ = root;
		_tmp3_ = _tmp2_->parent;
		root = _tmp3_;
	}
	_tmp4_ = root;
	result = _tmp4_;
	return result;
}

void
ft_token_append (FtToken* self,
                 FtToken* token)
{
	FtToken* _tmp0_;
	FtToken* last_token = NULL;
	FtToken* _tmp5_;
	FtToken* _tmp6_;
	FtToken* _tmp7_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (token != NULL);
	_tmp0_ = token->parent;
	_vala_return_if_fail (_tmp0_ == NULL, "token.parent == null");
	last_token = self;
	while (TRUE) {
		FtToken* _tmp1_;
		FtToken* _tmp2_;
		FtToken* _tmp3_;
		FtToken* _tmp4_;
		_tmp1_ = last_token;
		_tmp2_ = _tmp1_->next;
		if (!(_tmp2_ != NULL)) {
			break;
		}
		_tmp3_ = last_token;
		_tmp4_ = _tmp3_->next;
		last_token = _tmp4_;
	}
	_tmp5_ = last_token;
	_tmp5_->next = token;
	_tmp6_ = last_token;
	token->prev = _tmp6_;
	_tmp7_ = self->parent;
	token->parent = _tmp7_;
}

inline void
ft_token_append_child (FtToken* self,
                       FtToken* token)
{
	FtToken* _tmp0_;
	FtToken* _tmp1_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (token != NULL);
	_tmp0_ = token->parent;
	_vala_return_if_fail (_tmp0_ == NULL, "token.parent == null");
	_tmp1_ = self->children;
	if (_tmp1_ == NULL) {
		token->parent = self;
		self->children = token;
	} else {
		FtToken* _tmp2_;
		_tmp2_ = self->children;
		ft_token_append (_tmp2_, token);
	}
}

/**
         * Insert given token as a new parent.
         */
void
ft_token_insert_parent (FtToken* self,
                        FtToken* token)
{
	FtToken* _tmp0_;
	FtToken* _tmp1_;
	FtToken* _tmp2_;
	FtToken* _tmp3_;
	gboolean _tmp4_ = FALSE;
	FtToken* _tmp5_;
	FtToken* _tmp9_;
	FtToken* _tmp11_;
	FtToken* _tmp12_;
	g_return_if_fail (self != NULL);
	g_return_if_fail (token != NULL);
	_tmp0_ = token->parent;
	_tmp1_ = token->children;
	_vala_return_if_fail ((_tmp0_ == NULL) && (_tmp1_ == NULL), "token.parent == null && token.children == null");
	_tmp2_ = token->prev;
	_tmp3_ = token->next;
	_vala_return_if_fail ((_tmp2_ == NULL) && (_tmp3_ == NULL), "token.prev == null && token.next == null");
	_tmp5_ = self->parent;
	if (_tmp5_ != NULL) {
		FtToken* _tmp6_;
		FtToken* _tmp7_;
		_tmp6_ = self->parent;
		_tmp7_ = _tmp6_->children;
		_tmp4_ = _tmp7_ == self;
	} else {
		_tmp4_ = FALSE;
	}
	if (_tmp4_) {
		FtToken* _tmp8_;
		_tmp8_ = self->parent;
		_tmp8_->children = token;
	}
	_tmp9_ = self->prev;
	if (_tmp9_ != NULL) {
		FtToken* _tmp10_;
		_tmp10_ = self->prev;
		_tmp10_->next = token;
	}
	_tmp11_ = self->parent;
	token->parent = _tmp11_;
	_tmp12_ = self->prev;
	token->prev = _tmp12_;
	token->children = self;
	self->parent = token;
	self->prev = NULL;
}

FtToken*
ft_token_new (void)
{
	FtToken* self;
	self = g_slice_new0 (FtToken);
	ft_token_instance_init (self);
	return self;
}

static void
ft_token_instance_init (FtToken * self)
{
	self->precedence = 0U;
}

void
ft_token_free (FtToken * self)
{
	_g_free0 (self->text);
	self->text = NULL;
	self->prev = NULL;
	self->next = NULL;
	self->parent = NULL;
	self->children = NULL;
	self->matching_token = NULL;
	_g_free0 (self->text);
	g_slice_free (FtToken, self);
}

static void
_g_free0_ (gpointer var)
{
	var = (g_free (var), NULL);
}

static void
__lambda60_ (FtExpressionParser* self,
             FtOperator operator)
{
	GHashTable* _tmp0_;
	gchar* _tmp1_;
	_tmp0_ = self->operators;
	_tmp1_ = ft_operator_to_string (operator);
	g_hash_table_insert (_tmp0_, _tmp1_, (gpointer) ((gintptr) operator));
}

static void
___lambda60__gfunc (gconstpointer data,
                    gpointer self)
{
	__lambda60_ ((FtExpressionParser*) self, (FtOperator) ((gintptr) data));
}

FtExpressionParser*
ft_expression_parser_new (void)
{
	FtExpressionParser* self;
	GHashFunc _tmp0_;
	GEqualFunc _tmp1_;
	GHashTable* _tmp2_;
	self = g_slice_new0 (FtExpressionParser);
	ft_expression_parser_instance_init (self);
	_tmp0_ = g_str_hash;
	_tmp1_ = g_str_equal;
	_tmp2_ = g_hash_table_new_full (_tmp0_, _tmp1_, _g_free0_, NULL);
	_g_hash_table_unref0 (self->operators);
	self->operators = _tmp2_;
	ft_operator_foreach (___lambda60__gfunc, self);
	return self;
}

static gboolean
string_get_next_char (const gchar* self,
                      gint* index,
                      gunichar* c)
{
	gunichar _vala_c = 0U;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	_vala_c = g_utf8_get_char (((gchar*) self) + (*index));
	if (_vala_c != ((gunichar) 0)) {
		gchar* _tmp0_;
		_tmp0_ = g_utf8_next_char (((gchar*) self) + (*index));
		*index = (gint) (_tmp0_ - ((gchar*) self));
		result = TRUE;
		if (c) {
			*c = _vala_c;
		}
		return result;
	} else {
		result = FALSE;
		if (c) {
			*c = _vala_c;
		}
		return result;
	}
}

static glong
string_strnlen (gchar* str,
                glong maxlen)
{
	gchar* end = NULL;
	gchar* _tmp0_;
	gchar* _tmp1_;
	glong result;
	_tmp0_ = memchr (str, 0, (gsize) maxlen);
	end = _tmp0_;
	_tmp1_ = end;
	if (_tmp1_ == NULL) {
		result = maxlen;
		return result;
	} else {
		gchar* _tmp2_;
		_tmp2_ = end;
		result = (glong) (_tmp2_ - str);
		return result;
	}
}

static gchar*
string_substring (const gchar* self,
                  glong offset,
                  glong len)
{
	glong string_length = 0L;
	gboolean _tmp0_ = FALSE;
	gchar* _tmp3_;
	gchar* result;
	g_return_val_if_fail (self != NULL, NULL);
	if (offset >= ((glong) 0)) {
		_tmp0_ = len >= ((glong) 0);
	} else {
		_tmp0_ = FALSE;
	}
	if (_tmp0_) {
		string_length = string_strnlen ((gchar*) self, offset + len);
	} else {
		gint _tmp1_;
		gint _tmp2_;
		_tmp1_ = strlen (self);
		_tmp2_ = _tmp1_;
		string_length = (glong) _tmp2_;
	}
	if (offset < ((glong) 0)) {
		offset = string_length + offset;
		g_return_val_if_fail (offset >= ((glong) 0), NULL);
	} else {
		g_return_val_if_fail (offset <= string_length, NULL);
	}
	if (len < ((glong) 0)) {
		len = string_length - offset;
	}
	g_return_val_if_fail ((offset + len) <= string_length, NULL);
	_tmp3_ = g_strndup (((gchar*) self) + offset, (gsize) len);
	result = _tmp3_;
	return result;
}

static gchar*
ft_expression_parser_format_error_context (const gchar* text,
                                           gint index,
                                           guint limit)
{
	gint span_start = 0;
	gint span_end = 0;
	gint n = 0;
	gunichar chr = 0U;
	gchar* _tmp4_;
	gchar* _tmp5_;
	gchar* _tmp6_;
	gchar* _tmp7_;
	gchar* result;
	g_return_val_if_fail (text != NULL, NULL);
	span_start = index;
	span_end = index;
	n = 0;
	while (TRUE) {
		gboolean _tmp0_ = FALSE;
		gint _tmp3_;
		if (((guint) n) < limit) {
			gunichar _tmp1_ = 0U;
			gboolean _tmp2_;
			_tmp2_ = string_get_next_char (text, &span_end, &_tmp1_);
			chr = _tmp1_;
			_tmp0_ = _tmp2_;
		} else {
			_tmp0_ = FALSE;
		}
		if (!_tmp0_) {
			break;
		}
		_tmp3_ = n;
		n = _tmp3_ + 1;
	}
	_tmp4_ = string_substring (text, (glong) span_start, (glong) (span_end - span_start));
	_tmp5_ = _tmp4_;
	_tmp6_ = g_strdup_printf ("'%s...' at position %d", _tmp5_, span_start);
	_tmp7_ = _tmp6_;
	_g_free0 (_tmp5_);
	result = _tmp7_;
	return result;
}

static FtToken*
ft_expression_parser_tokenize_string_literal (FtExpressionParser* self,
                                              const gchar* text,
                                              gint* index,
                                              GError** error)
{
	FtToken* token = NULL;
	FtToken* _tmp0_ = NULL;
	gboolean is_escaped = FALSE;
	GString* string_builder = NULL;
	GString* _tmp1_;
	gunichar chr = 0U;
	gint _tmp2_;
	GError* _tmp17_;
	GError* _inner_error0_ = NULL;
	FtToken* result;
	g_return_val_if_fail (self != NULL, NULL);
	g_return_val_if_fail (text != NULL, NULL);
	_tmp0_ = ft_token_new ();
	_tmp0_->type = FT_TOKEN_TYPE_STRING_LITERAL;
	_tmp0_->span_start = *index;
	token = _tmp0_;
	is_escaped = FALSE;
	_tmp1_ = g_string_new ("");
	string_builder = _tmp1_;
	_tmp2_ = *index;
	*index = _tmp2_ + 1;
	while (TRUE) {
		gunichar _tmp3_ = 0U;
		gboolean _tmp4_;
		GString* _tmp16_;
		_tmp4_ = string_get_next_char (text, index, &_tmp3_);
		chr = _tmp3_;
		if (!_tmp4_) {
			break;
		}
		if (chr == ((gunichar) '\\')) {
			is_escaped = !is_escaped;
			continue;
		}
		if (is_escaped) {
			switch (chr) {
				case 'n':
				{
					GString* _tmp5_;
					_tmp5_ = string_builder;
					g_string_append (_tmp5_, "\n");
					break;
				}
				case 'r':
				{
					GString* _tmp6_;
					_tmp6_ = string_builder;
					g_string_append (_tmp6_, "\r");
					break;
				}
				case 't':
				{
					GString* _tmp7_;
					_tmp7_ = string_builder;
					g_string_append (_tmp7_, "\t");
					break;
				}
				case 'f':
				{
					GString* _tmp8_;
					_tmp8_ = string_builder;
					g_string_append (_tmp8_, "\f");
					break;
				}
				case 'b':
				{
					GString* _tmp9_;
					_tmp9_ = string_builder;
					g_string_append (_tmp9_, "\b");
					break;
				}
				default:
				{
					GString* _tmp10_;
					_tmp10_ = string_builder;
					g_string_append_unichar (_tmp10_, chr);
					break;
				}
			}
			is_escaped = FALSE;
			continue;
		}
		if (chr == ((gunichar) '"')) {
			FtToken* _tmp11_;
			FtToken* _tmp12_;
			GString* _tmp13_;
			const gchar* _tmp14_;
			gchar* _tmp15_;
			_tmp11_ = token;
			_tmp11_->span_end = *index;
			_tmp12_ = token;
			_tmp13_ = string_builder;
			_tmp14_ = _tmp13_->str;
			_tmp15_ = g_strdup (_tmp14_);
			_g_free0 (_tmp12_->text);
			_tmp12_->text = _tmp15_;
			result = token;
			_g_string_free0 (string_builder);
			return result;
		}
		_tmp16_ = string_builder;
		g_string_append_unichar (_tmp16_, chr);
	}
	_tmp17_ = g_error_new (FT_EXPRESSION_PARSER_ERROR, FT_EXPRESSION_PARSER_ERROR_SYNTAX_ERROR, "Unquoted string at %d", *index);
	_inner_error0_ = _tmp17_;
	if (_inner_error0_->domain == FT_EXPRESSION_PARSER_ERROR) {
		g_propagate_error (error, _inner_error0_);
		_g_string_free0 (string_builder);
		_ft_token_free0 (token);
		return NULL;
	} else {
		_g_string_free0 (string_builder);
		_ft_token_free0 (token);
		g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
		g_clear_error (&_inner_error0_);
		return NULL;
	}
}

static FtToken*
ft_expression_parser_tokenize_identifier (FtExpressionParser* self,
                                          const gchar* text,
                                          gint* index)
{
	FtToken* token = NULL;
	FtToken* _tmp0_ = NULL;
	gunichar chr = 0U;
	gint _tmp1_;
	FtToken* _tmp11_;
	FtToken* _tmp12_;
	FtToken* _tmp13_;
	FtToken* _tmp14_;
	gchar* _tmp15_;
	FtToken* result;
	g_return_val_if_fail (self != NULL, NULL);
	g_return_val_if_fail (text != NULL, NULL);
	_tmp0_ = ft_token_new ();
	_tmp0_->type = FT_TOKEN_TYPE_IDENTIFIER;
	_tmp0_->span_start = *index;
	_tmp0_->span_end = (*index) + 1;
	token = _tmp0_;
	_tmp1_ = *index;
	*index = _tmp1_ + 1;
	while (TRUE) {
		gunichar _tmp2_ = 0U;
		gboolean _tmp3_;
		gboolean _tmp4_ = FALSE;
		gboolean _tmp5_ = FALSE;
		gboolean _tmp6_ = FALSE;
		_tmp3_ = string_get_next_char (text, index, &_tmp2_);
		chr = _tmp2_;
		if (!_tmp3_) {
			break;
		}
		if (chr >= ((gunichar) 'a')) {
			_tmp6_ = chr <= ((gunichar) 'z');
		} else {
			_tmp6_ = FALSE;
		}
		if (_tmp6_) {
			_tmp5_ = TRUE;
		} else {
			gboolean _tmp7_ = FALSE;
			if (chr >= ((gunichar) 'A')) {
				_tmp7_ = chr <= ((gunichar) 'Z');
			} else {
				_tmp7_ = FALSE;
			}
			_tmp5_ = _tmp7_;
		}
		if (_tmp5_) {
			_tmp4_ = TRUE;
		} else {
			gboolean _tmp8_ = FALSE;
			if (chr >= ((gunichar) '0')) {
				_tmp8_ = chr <= ((gunichar) '9');
			} else {
				_tmp8_ = FALSE;
			}
			_tmp4_ = _tmp8_;
		}
		if (_tmp4_) {
			FtToken* _tmp9_;
			_tmp9_ = token;
			_tmp9_->span_end = *index;
			continue;
		} else {
			FtToken* _tmp10_;
			_tmp10_ = token;
			*index = _tmp10_->span_end;
			break;
		}
	}
	_tmp11_ = token;
	_tmp12_ = token;
	_tmp13_ = token;
	_tmp14_ = token;
	_tmp15_ = string_substring (text, (glong) _tmp12_->span_start, (glong) (_tmp13_->span_end - _tmp14_->span_start));
	_g_free0 (_tmp11_->text);
	_tmp11_->text = _tmp15_;
	result = token;
	return result;
}

static FtToken*
ft_expression_parser_tokenize_operator (FtExpressionParser* self,
                                        const gchar* text,
                                        gint* index,
                                        GError** error)
{
	FtToken* token = NULL;
	FtToken* _tmp0_ = NULL;
	gunichar chr = 0U;
	gint _tmp1_;
	FtToken* _tmp11_;
	FtToken* _tmp12_;
	FtToken* _tmp13_;
	FtToken* _tmp14_;
	gchar* _tmp15_;
	GHashTable* _tmp16_;
	FtToken* _tmp17_;
	const gchar* _tmp18_;
	GError* _inner_error0_ = NULL;
	FtToken* result;
	g_return_val_if_fail (self != NULL, NULL);
	g_return_val_if_fail (text != NULL, NULL);
	_tmp0_ = ft_token_new ();
	_tmp0_->type = FT_TOKEN_TYPE_OPERATOR;
	_tmp0_->span_start = *index;
	_tmp0_->span_end = (*index) + 1;
	token = _tmp0_;
	_tmp1_ = *index;
	*index = _tmp1_ + 1;
	while (TRUE) {
		gunichar _tmp2_ = 0U;
		gboolean _tmp3_;
		gboolean _tmp4_ = FALSE;
		gboolean _tmp5_ = FALSE;
		gboolean _tmp6_ = FALSE;
		gboolean _tmp7_ = FALSE;
		gboolean _tmp8_ = FALSE;
		_tmp3_ = string_get_next_char (text, index, &_tmp2_);
		chr = _tmp2_;
		if (!_tmp3_) {
			break;
		}
		if (chr == ((gunichar) '|')) {
			_tmp8_ = TRUE;
		} else {
			_tmp8_ = chr == ((gunichar) '&');
		}
		if (_tmp8_) {
			_tmp7_ = TRUE;
		} else {
			_tmp7_ = chr == ((gunichar) '=');
		}
		if (_tmp7_) {
			_tmp6_ = TRUE;
		} else {
			_tmp6_ = chr == ((gunichar) '!');
		}
		if (_tmp6_) {
			_tmp5_ = TRUE;
		} else {
			_tmp5_ = chr == ((gunichar) '>');
		}
		if (_tmp5_) {
			_tmp4_ = TRUE;
		} else {
			_tmp4_ = chr == ((gunichar) '<');
		}
		if (_tmp4_) {
			FtToken* _tmp9_;
			_tmp9_ = token;
			_tmp9_->span_end = *index;
		} else {
			FtToken* _tmp10_;
			_tmp10_ = token;
			*index = _tmp10_->span_end;
			break;
		}
	}
	_tmp11_ = token;
	_tmp12_ = token;
	_tmp13_ = token;
	_tmp14_ = token;
	_tmp15_ = string_substring (text, (glong) _tmp12_->span_start, (glong) (_tmp13_->span_end - _tmp14_->span_start));
	_g_free0 (_tmp11_->text);
	_tmp11_->text = _tmp15_;
	_tmp16_ = self->operators;
	_tmp17_ = token;
	_tmp18_ = _tmp17_->text;
	if (!g_hash_table_contains (_tmp16_, _tmp18_)) {
		FtToken* _tmp19_;
		const gchar* _tmp20_;
		GError* _tmp21_;
		_tmp19_ = token;
		_tmp20_ = _tmp19_->text;
		_tmp21_ = g_error_new (FT_EXPRESSION_PARSER_ERROR, FT_EXPRESSION_PARSER_ERROR_SYNTAX_ERROR, "Invalid operator '%s' at position %d", _tmp20_, *index);
		_inner_error0_ = _tmp21_;
		if (_inner_error0_->domain == FT_EXPRESSION_PARSER_ERROR) {
			g_propagate_error (error, _inner_error0_);
			_ft_token_free0 (token);
			return NULL;
		} else {
			_ft_token_free0 (token);
			g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
			g_clear_error (&_inner_error0_);
			return NULL;
		}
	}
	result = token;
	return result;
}

static FtToken*
ft_expression_parser_tokenize_numeric_literal (FtExpressionParser* self,
                                               const gchar* text,
                                               gint* index)
{
	FtToken* token = NULL;
	FtToken* _tmp0_ = NULL;
	gunichar chr = 0U;
	gint _tmp1_;
	FtToken* _tmp7_;
	FtToken* _tmp8_;
	FtToken* _tmp9_;
	FtToken* _tmp10_;
	gchar* _tmp11_;
	FtToken* result;
	g_return_val_if_fail (self != NULL, NULL);
	g_return_val_if_fail (text != NULL, NULL);
	_tmp0_ = ft_token_new ();
	_tmp0_->type = FT_TOKEN_TYPE_NUMERIC_LITERAL;
	_tmp0_->span_start = *index;
	_tmp0_->span_end = (*index) + 1;
	token = _tmp0_;
	_tmp1_ = *index;
	*index = _tmp1_ + 1;
	while (TRUE) {
		gunichar _tmp2_ = 0U;
		gboolean _tmp3_;
		gboolean _tmp4_ = FALSE;
		_tmp3_ = string_get_next_char (text, index, &_tmp2_);
		chr = _tmp2_;
		if (!_tmp3_) {
			break;
		}
		if (chr >= ((gunichar) '0')) {
			_tmp4_ = chr <= ((gunichar) '9');
		} else {
			_tmp4_ = FALSE;
		}
		if (_tmp4_) {
			FtToken* _tmp5_;
			_tmp5_ = token;
			_tmp5_->span_end = *index;
			continue;
		} else {
			FtToken* _tmp6_;
			_tmp6_ = token;
			*index = _tmp6_->span_end;
			break;
		}
	}
	_tmp7_ = token;
	_tmp8_ = token;
	_tmp9_ = token;
	_tmp10_ = token;
	_tmp11_ = string_substring (text, (glong) _tmp8_->span_start, (glong) (_tmp9_->span_end - _tmp10_->span_start));
	_g_free0 (_tmp7_->text);
	_tmp7_->text = _tmp11_;
	result = token;
	return result;
}

static void
_ft_token_free0_ (gpointer var)
{
	(var == NULL) ? NULL : (var = (ft_token_free (var), NULL));
}

static void
_vala_FtToken_free_function_content_of (gpointer data)
{
	FtToken* self;
	self = *((FtToken**) data);
	_ft_token_free0_ (self);
}

static gchar*
g_unichar_to_string (gunichar self)
{
	gchar* str = NULL;
	gchar* _tmp0_;
	gchar* result;
	_tmp0_ = g_new0 (gchar, 7);
	str = (gchar*) _tmp0_;
	g_unichar_to_utf8 (self, str);
	result = str;
	return result;
}

static GArray*
ft_expression_parser_tokenize (FtExpressionParser* self,
                               const gchar* text,
                               GError** error)
{
	GArray* tokens = NULL;
	GArray* _tmp0_;
	gunichar chr = 0U;
	gint chr_span_start = 0;
	gint chr_span_end = 0;
	GError* _inner_error0_ = NULL;
	GArray* result;
	g_return_val_if_fail (self != NULL, NULL);
	g_return_val_if_fail (text != NULL, NULL);
	_tmp0_ = g_array_sized_new (FALSE, TRUE, (gulong) 8U, (guint) 0);
	g_array_set_clear_func (_tmp0_, (GDestroyNotify) _vala_FtToken_free_function_content_of);
	tokens = _tmp0_;
	chr_span_start = 0;
	chr_span_end = 0;
	while (TRUE) {
		gunichar _tmp1_ = 0U;
		gboolean _tmp2_;
		_tmp2_ = string_get_next_char (text, &chr_span_end, &_tmp1_);
		chr = _tmp1_;
		if (!_tmp2_) {
			break;
		}
		switch (chr) {
			case ' ':
			{
				break;
			}
			case '(':
			case ')':
			{
				GArray* _tmp3_;
				gchar* _tmp4_;
				FtToken* _tmp5_ = NULL;
				_tmp3_ = tokens;
				_tmp4_ = g_unichar_to_string (chr);
				_tmp5_ = ft_token_new ();
				_tmp5_->type = FT_TOKEN_TYPE_PARENTHESIS;
				_tmp5_->span_start = chr_span_start;
				_tmp5_->span_end = chr_span_end;
				_g_free0 (_tmp5_->text);
				_tmp5_->text = _tmp4_;
				g_array_append_val (_tmp3_, _tmp5_);
				break;
			}
			case '"':
			{
				FtToken* _tmp6_ = NULL;
				FtToken* _tmp7_;
				GArray* _tmp8_;
				FtToken* _tmp9_;
				chr_span_end = chr_span_start;
				_tmp7_ = ft_expression_parser_tokenize_string_literal (self, text, &chr_span_end, &_inner_error0_);
				_tmp6_ = _tmp7_;
				if (G_UNLIKELY (_inner_error0_ != NULL)) {
					if (_inner_error0_->domain == FT_EXPRESSION_PARSER_ERROR) {
						g_propagate_error (error, _inner_error0_);
						_g_array_unref0 (tokens);
						return NULL;
					} else {
						_g_array_unref0 (tokens);
						g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
						g_clear_error (&_inner_error0_);
						return NULL;
					}
				}
				_tmp8_ = tokens;
				_tmp9_ = _tmp6_;
				_tmp6_ = NULL;
				g_array_append_val (_tmp8_, _tmp9_);
				_ft_token_free0 (_tmp6_);
				break;
			}
			case '|':
			case '&':
			case '=':
			case '!':
			case '>':
			case '<':
			{
				FtToken* _tmp10_ = NULL;
				FtToken* _tmp11_;
				GArray* _tmp12_;
				FtToken* _tmp13_;
				chr_span_end = chr_span_start;
				_tmp11_ = ft_expression_parser_tokenize_operator (self, text, &chr_span_end, &_inner_error0_);
				_tmp10_ = _tmp11_;
				if (G_UNLIKELY (_inner_error0_ != NULL)) {
					if (_inner_error0_->domain == FT_EXPRESSION_PARSER_ERROR) {
						g_propagate_error (error, _inner_error0_);
						_g_array_unref0 (tokens);
						return NULL;
					} else {
						_g_array_unref0 (tokens);
						g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
						g_clear_error (&_inner_error0_);
						return NULL;
					}
				}
				_tmp12_ = tokens;
				_tmp13_ = _tmp10_;
				_tmp10_ = NULL;
				g_array_append_val (_tmp12_, _tmp13_);
				_ft_token_free0 (_tmp10_);
				break;
			}
			default:
			{
				gboolean _tmp14_ = FALSE;
				gboolean _tmp15_ = FALSE;
				gboolean _tmp19_ = FALSE;
				gboolean _tmp20_ = FALSE;
				gchar* _tmp23_;
				gchar* _tmp24_;
				GError* _tmp25_;
				GError* _tmp26_;
				if (chr >= ((gunichar) 'a')) {
					_tmp15_ = chr <= ((gunichar) 'z');
				} else {
					_tmp15_ = FALSE;
				}
				if (_tmp15_) {
					_tmp14_ = TRUE;
				} else {
					gboolean _tmp16_ = FALSE;
					if (chr >= ((gunichar) 'A')) {
						_tmp16_ = chr <= ((gunichar) 'Z');
					} else {
						_tmp16_ = FALSE;
					}
					_tmp14_ = _tmp16_;
				}
				if (_tmp14_) {
					GArray* _tmp17_;
					FtToken* _tmp18_;
					chr_span_end = chr_span_start;
					_tmp17_ = tokens;
					_tmp18_ = ft_expression_parser_tokenize_identifier (self, text, &chr_span_end);
					g_array_append_val (_tmp17_, _tmp18_);
					break;
				}
				if (chr >= ((gunichar) '0')) {
					_tmp20_ = chr <= ((gunichar) '9');
				} else {
					_tmp20_ = FALSE;
				}
				if (_tmp20_) {
					_tmp19_ = TRUE;
				} else {
					_tmp19_ = chr == ((gunichar) '-');
				}
				if (_tmp19_) {
					GArray* _tmp21_;
					FtToken* _tmp22_;
					chr_span_end = chr_span_start;
					_tmp21_ = tokens;
					_tmp22_ = ft_expression_parser_tokenize_numeric_literal (self, text, &chr_span_end);
					g_array_append_val (_tmp21_, _tmp22_);
					break;
				}
				if (g_unichar_isspace (chr)) {
					break;
				}
				_tmp23_ = ft_expression_parser_format_error_context (text, chr_span_start, (guint) 10);
				_tmp24_ = _tmp23_;
				_tmp25_ = g_error_new (FT_EXPRESSION_PARSER_ERROR, FT_EXPRESSION_PARSER_ERROR_SYNTAX_ERROR, "Unexpected expression %s", _tmp24_);
				_tmp26_ = _tmp25_;
				_g_free0 (_tmp24_);
				_inner_error0_ = _tmp26_;
				if (_inner_error0_->domain == FT_EXPRESSION_PARSER_ERROR) {
					g_propagate_error (error, _inner_error0_);
					_g_array_unref0 (tokens);
					return NULL;
				} else {
					_g_array_unref0 (tokens);
					g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
					g_clear_error (&_inner_error0_);
					return NULL;
				}
			}
		}
		chr_span_start = chr_span_end;
	}
	result = tokens;
	return result;
}

static inline FtToken*
ft_expression_parser_find_open_parenthesis (FtExpressionParser* self,
                                            FtToken* token)
{
	FtToken* node = NULL;
	FtToken* result;
	g_return_val_if_fail (self != NULL, NULL);
	node = token;
	while (TRUE) {
		FtToken* _tmp0_;
		gboolean _tmp1_ = FALSE;
		FtToken* _tmp2_;
		FtToken* _tmp6_;
		FtToken* _tmp7_;
		_tmp0_ = node;
		if (!(_tmp0_ != NULL)) {
			break;
		}
		_tmp2_ = node;
		if (_tmp2_->type == FT_TOKEN_TYPE_PARENTHESIS) {
			FtToken* _tmp3_;
			FtToken* _tmp4_;
			_tmp3_ = node;
			_tmp4_ = _tmp3_->matching_token;
			_tmp1_ = _tmp4_ == NULL;
		} else {
			_tmp1_ = FALSE;
		}
		if (_tmp1_) {
			FtToken* _tmp5_;
			_tmp5_ = node;
			result = _tmp5_;
			return result;
		}
		_tmp6_ = node;
		_tmp7_ = _tmp6_->parent;
		node = _tmp7_;
	}
	result = NULL;
	return result;
}

/**
         * Validate roughly if syntax makes sense.
         */
static inline gboolean
ft_expression_parser_is_valid_token (FtExpressionParser* self,
                                     FtToken* token,
                                     FtToken* previous_token)
{
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	g_return_val_if_fail (token != NULL, FALSE);
	if (previous_token == NULL) {
		result = token->type != FT_TOKEN_TYPE_OPERATOR;
		return result;
	}
	switch (previous_token->type) {
		case FT_TOKEN_TYPE_OPERATOR:
		{
			result = token->type != FT_TOKEN_TYPE_OPERATOR;
			return result;
		}
		case FT_TOKEN_TYPE_PARENTHESIS:
		{
			result = TRUE;
			return result;
		}
		case FT_TOKEN_TYPE_STRING_LITERAL:
		case FT_TOKEN_TYPE_NUMERIC_LITERAL:
		case FT_TOKEN_TYPE_IDENTIFIER:
		{
			gboolean _tmp0_ = FALSE;
			if (token->type == FT_TOKEN_TYPE_OPERATOR) {
				_tmp0_ = TRUE;
			} else {
				_tmp0_ = token->type == FT_TOKEN_TYPE_PARENTHESIS;
			}
			result = _tmp0_;
			return result;
		}
		default:
		{
			g_assert_not_reached ();
		}
	}
}

static inline gboolean
ft_expression_parser_is_valid_expression (FtExpressionParser* self,
                                          FtToken* last_token)
{
	FtToken* _tmp0_;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	if (last_token == NULL) {
		result = TRUE;
		return result;
	}
	if (last_token->type == FT_TOKEN_TYPE_OPERATOR) {
		result = FALSE;
		return result;
	}
	_tmp0_ = ft_expression_parser_find_open_parenthesis (self, last_token);
	if (_tmp0_ != NULL) {
		result = FALSE;
		return result;
	}
	result = TRUE;
	return result;
}

static inline guint
ft_expression_parser_determine_precedence (FtExpressionParser* self,
                                           FtToken* token,
                                           FtToken* previous_token)
{
	guint result;
	g_return_val_if_fail (self != NULL, 0U);
	g_return_val_if_fail (token != NULL, 0U);
	switch (token->type) {
		case FT_TOKEN_TYPE_OPERATOR:
		{
			FtOperator operator = 0;
			GHashTable* _tmp0_;
			const gchar* _tmp1_;
			gconstpointer _tmp2_;
			_tmp0_ = self->operators;
			_tmp1_ = token->text;
			_tmp2_ = g_hash_table_lookup (_tmp0_, _tmp1_);
			operator = (FtOperator) ((gintptr) _tmp2_);
			result = FT_EXPRESSION_PARSER_BASE_OPERATOR_PRECEDENCE + ft_operator_get_precedence (operator);
			return result;
		}
		case FT_TOKEN_TYPE_PARENTHESIS:
		{
			guint _tmp3_ = 0U;
			gboolean _tmp4_ = FALSE;
			if (previous_token != NULL) {
				_tmp4_ = previous_token->type == FT_TOKEN_TYPE_PARENTHESIS;
			} else {
				_tmp4_ = FALSE;
			}
			if (_tmp4_) {
				_tmp3_ = previous_token->precedence - 1U;
			} else {
				_tmp3_ = FT_EXPRESSION_PARSER_BASE_OPERATOR_PRECEDENCE;
			}
			result = _tmp3_;
			return result;
		}
		default:
		{
			result = 0U;
			return result;
		}
	}
}

static inline FtToken*
ft_expression_parser_link_tokens (FtExpressionParser* self,
                                  FtToken* token,
                                  FtToken* previous_token)
{
	FtToken* result;
	g_return_val_if_fail (self != NULL, NULL);
	g_return_val_if_fail (token != NULL, NULL);
	if (token->type == FT_TOKEN_TYPE_OPERATOR) {
		FtToken* reference_token = NULL;
		gboolean _tmp6_ = FALSE;
		FtToken* _tmp7_;
		reference_token = previous_token;
		while (TRUE) {
			gboolean _tmp0_ = FALSE;
			FtToken* _tmp1_;
			FtToken* _tmp2_;
			FtToken* _tmp4_;
			FtToken* _tmp5_;
			_tmp1_ = reference_token;
			_tmp2_ = _tmp1_->parent;
			if (_tmp2_ != NULL) {
				FtToken* _tmp3_;
				_tmp3_ = reference_token;
				_tmp0_ = _tmp3_->type != FT_TOKEN_TYPE_OPERATOR;
			} else {
				_tmp0_ = FALSE;
			}
			if (!_tmp0_) {
				break;
			}
			_tmp4_ = reference_token;
			_tmp5_ = _tmp4_->parent;
			reference_token = _tmp5_;
		}
		_tmp7_ = reference_token;
		if (_tmp7_->type == FT_TOKEN_TYPE_OPERATOR) {
			FtToken* _tmp8_;
			const gchar* _tmp9_;
			const gchar* _tmp10_;
			_tmp8_ = reference_token;
			_tmp9_ = _tmp8_->text;
			_tmp10_ = token->text;
			_tmp6_ = g_strcmp0 (_tmp9_, _tmp10_) == 0;
		} else {
			_tmp6_ = FALSE;
		}
		if (_tmp6_) {
			FtToken* _tmp11_;
			_tmp11_ = reference_token;
			result = _tmp11_;
			return result;
		}
	}
	if (previous_token != NULL) {
		FtToken* reference_token = NULL;
		gboolean _tmp12_ = FALSE;
		gboolean _tmp13_ = FALSE;
		reference_token = previous_token;
		if (token->precedence > ((guint) 0)) {
			FtToken* _tmp14_;
			FtToken* _tmp15_;
			_tmp14_ = reference_token;
			_tmp15_ = _tmp14_->parent;
			_tmp13_ = _tmp15_ != NULL;
		} else {
			_tmp13_ = FALSE;
		}
		if (_tmp13_) {
			FtToken* _tmp16_;
			FtToken* _tmp17_;
			_tmp16_ = reference_token;
			_tmp17_ = _tmp16_->parent;
			_tmp12_ = _tmp17_->precedence > token->precedence;
		} else {
			_tmp12_ = FALSE;
		}
		if (_tmp12_) {
			FtToken* _tmp18_;
			FtToken* _tmp19_;
			FtToken* _tmp20_;
			FtToken* _tmp21_;
			_tmp18_ = reference_token;
			_tmp19_ = _tmp18_->parent;
			reference_token = _tmp19_;
			_tmp20_ = reference_token;
			ft_token_insert_parent (_tmp20_, token);
			_tmp21_ = reference_token;
			_vala_assert (token->precedence < _tmp21_->precedence, "token.precedence < reference_token.precedence");
		} else {
			FtToken* _tmp22_;
			_tmp22_ = reference_token;
			if (token->precedence > _tmp22_->precedence) {
				FtToken* _tmp23_;
				_tmp23_ = reference_token;
				ft_token_insert_parent (_tmp23_, token);
			} else {
				FtToken* _tmp24_;
				_tmp24_ = reference_token;
				if (token->precedence < _tmp24_->precedence) {
					FtToken* _tmp25_;
					_tmp25_ = reference_token;
					ft_token_append_child (_tmp25_, token);
				} else {
					FtToken* _tmp26_;
					_tmp26_ = reference_token;
					ft_token_append (_tmp26_, token);
				}
			}
		}
	}
	result = token;
	return result;
}

/**
         * Convert array of tokens into an Abstract Syntax Tree (AST).
         *
         * The AST represents the hierarchical structure of the expression. For example
         * `A || B && C` we want to build a tree:
         *
         *       ||
         *      /  \
         *     A   &&
         *         /  \
         *        B    C
         */
FtToken*
ft_expression_parser_build_token_tree (FtExpressionParser* self,
                                       GArray* tokens,
                                       GError** error)
{
	FtToken* token = NULL;
	FtToken* previous_token = NULL;
	FtToken* _tmp28_;
	FtToken* _tmp30_ = NULL;
	FtToken* _tmp31_;
	FtToken* _tmp32_ = NULL;
	GError* _inner_error0_ = NULL;
	FtToken* result;
	g_return_val_if_fail (self != NULL, NULL);
	g_return_val_if_fail (tokens != NULL, NULL);
	token = NULL;
	previous_token = NULL;
	{
		guint index = 0U;
		index = 0U;
		{
			gboolean _tmp0_ = FALSE;
			_tmp0_ = TRUE;
			while (TRUE) {
				FtToken* _tmp2_;
				FtToken* _tmp3_;
				FtToken* _tmp4_;
				gboolean _tmp9_ = FALSE;
				FtToken* _tmp10_;
				FtToken* _tmp21_;
				FtToken* _tmp22_;
				FtToken* _tmp23_;
				FtToken* _tmp24_;
				FtToken* _tmp25_;
				FtToken* _tmp26_;
				FtToken* _tmp27_;
				if (!_tmp0_) {
					guint _tmp1_;
					_tmp1_ = index;
					index = _tmp1_ + 1;
				}
				_tmp0_ = FALSE;
				if (!(index < tokens->len)) {
					break;
				}
				_tmp2_ = g_array_index (tokens, FtToken*, index);
				token = _tmp2_;
				_tmp3_ = token;
				_tmp4_ = previous_token;
				if (!ft_expression_parser_is_valid_token (self, _tmp3_, _tmp4_)) {
					FtToken* _tmp5_;
					const gchar* _tmp6_;
					FtToken* _tmp7_;
					GError* _tmp8_;
					_tmp5_ = token;
					_tmp6_ = _tmp5_->text;
					_tmp7_ = token;
					_tmp8_ = g_error_new (FT_EXPRESSION_PARSER_ERROR, FT_EXPRESSION_PARSER_ERROR_SYNTAX_ERROR, "Unexpected token '%s' at position %d", _tmp6_, _tmp7_->span_start);
					_inner_error0_ = _tmp8_;
					if (_inner_error0_->domain == FT_EXPRESSION_PARSER_ERROR) {
						g_propagate_error (error, _inner_error0_);
						return NULL;
					} else {
						g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
						g_clear_error (&_inner_error0_);
						return NULL;
					}
				}
				_tmp10_ = token;
				if (_tmp10_->type == FT_TOKEN_TYPE_PARENTHESIS) {
					FtToken* _tmp11_;
					const gchar* _tmp12_;
					_tmp11_ = token;
					_tmp12_ = _tmp11_->text;
					_tmp9_ = g_strcmp0 (_tmp12_, ")") == 0;
				} else {
					_tmp9_ = FALSE;
				}
				if (_tmp9_) {
					FtToken* reference_token = NULL;
					FtToken* _tmp13_;
					FtToken* _tmp14_;
					FtToken* _tmp15_;
					FtToken* _tmp17_;
					FtToken* _tmp18_;
					FtToken* _tmp19_;
					FtToken* _tmp20_;
					_tmp13_ = previous_token;
					_tmp14_ = ft_expression_parser_find_open_parenthesis (self, _tmp13_);
					reference_token = _tmp14_;
					_tmp15_ = reference_token;
					if (_tmp15_ == NULL) {
						GError* _tmp16_;
						_tmp16_ = g_error_new_literal (FT_EXPRESSION_PARSER_ERROR, FT_EXPRESSION_PARSER_ERROR_SYNTAX_ERROR, "Unmatched parenthesis");
						_inner_error0_ = _tmp16_;
						if (_inner_error0_->domain == FT_EXPRESSION_PARSER_ERROR) {
							g_propagate_error (error, _inner_error0_);
							return NULL;
						} else {
							g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
							g_clear_error (&_inner_error0_);
							return NULL;
						}
					}
					_tmp17_ = reference_token;
					_tmp18_ = token;
					_tmp17_->matching_token = _tmp18_;
					_tmp19_ = reference_token;
					token = _tmp19_;
					_tmp20_ = token;
					previous_token = _tmp20_;
					continue;
				}
				_tmp21_ = token;
				_tmp22_ = token;
				_tmp23_ = previous_token;
				_tmp21_->precedence = ft_expression_parser_determine_precedence (self, _tmp22_, _tmp23_);
				_tmp24_ = token;
				_tmp25_ = previous_token;
				_tmp26_ = ft_expression_parser_link_tokens (self, _tmp24_, _tmp25_);
				token = _tmp26_;
				_tmp27_ = token;
				previous_token = _tmp27_;
			}
		}
	}
	_tmp28_ = token;
	if (!ft_expression_parser_is_valid_expression (self, _tmp28_)) {
		GError* _tmp29_;
		_tmp29_ = g_error_new_literal (FT_EXPRESSION_PARSER_ERROR, FT_EXPRESSION_PARSER_ERROR_SYNTAX_ERROR, "Unexpected end of expression");
		_inner_error0_ = _tmp29_;
		if (_inner_error0_->domain == FT_EXPRESSION_PARSER_ERROR) {
			g_propagate_error (error, _inner_error0_);
			return NULL;
		} else {
			g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
			g_clear_error (&_inner_error0_);
			return NULL;
		}
	}
	_tmp31_ = token;
	_tmp30_ = _tmp31_;
	_tmp32_ = NULL;
	if (_tmp30_ != NULL) {
		FtToken* _tmp33_;
		_tmp33_ = ft_token_get_root (_tmp30_);
		_tmp32_ = _tmp33_;
	}
	result = _tmp32_;
	return result;
}

/**
         * We serialize timestamps and enums to `string`, for the result expression to
         * look more like JSON. But this has cost - we now have to deduce original types from
         * the strings during parsing.
         */
static inline FtValue*
ft_expression_parser_cast_string_literal (FtExpressionParser* self,
                                          const gchar* text)
{
	const gchar* _tmp0_;
	GQuark _tmp2_ = 0U;
	static GQuark _tmp1_label0 = 0;
	static GQuark _tmp1_label1 = 0;
	static GQuark _tmp1_label2 = 0;
	static GQuark _tmp1_label3 = 0;
	static GQuark _tmp1_label4 = 0;
	static GQuark _tmp1_label5 = 0;
	static GQuark _tmp1_label6 = 0;
	static GQuark _tmp1_label7 = 0;
	static GQuark _tmp1_label8 = 0;
	gint64 timestamp = 0LL;
	FtStringValue* _tmp13_;
	FtValue* result;
	g_return_val_if_fail (self != NULL, NULL);
	g_return_val_if_fail (text != NULL, NULL);
	_tmp0_ = text;
	_tmp2_ = (NULL == _tmp0_) ? 0 : g_quark_from_string (_tmp0_);
	if (_tmp2_ == ((0 != _tmp1_label0) ? _tmp1_label0 : (_tmp1_label0 = g_quark_from_static_string ("stopped")))) {
		switch (0) {
			default:
			{
				FtStateValue* _tmp3_;
				_tmp3_ = ft_state_value_new (FT_STATE_STOPPED);
				result = (FtValue*) _tmp3_;
				return result;
			}
		}
	} else if (_tmp2_ == ((0 != _tmp1_label1) ? _tmp1_label1 : (_tmp1_label1 = g_quark_from_static_string ("pomodoro")))) {
		switch (0) {
			default:
			{
				FtStateValue* _tmp4_;
				_tmp4_ = ft_state_value_new (FT_STATE_POMODORO);
				result = (FtValue*) _tmp4_;
				return result;
			}
		}
	} else if (_tmp2_ == ((0 != _tmp1_label2) ? _tmp1_label2 : (_tmp1_label2 = g_quark_from_static_string ("break")))) {
		switch (0) {
			default:
			{
				FtStateValue* _tmp5_;
				_tmp5_ = ft_state_value_new (FT_STATE_BREAK);
				result = (FtValue*) _tmp5_;
				return result;
			}
		}
	} else if (_tmp2_ == ((0 != _tmp1_label3) ? _tmp1_label3 : (_tmp1_label3 = g_quark_from_static_string ("short-break")))) {
		switch (0) {
			default:
			{
				FtStateValue* _tmp6_;
				_tmp6_ = ft_state_value_new (FT_STATE_SHORT_BREAK);
				result = (FtValue*) _tmp6_;
				return result;
			}
		}
	} else if (_tmp2_ == ((0 != _tmp1_label4) ? _tmp1_label4 : (_tmp1_label4 = g_quark_from_static_string ("long-break")))) {
		switch (0) {
			default:
			{
				FtStateValue* _tmp7_;
				_tmp7_ = ft_state_value_new (FT_STATE_LONG_BREAK);
				result = (FtValue*) _tmp7_;
				return result;
			}
		}
	} else if (_tmp2_ == ((0 != _tmp1_label5) ? _tmp1_label5 : (_tmp1_label5 = g_quark_from_static_string ("scheduled")))) {
		switch (0) {
			default:
			{
				FtStatusValue* _tmp8_;
				_tmp8_ = ft_status_value_new (FT_TIME_BLOCK_STATUS_SCHEDULED);
				result = (FtValue*) _tmp8_;
				return result;
			}
		}
	} else if (_tmp2_ == ((0 != _tmp1_label6) ? _tmp1_label6 : (_tmp1_label6 = g_quark_from_static_string ("in-progress")))) {
		switch (0) {
			default:
			{
				FtStatusValue* _tmp9_;
				_tmp9_ = ft_status_value_new (FT_TIME_BLOCK_STATUS_IN_PROGRESS);
				result = (FtValue*) _tmp9_;
				return result;
			}
		}
	} else if (_tmp2_ == ((0 != _tmp1_label7) ? _tmp1_label7 : (_tmp1_label7 = g_quark_from_static_string ("completed")))) {
		switch (0) {
			default:
			{
				FtStatusValue* _tmp10_;
				_tmp10_ = ft_status_value_new (FT_TIME_BLOCK_STATUS_COMPLETED);
				result = (FtValue*) _tmp10_;
				return result;
			}
		}
	} else if (_tmp2_ == ((0 != _tmp1_label8) ? _tmp1_label8 : (_tmp1_label8 = g_quark_from_static_string ("uncompleted")))) {
		switch (0) {
			default:
			{
				FtStatusValue* _tmp11_;
				_tmp11_ = ft_status_value_new (FT_TIME_BLOCK_STATUS_UNCOMPLETED);
				result = (FtValue*) _tmp11_;
				return result;
			}
		}
	} else {
		switch (0) {
			default:
			{
				break;
			}
		}
	}
	timestamp = ft_timestamp_from_iso8601 (text);
	if (timestamp != FT_TIMESTAMP_UNDEFINED) {
		FtTimestampValue* _tmp12_;
		_tmp12_ = ft_timestamp_value_new (timestamp);
		result = (FtValue*) _tmp12_;
		return result;
	}
	_tmp13_ = ft_string_value_new (text);
	result = (FtValue*) _tmp13_;
	return result;
}

static gint64
int64_parse (const gchar* str,
             guint _base)
{
	gint64 result;
	g_return_val_if_fail (str != NULL, -1LL);
	result = g_ascii_strtoll (str, NULL, _base);
	return result;
}

static inline FtValue*
ft_expression_parser_cast_numeric_literal (FtExpressionParser* self,
                                           const gchar* text)
{
	FtIntervalValue* _tmp0_;
	FtValue* result;
	g_return_val_if_fail (self != NULL, NULL);
	g_return_val_if_fail (text != NULL, NULL);
	_tmp0_ = ft_interval_value_new (int64_parse (text, (guint) 0));
	result = (FtValue*) _tmp0_;
	return result;
}

static inline FtExpression*
ft_expression_parser_interpret_identifier (FtExpressionParser* self,
                                           FtToken* token,
                                           GError** error)
{
	const gchar* _tmp0_;
	const gchar* _tmp5_;
	gchar* name = NULL;
	const gchar* _tmp10_;
	gchar* _tmp11_;
	const gchar* _tmp12_;
	FtVariableSpec* _tmp13_;
	const gchar* _tmp16_;
	FtVariable* _tmp17_;
	GError* _inner_error0_ = NULL;
	FtExpression* result;
	g_return_val_if_fail (self != NULL, NULL);
	g_return_val_if_fail (token != NULL, NULL);
	_vala_assert (ft_token_n_children (token) == ((guint) 0), "token.n_children () == 0");
	_tmp0_ = token->text;
	if (g_strcmp0 (_tmp0_, "true") == 0) {
		FtBooleanValue* _tmp1_;
		FtBooleanValue* _tmp2_;
		FtConstant* _tmp3_;
		FtExpression* _tmp4_;
		_tmp1_ = ft_boolean_value_new (TRUE);
		_tmp2_ = _tmp1_;
		_tmp3_ = ft_constant_new ((FtValue*) _tmp2_);
		_tmp4_ = (FtExpression*) _tmp3_;
		_ft_value_unref0 (_tmp2_);
		result = _tmp4_;
		return result;
	}
	_tmp5_ = token->text;
	if (g_strcmp0 (_tmp5_, "false") == 0) {
		FtBooleanValue* _tmp6_;
		FtBooleanValue* _tmp7_;
		FtConstant* _tmp8_;
		FtExpression* _tmp9_;
		_tmp6_ = ft_boolean_value_new (FALSE);
		_tmp7_ = _tmp6_;
		_tmp8_ = ft_constant_new ((FtValue*) _tmp7_);
		_tmp9_ = (FtExpression*) _tmp8_;
		_ft_value_unref0 (_tmp7_);
		result = _tmp9_;
		return result;
	}
	_tmp10_ = token->text;
	_tmp11_ = ft_from_camel_case (_tmp10_);
	name = _tmp11_;
	_tmp12_ = name;
	_tmp13_ = ft_find_variable (_tmp12_);
	if (_tmp13_ == NULL) {
		const gchar* _tmp14_;
		GError* _tmp15_;
		_tmp14_ = token->text;
		_tmp15_ = g_error_new (FT_EXPRESSION_PARSER_ERROR, FT_EXPRESSION_PARSER_ERROR_UNKNOWN_IDENTIFIER, "Unknown identifier '%s' at %d", _tmp14_, token->span_start);
		_inner_error0_ = _tmp15_;
		if (_inner_error0_->domain == FT_EXPRESSION_PARSER_ERROR) {
			g_propagate_error (error, _inner_error0_);
			_g_free0 (name);
			return NULL;
		} else {
			_g_free0 (name);
			g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
			g_clear_error (&_inner_error0_);
			return NULL;
		}
	}
	_tmp16_ = name;
	_tmp17_ = ft_variable_new (_tmp16_);
	result = (FtExpression*) _tmp17_;
	_g_free0 (name);
	return result;
}

static gpointer
_ft_expression_ref0 (gpointer self)
{
	return self ? ft_expression_ref (self) : NULL;
}

static FtExpression**
_vala_array_dup11 (FtExpression** self,
                   gssize length)
{
	if (length >= 0) {
		FtExpression** result;
		gssize i;
		result = g_new0 (FtExpression*, length + 1);
		for (i = 0; i < length; i++) {
			FtExpression* _tmp0_;
			_tmp0_ = _ft_expression_ref0 (self[i]);
			result[i] = _tmp0_;
		}
		return result;
	}
	return NULL;
}

static inline FtExpression*
ft_expression_parser_interpret_operator (FtExpressionParser* self,
                                         FtToken* token,
                                         GError** error)
{
	FtOperator operator = 0;
	GHashTable* _tmp0_;
	const gchar* _tmp1_;
	gconstpointer _tmp2_;
	guint n_children = 0U;
	FtToken* child = NULL;
	FtToken* _tmp3_;
	GError* _inner_error0_ = NULL;
	FtExpression* result;
	g_return_val_if_fail (self != NULL, NULL);
	g_return_val_if_fail (token != NULL, NULL);
	_tmp0_ = self->operators;
	_tmp1_ = token->text;
	_tmp2_ = g_hash_table_lookup (_tmp0_, _tmp1_);
	operator = (FtOperator) ((gintptr) _tmp2_);
	n_children = ft_token_n_children (token);
	_tmp3_ = token->children;
	child = _tmp3_;
	switch (ft_operator_get_category (operator)) {
		case FT_OPERATOR_CATEGORY_LOGICAL:
		{
			FtExpression** arguments = NULL;
			FtExpression** _tmp4_;
			gint arguments_length1;
			gint _arguments_size_;
			FtExpression** _tmp14_;
			gint _tmp14__length1;
			FtExpression** _tmp15_;
			gint _tmp15__length1;
			FtOperation* _tmp16_;
			_vala_assert (n_children >= ((guint) 2), "n_children >= 2");
			_tmp4_ = g_new0 (FtExpression*, n_children + 1);
			arguments = _tmp4_;
			arguments_length1 = n_children;
			_arguments_size_ = arguments_length1;
			{
				gint index = 0;
				index = 0;
				{
					gboolean _tmp5_ = FALSE;
					_tmp5_ = TRUE;
					while (TRUE) {
						FtExpression* _tmp7_ = NULL;
						FtToken* _tmp8_;
						FtExpression* _tmp9_;
						FtExpression** _tmp10_;
						gint _tmp10__length1;
						FtExpression* _tmp11_;
						FtToken* _tmp12_;
						FtToken* _tmp13_;
						if (!_tmp5_) {
							gint _tmp6_;
							_tmp6_ = index;
							index = _tmp6_ + 1;
						}
						_tmp5_ = FALSE;
						if (!(((guint) index) < n_children)) {
							break;
						}
						_tmp8_ = child;
						_tmp9_ = ft_expression_parser_interpret (self, _tmp8_, &_inner_error0_);
						_tmp7_ = _tmp9_;
						if (G_UNLIKELY (_inner_error0_ != NULL)) {
							if (_inner_error0_->domain == FT_EXPRESSION_PARSER_ERROR) {
								g_propagate_error (error, _inner_error0_);
								arguments = (_vala_array_free (arguments, arguments_length1, (GDestroyNotify) ft_expression_unref), NULL);
								return NULL;
							} else {
								arguments = (_vala_array_free (arguments, arguments_length1, (GDestroyNotify) ft_expression_unref), NULL);
								g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
								g_clear_error (&_inner_error0_);
								return NULL;
							}
						}
						_tmp10_ = arguments;
						_tmp10__length1 = arguments_length1;
						_tmp11_ = _tmp7_;
						_tmp7_ = NULL;
						_ft_expression_unref0 (_tmp10_[index]);
						_tmp10_[index] = _tmp11_;
						_tmp12_ = child;
						_tmp13_ = _tmp12_->next;
						child = _tmp13_;
						_ft_expression_unref0 (_tmp7_);
					}
				}
			}
			_tmp14_ = arguments;
			_tmp14__length1 = arguments_length1;
			_tmp15_ = (_tmp14_ != NULL) ? _vala_array_dup11 (_tmp14_, _tmp14__length1) : _tmp14_;
			_tmp15__length1 = _tmp14__length1;
			_tmp16_ = ft_operation_new_with_argv (operator, _tmp15_, _tmp15__length1);
			result = (FtExpression*) _tmp16_;
			arguments = (_vala_array_free (arguments, arguments_length1, (GDestroyNotify) ft_expression_unref), NULL);
			return result;
		}
		case FT_OPERATOR_CATEGORY_COMPARISON:
		{
			FtExpression* argument_lhs = NULL;
			FtToken* _tmp17_;
			FtExpression* _tmp18_;
			FtExpression* argument_rhs = NULL;
			FtToken* _tmp19_;
			FtToken* _tmp20_;
			FtExpression* _tmp21_;
			FtExpression* _tmp22_;
			FtExpression* _tmp23_;
			FtComparison* _tmp24_;
			_vala_assert (n_children == ((guint) 2), "n_children == 2");
			_tmp17_ = child;
			_tmp18_ = ft_expression_parser_interpret (self, _tmp17_, &_inner_error0_);
			argument_lhs = _tmp18_;
			if (G_UNLIKELY (_inner_error0_ != NULL)) {
				if (_inner_error0_->domain == FT_EXPRESSION_PARSER_ERROR) {
					g_propagate_error (error, _inner_error0_);
					return NULL;
				} else {
					g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
					g_clear_error (&_inner_error0_);
					return NULL;
				}
			}
			_tmp19_ = child;
			_tmp20_ = _tmp19_->next;
			_tmp21_ = ft_expression_parser_interpret (self, _tmp20_, &_inner_error0_);
			argument_rhs = _tmp21_;
			if (G_UNLIKELY (_inner_error0_ != NULL)) {
				if (_inner_error0_->domain == FT_EXPRESSION_PARSER_ERROR) {
					g_propagate_error (error, _inner_error0_);
					_ft_expression_unref0 (argument_lhs);
					return NULL;
				} else {
					_ft_expression_unref0 (argument_lhs);
					g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
					g_clear_error (&_inner_error0_);
					return NULL;
				}
			}
			_tmp22_ = argument_lhs;
			_tmp23_ = argument_rhs;
			_tmp24_ = ft_comparison_new (_tmp22_, operator, _tmp23_);
			result = (FtExpression*) _tmp24_;
			_ft_expression_unref0 (argument_rhs);
			_ft_expression_unref0 (argument_lhs);
			return result;
		}
		default:
		{
			g_assert_not_reached ();
		}
	}
}

/**
         * Convert token tree (aka AST) into our expression.
         */
static FtExpression*
ft_expression_parser_interpret (FtExpressionParser* self,
                                FtToken* token,
                                GError** error)
{
	GError* _inner_error0_ = NULL;
	FtExpression* result;
	g_return_val_if_fail (self != NULL, NULL);
	if (token == NULL) {
		result = NULL;
		return result;
	}
	switch (token->type) {
		case FT_TOKEN_TYPE_STRING_LITERAL:
		{
			const gchar* _tmp0_;
			FtValue* _tmp1_;
			FtValue* _tmp2_;
			FtConstant* _tmp3_;
			FtExpression* _tmp4_;
			_vala_assert (ft_token_n_children (token) == ((guint) 0), "token.n_children () == 0");
			_tmp0_ = token->text;
			_tmp1_ = ft_expression_parser_cast_string_literal (self, _tmp0_);
			_tmp2_ = _tmp1_;
			_tmp3_ = ft_constant_new (_tmp2_);
			_tmp4_ = (FtExpression*) _tmp3_;
			_ft_value_unref0 (_tmp2_);
			result = _tmp4_;
			return result;
		}
		case FT_TOKEN_TYPE_NUMERIC_LITERAL:
		{
			const gchar* _tmp5_;
			FtValue* _tmp6_;
			FtValue* _tmp7_;
			FtConstant* _tmp8_;
			FtExpression* _tmp9_;
			_vala_assert (ft_token_n_children (token) == ((guint) 0), "token.n_children () == 0");
			_tmp5_ = token->text;
			_tmp6_ = ft_expression_parser_cast_numeric_literal (self, _tmp5_);
			_tmp7_ = _tmp6_;
			_tmp8_ = ft_constant_new (_tmp7_);
			_tmp9_ = (FtExpression*) _tmp8_;
			_ft_value_unref0 (_tmp7_);
			result = _tmp9_;
			return result;
		}
		case FT_TOKEN_TYPE_IDENTIFIER:
		{
			FtExpression* _tmp10_ = NULL;
			FtExpression* _tmp11_;
			FtExpression* _tmp12_;
			_vala_assert (ft_token_n_children (token) == ((guint) 0), "token.n_children () == 0");
			_tmp11_ = ft_expression_parser_interpret_identifier (self, token, &_inner_error0_);
			_tmp10_ = _tmp11_;
			if (G_UNLIKELY (_inner_error0_ != NULL)) {
				if (_inner_error0_->domain == FT_EXPRESSION_PARSER_ERROR) {
					g_propagate_error (error, _inner_error0_);
					return NULL;
				} else {
					g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
					g_clear_error (&_inner_error0_);
					return NULL;
				}
			}
			_tmp12_ = _tmp10_;
			_tmp10_ = NULL;
			result = _tmp12_;
			_ft_expression_unref0 (_tmp10_);
			return result;
		}
		case FT_TOKEN_TYPE_OPERATOR:
		{
			FtExpression* _tmp13_ = NULL;
			FtExpression* _tmp14_;
			FtExpression* _tmp15_;
			_tmp14_ = ft_expression_parser_interpret_operator (self, token, &_inner_error0_);
			_tmp13_ = _tmp14_;
			if (G_UNLIKELY (_inner_error0_ != NULL)) {
				if (_inner_error0_->domain == FT_EXPRESSION_PARSER_ERROR) {
					g_propagate_error (error, _inner_error0_);
					return NULL;
				} else {
					g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
					g_clear_error (&_inner_error0_);
					return NULL;
				}
			}
			_tmp15_ = _tmp13_;
			_tmp13_ = NULL;
			result = _tmp15_;
			_ft_expression_unref0 (_tmp13_);
			return result;
		}
		case FT_TOKEN_TYPE_PARENTHESIS:
		{
			FtExpression* _tmp16_ = NULL;
			FtToken* _tmp17_;
			FtExpression* _tmp18_;
			FtExpression* _tmp19_;
			_tmp17_ = token->children;
			_tmp18_ = ft_expression_parser_interpret (self, _tmp17_, &_inner_error0_);
			_tmp16_ = _tmp18_;
			if (G_UNLIKELY (_inner_error0_ != NULL)) {
				if (_inner_error0_->domain == FT_EXPRESSION_PARSER_ERROR) {
					g_propagate_error (error, _inner_error0_);
					return NULL;
				} else {
					g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
					g_clear_error (&_inner_error0_);
					return NULL;
				}
			}
			_tmp19_ = _tmp16_;
			_tmp16_ = NULL;
			result = _tmp19_;
			_ft_expression_unref0 (_tmp16_);
			return result;
		}
		default:
		{
			g_assert_not_reached ();
		}
	}
}

FtExpression*
ft_expression_parser_parse (FtExpressionParser* self,
                            const gchar* text,
                            GError** error)
{
	GArray* tokens = NULL;
	GArray* _tmp0_;
	FtToken* root = NULL;
	GArray* _tmp1_;
	FtToken* _tmp2_;
	FtExpression* _tmp3_ = NULL;
	FtToken* _tmp4_;
	FtExpression* _tmp5_;
	FtExpression* _tmp6_;
	GError* _inner_error0_ = NULL;
	FtExpression* result;
	g_return_val_if_fail (self != NULL, NULL);
	g_return_val_if_fail (text != NULL, NULL);
	_tmp0_ = ft_expression_parser_tokenize (self, text, &_inner_error0_);
	tokens = _tmp0_;
	if (G_UNLIKELY (_inner_error0_ != NULL)) {
		if (_inner_error0_->domain == FT_EXPRESSION_PARSER_ERROR) {
			g_propagate_error (error, _inner_error0_);
			return NULL;
		} else {
			g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
			g_clear_error (&_inner_error0_);
			return NULL;
		}
	}
	_tmp1_ = tokens;
	_tmp2_ = ft_expression_parser_build_token_tree (self, _tmp1_, &_inner_error0_);
	root = _tmp2_;
	if (G_UNLIKELY (_inner_error0_ != NULL)) {
		if (_inner_error0_->domain == FT_EXPRESSION_PARSER_ERROR) {
			g_propagate_error (error, _inner_error0_);
			_g_array_unref0 (tokens);
			return NULL;
		} else {
			_g_array_unref0 (tokens);
			g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
			g_clear_error (&_inner_error0_);
			return NULL;
		}
	}
	_tmp4_ = root;
	_tmp5_ = ft_expression_parser_interpret (self, _tmp4_, &_inner_error0_);
	_tmp3_ = _tmp5_;
	if (G_UNLIKELY (_inner_error0_ != NULL)) {
		if (_inner_error0_->domain == FT_EXPRESSION_PARSER_ERROR) {
			g_propagate_error (error, _inner_error0_);
			_g_array_unref0 (tokens);
			return NULL;
		} else {
			_g_array_unref0 (tokens);
			g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
			g_clear_error (&_inner_error0_);
			return NULL;
		}
	}
	_tmp6_ = _tmp3_;
	_tmp3_ = NULL;
	result = _tmp6_;
	_ft_expression_unref0 (_tmp3_);
	_g_array_unref0 (tokens);
	return result;
}

static void
ft_expression_parser_instance_init (FtExpressionParser * self)
{
}

void
ft_expression_parser_free (FtExpressionParser * self)
{
	_g_hash_table_unref0 (self->operators);
	self->operators = NULL;
	_g_hash_table_unref0 (self->operators);
	g_slice_free (FtExpressionParser, self);
}

static void
_vala_array_destroy (gpointer array,
                     gssize array_length,
                     GDestroyNotify destroy_func)
{
	if ((array != NULL) && (destroy_func != NULL)) {
		gssize i;
		for (i = 0; i < array_length; i = i + 1) {
			if (((gpointer*) array)[i] != NULL) {
				destroy_func (((gpointer*) array)[i]);
			}
		}
	}
}

static void
_vala_array_free (gpointer array,
                  gssize array_length,
                  GDestroyNotify destroy_func)
{
	_vala_array_destroy (array, array_length, destroy_func);
	g_free (array);
}

static inline gpointer
_vala_memdup2 (gconstpointer mem,
               gsize byte_size)
{
	gpointer new_mem;
	if (mem && byte_size != 0) {
		new_mem = g_malloc (byte_size);
		memcpy (new_mem, mem, byte_size);
	} else {
		new_mem = NULL;
	}
	return new_mem;
}

