summaryrefslogtreecommitdiff
path: root/src/ast
diff options
context:
space:
mode:
Diffstat (limited to 'src/ast')
-rw-r--r--src/ast/npc.cpp55
-rw-r--r--src/ast/npc.hpp11
-rw-r--r--src/ast/npc_test.cpp68
-rw-r--r--src/ast/quest.cpp125
-rw-r--r--src/ast/quest.hpp65
5 files changed, 202 insertions, 122 deletions
diff --git a/src/ast/npc.cpp b/src/ast/npc.cpp
index e9c3464..8d4a43e 100644
--- a/src/ast/npc.cpp
+++ b/src/ast/npc.cpp
@@ -306,7 +306,7 @@ namespace npc
static
Result<ScriptNone> parse_script_none_head(io::LineSpan span, std::vector<Spanned<std::vector<Spanned<RString>>>>& bits)
{
- // ScriptNone: -|script|script name|-1{code}
+ // ScriptNone: -|script|script name|32767{code}
if (bits.size() != 4)
{
return Err(span.error_str("expect 4 |component|s"_s));
@@ -319,10 +319,10 @@ namespace npc
{
return Err(bits[2].span.error_str("in |component 3| expect 1 ,component,s"_s));
}
- assert(bits[3].data[0].data == "-1"_s);
+ assert(bits[3].data[0].data == "32767"_s);
if (bits[3].data.size() != 1)
{
- return Err(bits[3].span.error_str("in |component 4| should be just -1"_s));
+ return Err(bits[3].span.error_str("in |component 4| should be just 32767"_s));
}
ScriptNone script_none;
@@ -333,39 +333,6 @@ namespace npc
return Ok(std::move(script_none));
}
static
- Result<ScriptMapNone> parse_script_map_none_head(io::LineSpan span, std::vector<Spanned<std::vector<Spanned<RString>>>>& bits)
- {
- // ScriptMapNone: m,x,y,d|script|script name|-1{code}
- if (bits.size() != 4)
- {
- return Err(span.error_str("expect 4 |component|s"_s));
- }
- if (bits[0].data.size() != 4)
- {
- return Err(bits[0].span.error_str("in |component 1| expect 3 ,component,s"_s));
- }
- assert(bits[1].data.size() == 1);
- assert(bits[1].data[0].data == "script"_s);
- if (bits[2].data.size() != 1)
- {
- return Err(bits[2].span.error_str("in |component 3| expect 1 ,component,s"_s));
- }
- if (bits[3].data.size() != 1 || bits[3].data[0].data != "-1"_s)
- {
- return Err(bits[3].span.error_str("in |component 4| should be just -1"_s));
- }
-
- ScriptMapNone script_map_none;
- TRY_EXTRACT(bits[0].data[0], script_map_none.m);
- TRY_EXTRACT(bits[0].data[1], script_map_none.x);
- TRY_EXTRACT(bits[0].data[2], script_map_none.y);
- TRY_EXTRACT(bits[0].data[3], script_map_none.d);
- TRY_EXTRACT(bits[2].data[0], script_map_none.name);
- script_map_none.key4_span = bits[3].data[0].span;
- // also expect '{' and parse real script (in caller)
- return Ok(std::move(script_map_none));
- }
- static
Result<ScriptMap> parse_script_map_head(io::LineSpan span, std::vector<Spanned<std::vector<Spanned<RString>>>>& bits)
{
// ScriptMap: m,x,y,d|script|script name|class,xs,ys{code}
@@ -417,10 +384,9 @@ namespace npc
static
Result<Script> parse_script_any(io::LineSpan span, std::vector<Spanned<std::vector<Spanned<RString>>>>& bits, io::LineCharReader& lr)
{
- // 4 cases:
+ // 3 cases:
// ScriptFunction: function|script|Fun Name{code}
- // ScriptNone: -|script|script name|-1{code}
- // ScriptMapNone: m,x,y,d|script|script name|-1{code}
+ // ScriptNone: -|script|script name|32767{code}
// ScriptMap: m,x,y,d|script|script name|class,xs,ys{code}
if (bits[0].data[0].data == "function"_s)
{
@@ -445,17 +411,6 @@ namespace npc
rv.body = TRY(ast::script::parse_script_body(lr, opt));
return Ok(std::move(rv));
}
- else if (bits.size() >= 4 && bits[3].data[0].data == "-1"_s)
- {
- Script rv = TRY(parse_script_map_none_head(span, bits));
- rv.key_span = bits[1].data[0].span;
-
- ast::script::ScriptOptions opt;
- opt.implicit_start = true;
- opt.no_start = true;
- rv.body = TRY(ast::script::parse_script_body(lr, opt));
- return Ok(std::move(rv));
- }
else
{
ScriptMap script_map = TRY(parse_script_map_head(span, bits));
diff --git a/src/ast/npc.hpp b/src/ast/npc.hpp
index a51acd3..ca6479e 100644
--- a/src/ast/npc.hpp
+++ b/src/ast/npc.hpp
@@ -103,14 +103,6 @@ namespace npc
Spanned<NpcName> name;
io::LineSpan key4_span;
};
- struct ScriptMapNone
- {
- Spanned<MapName> m;
- Spanned<unsigned> x, y;
- Spanned<DIR> d;
- Spanned<NpcName> name;
- io::LineSpan key4_span;
- };
struct ScriptMap
{
Spanned<MapName> m;
@@ -120,13 +112,12 @@ namespace npc
Spanned<Species> npc_class;
Spanned<unsigned> xs, ys;
};
- using ScriptBase = Variant<ScriptFunction, ScriptNone, ScriptMapNone, ScriptMap>;
+ using ScriptBase = Variant<ScriptFunction, ScriptNone, ScriptMap>;
struct Script : ScriptBase
{
Script() = default;
Script(ScriptFunction s) : ScriptBase(std::move(s)) {}
Script(ScriptNone s) : ScriptBase(std::move(s)) {}
- Script(ScriptMapNone s) : ScriptBase(std::move(s)) {}
Script(ScriptMap s) : ScriptBase(std::move(s)) {}
io::LineSpan key_span;
diff --git a/src/ast/npc_test.cpp b/src/ast/npc_test.cpp
index a753623..dadeba7 100644
--- a/src/ast/npc_test.cpp
+++ b/src/ast/npc_test.cpp
@@ -423,11 +423,11 @@ namespace npc
{
// 1 2 3
//23456789012345678901234567890123456789
- "-|script|#config|-1{end;}"_s,
+ "-|script|#config|32767{end;}"_s,
// 123456
- "-|script|#config|-1\n{end;}\n"_s,
+ "-|script|#config|32767\n{end;}\n"_s,
// 1234567
- "-|script|#config|-1\n \n {end;} "_s,
+ "-|script|#config|32767\n \n {end;} "_s,
};
for (auto input : inputs)
{
@@ -435,7 +435,7 @@ namespace npc
auto res = TRY_UNWRAP(parse_top(lr), FAIL());
EXPECT_TRUE(res.get_success().is_some());
auto top = TRY_UNWRAP(std::move(res.get_success()), FAIL());
- EXPECT_SPAN(top.span, 1,1, 1,19);
+ EXPECT_SPAN(top.span, 1,1, 1,22);
auto script = top.get_if<Script>();
EXPECT_TRUE(script);
auto p = script->get_if<ScriptNone>();
@@ -446,66 +446,10 @@ namespace npc
EXPECT_SPAN(script->key_span, 1,3, 1,8);
EXPECT_SPAN(p->name.span, 1,10, 1,16);
EXPECT_EQ(p->name.data, stringish<NpcName>("#config"_s));
- EXPECT_SPAN(p->key4_span, 1,18, 1,19);
+ EXPECT_SPAN(p->key4_span, 1,18, 1,22);
if (input.endswith('}'))
{
- EXPECT_SPAN(script->body.span, 1,20, 1,25);
- }
- else if (input.endswith('\n'))
- {
- EXPECT_SPAN(script->body.span, 2,1, 2,6);
- }
- else if (input.endswith(' '))
- {
- EXPECT_SPAN(script->body.span, 3,2, 3,7);
- }
- else
- {
- FAIL();
- }
- EXPECT_EQ(script->body.braced_body, "{end;}"_s);
- }
- }
- }
- TEST(npcast, scriptmapnone)
- {
- QuietFd q;
- LString inputs[] =
- {
- // 1 2 3
- //23456789012345678901234567890123456789
- "map.gat,1,2,3|script|Init|-1{end;}"_s,
- "map.gat,1,2,3|script|Init|-1\n{end;}\n"_s,
- "map.gat,1,2,3|script|Init|-1\n \n {end;} "_s,
- };
- for (auto input : inputs)
- {
- io::LineCharReader lr(io::from_string, "<string>"_s, input);
- auto res = TRY_UNWRAP(parse_top(lr), FAIL());
- EXPECT_TRUE(res.get_success().is_some());
- auto top = TRY_UNWRAP(std::move(res.get_success()), FAIL());
- EXPECT_SPAN(top.span, 1,1, 1,28);
- auto script = top.get_if<Script>();
- EXPECT_TRUE(script);
- auto p = script->get_if<ScriptMapNone>();
- EXPECT_TRUE(p);
- if (p)
- {
- EXPECT_SPAN(p->m.span, 1,1, 1,7);
- EXPECT_EQ(p->m.data, stringish<MapName>("map"_s));
- EXPECT_SPAN(p->x.span, 1,9, 1,9);
- EXPECT_EQ(p->x.data, 1);
- EXPECT_SPAN(p->y.span, 1,11, 1,11);
- EXPECT_EQ(p->y.data, 2);
- EXPECT_SPAN(p->d.span, 1,13, 1,13);
- EXPECT_EQ(p->d.data, DIR::NW);
- EXPECT_SPAN(script->key_span, 1,15, 1,20);
- EXPECT_SPAN(p->name.span, 1,22, 1,25);
- EXPECT_EQ(p->name.data, stringish<NpcName>("Init"_s));
- EXPECT_SPAN(p->key4_span, 1,27, 1,28);
- if (input.endswith('}'))
- {
- EXPECT_SPAN(script->body.span, 1,29, 1,34);
+ EXPECT_SPAN(script->body.span, 1,23, 1,28);
}
else if (input.endswith('\n'))
{
diff --git a/src/ast/quest.cpp b/src/ast/quest.cpp
new file mode 100644
index 0000000..bd339c2
--- /dev/null
+++ b/src/ast/quest.cpp
@@ -0,0 +1,125 @@
+#include "quest.hpp"
+// ast/quest.cpp - Structure of tmwa questdb
+//
+// Copyright © 2015 Ed Pasek <pasekei@gmail.com>
+//
+// This file is part of The Mana World (Athena server)
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+#include "../io/extract.hpp"
+#include "../io/line.hpp"
+
+#include "../mmo/extract_enums.hpp"
+
+#include "../poison.hpp"
+
+
+namespace tmwa
+{
+namespace ast
+{
+namespace quest
+{
+ using io::respan;
+
+ static
+ void skip_comma_space(io::LineCharReader& lr)
+ {
+ io::LineChar c;
+ if (lr.get(c) && c.ch() == ',')
+ {
+ lr.adv();
+ while (lr.get(c) && c.ch() == ' ')
+ {
+ lr.adv();
+ }
+ }
+ }
+ static
+ Option<Spanned<RString>> lex_nonscript(io::LineCharReader& lr, bool first)
+ {
+ io::LineChar c;
+ if (first)
+ {
+ while (lr.get(c) && c.ch() == '\n')
+ {
+ lr.adv();
+ }
+ }
+ if (!lr.get(c))
+ {
+ return None;
+ }
+ io::LineSpan span;
+ MString accum;
+ accum += c.ch();
+ span.begin = c;
+ span.end = c;
+ lr.adv();
+ if (c.ch() != '/')
+ first = false;
+
+ if (first && lr.get(c) && c.ch() == '/')
+ {
+ accum += c.ch();
+ span.end = c;
+ lr.adv();
+ while (lr.get(c) && c.ch() != '\n')
+ {
+ accum += c.ch();
+ span.end = c;
+ lr.adv();
+ }
+ return Some(respan(span, RString(accum)));
+ }
+
+ while (lr.get(c) && c.ch() != ',' && c.ch() != '\n')
+ {
+ accum += c.ch();
+ span.end = c;
+ lr.adv();
+ }
+ skip_comma_space(lr);
+ return Some(respan(span, RString(accum)));
+ }
+
+#define SPAN_EXTRACT(bitexpr, var) ({ auto bit = bitexpr; if (!extract(bit.data, &var.data)) return Err(bit.span.error_str("failed to extract "_s #var)); var.span = bit.span; })
+
+#define EOL_ERROR(lr) ({ io::LineChar c; lr.get(c) ? Err(c.error_str("unexpected EOL"_s)) : Err("unexpected EOF before unexpected EOL"_s); })
+ Option<Result<QuestOrComment>> parse_quest(io::LineCharReader& lr)
+ {
+ Spanned<RString> first = TRY_UNWRAP(lex_nonscript(lr, true), return None);
+ if (first.data.startswith("//"_s))
+ {
+ Comment comment;
+ comment.comment = first.data;
+ QuestOrComment rv = std::move(comment);
+ rv.span = first.span;
+ return Some(Ok(std::move(rv)));
+ }
+ Quest quest;
+ SPAN_EXTRACT(first, quest.questid);
+ SPAN_EXTRACT(TRY_UNWRAP(lex_nonscript(lr, false), return EOL_ERROR(lr)), quest.quest_var);
+ SPAN_EXTRACT(TRY_UNWRAP(lex_nonscript(lr, false), return EOL_ERROR(lr)), quest.quest_vr);
+ SPAN_EXTRACT(TRY_UNWRAP(lex_nonscript(lr, false), return EOL_ERROR(lr)), quest.quest_shift);
+ SPAN_EXTRACT(TRY_UNWRAP(lex_nonscript(lr, false), return EOL_ERROR(lr)), quest.quest_mask);
+ QuestOrComment rv = std::move(quest);
+ rv.span.begin = quest.questid.span.begin;
+ rv.span.end = quest.quest_mask.span.end;
+ return Some(Ok(std::move(rv)));
+ }
+} // namespace quest
+} // namespace ast
+} // namespace tmwa
diff --git a/src/ast/quest.hpp b/src/ast/quest.hpp
new file mode 100644
index 0000000..5112524
--- /dev/null
+++ b/src/ast/quest.hpp
@@ -0,0 +1,65 @@
+#pragma once
+// ast/quest.hpp - Structure of tmwa questdb
+//
+// Copyright © 2015 Ed Pasek <pasekei@gmail.com>
+//
+// This file is part of The Mana World (Athena server)
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+#include "fwd.hpp"
+
+#include "../compat/result.hpp"
+
+#include "../io/span.hpp"
+
+#include "../sexpr/variant.hpp"
+
+#include "../mmo/clif.t.hpp"
+#include "../mmo/ids.hpp"
+#include "../mmo/strs.hpp"
+
+namespace tmwa
+{
+namespace ast
+{
+namespace quest
+{
+ using io::Spanned;
+
+ struct Comment
+ {
+ RString comment;
+ };
+ struct Quest
+ {
+ Spanned<QuestId> questid;
+ Spanned<VarName> quest_var;
+ Spanned<VarName> quest_vr;
+ Spanned<int> quest_shift;
+ Spanned<int> quest_mask;
+ };
+
+ using QuestOrCommentBase = Variant<Comment, Quest>;
+ struct QuestOrComment : QuestOrCommentBase
+ {
+ QuestOrComment(Comment o) : QuestOrCommentBase(std::move(o)) {}
+ QuestOrComment(Quest o) : QuestOrCommentBase(std::move(o)) {}
+ io::LineSpan span;
+ };
+
+ Option<Result<QuestOrComment>> parse_quest(io::LineCharReader& lr);
+} // namespace quest
+} // namespace ast
+} // namespace tmwa