add: simple
This commit is contained in:
parent
7f2a90738b
commit
a34a05d0d0
|
|
@ -1,4 +1,4 @@
|
||||||
UseTab: true
|
UseTab: Always
|
||||||
IndentWidth: 4
|
IndentWidth: 4
|
||||||
---
|
---
|
||||||
Language: Cpp
|
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:
|
# I am a Makefile.
|
||||||
echo "Working"
|
.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:
|
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