librdesc
Loading...
Searching...
No Matches
bc_interactive.c
1#include "../include/rdesc.h"
2#include "../include/grammar.h"
3#include "../src/common.h"
4
5#include "grammar/bc.h"
7#include "lib/exblex.h"
8
9#include <stdint.h>
10#include <stdio.h>
11#include <stdbool.h>
12#include <string.h>
13
14
15void program(struct exblex *lex, struct rdesc *p)
16{
17 char buf[4096];
18
19 int pump_res;
20
21 while (true) {
22 unwrap(rdesc_start(p, NT_STMT));
23
24 pump_res = -1;
25
26 printf("> ");
27 while (pump_res != RDESC_READY) {
28 if (fgets(buf, 4096, stdin) == NULL) {
29 rdesc_reset(p);
30
31 return;
32 }
33
34 exblex_init(lex, buf, bc_tks);
35
36 uint16_t tk;
37 while ((tk = exblex_next(lex)) != 0) {
38 const void *seminfo = exblex_current_seminfo(lex);
39 pump_res =
40 rdesc_pump(p, tk, &seminfo);
41
42 if (pump_res == RDESC_CONTINUE)
43 continue;
44
45 break;
46 }
47
48 if (tk == 0 && lex->cur <= strlen(buf)) {
49 printf(" %*s", (int) lex->cur, "^\n");
50 printf("Invalid token, ignoring tokens after "
51 "index %zu!\n", lex->cur);
52 }
53
54 if (pump_res == RDESC_NOMATCH) {
55 printf("SYNTAX ERROR!\n");
56 rdesc_reset(p);
57
58 break;
59 }
60
61 if (pump_res == RDESC_CONTINUE || pump_res == -1)
62 printf(" ");
63 }
64
65 if (pump_res == RDESC_READY) {
66 struct rdesc_node *cst;
67 cst = rdesc_root(p);
68
69 printf("< (%.2lf)\n", bc_interpreter(p, cst));
70 }
71 }
72}
73
74
75int main(void)
76{
77 struct exblex lex;
78 struct rdesc_grammar grammar;
79 struct rdesc p;
80
81 unwrap(rdesc_grammar_init(&grammar,
82 BC_PRODUCTION_COUNT,
83 BC_MAX_ALTERNATIVE_COUNT,
84 BC_MAX_ALTERNATIVE_SIZE,
85 (struct rdesc_grammar_symbol *) bc));
86 unwrap(rdesc_init(&p,
87 &grammar,
88 sizeof(void *) /* semantic info holds char* */,
90
91 printf("Basic Calculator, librdesc sample program\n");
92 program(&lex, &p);
93
94 rdesc_destroy(&p);
95 rdesc_grammar_destroy(&grammar);
96}
Basic calculator.
Basic interpreter for bc.
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.
Basic lexer, used for testing.
static char * exblex_current_seminfo(struct exblex *l)
Retrieves the semantic information for the last token.
Definition exblex.h:107
static uint16_t exblex_next(struct exblex *l)
Fetches the next token.
Definition exblex.h:122
static void exblex_init(struct exblex *l, const char *buf, const char *tokens)
Initializes the basic lexer with a null-terminated list of chars.
Definition exblex.h:82
void rdesc_grammar_destroy(struct rdesc_grammar *grammar)
Frees resources allocated by the grammar.
int rdesc_grammar_init(struct rdesc_grammar *grammar, uint16_t production_count, uint16_t max_alternative_count, uint16_t max_alternative_size, const struct rdesc_grammar_symbol *production_rules) _rdesc_wur
Initializes a grammar struct.
int rdesc_start(struct rdesc *parser, uint16_t start_symbol) _rdesc_wur
Sets start symbol for the next match.
int rdesc_init(struct rdesc *parser, const struct rdesc_grammar *grammar, size_t seminfo_size, void(*token_destroyer)(uint16_t id, void *seminfo)) _rdesc_wur
Initializes a new parser.
void rdesc_reset(struct rdesc *parser)
Resets the parser to its initial state.
enum rdesc_result rdesc_pump(struct rdesc *parser, uint16_t id, void *seminfo) _rdesc_wur
Drives the parsing process, the pump.
void rdesc_destroy(struct rdesc *parser)
Frees memory allocated by the parser and destroys the parser instance.
struct rdesc_node * rdesc_root(struct rdesc *parser)
Returns the root of the CST.
@ RDESC_READY
Definition rdesc.h:32
@ RDESC_NOMATCH
Definition rdesc.h:36
@ RDESC_CONTINUE
Definition rdesc.h:34
EXtremely Basic LEXer.
Definition exblex.h:37
size_t cur
(current) Position in the buffer.
Definition exblex.h:50
A terminal or nonterminal representing the body (right side) of a production rule.
Definition grammar.h:89
Grammar definition.
Definition grammar.h:50
Recursive descent parser state.
Definition rdesc.h:40