Skip to content

Commit 3cb3e53

Browse files
authored
Merge pull request #10 from sillydan1/symbol-table-extensions
Symbol table extensions
2 parents 8007052 + a64f589 commit 3cb3e53

File tree

18 files changed

+446
-387
lines changed

18 files changed

+446
-387
lines changed

CMakeLists.txt

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2121
# SOFTWARE.
2222
cmake_minimum_required(VERSION 3.21)
23-
project(expr VERSION 1.5.0)
23+
project(expr VERSION 1.6.0)
2424
include(cmake/CPM.cmake)
2525
configure_file(src/config.h.in config.h)
2626
set(CMAKE_CXX_STANDARD 20)
@@ -30,8 +30,6 @@ set(CXX_STANDARD_REQUIRED ON)
3030
option(ENABLE_Z3 "Enables the download and compilation of the expr::z3_driver driver. OFF by default" OFF)
3131

3232
# DEPENDENCIES
33-
find_package(FLEX REQUIRED)
34-
find_package(BISON REQUIRED)
3533
CPMAddPackage("gh:yalibs/[email protected]")
3634
CPMAddPackage("gh:yalibs/[email protected]")
3735
CPMAddPackage("gh:yalibs/[email protected]")
@@ -41,14 +39,27 @@ if(ENABLE_Z3)
4139
CPMAddPackage("gh:Z3Prover/z3#z3-4.8.17")
4240
endif()
4341

44-
BISON_TARGET(expr_parser src/parser/parser.y ${CMAKE_CURRENT_BINARY_DIR}/parser.cpp)
45-
FLEX_TARGET(expr_scanner src/parser/scanner.l ${CMAKE_CURRENT_BINARY_DIR}/scanner.cpp)
46-
ADD_FLEX_BISON_DEPENDENCY(expr_scanner expr_parser)
47-
4842
set(${PROJECT_NAME}_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR} CACHE STRING "expr_BUILD_DIR" FORCE)
49-
include_directories(${overload_SOURCE_DIR}/include)
43+
find_package(FLEX REQUIRED)
44+
find_package(BISON REQUIRED)
45+
46+
add_custom_command(OUTPUT
47+
${CMAKE_CURRENT_BINARY_DIR}/lex.l
48+
COMMAND m4
49+
ARGS -I ${PROJECT_SOURCE_DIR}/src/parser/lex -P ${PROJECT_SOURCE_DIR}/src/parser/lex/scanner.l > ${CMAKE_CURRENT_BINARY_DIR}/lex.l
50+
VERBATIM)
51+
add_custom_command(OUTPUT
52+
${CMAKE_CURRENT_BINARY_DIR}/yacc.y
53+
COMMAND m4
54+
ARGS -I ${PROJECT_SOURCE_DIR}/src/parser/yacc -P ${PROJECT_SOURCE_DIR}/src/parser/yacc/parser.y > ${CMAKE_CURRENT_BINARY_DIR}/yacc.y
55+
VERBATIM)
56+
57+
BISON_TARGET(expr_parser ${CMAKE_CURRENT_BINARY_DIR}/yacc.y ${CMAKE_CURRENT_BINARY_DIR}/parser.cpp)
58+
FLEX_TARGET(expr_lexer ${CMAKE_CURRENT_BINARY_DIR}/lex.l ${CMAKE_CURRENT_BINARY_DIR}/scanner.cpp)
59+
ADD_FLEX_BISON_DEPENDENCY(expr_lexer expr_parser)
5060
include_directories(
5161
${CMAKE_CURRENT_BINARY_DIR}
62+
${CMAKE_CURRENT_BINARY_DIR}/src
5263
${yaoverload_SOURCE_DIR}/include
5364
${yatree_SOURCE_DIR}/include
5465
${yatimer_SOURCE_DIR}/include
@@ -59,7 +70,7 @@ include_directories(
5970
src)
6071
add_library(${PROJECT_NAME} SHARED
6172
${BISON_expr_parser_OUTPUTS}
62-
${FLEX_expr_scanner_OUTPUTS}
73+
${FLEX_expr_lexer_OUTPUTS}
6374
src/drivers/interpreter.cpp
6475
src/drivers/compiler.cpp
6576

@@ -71,6 +82,7 @@ add_library(${PROJECT_NAME} SHARED
7182
src/operations/modulo.cpp
7283
src/operations/pow.cpp
7384
src/operations/boolean.cpp)
85+
7486
if(ENABLE_Z3)
7587
target_sources(${PROJECT_NAME} PUBLIC src/drivers/z3_driver.cpp)
7688
target_link_libraries(${PROJECT_NAME} libz3)

include/symbol_table.h

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,13 @@ namespace expr {
6969

7070
using underlying_symbol_table_t = std::map<std::string, symbol_value_t>;
7171
struct symbol_table_t : public underlying_symbol_table_t {
72-
symbol_table_t &operator+=(const symbol_table_t &);
72+
auto operator+=(const symbol_table_t &) -> symbol_table_t&;
73+
auto operator*=(const symbol_table_t &) -> symbol_table_t&;
74+
auto put(const symbol_table_t &) -> symbol_table_t&;
75+
auto overwrite_elements(const symbol_table_t &) -> symbol_table_t&;
7376
auto is_overlapping(const symbol_table_t& other) -> bool;
7477
auto is_overlapping_and_not_idempotent(const symbol_table_t& other) -> bool;
78+
auto is_completely_overlapping(const symbol_table_t& other) -> bool;
7579
};
7680

7781
symbol_table_t operator+(const symbol_table_t &a, const symbol_table_t &b);
@@ -132,4 +136,17 @@ namespace std {
132136
};
133137
}
134138

139+
#ifndef BINOP_CTOR
140+
#define BINOP_CTOR(op,arg1,arg2) expr::syntax_tree_t{expr::operator_t{expr::operator_type_t::op}}.concat(arg1).concat(arg2)
141+
#endif
142+
#ifndef IDENT_CTOR
143+
#define IDENT_CTOR(arg1) drv->get_symbol(arg1);
144+
#endif
145+
#ifndef MONOOP_CTOR
146+
#define MONOOP_CTOR(op,arg1) expr::syntax_tree_t{expr::operator_t{expr::operator_type_t::op}}.concat(arg1)
147+
#endif
148+
#ifndef LIT_CTOR
149+
#define LIT_CTOR(arg1) expr::syntax_tree_t{arg1}
150+
#endif
151+
135152
#endif
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
m4_changequote()
2+
3+
void expr::driver::scan_begin() {
4+
yy_flex_debug = trace_scanning;
5+
if(file.empty() || file == "-")
6+
yyin = stdin;
7+
else
8+
yy_scan_string(file.c_str());
9+
}
10+
11+
void expr::driver::scan_end() {
12+
}

src/parser/lex/footer.l

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
m4_changequote()
2+
3+
yy::parser::symbol_type make_NUMBER(const std::string &s, const yy::parser::location_type& loc) {
4+
errno = 0;
5+
long n = strtol (s.c_str(), NULL, 10);
6+
if (! (INT_MIN <= n && n <= INT_MAX && errno != ERANGE))
7+
throw yy::parser::syntax_error (loc, "integer is out of range: " + s);
8+
return yy::parser::make_NUMBER ((int) n, loc);
9+
}
10+
11+
yy::parser::symbol_type make_FLOAT(const std::string &s, const yy::parser::location_type& loc) {
12+
try {
13+
double n = std::stod(s.c_str());
14+
return yy::parser::make_FLOAT((double)n, loc);
15+
} catch(std::out_of_range& e) {
16+
throw yy::parser::syntax_error (loc, "double is out of range: " + s);
17+
}
18+
}
19+
20+
yy::parser::symbol_type make_STRING(const std::string &s, const yy::parser::location_type& loc) {
21+
return yy::parser::make_STRING(s.substr(1, s.size()-2), loc);
22+
}
23+
24+
yy::parser::symbol_type make_BOOL(std::string s, const yy::parser::location_type& loc) {
25+
std::transform(s.begin(), s.end(), s.begin(), [](unsigned char c){ return std::tolower(c); });
26+
bool b;
27+
std::istringstream(s) >> std::boolalpha >> b;
28+
return yy::parser::make_BOOL(b, loc);
29+
}

src/parser/lex/includes.l

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
%{
2+
#include <cerrno>
3+
#include <climits>
4+
#include <cstdlib>
5+
#include <cstring> // strerror
6+
#include <string>
7+
#include <sstream>
8+
#include "drivers/driver.h"
9+
#include "parser.hpp"
10+
%}

src/parser/lex/lexer.l

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
m4_changequote()
2+
3+
{blank}+ loc.step();
4+
\n+ { loc.lines(yyleng); loc.step(); }
5+
6+
"-" return yy::parser::make_MINUS (loc);
7+
"+" return yy::parser::make_PLUS (loc);
8+
"*" return yy::parser::make_STAR (loc);
9+
"/" return yy::parser::make_SLASH (loc);
10+
"%" return yy::parser::make_PERCENT(loc);
11+
"^" return yy::parser::make_HAT (loc);
12+
"&&" return yy::parser::make_AND (loc);
13+
"||" return yy::parser::make_OR (loc);
14+
"^^" return yy::parser::make_XOR (loc);
15+
"=>" return yy::parser::make_IMPLIES(loc);
16+
">" return yy::parser::make_GT (loc);
17+
">=" return yy::parser::make_GE (loc);
18+
"==" return yy::parser::make_EE (loc);
19+
"!=" return yy::parser::make_NE (loc);
20+
"<=" return yy::parser::make_LE (loc);
21+
"<" return yy::parser::make_LT (loc);
22+
"!" return yy::parser::make_NOT (loc);
23+
"(" return yy::parser::make_LPAREN (loc);
24+
")" return yy::parser::make_RPAREN (loc);
25+
":=" return yy::parser::make_ASSIGN (loc);
26+
";" return yy::parser::make_TERM (loc);
27+
28+
{accmod} return yy::parser::make_ACCMOD(loc);
29+
{type} return yy::parser::make_TYPE(loc);
30+
31+
{int} return make_NUMBER(yytext, loc);
32+
{flt} return make_FLOAT(yytext, loc);
33+
{str} return make_STRING(yytext, loc);
34+
{bool} return make_BOOL(yytext, loc);
35+
{id} return yy::parser::make_IDENTIFIER (yytext, loc);
36+
. { throw yy::parser::syntax_error(loc, "invalid character: " + std::string(yytext)); }
37+
<<EOF>> return yy::parser::make_YYEOF (loc);

src/parser/lex/scanner.l

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
m4_changequote()
2+
/*
3+
m4_include(../mit.license)
4+
*/
5+
6+
m4_include(includes.l)
7+
m4_include(skeleton.l)
8+
m4_include(tokens.l)
9+
10+
%{
11+
// Code run each time a pattern is matched.
12+
#define YY_USER_ACTION loc.columns(yyleng);
13+
%}
14+
15+
%%
16+
%{
17+
// A handy shortcut to the location held by the driver.
18+
yy::location& loc = drv->location;
19+
// Code run each time yylex is called.
20+
loc.step();
21+
%}
22+
23+
m4_include(lexer.l)
24+
25+
%%
26+
27+
m4_include(footer.l)
28+
m4_include(expr_driver_footer.l)

src/parser/lex/skeleton.l

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
m4_changequote()
2+
3+
%{
4+
#if defined __clang__
5+
# define CLANG_VERSION (__clang_major__ * 100 + __clang_minor__)
6+
#endif
7+
8+
// Clang and ICC like to pretend they are GCC.
9+
#if defined __GNUC__ && !defined __clang__ && !defined __ICC
10+
# define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
11+
#endif
12+
13+
// Pacify warnings in yy_init_buffer (observed with Flex 2.6.4)
14+
// and GCC 6.4.0, 7.3.0 with -O3.
15+
#if defined GCC_VERSION && 600 <= GCC_VERSION
16+
# pragma GCC diagnostic ignored "-Wnull-dereference"
17+
#endif
18+
19+
// This example uses Flex's C back end, yet compiles it as C++.
20+
// So expect warnings about C style casts and NULL.
21+
#if defined CLANG_VERSION && 500 <= CLANG_VERSION
22+
# pragma clang diagnostic ignored "-Wold-style-cast"
23+
# pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant"
24+
#elif defined GCC_VERSION && 407 <= GCC_VERSION
25+
# pragma GCC diagnostic ignored "-Wold-style-cast"
26+
# pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"
27+
#endif
28+
29+
#define FLEX_VERSION (YY_FLEX_MAJOR_VERSION * 100 + YY_FLEX_MINOR_VERSION)
30+
31+
// Old versions of Flex (2.5.35) generate an incomplete documentation comment.
32+
//
33+
// In file included from src/scan-code-c.c:3:
34+
// src/scan-code.c:2198:21: error: empty paragraph passed to '@param' command
35+
// [-Werror,-Wdocumentation]
36+
// * @param line_number
37+
// ~~~~~~~~~~~~~~~~~^
38+
// 1 error generated.
39+
#if FLEX_VERSION < 206 && defined CLANG_VERSION
40+
# pragma clang diagnostic ignored "-Wdocumentation"
41+
#endif
42+
43+
// Old versions of Flex (2.5.35) use 'register'. Warnings introduced in
44+
// GCC 7 and Clang 6.
45+
#if FLEX_VERSION < 206
46+
# if defined CLANG_VERSION && 600 <= CLANG_VERSION
47+
# pragma clang diagnostic ignored "-Wdeprecated-register"
48+
# elif defined GCC_VERSION && 700 <= GCC_VERSION
49+
# pragma GCC diagnostic ignored "-Wregister"
50+
# endif
51+
#endif
52+
53+
#if FLEX_VERSION < 206
54+
# if defined CLANG_VERSION
55+
# pragma clang diagnostic ignored "-Wconversion"
56+
# pragma clang diagnostic ignored "-Wdocumentation"
57+
# pragma clang diagnostic ignored "-Wshorten-64-to-32"
58+
# pragma clang diagnostic ignored "-Wsign-conversion"
59+
# elif defined GCC_VERSION
60+
# pragma GCC diagnostic ignored "-Wconversion"
61+
# pragma GCC diagnostic ignored "-Wsign-conversion"
62+
# endif
63+
#endif
64+
65+
// Flex 2.6.4, GCC 9
66+
// warning: useless cast to type 'int' [-Wuseless-cast]
67+
// 1361 | YY_CURRENT_BUFFER_LVALUE->yy_buf_size = (int) (new_size - 2);
68+
// | ^
69+
#if defined GCC_VERSION && 900 <= GCC_VERSION
70+
# pragma GCC diagnostic ignored "-Wuseless-cast"
71+
#endif
72+
%}
73+
74+
%option noyywrap nounput noinput batch debug
75+
76+
%{
77+
// A number symbol corresponding to the value in provided string.
78+
yy::parser::symbol_type make_NUMBER(const std::string &s, const yy::parser::location_type& loc);
79+
yy::parser::symbol_type make_FLOAT(const std::string &s, const yy::parser::location_type& loc);
80+
yy::parser::symbol_type make_STRING(const std::string &s, const yy::parser::location_type& loc);
81+
yy::parser::symbol_type make_BOOL(std::string s, const yy::parser::location_type& loc);
82+
%}

src/parser/lex/tokens.l

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
m4_changequote()
2+
3+
%{
4+
// TODO: Remove [ðđ€\(\)]
5+
%}
6+
id [a-z_A-Z]([.ðđ€\(\)a-zA-Z_0-9]*[a-zA-Z_0-9]+)?
7+
int [0-9]+[Ll]?
8+
flt [0-9]+[.][0-9]+[fd]?
9+
bool [Ff]alse|[Tt]rue
10+
str \"(\\.|[^\\"])*\"
11+
blank [ \t\r]
12+
accmod [Pp](ublic|rivate|rotected)
13+
type int|long|float|double|string|bool|var|auto

src/parser/mit.license

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2022 Asger Gitz-Johansen
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

0 commit comments

Comments
 (0)