mirror of
https://github.com/yhirose/cpp-peglib.git
synced 2025-01-22 13:25:30 +00:00
Enhanced index access to array.
This commit is contained in:
parent
0e23f8f0b2
commit
f9ef592bd3
@ -29,10 +29,12 @@ const auto grammar_ = R"(
|
|||||||
MULTIPLICATIVE <- CALL (_ MULTIPLICATIVE_OPERATOR _ CALL)*
|
MULTIPLICATIVE <- CALL (_ MULTIPLICATIVE_OPERATOR _ CALL)*
|
||||||
|
|
||||||
CALL <- PRIMARY (_ (ARGUMENTS / INDEX / DOT))*
|
CALL <- PRIMARY (_ (ARGUMENTS / INDEX / DOT))*
|
||||||
ARGUMENTS <- '(' _ (EXPRESSION (_ ',' _ EXPRESSION)*)? _ ')'
|
ARGUMENTS <- '(' _ SEQUENCE _ ')'
|
||||||
INDEX <- '[' _ EXPRESSION _ ']'
|
INDEX <- '[' _ EXPRESSION _ ']'
|
||||||
DOT <- '.' _ IDENTIFIER
|
DOT <- '.' _ IDENTIFIER
|
||||||
|
|
||||||
|
SEQUENCE <- (EXPRESSION (_ ',' _ EXPRESSION)*)?
|
||||||
|
|
||||||
WHILE <- while _ EXPRESSION _ BLOCK
|
WHILE <- while _ EXPRESSION _ BLOCK
|
||||||
IF <- if _ EXPRESSION _ BLOCK (_ else _ if _ EXPRESSION _ BLOCK)* (_ else _ BLOCK)?
|
IF <- if _ EXPRESSION _ BLOCK (_ else _ if _ EXPRESSION _ BLOCK)* (_ else _ BLOCK)?
|
||||||
|
|
||||||
@ -59,7 +61,7 @@ const auto grammar_ = R"(
|
|||||||
OBJECT <- '{' _ (OBJECT_PROPERTY (_ ',' _ OBJECT_PROPERTY)*)? _ '}'
|
OBJECT <- '{' _ (OBJECT_PROPERTY (_ ',' _ OBJECT_PROPERTY)*)? _ '}'
|
||||||
OBJECT_PROPERTY <- MUTABLE _ IDENTIFIER _ ':' _ EXPRESSION
|
OBJECT_PROPERTY <- MUTABLE _ IDENTIFIER _ ':' _ EXPRESSION
|
||||||
|
|
||||||
ARRAY <- '[' _ (EXPRESSION (_ ',' _ EXPRESSION)*)? _ ']'
|
ARRAY <- '[' _ SEQUENCE _ ']' (_ '(' _ EXPRESSION (_ ',' _ EXPRESSION)? _ ')')?
|
||||||
|
|
||||||
UNDEFINED <- < 'undefined' _wd_ >
|
UNDEFINED <- < 'undefined' _wd_ >
|
||||||
BOOLEAN <- < ('true' / 'false') _wd_ >
|
BOOLEAN <- < ('true' / 'false') _wd_ >
|
||||||
@ -681,10 +683,13 @@ private:
|
|||||||
Value eval_array_reference(const peg::Ast& ast, std::shared_ptr<Environment> env, const Value& val) {
|
Value eval_array_reference(const peg::Ast& ast, std::shared_ptr<Environment> env, const Value& val) {
|
||||||
const auto& arr = val.to_array();
|
const auto& arr = val.to_array();
|
||||||
auto idx = eval(ast, env).to_long();
|
auto idx = eval(ast, env).to_long();
|
||||||
|
if (idx < 0) {
|
||||||
|
idx = arr.values->size() + idx;
|
||||||
|
}
|
||||||
if (0 <= idx && idx < static_cast<long>(arr.values->size())) {
|
if (0 <= idx && idx < static_cast<long>(arr.values->size())) {
|
||||||
return arr.values->at(idx);
|
return arr.values->at(idx);
|
||||||
} else {
|
} else {
|
||||||
// TODO: error? or 'undefined'?
|
throw std::logic_error("index out of range.");
|
||||||
}
|
}
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
@ -894,11 +899,28 @@ private:
|
|||||||
|
|
||||||
Value eval_array(const peg::Ast& ast, std::shared_ptr<Environment> env) {
|
Value eval_array(const peg::Ast& ast, std::shared_ptr<Environment> env) {
|
||||||
ArrayValue arr;
|
ArrayValue arr;
|
||||||
for (auto i = 0u; i < ast.nodes.size(); i++) {
|
|
||||||
auto expr = ast.nodes[i];
|
if (ast.nodes.size() >= 2) {
|
||||||
auto val = eval(*expr, env);
|
auto count = eval(*ast.nodes[1], env).to_long();
|
||||||
arr.values->push_back(std::move(val));
|
if (ast.nodes.size() == 3) {
|
||||||
|
auto val = eval(*ast.nodes[2], env);
|
||||||
|
arr.values->resize(count, std::move(val));
|
||||||
|
} else {
|
||||||
|
arr.values->resize(count);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto& nodes = ast.nodes[0]->nodes;
|
||||||
|
for (auto i = 0u; i < nodes.size(); i++) {
|
||||||
|
auto expr = nodes[i];
|
||||||
|
auto val = eval(*expr, env);
|
||||||
|
if (i < arr.values->size()) {
|
||||||
|
arr.values->at(i) = std::move(val);
|
||||||
|
} else {
|
||||||
|
arr.values->push_back(std::move(val));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return Value(std::move(arr));
|
return Value(std::move(arr));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -954,7 +976,7 @@ inline std::shared_ptr<peg::Ast> parse(
|
|||||||
|
|
||||||
std::shared_ptr<peg::Ast> ast;
|
std::shared_ptr<peg::Ast> ast;
|
||||||
if (parser.parse_n(expr, len, ast, path.c_str())) {
|
if (parser.parse_n(expr, len, ast, path.c_str())) {
|
||||||
return peg::AstOptimizer(true, { "PARAMETERS", "ARGUMENTS", "OBJECT", "ARRAY", "RETURN", "LEXICAL_SCOPE" }).optimize(ast);
|
return peg::AstOptimizer(true, { "PARAMETERS", "SEQUENCE", "OBJECT", "ARRAY", "RETURN", "LEXICAL_SCOPE" }).optimize(ast);
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -75,6 +75,15 @@ test_array = fn () {
|
|||||||
|
|
||||||
c = [1]
|
c = [1]
|
||||||
assert(c.size() == 1)
|
assert(c.size() == 1)
|
||||||
|
|
||||||
|
d = [1,2,3](5, 0)
|
||||||
|
assert(d.size() == 5 && d[-1] == 0)
|
||||||
|
|
||||||
|
e = [1,2,3](2)
|
||||||
|
assert(e.size() == 3 && e[-1] == 3)
|
||||||
|
|
||||||
|
f = [1,2,3](5)
|
||||||
|
assert(f.size() == 5 && f[-1] == undefined)
|
||||||
}
|
}
|
||||||
|
|
||||||
g_ = 1
|
g_ = 1
|
||||||
|
Loading…
Reference in New Issue
Block a user