ZRCola/ZRColaCompile/parse.cpp
Simon Rozman 47d3884af3 Update Copyright and build year
Signed-off-by: Simon Rozman <simon@rozman.si>
2022-01-07 11:38:32 +01:00

199 lines
6.6 KiB
C++

/*
SPDX-License-Identifier: GPL-3.0-or-later
Copyright © 2018-2022 Amebis
*/
#include "pch.h"
using namespace std;
using namespace stdex;
using namespace winstd;
//////////////////////////////////////////////////////////////////////////
// ZRCola::DecompParser
//////////////////////////////////////////////////////////////////////////
ZRCola::DecompParser::DecompParser(_In_ const std::wstring &decomposed) : m_decomposed(decomposed)
{
if (m_decomposed.empty()) {
m_sym = 0;
m_idx = 0;
} else {
m_sym = m_decomposed[0];
m_idx = 1;
}
}
void ZRCola::DecompParser::ParsePrefixes(_Inout_ std::vector<wchar_t> &prefix)
{
for (;;) {
if (
m_sym == 0x203F || // Undertie
0xE0F0 <= m_sym && m_sym <= 0xE0F3 || // 1st Set of Prefix Modifiers
m_sym == 0xE0F6 || // Above
m_sym == 0xE0F7 || // Below
0xE0F8 <= m_sym && m_sym <= 0xE0FC) // 2nd Set of Prefix Modifiers
{
// Prefix modifier
prefix.push_back(m_sym);
NextChar();
} else
break;
}
}
void ZRCola::DecompParser::ParseModifiers(_Inout_ std::vector<wchar_t> &mod)
{
for (;;) {
if (0xE000 <= m_sym && m_sym <= 0xE05B || // 1st Set of Modifiers
0xE063 <= m_sym && m_sym <= 0xE0BE || // 2nd Set of Modifiers
m_sym == 0x0023 || // Number Sign
m_sym == 0x003A || // Colon
m_sym == 0x02DE || // Rhotic Hook
m_sym == 0x2019 || // Right Single Quotation Mark
0x02B0 <= m_sym && m_sym <= 0x02FF || // Standard Unicode Modifiers
m_sym == 0xE0C0 || // Circle
m_sym == 0xE0C2 || // Square
m_sym == 0xE0CA || // Diamond
m_sym == 0xE0CD) // Not Circle
{
mod.push_back(m_sym);
NextChar();
} else
break;
}
}
ZRCola::DecompParser::Expression* ZRCola::DecompParser::ParseParentheses(_In_ wchar_t open, _In_ wchar_t close)
{
if (m_sym == open) {
// Parenthesis Start
NextChar();
if (m_sym == 0xE037) {
// EVA Parenthesis End
unique_ptr<Character> res(new Character(close));
NextChar();
return res.release();
} else {
unique_ptr<Parentheses> res(new Parentheses(open, close, ParseExpression()));
if (m_sym == close) {
// Parenthesis End
NextChar();
} else if (m_sym == open && m_idx < m_decomposed.length() && m_decomposed[m_idx] == 0xE037) {
// Decomposed Parenthesis End
NextChar();
NextChar();
} else
throw invalid_argument(string_printf("%lc is unexpected. Should end with %lc.", m_sym, close));
return res.release();
}
} else
return NULL;
}
ZRCola::DecompParser::Expression* ZRCola::DecompParser::ParseCharacter()
{
Expression *res_p;
if ((res_p = ParseParentheses(0xE0C5, 0xE0C6)) != NULL || // Superscript
(res_p = ParseParentheses(0xE0CE, 0xE0CF)) != NULL || // Subscript
(res_p = ParseParentheses(0xE2E0, 0xE2E1)) != NULL || // EVA Double
(res_p = ParseParentheses(0xE2E2, 0xE2E3)) != NULL || // EVA Condensed
(res_p = ParseParentheses(0xE2E4, 0xE2E5)) != NULL || // EVA Emphasis
(res_p = ParseParentheses(0xE2E6, 0xE2E7)) != NULL || // EVA Strike
(res_p = ParseParentheses(0xE2E8, 0xE2E9)) != NULL || // EVA Undeal
(res_p = ParseParentheses(0xE2EA, 0xE2EB)) != NULL || // EVA Italic
(res_p = ParseParentheses(0xE2EC, 0xE2ED)) != NULL || // EVA Superscript
(res_p = ParseParentheses(0xE2EE, 0xE2EF)) != NULL) // EVA Subscript
{
return res_p;
}
unique_ptr<Character> res(new Character());
ParsePrefixes(res->m_prefix);
if (m_sym < 0xE000 || 0xE0FC < m_sym ||
m_sym == 0xE0D6 || // Clockwise Top Semicircle Arrow
m_sym == 0xE0D7) // Anticlockwise Top Semicircle Arrow
{
// Base Character
res->m_char = m_sym;
NextChar();
}
ParseModifiers(res->m_mod);
return res.release();
}
ZRCola::DecompParser::Expression* ZRCola::DecompParser::ParseTerm()
{
unique_ptr<Ligature> res(new Ligature(ParseCharacter()));
while (m_sym == 0xE0C4) {
// Ligature
std::unique_ptr<Ligature::Element> res2(new Ligature::Element(m_sym));
NextChar();
ParseModifiers(res2->m_mod);
res2->m_el.reset(ParseCharacter());
res->m_rest.push_back(std::move(res2));
}
if (res->m_rest.empty()) {
// A ligature of, well one single character, is rather a character alone.
return res->m_first.release();
} else
return res.release();
}
ZRCola::DecompParser::Expression* ZRCola::DecompParser::ParseExpression()
{
unique_ptr<Expression> res(ParseTerm());
if (0xE05C <= m_sym && m_sym <= 0xE062 ||
m_sym == 0xE0C1 || // Two Characters in Circle
m_sym == 0xE0C3 || // Two Characters in Square
m_sym == 0xE0C7 || // Breved below
m_sym == 0xE0CB || // Inverse tilded
m_sym == 0xE0CC || // Diagonally Barred
0xE0D0 <= m_sym && m_sym <= 0xE0D5)
{
// Joiner of two terms
unique_ptr<Joined2> res_j(new Joined2(m_sym, res.release()));
NextChar();
ParseModifiers(res_j->m_mod);
res_j->m_second.reset(ParseTerm());
return res_j.release();
} else if (
m_sym == 0xE0C8 || // Inverse breved
m_sym == 0xE0C9) // Breved below
{
// Joiner of three terms
unique_ptr<Joined3> res_j(new Joined3(m_sym, res.release()));
NextChar();
ParseModifiers(res_j->m_mod);
res_j->m_second.reset(ParseTerm());
res_j->m_third.reset(ParseTerm());
return res_j.release();
} else
return res.release();
}
ZRCola::DecompParser::Expression* ZRCola::DecompParser::Parse()
{
unique_ptr<Expression> res(ParseExpression());
if (m_sym)
throw invalid_argument("Unexpected trailing character(s).");
return res.release();
}