199 lines
6.6 KiB
C++
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();
|
|
}
|