blob: c6b3e60ae165a6a56e9d766feab04b66cd34d847 [file] [log] [blame]
Damien George04b91472014-05-03 23:27:38 +01001/*
2 * This file is part of the Micro Python project, http://micropython.org/
3 *
4 * The MIT License (MIT)
5 *
6 * Copyright (c) 2013, 2014 Damien P. George
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 * THE SOFTWARE.
25 */
26
Damien George51dfcb42015-01-01 20:27:54 +000027#include "py/repl.h"
Damien92c06562013-10-22 22:32:27 +010028
Damien George58ebde42014-05-21 20:32:59 +010029#if MICROPY_HELPER_REPL
Damien George136f6752014-01-07 14:54:15 +000030
Damien George969a6b32014-12-10 22:07:04 +000031STATIC bool str_startswith_word(const char *str, const char *head) {
Damien George42f3de92014-10-03 17:44:14 +000032 mp_uint_t i;
Damien92c06562013-10-22 22:32:27 +010033 for (i = 0; str[i] && head[i]; i++) {
34 if (str[i] != head[i]) {
35 return false;
36 }
37 }
Damien George8cc96a32013-12-30 18:23:50 +000038 return head[i] == '\0' && (str[i] == '\0' || !unichar_isalpha(str[i]));
Damien92c06562013-10-22 22:32:27 +010039}
40
Damien George97790452014-04-08 11:04:29 +000041bool mp_repl_continue_with_input(const char *input) {
42 // check for blank input
43 if (input[0] == '\0') {
44 return false;
Damien92c06562013-10-22 22:32:27 +010045 }
46
Damien George97790452014-04-08 11:04:29 +000047 // check if input starts with a certain keyword
48 bool starts_with_compound_keyword =
49 input[0] == '@'
50 || str_startswith_word(input, "if")
51 || str_startswith_word(input, "while")
52 || str_startswith_word(input, "for")
53 || str_startswith_word(input, "try")
54 || str_startswith_word(input, "with")
55 || str_startswith_word(input, "def")
56 || str_startswith_word(input, "class")
57 ;
58
59 // check for unmatched open bracket or triple quote
60 // TODO don't look at triple quotes inside single quotes
Damien92c06562013-10-22 22:32:27 +010061 int n_paren = 0;
62 int n_brack = 0;
63 int n_brace = 0;
Damien Georgea28507a2014-04-07 13:01:30 +010064 int in_triple_quote = 0;
Damien George97790452014-04-08 11:04:29 +000065 const char *i;
66 for (i = input; *i; i++) {
67 switch (*i) {
Damien92c06562013-10-22 22:32:27 +010068 case '(': n_paren += 1; break;
69 case ')': n_paren -= 1; break;
70 case '[': n_brack += 1; break;
71 case ']': n_brack -= 1; break;
72 case '{': n_brace += 1; break;
73 case '}': n_brace -= 1; break;
Damien George97790452014-04-08 11:04:29 +000074 case '\'':
75 if (in_triple_quote != '"' && i[1] == '\'' && i[2] == '\'') {
76 i += 2;
77 in_triple_quote = '\'' - in_triple_quote;
78 }
79 break;
Damien Georgea28507a2014-04-07 13:01:30 +010080 case '"':
Damien George97790452014-04-08 11:04:29 +000081 if (in_triple_quote != '\'' && i[1] == '"' && i[2] == '"') {
82 i += 2;
83 in_triple_quote = '"' - in_triple_quote;
Damien Georgea28507a2014-04-07 13:01:30 +010084 }
85 break;
Damien92c06562013-10-22 22:32:27 +010086 }
87 }
Damien George97790452014-04-08 11:04:29 +000088
89 // continue if unmatched brackets or quotes
90 if (n_paren > 0 || n_brack > 0 || n_brace > 0 || in_triple_quote != 0) {
91 return true;
92 }
93
Damien George73c79b92014-04-08 11:33:28 +000094 // continue if last character was backslash (for line continuation)
95 if (i[-1] == '\\') {
96 return true;
97 }
98
Damien George97790452014-04-08 11:04:29 +000099 // continue if compound keyword and last line was not empty
100 if (starts_with_compound_keyword && i[-1] != '\n') {
101 return true;
102 }
103
104 // otherwise, don't continue
105 return false;
Damien92c06562013-10-22 22:32:27 +0100106}
Damien George136f6752014-01-07 14:54:15 +0000107
Damien George58ebde42014-05-21 20:32:59 +0100108#endif // MICROPY_HELPER_REPL