librdesc
Loading...
Searching...
No Matches
bc_interpreter.h
Go to the documentation of this file.
1
6#ifndef BC_INTERPRETER_H
7#define BC_INTERPRETER_H
8
9#include "../../include/cst_macros.h"
10#include "../../include/rdesc.h"
11#include "../../include/util.h"
12#include "../../src/common.h"
13
14#include "../grammar/bc.h"
15
16#include <stdint.h>
17#include <string.h>
18#include <stdlib.h>
19
20
22static inline double bc_pow10(int i)
23{
24 double r = 1;
25
26 while (i--)
27 r *= 10;
28
29 return r;
30}
31
33static inline double bc_interpreter(struct rdesc *p, struct rdesc_node *n)
34{
35 size_t alt_idx = ralt_idx(n);
36
37 /* for use in str->num serialization in NT_UNSIGNED_NUM */
38 char *decimal_part, *floating_part;
39 double converted;
40
41 switch (rid(n)) {
42 case NT_UNSIGNED_NUM:
43 switch (alt_idx) {
44 case 0:
45 memcpy(&decimal_part, rseminfo(rchild(p, n, 0)),
46 sizeof(char *));
47
48 converted = strtod(decimal_part, NULL);
49
50 free(decimal_part);
51 return converted;
52 case 1:
53 memcpy(&floating_part, rseminfo(rchild(p, n, 1)),
54 sizeof(char *));
55
56 converted = strtod(floating_part, NULL) /
57 bc_pow10(strlen(floating_part));
58
59 free(floating_part);
60 return converted;
61 default:
62 memcpy(&decimal_part, rseminfo(rchild(p, n, 0)),
63 sizeof(char *));
64 memcpy(&floating_part, rseminfo(rchild(p, n, 2)),
65 sizeof(char *));
66
67 converted = strtod(decimal_part, NULL) +
68 strtod(floating_part, NULL) /
69 bc_pow10(strlen(floating_part));
70
71 free(decimal_part);
72 free(floating_part);
73 return converted;
74 }
75
76 case NT_OPTSIGN:
77 return (alt_idx == 0) ? -1 : 1;
78
79 case NT_FACTOR:
80 return bc_interpreter(p, rchild(p, n, 0)) *
81 bc_interpreter(p, rchild(p, n, 1));
82
83 case NT_EXPR:
84 switch (alt_idx) {
85 case 0:
86 rdesc_flip_left(p, n, 2) /* flip term */;
87
88 return bc_interpreter(p, rchild(p, n, 0)) +
89 (ralt_idx(rchild(p, n, 1)) == 0 ? 1 : -1) *
90 bc_interpreter(p, rchild(p, n, 2));
91 default:
92 rdesc_flip_left(p, n, 0) /* flip term */;
93
94 return bc_interpreter(p, rchild(p, n, 0));
95 }
96
97 case NT_TERM:
98 switch (alt_idx) {
99 case 0:
100 return bc_interpreter(p, rchild(p, n, 0)) *
101 (ralt_idx(rchild(p, n, 1)) == 0 ?
102 bc_interpreter(p, rchild(p, n, 2)) :
103 1 / bc_interpreter(p, rchild(p, n, 2)));
104 default:
105 return bc_interpreter(p, rchild(p, n, 0));
106 }
107
108 case NT_ATOM:
109 switch (alt_idx) {
110 case 0:
111 return bc_interpreter(p, rchild(p, n, 0));
112 default:
113 rdesc_flip_left(p, n, 1) /* flip expr */;
114
115 return bc_interpreter(p, rchild(p, n, 1));
116 }
117
118 case NT_STMT:
119 rdesc_flip_left(p, n, 0) /* flip expr */;
120
121 return bc_interpreter(p, rchild(p, n, 0));
122 }
123
124 unreachable(); return 0; // GCOV_EXCL_LINE
125}
126
128static inline void bc_tk_destroyer(uint16_t tk, void *seminfo_)
129{
130 if (tk == TK_NUM) {
131 void *seminfo;
132 memcpy(&seminfo, seminfo_, sizeof(void *));
133
134 if (seminfo)
135 free(seminfo);
136 }
137}
138
139
140#endif
static double bc_interpreter(struct rdesc *p, struct rdesc_node *n)
Interprets CST of bc.
static void bc_tk_destroyer(uint16_t tk, void *seminfo_)
Frees seminfo of a bc token.
static double bc_pow10(int i)
Raises 10 to the power of i.
#define rid(node)
Returns the 15-bit identifier for underlying token/nonterminal.
Definition cst_macros.h:77
#define rchild(p, nt_node, child_idx)
Returns child of the node by its index.
Definition cst_macros.h:115
#define ralt_idx(nt_node)
Returns index of the nonterminal alternative in production rule.
Definition cst_macros.h:84
#define rseminfo(tk_node)
Returns a reference to the token's seminfo field.
Definition cst_macros.h:99
#define r(...)
Macro to define a grammar rule. Adds end of alternative and end of production body sentinels to gramm...
Definition rule_macros.h:72
Recursive descent parser state.
Definition rdesc.h:40
void rdesc_flip_left(struct rdesc *parser, struct rdesc_node *parent, uint16_t child_index)
Rotates a right-recursive concrete syntax tree into a left-recursive form.