diff --git a/jerry-core/parser/js/lexer.cpp b/jerry-core/parser/js/lexer.cpp index a3926cc55..c1f1d20ce 100644 --- a/jerry-core/parser/js/lexer.cpp +++ b/jerry-core/parser/js/lexer.cpp @@ -15,9 +15,14 @@ */ #include "ecma-helpers.h" +#include "ecma-exceptions.h" #include "jrt-libc-includes.h" #include "jsp-mm.h" #include "lexer.h" +#include "mem-allocator.h" +#include "opcodes.h" +#include "parser.h" +#include "stack.h" #include "syntax-errors.h" static token saved_token, prev_token, sent_token, empty_token; @@ -961,6 +966,76 @@ parse_string (void) return ret; } /* parse_string */ +/** + * Parse string literal (ECMA-262 v5, 7.8.5) + */ +static token +parse_regexp (void) +{ + token result; + bool is_char_class = false; + + /* Eat up '/' */ + JERRY_ASSERT ((ecma_char_t) LA (0) == '/'); + consume_char (); + new_token (); + + while (true) + { + ecma_char_t c = (ecma_char_t) LA (0); + + if (c == '\0') + { + PARSE_ERROR ("Unclosed string", token_start - buffer_start); + } + else if (c == '\n') + { + PARSE_ERROR ("RegExp literal shall not contain newline character", token_start - buffer_start); + } + else if (c == '\\') + { + consume_char (); + } + else if (c == '[') + { + is_char_class = true; + } + else if (c == ']') + { + is_char_class = false; + } + else if (c == '/' && !is_char_class) + { + /* Eat up '/' */ + consume_char (); + break; + } + + consume_char (); + } + + /* Try to parse RegExp flags */ + while (true) + { + ecma_char_t c = (ecma_char_t) LA (0); + + if (c == '\0' + || !ecma_char_is_word_char (c) + || ecma_char_is_line_terminator (c)) + { + break; + } + consume_char (); + } + + result = convert_string_to_token (TOK_REGEXP, + (const ecma_char_t*) token_start, + static_cast (buffer - token_start)); + + token_start = NULL; + return result; +} /* parse_regexp */ + static void grobble_whitespaces (void) { @@ -1084,10 +1159,27 @@ lexer_next_token_private (void) } } - if (c == '/' && LA (1) == '/') + + if (c == '/') { - replace_comment_by_newline (); - return lexer_next_token_private (); + if (LA (1) == '/') + { + replace_comment_by_newline (); + return lexer_next_token_private (); + } + else if (!(sent_token.type == TOK_NAME + || sent_token.type == TOK_NULL + || sent_token.type == TOK_BOOL + || sent_token.type == TOK_CLOSE_BRACE + || sent_token.type == TOK_CLOSE_SQUARE + || sent_token.type == TOK_CLOSE_PAREN + || sent_token.type == TOK_SMALL_INT + || sent_token.type == TOK_NUMBER + || sent_token.type == TOK_STRING + || sent_token.type == TOK_REGEXP)) + { + return parse_regexp (); + } } switch (c) @@ -1203,7 +1295,6 @@ lexer_next_token (void) prev_token = sent_token; sent_token = lexer_next_token_private (); - if (sent_token.type == TOK_NEWLINE) { dump_current_line (); diff --git a/jerry-core/parser/js/lexer.h b/jerry-core/parser/js/lexer.h index f67b6a991..3d09d0df8 100644 --- a/jerry-core/parser/js/lexer.h +++ b/jerry-core/parser/js/lexer.h @@ -99,7 +99,7 @@ typedef enum __attr_packed___ TOK_OPEN_PAREN, // ( TOK_CLOSE_PAREN, //) TOK_OPEN_SQUARE, // [ - TOK_CLOSE_SQUARE, // [ + TOK_CLOSE_SQUARE, // ] TOK_DOT, // . TOK_SEMICOLON, // ; @@ -152,6 +152,7 @@ typedef enum __attr_packed___ TOK_DIV, // / TOK_DIV_EQ, // /= TOK_EMPTY, + TOK_REGEXP, // RegularExpressionLiteral (/.../gim) } token_type; typedef size_t locus; @@ -170,6 +171,9 @@ typedef struct #define TOKEN_EMPTY_INITIALIZER {0, TOK_EMPTY, 0} void lexer_init (const char *, size_t, bool); +void lexer_init_source (const char *, size_t); + +void lexer_free (void); token lexer_next_token (void); void lexer_save_token (token); diff --git a/jerry-core/parser/js/opcodes-dumper.cpp b/jerry-core/parser/js/opcodes-dumper.cpp index 16ce7bfec..abc733033 100644 --- a/jerry-core/parser/js/opcodes-dumper.cpp +++ b/jerry-core/parser/js/opcodes-dumper.cpp @@ -843,6 +843,34 @@ dump_number_assignment_res (lit_cpointer_t lit_id) return op; } +void +dump_regexp_assignment (operand op, lit_cpointer_t lit_id) +{ + switch (op.type) + { + case OPERAND_LITERAL: + { + const opcode_t opcode = getop_assignment (LITERAL_TO_REWRITE, OPCODE_ARG_TYPE_REGEXP, LITERAL_TO_REWRITE); + serializer_dump_op_meta (create_op_meta_101 (opcode, op.data.lit_id, lit_id)); + break; + } + case OPERAND_TMP: + { + const opcode_t opcode = getop_assignment (op.data.uid, OPCODE_ARG_TYPE_REGEXP, LITERAL_TO_REWRITE); + serializer_dump_op_meta (create_op_meta_001 (opcode, lit_id)); + break; + } + } +} + +operand +dump_regexp_assignment_res (lit_cpointer_t lit_id) +{ + operand op = tmp_operand (); + dump_regexp_assignment (op, lit_id); + return op; +} + void dump_smallint_assignment (operand op, idx_t uid) { diff --git a/jerry-core/parser/js/opcodes-dumper.h b/jerry-core/parser/js/opcodes-dumper.h index 94719a6e7..72ed8573c 100644 --- a/jerry-core/parser/js/opcodes-dumper.h +++ b/jerry-core/parser/js/opcodes-dumper.h @@ -69,6 +69,8 @@ void dump_string_assignment (operand, lit_cpointer_t); operand dump_string_assignment_res (lit_cpointer_t); void dump_number_assignment (operand, lit_cpointer_t); operand dump_number_assignment_res (lit_cpointer_t); +void dump_regexp_assignment (operand, lit_cpointer_t); +operand dump_regexp_assignment_res (lit_cpointer_t); void dump_smallint_assignment (operand, idx_t); operand dump_smallint_assignment_res (idx_t); void dump_undefined_assignment (operand); diff --git a/jerry-core/parser/js/parser.cpp b/jerry-core/parser/js/parser.cpp index e6014f0c1..a2696256c 100644 --- a/jerry-core/parser/js/parser.cpp +++ b/jerry-core/parser/js/parser.cpp @@ -1,4 +1,5 @@ /* Copyright 2014-2015 Samsung Electronics Co., Ltd. + * Copyright 2015 University of Szeged. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,6 +23,7 @@ #include "opcodes-dumper.h" #include "opcodes-native-call.h" #include "parser.h" +#include "re-parser.h" #include "scopes-tree.h" #include "serializer.h" #include "stack.h" @@ -745,6 +747,7 @@ parse_object_literal (void) | 'false' | number_literal | string_literal + | regexp_literal ; */ static operand parse_literal (void) @@ -753,6 +756,7 @@ parse_literal (void) { case TOK_NUMBER: return dump_number_assignment_res (token_data_as_lit_cp ()); case TOK_STRING: return dump_string_assignment_res (token_data_as_lit_cp ()); + case TOK_REGEXP: return dump_regexp_assignment_res (token_data_as_lit_cp ()); case TOK_NULL: return dump_null_assignment_res (); case TOK_BOOL: return dump_boolean_assignment_res ((bool) token_data ()); case TOK_SMALL_INT: return dump_smallint_assignment_res ((idx_t) token_data ()); @@ -786,6 +790,7 @@ parse_primary_expression (void) case TOK_BOOL: case TOK_SMALL_INT: case TOK_NUMBER: + case TOK_REGEXP: case TOK_STRING: return parse_literal (); case TOK_NAME: return literal_operand (token_data_as_lit_cp ()); case TOK_OPEN_SQUARE: return parse_array_literal (); diff --git a/jerry-core/parser/js/scopes-tree.cpp b/jerry-core/parser/js/scopes-tree.cpp index ce083e868..7a00d9399 100644 --- a/jerry-core/parser/js/scopes-tree.cpp +++ b/jerry-core/parser/js/scopes-tree.cpp @@ -291,6 +291,7 @@ generate_opcode (scopes_tree tree, opcode_counter_t opc_index, lit_id_hash_table } case OPCODE_ARG_TYPE_NUMBER: case OPCODE_ARG_TYPE_NUMBER_NEGATE: + case OPCODE_ARG_TYPE_REGEXP: case OPCODE_ARG_TYPE_STRING: case OPCODE_ARG_TYPE_VARIABLE: { @@ -430,6 +431,7 @@ count_new_literals_in_opcode (scopes_tree tree, opcode_counter_t opc_index) } case OPCODE_ARG_TYPE_NUMBER: case OPCODE_ARG_TYPE_NUMBER_NEGATE: + case OPCODE_ARG_TYPE_REGEXP: case OPCODE_ARG_TYPE_STRING: case OPCODE_ARG_TYPE_VARIABLE: { diff --git a/jerry-core/vm/opcodes-ecma-support.h b/jerry-core/vm/opcodes-ecma-support.h index 8fd39c9da..9826c63d2 100644 --- a/jerry-core/vm/opcodes-ecma-support.h +++ b/jerry-core/vm/opcodes-ecma-support.h @@ -29,6 +29,7 @@ #include "ecma-objects.h" #include "ecma-objects-general.h" #include "ecma-reference.h" +#include "ecma-regexp-object.h" #include "ecma-try-catch-macro.h" #include "serializer.h" diff --git a/jerry-core/vm/opcodes.cpp b/jerry-core/vm/opcodes.cpp index 04e04948f..d1e3a6fc5 100644 --- a/jerry-core/vm/opcodes.cpp +++ b/jerry-core/vm/opcodes.cpp @@ -1,4 +1,5 @@ /* Copyright 2014-2015 Samsung Electronics Co., Ltd. + * Copyright 2015 University of Szeged. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -162,6 +163,65 @@ opfunc_assignment (opcode_t opdata, /**< operation data */ dst_var_idx, ecma_make_number_value (num_p)); } + else if (type_value_right == OPCODE_ARG_TYPE_REGEXP) + { +#ifndef CONFIG_ECMA_COMPACT_PROFILE_DISABLE_REGEXP_BUILTIN + lit_cpointer_t lit_cp = serializer_get_literal_cp_by_uid (src_val_descr, + int_data->opcodes_p, + int_data->pos); + ecma_string_t *string_p = ecma_new_ecma_string_from_lit_cp (lit_cp); + + int32_t re_str_len = ecma_string_get_length (string_p); + MEM_DEFINE_LOCAL_ARRAY (re_str_p, re_str_len + 1, ecma_char_t); + + ssize_t zt_str_size = (ssize_t) sizeof (ecma_char_t) * (re_str_len + 1); + ecma_string_to_zt_string (string_p, re_str_p, zt_str_size); + + ecma_char_t *ch_p = re_str_p; + ecma_char_t *last_slash_p = NULL; + while (*ch_p) + { + if (*ch_p == '/') + { + last_slash_p = ch_p; + } + ch_p++; + } + + JERRY_ASSERT (last_slash_p != NULL); + JERRY_ASSERT ((re_str_p < last_slash_p) && (last_slash_p < ch_p)); + JERRY_ASSERT ((last_slash_p - re_str_p) > 0); + ecma_string_t *pattern_p = ecma_new_ecma_string (re_str_p, (ecma_length_t) (last_slash_p - re_str_p)); + ecma_string_t *flags_p = NULL; + + if ((ch_p - last_slash_p) > 1) + { + flags_p = ecma_new_ecma_string (last_slash_p + 1, (ecma_length_t) ((ch_p - last_slash_p - 1))); + } + + ECMA_TRY_CATCH (regexp_obj_value, + ecma_op_create_regexp_object (pattern_p, flags_p), + ret_value); + + ret_value = set_variable_value (int_data, + int_data->pos, + dst_var_idx, + regexp_obj_value); + + ECMA_FINALIZE (regexp_obj_value); + + ecma_deref_ecma_string (pattern_p); + if (flags_p != NULL) + { + ecma_deref_ecma_string (flags_p); + } + + MEM_FINALIZE_LOCAL_ARRAY (re_str_p) + ecma_deref_ecma_string (string_p); +#else + JERRY_UNIMPLEMENTED ("Regular Expressions are not supported in compact profile!"); +#endif /* CONFIG_ECMA_COMPACT_PROFILE_DISABLE_REGEXP_BUILTIN */ + } else { JERRY_ASSERT (type_value_right == OPCODE_ARG_TYPE_SMALLINT_NEGATE); diff --git a/jerry-core/vm/opcodes.h b/jerry-core/vm/opcodes.h index 1afea172c..ff7d8594a 100644 --- a/jerry-core/vm/opcodes.h +++ b/jerry-core/vm/opcodes.h @@ -50,7 +50,8 @@ typedef enum OPCODE_ARG_TYPE_NUMBER, /**< index of number literal */ OPCODE_ARG_TYPE_NUMBER_NEGATE, /**< index of number literal with negation */ OPCODE_ARG_TYPE_STRING, /**< index of string literal */ - OPCODE_ARG_TYPE_VARIABLE /**< index of variable name */ + OPCODE_ARG_TYPE_VARIABLE, /**< index of string literal with variable name */ + OPCODE_ARG_TYPE_REGEXP /**< index of string literal with regular expression */ } opcode_arg_type_operand; /** diff --git a/tests/jerry/regexp-alternatives.js b/tests/jerry/regexp-alternatives.js new file mode 100644 index 000000000..dcb102ad8 --- /dev/null +++ b/tests/jerry/regexp-alternatives.js @@ -0,0 +1,61 @@ +// Copyright 2015 Samsung Electronics Co., Ltd. +// Copyright 2015 University of Szeged. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +var r; + +r = new RegExp ("a|b"); +assert (r.exec("a") == "a"); + +r = new RegExp ("a|b"); +assert (r.exec("b") == "b"); + +r = new RegExp ("a|b|c"); +assert (r.exec("b") == "b"); + +r = new RegExp ("a|b|c"); +assert (r.exec("c") == "c"); + +r = new RegExp ("a|b|c|d"); +assert (r.exec("") == undefined); + +r = new RegExp ("a|b|c|d"); +assert (r.exec("a") == "a"); + +r = new RegExp ("a|b|c|d"); +assert (r.exec("b") == "b"); + +r = new RegExp ("a|b|c|d"); +assert (r.exec("c") == "c"); + +r = new RegExp ("a|b|c|d"); +assert (r.exec("d") == "d"); + +r = new RegExp ("a|bb|c|d"); +assert (r.exec("e") == undefined); + +r = new RegExp ("a|bb|c|d"); +assert (r.exec("bb") == "bb"); + +r = new RegExp ("a|bb|c|d"); +assert (r.exec("bba") == "bb"); + +r = new RegExp ("a|bb|c|d"); +assert (r.exec("bbbb") == "bb"); + +r = new RegExp ("a|bb|c|d"); +assert (r.exec("a") == "a"); + +r = new RegExp ("a|bb|c|d"); +assert (r.exec("b") == undefined); diff --git a/tests/jerry/regexp-assertions.js b/tests/jerry/regexp-assertions.js new file mode 100644 index 000000000..a8656b691 --- /dev/null +++ b/tests/jerry/regexp-assertions.js @@ -0,0 +1,152 @@ +// Copyright 2015 Samsung Electronics Co., Ltd. +// Copyright 2015 University of Szeged. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +var t; + +t = new RegExp ("^alma$").exec("alma"); +assert (t == "alma"); + +t = new RegExp ("^alma$").exec("almaa"); +assert (t == undefined); + +t = new RegExp ("^alma$").exec("aalma"); +assert (t == undefined); + +t = new RegExp ("^alma").exec("alma"); +assert (t == "alma"); + +t = new RegExp ("^alma").exec("almaa"); +assert (t == "alma"); + +t = new RegExp ("^alma").exec("aalma"); +assert (t == undefined); + +t = new RegExp ("alma$").exec("alma"); +assert (t == "alma"); + +t = new RegExp ("alma$").exec("almaa"); +assert (t == undefined); + +t = new RegExp ("alma$").exec("aalma"); +assert (t == "alma"); + +t = new RegExp ("\\bis\\b").exec("This island is beautiful"); +assert (t == "is"); + +t = new RegExp ("\\Bis\\B").exec("This island is beautiful"); +assert (t == undefined); + +t = new RegExp ("\\Bis").exec("This island is beautiful"); +assert (t == "is"); + +t = new RegExp ("is\\B").exec("This island is beautiful"); +assert (t == "is"); + +t = new RegExp ("\\Bis\\b").exec("This island is beautiful"); +assert (t == "is"); + +t = new RegExp ("\\bis\\B").exec("This island is beautiful"); +assert (t == "is"); + +t = new RegExp ("al(?=(ma))").exec("al"); +assert (t == undefined); + +t = new RegExp ("al(?!(ma))").exec("ala"); +assert (t[0] == "al"); +assert (t[1] == undefined); + +t = new RegExp ("al(?=(ma))").exec("alma"); +assert (t[0] == "al"); +assert (t[1] == "ma"); + +t = new RegExp ("al(?=(ma))").exec("almama"); +assert (t[0] == "al"); +assert (t[1] == "ma"); + +t = new RegExp ("(al)(?=(ma))ma").exec("al"); +assert (t == undefined); + +t = new RegExp ("(al)(?=(ma)ma)").exec("al"); +assert (t == undefined); + +t = new RegExp ("al(?=(ma))*ma").exec("alma"); +assert (t[0] == "alma"); +assert (t[1] == undefined); + +t = new RegExp ("al(?!(ma))*ma").exec("alma"); +assert (t[0] == "alma"); +assert (t[1] == undefined); + +t = new RegExp ("al(?=(ma))ma").exec("alma"); +assert (t[0] == "alma"); +assert (t[1] == "ma"); + +t = new RegExp ("al(?!(ma))ma").exec("alma"); +assert (t == undefined); + +t = new RegExp ("(al)(?=(ma))ma").exec("almama"); +t = new RegExp ("(al)(?=(ma)ma)").exec("almama"); + +t = new RegExp ("al(?=(ma))ma").exec("almama"); +assert (t[0] == "alma"); +assert (t[1] == "ma"); + +t = new RegExp ("al(?=(ma)ma)").exec("almama"); +assert (t[0] == "al"); +assert (t[1] == "ma"); + +t = new RegExp ("al(?!(ma))ma").exec("almama"); +assert (t == undefined); + +t = new RegExp ("a(?=(a)(a))aab|aaac").exec("aaac"); +t = new RegExp ("a(?=(a)(a))aab|aaac").exec("aaab"); + +t = new RegExp ("(?!(a)b)|ab").exec("ab"); +assert (t[0] == "ab"); +assert (t[1] == undefined); + +t = new RegExp ("(?=(a)b)|ab").exec("ab"); +assert (t[0] == ""); +assert (t[1] == "a"); + +t = new RegExp ("(?=a|.)Dt").exec("Dt"); +assert (t == "Dt"); + +t = new RegExp ("(?=.|a)Dt").exec("Dt"); +assert (t == "Dt"); + +t = new RegExp ("(?=a|b)Dt").exec("Dt"); +assert (t == undefined); + +t = new RegExp ("(?=.|P)").exec("a"); +assert (t == ""); + +t = new RegExp ("(?=.)").exec("a"); +assert (t == ""); + +t = new RegExp ("(?!a|.)Dt").exec("Dt"); +assert (t == undefined); + +t = new RegExp ("(?!.|a)Dt").exec("Dt"); +assert (t == undefined); + +t = new RegExp ("(?!a|b)Dt").exec("Dt"); +assert (t == "Dt"); + +t = new RegExp ("(?!.|P)").exec("a"); +assert (t == ""); + +t = new RegExp ("(?!.)").exec("a"); +assert (t == ""); diff --git a/tests/jerry/regexp-backreference.js b/tests/jerry/regexp-backreference.js new file mode 100644 index 000000000..d638ab5da --- /dev/null +++ b/tests/jerry/regexp-backreference.js @@ -0,0 +1,27 @@ +// Copyright 2015 Samsung Electronics Co., Ltd. +// Copyright 2015 University of Szeged. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +var r; + +r = new RegExp ("(a)b\\1").exec("aba"); +assert (r[0] == "aba"); +assert (r[1] == "a"); + +r = new RegExp ("(a)b\\1").exec("b"); +assert (r == undefined); + +r = new RegExp ("(a)*b\\1").exec("b"); +assert (r[0] == "b"); +assert (r[1] == undefined); diff --git a/tests/jerry/regexp-capture-groups.js b/tests/jerry/regexp-capture-groups.js new file mode 100644 index 000000000..85bc8d21b --- /dev/null +++ b/tests/jerry/regexp-capture-groups.js @@ -0,0 +1,199 @@ +// Copyright 2015 Samsung Electronics Co., Ltd. +// Copyright 2015 University of Szeged. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +var r; + +// Simple test cases +r = new RegExp ("()"); +assert (r.exec ("a") == ","); + +r = new RegExp ("(a)"); +assert (r.exec ("a") == "a,a"); + +r = new RegExp ("((a)b)c"); +assert (r.exec ("abc") == "abc,ab,a"); + +r = new RegExp ("(a)*"); +assert (r.exec ("b")[0] == ""); +assert (r.exec ("b")[1] == undefined); +assert (r.exec ("aaaa") == "aaaa,a"); + +r = new RegExp ("(a)+"); +assert (r.exec ("aaaa") == "aaaa,a"); + +r = new RegExp ("(a){4}"); +assert (r.exec ("aaaa") == "aaaa,a"); + +r = new RegExp ("(a){1,2}"); +assert (r.exec ("a") == "a,a"); +assert (r.exec ("aa") == "aa,a"); +assert (r.exec ("aaaa") == "aa,a"); + +r = new RegExp ("(a)?"); +assert (r.exec ("a") == "a,a"); +assert (r.exec ("b")[0] == ""); +assert (r.exec ("b")[1] == undefined); + +// Test greedy iterations +r = new RegExp ("(a){1,3}a"); +assert (r.exec("aa") == "aa,a"); + +r = new RegExp ("(a){1,3}a"); +assert (r.exec("aaa") == "aaa,a"); + +r = new RegExp ("(a){1,3}"); +assert (r.exec("a") == "a,a"); + +r = new RegExp ("(a){1,3}"); +assert (r.exec("aaa") == "aaa,a"); + +r = new RegExp ("(a){1,3}"); +assert (r.exec("aaaa") == "aaa,a"); + +r = new RegExp ("(a){1,5}"); +assert (r.exec("aaaa") == "aaaa,a"); + +r = new RegExp ("(a|b){1,2}"); +assert (r.exec("a") == "a,a"); + +r = new RegExp ("(a|b){1,3}a"); +assert (r.exec("aaa") == "aaa,a"); + +r = new RegExp ("(a|b){1,3}a"); +assert (r.exec("aba") == "aba,b"); + +r = new RegExp ("(a|b){1,3}a"); +assert (r.exec("b") == undefined); + +r = new RegExp ("(a|b){1,3}a"); +assert (r.exec("bbb") == undefined); + +r = new RegExp ("(a|b){1,3}"); +assert (r.exec("a") == "a,a"); + +r = new RegExp ("(a|b){1,3}"); +assert (r.exec("aa") == "aa,a"); + +r = new RegExp ("(a|b){1,3}"); +assert (r.exec("aaa") == "aaa,a"); + +r = new RegExp ("(a|b){1,3}"); +assert (r.exec("ab") == "ab,b"); + +r = new RegExp ("(a|b){1,3}"); +assert (r.exec("aba") == "aba,a"); + +r = new RegExp ("(a|b){1,3}"); +assert (r.exec("bab") == "bab,b"); + +r = new RegExp ("(a|b){1,3}"); +assert (r.exec("bbb") == "bbb,b"); + +r = new RegExp ("(a|b){1,4}a"); +assert (r.exec("bbb") == undefined); + +r = new RegExp ("(a|b){1,4}"); +assert (r.exec("ab") == "ab,b"); + +r = new RegExp ("(a|b){1,4}"); +assert (r.exec("aba") == "aba,a"); + +r = new RegExp ("(a|b){1,4}"); +assert (r.exec("bbb") == "bbb,b"); + +r = new RegExp ("(a|b){1,5}"); +assert (r.exec("aba") == "aba,a"); + +r = new RegExp ("(a|b){1,5}"); +assert (r.exec("abab") == "abab,b"); + +r = new RegExp ("(a|b){1,5}"); +assert (r.exec("bbb") == "bbb,b"); + +r = new RegExp ("(aba)*"); +assert (r.exec("aaaa") == ","); + +r = new RegExp ("(aba)+"); +assert (r.exec("aaaa") == undefined); + +r = new RegExp ("(a|bb|c|d)"); +assert (r.exec("a") == "a,a"); + +r = new RegExp ("(a|b)"); +assert (r.exec("a") == "a,a"); + +r = new RegExp ("(a|b)+"); +assert (r.exec("aba") == "aba,a"); + +r = new RegExp ("(a|b)"); +assert (r.exec("b") == "b,b"); + +r = new RegExp ("(a)"); +assert (r.exec("a") == "a,a"); + +r = new RegExp ("(a)*"); +assert (r.exec("a") == "a,a"); + +r = new RegExp ("(a)*"); +assert (r.exec("aaaa") == "aaaa,a"); + +r = new RegExp ("(a)+"); +assert (r.exec("aaaa") == "aaaa,a"); + +r = new RegExp ("(a|aa){0,3}b"); +assert (r.exec("aaaaaab") == "aaaaaab,aa"); + +r = new RegExp ("((a){2,3}){4}b"); +assert (r.exec("aaaaaaaab") == "aaaaaaaab,aa,a"); + +// Test non-greedy iterations +r = new RegExp ("(a)+?"); +assert (r.exec("aaaa") == "a,a"); + +r = new RegExp ("(a)*?aa"); +assert (r.exec("aaaa") == "aa,"); + +r = new RegExp ("(aaa|aa)*?aa"); +assert (r.exec("aaaa")[0] == "aa"); +assert (r.exec("aaaa")[1] == undefined); + +r = new RegExp ("(a)??aa"); +assert (r.exec("aaaa")[0] == "aa"); +assert (r.exec("aaaa")[1] == undefined); + +r = new RegExp ("(a)?aa"); +assert (r.exec("aaaa") == "aaa,a"); + +r = new RegExp ("(()*?)*?a"); +assert (r.exec("ba")[0] == "a"); +assert (r.exec("ba")[1] == undefined); +assert (r.exec("ba")[2] == undefined); + +r = new RegExp ("((bb?)*)*a"); +assert (r.exec("bbba") == "bbba,bbb,b"); + +r = new RegExp ("((bb?)*)*bbb\\Ba"); +assert (r.exec("bbba")[0] == "bbba"); +assert (r.exec("bbba")[1] == undefined); +assert (r.exec("bbba")[2] == undefined); + +r = new RegExp ("(a??){0,1}a"); +assert (r.exec("aa") == "aa,a"); + +r = new RegExp ("(a?){0,1}a"); +assert (r.exec("aa") == "aa,a"); + +r = new RegExp ("(a{0,1}?){0,1}a"); +assert (r.exec("aa") == "aa,a"); diff --git a/tests/jerry/regexp-character-class.js b/tests/jerry/regexp-character-class.js new file mode 100644 index 000000000..aaa744dee --- /dev/null +++ b/tests/jerry/regexp-character-class.js @@ -0,0 +1,33 @@ +// Copyright 2015 Samsung Electronics Co., Ltd. +// Copyright 2015 University of Szeged. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +var r; + +r = new RegExp ("[abc]*").exec("aaabbcccabcacbacabacbacab"); +assert (r == "aaabbcccabcacbacabacbacab"); + +r = new RegExp ("[abc]*").exec("aaabbcccabdcacb"); +assert (r == "aaabbcccab"); + +r = new RegExp ("[abc]*").exec("defghjklmnopqrstuvwxyz"); +assert (r == ""); + +r = new RegExp ("[a-z]*").exec("abcdefghjklmnopqrstuvwxyz"); +assert (r == "abcdefghjklmnopqrstuvwxyz"); + +r = new RegExp ("[A-Z]*").exec("abcdefghjklmnopqrstuvwxyz"); +assert (r == ""); + +// FIXME: Add more tescase when Unicode support is finished! diff --git a/tests/jerry/regexp-construct.js b/tests/jerry/regexp-construct.js new file mode 100644 index 000000000..88faa9e77 --- /dev/null +++ b/tests/jerry/regexp-construct.js @@ -0,0 +1,88 @@ +// Copyright 2015 Samsung Electronics Co., Ltd. +// Copyright 2015 University of Szeged. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +var r; + +r = new RegExp (); +assert (r.source == "(?:)"); +assert (r.global == false); +assert (r.ignoreCase == false); +assert (r.multiline == false); + +r = new RegExp ("a"); +assert (r.source == "a"); +assert (r.global == false); +assert (r.ignoreCase == false); +assert (r.multiline == false); + +r = new RegExp ("a","gim"); +assert (r.source == "a"); +assert (r.global == true); +assert (r.ignoreCase == true); +assert (r.multiline == true); + +r = RegExp ("a"); +assert (r.source == "a"); +assert (r.global == false); +assert (r.ignoreCase == false); +assert (r.multiline == false); + +r = RegExp ("a","gim"); +assert (r.source == "a"); +assert (r.global == true); +assert (r.ignoreCase == true); +assert (r.multiline == true); + +var r2; +try { + r2 = RegExp (r,"gim"); + assert(false); +} +catch ( e ) +{ + assert (e instanceof TypeError); +} + +r2 = RegExp (r); +assert (r2.source == "a"); +assert (r2.global == true); +assert (r2.ignoreCase == true); +assert (r2.multiline == true); + +r2 = RegExp (r, undefined); +assert (r2.source == "a"); +assert (r2.global == true); +assert (r2.ignoreCase == true); +assert (r2.multiline == true); + +r = /(?:)/; +assert (r.source == "(?:)"); +assert (r.global == false); +assert (r.ignoreCase == false); +assert (r.multiline == false); + +r = /a/; +assert (r.source == "a"); +assert (r.global == false); +assert (r.ignoreCase == false); +assert (r.multiline == false); + +r = /a/gim; +assert (r.source == "a"); +assert (r.global == true); +assert (r.ignoreCase == true); +assert (r.multiline == true); + +assert(Object.prototype.toString.call(RegExp.prototype) === '[object RegExp]'); diff --git a/tests/jerry/regexp-literal.js b/tests/jerry/regexp-literal.js new file mode 100644 index 000000000..70124e946 --- /dev/null +++ b/tests/jerry/regexp-literal.js @@ -0,0 +1,25 @@ +// Copyright 2015 Samsung Electronics Co., Ltd. +// Copyright 2015 University of Szeged. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +var t; + +t = /\//.exec("/"); +assert (t == "/"); + +t = /[/]/.exec("/"); +assert ("a"+/x/+"b" == "a/x/b"); + +t = /\/\[[\]/]/.exec("/[/"); +assert (t == "/[/"); diff --git a/tests/jerry/regexp-non-capture-groups.js b/tests/jerry/regexp-non-capture-groups.js new file mode 100644 index 000000000..55bbcc9de --- /dev/null +++ b/tests/jerry/regexp-non-capture-groups.js @@ -0,0 +1,197 @@ +// Copyright 2015 Samsung Electronics Co., Ltd. +// Copyright 2015 University of Szeged. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +var r; + +// Simple test cases +r = new RegExp ("(?:)"); +assert (r.exec ("a") == ""); + +r = new RegExp ("(?:a)"); +assert (r.exec ("a") == "a"); + +r = new RegExp ("(?:(?:a)b)c"); +assert (r.exec ("abc") == "abc"); + +r = new RegExp ("(?:a)*"); +assert (r.exec ("b") == ""); +assert (r.exec ("aaaa") == "aaaa"); + +r = new RegExp ("(?:a)+"); +assert (r.exec ("aaaa") == "aaaa"); + +r = new RegExp ("(?:a){4}"); +assert (r.exec ("aaaa") == "aaaa"); + +r = new RegExp ("(?:a){1,2}"); +assert (r.exec ("a") == "a"); +assert (r.exec ("aa") == "aa"); +assert (r.exec ("aaaa") == "aa"); + +r = new RegExp ("(?:a)?"); +assert (r.exec ("a") == "a"); +assert (r.exec ("b") == ""); + +// Test greedy iterations +r = new RegExp ("(?:a){1,3}a"); +assert (r.exec ("aa") == "aa"); + +r = new RegExp ("(?:a){1,3}a"); +assert (r.exec ("aaa") == "aaa"); + +r = new RegExp ("(?:a){1,3}"); +assert (r.exec ("a") == "a"); + +r = new RegExp ("(?:a){1,3}"); +assert (r.exec ("aaa") == "aaa"); + +r = new RegExp ("(?:a){1,3}"); +assert (r.exec ("aaaa") == "aaa"); + +r = new RegExp ("(?:a){1,5}"); +assert (r.exec ("aaaa") == "aaaa"); + +r = new RegExp ("(?:a|b){1,2}"); +assert (r.exec ("a") == "a"); + +r = new RegExp ("(?:a|b){1,3}a"); +assert (r.exec ("aaa") == "aaa"); + +r = new RegExp ("(?:a|b){1,3}a"); +assert (r.exec ("aba") == "aba"); + +r = new RegExp ("(?:a|b){1,3}a"); +assert (r.exec ("b") == undefined); + +r = new RegExp ("(?:a|b){1,3}a"); +assert (r.exec ("bbb") == undefined); + +r = new RegExp ("(?:a|b){1,3}"); +assert (r.exec ("a") == "a"); + +r = new RegExp ("(?:a|b){1,3}"); +assert (r.exec ("aa") == "aa"); + +r = new RegExp ("(?:a|b){1,3}"); +assert (r.exec ("aaa") == "aaa"); + +r = new RegExp ("(?:a|b){1,3}"); +assert (r.exec ("ab") == "ab"); + +r = new RegExp ("(?:a|b){1,3}"); +assert (r.exec ("aba") == "aba"); + +r = new RegExp ("(?:a|b){1,3}"); +assert (r.exec ("bab") == "bab"); + +r = new RegExp ("(?:a|b){1,3}"); +assert (r.exec ("bbb") == "bbb"); + +r = new RegExp ("(?:a|b){1,4}a"); +assert (r.exec ("bbb") == undefined); + +r = new RegExp ("(?:a|b){1,4}"); +assert (r.exec ("ab") == "ab"); + +r = new RegExp ("(?:a|b){1,4}"); +assert (r.exec ("aba") == "aba"); + +r = new RegExp ("(?:a|b){1,4}"); +assert (r.exec ("bbb") == "bbb"); + +r = new RegExp ("(?:a|b){1,5}"); +assert (r.exec ("abab") == "abab"); + +r = new RegExp ("(?:aba)*"); +assert (r.exec ("aaaa") == ""); + +r = new RegExp ("(?:aba)+"); +assert (r.exec ("aaaa") == undefined); + +r = new RegExp ("(?:a|bb|c|d)"); +assert (r.exec ("a") == "a"); + +r = new RegExp ("(?:a|b|c|d)"); +assert (r.exec ("") == undefined); + +r = new RegExp ("(?:a|b|c|d)"); +assert (r.exec ("a") == "a"); + +r = new RegExp ("(?:a|b|c|d)"); +assert (r.exec ("b") == "b"); + +r = new RegExp ("(?:a|b|c|d)"); +assert (r.exec ("c") == "c"); + +r = new RegExp ("(?:a|b|c|d)"); +assert (r.exec ("d") == "d"); + +r = new RegExp ("(?:a|b)+"); +assert (r.exec ("aba") == "aba"); + +r = new RegExp ("(?:a|b)"); +assert (r.exec ("b") == "b"); + +r = new RegExp ("(?:a)"); +assert (r.exec ("a") == "a"); + +r = new RegExp ("(?:a)*"); +assert (r.exec ("a") == "a"); + +r = new RegExp ("(?:a)*"); +assert (r.exec ("aaaa") == "aaaa"); + +r = new RegExp ("(?:a)+"); +assert (r.exec ("aaaa") == "aaaa"); + +r = new RegExp ("(?:a)?aa"); +assert (r.exec ("aaaa") == "aaa"); + +r = new RegExp ("(?:a?){0,1}a"); +assert (r.exec ("aa") == "aa"); + +r = new RegExp ("(?:a|aa){0,3}b"); +assert (r.exec ("aaaaaab") == "aaaaaab"); + +r = new RegExp ("(?:(?:a){2,3}){4}b"); +assert (r.exec ("aaaaaaaab") == "aaaaaaaab"); + +// Test non-greedy iterations +r = new RegExp ("(?:a)+?"); +assert (r.exec ("aaaa") == "a"); + +r = new RegExp ("(?:a)*?aa"); +assert (r.exec ("aaaa") == "aa"); + +r = new RegExp ("(?:aaa|aa)*?aa"); +assert (r.exec ("aaaa") == "aa"); + +r = new RegExp ("(?:a)??aa"); +assert (r.exec ("aaaa") == "aa"); + +r = new RegExp ("(?:(?:)*?)*?a"); +assert (r.exec ("ba") == "a"); + +r = new RegExp ("(?:(?:bb?)*)*a"); +assert (r.exec ("bbba") == "bbba"); + +r = new RegExp ("(?:(?:bb?)*)*bbb\\Ba"); +assert (r.exec ("bbba") == "bbba"); + +r = new RegExp ("(?:a??){0,1}a"); +assert (r.exec ("aa") == "aa"); + +r = new RegExp ("(?:a{0,1}?){0,1}a"); +assert (r.exec ("aa") == "aa"); diff --git a/tests/jerry/regexp-routines.js b/tests/jerry/regexp-routines.js new file mode 100644 index 000000000..df3653ca5 --- /dev/null +++ b/tests/jerry/regexp-routines.js @@ -0,0 +1,50 @@ +// Copyright 2015 Samsung Electronics Co., Ltd. +// Copyright 2015 University of Szeged. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +var r; + +r = new RegExp ("a"); +assert (r.exec ("a") == "a"); +assert (r.exec ("b") == undefined); +try { + r.exec.call({}, "a"); + assert (false) +} +catch (e) +{ + assert (e instanceof TypeError); +} + +assert (r.test ("a") == true); +assert (r.test ("b") == false); +try { + r.test.call({}, "a"); + assert (false) +} +catch (e) +{ + assert (e instanceof TypeError); +} + +r = new RegExp ("a", "mig"); +assert (r.toString () == "/a/gim"); +try { + r.toString.call({}, "a"); + assert (false) +} +catch (e) +{ + assert (e instanceof TypeError); +} diff --git a/tests/jerry/regexp-simple-atom-and-iterations.js b/tests/jerry/regexp-simple-atom-and-iterations.js new file mode 100644 index 000000000..71d2aafe9 --- /dev/null +++ b/tests/jerry/regexp-simple-atom-and-iterations.js @@ -0,0 +1,55 @@ +// Copyright 2015 Samsung Electronics Co., Ltd. +// Copyright 2015 University of Szeged. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +var r; + +r = new RegExp ("a"); +assert (r.exec ("a") == "a"); +assert (r.exec ("b") == undefined); + +r = new RegExp ("abc"); +assert (r.exec ("abc") == "abc"); + +r = new RegExp ("a*"); +assert (r.exec ("aaa") == "aaa"); +assert (r.exec ("b") == ""); + +r = new RegExp ("a+"); +assert (r.exec ("aaa") == "aaa"); +assert (r.exec ("b") == undefined); + +r = new RegExp ("ab*"); +assert (r.exec ("a") == "a"); +assert (r.exec ("ab") == "ab"); +assert (r.exec ("abbbb") == "abbbb"); +assert (r.exec ("bbb") == undefined); + +r = new RegExp ("a?"); +assert (r.exec ("a") == "a"); +assert (r.exec ("b") == ""); + +r = new RegExp ("a{4}"); +assert (r.exec ("aaa") == undefined); +assert (r.exec ("aaaaa") == "aaaa"); +assert (r.exec ("aaaa") == "aaaa"); + +r = new RegExp ("a{2,6}"); +assert (r.exec ("a") == undefined); +assert (r.exec ("aa") == "aa"); +assert (r.exec ("aaaaaa") == "aaaaaa"); +assert (r.exec ("aaaaaaa") == "aaaaaa"); + +r = new RegExp (".*"); +assert (r.exec ("abcdefghijkl") == "abcdefghijkl");