parsing for registers
haldean
4 years ago
19 | 19 | #include "meka.h" |
20 | 20 | #include "meka_internal.h" |
21 | 21 | |
22 | #include <stdio.h> | |
23 | #include <string.h> | |
24 | ||
22 | 25 | #define _is_whitespace(c) ((c) == ' ' || (c) == '\n' || (c) == '\r') |
23 | 26 | |
24 | 27 | static meka_word p[4096]; |
25 | 28 | static uint16_t pn = 0; |
29 | ||
30 | meka_register reg[] = { | |
31 | { .name = {'c', 'a', 'l', 0 }, .typ = meka_tag_bool }, | |
32 | { .name = {'g', 'o', 0, 0 }, .typ = meka_tag_bool }, | |
33 | { .name = {'j', 'o', 'g', 'q'}, .typ = meka_tag_qvec }, | |
34 | { .name = {'j', 'o', 'g', 'r'}, .typ = meka_tag_rvec }, | |
35 | { .name = {'m', 'l', 'd', 0 }, .typ = meka_tag_chan }, | |
36 | { .name = {'m', 'l', 'e', 0 }, .typ = meka_tag_chan }, | |
37 | { .name = {'m', 'l', 's', 0 }, .typ = meka_tag_chan }, | |
38 | { .name = {'m', 'r', 'd', 0 }, .typ = meka_tag_chan }, | |
39 | { .name = {'m', 'r', 'e', 0 }, .typ = meka_tag_chan }, | |
40 | { .name = {'m', 'r', 's', 0 }, .typ = meka_tag_chan }, | |
41 | { .name = {'p', 'e', 'n', 0 }, .typ = meka_tag_bool }, | |
42 | { .name = {'p', 'i', 'v', 'l'}, .typ = meka_tag_rvec }, | |
43 | { .name = {'p', 'i', 'v', 'r'}, .typ = meka_tag_rvec }, | |
44 | { .name = {'r', 'a', 'd', 'l'}, .typ = meka_tag_int }, | |
45 | { .name = {'r', 'a', 'd', 'r'}, .typ = meka_tag_int }, | |
46 | { .name = {'s', 't', 'e', 'p'}, .typ = meka_tag_int }, | |
47 | }; | |
48 | const size_t regn = sizeof(reg) / sizeof(*reg); | |
26 | 49 | |
27 | 50 | void |
28 | 51 | meka_skip_to_token(meka_source *src) |
63 | 86 | return res->len > 0; |
64 | 87 | } |
65 | 88 | |
66 | meka_value | |
67 | meka_parse_number(meka_token *t) | |
89 | meka_parse_result | |
90 | meka_parse_number(meka_token *t, meka_value *v) | |
68 | 91 | { |
69 | 92 | int32_t res; |
70 | 93 | int8_t s; |
95 | 118 | * early-reject those and then don't have to check for overflow when |
96 | 119 | * building the 32-bit intermediate result. */ |
97 | 120 | if (t->len - i > 9) |
98 | return meka_bad_value; | |
121 | { | |
122 | /* distinguish between not-a-number and number-but-overflow */ | |
123 | for (; i < t->len; i++) | |
124 | if ('0' > t->data[i] || t->data[i] > '9') | |
125 | return PARSE_FAIL; | |
126 | return PARSE_INVALID_VALUE; | |
127 | } | |
99 | 128 | |
100 | 129 | for (; i < t->len; i++) |
101 | 130 | { |
103 | 132 | if ('0' <= c && c <= '9') |
104 | 133 | res = res * 10 + (c - '0'); |
105 | 134 | else |
106 | return meka_bad_value; | |
135 | return PARSE_FAIL; | |
107 | 136 | } |
108 | 137 | |
109 | 138 | if (res > 0xFFFFFFF) |
110 | return meka_bad_value; | |
111 | return meka_pack(int, s * res); | |
139 | return PARSE_INVALID_VALUE; | |
140 | *v = meka_pack(int, s * res); | |
141 | return PARSE_OK; | |
142 | } | |
143 | ||
144 | meka_parse_result | |
145 | meka_parse_register(meka_token *t, meka_value *v) | |
146 | { | |
147 | size_t i; | |
148 | meka_register test = {0}; | |
149 | ||
150 | if (t->len <= 0 || t->len > 5 || t->data[0] != '%') | |
151 | return PARSE_FAIL; | |
152 | ||
153 | for (i = 1; i < t->len; i++) | |
154 | test.name[i - 1] = t->data[i]; | |
155 | ||
156 | for (i = 0; i < regn; i++) | |
157 | { | |
158 | if (test.namebits == reg[i].namebits) | |
159 | { | |
160 | *v = meka_pack(reg, i); | |
161 | return PARSE_OK; | |
162 | } | |
163 | } | |
164 | return PARSE_INVALID_VALUE; | |
112 | 165 | } |
113 | 166 | |
114 | 167 | int |
116 | 169 | { |
117 | 170 | meka_token tok; |
118 | 171 | meka_value v; |
172 | meka_parse_result rc; | |
119 | 173 | |
120 | 174 | pn = 0; |
121 | 175 | while (meka_next_token(&tok, src)) |
122 | 176 | { |
123 | v = meka_parse_number(&tok); | |
124 | if (v != meka_bad_value) | |
125 | { | |
126 | p[pn++].v = v; | |
127 | continue; | |
177 | rc = meka_parse_number(&tok, &p[pn++].v); | |
178 | if (rc == PARSE_OK) | |
179 | continue; | |
180 | if (rc == PARSE_INVALID_VALUE) | |
181 | { | |
182 | printf("number '"); | |
183 | fwrite(tok.data, 1, tok.len, stdout); | |
184 | printf("' overflows a 28-bit signed value\n"); | |
185 | goto fail; | |
186 | } | |
187 | ||
188 | rc = meka_parse_register(&tok, &v); | |
189 | if (rc == PARSE_OK) | |
190 | continue; | |
191 | if (rc == PARSE_INVALID_VALUE) | |
192 | { | |
193 | printf("register "); | |
194 | fwrite(tok.data, 1, tok.len, stdout); | |
195 | printf(" doesn't exist\n"); | |
196 | goto fail; | |
128 | 197 | } |
129 | 198 | } |
130 | 199 | |
131 | 200 | return pn; |
132 | } | |
201 | ||
202 | fail: | |
203 | pn = 0; | |
204 | memset(p, 0, sizeof(p)); | |
205 | return pn; | |
206 | } |
19 | 19 | #pragma once |
20 | 20 | #include <stdint.h> |
21 | 21 | |
22 | static const uint32_t meka_tag_bool = 0x00000000; | |
23 | static const uint32_t meka_tag_int = 0x00000001; | |
24 | static const uint32_t meka_tag_qvec = 0x00000002; | |
25 | static const uint32_t meka_tag_rvec = 0x00000003; | |
26 | static const uint32_t meka_tag_reg = 0x00000004; | |
27 | static const uint32_t meka_tag_chan = 0x00000005; | |
28 | static const uint32_t meka_tag_cset = 0x00000006; | |
29 | static const uint32_t meka_tag_none = 0x00000007; | |
30 | static const uint32_t meka_tag_mask = 0xFFFFFFF8; | |
22 | /* these are #defines instead of const uint32_t's so that they can be | |
23 | * used to initialize static structures */ | |
24 | #define meka_tag_bool ((uint32_t) 0x00000000) | |
25 | #define meka_tag_int ((uint32_t) 0x00000001) | |
26 | #define meka_tag_qvec ((uint32_t) 0x00000002) | |
27 | #define meka_tag_rvec ((uint32_t) 0x00000003) | |
28 | #define meka_tag_reg ((uint32_t) 0x00000004) | |
29 | #define meka_tag_chan ((uint32_t) 0x00000005) | |
30 | #define meka_tag_cset ((uint32_t) 0x00000006) | |
31 | #define meka_tag_none ((uint32_t) 0x00000007) | |
32 | #define meka_tag_mask ((uint32_t) 0xFFFFFFF8) | |
31 | 33 | |
32 | 34 | typedef uint32_t meka_value; |
33 | 35 |
28 | 28 | uint8_t marker; |
29 | 29 | } meka_token; |
30 | 30 | |
31 | static const uint8_t meka_word_none = 0x00; | |
32 | static const uint8_t meka_word_int = 0x01; | |
33 | static const uint8_t meka_word_reg = 0x02; | |
34 | static const uint8_t meka_word_txt = 0x03; | |
35 | ||
36 | 31 | typedef struct |
37 | 32 | { |
38 | 33 | union |
41 | 36 | meka_token t; |
42 | 37 | }; |
43 | 38 | } meka_word; |
39 | ||
40 | typedef struct | |
41 | { | |
42 | union | |
43 | { | |
44 | char name[4]; | |
45 | uint32_t namebits; | |
46 | }; | |
47 | uint32_t typ; | |
48 | } meka_register; | |
49 | ||
50 | typedef enum | |
51 | { | |
52 | PARSE_OK, | |
53 | /* parsed successfully but the value it represents is invalid */ | |
54 | PARSE_INVALID_VALUE, | |
55 | /* couldn't parse it at all */ | |
56 | PARSE_FAIL, | |
57 | } meka_parse_result; |
46 | 46 | return ok; |
47 | 47 | } |
48 | 48 | |
49 | test_t | |
50 | pack_register() | |
51 | { | |
52 | meka_value v; | |
53 | ||
54 | v = meka_pack(reg, 1); | |
55 | assert((int32_t) meka_unpack(v) == 1); | |
56 | assert(meka_tag(v) == meka_tag_reg); | |
57 | ||
58 | return ok; | |
59 | } | |
60 | ||
49 | 61 | int main() |
50 | 62 | { |
51 | 63 | init(); |
52 | 64 | run(pack_positive_int); |
53 | 65 | run(pack_negative_int); |
66 | run(pack_register); | |
54 | 67 | finish(); |
55 | 68 | } |
20 | 20 | #include "meka_internal.h" |
21 | 21 | #include "unit.h" |
22 | 22 | |
23 | extern meka_value meka_parse_number(meka_token *t); | |
23 | #include <string.h> | |
24 | ||
25 | extern meka_parse_result meka_parse_number(meka_token *t, meka_value *v); | |
26 | extern meka_parse_result meka_parse_register(meka_token *t, meka_value *v); | |
27 | extern meka_register reg[]; | |
28 | ||
29 | #define parse_number_case(str, num) \ | |
30 | t.data = str; t.len = strlen(str); \ | |
31 | assert(meka_parse_number(&t, &v) == PARSE_OK); \ | |
32 | assert(v == meka_pack(int, num)); | |
33 | ||
34 | #define parse_number_case_fail(str, code) \ | |
35 | t.data = str; t.len = strlen(str); \ | |
36 | assert(meka_parse_number(&t, &v) == code); | |
24 | 37 | |
25 | 38 | test_t |
26 | 39 | parse_number() |
27 | 40 | { |
28 | 41 | meka_token t; |
42 | meka_value v; | |
29 | 43 | |
30 | t.data = "0"; t.len = 1; | |
31 | assert(meka_parse_number(&t) == meka_pack(int, 0)); | |
32 | ||
33 | t.data = "1"; t.len = 1; | |
34 | assert(meka_parse_number(&t) == meka_pack(int, 1)); | |
35 | ||
36 | t.data = "+1"; t.len = 2; | |
37 | assert(meka_parse_number(&t) == meka_pack(int, 1)); | |
38 | ||
39 | t.data = "-1"; t.len = 2; | |
40 | assert(meka_parse_number(&t) == meka_pack(int, -1)); | |
41 | ||
42 | t.data = "00000"; t.len = 5; | |
43 | assert(meka_parse_number(&t) == meka_pack(int, 0)); | |
44 | parse_number_case("0", 0); | |
45 | parse_number_case("1", 1); | |
46 | parse_number_case("+1", 1); | |
47 | parse_number_case("-1", -1); | |
48 | parse_number_case("00000", 0); | |
44 | 49 | |
45 | 50 | /* Not a digit overflow, because they're all "leading" zeroes */ |
46 | t.data = "0000000000000000"; t.len = 16; | |
47 | assert(meka_parse_number(&t) == meka_pack(int, 0)); | |
51 | parse_number_case("0000000000000000", 0); | |
48 | 52 | |
49 | 53 | /* Digit overflow */ |
50 | t.data = "1000000000000000"; t.len = 16; | |
51 | assert(meka_parse_number(&t) == meka_bad_value); | |
54 | parse_number_case_fail("1000000000000000", PARSE_INVALID_VALUE); | |
52 | 55 | |
53 | 56 | /* 28-bit overflow, with admissable number of digits */ |
54 | t.data = "268435457"; t.len = 9; | |
55 | assert(meka_parse_number(&t) == meka_bad_value); | |
57 | parse_number_case_fail("268435457", PARSE_INVALID_VALUE); | |
56 | 58 | |
57 | 59 | /* 28-bit int-max */ |
58 | t.data = "268435455"; t.len = 9; | |
59 | assert(meka_parse_number(&t) == meka_pack(int, 268435455)); | |
60 | parse_number_case("268435455", 268435455); | |
60 | 61 | |
61 | 62 | /* 28-bit int-min */ |
62 | t.data = "-268435455"; t.len = 10; | |
63 | assert(meka_parse_number(&t) == meka_pack(int, -268435455)); | |
63 | parse_number_case("-268435455", -268435455); | |
64 | ||
65 | /* Not even a number */ | |
66 | parse_number_case_fail("1234asdf", PARSE_FAIL); | |
67 | ||
68 | /* Overflows on length but is also not a number */ | |
69 | parse_number_case_fail("123456789asdf", PARSE_FAIL); | |
70 | ||
71 | return ok; | |
72 | } | |
73 | ||
74 | #define parse_register_case(str, type) \ | |
75 | t.data = str; t.len = strlen(str); \ | |
76 | assert(meka_parse_register(&t, &v) == PARSE_OK); \ | |
77 | assert(reg[meka_unpack(v)].typ == meka_tag_ ## type); | |
78 | ||
79 | #define parse_register_case_fail(str, code) \ | |
80 | t.data = str; t.len = strlen(str); \ | |
81 | assert(meka_parse_register(&t, &v) == code); | |
82 | ||
83 | test_t | |
84 | parse_register() | |
85 | { | |
86 | meka_token t; | |
87 | meka_value v; | |
88 | ||
89 | parse_register_case("%cal", bool); | |
90 | parse_register_case("%go", bool); | |
91 | parse_register_case("%jogq", qvec); | |
92 | parse_register_case("%jogr", rvec); | |
93 | parse_register_case("%mld", chan); | |
94 | parse_register_case("%mle", chan); | |
95 | parse_register_case("%mls", chan); | |
96 | parse_register_case("%mrd", chan); | |
97 | parse_register_case("%mre", chan); | |
98 | parse_register_case("%mrs", chan); | |
99 | parse_register_case("%pen", bool); | |
100 | parse_register_case("%pivl", rvec); | |
101 | parse_register_case("%pivr", rvec); | |
102 | parse_register_case("%radl", int); | |
103 | parse_register_case("%radr", int); | |
104 | parse_register_case("%step", int); | |
105 | ||
106 | parse_register_case_fail("asdf", PARSE_FAIL); | |
107 | parse_register_case_fail("%asdf", PARSE_INVALID_VALUE); | |
64 | 108 | |
65 | 109 | return ok; |
66 | 110 | } |
70 | 114 | { |
71 | 115 | init(); |
72 | 116 | run(parse_number); |
117 | run(parse_register); | |
73 | 118 | finish(); |
74 | 119 | } |