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