mirror of
https://github.com/yhirose/cpp-peglib.git
synced 2024-12-22 20:05:31 +00:00
Added 'return' statement.
This commit is contained in:
parent
3cb801a5df
commit
ff6deb98e3
@ -6,10 +6,12 @@ syn match culError ";"
|
|||||||
syn match culError "\s*$"
|
syn match culError "\s*$"
|
||||||
syn match culLineComment "\(\/\/\|#\).*" contains=@Spell,javaScriptCommentTodo
|
syn match culLineComment "\(\/\/\|#\).*" contains=@Spell,javaScriptCommentTodo
|
||||||
|
|
||||||
syn keyword culKeyword fn
|
syn keyword culFunction fn
|
||||||
syn keyword culSelf self
|
syn keyword culSelf self
|
||||||
syn keyword culConditional if else
|
syn keyword culConditional if else
|
||||||
syn keyword culRepeat while
|
syn keyword culRepeat while
|
||||||
|
syn keyword culReturn return
|
||||||
|
syn keyword culDebugger debugger
|
||||||
syn keyword culBoolean true false
|
syn keyword culBoolean true false
|
||||||
syn keyword culCommentTodo TODO FIXME XXX TBD contained
|
syn keyword culCommentTodo TODO FIXME XXX TBD contained
|
||||||
syn keyword culStorage mut
|
syn keyword culStorage mut
|
||||||
@ -24,10 +26,12 @@ hi def link culCommentTodo Todo
|
|||||||
hi def link culConditional Conditional
|
hi def link culConditional Conditional
|
||||||
hi def link culDecNumber Number
|
hi def link culDecNumber Number
|
||||||
hi def link culFuncCall Function
|
hi def link culFuncCall Function
|
||||||
hi def link culKeyword Keyword
|
hi def link culFunction Type
|
||||||
hi def link culLineComment Comment
|
hi def link culLineComment Comment
|
||||||
hi def link culOperator Operator
|
hi def link culOperator Operator
|
||||||
hi def link culRepeat Repeat
|
hi def link culRepeat Repeat
|
||||||
|
hi def link culReturn Statement
|
||||||
|
hi def link culDebugger Debug
|
||||||
hi def link culSelf Constant
|
hi def link culSelf Constant
|
||||||
hi def link culStorage StorageClass
|
hi def link culStorage StorageClass
|
||||||
hi def link culStringD String
|
hi def link culStringD String
|
||||||
|
@ -9,9 +9,10 @@ const auto grammar_ = R"(
|
|||||||
|
|
||||||
PROGRAM <- _ STATEMENTS
|
PROGRAM <- _ STATEMENTS
|
||||||
STATEMENTS <- (STATEMENT (';' _)?)*
|
STATEMENTS <- (STATEMENT (';' _)?)*
|
||||||
STATEMENT <- DEBUGGER / EXPRESSION
|
STATEMENT <- DEBUGGER / RETURN / EXPRESSION
|
||||||
|
|
||||||
DEBUGGER <- 'debugger' _
|
DEBUGGER <- 'debugger' _
|
||||||
|
RETURN <- 'return' __ '\n' / 'return' _ EXPRESSION?
|
||||||
|
|
||||||
EXPRESSION <- ASSIGNMENT / LOGICAL_OR
|
EXPRESSION <- ASSIGNMENT / LOGICAL_OR
|
||||||
|
|
||||||
@ -67,10 +68,11 @@ const auto grammar_ = R"(
|
|||||||
MUTABLE <- < 'mut'? > _
|
MUTABLE <- < 'mut'? > _
|
||||||
|
|
||||||
~_ <- (Space / EndOfLine / Comment)*
|
~_ <- (Space / EndOfLine / Comment)*
|
||||||
|
~__ <- (Space / Comment)*
|
||||||
Space <- ' ' / '\t'
|
Space <- ' ' / '\t'
|
||||||
EndOfLine <- '\r\n' / '\n' / '\r'
|
EndOfLine <- '\r\n' / '\n' / '\r'
|
||||||
EndOfFile <- !.
|
EndOfFile <- !.
|
||||||
Comment <- '/*' (!'*/' .)* '*/' / ('#' / '//') (!(EndOfLine / EndOfFile) .)* (EndOfLine / EndOfFile)
|
Comment <- '/*' (!'*/' .)* '*/' / ('#' / '//') (!(EndOfLine / EndOfFile) .)* &(EndOfLine / EndOfFile)
|
||||||
|
|
||||||
)";
|
)";
|
||||||
|
|
||||||
@ -526,12 +528,21 @@ inline void setup_built_in_functions(Environment& env) {
|
|||||||
false);
|
false);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Eval
|
struct Interpreter
|
||||||
{
|
{
|
||||||
Eval(Debugger debugger = nullptr)
|
Interpreter(Debugger debugger = nullptr)
|
||||||
: debugger_(debugger) {
|
: debugger_(debugger) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Value exec(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
|
||||||
|
try {
|
||||||
|
return eval(ast, env);
|
||||||
|
} catch (const Value& val) {
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
Value eval(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
|
Value eval(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
|
||||||
using peglib::operator"" _;
|
using peglib::operator"" _;
|
||||||
|
|
||||||
@ -566,6 +577,7 @@ struct Eval
|
|||||||
case "NUMBER"_: return eval_number(ast, env);
|
case "NUMBER"_: return eval_number(ast, env);
|
||||||
case "INTERPOLATED_STRING"_: return eval_interpolated_string(ast, env);
|
case "INTERPOLATED_STRING"_: return eval_interpolated_string(ast, env);
|
||||||
case "DEBUGGER"_: return Value();
|
case "DEBUGGER"_: return Value();
|
||||||
|
case "RETURN"_: eval_return(ast, env);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ast.is_token) {
|
if (ast.is_token) {
|
||||||
@ -576,7 +588,6 @@ struct Eval
|
|||||||
throw std::logic_error("invalid Ast type");
|
throw std::logic_error("invalid Ast type");
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
|
||||||
Value eval_statements(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
|
Value eval_statements(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
|
||||||
if (ast.is_token) {
|
if (ast.is_token) {
|
||||||
return eval(ast, env);
|
return eval(ast, env);
|
||||||
@ -654,7 +665,11 @@ private:
|
|||||||
}
|
}
|
||||||
callEnv->initialize("__LINE__", Value((long)ast.line), false);
|
callEnv->initialize("__LINE__", Value((long)ast.line), false);
|
||||||
callEnv->initialize("__COLUMN__", Value((long)ast.column), false);
|
callEnv->initialize("__COLUMN__", Value((long)ast.column), false);
|
||||||
return f.eval(callEnv);
|
try {
|
||||||
|
return f.eval(callEnv);
|
||||||
|
} catch (const Value& val) {
|
||||||
|
return val;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string msg = "arguments error...";
|
std::string msg = "arguments error...";
|
||||||
@ -901,6 +916,14 @@ private:
|
|||||||
return Value(std::move(s));
|
return Value(std::move(s));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void eval_return(const peglib::Ast& ast, std::shared_ptr<Environment> env) {
|
||||||
|
if (ast.nodes.empty()) {
|
||||||
|
throw Value();
|
||||||
|
} else {
|
||||||
|
throw eval(*ast.nodes[0], env);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Debugger debugger_;
|
Debugger debugger_;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -924,8 +947,8 @@ inline bool run(
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (parser.parse_n(expr, len, ast, path.c_str())) {
|
if (parser.parse_n(expr, len, ast, path.c_str())) {
|
||||||
ast = peglib::AstOptimizer(true, { "PARAMETERS", "ARGUMENTS", "OBJECT", "ARRAY" }).optimize(ast);
|
ast = peglib::AstOptimizer(true, { "PARAMETERS", "ARGUMENTS", "OBJECT", "ARRAY", "RETURN" }).optimize(ast);
|
||||||
val = Eval(debugger).eval(*ast, env);
|
val = Interpreter(debugger).exec(*ast, env);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} catch (std::runtime_error& e) {
|
} catch (std::runtime_error& e) {
|
||||||
|
@ -1,9 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* Unit tests
|
||||||
|
*/
|
||||||
|
|
||||||
test_call = fn () {
|
test_call = fn () {
|
||||||
ret = fn(){[1,fn(){[4,5,6]},3]}()[1]()[1]
|
ret = fn(){[1,fn(){[4,5,6]},3]}()[1]()[1]
|
||||||
assert(ret == 5)
|
assert(ret == 5)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test_return = fn () {
|
||||||
|
f = fn (x) {
|
||||||
|
if (x % 2) {
|
||||||
|
return 'odd'
|
||||||
|
}
|
||||||
|
'even'
|
||||||
|
}
|
||||||
|
assert(f(3) == 'odd')
|
||||||
|
assert(f(4) == 'even')
|
||||||
|
|
||||||
|
mut val = 0
|
||||||
|
f2 = fn () {
|
||||||
|
val = 1
|
||||||
|
return // comment
|
||||||
|
val = 2
|
||||||
|
}
|
||||||
|
f2()
|
||||||
|
assert(val == 1)
|
||||||
|
}
|
||||||
|
|
||||||
test_undefined = fn () {
|
test_undefined = fn () {
|
||||||
assert(undefined == undefined)
|
assert(undefined == undefined)
|
||||||
assert(!(undefined != undefined))
|
assert(!(undefined != undefined))
|
||||||
@ -162,13 +185,14 @@ test_fib = fn () {
|
|||||||
|
|
||||||
test_interpolated_string = fn () {
|
test_interpolated_string = fn () {
|
||||||
hello = "Hello"
|
hello = "Hello"
|
||||||
world = "World!"
|
world = "World!"
|
||||||
ret = "{hello} {world}"
|
ret = "{hello} {world}"
|
||||||
assert(ret == 'Hello World!')
|
assert(ret == 'Hello World!')
|
||||||
}
|
}
|
||||||
|
|
||||||
debugger
|
debugger
|
||||||
test_call()
|
test_call()
|
||||||
|
test_return()
|
||||||
test_closure()
|
test_closure()
|
||||||
test_undefined()
|
test_undefined()
|
||||||
test_array()
|
test_array()
|
||||||
@ -176,6 +200,9 @@ test_function()
|
|||||||
test_object()
|
test_object()
|
||||||
test_object_factory()
|
test_object_factory()
|
||||||
test_class()
|
test_class()
|
||||||
|
debugger
|
||||||
test_sum()
|
test_sum()
|
||||||
test_fib()
|
test_fib()
|
||||||
test_interpolated_string()
|
test_interpolated_string()
|
||||||
|
|
||||||
|
return // end
|
Loading…
Reference in New Issue
Block a user