add: simple
This commit is contained in:
parent
7f2a90738b
commit
a34a05d0d0
|
|
@ -1,4 +1,4 @@
|
|||
UseTab: true
|
||||
UseTab: Always
|
||||
IndentWidth: 4
|
||||
---
|
||||
Language: Cpp
|
||||
|
|
|
|||
|
|
@ -0,0 +1,58 @@
|
|||
%{
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
|
||||
#include "DragonLispScanner.hh"
|
||||
|
||||
#undef YY_DECL
|
||||
#define YY_DECL int DragonLisp::DLScanner::yylex(DragonLisp::DLParser::semantic_type* const lval, DragonLisp::DLParser::location_type* location, DragonLisp::DLDriver& drv)
|
||||
|
||||
using token = DragonLisp::DLParser::token;
|
||||
|
||||
#define yyterminate() return token::TOKEN_END;
|
||||
|
||||
#define YY_USER_ACTION loc->columns(yyleng);
|
||||
|
||||
%}
|
||||
|
||||
%option yyclass="DragonLisp::DLScanner"
|
||||
%option verbose backup warn noyywrap c++ nounistd debug noline
|
||||
|
||||
id [a-zA-Z_][a-zA-Z_0-9]*
|
||||
int [0-9]+
|
||||
blank [ \t\v\r]
|
||||
|
||||
%%
|
||||
|
||||
%{
|
||||
yylval = lval;
|
||||
%}
|
||||
|
||||
{blank}+ { loc->step(); }
|
||||
\n+ { loc->lines(yyleng); loc->step(); }
|
||||
|
||||
"(" { return token::TOKEN_LPAREN; }
|
||||
")" { return token::TOKEN_RPAREN; }
|
||||
"+" { return token::TOKEN_PLUS; }
|
||||
"-" { return token::TOKEN_MINUS; }
|
||||
"*" { return token::TOKEN_STAR; }
|
||||
"/" { return token::TOKEN_SLASH; }
|
||||
|
||||
{int} {
|
||||
errno = 0;
|
||||
int64_t n = strtoll(yytext, nullptr, 10);
|
||||
if (errno)
|
||||
throw DragonLisp::DLParser::syntax_error(*loc, "Invalid integer provided: " + std::string(yytext));
|
||||
yylval->emplace<int64_t>(n);
|
||||
return token::TOKEN_NUMBER;
|
||||
};
|
||||
|
||||
{id} { /* return DragonLisp::DLParser::make_IDENTIFIER(yytext, *loc); */ }
|
||||
|
||||
. { throw DragonLisp::DLParser::syntax_error(*loc, "Invalid character: " + std::string(yytext)); }
|
||||
|
||||
<<EOF>> { yyterminate(); }
|
||||
|
||||
%%
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
%require "3.8.2"
|
||||
%debug
|
||||
|
||||
%defines
|
||||
%define api.namespace { DragonLisp }
|
||||
%define api.parser.class { DLParser }
|
||||
|
||||
%code requires {
|
||||
|
||||
namespace DragonLisp {
|
||||
class DLDriver;
|
||||
class DLScanner;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
%parse-param { DLScanner& scanner }
|
||||
|
||||
%param { DLDriver& drv }
|
||||
|
||||
%code {
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
|
||||
#include "DragonLispDriver.hh"
|
||||
|
||||
#undef yylex
|
||||
#define yylex scanner.yylex
|
||||
|
||||
}
|
||||
|
||||
%locations
|
||||
%define api.token.prefix {TOKEN_}
|
||||
%define api.value.type variant
|
||||
%define parse.assert
|
||||
|
||||
%token
|
||||
LPAREN "("
|
||||
RPAREN ")"
|
||||
PLUS "+"
|
||||
MINUS "-"
|
||||
STAR "*"
|
||||
SLASH "/"
|
||||
;
|
||||
|
||||
%token END 0 "EOF"
|
||||
%token <int64_t> NUMBER "number"
|
||||
|
||||
%define parse.error verbose
|
||||
|
||||
%%
|
||||
|
||||
S
|
||||
: R END
|
||||
|
||||
R
|
||||
:
|
||||
| R S-Expr
|
||||
|
||||
S-Expr
|
||||
: LPAREN operator NUMBER NUMBER RPAREN { std::printf("This is S-Expr!\n"); }
|
||||
|
||||
operator
|
||||
: PLUS { std::printf("I am plus +\n"); }
|
||||
| MINUS { std::printf("I am minus -\n"); }
|
||||
| STAR { std::printf("I am star *\n"); }
|
||||
| SLASH { std::printf("I am slash /\n"); }
|
||||
|
||||
%%
|
||||
|
||||
void DragonLisp::DLParser::error(const location_type& l, const std::string& msg) {
|
||||
std::cerr << "Error: " << msg << " at " << l << "\n";
|
||||
}
|
||||
|
||||
DragonLisp::DLParser::symbol_type make_NUMBER(const std::string& s, const DragonLisp::DLParser::location_type& loc) {
|
||||
try {
|
||||
int n = std::stoi(s);
|
||||
return DragonLisp::DLParser::make_NUMBER(n, loc);
|
||||
} catch (...) {
|
||||
throw DragonLisp::DLParser::syntax_error(loc, "Invalid integer provided: " + s);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
#include "DragonLispDriver.hh"
|
||||
|
||||
namespace DragonLisp {
|
||||
|
||||
DLDriver::~DLDriver() {
|
||||
delete (this->scanner);
|
||||
this->scanner = nullptr;
|
||||
delete (this->parser);
|
||||
this->parser = nullptr;
|
||||
}
|
||||
|
||||
int DLDriver::parse(const std::string& f) {
|
||||
std::ifstream in(f);
|
||||
if (!in.good())
|
||||
return 1;
|
||||
return this->parse(in, f);
|
||||
}
|
||||
|
||||
int DLDriver::parse(std::istream& in, const std::string& s) {
|
||||
// Scanner
|
||||
delete this->scanner;
|
||||
this->scanner = new DLScanner(&in);
|
||||
|
||||
// Parser
|
||||
delete this->parser;
|
||||
this->parser = new DLParser(*this->scanner, *this);
|
||||
|
||||
this->parser->set_debug_level(1);
|
||||
return this->parser->parse();
|
||||
}
|
||||
|
||||
} // end namespace DragonLisp
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
#ifndef __DRAGON_LISP_DRIVER_HH__
|
||||
#define __DRAGON_LISP_DRIVER_HH__
|
||||
|
||||
#include <string>
|
||||
#include <istream>
|
||||
|
||||
#include "DragonLispScanner.hh"
|
||||
#include "DragonLisp.tab.hh"
|
||||
|
||||
namespace DragonLisp {
|
||||
|
||||
class DLDriver {
|
||||
public:
|
||||
DLDriver() = default;
|
||||
virtual ~DLDriver();
|
||||
|
||||
int parse(const std::string& f);
|
||||
int parse(std::istream& in, const std::string& s = "stream input");
|
||||
|
||||
void error(const DLParser::location_type& l, const std::string& m);
|
||||
void error(const std::string& m);
|
||||
|
||||
private:
|
||||
DLParser* parser = nullptr;
|
||||
DLScanner* scanner = nullptr;
|
||||
DragonLisp::location location;
|
||||
};
|
||||
|
||||
} // end namespace DragonLisp
|
||||
|
||||
#endif // __DRAGON_LISP_DRIVER_HH__
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
#ifndef __DRAGON_LISP_SCANNER_HH__
|
||||
#define __DRAGON_LISP_SCANNER_HH__
|
||||
|
||||
#ifndef yyFlexLexerOnce
|
||||
#include <FlexLexer.h>
|
||||
#endif
|
||||
|
||||
#include <istream>
|
||||
|
||||
#include "DragonLisp.tab.hh"
|
||||
#include "location.hh"
|
||||
|
||||
namespace DragonLisp {
|
||||
|
||||
class DLScanner : public yyFlexLexer {
|
||||
private:
|
||||
DragonLisp::DLParser::semantic_type* yylval = nullptr;
|
||||
DragonLisp::DLParser::location_type* loc = nullptr;
|
||||
|
||||
public:
|
||||
DLScanner(std::istream* in) : yyFlexLexer(in) {
|
||||
this->loc = new DragonLisp::DLParser::location_type();
|
||||
}
|
||||
|
||||
using FlexLexer::yylex;
|
||||
virtual int yylex(
|
||||
DragonLisp::DLParser::semantic_type* const lval,
|
||||
DragonLisp::DLParser::location_type* location,
|
||||
DragonLisp::DLDriver& drv
|
||||
);
|
||||
};
|
||||
|
||||
} // end namespace DragonLisp
|
||||
|
||||
#endif // __DRAGON_LISP_SCANNER_HH__
|
||||
69
Makefile
69
Makefile
|
|
@ -1,6 +1,67 @@
|
|||
all:
|
||||
echo "Working"
|
||||
# I am a Makefile.
|
||||
.PHONY: clean all
|
||||
|
||||
# Global
|
||||
PROJ ?= DragonLisp
|
||||
|
||||
# Lexical Analysis
|
||||
LEX = flex
|
||||
LEXFLAGS ?= -T --hex
|
||||
|
||||
# Syntax Analysis
|
||||
YACC = bison
|
||||
YACCFLAGS ?= -Wall --color -v -t -d
|
||||
LANG = c++
|
||||
|
||||
# Compile C/C++ Code
|
||||
CC = gcc
|
||||
CXX = g++
|
||||
OUTPUT ?= $(PROJ).exe
|
||||
|
||||
COMMONFLAGS ?= -g -Wall
|
||||
CFLAGS ?= $(COMMONFLAGS)
|
||||
CXXFLAGS ?= $(COMMONFLAGS)
|
||||
|
||||
MISCOBJ = main DragonLispDriver
|
||||
OBJS = $(addsuffix .o, $(MISCOBJ))
|
||||
|
||||
all: compile
|
||||
|
||||
lexer:
|
||||
$(LEX) $(LEXFLAGS) $(PROJ).l
|
||||
|
||||
lexer_compile: lexer parser
|
||||
$(CXX) $(CXXFLAGS) -c -o lexer.o lex.yy.cc
|
||||
|
||||
parser:
|
||||
$(YACC) $(YACCFLAGS) --language=$(LANG) $(PROJ).y
|
||||
|
||||
parser_compile: parser
|
||||
$(CXX) $(CXXFLAGS) -c -o parser.o $(PROJ).tab.cc
|
||||
|
||||
misc_compile: lexer parser
|
||||
$(MAKE) $(OBJS)
|
||||
|
||||
compile: lexer_compile parser_compile misc_compile
|
||||
$(CXX) $(CXXFLAGS) -o $(OUTPUT) $(OBJS) parser.o lexer.o $(LIBS)
|
||||
|
||||
compile_debug: lexer parser
|
||||
$(CXX) $(CXXFLAGS) -o $(OUTPUT) \
|
||||
main.cpp \
|
||||
DragonLispDriver.cpp \
|
||||
DragonLisp.tab.cc \
|
||||
lex.yy.cc
|
||||
|
||||
clean:
|
||||
echo "Cleaning"
|
||||
|
||||
rm -fv \
|
||||
lex.backup \
|
||||
lex.yy.cc \
|
||||
$(PROJ).output \
|
||||
$(PROJ).tab.cc \
|
||||
$(PROJ).tab.hh \
|
||||
stack.hh \
|
||||
location.hh \
|
||||
parser.o \
|
||||
lexer.o \
|
||||
$(OBJS) \
|
||||
$(OUTPUT)
|
||||
|
|
|
|||
Loading…
Reference in New Issue