~fincham/relic

relic/relic.yacc -rw-r--r-- 2.3 KiB
be08dd29Michael Fincham Allow literals to contain a literal backtick if escaped a month ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
%{
#include <mcheck.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define YYSTYPE char*
#define YYDEBUG 1

/* prevent gcc warnings */
int yylex(void);
int yyparse(void);

int yydebug = 0;

void yyerror(const char *str) {
    fprintf(stderr,"error: %s\n", str);
}

int yywrap() {
    return 1;
}

void main() {
    mtrace();
    yyparse();
}

char* string_append(char* left, char* right) {
    char* combined = malloc(strlen(left) + strlen(right) + 1);
    sprintf(combined, "%s%s", left, right);
    free(left);
    free(right);
    return combined;
}

char* html_wrap_with_tag(char* tag, char* text) {
    char* wrapped = malloc(strlen(tag) * 2 + strlen(text) + 6); /* 6 = strlen("<></>") + 1 */
    sprintf(wrapped, "<%s>%s</%s>", tag, text, tag);
    free(text);
    return wrapped;
}

char* html_link_to(char* href, char* text) {
    const char* link_format = "{<a href=\"%s\">%s</a>}";
    char* wrapped = malloc(strlen(href) + strlen(text) + strlen(link_format) - 3); /* 3 = strlen('%s') * 2 - 1 */
    sprintf(wrapped, link_format, href, text);
    if (href != text) {
        free(text);
    }
    free(href);
    return wrapped;
}

char* html_image(char* src, char* alt) {
    const char* image_format = "<img src=\"%s\" alt=\"%s\">";
    char* wrapped = malloc(strlen(src) + strlen(alt) + strlen(image_format) - 3); /* 3 = strlen('%s') * 2 - 1 */
    sprintf(wrapped, image_format, src, alt);
    free(src);
    free(alt);
    return wrapped;
}
%}
%token NEWLINE SPACE WORD LSTAR RSTAR LSLASH RSLASH LBRACE RBRACE LSQUARE RSQUARE IMAGE LBACKTICK RBACKTICK
%%
page: 
    lines;

lines:
    | lines line;

line:
    NEWLINE { 
        printf("<br>\n"); 
    } | inlines NEWLINE { 
        printf("<p>%s</p>\n", $1);
        free($1);
    }

inlines:
    inline | inlines inline {
        $$ = string_append($1, $2);
    }

inline:
    WORD
    | SPACE
    | LBACKTICK inlines RBACKTICK {
        $$ = html_wrap_with_tag("code", $2);
    } | IMAGE WORD SPACE inlines RSQUARE {
        $$ = html_image($2, $4);
    } | LBRACE WORD RBRACE {
        $$ = html_link_to($2, $2);    
    } | LBRACE WORD SPACE inlines RBRACE {
        $$ = html_link_to($2, $4);    
    } | LSTAR inlines RSTAR {
        $$ = html_wrap_with_tag("strong", $2);    
    } | LSLASH inlines RSLASH {
        $$ = html_wrap_with_tag("em", $2);    
    };