From 080d115e172fc72aaf2cb01dc2f68074266a86ad Mon Sep 17 00:00:00 2001 From: bronku Date: Tue, 18 Nov 2025 15:36:34 +0100 Subject: [PATCH] inital --- .gitignore | 1 + makefile | 24 +++++++++++++ src/ParserCtx.cpp | 22 ++++++++++++ src/ParserCtx.hpp | 23 +++++++++++++ src/lexer.l | 46 +++++++++++++++++++++++++ src/parser.y | 86 +++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 202 insertions(+) create mode 100644 .gitignore create mode 100644 makefile create mode 100644 src/ParserCtx.cpp create mode 100644 src/ParserCtx.hpp create mode 100644 src/lexer.l create mode 100644 src/parser.y diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..378eac2 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +build diff --git a/makefile b/makefile new file mode 100644 index 0000000..12c06fd --- /dev/null +++ b/makefile @@ -0,0 +1,24 @@ +CXX = g++ +ARGS = -std=c++17 +BISON = /opt/homebrew/opt/bison/bin/bison +FLEX = flex + +TARGET = build/py2rb + +$(TARGET): build/lexer.o build/parser.o build/ParserCtx.o + $(CXX) $^ -o $@ + +build/lexer.hpp build/lexer.cpp: src/lexer.l build/parser.hpp + $(FLEX) --header-file=build/lexer.hpp -o build/lexer.cpp src/lexer.l + +build/parser.hpp build/parser.cpp: src/parser.y + $(BISON) -d -v -o build/parser.cpp src/parser.y + +build/lexer.o: build/lexer.cpp + $(CXX) -c $(ARGS) $< -o $@ + +build/parser.o: build/parser.cpp + $(CXX) -c $(ARGS) $< -o $@ + +build/ParserCtx.o: src/ParserCtx.cpp + $(CXX) -c $(ARGS) $< -o $@ diff --git a/src/ParserCtx.cpp b/src/ParserCtx.cpp new file mode 100644 index 0000000..b7d7764 --- /dev/null +++ b/src/ParserCtx.cpp @@ -0,0 +1,22 @@ +#include "ParserCtx.hpp" +#include "../build/lexer.hpp" +#include "../build/parser.hpp" +namespace Elite +{ + + ParserCtx::ParserCtx() + { + yylex_init(&lexer); + // yyset_in() + loc = new yy::location(); + parser = new yy::Parser(lexer, *loc, *this); + } + + ParserCtx::~ParserCtx() + { + yylex_destroy(lexer); + delete loc; + delete parser; + } + +} // namespace Elite diff --git a/src/ParserCtx.hpp b/src/ParserCtx.hpp new file mode 100644 index 0000000..0c96cf5 --- /dev/null +++ b/src/ParserCtx.hpp @@ -0,0 +1,23 @@ +#pragma once + +namespace yy +{ + class Parser; + class location; +} + +namespace Elite +{ + + class ParserCtx + { + public: + ParserCtx(); + ~ParserCtx(); + + void *lexer; + yy::location *loc; + yy::Parser *parser; + }; + +} // namespace Elite diff --git a/src/lexer.l b/src/lexer.l new file mode 100644 index 0000000..59bfd76 --- /dev/null +++ b/src/lexer.l @@ -0,0 +1,46 @@ + +%option reentrant noyywrap nounput + +%{ +#include +#define YY_DECL yy::Parser::symbol_type yylex(yyscan_t yyscanner, yy::location& loc) + +#define YY_USER_ACTION loc.columns(yyleng); +#define yyterminate() return yy::Parser::make_END(loc) + +#include "../build/parser.hpp" + +%} + + /* your definitions here */ + + /* your definitions end */ + +%% + +%{ + loc.step(); +%} + + /* your rules here */ + + /* use this structure to pass the Token : + * return yy::parser::make_TokenName(loc) + * if the token has a type you can pass it's value + * as the first argument. as an example we put + * the rule to return token function. + */ + +function {return yy::Parser::make_FUNCTION(loc);} + +[ \n\r\t\v] {} + +. {std::cerr << loc << ": " << "token error" << std::endl; exit(1);} + + + /* if you didn't define #define yyterminate() at beginnign, you will need + this rule to match the end of file */ + /* <> {return yy::Parser::make_END(loc);} */ + /* your rules end */ + +%% diff --git a/src/parser.y b/src/parser.y new file mode 100644 index 0000000..898b71e --- /dev/null +++ b/src/parser.y @@ -0,0 +1,86 @@ + +/* Require bison minimal version */ +%require "3.0.4" + +/* use newer C++ skeleton file */ +%skeleton "lalr1.cc" + +/* write out a header file containing the token defines */ +%defines + +/* namespace to enclose parser in */ +%name-prefix="yy" + +/* set the parser's class identifier */ +%define api.parser.class {Parser} + +/* it will generate a location class which can be used in your lexer */ +%locations + +/* use the constructor for each token, and make_TOKENNAME functions will be generated */ +%define api.token.constructor + +/* use the variant type for $1~$n and $$ those variables */ +%define api.value.type variant + + +%define parse.trace +%define parse.error verbose + + +%code requires +{ + /* you may need these header files + * add more header file if you need more + */ +#include +#include +#include +#include "../src/ParserCtx.hpp" + + /* define the sturctures using as types for non-terminals */ + + /* end the structures for non-terminal types */ +} + + +%code +{ +yy::Parser::symbol_type yylex(void* yyscanner, yy::location& loc); +} + + +%token END 0; + + /* specify tokens, type of non-terminals and terminals here */ +%token FUNCTION + /* end of token specifications */ + + +/* The driver is passed by reference to the parser and to the scanner. This + * provides a simple but effective pure interface, not relying on global + * variables. */ +%lex-param {void *scanner} {yy::location& loc} +%parse-param {void *scanner} {yy::location& loc} { class Elite::ParserCtx& ctx } + + + +%% + +%start program; + +program: FUNCTION; + + +%% + +int main(int argc, char *argv[]) +{ + Elite::ParserCtx ctx; + return ctx.parser->parse(); +} + +void yy::Parser::error(const yy::location& l, const std::string& m) +{ + std::cerr << l << ": " << m << std::endl; +} \ No newline at end of file