Build lexy parser as a lisp package and implement enough to be on par with esrap version

This commit is contained in:
Renaud Casenave-Péré 2022-07-25 21:32:45 +02:00
parent 992ed2ae03
commit faf01b26b1
19 changed files with 583 additions and 245 deletions

10
bootstrap.pro Normal file
View file

@ -0,0 +1,10 @@
QT += widgets
TEMPLATE = app
TARGET = sextant-bootstrap
DESTDIR = $$PWD
OBJECTS_DIR = $$PWD/tmp/bootstrap
LIBS += -lecl -leql5 -lsextant-parser -L.
QMAKE_CXXFLAGS += -std=c++2a -Wno-parentheses -Wno-unused-local-typedefs -Wno-array-bounds -Wno-maybe-uninitialized -Wno-restrict
QMAKE_LFLAGS += "-Wl,-rpath,\'\$$ORIGIN\'"
SOURCES += src/bootstrap.cc

153
external/test.cc vendored Normal file
View file

@ -0,0 +1,153 @@
#include <string>
#include <cassert>
#include <iostream>
#include <fstream>
#include <vector>
#include "lexy/callback.hpp"
#include "lexy/dsl.hpp"
#include "lexy/input/string_input.hpp"
#include "lexy/action/parse.hpp"
#include "lexy_ext/report_error.hpp"
struct raw_text
{
std::string text;
std::string eol;
raw_text* next;
raw_text* prev;
};
struct document
{
raw_text* first_child;
};
raw_text* make_raw_text(const std::string& str, const std::string& eol)
{
raw_text* line = new raw_text;
line->text = str;
line->eol = eol;
line->next = nullptr;
line->prev = nullptr;
return line;
}
struct _node_sink
{
raw_text* _head = nullptr;
raw_text* _tail = nullptr;
using return_type = raw_text*;
raw_text* operator()(raw_text* obj)
{
if (obj != NULL)
{
if (_head == nullptr)
_head = _tail = obj;
else
{
_tail->next = obj;
obj->prev = _tail;
_tail = obj;
}
}
return _head;
}
raw_text* operator()(std::vector<char>&& str)
{
assert(false);
return make_raw_text("", "");
}
raw_text* operator()(std::string&& str)
{
return make_raw_text(str, "");
}
raw_text* finish() &&
{
return LEXY_MOV(_head);
}
};
struct _append_node
{
using return_type = raw_text*;
constexpr raw_text* operator()(raw_text* obj) const
{
return LEXY_MOV(obj);
}
raw_text* operator()(lexy::nullopt&&) const
{
return nullptr;
}
template <typename... Args>
constexpr raw_text* operator()(Args&&... args) const
{
assert(false);
return nullptr;
}
auto sink() const
{
return _node_sink{};
}
};
constexpr auto append_node = _append_node {};
namespace grammar
{
namespace dsl = lexy::dsl;
struct eol
{
static constexpr auto rule = dsl::capture(dsl::newline);
static constexpr auto value = lexy::as_string<std::string>;
};
struct raw_line
{
// static constexpr auto rule = dsl::terminator(dsl::eol).opt_list(dsl::capture(dsl::code_point));
static constexpr auto rule = dsl::terminator(dsl::p<eol>).opt_list(dsl::capture(dsl::code_point));
static constexpr auto value = lexy::as_string<std::string> >>
lexy::callback<raw_text*>([](lexy::nullopt&& opt, std::string&& _eol) {
return make_raw_text("", _eol);
},
[](std::string&& str, std::string&& _eol) {
return make_raw_text(str, _eol);
});
};
struct document
{
static constexpr auto rule = dsl::terminator(dsl::eof).list(dsl::p<raw_line>);
static constexpr auto value = append_node;
};
} // namespace grammar
int main (int argc, char** argv)
{
if (argc > 1)
{
std::ifstream ifs(argv[1]);
std::string content((std::istreambuf_iterator<char>(ifs)),
(std::istreambuf_iterator<char>()));
auto input = lexy::string_input<lexy::utf8_encoding>(content);
auto result = lexy::parse<grammar::document>(input, lexy_ext::report_error);
if (!result)
return 2;
if (result.has_value())
return 0;
}
return 1;
}

View file

@ -1,203 +1,10 @@
# NOTICE:
#
# Application name defined in TARGET has a corresponding QML filename.
# If name defined in TARGET is changed, the following needs to be done
# to match new name:
# - corresponding QML filename must be changed
# - desktop icon filename must be changed
# - desktop filename must be changed
# - icon definition filename in desktop file must be changed
# - translation filenames have to be changed
TEMPLATE = subdirs
SUBDIRS = parser \
bootstrap \
sextant
LISP_FILES = make.lisp \
lisp/system-index.txt \
lisp/local-projects/clorg/parser/all.lisp \
lisp/local-projects/clorg/parser/ast.lisp \
lisp/local-projects/clorg/parser/parser.lisp \
lisp/local-projects/clorg/parser/printer.lisp \
lisp/local-projects/clorg/clorg.lisp \
lisp/local-projects/clorg/clorg.asd \
lisp/local-projects/sextant/models/all.lisp \
lisp/local-projects/sextant/models/utils.lisp \
lisp/local-projects/sextant/models/files-model.lisp \
lisp/local-projects/sextant/models/org-model.lisp \
lisp/local-projects/sextant/options/all.lisp \
lisp/local-projects/sextant/options/config.lisp \
lisp/local-projects/sextant/options/options.lisp \
lisp/local-projects/sextant/sextant.lisp \
lisp/local-projects/sextant/sextant.asd
lisp.output = libsextant.a
lisp.commands = eql5 -platform minimal $$PWD/make.lisp
lisp.input = LISP_FILES
lisp.CONFIG = combine target_predeps
QMAKE_EXTRA_COMPILERS += lisp
# The name of your application
TARGET = harbour-sextant
QMAKE_CXXFLAGS += -std=c++17 -Wno-parentheses -Wno-unused-local-typedefs -Wno-array-bounds -Wno-maybe-uninitialized -Wno-restrict
CONFIG += sailfishapp
LIBS += -L. -lsextant -lecl -leql5
QT += widgets qml multimedia network quick sql
norepl|standalone:lisp.commands = eql5 -platform minimal $$PWD/make.lisp norepl
standalone {
CONFIG += link_prl
LIBS -= -lecl -leql5
LIBS += -l:libecl.a -l:libeclatomic.a -l:libeclgc.a -l:libeclgmp.a -l:libeclffi.a -l:libeql5.a
}
SOURCES += src/harbour-sextant.cc \
src/parser/parser.cc \
src/parser/ast.cc
HEADERS+= \
src/parser/grammar.hh \
src/parser/parser.hh \
src/parser/ecl_helpers.hh \
src/parser/ast.hh \
external/lexy/include/lexy/input/string_input.hpp \
external/lexy/include/lexy/input/base.hpp \
external/lexy/include/lexy/input/range_input.hpp \
external/lexy/include/lexy/input/buffer.hpp \
external/lexy/include/lexy/input/lexeme_input.hpp \
external/lexy/include/lexy/input/argv_input.hpp \
external/lexy/include/lexy/input/file.hpp \
external/lexy/include/lexy/_detail/detect.hpp \
external/lexy/include/lexy/_detail/buffer_builder.hpp \
external/lexy/include/lexy/_detail/assert.hpp \
external/lexy/include/lexy/_detail/type_name.hpp \
external/lexy/include/lexy/_detail/string_view.hpp \
external/lexy/include/lexy/_detail/std.hpp \
external/lexy/include/lexy/_detail/code_point.hpp \
external/lexy/include/lexy/_detail/stateless_lambda.hpp \
external/lexy/include/lexy/_detail/iterator.hpp \
external/lexy/include/lexy/_detail/invoke.hpp \
external/lexy/include/lexy/_detail/nttp_string.hpp \
external/lexy/include/lexy/_detail/tuple.hpp \
external/lexy/include/lexy/_detail/lazy_init.hpp \
external/lexy/include/lexy/_detail/memory_resource.hpp \
external/lexy/include/lexy/_detail/config.hpp \
external/lexy/include/lexy/_detail/unicode_database.hpp \
external/lexy/include/lexy/_detail/integer_sequence.hpp \
external/lexy/include/lexy/parse_tree.hpp \
external/lexy/include/lexy/code_point.hpp \
external/lexy/include/lexy/dsl/context_flag.hpp \
external/lexy/include/lexy/dsl/unicode.hpp \
external/lexy/include/lexy/dsl/option.hpp \
external/lexy/include/lexy/dsl/sign.hpp \
external/lexy/include/lexy/dsl/base.hpp \
external/lexy/include/lexy/dsl/position.hpp \
external/lexy/include/lexy/dsl/sequence.hpp \
external/lexy/include/lexy/dsl/loop.hpp \
external/lexy/include/lexy/dsl/separator.hpp \
external/lexy/include/lexy/dsl/context_counter.hpp \
external/lexy/include/lexy/dsl/integer.hpp \
external/lexy/include/lexy/dsl/brackets.hpp \
external/lexy/include/lexy/dsl/parse_as.hpp \
external/lexy/include/lexy/dsl/bits.hpp \
external/lexy/include/lexy/dsl/whitespace.hpp \
external/lexy/include/lexy/dsl/lookahead.hpp \
external/lexy/include/lexy/dsl/case_folding.hpp \
external/lexy/include/lexy/dsl/production.hpp \
external/lexy/include/lexy/dsl/eof.hpp \
external/lexy/include/lexy/dsl/code_point.hpp \
external/lexy/include/lexy/dsl/return.hpp \
external/lexy/include/lexy/dsl/delimited.hpp \
external/lexy/include/lexy/dsl/capture.hpp \
external/lexy/include/lexy/dsl/context_identifier.hpp \
external/lexy/include/lexy/dsl/recover.hpp \
external/lexy/include/lexy/dsl/any.hpp \
external/lexy/include/lexy/dsl/operator.hpp \
external/lexy/include/lexy/dsl/char_class.hpp \
external/lexy/include/lexy/dsl/digit.hpp \
external/lexy/include/lexy/dsl/list.hpp \
external/lexy/include/lexy/dsl/follow.hpp \
external/lexy/include/lexy/dsl/newline.hpp \
external/lexy/include/lexy/dsl/bom.hpp \
external/lexy/include/lexy/dsl/repeat.hpp \
external/lexy/include/lexy/dsl/branch.hpp \
external/lexy/include/lexy/dsl/terminator.hpp \
external/lexy/include/lexy/dsl/literal.hpp \
external/lexy/include/lexy/dsl/error.hpp \
external/lexy/include/lexy/dsl/until.hpp \
external/lexy/include/lexy/dsl/symbol.hpp \
external/lexy/include/lexy/dsl/member.hpp \
external/lexy/include/lexy/dsl/identifier.hpp \
external/lexy/include/lexy/dsl/expression.hpp \
external/lexy/include/lexy/dsl/peek.hpp \
external/lexy/include/lexy/dsl/if.hpp \
external/lexy/include/lexy/dsl/scan.hpp \
external/lexy/include/lexy/dsl/byte.hpp \
external/lexy/include/lexy/dsl/ascii.hpp \
external/lexy/include/lexy/dsl/token.hpp \
external/lexy/include/lexy/dsl/combination.hpp \
external/lexy/include/lexy/dsl/punctuator.hpp \
external/lexy/include/lexy/dsl/choice.hpp \
external/lexy/include/lexy/dsl/times.hpp \
external/lexy/include/lexy/grammar.hpp \
external/lexy/include/lexy/lexeme.hpp \
external/lexy/include/lexy/error.hpp \
external/lexy/include/lexy/encoding.hpp \
external/lexy/include/lexy/action/base.hpp \
external/lexy/include/lexy/action/match.hpp \
external/lexy/include/lexy/action/parse_as_tree.hpp \
external/lexy/include/lexy/action/parse.hpp \
external/lexy/include/lexy/action/scan.hpp \
external/lexy/include/lexy/action/validate.hpp \
external/lexy/include/lexy/action/trace.hpp \
external/lexy/include/lexy/input_location.hpp \
external/lexy/include/lexy/visualize.hpp \
external/lexy/include/lexy/callback/adapter.hpp \
external/lexy/include/lexy/callback/base.hpp \
external/lexy/include/lexy/callback/object.hpp \
external/lexy/include/lexy/callback/string.hpp \
external/lexy/include/lexy/callback/integer.hpp \
external/lexy/include/lexy/callback/container.hpp \
external/lexy/include/lexy/callback/composition.hpp \
external/lexy/include/lexy/callback/noop.hpp \
external/lexy/include/lexy/callback/constant.hpp \
external/lexy/include/lexy/callback/bit_cast.hpp \
external/lexy/include/lexy/callback/forward.hpp \
external/lexy/include/lexy/callback/bind.hpp \
external/lexy/include/lexy/callback/fold.hpp \
external/lexy/include/lexy/callback/aggregate.hpp \
external/lexy/include/lexy/token.hpp \
external/lexy/include/lexy/callback.hpp \
external/lexy/include/lexy/dsl.hpp \
external/lexy/include/lexy_ext/parse_tree_doctest.hpp \
external/lexy/include/lexy_ext/parse_tree_algorithm.hpp \
external/lexy/include/lexy_ext/compiler_explorer.hpp \
external/lexy/include/lexy_ext/shell.hpp \
external/lexy/include/lexy_ext/report_error.hpp
INCLUDEPATH += $$PWD/external/lexy/include
DEFINES += LEXY_HAS_UNICODE_DATABASE=1
DISTFILES += qml/harbour-sextant.qml \
qml/cover/CoverPage.qml \
qml/pages/FirstPage.qml \
qml/pages/SecondPage.qml \
qml/pages/Files.qml \
qml/pages/Settings.qml \
rpm/harbour-sextant.changes.in \
rpm/harbour-sextant.changes.run.in \
rpm/harbour-sextant.spec \
rpm/harbour-sextant.yaml \
# translations/*.ts \
harbour-sextant.desktop
SAILFISHAPP_ICONS = 86x86 108x108 128x128 172x172
# to disable building translations every time, comment out the
# following CONFIG line
# CONFIG += sailfishapp_i18n
# German translation is enabled as an example. If you aren't
# planning to localize your app, remember to comment out the
# following TRANSLATIONS line. And also do not forget to
# modify the localized app name in the the .desktop file.
# TRANSLATIONS += translations/harbour-sextant-de.ts
parser.file = parser.pro
bootstrap.file = bootstrap.pro
bootstrap.depends = parser
sextant.file = sextant.pro
sextant.depends = parser bootstrap

View file

@ -3,7 +3,7 @@
:defsystem-depends-on (:asdf-package-system)
:class :package-inferred-system
:around-compile (lambda (thunk)
(proclaim '(optimize (debug 0) (safety 0) (speed 3)))
(proclaim '(optimize (debug 0) (safety 1) (speed 3)))
(funcall thunk))
:depends-on ("alexandria"
"esrap"

View file

@ -22,4 +22,5 @@
(let ((str (etypecase spec
(string spec)
((or pathname stream) (read-file-into-string spec)))))
(parse 'org-parser str)))
;; (time (parse 'org-parser str))
(time (lexy::parse-string str))))

View file

@ -11,7 +11,13 @@
#:line-ending-of
#:make-org-document
#:make-org-text
#:walk-ast))
#:walk-ast
#:last-child
#:rightmost-leaf
#:reparent-children
#:append-node
#:collect-nodes
#:append-children))
(in-package :clorg/parser/ast)
(defclass org-node ()

View file

@ -3,7 +3,7 @@
:defsystem-depends-on (:asdf-package-system)
:class :package-inferred-system
:around-compile (lambda (thunk)
(proclaim '(optimize (debug 3) (safety 3) (speed 0)))
(proclaim '(optimize (debug 0) (safety 1) (speed 3)))
(funcall thunk))
:depends-on #.(append (uiop:read-file-form (merge-pathnames #p"dependencies.sexp" (or *load-pathname* *compile-file-pathname*)))
'("clorg")

137
parser.pro Normal file
View file

@ -0,0 +1,137 @@
TEMPLATE = lib
CONFIG += debug
TARGET = sextant-parser
DESTDIR = $$PWD
OBJECTS_DIR = $$PWD/tmp/parser/
INCLUDEPATH += $$PWD/external/lexy/include
DEFINES += LEXY_HAS_UNICODE_DATABASE=1
LIBS += -lecl
QMAKE_CXXFLAGS += -std=c++2a -Wno-parentheses -Wno-unused-local-typedefs -Wno-array-bounds -Wno-maybe-uninitialized -Wno-restrict
target.path = $$[QT_INSTALL_LIBS]
INSTALLS = target
SOURCES += \
src/parser/parser.cc \
src/parser/ast.cc
HEADERS+= \
src/parser/grammar.hh \
src/parser/parser.hh \
src/parser/ecl_helpers.hh \
src/parser/ast.hh \
external/lexy/include/lexy/input/string_input.hpp \
external/lexy/include/lexy/input/base.hpp \
external/lexy/include/lexy/input/range_input.hpp \
external/lexy/include/lexy/input/buffer.hpp \
external/lexy/include/lexy/input/lexeme_input.hpp \
external/lexy/include/lexy/input/argv_input.hpp \
external/lexy/include/lexy/input/file.hpp \
external/lexy/include/lexy/_detail/detect.hpp \
external/lexy/include/lexy/_detail/buffer_builder.hpp \
external/lexy/include/lexy/_detail/assert.hpp \
external/lexy/include/lexy/_detail/type_name.hpp \
external/lexy/include/lexy/_detail/string_view.hpp \
external/lexy/include/lexy/_detail/std.hpp \
external/lexy/include/lexy/_detail/code_point.hpp \
external/lexy/include/lexy/_detail/stateless_lambda.hpp \
external/lexy/include/lexy/_detail/iterator.hpp \
external/lexy/include/lexy/_detail/invoke.hpp \
external/lexy/include/lexy/_detail/nttp_string.hpp \
external/lexy/include/lexy/_detail/tuple.hpp \
external/lexy/include/lexy/_detail/lazy_init.hpp \
external/lexy/include/lexy/_detail/memory_resource.hpp \
external/lexy/include/lexy/_detail/config.hpp \
external/lexy/include/lexy/_detail/unicode_database.hpp \
external/lexy/include/lexy/_detail/integer_sequence.hpp \
external/lexy/include/lexy/parse_tree.hpp \
external/lexy/include/lexy/code_point.hpp \
external/lexy/include/lexy/dsl/context_flag.hpp \
external/lexy/include/lexy/dsl/unicode.hpp \
external/lexy/include/lexy/dsl/option.hpp \
external/lexy/include/lexy/dsl/sign.hpp \
external/lexy/include/lexy/dsl/base.hpp \
external/lexy/include/lexy/dsl/position.hpp \
external/lexy/include/lexy/dsl/sequence.hpp \
external/lexy/include/lexy/dsl/loop.hpp \
external/lexy/include/lexy/dsl/separator.hpp \
external/lexy/include/lexy/dsl/context_counter.hpp \
external/lexy/include/lexy/dsl/integer.hpp \
external/lexy/include/lexy/dsl/brackets.hpp \
external/lexy/include/lexy/dsl/parse_as.hpp \
external/lexy/include/lexy/dsl/bits.hpp \
external/lexy/include/lexy/dsl/whitespace.hpp \
external/lexy/include/lexy/dsl/lookahead.hpp \
external/lexy/include/lexy/dsl/case_folding.hpp \
external/lexy/include/lexy/dsl/production.hpp \
external/lexy/include/lexy/dsl/eof.hpp \
external/lexy/include/lexy/dsl/code_point.hpp \
external/lexy/include/lexy/dsl/return.hpp \
external/lexy/include/lexy/dsl/delimited.hpp \
external/lexy/include/lexy/dsl/capture.hpp \
external/lexy/include/lexy/dsl/context_identifier.hpp \
external/lexy/include/lexy/dsl/recover.hpp \
external/lexy/include/lexy/dsl/any.hpp \
external/lexy/include/lexy/dsl/operator.hpp \
external/lexy/include/lexy/dsl/char_class.hpp \
external/lexy/include/lexy/dsl/digit.hpp \
external/lexy/include/lexy/dsl/list.hpp \
external/lexy/include/lexy/dsl/follow.hpp \
external/lexy/include/lexy/dsl/newline.hpp \
external/lexy/include/lexy/dsl/bom.hpp \
external/lexy/include/lexy/dsl/repeat.hpp \
external/lexy/include/lexy/dsl/branch.hpp \
external/lexy/include/lexy/dsl/terminator.hpp \
external/lexy/include/lexy/dsl/literal.hpp \
external/lexy/include/lexy/dsl/error.hpp \
external/lexy/include/lexy/dsl/until.hpp \
external/lexy/include/lexy/dsl/symbol.hpp \
external/lexy/include/lexy/dsl/member.hpp \
external/lexy/include/lexy/dsl/identifier.hpp \
external/lexy/include/lexy/dsl/expression.hpp \
external/lexy/include/lexy/dsl/peek.hpp \
external/lexy/include/lexy/dsl/if.hpp \
external/lexy/include/lexy/dsl/scan.hpp \
external/lexy/include/lexy/dsl/byte.hpp \
external/lexy/include/lexy/dsl/ascii.hpp \
external/lexy/include/lexy/dsl/token.hpp \
external/lexy/include/lexy/dsl/combination.hpp \
external/lexy/include/lexy/dsl/punctuator.hpp \
external/lexy/include/lexy/dsl/choice.hpp \
external/lexy/include/lexy/dsl/times.hpp \
external/lexy/include/lexy/grammar.hpp \
external/lexy/include/lexy/lexeme.hpp \
external/lexy/include/lexy/error.hpp \
external/lexy/include/lexy/encoding.hpp \
external/lexy/include/lexy/action/base.hpp \
external/lexy/include/lexy/action/match.hpp \
external/lexy/include/lexy/action/parse_as_tree.hpp \
external/lexy/include/lexy/action/parse.hpp \
external/lexy/include/lexy/action/scan.hpp \
external/lexy/include/lexy/action/validate.hpp \
external/lexy/include/lexy/action/trace.hpp \
external/lexy/include/lexy/input_location.hpp \
external/lexy/include/lexy/visualize.hpp \
external/lexy/include/lexy/callback/adapter.hpp \
external/lexy/include/lexy/callback/base.hpp \
external/lexy/include/lexy/callback/object.hpp \
external/lexy/include/lexy/callback/string.hpp \
external/lexy/include/lexy/callback/integer.hpp \
external/lexy/include/lexy/callback/container.hpp \
external/lexy/include/lexy/callback/composition.hpp \
external/lexy/include/lexy/callback/noop.hpp \
external/lexy/include/lexy/callback/constant.hpp \
external/lexy/include/lexy/callback/bit_cast.hpp \
external/lexy/include/lexy/callback/forward.hpp \
external/lexy/include/lexy/callback/bind.hpp \
external/lexy/include/lexy/callback/fold.hpp \
external/lexy/include/lexy/callback/aggregate.hpp \
external/lexy/include/lexy/token.hpp \
external/lexy/include/lexy/callback.hpp \
external/lexy/include/lexy/dsl.hpp \
external/lexy/include/lexy_ext/parse_tree_doctest.hpp \
external/lexy/include/lexy_ext/parse_tree_algorithm.hpp \
external/lexy/include/lexy_ext/compiler_explorer.hpp \
external/lexy/include/lexy_ext/shell.hpp \
external/lexy/include/lexy_ext/report_error.hpp

View file

@ -67,6 +67,7 @@ desktop-file-install --delete-original \
%files
%defattr(-,root,root,-)
%{_bindir}
%{_libdir}
%{_datadir}/%{name}
%{_datadir}/applications/%{name}.desktop
%{_datadir}/icons/hicolor/*/apps/%{name}.png

View file

@ -41,6 +41,7 @@ Requires:
# All installed files
Files:
- '%{_bindir}'
- '%{_libdir}'
- '%{_datadir}/%{name}'
- '%{_datadir}/applications/%{name}.desktop'
- '%{_datadir}/icons/hicolor/*/apps/%{name}.png'

80
sextant.pro Normal file
View file

@ -0,0 +1,80 @@
# NOTICE:
#
# Application name defined in TARGET has a corresponding QML filename.
# If name defined in TARGET is changed, the following needs to be done
# to match new name:
# - corresponding QML filename must be changed
# - desktop icon filename must be changed
# - desktop filename must be changed
# - icon definition filename in desktop file must be changed
# - translation filenames have to be changed
CONFIG += debug
LISP_FILES = make.lisp \
lisp/system-index.txt \
lisp/local-projects/clorg/parser/all.lisp \
lisp/local-projects/clorg/parser/ast.lisp \
lisp/local-projects/clorg/parser/parser.lisp \
lisp/local-projects/clorg/parser/printer.lisp \
lisp/local-projects/clorg/clorg.lisp \
lisp/local-projects/clorg/clorg.asd \
lisp/local-projects/sextant/models/all.lisp \
lisp/local-projects/sextant/models/utils.lisp \
lisp/local-projects/sextant/models/files-model.lisp \
lisp/local-projects/sextant/models/org-model.lisp \
lisp/local-projects/sextant/options/all.lisp \
lisp/local-projects/sextant/options/config.lisp \
lisp/local-projects/sextant/options/options.lisp \
lisp/local-projects/sextant/sextant.lisp \
lisp/local-projects/sextant/sextant.asd
lisp.output = libsextant.a
lisp.commands = $$PWD/sextant-bootstrap -platform minimal $$PWD/make.lisp
lisp.input = LISP_FILES
lisp.CONFIG = combine target_predeps
QMAKE_EXTRA_COMPILERS += lisp
# The name of your application
TARGET = harbour-sextant
QMAKE_CXXFLAGS += -std=c++2a -Wno-parentheses -Wno-unused-local-typedefs -Wno-array-bounds -Wno-maybe-uninitialized -Wno-restrict
CONFIG += sailfishapp
LIBS += -L. -lsextant-parser -lsextant -lecl -leql5
QT += widgets qml multimedia network quick sql
norepl|standalone:lisp.commands = $$PWD/sextant-bootstrap -platform minimal $$PWD/make.lisp norepl
standalone {
CONFIG += link_prl
LIBS -= -lecl -leql5
LIBS += -l:libecl.a -l:libeclatomic.a -l:libeclgc.a -l:libeclgmp.a -l:libeclffi.a -l:libeql5.a
}
SOURCES += src/harbour-sextant.cc
DISTFILES += qml/harbour-sextant.qml \
qml/cover/CoverPage.qml \
qml/pages/FirstPage.qml \
qml/pages/SecondPage.qml \
qml/pages/Files.qml \
qml/pages/Settings.qml \
rpm/harbour-sextant.changes.in \
rpm/harbour-sextant.changes.run.in \
rpm/harbour-sextant.spec \
rpm/harbour-sextant.yaml \
# translations/*.ts \
harbour-sextant.desktop
SAILFISHAPP_ICONS = 86x86 108x108 128x128 172x172
# to disable building translations every time, comment out the
# following CONFIG line
# CONFIG += sailfishapp_i18n
# German translation is enabled as an example. If you aren't
# planning to localize your app, remember to comment out the
# following TRANSLATIONS line. And also do not forget to
# modify the localized app name in the the .desktop file.
# TRANSLATIONS += translations/harbour-sextant-de.ts

37
src/bootstrap.cc Normal file
View file

@ -0,0 +1,37 @@
#include "parser/parser.hh"
#include <string>
#include <QApplication>
#include <QtCore>
#include <eql5/eql.h>
int main(int argc, char** argv)
{
QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts); // for Qt WebEngine
QApplication qapp(argc, argv);
EQL::ini(argc, argv);
if (argc == 1)
return 0;
EQL eql;
eql.printVersion();
sextant::parser::init_parser_lib();
si_select_package(ecl_make_constant_base_string("COMMON-LISP-USER", 16));
std::string code("(load \"");
code += argv[1];
code += "\")";
CL_CATCH_ALL_BEGIN(ecl_process_env())
{
si_safe_eval(2, ecl_read_from_cstring(code.c_str()), ECL_NIL);
}
CL_CATCH_ALL_END;
return 0;
}

View file

@ -10,6 +10,8 @@
#include <QQuickView>
#include <QTextCodec>
#include "parser/parser.hh"
extern "C" void init_sextant (cl_object);
int main(int argc, char *argv[])
@ -31,6 +33,8 @@ int main(int argc, char *argv[])
QTextCodec::setCodecForLocale(utf8);
EQL eql;
sextant::parser::init_parser_lib();
eql.exec (init_sextant);
eql_fun ("qml:ini-sailfish", Q_ARG (QUrl, SailfishApp::pathToMainQml()),

View file

@ -2,7 +2,7 @@
const char* type_to_ctor[] =
{
"nil",
"make-org-text",
"make-org-document"
"NIL",
"MAKE-ORG-TEXT",
"MAKE-ORG-DOCUMENT"
};

View file

@ -45,33 +45,97 @@ namespace sextant
return to_cl_object(arg.c_str());
}
inline cl_object collect_args(cl_object list)
inline cl_object to_cl_object(const std::u32string& arg)
{
return list;
size_t len = arg.size();
cl_object l_s = ecl_alloc_simple_extended_string(len);
ecl_character* l_p = l_s->string.self;
for (size_t i = 0; i < len; ++i)
l_p[i] = arg[i];
return l_s;
}
inline cl_object collect_args()
{
return ECL_NIL;
}
template <class T>
cl_object collect_args(cl_object list, T arg)
cl_object collect_args(T arg)
{
list = CONS(to_cl_object(arg), list);
return list;
return CONS(to_cl_object(arg), ECL_NIL);
}
template <class T, class... Args>
cl_object collect_args(cl_object list, T arg, Args... args)
cl_object collect_args(T arg, Args... args)
{
list = CONS(to_cl_object(arg), list);
return collect_args(list, args...);
return CONS(to_cl_object(arg), collect_args(args...));
}
inline int count_args()
{
return 0;
}
template <class T>
int count_args(T)
{
return 1;
}
template <class T, class... Args>
int count_args(T arg, Args... args)
{
return 1 + count_args(args...);
}
inline cl_object ast_funcall(const char* fun)
{
cl_object l_fun = cl_find_symbol(2, ecl_make_constant_base_string(fun, -1),
ecl_find_package("CLORG"), NULL);
cl_object l_ret = ECL_NIL;
const cl_env_ptr l_env = ecl_process_env();
ECL_CATCH_ALL_BEGIN(l_env)
{
ECL_UNWIND_PROTECT_BEGIN(l_env)
{
l_ret = cl_funcall(1, l_fun);
}
ECL_UNWIND_PROTECT_EXIT {}
ECL_UNWIND_PROTECT_END;
}
ECL_CATCH_ALL_END;
return l_ret;
}
template <class... Args>
cl_object ast_funcall(const char* fun, cl_object arg1, Args... args)
{
cl_object l_fun = cl_find_symbol(2, ecl_make_constant_base_string(fun, -1),
ecl_find_package("CLORG"), NULL);
int count = count_args(args...) + 2;
cl_object l_ret = ECL_NIL;
const cl_env_ptr l_env = ecl_process_env();
ECL_CATCH_ALL_BEGIN(l_env)
{
ECL_UNWIND_PROTECT_BEGIN(l_env)
{
l_ret = cl_funcall(count, l_fun, arg1, args...);
}
ECL_UNWIND_PROTECT_EXIT {}
ECL_UNWIND_PROTECT_END;
}
ECL_CATCH_ALL_END;
return l_ret;
}
template <class... Args>
cl_object ast_funcall(const char* fun, Args... args)
{
cl_object l_fun = ecl_find_symbol(ecl_make_constant_base_string(fun, -1),
ecl_make_constant_base_string("clorg/parser/ast", -1),
NULL);
cl_object l_args = ECL_NIL;
collect_args(l_args, args...);
cl_object l_fun = cl_find_symbol(2, ecl_make_constant_base_string(fun, -1),
ecl_find_package("CLORG"), NULL);
cl_object l_args = collect_args(args...);
cl_object l_ret = ECL_NIL;
const cl_env_ptr l_env = ecl_process_env();

View file

@ -5,6 +5,8 @@
#include "node_sink.hh"
#include <string>
#include <locale>
#include <codecvt>
#include <vector>
#include "lexy/callback.hpp"
@ -18,19 +20,32 @@ namespace sextant
{
namespace dsl = lexy::dsl;
struct eol
{
static constexpr auto rule = dsl::capture(dsl::newline);
static constexpr auto value = lexy::as_string<std::string>;
};
struct raw_line
{
static constexpr auto rule = dsl::terminator(dsl::eol).opt_list(dsl::code_point);
static constexpr auto value = lexy::as_string<std::string, lexy::utf8_encoding> >>
lexy::callback<cl_object>([](std::string&& str) {
return ast_funcall("make-org-text", str);
});
static constexpr auto rule = dsl::terminator(dsl::p<eol>).opt_list(dsl::capture(dsl::code_point));
static constexpr auto value = lexy::as_string<std::string> >>
lexy::callback<cl_object>([](lexy::nullopt&&, std::string&& eol) {
return ast_funcall("MAKE-ORG-TEXT", "", eol);
},
[](std::string&& str, std::string&& eol) {
std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> converter;
std::u32string u32str = converter.from_bytes(str.c_str());
return ast_funcall("MAKE-ORG-TEXT", u32str, eol);
});
};
struct document
{
static constexpr auto rule = dsl::terminator(dsl::eof).opt_list(dsl::p<raw_line>);
static constexpr auto value = append_node;
static constexpr auto rule = dsl::terminator(dsl::eof).list(dsl::p<raw_line>);
static constexpr auto value = append_node >> lexy::callback<cl_object>([](cl_object head) {
return ast_funcall("MAKE-ORG-DOCUMENT", head);
});
};
}
}

View file

@ -17,24 +17,27 @@ namespace sextant
struct _node_sink
{
cl_object _result = ECL_NIL;
cl_object _head = ECL_NIL;
cl_object _tail = ECL_NIL;
using return_type = cl_object;
cl_object operator()(cl_object&& obj)
{
if (_result == ECL_NIL)
{
_result = obj;
return _result;
}
if (_head == ECL_NIL)
_head = _tail = obj;
else
return ast_funcall("append-node", _result, obj);
{
ast_funcall("APPEND-NODE", _tail, obj);
_tail = obj;
}
return _head;
}
cl_object&& finish() &&
{
return LEXY_MOV(_result);
return LEXY_MOV(_head);
}
};
@ -55,12 +58,12 @@ namespace sextant
template <typename... Args>
constexpr cl_object operator()(Args&&... args) const
{
return ast_funcall("collect-nodes", args...);
return ast_funcall("COLLECT-NODES", args...);
}
auto sink() const
{
return _node_sink{ECL_NIL};
return _node_sink{};
}
};

View file

@ -3,6 +3,8 @@
#include "grammar.hh"
#include <string>
#include <locale>
#include <codecvt>
#include <cassert>
#include "lexy/input/string_input.hpp"
@ -23,15 +25,14 @@ namespace sextant
str = std::string((char*)l_str->base_string.self, l_str->base_string.fillp);
else
{
uint l = l_str->string.fillp;
str.resize(l);
ecl_character* l_s = l_str->string.self;
for (uint i = 0; i < l; ++i)
str[i] = l_s[i];
ecl_character* l_p = l_str->string.self;
std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> converter;
str = converter.to_bytes((char32_t*)l_p, (char32_t*)(l_p + l_str->string.dim));
}
auto input = lexy::string_input<lexy::utf8_encoding>(str);
auto result = lexy::parse<grammar::document>(input, lexy_ext::report_error);
if (!result)
return ECL_NIL;
@ -41,5 +42,14 @@ namespace sextant
return ECL_NIL;
}
void init_parser_lib()
{
cl_object lexy = ecl_make_constant_base_string("LEXY", 4);
if (cl_find_package(lexy) == ECL_NIL)
ecl_make_package(lexy, ECL_NIL, ECL_NIL, ECL_NIL);
si_select_package(lexy);
ecl_def_c_function(ecl_read_from_cstring("parse-string"), (cl_objectfn_fixed)parse_string, 1);
}
}
}

View file

@ -3,6 +3,15 @@
#include <ecl/ecl.h>
cl_object parse_string(cl_object l_str);
namespace sextant
{
namespace parser
{
cl_object parse_string(cl_object l_str);
void init_parser_lib();
}
}
#endif // PARSER_HH