From 456ce928eaf7d91e565c29d2d5caed93fe4e3aea Mon Sep 17 00:00:00 2001 From: yhirose Date: Thu, 28 May 2015 23:32:04 -0400 Subject: [PATCH] Interpolated string support. --- language/interpreter.cc | 10 ++++++++++ language/interpreter.hpp | 15 ++++++++++++++- language/parser.cc | 7 ++++++- language/parser.hpp | 3 ++- 4 files changed, 32 insertions(+), 3 deletions(-) diff --git a/language/interpreter.cc b/language/interpreter.cc index 12d0a8a..58f52fe 100644 --- a/language/interpreter.cc +++ b/language/interpreter.cc @@ -20,6 +20,7 @@ struct Eval case Identifier: return eval_identifier(ast, env); case Number: return eval_number(ast, env); case Boolean: return eval_bool(ast, env); + case InterpolatedString: return eval_interpolated_string(ast, env); } if (ast.is_token) { @@ -174,6 +175,15 @@ private: return Value(ast.token == "true"); }; + static Value eval_interpolated_string(const Ast& ast, Env& env) { + string s; + for (auto node: ast.nodes) { + const auto& val = eval(*node, env); + s += val.str(); + } + return Value(s); + }; + static Value dereference_identirier(Env& env, const string& var) { if (!env.has(var)) { string msg = "undefined variable '" + var + "'..."; diff --git a/language/interpreter.hpp b/language/interpreter.hpp index d59eb78..cbce785 100644 --- a/language/interpreter.hpp +++ b/language/interpreter.hpp @@ -61,6 +61,19 @@ struct Value throw std::runtime_error("type error."); } + std::string str() const { + switch (type) { + case Undefined: return "undefined"; + case Bool: return to_bool() ? "true" : "false"; + case Long: return std::to_string(to_long()); break; + case String: return to_string(); + //case Function: return "[function]"; + //case Array: return "[array]"; + default: throw std::logic_error("invalid internal condition."); + } + // NOTREACHED + } + std::ostream& out(std::ostream& os) const { switch (type) { case Undefined: os << "undefined"; break; @@ -181,7 +194,7 @@ struct Env auto func_pretty_print = Value::FunctionValue { { "arg" }, [](Env& env) { - std::cout << env.get("arg") << std::endl; + std::cout << env.get("arg").str() << std::endl; return Value(); } }; diff --git a/language/parser.cc b/language/parser.cc index 2ab992f..ae713eb 100644 --- a/language/parser.cc +++ b/language/parser.cc @@ -20,7 +20,7 @@ static auto g_grammar = R"( PRIMARY <- CONDITION (CONDITION_OPERATOR CONDITION)? CONDITION <- TERM (TERM_OPERATOR TERM)* TERM <- FACTOR (FACTOR_OPERATOR FACTOR)* - FACTOR <- WHILE / IF / FUNCTION / FUNCTION_CALL / NUMBER / BOOLEAN / STRING / IDENTIFIER / '(' _ EXPRESSION ')' _ + FACTOR <- WHILE / IF / FUNCTION / FUNCTION_CALL / NUMBER / BOOLEAN / STRING / INTERPOLATED_STRING / IDENTIFIER / '(' _ EXPRESSION ')' _ BLOCK <- '{' _ STATEMENTS '}' _ @@ -33,6 +33,9 @@ static auto g_grammar = R"( BOOLEAN <- < ('true' / 'false') > _ STRING <- ['] < (!['] .)* > ['] _ + INTERPOLATED_STRING <- '"' ('{' _ EXPRESSION '}' / INTERPOLATED_CONTENT)* '"' _ + INTERPOLATED_CONTENT <- (!["{] .) (!["{] .)* + ~_ <- (Space / EndOfLine / Comment)* Space <- ' ' / '\t' EndOfLine <- '\r\n' / '\n' / '\r' @@ -76,6 +79,8 @@ peglib::peg& get_parser() .ast_token("BOOLEAN", Boolean) .ast_token("STRING") .ast_token("IDENTIFIER", Identifier) + .ast_node("INTERPOLATED_STRING", InterpolatedString) + .ast_token("INTERPOLATED_CONTENT") .ast_end(); } diff --git a/language/parser.hpp b/language/parser.hpp index fc1c9e2..001b976 100644 --- a/language/parser.hpp +++ b/language/parser.hpp @@ -3,7 +3,8 @@ enum AstType { Statements, While, If, FunctionCall, Assignment, Condition, BinExpresion, - Identifier, Number, Boolean, Function + Identifier, InterpolatedString, + Number, Boolean, Function }; peglib::peg& get_parser();