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 decimal_part = rseminfo(rchild(p, n, 0));
46
47 converted = strtod(*decimal_part, NULL);
48
49 free(*decimal_part);
50 return converted;
51 case 1:
52 floating_part = rseminfo(rchild(p, n, 1));
53
54 converted = strtod(*floating_part, NULL) /
55 bc_pow10(strlen(*floating_part));
56
57 free(*floating_part);
58 return converted;
59 default:
60 decimal_part = rseminfo(rchild(p, n, 0));
61 floating_part = rseminfo(rchild(p, n, 2));
62
63 converted = strtod(*decimal_part, NULL) +
64 strtod(*floating_part, NULL) /
65 bc_pow10(strlen(*floating_part));
66
67 free(*decimal_part);
68 free(*floating_part);
69 return converted;
70 }
71
72 case NT_OPTSIGN:
73 return (alt_idx == 0) ? -1 : 1;
74
75 case NT_FACTOR:
76 return bc_interpreter(p, rchild(p, n, 0)) *
77 bc_interpreter(p, rchild(p, n, 1));
78
79 case NT_EXPR:
80 switch (alt_idx) {
81 case 0:
82 rdesc_flip_left(p, n, 2) /* flip term */;
83
84 return bc_interpreter(p, rchild(p, n, 0)) +
85 (ralt_idx(rchild(p, n, 1)) == 0 ? 1 : -1) *
86 bc_interpreter(p, rchild(p, n, 2));
87 default:
88 rdesc_flip_left(p, n, 0) /* flip term */;
89
90 return bc_interpreter(p, rchild(p, n, 0));
91 }
92
93 case NT_TERM:
94 switch (alt_idx) {
95 case 0:
96 return bc_interpreter(p, rchild(p, n, 0)) *
97 (ralt_idx(rchild(p, n, 1)) == 0 ?
98 bc_interpreter(p, rchild(p, n, 2)) :
99 1 / bc_interpreter(p, rchild(p, n, 2)));
100 default:
101 return bc_interpreter(p, rchild(p, n, 0));
102 }
103
104 case NT_ATOM:
105 switch (alt_idx) {
106 case 0:
107 return bc_interpreter(p, rchild(p, n, 0));
108 default:
109 rdesc_flip_left(p, n, 1) /* flip expr */;
110
111 return bc_interpreter(p, rchild(p, n, 1));
112 }
113
114 case NT_STMT:
115 rdesc_flip_left(p, n, 0) /* flip expr */;
116
117 return bc_interpreter(p, rchild(p, n, 0));
118 }
119
120 unreachable(); return 0; // GCOV_EXCL_LINE
121}
122
124static inline void bc_tk_destroyer(uint16_t tk, void *seminfo_)
125{
126 if (tk == TK_NUM) {
127 void *seminfo;
128 memcpy(&seminfo, seminfo_, sizeof(void *));
129
130 if (seminfo)
131 free(seminfo);
132 }
133}
134
135
136#endif
static double bc_interpreter(struct rdesc *p, struct rdesc_node *n)
Interprets CST of bc.
Definition bc_interpreter.h:33
static void bc_tk_destroyer(uint16_t tk, void *seminfo_)
Frees seminfo of a bc token.
Definition bc_interpreter.h:124
static double bc_pow10(int i)
Raises 10 to the power of i.
Definition bc_interpreter.h:22
#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:42
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.