diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/bin/main.c | 8 | ||||
| -rw-r--r-- | src/include/aplwc.h | 11 | ||||
| -rw-r--r-- | src/lib/aplwc_internal.h | 31 | ||||
| -rw-r--r-- | src/lib/eval.c | 7 | ||||
| -rw-r--r-- | src/lib/main.c | 52 | ||||
| -rw-r--r-- | src/lib/memory.c | 32 | ||||
| -rw-r--r-- | src/lib/string.c | 82 | ||||
| -rw-r--r-- | src/lib/syntax.c | 9 |
8 files changed, 227 insertions, 5 deletions
diff --git a/src/bin/main.c b/src/bin/main.c index 80b2ee0..a1c65bf 100644 --- a/src/bin/main.c +++ b/src/bin/main.c @@ -5,6 +5,7 @@ int main(void) { struct aplwc *aplwc; + struct aplwc_line *line; uint8_t *data; int ret; size_t memsize; @@ -24,6 +25,13 @@ main(void) return 1; } + line = aplwc_read(aplwc, "a←10+20"); + if(line == NULL) + fprintf(stderr, "Could not parse line: %s\n", aplwc_errstr(aplwc)); + else + aplwc_eval(line); + aplwc_free_line(line); + aplwc_destroy(aplwc); free(data); diff --git a/src/include/aplwc.h b/src/include/aplwc.h index d4d101c..75d9485 100644 --- a/src/include/aplwc.h +++ b/src/include/aplwc.h @@ -7,17 +7,24 @@ enum aplwc_rc { APLWC_OK, APLWC_OUT_OF_MEMORY, + APLWC_NOT_YET_IMPLEMENTED, + APLWC_INVALID_UTF8, - APLWC_RC_LAST = APLWC_OUT_OF_MEMORY + APLWC_RC_LAST = APLWC_INVALID_UTF8 }; struct aplwc; +struct aplwc_line; enum aplwc_rc aplwc_new(struct aplwc **, uint8_t *, size_t); void aplwc_destroy(struct aplwc *); const char *aplwc_errstr_rc(enum aplwc_rc); const char *aplwc_errstr(struct aplwc *); +enum aplwc_rc aplwc_last_error(struct aplwc *); +struct aplwc_line *aplwc_read(struct aplwc *, const char *); +void aplwc_free_line(struct aplwc_line *); +enum aplwc_rc aplwc_eval(struct aplwc_line *); -#define APLWC_MIN_MEM (128) +#define APLWC_MIN_MEM (64) #endif /* APLWC_H */ diff --git a/src/lib/aplwc_internal.h b/src/lib/aplwc_internal.h index 52ecd2e..155508d 100644 --- a/src/lib/aplwc_internal.h +++ b/src/lib/aplwc_internal.h @@ -21,16 +21,41 @@ struct memory { struct aplwc { enum aplwc_rc last_error; - char last_error_msg[64]; struct memory memory; }; -/* errors.c */ -const char *rc_to_string(enum aplwc_rc); +struct aplwc_line { + struct aplwc *aplwc; + struct string *text; + struct token_list *tokens; +}; + +struct string { + size_t bytes; + size_t chars; + uint8_t *utf8; +}; + +struct token_list { + size_t length; +}; + +/* eval.c */ +void eval_line(struct aplwc_line *); /* memory.c */ struct memory memory_init(uint8_t *, size_t); struct aplwc *memory_alloc_aplwc(struct memory *); +struct aplwc_line *memory_alloc_aplwc_line(struct memory *); +struct string *memory_alloc_string(struct memory *, size_t); void memory_free_aplwc(struct memory *, struct aplwc *); +void memory_free_aplwc_line(struct memory *, struct aplwc_line *); +void memory_free_string(struct memory *, struct string *); + +/* string.c */ +struct string *chars_to_string(struct aplwc *, const char *); + +/* syntax.c */ +struct token_list *scan_line(struct aplwc *, struct string *); #endif /* APLWC_INTERNAL_H */ diff --git a/src/lib/eval.c b/src/lib/eval.c new file mode 100644 index 0000000..89bdf59 --- /dev/null +++ b/src/lib/eval.c @@ -0,0 +1,7 @@ +#include "aplwc_internal.h" + +void +eval_line(struct aplwc_line *line) +{ + line->aplwc->last_error = APLWC_NOT_YET_IMPLEMENTED; +} diff --git a/src/lib/main.c b/src/lib/main.c index f7cbe7d..cca1e68 100644 --- a/src/lib/main.c +++ b/src/lib/main.c @@ -30,6 +30,10 @@ aplwc_errstr_rc(enum aplwc_rc rc) return ""; case APLWC_OUT_OF_MEMORY: return "Out of memory"; + case APLWC_NOT_YET_IMPLEMENTED: + return "Not yet implemented"; + case APLWC_INVALID_UTF8: + return "Invalid UTF-8"; default: return "(unable to produce error string)"; } @@ -50,3 +54,51 @@ aplwc_errstr(struct aplwc *aplwc) return err; } + +enum aplwc_rc +aplwc_last_error(struct aplwc *aplwc) +{ + return aplwc->last_error; +} + +struct aplwc_line * +aplwc_read(struct aplwc *aplwc, const char *line) +{ + struct string *text; + struct token_list *tokens; + struct aplwc_line *ret; + + text = chars_to_string(aplwc, line); + if(text == NULL) + return NULL; + + tokens = scan_line(aplwc, text); + if(tokens == NULL) + return NULL; + + ret = memory_alloc_aplwc_line(&aplwc->memory); + if(ret == NULL) + return NULL; + + ret->aplwc = aplwc; + ret->text = text; + ret->tokens = tokens; + + return ret; +} + +void +aplwc_free_line(struct aplwc_line *line) +{ + if(line == NULL) + return; + memory_free_aplwc_line(&line->aplwc->memory, line); +} + +enum aplwc_rc +aplwc_eval(struct aplwc_line *line) +{ + line->aplwc->last_error = APLWC_OK; + eval_line(line); + return line->aplwc->last_error; +} diff --git a/src/lib/memory.c b/src/lib/memory.c index 187137e..136c7e6 100644 --- a/src/lib/memory.c +++ b/src/lib/memory.c @@ -53,3 +53,35 @@ memory_free_aplwc(struct memory *m, struct aplwc *p) UNUSED_PARAMETER(m); UNUSED_PARAMETER(p); } + +struct aplwc_line * +memory_alloc_aplwc_line(struct memory *m) +{ + struct aplwc_line *p; + + p = alloc(m, sizeof(struct aplwc_line), alignof(struct aplwc_line)); + return p; +} + +void +memory_free_aplwc_line(struct memory *m, struct aplwc_line *p) +{ + UNUSED_PARAMETER(m); + UNUSED_PARAMETER(p); +} + +struct string * +memory_alloc_string(struct memory *m, size_t bytes) +{ + struct string *p; + + p = alloc(m, sizeof(struct string) + bytes, alignof(struct string)); + return p; +} + +void +memory_free_string(struct memory *m, struct string *p) +{ + UNUSED_PARAMETER(m); + UNUSED_PARAMETER(p); +} diff --git a/src/lib/string.c b/src/lib/string.c new file mode 100644 index 0000000..f6fa49d --- /dev/null +++ b/src/lib/string.c @@ -0,0 +1,82 @@ +#include "aplwc_internal.h" + +struct string * +chars_to_string(struct aplwc *aplwc, const char *chars) +{ + const uint8_t *utf8; + size_t bytecount, charcount; + struct string *string; + uint32_t c; + uint8_t b; + int seqlen, extra; + + utf8 = (const uint8_t *)chars; + seqlen = extra = 0; + for(bytecount = 0, charcount = 0; utf8[bytecount]; bytecount++){ + b = utf8[bytecount]; + if(extra == 0){ + c = 0; + if((b & 0x80) == 0){ + seqlen = 0; + c |= (b & 0x7F); + }else if((b & 0xE0) == 0xC0){ + seqlen = 1; + c |= (b & 0x1F); + }else if((b & 0xF0) == 0xE0){ + seqlen = 2; + c |= (b & 0x0F); + }else if((b & 0xF8) == 0xF0){ + seqlen = 3; + c |= (b & 0x7); + }else{ +invalid: + aplwc->last_error = APLWC_INVALID_UTF8; + return NULL; + } + extra = seqlen; + }else{ + extra--; + c <<= 6; + if((b & 0xC0) == 0x80) + c |= (b & 0x3F); + else + goto invalid; + } + + if(extra == 0){ + charcount++; + switch(seqlen){ + case 0: + if(NEVER(c > 0x7F)) + goto invalid; + break; + case 1: + if((c < 0x80) || NEVER(c > 0x07FF)) + goto invalid; + break; + case 2: + if((c < 0x0800) || NEVER(c > 0xFFFF)) + goto invalid; + break; + case 3: + if((c < 0x010000) || NEVER(c > 0x10FFFF)) + goto invalid; + break; + } + } + } + + if(extra != 0) + goto invalid; + + string = memory_alloc_string(&aplwc->memory, bytecount); + if(string){ + string->bytes = bytecount; + string->chars = charcount; + string->utf8 = ((uint8_t *)string)+sizeof(*string); + memcpy(string->utf8, utf8, bytecount); + }else + aplwc->last_error = APLWC_OUT_OF_MEMORY; + + return string; +} diff --git a/src/lib/syntax.c b/src/lib/syntax.c new file mode 100644 index 0000000..c1a5a85 --- /dev/null +++ b/src/lib/syntax.c @@ -0,0 +1,9 @@ +#include "aplwc_internal.h" + +struct token_list * +scan_line(struct aplwc *aplwc, struct string *text) +{ + aplwc->last_error = APLWC_NOT_YET_IMPLEMENTED; + UNUSED_PARAMETER(text); + return NULL; +} |