From cd538159cffdd108e5f3e85faa7e296491b7f251 Mon Sep 17 00:00:00 2001 From: jorenchik Date: Sun, 15 Sep 2024 20:02:19 +0300 Subject: [PATCH] add c++ project and translate from go partially --- src/cpp/CMakeLists.txt | 10 + .../index/main.cpp.6DE93E662B25E657.idx | Bin 0 -> 680 bytes .../mocs_compilation.cpp.24E22B09DF7BB0D0.idx | Bin 0 -> 556 bytes src/cpp/qtapp/.clang-format | 401 ++++++++++++++++++ src/cpp/qtapp/.gitignore | 2 + src/cpp/qtapp/CMakeLists.txt | 22 + src/cpp/qtapp/compile_commands.json | 14 + src/cpp/qtapp/main.cpp | 222 ++++++++++ .../clangd/index/api.h.09188030E1E1AD2B.idx | Bin 0 -> 184 bytes .../index/config.h.37161B9BC74F84AB.idx | Bin 0 -> 224 bytes .../index/lexer.cpp.83041CDDE7BB82EA.idx | Bin 0 -> 6334 bytes .../clangd/index/lexer.h.56AED8998E88A18A.idx | Bin 0 -> 1788 bytes .../index/main.cpp.3110054129CACA6D.idx | Bin 0 -> 2316 bytes .../index/parser.cpp.1DA6C31FD012A889.idx | Bin 0 -> 7778 bytes .../index/parser.h.A6B071E84CF21EB1.idx | Bin 0 -> 1870 bytes .../index/result.h.9FDF8FE2A27152FF.idx | Bin 0 -> 616 bytes .../clangd/index/time.h.A5DECF25CDA82FFC.idx | Bin 0 -> 600 bytes src/cpp/transpiler/.gitignore | 2 + src/cpp/transpiler/.vscode/launch.json | 16 + src/cpp/transpiler/.vscode/settings.json | 5 + src/cpp/transpiler/.vscode/tasks.json | 12 + src/cpp/transpiler/CMakeLists.txt | 24 ++ src/cpp/transpiler/api.cpp | 43 ++ src/cpp/transpiler/api.h | 4 + src/cpp/transpiler/compile_commands.json | 20 + src/cpp/transpiler/config.h | 4 + src/cpp/transpiler/lexer.cpp | 284 +++++++++++++ src/cpp/transpiler/lexer.h | 33 ++ src/cpp/transpiler/main.cpp | 82 ++++ src/cpp/transpiler/parser.cpp | 278 ++++++++++++ src/cpp/transpiler/parser.h | 43 ++ src/cpp/transpiler/result.h | 13 + src/cpp/transpiler/time.cpp | 10 + src/cpp/transpiler/time.h | 8 + src/{ => go}/compiler/.gitignore | 0 src/{ => go}/compiler/api/api.go | 0 src/{ => go}/compiler/comperror/comperror.go | 0 src/{ => go}/compiler/compiler.go | 0 src/{ => go}/compiler/deck.moml | 0 src/{ => go}/compiler/go.mod | 0 src/{ => go}/compiler/go.sum | 0 src/{ => go}/compiler/lexer/lexer.go | 0 src/{ => go}/compiler/parser/parser.go | 0 src/{ => go}/mdemory-app-qt/.gitignore | 0 .../mdemory-app-qt/.vscode/launch.json | 0 src/{ => go}/mdemory-app-qt/go.mod | 0 src/{ => go}/mdemory-app-qt/go.sum | 0 src/{ => go}/mdemory-app-qt/main | Bin src/{ => go}/mdemory-app-qt/main.go | 0 49 files changed, 1552 insertions(+) create mode 100644 src/cpp/CMakeLists.txt create mode 100644 src/cpp/qtapp/.cache/clangd/index/main.cpp.6DE93E662B25E657.idx create mode 100644 src/cpp/qtapp/.cache/clangd/index/mocs_compilation.cpp.24E22B09DF7BB0D0.idx create mode 100644 src/cpp/qtapp/.clang-format create mode 100644 src/cpp/qtapp/.gitignore create mode 100644 src/cpp/qtapp/CMakeLists.txt create mode 100644 src/cpp/qtapp/compile_commands.json create mode 100644 src/cpp/qtapp/main.cpp create mode 100644 src/cpp/transpiler/.cache/clangd/index/api.h.09188030E1E1AD2B.idx create mode 100644 src/cpp/transpiler/.cache/clangd/index/config.h.37161B9BC74F84AB.idx create mode 100644 src/cpp/transpiler/.cache/clangd/index/lexer.cpp.83041CDDE7BB82EA.idx create mode 100644 src/cpp/transpiler/.cache/clangd/index/lexer.h.56AED8998E88A18A.idx create mode 100644 src/cpp/transpiler/.cache/clangd/index/main.cpp.3110054129CACA6D.idx create mode 100644 src/cpp/transpiler/.cache/clangd/index/parser.cpp.1DA6C31FD012A889.idx create mode 100644 src/cpp/transpiler/.cache/clangd/index/parser.h.A6B071E84CF21EB1.idx create mode 100644 src/cpp/transpiler/.cache/clangd/index/result.h.9FDF8FE2A27152FF.idx create mode 100644 src/cpp/transpiler/.cache/clangd/index/time.h.A5DECF25CDA82FFC.idx create mode 100644 src/cpp/transpiler/.gitignore create mode 100644 src/cpp/transpiler/.vscode/launch.json create mode 100644 src/cpp/transpiler/.vscode/settings.json create mode 100644 src/cpp/transpiler/.vscode/tasks.json create mode 100644 src/cpp/transpiler/CMakeLists.txt create mode 100644 src/cpp/transpiler/api.cpp create mode 100644 src/cpp/transpiler/api.h create mode 100644 src/cpp/transpiler/compile_commands.json create mode 100644 src/cpp/transpiler/config.h create mode 100644 src/cpp/transpiler/lexer.cpp create mode 100644 src/cpp/transpiler/lexer.h create mode 100644 src/cpp/transpiler/main.cpp create mode 100644 src/cpp/transpiler/parser.cpp create mode 100644 src/cpp/transpiler/parser.h create mode 100644 src/cpp/transpiler/result.h create mode 100644 src/cpp/transpiler/time.cpp create mode 100644 src/cpp/transpiler/time.h rename src/{ => go}/compiler/.gitignore (100%) rename src/{ => go}/compiler/api/api.go (100%) rename src/{ => go}/compiler/comperror/comperror.go (100%) rename src/{ => go}/compiler/compiler.go (100%) rename src/{ => go}/compiler/deck.moml (100%) rename src/{ => go}/compiler/go.mod (100%) rename src/{ => go}/compiler/go.sum (100%) rename src/{ => go}/compiler/lexer/lexer.go (100%) rename src/{ => go}/compiler/parser/parser.go (100%) rename src/{ => go}/mdemory-app-qt/.gitignore (100%) rename src/{ => go}/mdemory-app-qt/.vscode/launch.json (100%) rename src/{ => go}/mdemory-app-qt/go.mod (100%) rename src/{ => go}/mdemory-app-qt/go.sum (100%) rename src/{ => go}/mdemory-app-qt/main (100%) rename src/{ => go}/mdemory-app-qt/main.go (100%) diff --git a/src/cpp/CMakeLists.txt b/src/cpp/CMakeLists.txt new file mode 100644 index 0000000..bf375b5 --- /dev/null +++ b/src/cpp/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 3.16) +project(mdemory) + +set(CMAKE_CXX_STANDARD 20) + +add_subdirectory(transpiler) +add_subdirectory(qtapp) + +# Add the main source files +# add_executable(MdemoryApp qtapp/main.cpp) diff --git a/src/cpp/qtapp/.cache/clangd/index/main.cpp.6DE93E662B25E657.idx b/src/cpp/qtapp/.cache/clangd/index/main.cpp.6DE93E662B25E657.idx new file mode 100644 index 0000000000000000000000000000000000000000..363fabf5cdc97f64eff88e0bb645c512eca66413 GIT binary patch literal 680 zcmWIYbaPw4#K7R3;#rZKT9U}Zz`!5`#Kk2=nI4P`410ib6?5hW#`+&J5PADQa@Xre z%$=P4Mg@^dOk58OHFIyi`epdr@yY$$mQz|Xn)Yq6d_M19@p;`t5{YNlSQKaJ7b=QqFFIEQD&jVb9LwyapT`Q$Q*3)|+1ZT@;XKyRU8*WuM0V=lXGnQ(mB z0*UZrat9;1w!D6Dc5=lz_HX-MYYFXHxsz?-N}e8NAHjS2r)3f!_MIzk-QakmD7|T^ zjB(=e>251crg#+aZj|}rs1a~Pl2>-2?#i9aTAk}|zFf5_uxj$XCXwBZjX5nFKIg=| zo}d!hwvPW3d*&R^7gN6FH*MY^EcL6kzA5;d#-1Y^K2_%YV~%C{$h=#0&9i&FQ|%H{ zLSI|?#kN@Od3?`g{^V))9FpP1|2j?9eXBlkWkKzl`;33oA6~zF|5$VAm&r{+`aS!c z_VTQo$?|^jj_(fgwhW()iz{=JC<6gSscFSK zfXo@kxsB3RTo+>G5ocv&<%Mb6d?jb!|2@uTKw%CJ4j!0r@xB|^vTx?31BJPGxCCIr zs^>X1*VYKg_Vt+OOQ*1OPEWDOO%(BTa1H;k)HtoC!z%w literal 0 HcmV?d00001 diff --git a/src/cpp/qtapp/.cache/clangd/index/mocs_compilation.cpp.24E22B09DF7BB0D0.idx b/src/cpp/qtapp/.cache/clangd/index/mocs_compilation.cpp.24E22B09DF7BB0D0.idx new file mode 100644 index 0000000000000000000000000000000000000000..2d8665151206d2948e8d3ea24ffe7418b13f1944 GIT binary patch literal 556 zcmWIYbaPW-VqkDi@vO*AElFfyU|Y9rF$u2z;qmN|*lH z5Yp+)Y0?$qmFXy>o2=hC`-WdG`_%i_Gbc>Y;`?%;d+p5F^Kbe%m$n4Gydo%jHSEzA zFCnMruX#_0=W~CHIp-FVbDFy%a^ugWZMtq-w4WbM`fNANd&OF}9~=03SA;TGim>Vi zMwc_aXX#kieEz`WoiaC%uS?#;zs-sHRL8dI9xD{Se29A1qE-Ki(RAUofcAUe{1m31 z@~xL%x>j@#YkYBgLZ4UjvwKo6c4Snv%DJ5ORXs0$TJ2?Q75~~>{X8kcPPG#*pZelC zDfP)W*MAqPa?^8L(+|D!+iIhc9c1Y7?cTvSNr``t+2<_owAydD##wIf`U|e>*KM#? z)#j;N!^7wjX1>q)p|Z(eaao_ws`(#0w;Jv|eIe85-!<7FZ@!N|nGe`MNfuD;o_oUS zEU&TIl~W-{+!q(?Tlw!}oM+EsQe2svWCsjiah?4s*97MTurf#jIZUif!e9a@0|xHv z_4nsXDoo^OkN`=GG3kH_m~>HUTCpCG12ct@3#)FBFi0!ZuA > instead of A> for LS_Cpp03. +# Possible values: +# LS_Cpp03 (in configuration: Cpp03) Use C++03-compatible syntax. +# LS_Cpp11 (in configuration: Cpp11) Use features of C++11 (e.g. A> instead of A >). +# LS_Auto (in configuration: Auto) Automatic detection based on the input. +Standard: Cpp11 + +# Pointer and reference alignment style. Possible values: Left, Right, Middle. +PointerAlignment: Left + +# AccessModifierOffset (int) +# The extra indent or outdent of access modifiers, e.g. public:. +AccessModifierOffset: 0 + +# AlignAfterOpenBracket (BracketAlignmentStyle) +# If true, horizontally aligns arguments after an open bracket. +# This applies to round brackets (parentheses), angle brackets and square brackets. +# Possible values: +# BAS_Align (in configuration: Align) Align parameters on the open bracket, e.g.: +# someLongFunction(argument1, +# argument2); +# BAS_DontAlign (in configuration: DontAlign) Don’t align, instead use ContinuationIndentWidth, e.g.: +# someLongFunction(argument1, +# argument2); +# BAS_AlwaysBreak (in configuration: AlwaysBreak) Always break after an open bracket, if the parameters don’t fit on a single line, e.g.: +# someLongFunction( +# argument1, argument2); +AlignAfterOpenBracket: false + +# AlignConsecutiveAssignments (bool) +# If true, aligns consecutive assignments. +# This will align the assignment operators of consecutive lines. This will result in formattings like +# int aaaa = 12; +# int b = 23; +# int ccc = 23; +AlignConsecutiveAssignments: true + +# AlignEscapedNewlinesLeft (bool) +# If true, aligns escaped newlines as far left as possible. Otherwise puts them into the right-most column. +AlignEscapedNewlinesLeft: true + +# AlignOperands (bool) +# If true, horizontally align operands of binary and ternary expressions. +# Specifically, this aligns operands of a single expression that needs to be split over multiple lines, e.g.: +# int aaa = bbbbbbbbbbbbbbb + +# ccccccccccccccc; +AlignOperands: false + +# AlignTrailingComments (bool) +# If true, aligns trailing comments. +AlignTrailingComments: true + +# AllowAllParametersOfDeclarationOnNextLine (bool) +# Allow putting all parameters of a function declaration onto the next line even if BinPackParameters is false. +AllowAllParametersOfDeclarationOnNextLine: false + +# AllowShortBlocksOnASingleLine (bool) +# Allows contracting simple braced statements to a single line. +AllowShortBlocksOnASingleLine: false + +# AllowShortCaseLabelsOnASingleLine (bool) +# If true, short case labels will be contracted to a single line. +AllowShortCaseLabelsOnASingleLine: true + +# AllowShortFunctionsOnASingleLine (ShortFunctionStyle) +# Dependent on the value, int f() { return 0; } can be put on a single line. +# Possible values: +# SFS_None (in configuration: None) Never merge functions into a single line. +# SFS_Empty (in configuration: Empty) Only merge empty functions. +# SFS_Inline (in configuration: Inline) Only merge functions defined inside a class. Implies “empty”. +# SFS_All (in configuration: All) Merge all functions fitting on a single line. +AllowShortFunctionsOnASingleLine: false + +# AllowShortIfStatementsOnASingleLine (bool) +# If true, if (a) return; can be put on a single line. +AllowShortIfStatementsOnASingleLine: false + +# AllowShortLoopsOnASingleLine (bool) +# If true, while (true) continue; can be put on a single line. +AllowShortLoopsOnASingleLine: false + +# AlwaysBreakBeforeMultilineStrings (bool) +# If true, always break before multiline string literals. +# This flag is mean to make cases where there are multiple multiline strings in a file look more consistent. Thus, it will only take effect if wrapping the string at that point leads to it being indented ContinuationIndentWidth spaces from the start of the line. +AlwaysBreakBeforeMultilineStrings: false + +# AlwaysBreakTemplateDeclarations (bool) +# If true, always break after the template<...> of a template declaration. +AlwaysBreakTemplateDeclarations: false + +# BinPackArguments (bool) +# If false, a function call’s arguments will either be all on the same line or will have one line each. +#BinPackArguments: false + +# BinPackParameters (bool) +# If false, a function declaration’s or function definition’s parameters will either all be on the same line or will have one line each. +BinPackParameters: false + +# BraceWrapping (BraceWrappingFlags) +# Control of individual brace wrapping cases. +# If BreakBeforeBraces is set to BS_Custom, use this to specify how each individual brace case should be handled. Otherwise, this is ignored. +# Nested configuration flags: +# bool AfterClass Wrap class definitions. +# bool AfterControlStatement Wrap control statements (if/for/while/switch/..). +# bool AfterEnum Wrap enum definitions. +# bool AfterFunction Wrap function definitions. +# bool AfterNamespace Wrap namespace definitions. +# bool AfterObjCDeclaration Wrap ObjC definitions (@autoreleasepool, interfaces, ..). +# bool AfterStruct Wrap struct definitions. +# bool AfterUnion Wrap union definitions. +# bool BeforeCatch Wrap before catch. +# bool BeforeElse Wrap before else. +# bool IndentBraces Indent the wrapped braces themselves. +#BraceWrapping: + +# BreakAfterJavaFieldAnnotations (bool) +# Break after each annotation on a field in Java files. +#BreakAfterJavaFieldAnnotations: + +# BreakBeforeBinaryOperators (BinaryOperatorStyle) +# The way to wrap binary operators. +# Possible values: +# BOS_None (in configuration: None) Break after operators. +# BOS_NonAssignment (in configuration: NonAssignment) Break before operators that aren’t assignments. +# BOS_All (in configuration: All) Break before operators. +BreakBeforeBinaryOperators: false + +# BreakBeforeBraces (BraceBreakingStyle) +# The brace breaking style to use. +# Possible values: +# BS_Attach (in configuration: Attach) Always attach braces to surrounding context. +# BS_Linux (in configuration: Linux) Like Attach, but break before braces on function, namespace and class definitions. +# BS_Mozilla (in configuration: Mozilla) Like Attach, but break before braces on enum, function, and record definitions. +# BS_Stroustrup (in configuration: Stroustrup) Like Attach, but break before function definitions, catch, and else. +# BS_Allman (in configuration: Allman) Always break before braces. +# BS_GNU (in configuration: GNU) Always break before braces and add an extra level of indentation to braces of control statements, not to those of class, function or other definitions. +# BS_WebKit (in configuration: WebKit) Like Attach, but break before functions. +# BS_Custom (in configuration: Custom) Configure each individual brace in BraceWrapping. +BreakBeforeBraces: Attach + +# BreakBeforeTernaryOperators (bool) +# If true, ternary operators will be placed after line breaks. +BreakBeforeTernaryOperators: false + +# BreakConstructorInitializersBeforeComma (bool) +# Always break constructor initializers before commas and align the commas with the colon. +BreakConstructorInitializersBeforeComma: false + +# BreakStringLiterals (bool) +# Allow breaking string literals when formatting. +#BreakStringLiterals: + +# ColumnLimit (unsigned) +# The column limit. +# A column limit of 0 means that there is no column limit. In this case, clang-format will respect the input’s line breaking decisions within statements unless they contradict other rules. +ColumnLimit: 80 + +# CommentPragmas (std::string) +# A regular expression that describes comments with special meaning, which should not be split into lines or otherwise changed. +CommentPragmas: '' + +# ConstructorInitializerAllOnOneLineOrOnePerLine (bool) +# If the constructor initializers don’t fit on a line, put each initializer on its own line. +ConstructorInitializerAllOnOneLineOrOnePerLine: false + +# ConstructorInitializerIndentWidth (unsigned) +# The number of characters to use for indentation of constructor initializer lists. +ConstructorInitializerIndentWidth: 0 + +# ContinuationIndentWidth (unsigned) +# Indent width for line continuations. +ContinuationIndentWidth: 0 + +# Cpp11BracedListStyle (bool) +# If true, format braced lists as best suited for C++11 braced lists. +# Important differences: - No spaces inside the braced list. - No line break before the closing brace. - Indentation with the continuation indent, not with the block indent. +# Fundamentally, C++11 braced lists are formatted exactly like function calls would be formatted in their place. If the braced list follows a name (e.g. a type or variable name), clang-format formats as if the {} were the parentheses of a function call with that name. If there is no name, a zero-length name is assumed. +Cpp11BracedListStyle: false + +# DerivePointerAlignment (bool) +# If true, analyze the formatted file for the most common alignment of & and \*. PointerAlignment is then used only as fallback. +DerivePointerBinding: false + +# DisableFormat (bool) +# Disables formatting completely. +#DisableFormat: + +# ExperimentalAutoDetectBinPacking (bool) +# If true, clang-format detects whether function calls and definitions are formatted with one parameter per line. +# Each call can be bin-packed, one-per-line or inconclusive. If it is inconclusive, e.g. completely on one line, but a decision needs to be made, clang-format analyzes whether there are other bin-packed cases in the input file and act accordingly. +# NOTE: This is an experimental flag, that might go away or be renamed. Do not use this in config files, etc. Use at your own risk. +#ExperimentalAutoDetectBinPacking: + +# ForEachMacros (std::vector) +# A vector of macros that should be interpreted as foreach loops instead of as function calls. +# These are expected to be macros of the form: +# FOREACH(, ...) +# +# In the .clang-format configuration file, this can be configured like: +# ForEachMacros: ['RANGES_FOR', 'FOREACH'] +# For example: BOOST_FOREACH. +#ForEachMacros: + +# IncludeCategories (std::vector) +# Regular expressions denoting the different #include categories used for ordering #includes. +# These regular expressions are matched against the filename of an include (including the <> or “”) in order. The value belonging to the first matching regular expression is assigned and #includes are sorted first according to increasing category number and then alphabetically within each category. +# If none of the regular expressions match, INT_MAX is assigned as category. The main header for a source file automatically gets category 0. so that it is generally kept at the beginning of the #includes (http://llvm.org/docs/CodingStandards.html#include-style). However, you can also assign negative priorities if you have certain headers that always need to be first. +# To configure this in the .clang-format file, use: +# IncludeCategories: +# - Regex: '^"(llvm|llvm-c|clang|clang-c)/' +# Priority: 2 +# - Regex: '^(<|"(gtest|isl|json)/)' +# Priority: 3 +# - Regex: '.\*' +# Priority: 1 +#IncludeCategories: + +# IndentCaseLabels (bool) +# Indent case labels one level from the switch statement. +# When false, use the same indentation level as for the switch statement. Switch statement body is always indented one level more than case labels. +IndentCaseLabels: false + +# IndentFunctionDeclarationAfterType (bool) +# If true, indent when breaking function declarations which are not also definitions after the type. +IndentFunctionDeclarationAfterType: false + +# IndentWrappedFunctionNames (bool) +# Indent if a function definition or declaration is wrapped after the type. +#IndentWrappedFunctionNames: + +# KeepEmptyLinesAtTheStartOfBlocks (bool) +# If true, empty lines at the start of blocks are kept. +#KeepEmptyLinesAtTheStartOfBlocks: + +# MacroBlockBegin (std::string) +# A regular expression matching macros that start a block. +#MacroBlockBegin: + +# MacroBlockEnd (std::string) +# A regular expression matching macros that end a block. +#MacroBlockEnd: + +# MaxEmptyLinesToKeep (unsigned) +# The maximum number of consecutive empty lines to keep. +MaxEmptyLinesToKeep: 2 + +# NamespaceIndentation (NamespaceIndentationKind) +# The indentation used for namespaces. +# Possible values: +# NI_None (in configuration: None) Don’t indent in namespaces. +# NI_Inner (in configuration: Inner) Indent only in inner namespaces (nested in other namespaces). +# NI_All (in configuration: All) Indent in all namespaces. +NamespaceIndentation: None + +# ObjCBlockIndentWidth (unsigned) +# The number of characters to use for indentation of ObjC blocks. +#ObjCBlockIndentWidth: + +# ObjCSpaceAfterProperty (bool) +# Add a space after @property in Objective-C, i.e. use @property (readonly) instead of @property(readonly). +ObjCSpaceAfterProperty: true + +# ObjCSpaceBeforeProtocolList (bool) +# Add a space in front of an Objective-C protocol list, i.e. use Foo instead of Foo. +ObjCSpaceBeforeProtocolList: true + +# PenaltyBreakBeforeFirstCallParameter (unsigned) +# The penalty for breaking a function call after call(. +PenaltyBreakBeforeFirstCallParameter: 100 + +# PenaltyBreakComment (unsigned) +# The penalty for each line break introduced inside a comment. +PenaltyBreakComment: 100 + +# PenaltyBreakFirstLessLess (unsigned) +# The penalty for breaking before the first <<. +PenaltyBreakFirstLessLess: 0 + +# PenaltyBreakString (unsigned) +# The penalty for each line break introduced inside a string literal. +PenaltyBreakString: 100 + +# PenaltyExcessCharacter (unsigned) +# The penalty for each character outside of the column limit. +PenaltyExcessCharacter: 1 + +# PenaltyReturnTypeOnItsOwnLine (unsigned) +# Penalty for putting the return type of a function onto its own line. +PenaltyReturnTypeOnItsOwnLine: 20 + +# PointerAlignment (PointerAlignmentStyle) +# Pointer and reference alignment style. +# Possible values: +# PAS_Left (in configuration: Left) Align pointer to the left. +# PAS_Right (in configuration: Right) Align pointer to the right. +# PAS_Middle (in configuration: Middle) Align pointer in the middle. +#PointerAlignment: + +# ReflowComments (bool) +# If true, clang-format will attempt to re-flow comments. +#ReflowComments: true (from v3.9) + +# SortIncludes (bool) +# If true, clang-format will sort #includes. +#SortIncludes: false (from v3.9) + +# SpaceAfterCStyleCast (bool) +# If true, a space may be inserted after C style casts. +SpaceAfterCStyleCast: false + +# SpaceBeforeAssignmentOperators (bool) +# If false, spaces will be removed before assignment operators. +SpaceBeforeAssignmentOperators: true + +# SpaceBeforeParens (SpaceBeforeParensOptions) +# Defines in which cases to put a space before opening parentheses. +# Possible values: +# SBPO_Never (in configuration: Never) Never put a space before opening parentheses. +# SBPO_ControlStatements (in configuration: ControlStatements) Put a space before opening parentheses only after control statement keywords (for/if/while...). +# SBPO_Always (in configuration: Always) Always put a space before opening parentheses, except when it’s prohibited by the syntax rules (in function-like macro definitions) or when determined by other style rules (after unary operators, opening parentheses, etc.) +SpaceBeforeParens: Always + +# SpaceInEmptyParentheses (bool) +# If true, spaces may be inserted into (). +SpaceInEmptyParentheses: false + +# SpacesBeforeTrailingComments (unsigned) +# The number of spaces before trailing line comments (// - comments). +# This does not affect trailing block comments (/* - comments) as those commonly have different usage patterns and a number of special cases. +SpacesBeforeTrailingComments: 1 + +# SpacesInAngles (bool) +# If true, spaces will be inserted after < and before > in template argument lists. +SpacesInAngles: false + +# SpacesInCStyleCastParentheses (bool) +# If true, spaces may be inserted into C style casts. +SpacesInCStyleCastParentheses: false + +# SpacesInContainerLiterals (bool) +# If true, spaces are inserted inside container literals (e.g. ObjC and Javascript array and dict literals). +SpacesInContainerLiterals: false + +# SpacesInParentheses (bool) +# If true, spaces will be inserted after ( and before ). +SpacesInParentheses: false + +# SpacesInSquareBrackets (bool) +# If true, spaces will be inserted after [ and before ]. +SpacesInSquareBrackets: false + diff --git a/src/cpp/qtapp/.gitignore b/src/cpp/qtapp/.gitignore new file mode 100644 index 0000000..0f3a6b1 --- /dev/null +++ b/src/cpp/qtapp/.gitignore @@ -0,0 +1,2 @@ +Debug +Release diff --git a/src/cpp/qtapp/CMakeLists.txt b/src/cpp/qtapp/CMakeLists.txt new file mode 100644 index 0000000..66c996f --- /dev/null +++ b/src/cpp/qtapp/CMakeLists.txt @@ -0,0 +1,22 @@ +cmake_minimum_required(VERSION 3.10) +if(CMAKE_VERSION VERSION_LESS "3.7.0") + set(CMAKE_INCLUDE_CURRENT_DIR ON) +endif() + +project(MdemoryApp VERSION 0.1.0 LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) +set(CMAKE_AUTOUIC ON) + +find_package(Qt5 COMPONENTS Widgets REQUIRED) + +add_executable( + MdemoryApp + main.cpp +) +target_link_libraries(MdemoryApp Qt5::Widgets) diff --git a/src/cpp/qtapp/compile_commands.json b/src/cpp/qtapp/compile_commands.json new file mode 100644 index 0000000..61e3c8b --- /dev/null +++ b/src/cpp/qtapp/compile_commands.json @@ -0,0 +1,14 @@ +[ +{ + "directory": "/home/jorenchik/Code/mdemory/src/cpp/qtapp", + "command": "/usr/bin/g++ -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NO_DEBUG -DQT_WIDGETS_LIB -I/home/jorenchik/Code/mdemory/src/cpp/qtapp/MdemoryApp_autogen/include -isystem /usr/include/qt -isystem /usr/include/qt/QtWidgets -isystem /usr/include/qt/QtGui -isystem /usr/include/qt/QtCore -isystem /usr/lib/qt/mkspecs/linux-g++ -std=gnu++11 -fPIC -o CMakeFiles/MdemoryApp.dir/MdemoryApp_autogen/mocs_compilation.cpp.o -c /home/jorenchik/Code/mdemory/src/cpp/qtapp/MdemoryApp_autogen/mocs_compilation.cpp", + "file": "/home/jorenchik/Code/mdemory/src/cpp/qtapp/MdemoryApp_autogen/mocs_compilation.cpp", + "output": "CMakeFiles/MdemoryApp.dir/MdemoryApp_autogen/mocs_compilation.cpp.o" +}, +{ + "directory": "/home/jorenchik/Code/mdemory/src/cpp/qtapp", + "command": "/usr/bin/g++ -DQT_CORE_LIB -DQT_GUI_LIB -DQT_NO_DEBUG -DQT_WIDGETS_LIB -I/home/jorenchik/Code/mdemory/src/cpp/qtapp/MdemoryApp_autogen/include -isystem /usr/include/qt -isystem /usr/include/qt/QtWidgets -isystem /usr/include/qt/QtGui -isystem /usr/include/qt/QtCore -isystem /usr/lib/qt/mkspecs/linux-g++ -std=gnu++11 -fPIC -o CMakeFiles/MdemoryApp.dir/main.cpp.o -c /home/jorenchik/Code/mdemory/src/cpp/qtapp/main.cpp", + "file": "/home/jorenchik/Code/mdemory/src/cpp/qtapp/main.cpp", + "output": "CMakeFiles/MdemoryApp.dir/main.cpp.o" +} +] \ No newline at end of file diff --git a/src/cpp/qtapp/main.cpp b/src/cpp/qtapp/main.cpp new file mode 100644 index 0000000..f7fbd90 --- /dev/null +++ b/src/cpp/qtapp/main.cpp @@ -0,0 +1,222 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct Page { + int start; + int end; +}; + +class Mdem { +public: + QWidget *wMdem; + QLabel *wFrontText; + QWidget *wBack; + QVector backLabels; + QToolButton *showButton; + int labelCount; + + // Method to show or hide back labels + void showBacklabels() { + for (int i = 0; i < backLabels.size(); ++i) { + if (i < labelCount) { + if (!backLabels[i]->isVisible()) { + backLabels[i]->show(); + } + } else { + if (backLabels[i]->isVisible()) { + backLabels[i]->hide(); + } + } + } + } + + // Constructor to create an Mdem object + Mdem() { + wMdem = new QWidget(); + QVBoxLayout *vMdem = new QVBoxLayout(); + wMdem->setLayout(vMdem); + + QString id = QString("mdem_%1").arg(1); + wMdem->setObjectName(id); + + // Front + QWidget *wFront = new QWidget(); + QHBoxLayout *hFront = new QHBoxLayout(); + wFront->setMinimumHeight(60); + wFront->setLayout(hFront); + wMdem->setStyleSheet(QString( + "QWidget#%1 > QWidget {" + "border-right: 1px solid gray;" + "border-bottom: 1px solid gray;" + "border-left: 1px solid gray;" + "} " + "QWidget#%1 > QWidget[first=\"true\"] {" + "border-top: 1px solid gray;" + "}" + ).arg(id)); + + // Add Front Content + wFrontText = new QLabel(); + hFront->addWidget(wFrontText); + hFront->addStretch(1); + + showButton = new QToolButton(); + showButton->setText("Show"); + hFront->addWidget(showButton); + + // Back + wBack = new QWidget(); + QVBoxLayout *hBack = new QVBoxLayout(); + wBack->setLayout(hBack); + vMdem->addWidget(wBack); + + // Add Back Content + for (int i = 0; i < 20; ++i) { + QLabel *elBackText = new QLabel(); + hBack->addWidget(elBackText); + backLabels.append(elBackText); + } + + vMdem->addWidget(wFront); + vMdem->addWidget(wBack); + vMdem->setContentsMargins(0, 0, 0, 0); + vMdem->setSpacing(0); + + wBack->hide(); + wMdem->hide(); + + // Connect button to toggle view + QObject::connect(showButton, &QToolButton::clicked, [this]() { + if (wBack->isVisible()) { + wBack->hide(); + showButton->setText("Show"); + } else { + wBack->show(); + showButton->setText("Hide"); + } + showBacklabels(); + }); + } +}; + +QLabel *deckListLabel; +QVBoxLayout *hMdemScroll; +QSpacerItem *mdemSpacer; +QList mdems; +QString workingPath = "/home/jorenchik/Code/mdemory/memorybase"; + +void CreateMdems(QList& questions) { + if (mdemSpacer) { + hMdemScroll->removeItem(mdemSpacer); + } + + for (Mdem *mdem : mdems) { + if (mdem->wMdem->isVisible()) { + mdem->wMdem->hide(); + } + } + + // TODO +} + +void SwitchPage(int pageIdx, QList& pages, QList& mdems) { + for (Mdem *mdem : mdems) { + if (mdem->wBack->isVisible()) { + mdem->wBack->hide(); + mdem->showButton->setText("Show"); + } + } + + // TODO +} + +int main(int argc, char *argv[]) { + QApplication app(argc, argv); + QMainWindow window; + + QSplitter *hSplitter = new QSplitter(); + + // LeftSide + QWidget *leftWidget = new QWidget(); + QVBoxLayout *leftLayout = new QVBoxLayout(); + QLabel *mdemLabel = new QLabel("Mdems"); + QFileSystemModel *model = new QFileSystemModel(); + QTreeView *mdemList = new QTreeView(); + + leftWidget->setLayout(leftLayout); + leftLayout->addWidget(mdemLabel); + model->setRootPath(workingPath); + mdemList->setModel(model); + + QModelIndex rootIndex = model->index("/home/jorenchik/Code/mdemory/memorybase"); + mdemList->setRootIndex(rootIndex); + leftLayout->addWidget(mdemList); + + // DeckList + QLabel *deckLabel = new QLabel("Decks"); + QListView *deckList = new QListView(); + leftLayout->addWidget(deckLabel); + leftLayout->addWidget(deckList); + + // RightSide + QWidget *rightWidget = new QWidget(); + QVBoxLayout *rightLayout = new QVBoxLayout(); + rightWidget->setLayout(rightLayout); + + QWidget *top = new QWidget(); + QHBoxLayout *hTop = new QHBoxLayout(); + deckListLabel = new QLabel("Mdem: todo.mdem"); + top->setLayout(hTop); + rightLayout->addWidget(top); + + hTop->addWidget(deckListLabel); + hTop->addStretch(1); + + QToolButton *refresh = new QToolButton(); + QToolButton *practice = new QToolButton(); + QToolButton *shuffle = new QToolButton(); + + hTop->addWidget(refresh); + hTop->addWidget(shuffle); + hTop->addWidget(practice); + + // Buttons + refresh->setText("Refresh"); + shuffle->setText("Shuffle"); + practice->setText("Practice"); + + // Mdems + QScrollArea *mdemScroll = new QScrollArea(); + QWidget *mdemContainer = new QWidget(); + hMdemScroll = new QVBoxLayout(); + mdemScroll->setWidget(mdemContainer); + mdemScroll->setWidgetResizable(true); + mdemContainer->setLayout(hMdemScroll); + rightLayout->addWidget(mdemScroll); + + // Pagination + hSplitter->addWidget(leftWidget); + hSplitter->addWidget(rightWidget); + hSplitter->setStretchFactor(0, 1); + hSplitter->setStretchFactor(1, 3); + + window.setCentralWidget(hSplitter); + window.show(); + return app.exec(); +} diff --git a/src/cpp/transpiler/.cache/clangd/index/api.h.09188030E1E1AD2B.idx b/src/cpp/transpiler/.cache/clangd/index/api.h.09188030E1E1AD2B.idx new file mode 100644 index 0000000000000000000000000000000000000000..3babb38c41deeba3898087ffff0488da77c25529 GIT binary patch literal 184 zcmWIYbaUIlz`)>~;#rZKT9U{DWD5ataY<2TFp%B{#1(Vqo<1nppuof8p!Mlr-P)E$ ziv>&kglUz*9ObkpQ L5eQ(0F&G#C3XV7c literal 0 HcmV?d00001 diff --git a/src/cpp/transpiler/.cache/clangd/index/config.h.37161B9BC74F84AB.idx b/src/cpp/transpiler/.cache/clangd/index/config.h.37161B9BC74F84AB.idx new file mode 100644 index 0000000000000000000000000000000000000000..cbe0f8761712eb26ffcb55c0763a439657d26382 GIT binary patch literal 224 zcmWIYbaT7Gz`)>~;#rZKT9U{DWD5ataY<2T6p)?(#1(Vqo<1$upuod=AmqsI>a9W? z4;MSlSirt}y40R`XMzIuc5HVDJTzJJs<#<~>+A;slg}-kcf*t`YRa;2Nm9+n59IDU zzp<%t>+)H#KY!0&e^+-gzw2`2{^H8qBt@XT$V@$ literal 0 HcmV?d00001 diff --git a/src/cpp/transpiler/.cache/clangd/index/lexer.cpp.83041CDDE7BB82EA.idx b/src/cpp/transpiler/.cache/clangd/index/lexer.cpp.83041CDDE7BB82EA.idx new file mode 100644 index 0000000000000000000000000000000000000000..a4c1a2a96b666bc4f86faaaafce6e6a59c4f859c GIT binary patch literal 6334 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 literal 0 HcmV?d00001 diff --git a/src/cpp/transpiler/.cache/clangd/index/lexer.h.56AED8998E88A18A.idx b/src/cpp/transpiler/.cache/clangd/index/lexer.h.56AED8998E88A18A.idx new file mode 100644 index 0000000000000000000000000000000000000000..75fe5a46993a95df258dc5729711b0c28fdfceff GIT binary patch literal 1788 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 Ow8PCL3oCOpO!t4!%wu=} literal 0 HcmV?d00001 diff --git a/src/cpp/transpiler/.cache/clangd/index/parser.h.A6B071E84CF21EB1.idx b/src/cpp/transpiler/.cache/clangd/index/parser.h.A6B071E84CF21EB1.idx new file mode 100644 index 0000000000000000000000000000000000000000..903df12b68a76d76e3c367a290a1277d50495f92 GIT binary patch literal 1870 zcmYL|e@t6d6vuC0N88sv`d&+Uw}lsKe~g-nIu&q&3tKiYfKXP3EZZVKW*J*n=je=# zZrS9=Uvpy!lW3*^0|tedk&L+n>J+UEmyA(xnK0*^WP(oE1Or5(-uLJ!O?qB?eth3K z=YFm`J1Z+oiO|;9va7wGBW3FlLVEJ`9jV%%DnlqpAyj?7v&oe!e})UrZ|8S){@LCh zEPVXhfxtpr*JOXv%=qcNW=~>w?C8ks!No>@fuUjZ;J|WV=;d!Km(mI+($%_#({5K= z-B561?yKPF{;t<+;!lmbHtjt;J8ddR@*PS}#`2xNbKXr^#huZgT;NhdUfRG+rUr6S zSbcYH@5h}lP1#4Q`fj;@ZuxO4aciw>UOU})aU?~ky(};9&OCAPmBz%wN$$^!jvcsN z*HH8Q^@VP$vgdf*+4b!|Y{+g-vnDXjf7JUfyOqJZ?Db!ix<-2bPD{VkG4Jn9;aggs zUG$%AO!#`{_JgU=q0O_;UsznS(tYEZ7J0=PwW46xMwCB)3`!3gwHwBr6qYTf^2qvLPIU&R;@ zMY&pvCE}RFf@B~(?nvNn7BD45JSHqIaDoxSZl?a25K~#9rR1dA$QgObKzL7p`*n}O z{{{&w5au|JmkflDj`ixV@~v+XaZOmE=Do6(8AB^9)<=K~UQc0;1!e)h8kPM1e|L9i zDHW-=a2CB}pnl7~^oGKBiv~%U499c4UNR8&>{i?IEvZ)(6u}*{N;Xl+L5n! zOgFt4C13Cvl7Pgp*Mr zof+_YxHB3Ct95D&Lo=A8ITre1Fi-O=AjDuyV-^Nxu#q;hFc5=Hw26g{GFYGm7Iwg3 z3vFS6QwCdUD+|ps*iPG7IAjJpXa@^pLj~zv#2N-E#W;I0uN{70Uk&uwIcYiIym|$^(yI+T1~Vj7J>{m z*bPabz+iKt`6-xybQt4|hYsOwxba5&iD(xD*yP^B(b*4Dph)m&0$s@81gp6xme(mS~4Ot{R literal 0 HcmV?d00001 diff --git a/src/cpp/transpiler/.cache/clangd/index/result.h.9FDF8FE2A27152FF.idx b/src/cpp/transpiler/.cache/clangd/index/result.h.9FDF8FE2A27152FF.idx new file mode 100644 index 0000000000000000000000000000000000000000..ff249d2aaae751b32a67939ae3f418d36ab30a32 GIT binary patch literal 616 zcmWIYbaP8!VqkDi@vO*AElFfyU|aqV&BI%FW=`dmY=GNFg)K<5b@S&Gfx>AH6{4!!Ht&AusCLL8P$1S|rK_}ZnylqfDUDap*UYT1 z_3Y|ftG{*g?7aB)x7%LM5(^GHE*?;Mp!Q4a173eUdpm~W%G{)VK-VolCz&Dm!=jXr ziJO&ygF}Er6ihI10Of$d~Bw2_So7;+r!?CiW? zf`OBX5vT;HKwHj5IZZR<5+4&6&;l-AE&(tBv!Ez7t#}7eCCnF$TwvG3j1A^=-J6># z(8tKb!O6+V5AzI+2C4@62&Nk58K5x8Coo}{CxF5rAAp?>Bw*4&VUW9F!Y~H|g+Z=` zsoLQ-wPKya^BasT9Gp^|GB6hurRF4pbQTvS7mI@!kdOhf7&sitZ>d~7sS?1*$p8Qh Cmakj@ literal 0 HcmV?d00001 diff --git a/src/cpp/transpiler/.cache/clangd/index/time.h.A5DECF25CDA82FFC.idx b/src/cpp/transpiler/.cache/clangd/index/time.h.A5DECF25CDA82FFC.idx new file mode 100644 index 0000000000000000000000000000000000000000..96863a0499b47540ca9fabc738f0a0fdbf22bcc4 GIT binary patch literal 600 zcmWIYbaM+}VqkDi@vO*AElFfyU|F2!}^^(wH`BHvTac`J=%1y`&~qO;GUyPYSm>= zoesLnWg0YJr)}8{+ZSPXHZHSxw<>e{{>lFfQ>`?W}Liwda@7@E_TD)WN|F7jomR9aK?vc=3l3aH3`7cxZ6>+C_tw}g{Jn5C@ z#_G++hjwmMzdW(;#WBtAcX*!Hr*6`YI$FoD(Q4v@;>z5lWT5Xgx$-=8{KDgS7?^=P z5a3{EW#?t!WMX9CVP)iC{k$#Q<%a9NVqOL|1_pKoeFY;9Rx?&h22P+-ZWf?|y?qH! zd`)~;@iK4$70Bz$n{cq0u~;J%FchVx6)yuSSMgIicCz@g5fcvwiwKJ*Od}5ms|c$m z%pRD77&##h0XYc>VA4Qgu=Nm8hG0(Dy}79ZeT+OD?85AlFwMOm6r}ka1ZRM3(q=J5 xvPqlO6lN4m6lf&a!B8WMQgaeP%;KWtVsQ|I!&5ir|KknPdl)&vo&t#h0RRRL%D(^r literal 0 HcmV?d00001 diff --git a/src/cpp/transpiler/.gitignore b/src/cpp/transpiler/.gitignore new file mode 100644 index 0000000..0f3a6b1 --- /dev/null +++ b/src/cpp/transpiler/.gitignore @@ -0,0 +1,2 @@ +Debug +Release diff --git a/src/cpp/transpiler/.vscode/launch.json b/src/cpp/transpiler/.vscode/launch.json new file mode 100644 index 0000000..54d9930 --- /dev/null +++ b/src/cpp/transpiler/.vscode/launch.json @@ -0,0 +1,16 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "lldb", + "name": "C/C++: gcc.exe build and debug active file", + "request": "launch", + "program": "./Debug/transpiler", + "args": ["input.mdem"], + "cwd": "${fileDirname}" + } + ] +} \ No newline at end of file diff --git a/src/cpp/transpiler/.vscode/settings.json b/src/cpp/transpiler/.vscode/settings.json new file mode 100644 index 0000000..d12d5bd --- /dev/null +++ b/src/cpp/transpiler/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "cmake.configureOnOpen": true, + "cmake.generator": "Unix Makefiles", // might use Ninja too + "cmake.buildDirectory": "${workspaceFolder}/build" +} diff --git a/src/cpp/transpiler/.vscode/tasks.json b/src/cpp/transpiler/.vscode/tasks.json new file mode 100644 index 0000000..182561b --- /dev/null +++ b/src/cpp/transpiler/.vscode/tasks.json @@ -0,0 +1,12 @@ +{ + "tasks": [ + { + "label": "Build transpiler", + "command": "cmake", + "args": [ + "--build Debug", + ], + } + ], + "version": "2.0.0" +} \ No newline at end of file diff --git a/src/cpp/transpiler/CMakeLists.txt b/src/cpp/transpiler/CMakeLists.txt new file mode 100644 index 0000000..ed250ef --- /dev/null +++ b/src/cpp/transpiler/CMakeLists.txt @@ -0,0 +1,24 @@ +cmake_minimum_required(VERSION 3.10) +project(MemoryTranspiler LANGUAGES CXX) + +# C++ standard spec +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED True) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +# Give info for intellisense +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +# Set sources +set(SOURCES + main.cpp + lexer.cpp + parser.cpp + time.cpp + api.cpp +) +include_directories(${CMAKE_SOURCE_DIR}/include) + +# Add the executable (CLI) +add_executable(transpiler ${SOURCES}) +target_compile_options(transpiler PRIVATE -Wall -Wextra -Wpedantic) diff --git a/src/cpp/transpiler/api.cpp b/src/cpp/transpiler/api.cpp new file mode 100644 index 0000000..bbcc7c1 --- /dev/null +++ b/src/cpp/transpiler/api.cpp @@ -0,0 +1,43 @@ +#include +#include + +#include "api.h" +#include "result.h" +#include "lexer.h" +#include "parser.h" +#include "time.h" + +Result> Transpile(std::string fileContent) { + start = std::chrono::high_resolution_clock::now(); + auto lexRes = TokenizeMdem(fileContent); + auto tokens = lexRes.value; + if (lexRes.error.length() > 0) { + return { + {}, + std::format( + "Lexical analysis error: {}", + lexRes.error + ), + lexRes.row, + lexRes.column + }; + } + + auto parseRes = ParseQuestions(tokens); + auto questions = parseRes.value; + if (parseRes.error.length() > 0) { + return { + {}, + std::format( + "Parsing error: {}", + parseRes.error + ), + parseRes.row, + parseRes.column + }; + } + + end = std::chrono::high_resolution_clock::now(); + ShowTime("Transpilation time"); + return {questions}; +} diff --git a/src/cpp/transpiler/api.h b/src/cpp/transpiler/api.h new file mode 100644 index 0000000..d5c75c1 --- /dev/null +++ b/src/cpp/transpiler/api.h @@ -0,0 +1,4 @@ +#include "result.h" +#include "parser.h" + +Result> Transpile(std::string fileContent); diff --git a/src/cpp/transpiler/compile_commands.json b/src/cpp/transpiler/compile_commands.json new file mode 100644 index 0000000..8e57e25 --- /dev/null +++ b/src/cpp/transpiler/compile_commands.json @@ -0,0 +1,20 @@ +[ +{ + "directory": "/home/jorenchik/Code/mdemory/src/cpp/transpiler/Debug", + "command": "/usr/bin/g++ -I/home/jorenchik/Code/mdemory/src/cpp/transpiler/include -g -std=gnu++20 -Wall -Wextra -Wpedantic -o CMakeFiles/transpiler.dir/main.cpp.o -c /home/jorenchik/Code/mdemory/src/cpp/transpiler/main.cpp", + "file": "/home/jorenchik/Code/mdemory/src/cpp/transpiler/main.cpp", + "output": "CMakeFiles/transpiler.dir/main.cpp.o" +}, +{ + "directory": "/home/jorenchik/Code/mdemory/src/cpp/transpiler/Debug", + "command": "/usr/bin/g++ -I/home/jorenchik/Code/mdemory/src/cpp/transpiler/include -g -std=gnu++20 -Wall -Wextra -Wpedantic -o CMakeFiles/transpiler.dir/lexer.cpp.o -c /home/jorenchik/Code/mdemory/src/cpp/transpiler/lexer.cpp", + "file": "/home/jorenchik/Code/mdemory/src/cpp/transpiler/lexer.cpp", + "output": "CMakeFiles/transpiler.dir/lexer.cpp.o" +}, +{ + "directory": "/home/jorenchik/Code/mdemory/src/cpp/transpiler/Debug", + "command": "/usr/bin/g++ -I/home/jorenchik/Code/mdemory/src/cpp/transpiler/include -g -std=gnu++20 -Wall -Wextra -Wpedantic -o CMakeFiles/transpiler.dir/parser.cpp.o -c /home/jorenchik/Code/mdemory/src/cpp/transpiler/parser.cpp", + "file": "/home/jorenchik/Code/mdemory/src/cpp/transpiler/parser.cpp", + "output": "CMakeFiles/transpiler.dir/parser.cpp.o" +} +] \ No newline at end of file diff --git a/src/cpp/transpiler/config.h b/src/cpp/transpiler/config.h new file mode 100644 index 0000000..58f8154 --- /dev/null +++ b/src/cpp/transpiler/config.h @@ -0,0 +1,4 @@ +#pragma once + +extern bool debug; + diff --git a/src/cpp/transpiler/lexer.cpp b/src/cpp/transpiler/lexer.cpp new file mode 100644 index 0000000..81446fd --- /dev/null +++ b/src/cpp/transpiler/lexer.cpp @@ -0,0 +1,284 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "lexer.h" +#include "config.h" +#include "result.h" + +std::vector tokens; +std::vector buffer; +int32_t row; +int32_t column; +int32_t previousRow; +int32_t previousColumn; +bool textStarted = false; +bool identifierStarted = false; + +void trimString(std::string &str, std::string trimChars) { + int padSize = 0; + bool pad = false; + for (size_t i = 0; i < str.size(); ++i) { + for (size_t k = 0; k < trimChars.size(); ++k) { + if (str[i] == trimChars[k]) { + padSize++; + pad = true; + break; + } + } + if (!pad) { + break; + } + pad = false; + } + if (padSize > 0) { + str.erase(0, padSize); + } + padSize = 0; + pad = false; + for (size_t i = str.size(); i-- > 0;) { + for (size_t k = 0; k < trimChars.size(); ++k) { + if (str[i] == trimChars[k]) { + padSize++; + pad = true; + break; + } + } + if (!pad) { + break; + } + pad = false; + } + if (padSize > 0) { + str.erase(str.end() - padSize, str.end()); + } +} + +void makeTokenWithTokenBuffer( + TokenType ttype, + size_t tokenLen, + TokenType textType +) { + std::string token(buffer.end() - tokenLen, buffer.end()); + if (buffer.size() > tokenLen) { + std::string prevFragment(buffer.begin(), buffer.end() - tokenLen); + trimString(prevFragment, " \n\t"); + if (prevFragment.length() > 0) { + tokens.push_back(Token{ + textType, + prevFragment, + previousRow, + previousColumn + }); + } + } + buffer.clear(); + + tokens.push_back(Token{ + ttype, + token, + row, + column + }); + + previousRow = row; + previousColumn = column; + buffer.clear(); +} + +Result> TokenizeMdem(const std::string& fileRunes) { + row = 1; + column = 1; + previousRow = 1; + previousColumn = 1; + textStarted = false; + tokens.clear(); + buffer.clear(); + + if (fileRunes.find_first_not_of(" \n\t") == std::string::npos) { + return {tokens, ""}; + } + + for (size_t i = 0; i < fileRunes.size(); ++i) { + char c = fileRunes[i]; + + // AdvancePointer + if (c == '\n') { + row += 1; + column = 0; + } + buffer.push_back(c); + + // SkipWhitetext + if (!textStarted) { + if (c == '\n') { + previousRow += 1; + previousColumn = 1; + } else if (c == ' ') { + previousColumn += 1; + } else if (c == '\t') { + previousColumn += 4; + } else { + textStarted = true; + } + } + + // EmitTokens + switch (c) { + case '[': + makeTokenWithTokenBuffer( + TokenType::IdentifierStart, + 1, + TokenType::TextFragment + ); + previousRow = row; + previousColumn = column; + textStarted = false; + identifierStarted = true; + break; + case ']': + if (!identifierStarted) { + return { + tokens, + "Cannot end identifier if it is not started", + tokens[i].row, + tokens[i].column + }; + } + makeTokenWithTokenBuffer( + TokenType::IdentifierEnd, + 1, + TokenType::Identifier + ); + previousRow = row; + previousColumn = column; + textStarted = false; + identifierStarted = false; + break; + case '#': + makeTokenWithTokenBuffer( + TokenType::SectionIdentifierStart, + 1, + TokenType::TextFragment + ); + previousRow = row; + previousColumn = column; + textStarted = false; + break; + case '{': + makeTokenWithTokenBuffer( + TokenType::SectionStart, + 1, + TokenType::Identifier + ); + previousRow = row; + previousColumn = column; + textStarted = false; + break; + case '}': + makeTokenWithTokenBuffer( + TokenType::SectionEnd, + 1, + TokenType::TextFragment + ); + previousRow = row; + previousColumn = column; + textStarted = false; + break; + case '-': + makeTokenWithTokenBuffer( + TokenType::ElementDashStart, + 1, + TokenType::TextFragment + ); + previousRow = row; + previousColumn = column; + textStarted = false; + break; + case '>': + makeTokenWithTokenBuffer( + TokenType::QuestionEnd, + 1, + TokenType::TextFragment + ); + previousRow = row; + previousColumn = column; + break; + case '+': + makeTokenWithTokenBuffer( + TokenType::ElementPlusStart, + 1, + TokenType::TextFragment + ); + previousRow = row; + previousColumn = column; + textStarted = false; + break; + } + + column += 1; + } + + makeTokenWithTokenBuffer( + TokenType::EndOfFile, + 0, + TokenType::TextFragment + ); + + if (debug) { + std::cout << "SECTION: Lexer output:\n"; + std::cout << std::format("Token count: {}", tokens.size()) << std::endl; + for (const Token& token : tokens) { + std::cout << token.ToString(); + } + std::cout << "SECTION END: Lexer output\n"; + } + + return {tokens, ""}; +} + +std::regex nextLineExp( + "\n", + std::regex_constants::ECMAScript +); + +std::regex doubleSpaceExp( + "\\s\\s+", + std::regex_constants::ECMAScript +); + +std::string Token::ToString(const TokenType* ttype) { + switch (*ttype) { + case TokenType::TextFragment: return "text fragment"; + case TokenType::QuestionEnd: return "question end symbol"; + case TokenType::ElementDashStart: return "dash element start"; + case TokenType::ElementPlusStart: return "plus element start"; + case TokenType::Identifier: return "identifier"; + case TokenType::IdentifierStart: return "start of identifier"; + case TokenType::IdentifierEnd: return "end of identifier"; + case TokenType::SectionIdentifierStart: return "section identifier start"; + case TokenType::SectionStart: return "start of section"; + case TokenType::SectionEnd: return "end of section"; + case TokenType::EndOfFile: return "end of file"; + default: return "unrecognized token"; + } +} + +std::string Token::ToString() const { + std::string contentStr = content; + if (tokenType == TokenType::TextFragment) { + contentStr = std::regex_replace(contentStr, nextLineExp, ""); + contentStr = std::regex_replace(contentStr, doubleSpaceExp, " "); + } + return std::format( + "{}: \"{}\" ({}:{})\n", + ToString(&tokenType), + contentStr, + row, + column + ); +} diff --git a/src/cpp/transpiler/lexer.h b/src/cpp/transpiler/lexer.h new file mode 100644 index 0000000..10cebb1 --- /dev/null +++ b/src/cpp/transpiler/lexer.h @@ -0,0 +1,33 @@ +#pragma once + +#include +#include + +#include "result.h" + +enum class TokenType { + TextFragment, + QuestionEnd, + ElementDashStart, + ElementPlusStart, + Identifier, + IdentifierStart, + IdentifierEnd, + SectionIdentifierStart, + SectionStart, + SectionEnd, + SOF, + EndOfFile +}; + +struct Token { + TokenType tokenType; + std::string content; + int32_t row; + int32_t column; + + std::string ToString() const; + static std::string ToString(const TokenType* ttype); +}; + +Result> TokenizeMdem(const std::string& fileRunes); diff --git a/src/cpp/transpiler/main.cpp b/src/cpp/transpiler/main.cpp new file mode 100644 index 0000000..424cd6b --- /dev/null +++ b/src/cpp/transpiler/main.cpp @@ -0,0 +1,82 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "api.h" +#include "parser.h" +#include "time.h" +#include "config.h" + +std::string readFile(const std::string& filePath) { + std::ifstream file(filePath); + if (!file.is_open()) { + throw std::runtime_error("Cannot open file: " + filePath); + } + + std::string content; + std::string line; + while (std::getline(file, line)) { + content += line + '\n'; + } + + file.close(); + return content; +} + +bool debug = false; + +std::chrono::high_resolution_clock::time_point start; +std::chrono::high_resolution_clock::time_point end; + +int main(int argc, char* argv[]) { + std::string filePath; + + if (argc == 3) { + auto option = std::string(argv[1]); + if (option == "--debug") { + debug = true; + } else { + std::cout << std::format("Unrecognized option: {}", option) << std::endl; + return 1; + } + filePath = argv[2]; + } else if (argc == 2) { + filePath = argv[1]; + } else { + std::cerr << "Usage: " << argv[0] << " \n"; + return 1; + } + + try { + start = std::chrono::high_resolution_clock::now(); + std::string fileContent = readFile(filePath); + end = std::chrono::high_resolution_clock::now(); + ShowTime("I/O time"); + + auto res = Transpile(fileContent); + auto questions = res.value; + if (res.error.length() > 0) { + std::cout << std::format( + "{} ({}:{})\n", + res.error, + res.row, + res.column + ); + return 1; + } + + for (Question* question: questions) { + delete question; + } + + } catch (std::exception &e) { + std::cout << e.what() << std::endl; + return 1; + } + + return 0; +} diff --git a/src/cpp/transpiler/parser.cpp b/src/cpp/transpiler/parser.cpp new file mode 100644 index 0000000..0ab7607 --- /dev/null +++ b/src/cpp/transpiler/parser.cpp @@ -0,0 +1,278 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "config.h" +#include "lexer.h" +#include "result.h" +#include "parser.h" + +struct QuestionElement { + bool isDash; + std::string content; +}; + +std::string SingleAnswerQuestion::ToString() const { + return std::format( + ":{} section:{} id:{} answer:{}", + QuestionText, + Section, + ID, + Answer + ); +} + +std::string MultipleChoiceQuestion::ToString() const { + std::stringstream choiceOut; + for (const auto& choice : Choices) { + char opener; + if (choice.IsCorrect) { + opener = '+'; + } else { + opener = '-'; + } + choiceOut << opener << " " << choice.Answer << "; "; + } + return std::format( + ":{} section: {} id: {}\n{}", + QuestionText, + Section, + ID, + choiceOut.str() + ); +} + +// Automaton for validating token transitions +std::map> automata; + +bool contains(const std::vector& vec, TokenType element) { + return std::find(vec.begin(), vec.end(), element) != vec.end(); +} + +// Automata for validating the parser state +std::map> parserAutomata() { + std::map> automata; + automata[TokenType::TextFragment] = { + TokenType::QuestionEnd, + TokenType::ElementDashStart, + TokenType::ElementPlusStart, + TokenType::SectionIdentifierStart, + TokenType::SectionStart, + TokenType::EndOfFile, + TokenType::SectionEnd + }; + automata[TokenType::QuestionEnd] = { + TokenType::ElementDashStart, + TokenType::ElementPlusStart + }; + automata[TokenType::ElementDashStart] = { + TokenType::IdentifierStart, + TokenType::TextFragment + }; + automata[TokenType::ElementPlusStart] = { + TokenType::TextFragment + }; + automata[TokenType::Identifier] = { + TokenType::IdentifierEnd, + TokenType::SectionStart + }; + automata[TokenType::IdentifierStart] = { + TokenType::Identifier + }; + automata[TokenType::IdentifierEnd] = { + TokenType::TextFragment + }; + automata[TokenType::SectionIdentifierStart] = { + TokenType::Identifier + }; + automata[TokenType::SectionStart] = { + TokenType::ElementDashStart, + TokenType::SectionIdentifierStart, + TokenType::EndOfFile + }; + automata[TokenType::SectionEnd] = { + TokenType::SectionIdentifierStart, + TokenType::ElementDashStart, + TokenType::EndOfFile + }; + automata[TokenType::SOF] = { + TokenType::ElementDashStart, + TokenType::SectionIdentifierStart, + TokenType::EndOfFile + }; + automata[TokenType::EndOfFile] = {}; + return automata; +} + +std::string capitalize(const std::string& str) { + if (str.empty()) return str; + std::string result = str; + result[0] = std::towupper(result[0]); + return result; +} + +Result ValidateGrammar(const std::vector& tokens) { + automata = parserAutomata(); + for (size_t i = 0; i < tokens.size() - 1; ++i) { + Token token = tokens[i]; + Token nextToken = tokens[i + 1]; + if (!contains(automata[token.tokenType], nextToken.tokenType)) { + return { + .error=std::format( + "Invalid token sequence: {} cannot precede {}", + std::string(capitalize(Token::ToString(&token.tokenType))), + std::string(capitalize(Token::ToString(&nextToken.tokenType))) + ), + .row=token.row, + .column=token.column + }; + } + } + return {}; +} + +Result> ParseQuestions(const std::vector& tokens) { + auto questions = std::vector(); + + auto result = ValidateGrammar(tokens); + if (result.error.length() > 0) { + return { + questions, + result.error, + result.row, + result.column + }; + } + + std::string section; + size_t i = 0; + + if (debug) { + std::cout << "SECTION: Parser output:\n"; + } + while (i < tokens.size()) { + if (tokens[i].tokenType == TokenType::ElementDashStart) { + + std::string id, questionText; + std::vector questionElements; + // Parsing for a single question or multiple choice question + if (tokens[i + 1].tokenType == TokenType::IdentifierStart) { + id = tokens[i + 2].content; + questionText = tokens[i + 4].content; + i += 6; + } else { + id = ""; + questionText = tokens[i + 1].content; + i += 3; + } + + while (true) { + if (i + 3 < tokens.size() && tokens[i + 3].tokenType != TokenType::EndOfFile) { + size_t offset = tokens[i + 1].tokenType == TokenType::IdentifierStart ? 5 : 2; + if (tokens[i].tokenType == TokenType::SectionIdentifierStart || + tokens[i].tokenType == TokenType::SectionEnd) { + break; + } + if (i + offset < tokens.size() && tokens[i + offset].tokenType == TokenType::QuestionEnd) { + break; + } + if (offset == 5 && tokens[i + 5].tokenType != TokenType::QuestionEnd) { + return { + questions, + "Invalid identifier placement", + tokens[i].row, + tokens[i].column + }; + } + } + if (i + 2 >= tokens.size()) { + break; + } + + // Create question elements + QuestionElement questionElement; + questionElement.isDash = (tokens[i].tokenType == TokenType::ElementDashStart); + questionElement.content = tokens[i + 1].content; + questionElements.push_back(questionElement); + i += 2; + } + + if (questionElements.size() > 1) { + auto* mcq = new MultipleChoiceQuestion(); + mcq->ID = id; + mcq->QuestionText = questionText; + for (const auto& elem : questionElements) { + Choice choice; + choice.Answer = elem.content; + choice.IsCorrect = !elem.isDash; + mcq->Choices.push_back(choice); + } + mcq->Section = section; + questions.push_back(mcq); + if (debug) { + std::cout << mcq->ToString() << "\n"; + } + } else if (questionElements.size() == 1) { + auto* saq = new SingleAnswerQuestion(); + saq->ID = id; + saq->QuestionText = questionText; + saq->Answer = questionElements[0].content; + saq->Section = section; + questions.push_back(saq); + if (debug) { + std::cout << saq->ToString() << "\n"; + } + } + } else if (tokens[i].tokenType == TokenType::SectionIdentifierStart) { + if (section.length() > 0) { + return { + questions, + std::format("Section \"{}\" is not closed, cannot open other section", section), + tokens[i].row, + tokens[i].column + }; + } + section = tokens[i + 1].content; + i += 3; + if (debug) { + std::cout << "Started section: " << section << "\n"; + } + } else if (tokens[i].tokenType == TokenType::SectionEnd) { + if (section.length() <= 0) { + return { + questions, + std::format("Cannot close section, no section was opened", section), + tokens[i].row, + tokens[i].column + }; + } + section.clear(); + i += 1; + if (debug) { + std::cout << "Section ended.\n"; + } + } else if (tokens[i].tokenType == TokenType::EndOfFile) { + if (debug) { + std::cout << "File terminated: EndOfFile\n"; + } + break; + } else { + return { + questions, + "Unexpected token encountered", + tokens[i].row, + tokens[i].column + }; + } + } + + if (debug) { + std::cout << "SECTION END: Parser output:\n"; + } + return {questions, ""}; +} diff --git a/src/cpp/transpiler/parser.h b/src/cpp/transpiler/parser.h new file mode 100644 index 0000000..022afec --- /dev/null +++ b/src/cpp/transpiler/parser.h @@ -0,0 +1,43 @@ +#pragma once + +#include +#include + +#include "lexer.h" +#include "result.h" + +class Question { +public: + virtual std::string ToString() const = 0; + virtual ~Question() = default; +}; + +// Choice struct for Multiple Choice Questions +struct Choice { + std::string Answer; + bool IsCorrect; +}; + +class SingleAnswerQuestion : public Question { +public: + std::string ID; + std::string QuestionText; + std::string Answer; + std::string Section; + + // Override ToString method + std::string ToString() const override; +}; + +class MultipleChoiceQuestion : public Question { +public: + std::string ID; + std::string QuestionText; + std::vector Choices; + std::string Section; + + // Override ToString method + std::string ToString() const override; +}; + +Result> ParseQuestions(const std::vector& tokens); diff --git a/src/cpp/transpiler/result.h b/src/cpp/transpiler/result.h new file mode 100644 index 0000000..06cdf0c --- /dev/null +++ b/src/cpp/transpiler/result.h @@ -0,0 +1,13 @@ +#pragma once + +#include + +struct NoneType {}; + +template +struct Result { + T value; + std::string error = ""; + int row = -1; + int column = -1; +}; diff --git a/src/cpp/transpiler/time.cpp b/src/cpp/transpiler/time.cpp new file mode 100644 index 0000000..bdcc551 --- /dev/null +++ b/src/cpp/transpiler/time.cpp @@ -0,0 +1,10 @@ +#include +#include + +#include "time.h" + +void ShowTime(std::string label) { + auto duration = std::chrono::duration_cast(end - start); + double_t msDuration = (double_t) duration.count() / 1000; + std::cout << std::format("{}: {:.3f} ms", label, msDuration) << std::endl; +} diff --git a/src/cpp/transpiler/time.h b/src/cpp/transpiler/time.h new file mode 100644 index 0000000..9bfbd75 --- /dev/null +++ b/src/cpp/transpiler/time.h @@ -0,0 +1,8 @@ +#pragma once + +#include + +extern std::chrono::high_resolution_clock::time_point start; +extern std::chrono::high_resolution_clock::time_point end; + +void ShowTime(std::string label); diff --git a/src/compiler/.gitignore b/src/go/compiler/.gitignore similarity index 100% rename from src/compiler/.gitignore rename to src/go/compiler/.gitignore diff --git a/src/compiler/api/api.go b/src/go/compiler/api/api.go similarity index 100% rename from src/compiler/api/api.go rename to src/go/compiler/api/api.go diff --git a/src/compiler/comperror/comperror.go b/src/go/compiler/comperror/comperror.go similarity index 100% rename from src/compiler/comperror/comperror.go rename to src/go/compiler/comperror/comperror.go diff --git a/src/compiler/compiler.go b/src/go/compiler/compiler.go similarity index 100% rename from src/compiler/compiler.go rename to src/go/compiler/compiler.go diff --git a/src/compiler/deck.moml b/src/go/compiler/deck.moml similarity index 100% rename from src/compiler/deck.moml rename to src/go/compiler/deck.moml diff --git a/src/compiler/go.mod b/src/go/compiler/go.mod similarity index 100% rename from src/compiler/go.mod rename to src/go/compiler/go.mod diff --git a/src/compiler/go.sum b/src/go/compiler/go.sum similarity index 100% rename from src/compiler/go.sum rename to src/go/compiler/go.sum diff --git a/src/compiler/lexer/lexer.go b/src/go/compiler/lexer/lexer.go similarity index 100% rename from src/compiler/lexer/lexer.go rename to src/go/compiler/lexer/lexer.go diff --git a/src/compiler/parser/parser.go b/src/go/compiler/parser/parser.go similarity index 100% rename from src/compiler/parser/parser.go rename to src/go/compiler/parser/parser.go diff --git a/src/mdemory-app-qt/.gitignore b/src/go/mdemory-app-qt/.gitignore similarity index 100% rename from src/mdemory-app-qt/.gitignore rename to src/go/mdemory-app-qt/.gitignore diff --git a/src/mdemory-app-qt/.vscode/launch.json b/src/go/mdemory-app-qt/.vscode/launch.json similarity index 100% rename from src/mdemory-app-qt/.vscode/launch.json rename to src/go/mdemory-app-qt/.vscode/launch.json diff --git a/src/mdemory-app-qt/go.mod b/src/go/mdemory-app-qt/go.mod similarity index 100% rename from src/mdemory-app-qt/go.mod rename to src/go/mdemory-app-qt/go.mod diff --git a/src/mdemory-app-qt/go.sum b/src/go/mdemory-app-qt/go.sum similarity index 100% rename from src/mdemory-app-qt/go.sum rename to src/go/mdemory-app-qt/go.sum diff --git a/src/mdemory-app-qt/main b/src/go/mdemory-app-qt/main similarity index 100% rename from src/mdemory-app-qt/main rename to src/go/mdemory-app-qt/main diff --git a/src/mdemory-app-qt/main.go b/src/go/mdemory-app-qt/main.go similarity index 100% rename from src/mdemory-app-qt/main.go rename to src/go/mdemory-app-qt/main.go