From db1fc26c82065656e558022e59f886b70ed7d78d Mon Sep 17 00:00:00 2001 From: "Sven M. Hallberg" <pesco@khjk.org> Date: Mon, 25 Nov 2019 12:57:48 +0100 Subject: [PATCH] add examples/ttuser - show custom tokens/pprint --- examples/SConscript | 3 +- examples/ttuser.c | 140 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 142 insertions(+), 1 deletion(-) create mode 100644 examples/ttuser.c diff --git a/examples/SConscript b/examples/SConscript index b34b85a1..8504b4bb 100644 --- a/examples/SConscript +++ b/examples/SConscript @@ -6,8 +6,9 @@ example = env.Clone() example.Append(LIBS="hammer", LIBPATH="../src") dns = example.Program('dns', ['dns.c', 'rr.c', 'dns_common.c']) +ttuser = example.Program('ttuser', 'ttuser.c') base64 = example.Program('base64', 'base64.c') base64_sem1 = example.Program('base64_sem1', 'base64_sem1.c') base64_sem2 = example.Program('base64_sem2', 'base64_sem2.c') ties = example.Program('ties', ['ties.c', 'grammar.c']) -env.Alias("examples", [dns, base64, base64_sem1, base64_sem2, ties]) \ No newline at end of file +env.Alias("examples", [dns, ttuser, base64, base64_sem1, base64_sem2, ties]) diff --git a/examples/ttuser.c b/examples/ttuser.c new file mode 100644 index 00000000..4e83356c --- /dev/null +++ b/examples/ttuser.c @@ -0,0 +1,140 @@ +/* + * Example parser that demonstrates the use of user-defined token types. + * + * Note the custom printer function that hooks into h_pprint(). + */ + +#include "../src/hammer.h" +#include "../src/glue.h" + + +/* + * custom tokens + */ + +HTokenType TT_SUBJ, TT_PRED, TT_OBJ, TT_ADJ, TT_ADVC; + +void +pprint(FILE *stream, const HParsedToken *tok, int indent, int delta) +{ + /* + * Pretty-printer rules: + * + * - Output 'indent' spaces after every newline you produce. + * - Do not add indent on the first line of output. + * - Do not add a trailing newline. + * - Indent sub-objects by adding 'delta' to 'indent'. + */ + + if (((HParsedToken *)tok->user)->token_type == TT_SEQUENCE) + fprintf(stream, "\n%*s", indent, ""); + h_pprint(stream, tok->user, indent, delta); +} + +/* XXX define umamb_sub as well */ + +void +init(void) +{ + TT_SUBJ = h_allocate_token_new("subject", NULL, pprint); + TT_PRED = h_allocate_token_new("predicate", NULL, pprint); + TT_OBJ = h_allocate_token_new("object", NULL, pprint); + TT_ADJ = h_allocate_token_new("adjective", NULL, pprint); + TT_ADVC = h_allocate_token_new("adverbial clause", NULL, pprint); +} + + +/* + * semantic actions + * + * Normally these would be more interesting, but for this example, we just wrap + * our tokens in their intended types. + */ +HParsedToken *act_subj(const HParseResult *p, void *u) { + return H_MAKE(SUBJ, (void *)p->ast); +} +HParsedToken *act_pred(const HParseResult *p, void *u) { + return H_MAKE(PRED, (void *)p->ast); +} +HParsedToken *act_obj(const HParseResult *p, void *u) { + return H_MAKE(OBJ, (void *)p->ast); +} +HParsedToken *act_adj(const HParseResult *p, void *u) { + return H_MAKE(ADJ, (void *)p->ast); +} +HParsedToken *act_advc(const HParseResult *p, void *u) { + return H_MAKE(ADVC, (void *)p->ast); +} + + +/* + * grammar + */ + +HParser * +build_parser(void) +{ + /* words */ + #define W(X) h_whitespace(h_literal(#X)) + H_RULE(art, h_choice(W(a), W(the), NULL)); + H_RULE(noun, h_choice(W(cat), W(dog), W(fox), W(tiger), W(lion), + W(bear), W(fence), W(tree), W(car), W(cow), NULL)); + H_RULE(verb, h_choice(W(eats), W(jumps), W(falls), NULL)); + H_ARULE(adj, h_choice(W(quick), W(slow), W(happy), W(lazy), W(cyan), + W(magenta), W(yellow), W(black), W(brown), NULL)); + H_RULE(adverb, h_choice(W(with), W(over), W(after), NULL)); + #undef W + + /* phrases */ + H_RULE(nphrase, h_sequence(art, h_many(adj), noun, NULL)); + + /* sentence structure */ + H_ARULE(subj, nphrase); + H_ARULE(pred, verb); + H_ARULE(obj, nphrase); + H_ARULE(advc, h_sequence(adverb, nphrase, NULL)); + H_RULE(sentnc, h_sequence(subj, pred, + h_optional(obj), h_optional(advc), NULL)); + + return sentnc; +} + + +/* + * main routine: read, parse, print + * + * input e.g.: + * "the quick brown fox jumps the fence with a cyan lion" + */ + +#include <stdio.h> +#include <inttypes.h> + +int +main(int argc, char **argv) +{ + uint8_t input[1024]; + size_t sz; + const HParser *parser; + const HParseResult *result; + + init(); + parser = build_parser(); + + sz = fread(input, 1, sizeof(input), stdin); + if (!feof(stdin)) { + fprintf(stderr, "too much input\n"); + return 1; + } + + result = h_parse(parser, input, sz); + if (!result) { + fprintf(stderr, "no parse\n"); + return 1; + } + + h_pprintln(stdout, result->ast); + fprintf(stderr, "consumed %" PRId64 "/%zu bytes.\n", + result->bit_length / 8, sz); + return 0; +} -- GitLab