Load scene render params

This commit is contained in:
josh committed 2026-11-02 22:28:18 -05:00
1 parent a3684b20b6
commit 0ba0ebfe71
4 files changed
+94 -8

No files matched your search

+32 -2
View File
@@ -1,5 +1,25 @@
tree;
tree_prefix P;
ptype double;
<<header
/* User terminate codes. */
#define PARSER_TERMINATE_NUMBER_RANGE 1u
>>
<<
#include <charconv>
/* Store the numeric value of the matched text in *out. Returns false if the
* value cannot be represented. */
static bool parse_number(uint8_t const * match_text, size_t match_length, double * out)
{
const char * first = (const char *)match_text;
const char * last = first + match_length;
std::from_chars_result r = std::from_chars(first, last, *out);
return (r.ec == std::errc()) && (r.ptr == last);
}
>>
drop /\s+/;
@@ -14,8 +34,18 @@ token rcurly /\}/;
token scene;
token width;
token uint /\d+/;
token number /-?\d+(\.\d+)?/;
token uint /\d+/ <<
if (!parse_number(match_text, match_length, &$$))
{
$terminate(PARSER_TERMINATE_NUMBER_RANGE);
}
>>
token number /-?\d+(\.\d+)?/ <<
if (!parse_number(match_text, match_length, &$$))
{
$terminate(PARSER_TERMINATE_NUMBER_RANGE);
}
>>
Start -> RenderParams Scene;
+4
View File
@@ -62,5 +62,9 @@ int Engine::run(string_view input_file, opt<string_view> output_file)
return 1;
}
/* CLI params take precedence over scene params; defaults fill the rest. */
params.merge(scene->params);
params.apply_defaults();
return 0;
}
+57 -5
View File
@@ -1,6 +1,7 @@
#include <fart/Parser.h>
#include <fart/propane.h>
#include <fart/read_file.h>
#include <stdint.h>
#include <stdio.h>
Scene * Parser::load_scene(const string_view & input_file)
@@ -49,6 +50,19 @@ Scene * Parser::load_scene(const string_view & input_file)
break;
}
case P_USER_TERMINATED:
if (p_user_terminate_code(context) == PARSER_TERMINATE_NUMBER_RANGE)
{
fprintf(stderr, "%.*s:%u:%u: error: number out of range\n",
fname_len, fname, pos.row, pos.col);
}
else
{
fprintf(stderr, "%.*s:%u:%u: internal error: unknown terminate code %zu\n",
fname_len, fname, pos.row, pos.col, p_user_terminate_code(context));
}
break;
default:
fprintf(stderr, "%.*s:%u:%u: internal error: unknown parser result %zu\n",
fname_len, fname, pos.row, pos.col, result);
@@ -61,29 +75,67 @@ Scene * Parser::load_scene(const string_view & input_file)
return nullptr;
}
Scene * scene = build_scene(p_result(context));
Scene * scene = build_scene(input_file, p_result(context));
p_context_delete(context);
return scene;
}
Scene * Parser::build_scene(PStart start)
/* Convert a uint token value to a size_t, reporting an error if it does not
* fit. */
static bool token_to_size(const string_view & input_file, PToken token, opt<size_t> * out)
{
/* SIZE_MAX + 1, computed so that it is exactly representable as a double. */
const double size_limit = (double)(SIZE_MAX / 2u + 1u) * 2.0;
double value = token.pvalue();
if (value >= size_limit)
{
p_position_t pos = token.position();
fprintf(stderr, "%.*s:%u:%u: error: value out of range\n",
(int)input_file.size(), input_file.data(), pos.row, pos.col);
return false;
}
*out = (size_t)value;
return true;
}
static Color vector_to_color(PVector vector)
{
Color color{
vector.pNumber2().pToken().pvalue(),
vector.pNumber4().pToken().pvalue(),
vector.pNumber6().pToken().pvalue(),
};
if (PNumber a = vector.pNumber8(); p_node_valid(a))
{
color.a = a.pToken().pvalue();
}
return color;
}
Scene * Parser::build_scene(const string_view & input_file, PStart start)
{
Scene * scene = new Scene();
for (PRenderParams rps = start.pRenderParams(); p_node_valid(rps); rps = rps.pRenderParams())
{
PRenderParam rp = rps.pRenderParam();
bool ok = true;
if (PBackground background = rp.pBackground(); p_node_valid(background))
{
/* TODO: set scene->params.background from the Vector. */
scene->params.background = vector_to_color(background.pVector());
}
else if (PHeight height = rp.pHeight(); p_node_valid(height))
{
/* TODO: set scene->params.height from the uint token. */
ok = token_to_size(input_file, height.pToken2(), &scene->params.height);
}
else if (PWidth width = rp.pWidth(); p_node_valid(width))
{
/* TODO: set scene->params.width from the uint token. */
ok = token_to_size(input_file, width.pToken2(), &scene->params.width);
}
if (!ok)
{
delete scene;
return nullptr;
}
}
+1 -1
View File
@@ -10,5 +10,5 @@ public:
static Scene * load_scene(const string_view & input_file);
private:
static Scene * build_scene(PStart start);
static Scene * build_scene(const string_view & input_file, PStart start);
};