Move checking of valid object names to parse time
This commit is contained in:
parent
52a191df9e
commit
c31ebb5665
@ -410,9 +410,6 @@ namespace chaiscript
|
|||||||
std::vector<std::pair<std::string, Boxed_Value>> m_boxed_functions;
|
std::vector<std::pair<std::string, Boxed_Value>> m_boxed_functions;
|
||||||
std::map<std::string, Boxed_Value> m_global_objects;
|
std::map<std::string, Boxed_Value> m_global_objects;
|
||||||
Type_Name_Map m_types;
|
Type_Name_Map m_types;
|
||||||
std::set<std::string> m_reserved_words
|
|
||||||
= {"def", "fun", "while", "for", "if", "else", "&&", "||", ",", "auto",
|
|
||||||
"return", "break", "true", "false", "class", "attr", "var", "global", "GLOBAL", "_"};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Dispatch_Engine(chaiscript::parser::ChaiScript_Parser_Base &parser)
|
Dispatch_Engine(chaiscript::parser::ChaiScript_Parser_Base &parser)
|
||||||
@ -439,7 +436,6 @@ namespace chaiscript
|
|||||||
/// Add a new named Proxy_Function to the system
|
/// Add a new named Proxy_Function to the system
|
||||||
void add(const Proxy_Function &f, const std::string &name)
|
void add(const Proxy_Function &f, const std::string &name)
|
||||||
{
|
{
|
||||||
validate_object_name(name);
|
|
||||||
add_function(f, name);
|
add_function(f, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -447,7 +443,6 @@ namespace chaiscript
|
|||||||
/// is not available in the current scope it is created
|
/// is not available in the current scope it is created
|
||||||
void add(Boxed_Value obj, const std::string &name)
|
void add(Boxed_Value obj, const std::string &name)
|
||||||
{
|
{
|
||||||
validate_object_name(name);
|
|
||||||
auto &stack = get_stack_data();
|
auto &stack = get_stack_data();
|
||||||
|
|
||||||
for (auto stack_elem = stack.rbegin(); stack_elem != stack.rend(); ++stack_elem)
|
for (auto stack_elem = stack.rbegin(); stack_elem != stack.rend(); ++stack_elem)
|
||||||
@ -497,7 +492,6 @@ namespace chaiscript
|
|||||||
/// Adds a new global shared object, between all the threads
|
/// Adds a new global shared object, between all the threads
|
||||||
void add_global_const(const Boxed_Value &obj, const std::string &name)
|
void add_global_const(const Boxed_Value &obj, const std::string &name)
|
||||||
{
|
{
|
||||||
validate_object_name(name);
|
|
||||||
if (!obj.is_const())
|
if (!obj.is_const())
|
||||||
{
|
{
|
||||||
throw chaiscript::exception::global_non_const();
|
throw chaiscript::exception::global_non_const();
|
||||||
@ -516,8 +510,6 @@ namespace chaiscript
|
|||||||
/// Adds a new global (non-const) shared object, between all the threads
|
/// Adds a new global (non-const) shared object, between all the threads
|
||||||
Boxed_Value add_global_no_throw(const Boxed_Value &obj, const std::string &name)
|
Boxed_Value add_global_no_throw(const Boxed_Value &obj, const std::string &name)
|
||||||
{
|
{
|
||||||
validate_object_name(name);
|
|
||||||
|
|
||||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||||
|
|
||||||
const auto itr = m_state.m_global_objects.find(name);
|
const auto itr = m_state.m_global_objects.find(name);
|
||||||
@ -534,8 +526,6 @@ namespace chaiscript
|
|||||||
/// Adds a new global (non-const) shared object, between all the threads
|
/// Adds a new global (non-const) shared object, between all the threads
|
||||||
void add_global(const Boxed_Value &obj, const std::string &name)
|
void add_global(const Boxed_Value &obj, const std::string &name)
|
||||||
{
|
{
|
||||||
validate_object_name(name);
|
|
||||||
|
|
||||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||||
|
|
||||||
if (m_state.m_global_objects.find(name) != m_state.m_global_objects.end())
|
if (m_state.m_global_objects.find(name) != m_state.m_global_objects.end())
|
||||||
@ -549,8 +539,6 @@ namespace chaiscript
|
|||||||
/// Updates an existing global shared object or adds a new global shared object if not found
|
/// Updates an existing global shared object or adds a new global shared object if not found
|
||||||
void set_global(const Boxed_Value &obj, const std::string &name)
|
void set_global(const Boxed_Value &obj, const std::string &name)
|
||||||
{
|
{
|
||||||
validate_object_name(name);
|
|
||||||
|
|
||||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||||
|
|
||||||
const auto itr = m_state.m_global_objects.find(name);
|
const auto itr = m_state.m_global_objects.find(name);
|
||||||
@ -1359,20 +1347,6 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Throw a reserved_word exception if the name is not allowed
|
|
||||||
void validate_object_name(const std::string &name) const
|
|
||||||
{
|
|
||||||
if (name.find("::") != std::string::npos) {
|
|
||||||
throw chaiscript::exception::illegal_name_error(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
|
||||||
|
|
||||||
if (m_state.m_reserved_words.find(name) != m_state.m_reserved_words.end())
|
|
||||||
{
|
|
||||||
throw chaiscript::exception::reserved_word_error(name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename Container, typename Key, typename Value>
|
template<typename Container, typename Key, typename Value>
|
||||||
static void add_keyed_value(Container &t_c, const Key &t_key, Value &&t_value)
|
static void add_keyed_value(Container &t_c, const Key &t_key, Value &&t_value)
|
||||||
|
@ -26,6 +26,30 @@ struct AST_Node;
|
|||||||
|
|
||||||
namespace chaiscript
|
namespace chaiscript
|
||||||
{
|
{
|
||||||
|
static bool is_reserved_word(const std::string &name)
|
||||||
|
{
|
||||||
|
static const std::set<std::string> m_reserved_words
|
||||||
|
= {"def", "fun", "while", "for", "if", "else", "&&", "||", ",", "auto",
|
||||||
|
"return", "break", "true", "false", "class", "attr", "var", "global", "GLOBAL", "_"};
|
||||||
|
return m_reserved_words.count(name) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool valid_object_name(const std::string &name)
|
||||||
|
{
|
||||||
|
return name.find("::") == std::string::npos && !is_reserved_word(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void validate_object_name(const std::string &name)
|
||||||
|
{
|
||||||
|
if (is_reserved_word(name)) {
|
||||||
|
throw exception::reserved_word_error(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name.find("::") != std::string::npos) {
|
||||||
|
throw exception::illegal_name_error(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Signature of module entry point that all binary loadable modules must implement.
|
/// Signature of module entry point that all binary loadable modules must implement.
|
||||||
typedef ModulePtr (*Create_Module_Func)();
|
typedef ModulePtr (*Create_Module_Func)();
|
||||||
|
@ -387,6 +387,7 @@ namespace chaiscript
|
|||||||
/// \sa Boxed_Value::is_const
|
/// \sa Boxed_Value::is_const
|
||||||
ChaiScript &add_global_const(const Boxed_Value &t_bv, const std::string &t_name)
|
ChaiScript &add_global_const(const Boxed_Value &t_bv, const std::string &t_name)
|
||||||
{
|
{
|
||||||
|
validate_object_name(t_name);
|
||||||
m_engine.add_global_const(t_bv, t_name);
|
m_engine.add_global_const(t_bv, t_name);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -398,12 +399,14 @@ namespace chaiscript
|
|||||||
/// ChaiScript is thread-safe but provides no threading locking mechanism to the script
|
/// ChaiScript is thread-safe but provides no threading locking mechanism to the script
|
||||||
ChaiScript &add_global(const Boxed_Value &t_bv, const std::string &t_name)
|
ChaiScript &add_global(const Boxed_Value &t_bv, const std::string &t_name)
|
||||||
{
|
{
|
||||||
|
validate_object_name(t_name);
|
||||||
m_engine.add_global(t_bv, t_name);
|
m_engine.add_global(t_bv, t_name);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
ChaiScript &set_global(const Boxed_Value &t_bv, const std::string &t_name)
|
ChaiScript &set_global(const Boxed_Value &t_bv, const std::string &t_name)
|
||||||
{
|
{
|
||||||
|
validate_object_name(t_name);
|
||||||
m_engine.set_global(t_bv, t_name);
|
m_engine.set_global(t_bv, t_name);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@ -503,6 +506,7 @@ namespace chaiscript
|
|||||||
template<typename T>
|
template<typename T>
|
||||||
ChaiScript &add(const T &t_t, const std::string &t_name)
|
ChaiScript &add(const T &t_t, const std::string &t_name)
|
||||||
{
|
{
|
||||||
|
validate_object_name(t_name);
|
||||||
m_engine.add(t_t, t_name);
|
m_engine.add(t_t, t_name);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -527,12 +527,7 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
|
|
||||||
try {
|
|
||||||
return t_ss->add_global_no_throw(Boxed_Value(), idname);
|
return t_ss->add_global_no_throw(Boxed_Value(), idname);
|
||||||
}
|
|
||||||
catch (const exception::reserved_word_error &) {
|
|
||||||
throw exception::eval_error("Reserved word used as global '" + idname + "'");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -550,9 +545,6 @@ namespace chaiscript
|
|||||||
Boxed_Value bv;
|
Boxed_Value bv;
|
||||||
t_ss.add_object(idname, bv);
|
t_ss.add_object(idname, bv);
|
||||||
return bv;
|
return bv;
|
||||||
}
|
|
||||||
catch (const exception::reserved_word_error &) {
|
|
||||||
throw exception::eval_error("Reserved word used as variable '" + idname + "'");
|
|
||||||
} catch (const exception::name_conflict_error &e) {
|
} catch (const exception::name_conflict_error &e) {
|
||||||
throw exception::eval_error("Variable redefined '" + e.name() + "'");
|
throw exception::eval_error("Variable redefined '" + e.name() + "'");
|
||||||
}
|
}
|
||||||
@ -763,9 +755,6 @@ namespace chaiscript
|
|||||||
},
|
},
|
||||||
static_cast<int>(numparams), this->children.back(),
|
static_cast<int>(numparams), this->children.back(),
|
||||||
param_types, guard), l_function_name);
|
param_types, guard), l_function_name);
|
||||||
}
|
|
||||||
catch (const exception::reserved_word_error &e) {
|
|
||||||
throw exception::eval_error("Reserved word used as function name '" + e.word() + "'");
|
|
||||||
} catch (const exception::name_conflict_error &e) {
|
} catch (const exception::name_conflict_error &e) {
|
||||||
throw exception::eval_error("Function redefined '" + e.name() + "'");
|
throw exception::eval_error("Function redefined '" + e.name() + "'");
|
||||||
}
|
}
|
||||||
@ -1069,15 +1058,10 @@ namespace chaiscript
|
|||||||
{ assert(children.size() == 1); }
|
{ assert(children.size() == 1); }
|
||||||
|
|
||||||
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{
|
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{
|
||||||
try {
|
|
||||||
Boxed_Value bv;
|
Boxed_Value bv;
|
||||||
t_ss.add_object(this->children[0]->text, bv);
|
t_ss.add_object(this->children[0]->text, bv);
|
||||||
return bv;
|
return bv;
|
||||||
}
|
}
|
||||||
catch (const exception::reserved_word_error &) {
|
|
||||||
throw exception::eval_error("Reserved word used as variable '" + this->children[0]->text + "'");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
@ -1377,9 +1361,6 @@ namespace chaiscript
|
|||||||
static_cast<int>(numparams), node, param_types, guard), type),
|
static_cast<int>(numparams), node, param_types, guard), type),
|
||||||
function_name);
|
function_name);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
catch (const exception::reserved_word_error &e) {
|
|
||||||
throw exception::eval_error("Reserved word used as method name '" + e.word() + "'");
|
|
||||||
} catch (const exception::name_conflict_error &e) {
|
} catch (const exception::name_conflict_error &e) {
|
||||||
throw exception::eval_error("Method redefined '" + e.name() + "'");
|
throw exception::eval_error("Method redefined '" + e.name() + "'");
|
||||||
}
|
}
|
||||||
@ -1412,10 +1393,6 @@ namespace chaiscript
|
|||||||
true
|
true
|
||||||
|
|
||||||
), this->children[static_cast<size_t>(1 + class_offset)]->text);
|
), this->children[static_cast<size_t>(1 + class_offset)]->text);
|
||||||
|
|
||||||
}
|
|
||||||
catch (const exception::reserved_word_error &) {
|
|
||||||
throw exception::eval_error("Reserved word used as attribute '" + this->children[static_cast<size_t>(1 + class_offset)]->text + "'");
|
|
||||||
} catch (const exception::name_conflict_error &e) {
|
} catch (const exception::name_conflict_error &e) {
|
||||||
throw exception::eval_error("Attribute redefined '" + e.name() + "'");
|
throw exception::eval_error("Attribute redefined '" + e.name() + "'");
|
||||||
}
|
}
|
||||||
|
@ -285,6 +285,13 @@ namespace chaiscript
|
|||||||
Tracer m_tracer;
|
Tracer m_tracer;
|
||||||
Optimizer m_optimizer;
|
Optimizer m_optimizer;
|
||||||
|
|
||||||
|
void validate_object_name(const std::string &name) const
|
||||||
|
{
|
||||||
|
if (!valid_object_name(name)) {
|
||||||
|
throw exception::eval_error("Invalid Object Name: " + name, File_Position(m_position.line, m_position.col), *m_filename);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ChaiScript_Parser(Tracer tracer = Tracer(), Optimizer optimizer=Optimizer())
|
explicit ChaiScript_Parser(Tracer tracer = Tracer(), Optimizer optimizer=Optimizer())
|
||||||
: m_tracer(std::move(tracer)),
|
: m_tracer(std::move(tracer)),
|
||||||
@ -756,13 +763,18 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Reads (and potentially captures) an identifier from input
|
/// Reads (and potentially captures) an identifier from input
|
||||||
bool Id() {
|
bool Id(const bool validate) {
|
||||||
SkipWS();
|
SkipWS();
|
||||||
|
|
||||||
const auto start = m_position;
|
const auto start = m_position;
|
||||||
if (Id_()) {
|
if (Id_()) {
|
||||||
|
|
||||||
const auto text = Position::str(start, m_position);
|
const auto text = Position::str(start, m_position);
|
||||||
|
|
||||||
|
if (validate) {
|
||||||
|
validate_object_name(text);
|
||||||
|
}
|
||||||
|
|
||||||
if (text == "true") {
|
if (text == "true") {
|
||||||
m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(text, start.line, start.col, const_var(true)));
|
m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(text, start.line, start.col, const_var(true)));
|
||||||
} else if (text == "false") {
|
} else if (text == "false") {
|
||||||
@ -801,14 +813,14 @@ namespace chaiscript
|
|||||||
const auto prev_stack_top = m_match_stack.size();
|
const auto prev_stack_top = m_match_stack.size();
|
||||||
SkipWS();
|
SkipWS();
|
||||||
|
|
||||||
if (!Id()) {
|
if (!Id(true)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
SkipWS();
|
SkipWS();
|
||||||
|
|
||||||
if (t_type_allowed) {
|
if (t_type_allowed) {
|
||||||
Id();
|
Id(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
build_match<eval::Arg_AST_Node<Tracer>>(prev_stack_top);
|
build_match<eval::Arg_AST_Node<Tracer>>(prev_stack_top);
|
||||||
@ -1427,7 +1439,7 @@ namespace chaiscript
|
|||||||
if (Keyword("def")) {
|
if (Keyword("def")) {
|
||||||
retval = true;
|
retval = true;
|
||||||
|
|
||||||
if (!Id()) {
|
if (!Id(true)) {
|
||||||
throw exception::eval_error("Missing function name in definition", File_Position(m_position.line, m_position.col), *m_filename);
|
throw exception::eval_error("Missing function name in definition", File_Position(m_position.line, m_position.col), *m_filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1437,7 +1449,7 @@ namespace chaiscript
|
|||||||
//We're now a method
|
//We're now a method
|
||||||
is_method = true;
|
is_method = true;
|
||||||
|
|
||||||
if (!Id()) {
|
if (!Id(true)) {
|
||||||
throw exception::eval_error("Missing method name in definition", File_Position(m_position.line, m_position.col), *m_filename);
|
throw exception::eval_error("Missing method name in definition", File_Position(m_position.line, m_position.col), *m_filename);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1588,7 +1600,7 @@ namespace chaiscript
|
|||||||
if (Keyword("class")) {
|
if (Keyword("class")) {
|
||||||
retval = true;
|
retval = true;
|
||||||
|
|
||||||
if (!Id()) {
|
if (!Id(true)) {
|
||||||
throw exception::eval_error("Missing class name in definition", File_Position(m_position.line, m_position.col), *m_filename);
|
throw exception::eval_error("Missing class name in definition", File_Position(m_position.line, m_position.col), *m_filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1871,7 +1883,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
const auto prev_stack_top = m_match_stack.size();
|
const auto prev_stack_top = m_match_stack.size();
|
||||||
if (Lambda() || Num(true) || Quoted_String(true) || Single_Quoted_String(true) ||
|
if (Lambda() || Num(true) || Quoted_String(true) || Single_Quoted_String(true) ||
|
||||||
Paren_Expression() || Inline_Container() || Id())
|
Paren_Expression() || Inline_Container() || Id(false))
|
||||||
{
|
{
|
||||||
retval = true;
|
retval = true;
|
||||||
bool has_more = true;
|
bool has_more = true;
|
||||||
@ -1916,7 +1928,7 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
else if (Symbol(".")) {
|
else if (Symbol(".")) {
|
||||||
has_more = true;
|
has_more = true;
|
||||||
if (!(Id())) {
|
if (!(Id(true))) {
|
||||||
throw exception::eval_error("Incomplete dot access fun call", File_Position(m_position.line, m_position.col), *m_filename);
|
throw exception::eval_error("Incomplete dot access fun call", File_Position(m_position.line, m_position.col), *m_filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1940,7 +1952,7 @@ namespace chaiscript
|
|||||||
if (t_class_context && (Keyword("attr") || Keyword("auto") || Keyword("var"))) {
|
if (t_class_context && (Keyword("attr") || Keyword("auto") || Keyword("var"))) {
|
||||||
retval = true;
|
retval = true;
|
||||||
|
|
||||||
if (!Id()) {
|
if (!Id(true)) {
|
||||||
throw exception::eval_error("Incomplete attribute declaration", File_Position(m_position.line, m_position.col), *m_filename);
|
throw exception::eval_error("Incomplete attribute declaration", File_Position(m_position.line, m_position.col), *m_filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1950,7 +1962,7 @@ namespace chaiscript
|
|||||||
|
|
||||||
if (Reference()) {
|
if (Reference()) {
|
||||||
// we built a reference node - continue
|
// we built a reference node - continue
|
||||||
} else if (Id()) {
|
} else if (Id(true)) {
|
||||||
build_match<eval::Var_Decl_AST_Node<Tracer>>(prev_stack_top);
|
build_match<eval::Var_Decl_AST_Node<Tracer>>(prev_stack_top);
|
||||||
} else {
|
} else {
|
||||||
throw exception::eval_error("Incomplete variable declaration", File_Position(m_position.line, m_position.col), *m_filename);
|
throw exception::eval_error("Incomplete variable declaration", File_Position(m_position.line, m_position.col), *m_filename);
|
||||||
@ -1959,7 +1971,7 @@ namespace chaiscript
|
|||||||
} else if (Keyword("GLOBAL") || Keyword("global")) {
|
} else if (Keyword("GLOBAL") || Keyword("global")) {
|
||||||
retval = true;
|
retval = true;
|
||||||
|
|
||||||
if (!(Reference() || Id())) {
|
if (!(Reference() || Id(true))) {
|
||||||
throw exception::eval_error("Incomplete global declaration", File_Position(m_position.line, m_position.col), *m_filename);
|
throw exception::eval_error("Incomplete global declaration", File_Position(m_position.line, m_position.col), *m_filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1967,13 +1979,13 @@ namespace chaiscript
|
|||||||
} else if (Keyword("attr")) {
|
} else if (Keyword("attr")) {
|
||||||
retval = true;
|
retval = true;
|
||||||
|
|
||||||
if (!Id()) {
|
if (!Id(true)) {
|
||||||
throw exception::eval_error("Incomplete attribute declaration", File_Position(m_position.line, m_position.col), *m_filename);
|
throw exception::eval_error("Incomplete attribute declaration", File_Position(m_position.line, m_position.col), *m_filename);
|
||||||
}
|
}
|
||||||
if (!Symbol("::")) {
|
if (!Symbol("::")) {
|
||||||
throw exception::eval_error("Incomplete attribute declaration", File_Position(m_position.line, m_position.col), *m_filename);
|
throw exception::eval_error("Incomplete attribute declaration", File_Position(m_position.line, m_position.col), *m_filename);
|
||||||
}
|
}
|
||||||
if (!Id()) {
|
if (!Id(true)) {
|
||||||
throw exception::eval_error("Missing attribute name in definition", File_Position(m_position.line, m_position.col), *m_filename);
|
throw exception::eval_error("Missing attribute name in definition", File_Position(m_position.line, m_position.col), *m_filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2035,7 +2047,7 @@ namespace chaiscript
|
|||||||
const auto prev_stack_top = m_match_stack.size();
|
const auto prev_stack_top = m_match_stack.size();
|
||||||
|
|
||||||
if (Symbol("&")) {
|
if (Symbol("&")) {
|
||||||
if (!Id()) {
|
if (!Id(true)) {
|
||||||
throw exception::eval_error("Incomplete '&' expression", File_Position(m_position.line, m_position.col), *m_filename);
|
throw exception::eval_error("Incomplete '&' expression", File_Position(m_position.line, m_position.col), *m_filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user