Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
e99431b
Add PALMSerializer and related constants for expression serialization
CodingPupper3033 Nov 8, 2025
dd995e0
Refactor PALMOpts and enhance PALMSerializer with comprehensive seria…
CodingPupper3033 Nov 8, 2025
86dc7a7
Enhance PALMSerializer with support for additional expressions and im…
CodingPupper3033 Nov 8, 2025
a081c5c
Refactor PALMDelimiters to use static string_view for expression deli…
CodingPupper3033 Nov 8, 2025
dde3d68
Add tests for malformed expressions in PALMSerializer
CodingPupper3033 Nov 8, 2025
f17f1ea
Add PALMHelper for expression token conversion and update includes in…
CodingPupper3033 Nov 8, 2025
19865ee
Refactor PALMHelper to use maps for expression and delimiter token co…
CodingPupper3033 Nov 8, 2025
d89b9f6
Add TODO comment for Matrix serialization in PALMSerializer
CodingPupper3033 Nov 8, 2025
d3b7e36
[Actions] Format CMakeLists.txt
invalid-email-address Nov 8, 2025
03ed67d
Add Boost Bimap includes and define TokenBimap for expression type ma…
CodingPupper3033 Nov 8, 2025
6acfe67
Update PALMDelimiterToToken to remove unused options parameter
CodingPupper3033 Nov 8, 2025
550c595
Update FetchBoost.cmake to include 'bimap' in BOOST_INCLUDE_LIBRARIES
CodingPupper3033 Nov 8, 2025
d10cde9
Refactor PALMSerializer to improve code formatting and readability
CodingPupper3033 Nov 8, 2025
f7eae8b
Update CMakeLists.txt to link Boost Bimap and adjust include directories
CodingPupper3033 Nov 8, 2025
21942de
Update CMakeLists.txt and FetchBoost.cmake to include Boost Assign; m…
CodingPupper3033 Nov 8, 2025
0c7c82a
Update CMakeLists.txt to conditionally link Boost libraries based on …
CodingPupper3033 Nov 9, 2025
b2607a2
[Actions] Format CMakeLists.txt
invalid-email-address Nov 9, 2025
0cd5c6d
Refactored PALMTokens to take in all possible tokens instead of split…
CodingPupper3033 Nov 9, 2025
5987d3e
Clang Format
CodingPupper3033 Nov 9, 2025
9816498
Split PALMHelper.hpp into PALMTypes.hpp, PALMConsts.hpp, and PALMSpec…
CodingPupper3033 Nov 10, 2025
bfa060e
Refactored PalmSerializer to use PALMSpec
CodingPupper3033 Nov 10, 2025
e5e0e5e
Refactored PalmSerializer to SerializeExpression by the parameter typ…
CodingPupper3033 Nov 10, 2025
77e8183
Clang Formatted
CodingPupper3033 Nov 10, 2025
c19c1a6
Removed PALMSpec and moved functions (which were tokenizer specific) …
CodingPupper3033 Nov 10, 2025
eb12ecf
Refactor parsing error handling to use new error types and structures
CodingPupper3033 Nov 21, 2025
1a5cb38
Refactor FromPALM functions and enhance error handling in PALM parsing
CodingPupper3033 Nov 22, 2025
4ef5690
Enhance error handling in FromPALM and PALMSerializer, update seriali…
CodingPupper3033 Nov 22, 2025
a9dfc5a
Refactor PALM serialization and parsing tests for improved clarity, c…
CodingPupper3033 Nov 22, 2025
b56404a
Refactor error types in FromPALM to improve clarity and consistency i…
CodingPupper3033 Nov 25, 2025
58b0a31
Add InvalidOperator error type to FromPALM and enhance parsing logic
CodingPupper3033 Nov 25, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion cmake/FetchBoost.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ FetchContent_Declare(
EXCLUDE_FROM_ALL
)

set(BOOST_INCLUDE_LIBRARIES any callable_traits mpl)
set(BOOST_INCLUDE_LIBRARIES any assign bimap callable_traits mpl)
FetchContent_MakeAvailable(Boost)
6 changes: 6 additions & 0 deletions include/Oasis/Concepts.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ class BinaryExpression;
template <template <IExpression> class DerivedT, IExpression OpT>
class UnaryExpression;

template <typename DerivedT>
class LeafExpression;

/**
* Checks if type T is same as any of the provided types in U.
*
Expand All @@ -59,6 +62,9 @@ concept DerivedFromUnaryExpression = requires(Derived& d) {
[]<template <typename> typename D, IExpression T>(UnaryExpression<D, T>&) { }(d);
};

template <typename T>
concept DerivedFromLeafExpression = std::derived_from<T, LeafExpression<T>>;

template <typename T>
concept IVisitor = requires {
typename T::RetT; // Checks for the type alias
Expand Down
20 changes: 17 additions & 3 deletions io/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,20 +1,34 @@
set(OASIS_IO_SOURCES
# cmake-format: sortable
src/FromPALM.cpp src/FromString.cpp src/InFixSerializer.cpp
src/MathMLSerializer.cpp src/TeXSerializer.cpp)
src/FromPALM.cpp
src/FromString.cpp
src/InFixSerializer.cpp
src/MathMLSerializer.cpp
src/PALMSerializer.cpp
src/PALMTokenizer.cpp
src/TeXSerializer.cpp)

set(OASIS_IO_HEADERS
# cmake-format: sortable
include/Oasis/FromPALM.hpp
include/Oasis/FromString.hpp
include/Oasis/InFixSerializer.hpp
include/Oasis/MathMLSerializer.hpp
include/Oasis/TeXSerializer.hpp)
include/Oasis/PALMSerializer.hpp
include/Oasis/TeXSerializer.hpp
src/PALMHelper.hpp)

add_library(OasisIO ${OASIS_IO_SOURCES} ${OASIS_IO_HEADERS})
add_library(Oasis::IO ALIAS OasisIO)

target_include_directories(OasisIO PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
if(NOT OASIS_BUILD_JS)
target_link_libraries(OasisIO PUBLIC Boost::bimap)
target_link_libraries(OasisIO PUBLIC Boost::assign)
target_include_directories(OasisIO PUBLIC ${Boost_INCLUDE_DIRS})
target_include_directories(OasisIO
PRIVATE ${Boost_SOURCE_DIR}/libs/assign/include)
endif()
target_link_libraries(OasisIO PUBLIC Oasis::Oasis tinyxml2::tinyxml2)

if(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
Expand Down
55 changes: 47 additions & 8 deletions io/include/Oasis/FromPALM.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,64 @@
#define OASIS_FROMPALM_HPP

#include "Oasis/Expression.hpp"
#include "../src/PALMTypes.hpp"

namespace Oasis {

enum class ParseError {
enum class ParseErrorOld {
None,
UnexpectedToken,
MissingClosingParen,
InvalidNumberFormat,
IncompleteExpression,
UnknownOperator,
UnexpectedEndOfInput
IncompleteExpression, // expression opens but required operands/args missing
MissingClosingParen, // '(' without matching ')'
UnexpectedEndOfInput, // input ended while more tokens were required
UnexpectedToken, // token present but not valid in this position
InvalidNumberFormat, // number failed to parse
UnknownOperator, // operator not recognized
TooManyOperands, // more expressions than operator's arity allows
TooFewOperands, // fewer expressions than operator's arity requires
AmbiguousParse, // grammar ambiguity or overload not resolvable
LexicalError, // tokenization error (bad character, unterminated string)
Other // fallback
};

/* Represents a parse error in PALM parsing. */
struct PALMParseError {
enum class PALMParseErrorType {
None,
InvalidNumberFormat,
InvalidVariableName,
InvalidOperator,
InvalidOperand,
NumberOutOfBounds,
LexicalError,
MissingOperator,
MissingOperand,
ExtraOperands,
UnexpectedToken,
UnexpectedEndOfInput,
MissingOpeningParenthesis,
MissingClosingParenthesis,
} type;

PALMToken token;
std::string message;
};

/** Equality operator for PALMParseError.
*
* @param lhs The left-hand side PALMParseError.
* @param rhs The right-hand side PALMParseError.
* @return True if the two errors are equal, false otherwise.
*/
bool operator==(const PALMParseError& lhs, const PALMParseError& rhs);

/** Parses an expression from a PALM string.
*
* @param palmString The PALM string to parse.
* @return The parsed expression, or nullptr if the string could not be parsed.
*/
auto FromPALM(const std::string& palmString) -> std::expected<std::unique_ptr<Expression>, ParseError>;
auto FromPALMOld(const std::string& palmString) -> std::expected<std::unique_ptr<Expression>, ParseErrorOld>;

auto FromPALM(const std::string& palmString) -> std::expected<std::unique_ptr<Expression>, PALMParseError>;
}

#endif // OASIS_FROMPALM_HPP
102 changes: 102 additions & 0 deletions io/include/Oasis/PALMSerializer.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
//
// Created by codin on 10/31/25.
//

#ifndef OASIS_PALMSERIALIZER_HPP
#define OASIS_PALMSERIALIZER_HPP

#include <format>
#include <string>
#include <vector>

#include "../../src/PALMTypes.hpp"
#include "Oasis/Visit.hpp"
#include "Oasis/Expression.hpp"

namespace Oasis {

/** Options for PALM serialization. */
struct PALMSerializationOpts {
enum class ImgSymType {
I,
J
} imaginarySymbol
= ImgSymType::I;

uint8_t numPlaces = 5;

std::string tokenSeparator = " ";

std::string expressionPadding = " ";
};

struct PALMSerializationError {
enum class PALMSerializationErrorType {
None,
InvalidIdentifier,
MissingOperand,
Other
} type;

const Expression* expression;
std::string message;
};

/** Equality operator for PALMSerializationError.
*
* @param lhs The left-hand side PALMSerializationError.
* @param rhs The right-hand side PALMSerializationError.
* @return True if the two errors are equal, false otherwise.
*/
bool operator==(const PALMSerializationError& lhs, const PALMSerializationError& rhs);

inline std::string_view PALM_UNEXPECTED_NO_MOST_SIG_OP = "Expression missing most significant operand";
inline std::string_view PALM_UNEXPECTED_NO_LEAST_SIG_OP = "Expression missing least significant operand";

class PALMSerializer final : public TypedVisitor<std::expected<std::string, PALMSerializationError>> {
public:
PALMSerializer()
: PALMSerializer(PALMSerializationOpts {})
{
}
explicit PALMSerializer(PALMSerializationOpts options)
: palmOptions(std::move(options))
{
}

auto TypedVisit(const Real& real) -> RetT override;
auto TypedVisit(const Imaginary& imaginary) -> RetT override;
auto TypedVisit(const Variable& variable) -> RetT override;
auto TypedVisit(const Undefined& undefined) -> RetT override;
auto TypedVisit(const Add<Expression, Expression>& add) -> RetT override;
auto TypedVisit(const Subtract<Expression, Expression>& subtract) -> RetT override;
auto TypedVisit(const Multiply<Expression, Expression>& multiply) -> RetT override;
auto TypedVisit(const Divide<Expression, Expression>& divide) -> RetT override;
auto TypedVisit(const Exponent<Expression, Expression>& exponent) -> RetT override;
auto TypedVisit(const Log<Expression, Expression>& log) -> RetT override;
auto TypedVisit(const Negate<Expression>& negate) -> RetT override;
auto TypedVisit(const Derivative<Expression, Expression>& derivative) -> RetT override;
auto TypedVisit(const Integral<Expression, Expression>& integral) -> RetT override;
auto TypedVisit(const Matrix& matrix) -> RetT override;
auto TypedVisit(const EulerNumber&) -> RetT override;
auto TypedVisit(const Pi&) -> RetT override;
auto TypedVisit(const Magnitude<Expression>& magnitude) -> RetT override;
~PALMSerializer() override = default;

private:
PALMSerializationOpts palmOptions {};

static inline auto OperatorToToken(ExpressionType op, const PALMSerializationOpts& options) -> std::string_view;
static inline auto PunctuatorToToken(PALMPunctuatorType punctuator, const PALMSerializationOpts& options) -> std::string_view;

[[nodiscard]] auto WrapExpression(ExpressionType expressionType, const std::initializer_list<std::expected<std::string, PALMSerializationError>>& operands = {}) const -> RetT;
static auto IsValidIdentifier(const std::string& string) -> bool;

auto SerializeExpression(const DerivedFromLeafExpression auto& expr) -> RetT;
auto SerializeExpression(const DerivedFromUnaryExpression auto& expr) -> RetT;
auto SerializeExpression(const DerivedFromBinaryExpression auto& expr) -> RetT;
};

}

#endif // OASIS_PALMSERIALIZER_HPP
Loading
Loading