2012-05-12 22:26:59 +01:00
|
|
|
/* Internals for Hammer.
|
|
|
|
|
* Copyright (C) 2012 Meredith L. Patterson, Dan "TQ" Hirsch
|
|
|
|
|
*
|
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
|
* as published by the Free Software Foundation, version 2.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
|
*/
|
|
|
|
|
|
2012-04-23 19:39:44 +01:00
|
|
|
#ifndef HAMMER_INTERNAL__H
|
|
|
|
|
#define HAMMER_INTERNAL__H
|
2012-05-13 01:01:26 +01:00
|
|
|
#include <err.h>
|
2012-04-23 19:39:44 +01:00
|
|
|
#include "hammer.h"
|
|
|
|
|
|
2012-05-13 01:01:26 +01:00
|
|
|
#ifdef NDEBUG
|
|
|
|
|
#define assert_message(check, message) do { } while(0)
|
|
|
|
|
#else
|
|
|
|
|
#define assert_message(check, message) do { \
|
|
|
|
|
if (!(check)) \
|
2012-05-18 12:37:36 +02:00
|
|
|
errx(1, "Assertion failed (programmer error): %s", message); \
|
2012-05-13 01:01:26 +01:00
|
|
|
} while(0)
|
|
|
|
|
#endif
|
2012-10-10 15:58:03 +02:00
|
|
|
|
|
|
|
|
#define HAMMER_FN_IMPL_NOARGS(rtype_t, name) \
|
|
|
|
|
rtype_t name(void) { \
|
|
|
|
|
return name##__m(system_allocator); \
|
|
|
|
|
} \
|
|
|
|
|
rtype_t name##__m(HAllocator* mm__)
|
|
|
|
|
// Functions with arguments are difficult to forward cleanly. Alas, we will need to forward them manually.
|
|
|
|
|
|
|
|
|
|
#define h_new(type, count) ((type*)(mm__->alloc(mm__, sizeof(type)*(count))))
|
|
|
|
|
#define h_free(addr) (mm__->free(mm__, (addr)))
|
|
|
|
|
|
2012-04-29 01:45:52 +01:00
|
|
|
#define false 0
|
|
|
|
|
#define true 1
|
|
|
|
|
|
2012-10-10 15:58:03 +02:00
|
|
|
// This is going to be generally useful.
|
|
|
|
|
static inline void h_generic_free(HAllocator *allocator, void* ptr) {
|
|
|
|
|
allocator->free(allocator, ptr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
HAllocator system_allocator;
|
|
|
|
|
|
|
|
|
|
|
2012-05-26 13:01:23 +02:00
|
|
|
typedef struct HInputStream_ {
|
2012-05-17 13:22:56 +02:00
|
|
|
// This should be considered to be a really big value type.
|
|
|
|
|
const uint8_t *input;
|
|
|
|
|
size_t index;
|
|
|
|
|
size_t length;
|
|
|
|
|
char bit_offset;
|
|
|
|
|
char endianness;
|
|
|
|
|
char overrun;
|
2012-05-26 13:01:23 +02:00
|
|
|
} HInputStream;
|
2012-05-17 13:22:56 +02:00
|
|
|
|
2012-10-08 18:16:18 +02:00
|
|
|
typedef struct HSlistNode_ {
|
|
|
|
|
void* elem;
|
|
|
|
|
struct HSlistNode_ *next;
|
|
|
|
|
} HSlistNode;
|
|
|
|
|
|
|
|
|
|
typedef struct HSlist_ {
|
|
|
|
|
HSlistNode *head;
|
|
|
|
|
struct HArena_ *arena;
|
|
|
|
|
} HSlist;
|
|
|
|
|
|
2012-10-08 21:12:56 +02:00
|
|
|
typedef unsigned int HHashValue;
|
|
|
|
|
typedef HHashValue (*HHashFunc)(const void* key);
|
|
|
|
|
typedef bool (*HEqualFunc)(const void* key1, const void* key2);
|
|
|
|
|
|
|
|
|
|
typedef struct HHashTableEntry_ {
|
|
|
|
|
struct HHashTableEntry_ *next;
|
|
|
|
|
void* key;
|
|
|
|
|
void* value;
|
|
|
|
|
HHashValue hashval;
|
|
|
|
|
} HHashTableEntry;
|
|
|
|
|
|
|
|
|
|
typedef struct HHashTable_ {
|
|
|
|
|
HHashTableEntry *contents;
|
|
|
|
|
HHashFunc hashFunc;
|
|
|
|
|
HEqualFunc equalFunc;
|
|
|
|
|
size_t capacity;
|
|
|
|
|
size_t used;
|
|
|
|
|
HArena *arena;
|
|
|
|
|
} HHashTable;
|
2012-10-08 18:16:18 +02:00
|
|
|
|
2012-05-17 13:22:56 +02:00
|
|
|
/* The state of the parser.
|
|
|
|
|
*
|
|
|
|
|
* Members:
|
2012-05-26 13:13:41 +02:00
|
|
|
* cache - a hash table describing the state of the parse, including partial HParseResult's. It's a hash table from HParserCacheKey to HParserCacheValue.
|
2012-05-17 13:22:56 +02:00
|
|
|
* input_stream - the input stream at this state.
|
|
|
|
|
* arena - the arena that has been allocated for the parse this state is in.
|
2012-05-26 13:13:41 +02:00
|
|
|
* lr_stack - a stack of HLeftRec's, used in Warth's recursion
|
|
|
|
|
* recursion_heads - table of recursion heads. Keys are HParserCacheKey's with only an HInputStream (parser can be NULL), values are HRecursionHead's.
|
2012-05-17 13:22:56 +02:00
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
2012-05-26 12:03:58 +02:00
|
|
|
struct HParseState_ {
|
2012-10-08 21:12:56 +02:00
|
|
|
HHashTable *cache;
|
2012-05-26 13:01:23 +02:00
|
|
|
HInputStream input_stream;
|
|
|
|
|
HArena * arena;
|
2012-10-08 18:16:18 +02:00
|
|
|
HSlist *lr_stack;
|
2012-10-08 21:12:56 +02:00
|
|
|
HHashTable *recursion_heads;
|
2012-05-17 18:27:59 +02:00
|
|
|
};
|
2012-05-17 13:22:56 +02:00
|
|
|
|
2012-11-02 17:16:53 -04:00
|
|
|
typedef struct HParserBackendVTable_ {
|
2012-11-05 23:08:18 -05:00
|
|
|
int (*compile)(HAllocator *mm__, const HParser* parser, const void* params);
|
|
|
|
|
HParseResult* (*parse)(HAllocator *mm__, const HParser* parser, HParseState* parse_state);
|
2012-11-02 17:16:53 -04:00
|
|
|
} HParserBackendVTable;
|
|
|
|
|
|
|
|
|
|
|
2012-05-17 13:22:56 +02:00
|
|
|
/* The (location, parser) tuple used to key the cache.
|
|
|
|
|
*/
|
2012-05-17 15:51:19 +02:00
|
|
|
|
2012-05-26 13:13:41 +02:00
|
|
|
typedef struct HParserCacheKey_ {
|
2012-05-26 13:01:23 +02:00
|
|
|
HInputStream input_pos;
|
|
|
|
|
const HParser *parser;
|
2012-05-26 13:13:41 +02:00
|
|
|
} HParserCacheKey;
|
2012-05-03 01:58:09 +01:00
|
|
|
|
2012-05-17 13:22:56 +02:00
|
|
|
/* A value in the cache is either of value Left or Right (this is a
|
|
|
|
|
* holdover from Scala, which used Either here). Left corresponds to
|
2012-05-26 13:13:41 +02:00
|
|
|
* HLeftRec, which is for left recursion; Right corresponds to
|
2012-05-26 13:01:23 +02:00
|
|
|
* HParseResult.
|
2012-05-17 13:22:56 +02:00
|
|
|
*/
|
|
|
|
|
|
2012-05-26 13:13:41 +02:00
|
|
|
typedef enum HParserCacheValueType_ {
|
2012-05-13 01:18:18 +01:00
|
|
|
PC_LEFT,
|
|
|
|
|
PC_RIGHT
|
2012-05-26 13:13:41 +02:00
|
|
|
} HParserCacheValueType;
|
2012-05-12 21:26:15 +01:00
|
|
|
|
2012-05-17 13:22:56 +02:00
|
|
|
|
|
|
|
|
/* A recursion head.
|
|
|
|
|
*
|
|
|
|
|
* Members:
|
2012-05-17 14:05:10 +02:00
|
|
|
* head_parser - the parse rule that started this recursion
|
2012-05-26 13:01:23 +02:00
|
|
|
* involved_set - A list of rules (HParser's) involved in the recursion
|
2012-05-17 13:22:56 +02:00
|
|
|
* eval_set -
|
|
|
|
|
*/
|
2012-05-26 13:13:41 +02:00
|
|
|
typedef struct HRecursionHead_ {
|
2012-05-26 13:01:23 +02:00
|
|
|
const HParser *head_parser;
|
2012-10-08 18:16:18 +02:00
|
|
|
HSlist *involved_set;
|
|
|
|
|
HSlist *eval_set;
|
2012-05-26 13:13:41 +02:00
|
|
|
} HRecursionHead;
|
2012-05-13 01:18:18 +01:00
|
|
|
|
2012-05-17 13:22:56 +02:00
|
|
|
|
|
|
|
|
/* A left recursion.
|
|
|
|
|
*
|
|
|
|
|
* Members:
|
|
|
|
|
* seed -
|
|
|
|
|
* rule -
|
|
|
|
|
* head -
|
|
|
|
|
*/
|
2012-05-26 13:13:41 +02:00
|
|
|
typedef struct HLeftRec_ {
|
2012-05-26 13:01:23 +02:00
|
|
|
HParseResult *seed;
|
|
|
|
|
const HParser *rule;
|
2012-05-26 13:13:41 +02:00
|
|
|
HRecursionHead *head;
|
|
|
|
|
} HLeftRec;
|
2012-05-13 01:18:18 +01:00
|
|
|
|
2012-06-02 02:39:00 +02:00
|
|
|
/* Result and remaining input, for rerunning from a cached position. */
|
|
|
|
|
typedef struct HCachedResult_ {
|
|
|
|
|
HParseResult *result;
|
|
|
|
|
HInputStream input_stream;
|
|
|
|
|
} HCachedResult;
|
|
|
|
|
|
2012-05-26 13:13:41 +02:00
|
|
|
/* Tagged union for values in the cache: either HLeftRec's (Left) or
|
2012-05-26 13:01:23 +02:00
|
|
|
* HParseResult's (Right).
|
2012-05-17 13:22:56 +02:00
|
|
|
*/
|
2012-05-26 13:13:41 +02:00
|
|
|
typedef struct HParserCacheValue_t {
|
|
|
|
|
HParserCacheValueType value_type;
|
2012-05-12 21:26:15 +01:00
|
|
|
union {
|
2012-05-26 13:13:41 +02:00
|
|
|
HLeftRec *left;
|
2012-06-02 02:39:00 +02:00
|
|
|
HCachedResult *right;
|
2012-05-12 21:26:15 +01:00
|
|
|
};
|
2012-05-26 13:13:41 +02:00
|
|
|
} HParserCacheValue;
|
2012-05-12 21:26:15 +01:00
|
|
|
|
2012-11-13 22:29:25 -05:00
|
|
|
// This file provides the logical inverse of bitreader.c
|
|
|
|
|
struct HBitWriter_ {
|
|
|
|
|
uint8_t* buf;
|
|
|
|
|
HAllocator *mm__;
|
|
|
|
|
size_t index;
|
|
|
|
|
size_t capacity;
|
|
|
|
|
char bit_offset; // unlike in bit_reader, this is always the number
|
|
|
|
|
// of used bits in the current byte. i.e., 0 always
|
|
|
|
|
// means that 8 bits are available for use.
|
|
|
|
|
char flags;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// }}}
|
|
|
|
|
|
2012-11-02 17:16:53 -04:00
|
|
|
// Backends {{{
|
|
|
|
|
extern HParserBackendVTable h__packrat_backend_vtable;
|
|
|
|
|
// }}}
|
|
|
|
|
|
2012-05-03 01:58:09 +01:00
|
|
|
// TODO(thequux): Set symbol visibility for these functions so that they aren't exported.
|
2012-04-23 19:39:44 +01:00
|
|
|
|
2012-05-26 14:06:52 +02:00
|
|
|
long long h_read_bits(HInputStream* state, int count, char signed_p);
|
|
|
|
|
// need to decide if we want to make this public.
|
|
|
|
|
HParseResult* h_do_parse(const HParser* parser, HParseState *state);
|
2012-05-26 13:01:23 +02:00
|
|
|
void put_cached(HParseState *ps, const HParser *p, HParseResult *cached);
|
2012-05-13 01:01:26 +01:00
|
|
|
|
2012-05-26 14:06:52 +02:00
|
|
|
HCountedArray *h_carray_new_sized(HArena * arena, size_t size);
|
|
|
|
|
HCountedArray *h_carray_new(HArena * arena);
|
|
|
|
|
void h_carray_append(HCountedArray *array, void* item);
|
2012-05-17 15:51:19 +02:00
|
|
|
|
2012-10-08 17:11:47 +02:00
|
|
|
HSlist* h_slist_new(HArena *arena);
|
2013-01-10 00:40:19 +01:00
|
|
|
HSlist* h_slist_copy(HSlist *slist);
|
2012-10-08 17:11:47 +02:00
|
|
|
void* h_slist_pop(HSlist *slist);
|
|
|
|
|
void h_slist_push(HSlist *slist, void* item);
|
2012-10-08 18:16:18 +02:00
|
|
|
bool h_slist_find(HSlist *slist, const void* item);
|
|
|
|
|
HSlist* h_slist_remove_all(HSlist *slist, const void* item);
|
2012-10-08 17:11:47 +02:00
|
|
|
void h_slist_free(HSlist *slist);
|
2012-05-26 16:00:43 +02:00
|
|
|
|
2012-10-08 21:12:56 +02:00
|
|
|
HHashTable* h_hashtable_new(HArena *arena, HEqualFunc equalFunc, HHashFunc hashFunc);
|
2012-10-08 19:20:36 +02:00
|
|
|
void* h_hashtable_get(HHashTable* ht, void* key);
|
|
|
|
|
void h_hashtable_put(HHashTable* ht, void* key, void* value);
|
|
|
|
|
int h_hashtable_present(HHashTable* ht, void* key);
|
|
|
|
|
void h_hashtable_del(HHashTable* ht, void* key);
|
|
|
|
|
void h_hashtable_free(HHashTable* ht);
|
|
|
|
|
|
2012-05-17 15:51:19 +02:00
|
|
|
#if 0
|
2012-11-14 14:05:25 -05:00
|
|
|
#include <stdlib.h>
|
2012-10-08 22:06:33 +02:00
|
|
|
#define h_arena_malloc(a, s) malloc(s)
|
2012-05-17 15:51:19 +02:00
|
|
|
#endif
|
|
|
|
|
|
2012-04-23 19:39:44 +01:00
|
|
|
#endif // #ifndef HAMMER_INTERNAL__H
|