aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRaghuram Subramani <raghus2247@gmail.com>2025-07-25 15:57:58 +0530
committerRaghuram Subramani <raghus2247@gmail.com>2025-07-25 15:57:58 +0530
commit1de65cb71f8b135c14b00804f6166622f402171d (patch)
tree55f912add7e2d6bb2f5f7c69215aa3d0d3518ea8
parent66994192d467c41ae82d15131e6814af3cc50bad (diff)
lexer: move away from a monolithic function to determine directive
-rw-r--r--include/lexer.h16
-rw-r--r--src/lexer.c189
2 files changed, 126 insertions, 79 deletions
diff --git a/include/lexer.h b/include/lexer.h
index d93877e..0831e90 100644
--- a/include/lexer.h
+++ b/include/lexer.h
@@ -3,6 +3,8 @@
#include <list.h>
+#define DIRECTIVE_IS(key) strncmp(buffer + n, key, strlen(key)) == 0
+
typedef enum {
_RAW,
INCLUDE,
@@ -33,4 +35,18 @@ directive_t *find_directive(char *content, key_match_t *match);
key_match_t *find_next_key(char *buffer, size_t skip);
char *find_contentfor_value(list_t *content_headers, char *key);
+void lexer_handle_include(directive_t *directive,
+ key_match_t *match,
+ char *buffer,
+ size_t n);
+void lexer_handle_contentfor(directive_t *directive,
+ key_match_t *match,
+ char *buffer,
+ char *content,
+ size_t n);
+void lexer_handle_content(directive_t *directive,
+ key_match_t *match,
+ char *buffer,
+ size_t n);
+
#endif
diff --git a/src/lexer.c b/src/lexer.c
index 0e1a80a..dcf4250 100644
--- a/src/lexer.c
+++ b/src/lexer.c
@@ -93,13 +93,112 @@ find_next_key(char *buffer, size_t skip)
return match;
}
+void
+lexer_handle_include(directive_t *directive,
+ key_match_t *match,
+ char *buffer,
+ size_t n)
+{
+ directive->type = INCLUDE;
+
+ char *operand = NULL;
+ for (size_t i = n + strlen("include"); i < match->length - n; i++)
+ if (isalnum(buffer[i])) {
+ sscanf(buffer + i, "%ms\"", &operand);
+ operand[strlen(operand) - 1] = '\0';
+ break;
+ }
+
+ directive->operands = operand;
+}
+
+void
+lexer_handle_contentfor(directive_t *directive,
+ key_match_t *match,
+ char *buffer,
+ char *content,
+ size_t n)
+{
+ directive->type = CONTENTFOR;
+ contentfor_operand_t *operands = malloc(sizeof(contentfor_operand_t));
+
+ for (size_t i = n + strlen("contentfor"); i < match->length; i++)
+ if (isalnum(buffer[i])) {
+ sscanf(buffer + i, "%ms\"", &operands->key);
+ operands->key[strlen(operands->key) - 1] = '\0';
+ break;
+ }
+
+ buffer = content + match->length + match->offset;
+
+ size_t content_length = 0;
+
+ key_match_t *new_match;
+ directive_t *new_directive;
+
+ while (true) {
+ new_match = find_next_key(buffer, 0);
+ if (new_match == NULL) {
+ printf("Cannot find endcontent\n");
+ free(new_directive);
+ free(new_match);
+ free(directive);
+ /* TODO: Handle early returns */
+ return;
+ }
+
+ new_directive = find_directive(buffer, new_match);
+ if (new_directive == NULL) {
+ printf("Cannot find directive: %.*s\n",
+ new_match->length,
+ buffer + new_match->offset);
+ free(new_directive);
+ free(new_match);
+ free(directive);
+ return;
+ }
+
+ if (new_directive->type == ENDCONTENT) {
+ break;
+ }
+ }
+
+ asprintf(&operands->content, "%.*s", new_match->offset, buffer);
+ operands->length
+ = match->offset + match->length + new_match->offset + new_match->length;
+
+ free(new_directive);
+ free(new_match);
+
+ directive->operands = operands;
+}
+
+void
+lexer_handle_content(directive_t *directive,
+ key_match_t *match,
+ char *buffer,
+ size_t n)
+{
+ directive->type = CONTENT;
+
+ char *operand = NULL;
+ for (size_t i = n + strlen("content"); i < match->length - n; i++)
+ if (isalnum(buffer[i])) {
+ sscanf(buffer + i, "%ms\"", &operand);
+ operand[strlen(operand) - 1] = '\0';
+ break;
+ }
+
+ directive->operands = operand;
+}
+
directive_t *
find_directive(char *content, key_match_t *match)
{
- directive_t *directive = (directive_t *) calloc(1, sizeof(directive_t));
+ directive_t *directive;
char *buffer = content + match->offset;
- unsigned int n = 0;
+ size_t n = 0;
for (size_t i = 0; i < match->length; i++)
switch (buffer[i]) {
@@ -117,88 +216,20 @@ find_directive(char *content, key_match_t *match)
return NULL;
found_start:
- if (strncmp(buffer + n, "include", strlen("include")) == 0) {
- directive->type = INCLUDE;
-
- char *operand = NULL;
- for (size_t i = n + strlen("include"); i < match->length - n; i++)
- if (isalnum(buffer[i])) {
- sscanf(buffer + i, "%ms\"", &operand);
- operand[strlen(operand) - 1] = '\0';
- break;
- }
+ directive = (directive_t *) calloc(1, sizeof(directive_t));
- directive->operands = operand;
- } else if (strncmp(buffer + n, "endcontent", strlen("endcontent")) == 0) {
+ if (DIRECTIVE_IS("include")) {
+ lexer_handle_include(directive, match, buffer, n);
+ } else if (DIRECTIVE_IS("endcontent")) {
directive->type = ENDCONTENT;
directive->operands = NULL;
- } else if (strncmp(buffer + n, "body", strlen("body")) == 0) {
+ } else if (DIRECTIVE_IS("body")) {
directive->type = BODY;
directive->operands = NULL;
- } else if (strncmp(buffer + n, "contentfor", strlen("contentfor")) == 0) {
- directive->type = CONTENTFOR;
- contentfor_operand_t *operands = malloc(sizeof(contentfor_operand_t));
-
- for (size_t i = n + strlen("contentfor"); i < match->length; i++)
- if (isalnum(buffer[i])) {
- sscanf(buffer + i, "%ms\"", &operands->key);
- operands->key[strlen(operands->key) - 1] = '\0';
- break;
- }
-
- buffer = content + match->length + match->offset;
-
- size_t content_length = 0;
-
- key_match_t *new_match;
- directive_t *new_directive;
-
- while (true) {
- new_match = find_next_key(buffer, 0);
- if (new_match == NULL) {
- printf("Cannot find endcontent\n");
- free(new_directive);
- free(new_match);
- free(directive);
- return NULL;
- }
-
- new_directive = find_directive(buffer, new_match);
- if (new_directive == NULL) {
- printf("Cannot find directive: %.*s\n",
- new_match->length,
- buffer + new_match->offset);
- free(new_directive);
- free(new_match);
- free(directive);
- return NULL;
- }
-
- if (new_directive->type == ENDCONTENT) {
- break;
- }
- }
-
- asprintf(&operands->content, "%.*s", new_match->offset, buffer);
- operands->length = match->offset + match->length + new_match->offset
- + new_match->length;
-
- free(new_directive);
- free(new_match);
-
- directive->operands = operands;
- } else if (strncmp(buffer + n, "content ", strlen("content")) == 0) {
- directive->type = CONTENT;
-
- char *operand = NULL;
- for (size_t i = n + strlen("content"); i < match->length - n; i++)
- if (isalnum(buffer[i])) {
- sscanf(buffer + i, "%ms\"", &operand);
- operand[strlen(operand) - 1] = '\0';
- break;
- }
-
- directive->operands = operand;
+ } else if (DIRECTIVE_IS("contentfor")) {
+ lexer_handle_contentfor(directive, match, buffer, content, n);
+ } else if (DIRECTIVE_IS("content")) {
+ lexer_handle_content(directive, match, buffer, n);
} else {
free(directive);
return NULL;