Let's go!
This commit is contained in:
commit
06f9b35c6c
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
.ccls-cache
|
||||||
|
bin/*
|
||||||
|
compile_commands.json
|
12
.gitlab-ci.yml
Normal file
12
.gitlab-ci.yml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
image: gcc
|
||||||
|
|
||||||
|
stages:
|
||||||
|
- build
|
||||||
|
|
||||||
|
build:
|
||||||
|
stage: build
|
||||||
|
script:
|
||||||
|
- make
|
||||||
|
artifacts:
|
||||||
|
path:
|
||||||
|
- main
|
22
Makefile
Normal file
22
Makefile
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
MAKEFLAGS="-j $(grep -c ^processor /proc/cpuinfo)"
|
||||||
|
CXXFLAGS=-std=c++20 -Wall -Wextra -O2 -Werror=switch
|
||||||
|
CPPFLAGS=-Ilib/expected/ -Ilib/ut/
|
||||||
|
|
||||||
|
Obj=bin/lexer.o \
|
||||||
|
bin/errors.o \
|
||||||
|
bin/main.o
|
||||||
|
|
||||||
|
all: bin/musique
|
||||||
|
|
||||||
|
bin/%.o: src/%.cc src/*.hh
|
||||||
|
g++ $(CXXFLAGS) $(CPPFLAGS) -o $@ $< -c
|
||||||
|
|
||||||
|
bin/musique: $(Obj) src/*.hh
|
||||||
|
g++ $(CXXFLAGS) $(CPPFLAGS) -o $@ $(Obj)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf bin
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
|
||||||
|
$(shell mkdir -p bin)
|
54
doc/składnia.txt
Normal file
54
doc/składnia.txt
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
program = ws*, expression, ws*, { expression, ws* }
|
||||||
|
block = "[", program, "]" ;
|
||||||
|
|
||||||
|
(* At interpreter runtime it is determined which symbols pass as operators, and which not *)
|
||||||
|
expression = value, ws*, operator, ws*, expression
|
||||||
|
| operator, ws*, value
|
||||||
|
| value ;
|
||||||
|
|
||||||
|
value = note
|
||||||
|
| chord
|
||||||
|
| symbol
|
||||||
|
| block
|
||||||
|
| number
|
||||||
|
| ( "(", expression, ")" ) ;
|
||||||
|
|
||||||
|
symbol = ( valid-symbol-start-characters, { valid-symbol-characters } ) - note - chord;
|
||||||
|
valid-symbol-start-characters = uniletter | "_" | "@" | "$" | "#" ;
|
||||||
|
valid-symbol-characters = valid-symbol-start-characters | unidigit | "-" ;
|
||||||
|
|
||||||
|
operator = operator-symbols, { operator-symbols } ;
|
||||||
|
operator-symbols = "+" | "-" | "*" | "/" | "%" | "!"
|
||||||
|
| "<" | ">" | "v" | "^" | "=" | ":" ;
|
||||||
|
|
||||||
|
(********************************* Literały liczbowe *********************************)
|
||||||
|
number = floating-point | fraction ;
|
||||||
|
|
||||||
|
(* Dopuszcza następujące zapisy: 1/2, *)
|
||||||
|
fraction = digits+, ws*, "/", ws*, digits+ ;
|
||||||
|
|
||||||
|
(* Dopuszcza następujące zapisy: -123.456, 123.456, .456; Notacja naukowa nie jest wspierana *)
|
||||||
|
floating-point = ( ["-"], digits+, [ ".", digits+ ] ) | ( ".", digits+ );
|
||||||
|
|
||||||
|
|
||||||
|
(********************************* Literały muzyczne *********************************)
|
||||||
|
(* DSL do definiowania muzycznych wartości. Brakuje notacji dla akordów, przewrotów itd *)
|
||||||
|
note = note-letter, ["#"], [ws*, octave] ;
|
||||||
|
note-letter = "c" | "C" | "d" | "D" | "e" | "E" | "f" | "F" | "g" | "G" | "a" | "A" | "h" | "H" | "b" | "B" ;
|
||||||
|
octave = "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" ;
|
||||||
|
|
||||||
|
chord = note-letter, ["#"], [ ("1" | "2" | "5" | "7" ), [ "," | "'" ] ];
|
||||||
|
|
||||||
|
(********************************* Definicje pomocnicze *********************************)
|
||||||
|
|
||||||
|
(* Unicode helpers, based on Go's compiler source code *)
|
||||||
|
uniletter = ? all characters that are considered letters in unicode ?;
|
||||||
|
unidigit = ? all characters that are considered digits in unicode ?;
|
||||||
|
|
||||||
|
digits+ = digit, { digits } ;
|
||||||
|
digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;
|
||||||
|
|
||||||
|
(* Whitespace helpers *)
|
||||||
|
ws* = { ws } ;
|
||||||
|
ws+ = ws, { ws } ;
|
||||||
|
ws = ? all characters that are considered ascii whitespace ? ;
|
91
lib/expected/README.md
Normal file
91
lib/expected/README.md
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
# expected
|
||||||
|
Single header implementation of `std::expected` with functional-style extensions.
|
||||||
|
|
||||||
|
[![Documentation Status](https://readthedocs.org/projects/tl-docs/badge/?version=latest)](https://tl.tartanllama.xyz/en/latest/?badge=latest)
|
||||||
|
Clang + GCC: [![Linux Build Status](https://travis-ci.org/TartanLlama/expected.png?branch=master)](https://travis-ci.org/TartanLlama/expected)
|
||||||
|
MSVC: [![Windows Build Status](https://ci.appveyor.com/api/projects/status/k5x00xa11y3s5wsg?svg=true)](https://ci.appveyor.com/project/TartanLlama/expected)
|
||||||
|
|
||||||
|
Available on [Vcpkg](https://github.com/microsoft/vcpkg/tree/master/ports/tl-expected) and [Conan](https://github.com/yipdw/conan-tl-expected).
|
||||||
|
|
||||||
|
[`std::expected`](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0323r3.pdf) is proposed as the preferred way to represent object which will either have an expected value, or an unexpected value giving information about why something failed. Unfortunately, chaining together many computations which may fail can be verbose, as error-checking code will be mixed in with the actual programming logic. This implementation provides a number of utilities to make coding with `expected` cleaner.
|
||||||
|
|
||||||
|
For example, instead of writing this code:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
std::expected<image,fail_reason> get_cute_cat (const image& img) {
|
||||||
|
auto cropped = crop_to_cat(img);
|
||||||
|
if (!cropped) {
|
||||||
|
return cropped;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto with_tie = add_bow_tie(*cropped);
|
||||||
|
if (!with_tie) {
|
||||||
|
return with_tie;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto with_sparkles = make_eyes_sparkle(*with_tie);
|
||||||
|
if (!with_sparkles) {
|
||||||
|
return with_sparkles;
|
||||||
|
}
|
||||||
|
|
||||||
|
return add_rainbow(make_smaller(*with_sparkles));
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
You can do this:
|
||||||
|
|
||||||
|
```cpp
|
||||||
|
tl::expected<image,fail_reason> get_cute_cat (const image& img) {
|
||||||
|
return crop_to_cat(img)
|
||||||
|
.and_then(add_bow_tie)
|
||||||
|
.and_then(make_eyes_sparkle)
|
||||||
|
.map(make_smaller)
|
||||||
|
.map(add_rainbow);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The interface is the same as `std::expected` as proposed in [p0323r3](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0323r3.pdf), but the following member functions are also defined. Explicit types are for clarity.
|
||||||
|
|
||||||
|
- `map`: carries out some operation on the stored object if there is one.
|
||||||
|
* `tl::expected<std::size_t,std::error_code> s = exp_string.map(&std::string::size);`
|
||||||
|
- `map_error`: carries out some operation on the unexpected object if there is one.
|
||||||
|
* `my_error_code translate_error (std::error_code);`
|
||||||
|
* `tl::expected<int,my_error_code> s = exp_int.map_error(translate_error);`
|
||||||
|
- `and_then`: like `map`, but for operations which return a `tl::expected`.
|
||||||
|
* `tl::expected<ast, fail_reason> parse (const std::string& s);`
|
||||||
|
* `tl::expected<ast, fail_reason> exp_ast = exp_string.and_then(parse);`
|
||||||
|
- `or_else`: calls some function if there is no value stored.
|
||||||
|
* `exp.or_else([] { throw std::runtime_error{"oh no"}; });`
|
||||||
|
|
||||||
|
### Compiler support
|
||||||
|
|
||||||
|
Tested on:
|
||||||
|
|
||||||
|
- Linux
|
||||||
|
* clang 6.0.1
|
||||||
|
* clang 5.0.2
|
||||||
|
* clang 4.0.1
|
||||||
|
* clang 3.9
|
||||||
|
* clang 3.8
|
||||||
|
* clang 3.7
|
||||||
|
* clang 3.6
|
||||||
|
* clang 3.5
|
||||||
|
* g++ 8.0.1
|
||||||
|
* g++ 7.3
|
||||||
|
* g++ 6.4
|
||||||
|
* g++ 5.5
|
||||||
|
* g++ 4.9
|
||||||
|
* g++ 4.8
|
||||||
|
- Windows
|
||||||
|
* MSVC 2015
|
||||||
|
* MSVC 2017
|
||||||
|
|
||||||
|
### Acknowledgements
|
||||||
|
|
||||||
|
Thanks to [Kévin Alexandre Boissonneault](https://github.com/KABoissonneault) and [Björn Fahller](https://github.com/rollbear) for various bug fixes.
|
||||||
|
|
||||||
|
----------
|
||||||
|
|
||||||
|
[![CC0](http://i.creativecommons.org/p/zero/1.0/88x31.png)]("http://creativecommons.org/publicdomain/zero/1.0/")
|
||||||
|
|
||||||
|
To the extent possible under law, [Sy Brand](https://twitter.com/TartanLlama) has waived all copyright and related or neighboring rights to the `expected` library. This work is published from: United Kingdom.
|
2326
lib/expected/tl/expected.hpp
Normal file
2326
lib/expected/tl/expected.hpp
Normal file
File diff suppressed because it is too large
Load Diff
23
lib/ut/LICENSE.md
Normal file
23
lib/ut/LICENSE.md
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
Boost Software License - Version 1.0 - August 17th, 2003
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person or organization
|
||||||
|
obtaining a copy of the software and accompanying documentation covered by
|
||||||
|
this license (the "Software") to use, reproduce, display, distribute,
|
||||||
|
execute, and transmit the Software, and to prepare derivative works of the
|
||||||
|
Software, and to permit third-parties to whom the Software is furnished to
|
||||||
|
do so, all subject to the following:
|
||||||
|
|
||||||
|
The copyright notices in the Software and this entire statement, including
|
||||||
|
the above license grant, this restriction and the following disclaimer,
|
||||||
|
must be included in all copies of the Software, in whole or in part, and
|
||||||
|
all derivative works of the Software, unless such copies or derivative
|
||||||
|
works are solely in the form of machine-executable object code generated by
|
||||||
|
a source language processor.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||||
|
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||||
|
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||||
|
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
DEALINGS IN THE SOFTWARE.
|
2027
lib/ut/README.md
Normal file
2027
lib/ut/README.md
Normal file
File diff suppressed because it is too large
Load Diff
2391
lib/ut/boost/ut.hpp
Normal file
2391
lib/ut/boost/ut.hpp
Normal file
File diff suppressed because it is too large
Load Diff
6
src/errors.cc
Normal file
6
src/errors.cc
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#include "musique.hh"
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& os, Error const&)
|
||||||
|
{
|
||||||
|
return os << "generic error";
|
||||||
|
}
|
12
src/lexer.cc
Normal file
12
src/lexer.cc
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#include "musique.hh"
|
||||||
|
|
||||||
|
auto Lexer::next_token() -> Result<Token>
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& os, Token const&)
|
||||||
|
{
|
||||||
|
os << "Token";
|
||||||
|
return os;
|
||||||
|
}
|
26
src/main.cc
Normal file
26
src/main.cc
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include "musique.hh"
|
||||||
|
|
||||||
|
std::string_view Source = R"musique(
|
||||||
|
nums = [ 1 2 3 ]
|
||||||
|
say ( min nums + max nums )
|
||||||
|
)musique";
|
||||||
|
|
||||||
|
tl::expected<void, Error> Main()
|
||||||
|
{
|
||||||
|
Lexer lexer{Source};
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
auto token = Try(lexer.next_token());
|
||||||
|
std::cout << token << '\n';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
auto result = Main();
|
||||||
|
if (not result.has_value()) {
|
||||||
|
std::cerr << result.error() << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
77
src/musique.hh
Normal file
77
src/musique.hh
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <string_view>
|
||||||
|
#include <ostream>
|
||||||
|
#include <tl/expected.hpp>
|
||||||
|
|
||||||
|
using u8 = std::uint8_t;
|
||||||
|
using u16 = std::uint16_t;
|
||||||
|
using u32 = std::uint32_t;
|
||||||
|
using u64 = std::uint64_t;
|
||||||
|
|
||||||
|
using i8 = std::int8_t;
|
||||||
|
using i16 = std::int16_t;
|
||||||
|
using i32 = std::int32_t;
|
||||||
|
using i64 = std::int64_t;
|
||||||
|
|
||||||
|
struct Error
|
||||||
|
{
|
||||||
|
std::string_view message;
|
||||||
|
Error *child = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
using Result = tl::expected<T, Error>;
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& os, Error const& err);
|
||||||
|
|
||||||
|
// NOTE This implementation requires C++ language extension: statement expressions
|
||||||
|
// It's supported by GCC, other compilers i don't know
|
||||||
|
#define Try(Value) ({ \
|
||||||
|
auto try_value = (Value); \
|
||||||
|
if (not try_value.has_value()) return tl::unexpected(try_value.error()); \
|
||||||
|
*std::move(try_value); \
|
||||||
|
})
|
||||||
|
|
||||||
|
struct Token
|
||||||
|
{
|
||||||
|
enum class Type
|
||||||
|
{
|
||||||
|
// like repeat or choose or chord
|
||||||
|
Symbol,
|
||||||
|
|
||||||
|
// chord literal, like c125
|
||||||
|
Chord,
|
||||||
|
|
||||||
|
// numeric literal (floating point or integer)
|
||||||
|
Numeric,
|
||||||
|
|
||||||
|
// "|" separaters arguments from block body, and provides variable introduction syntax
|
||||||
|
Variable_Separator,
|
||||||
|
|
||||||
|
// "[" and "]", delimit anonymous block of code (potentially a function)
|
||||||
|
Open_Block,
|
||||||
|
Close_Block,
|
||||||
|
|
||||||
|
// "(" and ")", used in arithmetic or as function invocation sarrounding (like in Haskell)
|
||||||
|
Open_Paren,
|
||||||
|
Close_Paren
|
||||||
|
};
|
||||||
|
|
||||||
|
std::string_view source;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& os, Token const& tok);
|
||||||
|
|
||||||
|
struct Lexer
|
||||||
|
{
|
||||||
|
// Source that is beeing lexed
|
||||||
|
std::string_view source;
|
||||||
|
|
||||||
|
// Determine location of tokens to produce nice errors
|
||||||
|
std::string_view source_name = "<unnamed>";
|
||||||
|
unsigned column = 1, row = 1;
|
||||||
|
|
||||||
|
auto next_token() -> Result<Token>;
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user