diff options
| author | Li Jin <dragon-fly@qq.com> | 2021-03-08 21:02:05 +0800 |
|---|---|---|
| committer | Li Jin <dragon-fly@qq.com> | 2021-03-08 21:02:05 +0800 |
| commit | 8acb48264d3ae87e5cdae2fea4207be22cf08a97 (patch) | |
| tree | 8f260c52388be52c9fd1b5b9d262300b21771ca8 | |
| parent | 34326185b0aaf63c0af8b0e8a07f928aa5a74eaf (diff) | |
| download | yuescript-8acb48264d3ae87e5cdae2fea4207be22cf08a97.tar.gz yuescript-8acb48264d3ae87e5cdae2fea4207be22cf08a97.tar.bz2 yuescript-8acb48264d3ae87e5cdae2fea4207be22cf08a97.zip | |
add new syntax for issue #41. fix a issue for destructure syntax with TableBlock. try fix luarocks installing problem again for issue #42.
Diffstat (limited to '')
| -rw-r--r-- | CMakeLists.txt | 72 | ||||
| -rw-r--r-- | spec/inputs/destructure.yue | 23 | ||||
| -rw-r--r-- | spec/inputs/metatable.yue | 11 | ||||
| -rw-r--r-- | src/yuescript/ast.hpp | 2 | ||||
| -rw-r--r-- | src/yuescript/yue_ast.h | 2 | ||||
| -rw-r--r-- | src/yuescript/yue_compiler.cpp | 188 | ||||
| -rw-r--r-- | src/yuescript/yue_parser.cpp | 4 |
7 files changed, 195 insertions, 107 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index ce5a7f7..55bcd7d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt | |||
| @@ -1,42 +1,46 @@ | |||
| 1 | project ( yue CXX ) | 1 | project(yue CXX) |
| 2 | cmake_minimum_required ( VERSION 3.1 ) | 2 | cmake_minimum_required(VERSION 3.1) |
| 3 | 3 | ||
| 4 | MESSAGE(STATUS "Lua: using information from luarocks") | 4 | SET(LUA_LIBDIR ${LUA_INCDIR}/../lib " " ${LUA_INCDIR}/../../lib) |
| 5 | 5 | ||
| 6 | MESSAGE(STATUS "LUA_LIBDIR: " ${LUA_INCDIR}/../lib " " ${LUA_INCDIR}/../../lib ) | 6 | find_package(Lua) |
| 7 | MESSAGE(STATUS "LUA_INCDIR: " ${LUA_INCDIR}) | 7 | IF(LUA_FOUND) |
| 8 | MESSAGE(STATUS "LUA: " ${LUA}) | 8 | SET(LUA_LIBRARIES "${LUA_LIBRARY}") |
| 9 | 9 | ELSE(LUA_FOUND) | |
| 10 | SET(LUA_EXECUTABLE "${LUA}") | 10 | MESSAGE(STATUS "Lua: using information from luarocks") |
| 11 | SET(LUA_INCLUDE_DIR "${LUA_INCDIR}") | 11 | SET(LUA_INCLUDE_DIR "${LUA_INCDIR}") |
| 12 | 12 | GET_FILENAME_COMPONENT(LUA_EXEC_NAME ${LUA} NAME_WE) | |
| 13 | GET_FILENAME_COMPONENT(LUA_EXEC_NAME ${LUA} NAME_WE) | 13 | IF(LUA_EXEC_NAME STREQUAL "luajit") |
| 14 | IF(LUA_EXEC_NAME STREQUAL "luajit") | 14 | FIND_LIBRARY(LUA_LIBRARIES |
| 15 | FIND_LIBRARY(LUA_LIBRARIES | 15 | NAMES luajit libluajit |
| 16 | NAMES luajit libluajit | 16 | PATHS ${LUA_LIBDIR} |
| 17 | PATHS ${LUA_INCDIR}/../lib ${LUA_INCDIR}/../../lib | 17 | NO_DEFAULT_PATH) |
| 18 | NO_DEFAULT_PATH) | 18 | ELSEIF(LUA_EXEC_NAME MATCHES "lua.*") |
| 19 | ELSEIF(LUA_EXEC_NAME MATCHES "lua.*") | 19 | FIND_LIBRARY(LUA_LIBRARIES |
| 20 | FIND_LIBRARY(LUA_LIBRARIES | 20 | NAMES lua lua54 lua53 lua52 lua51 liblua liblua54 liblua53 liblua52 liblua51 liblua5.4 liblua5.3 liblua5.2 liblua5.1 |
| 21 | NAMES lua lua54 lua53 lua52 lua51 liblua liblua54 liblua53 liblua52 liblua51 liblua5.4 liblua5.3 liblua5.2 liblua5.1 | 21 | PATHS ${LUA_LIBDIR} |
| 22 | PATHS ${LUA_INCDIR}/../lib ${LUA_INCDIR}/../../lib | 22 | NO_DEFAULT_PATH) |
| 23 | NO_DEFAULT_PATH) | 23 | ENDIF(LUA_EXEC_NAME) |
| 24 | ENDIF() | 24 | ENDIF(LUA_FOUND) |
| 25 | |||
| 26 | MESSAGE(STATUS "Lua: " ${LUA}) | ||
| 27 | MESSAGE(STATUS "Lua include: " ${LUA_INCLUDE_DIR}) | ||
| 25 | MESSAGE(STATUS "Lua library: ${LUA_LIBRARIES}") | 28 | MESSAGE(STATUS "Lua library: ${LUA_LIBRARIES}") |
| 26 | 29 | ||
| 27 | enable_language( CXX ) | 30 | enable_language(CXX) |
| 28 | include_directories( src ${LUA_INCLUDE_DIR} ) | 31 | include_directories(src ${LUA_INCLUDE_DIR}) |
| 29 | add_definitions( -std=c++17 -O3 -fPIC ) | 32 | add_definitions(-std=c++17 -O3 -fPIC) |
| 30 | 33 | ||
| 31 | add_library( libyue MODULE src/yuescript/ast.cpp src/yuescript/parser.cpp src/yuescript/yue_parser.cpp src/yuescript/yue_compiler.cpp src/yuescript/yuescript.cpp) | 34 | add_library(libyue MODULE src/yuescript/ast.cpp src/yuescript/parser.cpp src/yuescript/yue_parser.cpp src/yuescript/yue_compiler.cpp src/yuescript/yuescript.cpp) |
| 32 | set_target_properties( libyue PROPERTIES PREFIX "" ) | 35 | set_target_properties(libyue PROPERTIES PREFIX "") |
| 33 | set_target_properties( libyue PROPERTIES OUTPUT_NAME "yue" ) | 36 | set_target_properties(libyue PROPERTIES OUTPUT_NAME "yue") |
| 34 | target_link_libraries( libyue ${LUA_LIBRARIES} ) | 37 | target_link_libraries(libyue ${LUA_LIBRARIES}) |
| 35 | 38 | ||
| 36 | add_executable( yue src/yuescript/ast.cpp src/yuescript/yue_compiler.cpp src/yuescript/yue_parser.cpp src/yuescript/yuescript.cpp src/yuescript/parser.cpp src/yue.cpp ) | 39 | add_executable(yue src/yuescript/ast.cpp src/yuescript/yue_compiler.cpp src/yuescript/yue_parser.cpp src/yuescript/yuescript.cpp src/yuescript/parser.cpp src/yue.cpp) |
| 37 | target_link_libraries( yue ${LUA_LIBRARIES} ) | 40 | target_link_libraries(yue ${LUA_LIBRARIES}) |
| 41 | target_link_options(yue PRIVATE -ldl -lpthread) | ||
| 38 | if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") | 42 | if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") |
| 39 | target_link_options( yue PRIVATE -ldl -lpthread -lstdc++fs ) | 43 | target_link_options(yue PRIVATE -lstdc++fs) |
| 40 | endif() | 44 | endif() |
| 41 | 45 | ||
| 42 | install(CODE "") | 46 | install(CODE "") |
diff --git a/spec/inputs/destructure.yue b/spec/inputs/destructure.yue index 6b52441..c68045d 100644 --- a/spec/inputs/destructure.yue +++ b/spec/inputs/destructure.yue | |||
| @@ -41,7 +41,28 @@ do | |||
| 41 | "Bellagio, Italy 22021" | 41 | "Bellagio, Italy 22021" |
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | {poet: {:name, address: {street, city}}} = futurists | 44 | do {poet: {:name, address: {street, city}}} = futurists |
| 45 | |||
| 46 | do { | ||
| 47 | :sculptor | ||
| 48 | :painter | ||
| 49 | poet: | ||
| 50 | :name | ||
| 51 | address: | ||
| 52 | * street | ||
| 53 | * city | ||
| 54 | } = futurists | ||
| 55 | |||
| 56 | do | ||
| 57 | a: | ||
| 58 | b: c | ||
| 59 | d: e = tb | ||
| 60 | |||
| 61 | do | ||
| 62 | a: | ||
| 63 | * b: c | ||
| 64 | * d: e | ||
| 65 | * f = tb | ||
| 45 | 66 | ||
| 46 | -- | 67 | -- |
| 47 | 68 | ||
diff --git a/spec/inputs/metatable.yue b/spec/inputs/metatable.yue index 13ea917..100844c 100644 --- a/spec/inputs/metatable.yue +++ b/spec/inputs/metatable.yue | |||
| @@ -48,4 +48,15 @@ with tb | |||
| 48 | b = t#.close#.test | 48 | b = t#.close#.test |
| 49 | c = t #.close# .test | 49 | c = t #.close# .test |
| 50 | 50 | ||
| 51 | #:mt = a | ||
| 52 | a = #:mt | ||
| 53 | a = #:__index:mt | ||
| 54 | |||
| 55 | local index | ||
| 56 | #:__index:index = a | ||
| 57 | :index# = a | ||
| 58 | |||
| 59 | do #:{new:ctor, :update} = a | ||
| 60 | do {new:ctor, :update} = a.# | ||
| 61 | |||
| 51 | nil | 62 | nil |
diff --git a/src/yuescript/ast.hpp b/src/yuescript/ast.hpp index eb5cd69..162a82e 100644 --- a/src/yuescript/ast.hpp +++ b/src/yuescript/ast.hpp | |||
| @@ -420,7 +420,7 @@ public: | |||
| 420 | return false; | 420 | return false; |
| 421 | } | 421 | } |
| 422 | 422 | ||
| 423 | const node_container& objects() const { | 423 | const node_container& objects() const { |
| 424 | return m_objects; | 424 | return m_objects; |
| 425 | } | 425 | } |
| 426 | 426 | ||
diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h index b673eb3..96968c9 100644 --- a/src/yuescript/yue_ast.h +++ b/src/yuescript/yue_ast.h | |||
| @@ -431,7 +431,7 @@ AST_NODE(meta_variable_pair) | |||
| 431 | AST_END(meta_variable_pair) | 431 | AST_END(meta_variable_pair) |
| 432 | 432 | ||
| 433 | AST_NODE(meta_normal_pair) | 433 | AST_NODE(meta_normal_pair) |
| 434 | ast_sel<true, Name_t, Exp_t> key; | 434 | ast_sel<false, Name_t, Exp_t> key; |
| 435 | ast_sel<true, Exp_t, TableBlock_t> value; | 435 | ast_sel<true, Exp_t, TableBlock_t> value; |
| 436 | AST_MEMBER(meta_normal_pair, &key, &value) | 436 | AST_MEMBER(meta_normal_pair, &key, &value) |
| 437 | AST_END(meta_normal_pair) | 437 | AST_END(meta_normal_pair) |
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index a958462..e8d028d 100644 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp | |||
| @@ -59,7 +59,7 @@ inline std::string s(std::string_view sv) { | |||
| 59 | return std::string(sv); | 59 | return std::string(sv); |
| 60 | } | 60 | } |
| 61 | 61 | ||
| 62 | const std::string_view version = "0.7.1"sv; | 62 | const std::string_view version = "0.7.2"sv; |
| 63 | const std::string_view extension = "yue"sv; | 63 | const std::string_view extension = "yue"sv; |
| 64 | 64 | ||
| 65 | class YueCompilerImpl { | 65 | class YueCompilerImpl { |
| @@ -1366,19 +1366,32 @@ private: | |||
| 1366 | 1366 | ||
| 1367 | std::list<DestructItem> destructFromExp(ast_node* node) { | 1367 | std::list<DestructItem> destructFromExp(ast_node* node) { |
| 1368 | const node_container* tableItems = nullptr; | 1368 | const node_container* tableItems = nullptr; |
| 1369 | if (ast_is<Exp_t>(node)) { | 1369 | switch (node->getId()) { |
| 1370 | auto item = singleValueFrom(node)->item.get(); | 1370 | case id<Exp_t>(): { |
| 1371 | if (!item) throw std::logic_error(_info.errorMessage("invalid destructure value"sv, node)); | 1371 | auto item = singleValueFrom(node)->item.get(); |
| 1372 | auto tbA = item->getByPath<TableLit_t>(); | 1372 | if (!item) throw std::logic_error(_info.errorMessage("invalid destructure value"sv, node)); |
| 1373 | if (tbA) { | 1373 | auto tbA = item->getByPath<TableLit_t>(); |
| 1374 | tableItems = &tbA->values.objects(); | 1374 | if (tbA) { |
| 1375 | } else { | 1375 | tableItems = &tbA->values.objects(); |
| 1376 | auto tbB = ast_cast<simple_table_t>(item); | 1376 | } else { |
| 1377 | if (tbB) tableItems = &tbB->pairs.objects(); | 1377 | auto tbB = ast_cast<simple_table_t>(item); |
| 1378 | if (tbB) tableItems = &tbB->pairs.objects(); | ||
| 1379 | } | ||
| 1380 | break; | ||
| 1381 | } | ||
| 1382 | case id<TableBlock_t>(): { | ||
| 1383 | auto table = ast_cast<TableBlock_t>(node); | ||
| 1384 | tableItems = &table->values.objects(); | ||
| 1385 | break; | ||
| 1378 | } | 1386 | } |
| 1379 | } else if (auto table = ast_cast<TableBlock_t>(node)) { | 1387 | case id<TableBlockIndent_t>(): { |
| 1380 | tableItems = &table->values.objects(); | 1388 | auto table = ast_cast<TableBlockIndent_t>(node); |
| 1389 | tableItems = &table->values.objects(); | ||
| 1390 | break; | ||
| 1391 | } | ||
| 1392 | default: YUEE("AST node mismatch", node); break; | ||
| 1381 | } | 1393 | } |
| 1394 | if (!tableItems) throw std::logic_error(_info.errorMessage("invalid destructure value"sv, node)); | ||
| 1382 | std::list<DestructItem> pairs; | 1395 | std::list<DestructItem> pairs; |
| 1383 | int index = 0; | 1396 | int index = 0; |
| 1384 | for (auto pair : *tableItems) { | 1397 | for (auto pair : *tableItems) { |
| @@ -1412,7 +1425,7 @@ private: | |||
| 1412 | pairs.push_back({ | 1425 | pairs.push_back({ |
| 1413 | isVariable, | 1426 | isVariable, |
| 1414 | varName, | 1427 | varName, |
| 1415 | s("["sv) + std::to_string(index) + s("]"sv) | 1428 | '[' + std::to_string(index) + ']' |
| 1416 | }); | 1429 | }); |
| 1417 | } | 1430 | } |
| 1418 | break; | 1431 | break; |
| @@ -1429,23 +1442,29 @@ private: | |||
| 1429 | } | 1442 | } |
| 1430 | case id<normal_pair_t>(): { | 1443 | case id<normal_pair_t>(): { |
| 1431 | auto np = static_cast<normal_pair_t*>(pair); | 1444 | auto np = static_cast<normal_pair_t*>(pair); |
| 1432 | auto key = np->key->getByPath<Name_t>(); | 1445 | std::string keyName; |
| 1433 | if (!key) throw std::logic_error(_info.errorMessage("invalid key for destructure"sv, np)); | 1446 | if (np->key) { |
| 1447 | auto key = np->key->getByPath<Name_t>(); | ||
| 1448 | if (!key) throw std::logic_error(_info.errorMessage("invalid key for destructure"sv, np)); | ||
| 1449 | keyName = _parser.toString(key); | ||
| 1450 | if (Keywords.find(keyName) != Keywords.end()) { | ||
| 1451 | keyName = s("[\""sv) + keyName + s("\"]"sv); | ||
| 1452 | } else { | ||
| 1453 | keyName = s("."sv) + keyName; | ||
| 1454 | } | ||
| 1455 | } | ||
| 1434 | if (auto exp = np->value.as<Exp_t>()) { | 1456 | if (auto exp = np->value.as<Exp_t>()) { |
| 1435 | if (!isAssignable(exp)) throw std::logic_error(_info.errorMessage("can't destructure value"sv, exp)); | 1457 | if (!isAssignable(exp)) throw std::logic_error(_info.errorMessage("can't destructure value"sv, exp)); |
| 1436 | auto item = singleValueFrom(exp)->item.get(); | 1458 | auto item = singleValueFrom(exp)->item.get(); |
| 1437 | if (ast_is<simple_table_t>(item) || | 1459 | if (ast_is<simple_table_t>(item) || |
| 1438 | item->getByPath<TableLit_t>()) { | 1460 | item->getByPath<TableLit_t>()) { |
| 1439 | auto subPairs = destructFromExp(exp); | 1461 | auto subPairs = destructFromExp(exp); |
| 1440 | auto name = _parser.toString(key); | ||
| 1441 | for (auto& p : subPairs) { | 1462 | for (auto& p : subPairs) { |
| 1442 | if (Keywords.find(name) != Keywords.end()) { | 1463 | pairs.push_back({ |
| 1443 | pairs.push_back({p.isVariable, p.name, | 1464 | p.isVariable, |
| 1444 | s("[\""sv) + name + s("\"]"sv) + p.structure}); | 1465 | p.name, |
| 1445 | } else { | 1466 | keyName + p.structure |
| 1446 | pairs.push_back({p.isVariable, p.name, | 1467 | }); |
| 1447 | s("."sv) + name + p.structure}); | ||
| 1448 | } | ||
| 1449 | } | 1468 | } |
| 1450 | } else { | 1469 | } else { |
| 1451 | bool lintGlobal = _config.lintGlobalVariable; | 1470 | bool lintGlobal = _config.lintGlobalVariable; |
| @@ -1458,32 +1477,39 @@ private: | |||
| 1458 | varName = std::move(temp.back()); | 1477 | varName = std::move(temp.back()); |
| 1459 | } | 1478 | } |
| 1460 | _config.lintGlobalVariable = lintGlobal; | 1479 | _config.lintGlobalVariable = lintGlobal; |
| 1461 | auto name = _parser.toString(key); | 1480 | pairs.push_back({ |
| 1462 | if (Keywords.find(name) != Keywords.end()) { | 1481 | isVariable, |
| 1463 | pairs.push_back({ | 1482 | varName, |
| 1464 | isVariable, | 1483 | keyName |
| 1465 | varName, | 1484 | }); |
| 1466 | s("[\""sv) + name + s("\"]"sv) | ||
| 1467 | }); | ||
| 1468 | } else { | ||
| 1469 | pairs.push_back({ | ||
| 1470 | isVariable, | ||
| 1471 | varName, | ||
| 1472 | s("."sv) + name | ||
| 1473 | }); | ||
| 1474 | } | ||
| 1475 | } | 1485 | } |
| 1476 | break; | 1486 | break; |
| 1477 | } | 1487 | } |
| 1478 | if (np->value.is<TableBlock_t>()) { | 1488 | if (np->value.is<TableBlock_t>()) { |
| 1479 | auto subPairs = destructFromExp(pair); | 1489 | auto subPairs = destructFromExp(np->value); |
| 1480 | for (auto& p : subPairs) { | 1490 | for (auto& p : subPairs) { |
| 1481 | pairs.push_back({p.isVariable, p.name, | 1491 | pairs.push_back({ |
| 1482 | s("."sv) + _parser.toString(key) + p.structure}); | 1492 | p.isVariable, |
| 1493 | p.name, | ||
| 1494 | keyName + p.structure | ||
| 1495 | }); | ||
| 1483 | } | 1496 | } |
| 1484 | } | 1497 | } |
| 1485 | break; | 1498 | break; |
| 1486 | } | 1499 | } |
| 1500 | case id<TableBlockIndent_t>(): { | ||
| 1501 | auto tb = static_cast<TableBlockIndent_t*>(pair); | ||
| 1502 | ++index; | ||
| 1503 | auto subPairs = destructFromExp(tb); | ||
| 1504 | for (auto& p : subPairs) { | ||
| 1505 | pairs.push_back({ | ||
| 1506 | p.isVariable, | ||
| 1507 | p.name, | ||
| 1508 | '[' + std::to_string(index) + ']' + p.structure | ||
| 1509 | }); | ||
| 1510 | } | ||
| 1511 | break; | ||
| 1512 | } | ||
| 1487 | default: YUEE("AST node mismatch", pair); break; | 1513 | default: YUEE("AST node mismatch", pair); break; |
| 1488 | } | 1514 | } |
| 1489 | } | 1515 | } |
| @@ -1498,9 +1524,10 @@ private: | |||
| 1498 | auto exprs = assignment->expList->exprs.objects(); | 1524 | auto exprs = assignment->expList->exprs.objects(); |
| 1499 | auto values = assignment->action.to<Assign_t>()->values.objects(); | 1525 | auto values = assignment->action.to<Assign_t>()->values.objects(); |
| 1500 | size_t size = std::max(exprs.size(), values.size()); | 1526 | size_t size = std::max(exprs.size(), values.size()); |
| 1501 | ast_ptr<false, Exp_t> var; | 1527 | ast_list<false, ast_node> cache; |
| 1502 | if (exprs.size() < size) { | 1528 | if (exprs.size() < size) { |
| 1503 | var = toAst<Exp_t>("_"sv, x); | 1529 | auto var = toAst<Exp_t>("_"sv, x); |
| 1530 | cache.push_back(var); | ||
| 1504 | while (exprs.size() < size) exprs.emplace_back(var); | 1531 | while (exprs.size() < size) exprs.emplace_back(var); |
| 1505 | } | 1532 | } |
| 1506 | ast_ptr<false, Exp_t> nullNode; | 1533 | ast_ptr<false, Exp_t> nullNode; |
| @@ -1551,18 +1578,20 @@ private: | |||
| 1551 | case id<meta_normal_pair_t>(): { | 1578 | case id<meta_normal_pair_t>(): { |
| 1552 | auto mp = static_cast<meta_normal_pair_t*>(item); | 1579 | auto mp = static_cast<meta_normal_pair_t*>(item); |
| 1553 | auto newPair = item->new_ptr<normal_pair_t>(); | 1580 | auto newPair = item->new_ptr<normal_pair_t>(); |
| 1554 | switch (mp->key->getId()) { | 1581 | if (mp->key) { |
| 1555 | case id<Name_t>(): { | 1582 | switch (mp->key->getId()) { |
| 1556 | auto key = _parser.toString(mp->key); | 1583 | case id<Name_t>(): { |
| 1557 | _buf << "__"sv << key; | 1584 | auto key = _parser.toString(mp->key); |
| 1558 | auto newKey = toAst<KeyName_t>(clearBuf(), mp->key); | 1585 | _buf << "__"sv << key; |
| 1559 | newPair->key.set(newKey); | 1586 | auto newKey = toAst<KeyName_t>(clearBuf(), mp->key); |
| 1560 | break; | 1587 | newPair->key.set(newKey); |
| 1588 | break; | ||
| 1589 | } | ||
| 1590 | case id<Exp_t>(): | ||
| 1591 | newPair->key.set(mp->key); | ||
| 1592 | break; | ||
| 1593 | default: YUEE("AST node mismatch", mp->key); break; | ||
| 1561 | } | 1594 | } |
| 1562 | case id<Exp_t>(): | ||
| 1563 | newPair->key.set(mp->key); | ||
| 1564 | break; | ||
| 1565 | default: YUEE("AST node mismatch", mp->key); break; | ||
| 1566 | } | 1595 | } |
| 1567 | newPair->value.set(mp->value); | 1596 | newPair->value.set(mp->value); |
| 1568 | subMetaDestruct->values.push_back(newPair); | 1597 | subMetaDestruct->values.push_back(newPair); |
| @@ -5150,6 +5179,7 @@ private: | |||
| 5150 | str_list temp; | 5179 | str_list temp; |
| 5151 | incIndentOffset(); | 5180 | incIndentOffset(); |
| 5152 | auto metatable = table->new_ptr<simple_table_t>(); | 5181 | auto metatable = table->new_ptr<simple_table_t>(); |
| 5182 | ast_sel<false, Exp_t, TableBlock_t> metatableItem; | ||
| 5153 | for (auto pair : pairs) { | 5183 | for (auto pair : pairs) { |
| 5154 | bool isMetamethod = false; | 5184 | bool isMetamethod = false; |
| 5155 | switch (pair->getId()) { | 5185 | switch (pair->getId()) { |
| @@ -5161,6 +5191,9 @@ private: | |||
| 5161 | case id<meta_variable_pair_t>(): { | 5191 | case id<meta_variable_pair_t>(): { |
| 5162 | isMetamethod = true; | 5192 | isMetamethod = true; |
| 5163 | auto mp = static_cast<meta_variable_pair_t*>(pair); | 5193 | auto mp = static_cast<meta_variable_pair_t*>(pair); |
| 5194 | if (metatableItem) { | ||
| 5195 | throw std::logic_error(_info.errorMessage("too many metatable declarations"sv, mp->name)); | ||
| 5196 | } | ||
| 5164 | auto name = _parser.toString(mp->name); | 5197 | auto name = _parser.toString(mp->name); |
| 5165 | _buf << "__"sv << name << ':' << name; | 5198 | _buf << "__"sv << name << ':' << name; |
| 5166 | auto newPair = toAst<normal_pair_t>(clearBuf(), pair); | 5199 | auto newPair = toAst<normal_pair_t>(clearBuf(), pair); |
| @@ -5171,21 +5204,31 @@ private: | |||
| 5171 | isMetamethod = true; | 5204 | isMetamethod = true; |
| 5172 | auto mp = static_cast<meta_normal_pair_t*>(pair); | 5205 | auto mp = static_cast<meta_normal_pair_t*>(pair); |
| 5173 | auto newPair = pair->new_ptr<normal_pair_t>(); | 5206 | auto newPair = pair->new_ptr<normal_pair_t>(); |
| 5174 | switch (mp->key->getId()) { | 5207 | if (mp->key) { |
| 5175 | case id<Name_t>(): { | 5208 | if (metatableItem) { |
| 5176 | auto key = _parser.toString(mp->key); | 5209 | throw std::logic_error(_info.errorMessage("too many metatable declarations"sv, mp->key)); |
| 5177 | _buf << "__"sv << key; | ||
| 5178 | auto newKey = toAst<KeyName_t>(clearBuf(), mp->key); | ||
| 5179 | newPair->key.set(newKey); | ||
| 5180 | break; | ||
| 5181 | } | 5210 | } |
| 5182 | case id<Exp_t>(): | 5211 | switch (mp->key->getId()) { |
| 5183 | newPair->key.set(mp->key); | 5212 | case id<Name_t>(): { |
| 5184 | break; | 5213 | auto key = _parser.toString(mp->key); |
| 5185 | default: YUEE("AST node mismatch", mp->key); break; | 5214 | _buf << "__"sv << key; |
| 5215 | auto newKey = toAst<KeyName_t>(clearBuf(), mp->key); | ||
| 5216 | newPair->key.set(newKey); | ||
| 5217 | break; | ||
| 5218 | } | ||
| 5219 | case id<Exp_t>(): | ||
| 5220 | newPair->key.set(mp->key); | ||
| 5221 | break; | ||
| 5222 | default: YUEE("AST node mismatch", mp->key); break; | ||
| 5223 | } | ||
| 5224 | newPair->value.set(mp->value); | ||
| 5225 | metatable->pairs.push_back(newPair); | ||
| 5226 | } else { | ||
| 5227 | if (!metatable->pairs.empty()) { | ||
| 5228 | throw std::logic_error(_info.errorMessage("too many metatable declarations"sv, mp->value)); | ||
| 5229 | } | ||
| 5230 | metatableItem.set(mp->value); | ||
| 5186 | } | 5231 | } |
| 5187 | newPair->value.set(mp->value); | ||
| 5188 | metatable->pairs.push_back(newPair); | ||
| 5189 | break; | 5232 | break; |
| 5190 | } | 5233 | } |
| 5191 | default: YUEE("AST node mismatch", pair); break; | 5234 | default: YUEE("AST node mismatch", pair); break; |
| @@ -5194,7 +5237,7 @@ private: | |||
| 5194 | temp.back() = indent() + temp.back() + (pair == pairs.back() ? Empty : s(","sv)) + nll(pair); | 5237 | temp.back() = indent() + temp.back() + (pair == pairs.back() ? Empty : s(","sv)) + nll(pair); |
| 5195 | } | 5238 | } |
| 5196 | } | 5239 | } |
| 5197 | if (metatable->pairs.empty()) { | 5240 | if (metatable->pairs.empty() && !metatableItem) { |
| 5198 | out.push_back(s("{"sv) + nll(table) + join(temp)); | 5241 | out.push_back(s("{"sv) + nll(table) + join(temp)); |
| 5199 | decIndentOffset(); | 5242 | decIndentOffset(); |
| 5200 | out.back() += (indent() + s("}"sv)); | 5243 | out.back() += (indent() + s("}"sv)); |
| @@ -5211,7 +5254,16 @@ private: | |||
| 5211 | } | 5254 | } |
| 5212 | tabStr += ", "sv; | 5255 | tabStr += ", "sv; |
| 5213 | str_list tmp; | 5256 | str_list tmp; |
| 5214 | transform_simple_table(metatable, tmp); | 5257 | if (!metatable->pairs.empty()) { |
| 5258 | transform_simple_table(metatable, tmp); | ||
| 5259 | } else switch (metatableItem->getId()) { | ||
| 5260 | case id<Exp_t>(): | ||
| 5261 | transformExp(static_cast<Exp_t*>(metatableItem.get()), tmp, ExpUsage::Closure); | ||
| 5262 | break; | ||
| 5263 | case id<TableBlock_t>(): | ||
| 5264 | transformTableBlock(static_cast<TableBlock_t*>(metatableItem.get()), tmp); | ||
| 5265 | break; | ||
| 5266 | } | ||
| 5215 | tabStr += tmp.back(); | 5267 | tabStr += tmp.back(); |
| 5216 | tabStr += s(")"sv); | 5268 | tabStr += s(")"sv); |
| 5217 | out.push_back(tabStr); | 5269 | out.push_back(tabStr); |
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp index ec6c997..2234a59 100644 --- a/src/yuescript/yue_parser.cpp +++ b/src/yuescript/yue_parser.cpp | |||
| @@ -328,7 +328,7 @@ YueParser::YueParser() { | |||
| 328 | 328 | ||
| 329 | unary_operator = | 329 | unary_operator = |
| 330 | expr('-') >> not_(set(">=") | space_one) | | 330 | expr('-') >> not_(set(">=") | space_one) | |
| 331 | expr('#') | | 331 | expr('#') >> not_(':') | |
| 332 | expr('~') >> not_(expr('=') | space_one) | | 332 | expr('~') >> not_(expr('=') | space_one) | |
| 333 | expr("not") >> not_(AlphaNum); | 333 | expr("not") >> not_(AlphaNum); |
| 334 | unary_exp = *(Space >> unary_operator) >> expo_exp; | 334 | unary_exp = *(Space >> unary_operator) >> expo_exp; |
| @@ -525,7 +525,7 @@ YueParser::YueParser() { | |||
| 525 | 525 | ||
| 526 | meta_variable_pair = sym(':') >> Variable >> expr('#'); | 526 | meta_variable_pair = sym(':') >> Variable >> expr('#'); |
| 527 | 527 | ||
| 528 | meta_normal_pair = (Space >> Name | sym('[') >> Exp >> sym(']')) >> expr("#:") >> | 528 | meta_normal_pair = Space >> -(Name | symx('[') >> Exp >> sym(']')) >> expr("#:") >> |
| 529 | (Exp | TableBlock | +(SpaceBreak) >> Exp); | 529 | (Exp | TableBlock | +(SpaceBreak) >> Exp); |
| 530 | 530 | ||
| 531 | KeyValue = variable_pair | normal_pair | meta_variable_pair | meta_normal_pair; | 531 | KeyValue = variable_pair | normal_pair | meta_variable_pair | meta_normal_pair; |
