aboutsummaryrefslogtreecommitdiff
path: root/src/parser.y
diff options
context:
space:
mode:
Diffstat (limited to 'src/parser.y')
-rw-r--r--src/parser.y243
1 files changed, 243 insertions, 0 deletions
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);
+}