Summary Files Commits Branches @commit @diff @stats
path: root / Year 2 / Implementation of Programming Languages / Homework 02 / commonlisp2html.y
blob: 2a7bf9100e60b0a935b0792a9154294ec429ea96 (plain) (blame)
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
101
102
103
104
105
106
107
108
109
110
111
%{
#include <stdio.h>
#include <string.h>

int yylex();
int yyerror(char *s);

#define LBRACKET_SPAN "<span class=\"bracket\">(</span>"
#define RBRACKET_SPAN "<span class=\"bracket\">)</span>"

char* span(char *c, char *s);
char* details(char *summary, char *rest);
char* concat2(char *first, char *second);
char* concatperm2(char *first, char *second);
char* concatperm3(char *first, char *second, char *third);
%}

%token LBRACKET RBRACKET OTHER 
%token NEWLINE SPACE TAB
%token STR NUM COMMENT PARAMETER_TYPE KEYWORD CONSTANT
%token SPECIAL_FORM FUNCTION MACRO VARIABLE

%define api.value.type {char*}

%%

start:
	 | start stlist   { printf("%s", $2); free($2); }
	 | start terminal { printf("%s", $2); free($2); }
	 | start NEWLINE  { printf("\n"); }

stlist: LBRACKET RBRACKET                       { $$ = concat2(LBRACKET_SPAN, RBRACKET_SPAN); } 
	  | LBRACKET list RBRACKET                  { $$ = concatperm3(LBRACKET_SPAN, $2, RBRACKET_SPAN); }
	  | LBRACKET NEWLINE list RBRACKET          { $$ = details(concat2(LBRACKET_SPAN, ""), $3); }
	  | LBRACKET list NEWLINE postlist RBRACKET { $$ = details($2, $4); }
	  ;

postlist:                   { $$ = ""; }
		| postlist stlist   { $$ = concat2($1, $2); free($2); }
		| postlist terminal { $$ = concat2($1, $2); free($2); }
		| postlist NEWLINE  { $$ = concat2($1, "\n"); }
		;

list: terminal
	| list terminal { $$ = concatperm2($1, $2); }
	| stlist
	| list stlist   { $$ = concatperm2($1, $2); }
	;

terminal: STR            { $$ = span("string", $1); }
		| NUM            { $$ = span("number", $1); }
		| COMMENT        { $$ = span("comment", $1); }
		| PARAMETER_TYPE { $$ = span("parameter-type", $1); }
		| KEYWORD        { $$ = span("keyword", $1); }
		| CONSTANT       { $$ = span("constant", $1); }
		| SPECIAL_FORM   { $$ = span("special-operator", $1); }
		| FUNCTION       { $$ = span("function", $1); }
		| MACRO          { $$ = span("macro", $1); }
		| VARIABLE       { $$ = span("variable", $1); }
		| OTHER          { $$ = span("", $1); }
		;

%%


char* span(char *c, char *s) {
	char* str = (char*)malloc(strlen(c) + strlen(s) + 1 + 22);
	sprintf(str, "<span class=\"%s\">%s</span>", c, s);
	free(s);
	return str;
}
char* details(char *summary, char *rest) {
	if (*rest == '\0') rest = concat2("", ""); // Зверски грозен фикс, но не е толкова голям проблем

	char* str = (char*)malloc(strlen(LBRACKET_SPAN) + strlen(summary) + strlen(rest) + strlen(RBRACKET_SPAN) + 1 + 39);
	sprintf(str, "<details><summary>%s%s</summary>\n%s%s</details>", LBRACKET_SPAN, summary, rest, RBRACKET_SPAN);

	free(summary); free(rest);
	return str;
}

char* concat2(char* first, char* second) {
	char* concat = (char*)malloc(strlen(first) + strlen(second) + 1);
	sprintf(concat, "%s%s", first, second);
	return concat;
}
char* concatperm2(char *first, char *second) {
	char* concat = concat2(first, second);
	free(first); free(second);
	return concat;
}

char* concatperm3(char *first, char *second, char *third) {
	char* concat = (char*)malloc(strlen(first) + strlen(second) + strlen(third) + 1);
	sprintf(concat, "%s%s%s", first, second, third);
	free(second);
	return concat;
}


int yyerror(char *s) {
	printf("Error: %s\n", s);
	return 0;
}

int main(int argc, char **argv) {
/* #ifdef YYDEBUG */
/*   yydebug = 1; */
/* #endif */
	yyparse();
}