From c035571d85e3d756804519d82de8b354f3910b29 Mon Sep 17 00:00:00 2001
From: Kimplul <kimi.h.kuparinen@gmail.com>
Date: Thu, 8 Feb 2024 21:19:38 +0200
Subject: project work phase 1

---
 src/parser.y | 243 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 243 insertions(+)
 create mode 100644 src/parser.y

(limited to 'src/parser.y')

diff --git a/src/parser.y b/src/parser.y
new file mode 100644
index 0000000..8a4ddb5
--- /dev/null
+++ b/src/parser.y
@@ -0,0 +1,243 @@
+%{
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <posthaste/parser.h>
+#include <posthaste/date.h>
+
+#define FOREACH_TOKEN(M) \
+	M(LPAREN)	\
+	M(RPAREN)	\
+	M(LSQUARE)	\
+	M(RSQUARE)	\
+	M(LCURLY)	\
+	M(RCURLY)	\
+	M(APOSTROPHE)	\
+	M(AMPERSAND)	\
+	M(COMMA)	\
+	M(DOT)		\
+	M(EQ)		\
+	M(LT)		\
+	M(PLUS)		\
+	M(MINUS)	\
+	M(MULT)		\
+	M(DIV)		\
+	M(VAR)		\
+	M(IS)		\
+	M(UNLESS)	\
+	M(OTHERWISE)	\
+	M(UNTIL)	\
+	M(DO)		\
+	M(DONE)		\
+	M(PROCEDURE)	\
+	M(FUNCTION)	\
+	M(RETURN)	\
+	M(PRINT)	\
+	M(END)		\
+	M(STRING)	\
+	M(DATE_LITERAL)	\
+	M(INT_LITERAL)	\
+	M(IDENT)	\
+	M(FUNC_IDENT)	\
+	M(PROC_IDENT)
+
+%}
+
+%locations
+
+%define parse.trace
+%define parse.error verbose
+%define api.pure full
+%define lr.type ielr
+
+%lex-param {void *scanner} {struct parser *parser}
+%parse-param {void *scanner} {struct parser* parser}
+
+%union {
+	struct ast_node *node;
+	ph_date_t num;
+	int64_t snum;
+	char *str;
+};
+
+%token <str> STRING
+%token <num> DATE_LITERAL
+%token <snum> INT_LITERAL
+%token <str> IDENT;
+%token <str> FUNC_IDENT;
+%token <str> PROC_IDENT;
+
+%token LPAREN "("
+%token RPAREN ")"
+%token LSQUARE "["
+%token RSQUARE "]"
+%token LCURLY "{"
+%token RCURLY "}"
+
+%token APOSTROPHE "'"
+%token AMPERSAND "&"
+%token COMMA ","
+%token DOT "."
+%token EQ "="
+%token LT "<"
+%token PLUS "+"
+%token MINUS "-"
+%token MULT "*"
+%token DIV "/"
+
+%token VAR "var"
+%token IS "is"
+%token UNLESS "unless"
+%token OTHERWISE "otherwise"
+%token UNTIL "until"
+%token DO "do"
+%token DONE "done"
+%token PROCEDURE "procedure"
+%token FUNCTION "function"
+%token RETURN "return"
+%token PRINT "print"
+%token END "end"
+
+%{
+
+/** Modifies the signature of yylex to fit our parser better. */
+#define YY_DECL int yylex(YYSTYPE *yylval, YYLTYPE *yylloc, \
+	                  void *yyscanner, struct parser *parser)
+
+/**
+ * Declare yylex.
+ *
+ * @param yylval Bison current value.
+ * @param yylloc Bison location info.
+ * @param yyscanner Flex scanner.
+ * @param parser Current parser state.
+ * @return \c 0 when succesful, \c 1 otherwise.
+ * More info on yylex() can be found in the flex manual.
+ */
+YY_DECL;
+
+/**
+ * Convert bison location info to our own source location info.
+ *
+ * @param yylloc Bison location info.
+ * @return Internal location info.
+ */
+static struct src_loc src_loc(YYLTYPE yylloc);
+
+/**
+ * Print parsing error.
+ * Automatically called by bison.
+ *
+ * @param yylloc Location of error.
+ * @param lexer Lexer.
+ * @param parser Parser state.
+ * @param msg Message to print.
+ */
+static void yyerror(YYLTYPE *yylloc, void *lexer,
+		struct parser *parser, const char *msg);
+
+%}
+
+%start input;
+%%
+
+input: /* empty */
+
+%%
+
+#include "gen_lexer.inc"
+
+static void dump_yychar(struct parser *p, int yychar, YYSTYPE yylval, YYLTYPE yylloc)
+{
+	struct src_loc loc = src_loc(yylloc);
+	printf("%s:%d:%d: ", p->fname, loc.first_line, loc.first_col);
+
+#define PRINT_NAME(token) case token: printf(#token " "); break;
+	switch (yychar) {
+	FOREACH_TOKEN(PRINT_NAME);
+	default: printf("Unknown yychar\n"); return;
+	}
+
+	char date_str[11] = {0};
+	switch (yychar) {
+	case INT_LITERAL:	printf("(%lld)", (long long int)yylval.snum); break;
+	case IDENT:		printf("(%s)", yylval.str); break;
+	case FUNC_IDENT:	printf("(%s)", yylval.str); break;
+	case PROC_IDENT:	printf("(%s)", yylval.str); break;
+	case DATE_LITERAL:
+		date_to_string(date_str, yylval.num);
+		printf("(%s)", date_str);
+		break;
+	}
+
+	printf("\n");
+}
+
+static void dump_lex(struct parser *p)
+{
+	int yychar;
+	YYSTYPE yylval;
+	YYLTYPE yylloc = {1, 1, 1, 1};
+
+	/* run lexer until we reach the end of the file */
+	while ((yychar = yylex(&yylval, &yylloc, p->lexer, p)) != YYEOF) {
+		dump_yychar(p, yychar, yylval, yylloc);
+	}
+}
+
+static struct src_loc src_loc(YYLTYPE yylloc)
+{
+	struct src_loc loc;
+	loc.first_line = yylloc.first_line;
+	loc.last_line = yylloc.last_line;
+	loc.first_col = yylloc.first_column;
+	loc.last_col = yylloc.last_column;
+	return loc;
+}
+
+static void yyerror(YYLTYPE *yylloc, void *lexer,
+		struct parser *parser, const char *msg)
+{
+	(void)lexer;
+
+	struct src_issue issue;
+	issue.loc = src_loc(*yylloc);
+	issue.fname = parser->fname;
+	issue.buf = parser->buf;
+
+	src_issue(issue, msg);
+}
+
+struct parser *create_parser()
+{
+	return calloc(1, sizeof(struct parser));
+}
+
+void destroy_parser(struct parser *p)
+{
+	yylex_destroy(p->lexer);
+	free(p);
+}
+
+void parse(struct parser *p, const char *fname, const char *buf)
+{
+	p->fname = fname;
+	p->buf = buf;
+
+	p->comment_nesting = 0;
+
+	p->failed = false;
+
+	yylex_init(&p->lexer);
+
+	yy_scan_string(buf, p->lexer);
+
+	// debugging, remember to reset yy_scan_string once the actual parser
+	// runs
+	dump_lex(p);
+
+	// yyparse(p->lexer, p);
+}
-- 
cgit v1.2.3