mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
implement literal %W %w %s
refactor string parsing
This commit is contained in:
+21
-7
@@ -58,16 +58,31 @@ struct mrb_parser_message {
|
||||
char* message;
|
||||
};
|
||||
|
||||
/* heredoc parse type */
|
||||
enum heredoc_type {
|
||||
heredoc_type_norm, /* <<EOH */
|
||||
heredoc_type_quote, /* <<'EOH' */
|
||||
#define STR_FUNC_PARSING 0x01
|
||||
#define STR_FUNC_EXPAND 0x02
|
||||
#define STR_FUNC_REGEXP 0x04
|
||||
#define STR_FUNC_WORD 0x08
|
||||
#define STR_FUNC_SYMBOL 0x10
|
||||
#define STR_FUNC_ARRAY 0x20
|
||||
#define STR_FUNC_HEREDOC 0x40
|
||||
|
||||
enum mrb_string_type {
|
||||
str_not_parsing = (0),
|
||||
str_squote = (STR_FUNC_PARSING),
|
||||
str_dquote = (STR_FUNC_PARSING|STR_FUNC_EXPAND),
|
||||
str_regexp = (STR_FUNC_PARSING|STR_FUNC_REGEXP|STR_FUNC_EXPAND),
|
||||
str_sword = (STR_FUNC_PARSING|STR_FUNC_WORD|STR_FUNC_ARRAY),
|
||||
str_dword = (STR_FUNC_PARSING|STR_FUNC_WORD|STR_FUNC_ARRAY|STR_FUNC_EXPAND),
|
||||
str_ssym = (STR_FUNC_PARSING|STR_FUNC_SYMBOL),
|
||||
str_sheredoc = (STR_FUNC_PARSING|STR_FUNC_HEREDOC),
|
||||
str_dheredoc = (STR_FUNC_PARSING|STR_FUNC_HEREDOC|STR_FUNC_EXPAND),
|
||||
};
|
||||
|
||||
/* heredoc structure */
|
||||
struct mrb_parser_heredoc_info {
|
||||
enum heredoc_type type;
|
||||
mrb_bool allow_indent:1;
|
||||
mrb_bool line_head:1;
|
||||
enum mrb_string_type type;
|
||||
const char *term;
|
||||
int term_len;
|
||||
mrb_ast_node *doc;
|
||||
@@ -85,8 +100,7 @@ struct mrb_parser_state {
|
||||
int column;
|
||||
|
||||
enum mrb_lex_state_enum lstate;
|
||||
int sterm; /* string terminator : ' ' means heredoc */
|
||||
int regexp;
|
||||
mrb_ast_node *lex_strterm; /* (type nest_level beg . end) */
|
||||
|
||||
unsigned int cond_stack;
|
||||
unsigned int cmdarg_stack;
|
||||
|
||||
+73
-5
@@ -955,6 +955,71 @@ gen_vmassignment(codegen_scope *s, node *tree, int rhs, int val)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gen_send_intern(codegen_scope *s)
|
||||
{
|
||||
pop();
|
||||
genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern(s->mrb, "intern")), 0));
|
||||
push();
|
||||
}
|
||||
static void
|
||||
gen_literal_array(codegen_scope *s, node *tree, int sym, int val)
|
||||
{
|
||||
if (val) {
|
||||
int i = 0, j = 0;
|
||||
|
||||
while (tree) {
|
||||
switch ((intptr_t)tree->car->car) {
|
||||
case NODE_STR:
|
||||
if ((tree->cdr == NULL) && ((intptr_t)tree->car->cdr->cdr == 0))
|
||||
break;
|
||||
/* fall through */
|
||||
case NODE_BEGIN:
|
||||
codegen(s, tree->car, VAL);
|
||||
++j;
|
||||
break;
|
||||
|
||||
case NODE_LITERAL_DELIM:
|
||||
if (j > 0) {
|
||||
j = 0;
|
||||
++i;
|
||||
if (sym)
|
||||
gen_send_intern(s);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
codegen_error(s, "compiler bug on %W %w %I %i");
|
||||
}
|
||||
if (j >= 2) {
|
||||
pop(); pop();
|
||||
genop_peep(s, MKOP_AB(OP_STRCAT, cursp(), cursp()+1), VAL);
|
||||
push();
|
||||
j = 1;
|
||||
}
|
||||
tree = tree->cdr;
|
||||
}
|
||||
if (j > 0) {
|
||||
j = 0;
|
||||
++i;
|
||||
if (sym)
|
||||
gen_send_intern(s);
|
||||
}
|
||||
pop_n(i);
|
||||
genop(s, MKOP_ABC(OP_ARRAY, cursp(), cursp(), i));
|
||||
push();
|
||||
}
|
||||
else {
|
||||
while (tree) {
|
||||
switch ((intptr_t)tree->car->car) {
|
||||
case NODE_BEGIN: case NODE_BLOCK:
|
||||
codegen(s, tree->car, NOVAL);
|
||||
}
|
||||
tree = tree->cdr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
raise_error(codegen_scope *s, const char *msg)
|
||||
{
|
||||
@@ -1933,9 +1998,7 @@ codegen(codegen_scope *s, node *tree, int val)
|
||||
break;
|
||||
|
||||
case NODE_HEREDOC:
|
||||
/*if(tree == NULL){printf("heredoc error 1\n");exit(11);}*/
|
||||
tree = ((struct mrb_parser_heredoc_info *)tree)->doc;
|
||||
/*if(tree == NULL){printf("heredoc error 2\n");exit(12);}*/
|
||||
/* fall through */
|
||||
case NODE_DSTR:
|
||||
if (val) {
|
||||
@@ -1963,6 +2026,13 @@ codegen(codegen_scope *s, node *tree, int val)
|
||||
}
|
||||
break;
|
||||
|
||||
case NODE_WORDS:
|
||||
gen_literal_array(s, tree, FALSE, val);
|
||||
break;
|
||||
case NODE_LITERAL_DELIM:
|
||||
codegen_error(s, "compiler bug on %W %w %I %i");
|
||||
break;
|
||||
|
||||
case NODE_REGX:
|
||||
if (val) {
|
||||
char *p1 = (char*)tree->car;
|
||||
@@ -2061,9 +2131,7 @@ codegen(codegen_scope *s, node *tree, int val)
|
||||
case NODE_DSYM:
|
||||
codegen(s, tree, val);
|
||||
if (val) {
|
||||
pop();
|
||||
genop(s, MKOP_ABC(OP_SEND, cursp(), new_msym(s, mrb_intern(s->mrb, "intern")), 0));
|
||||
push();
|
||||
gen_send_intern(s);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
@@ -106,6 +106,8 @@ enum node_type {
|
||||
NODE_DSYM,
|
||||
NODE_ATTRASGN,
|
||||
NODE_HEREDOC,
|
||||
NODE_LITERAL_DELIM,
|
||||
NODE_WORDS,
|
||||
NODE_LAST
|
||||
};
|
||||
|
||||
|
||||
+753
-805
File diff suppressed because it is too large
Load Diff
+71
-2
@@ -128,8 +128,77 @@ ZZZ
|
||||
z == ""
|
||||
end
|
||||
|
||||
# Not Implemented ATM assert('Literals Array', '8.7.6.4') do
|
||||
assert('Literals Array', '8.7.6.4') do
|
||||
a = %W{abc#{1+2}def \}g}
|
||||
b = %W(abc #{2+3} def \(g)
|
||||
c = %W[#{3+4}]
|
||||
d = %W< #{4+5} >
|
||||
e = %W//
|
||||
f = %W[[ab cd][ef]]
|
||||
g = %W{
|
||||
ab
|
||||
#{-1}1
|
||||
2#{2}
|
||||
}
|
||||
|
||||
test1 = (a == ['abc3def', '}g'] and
|
||||
b == ['abc', '5', 'def', '(g'] and
|
||||
c == ['7'] and
|
||||
d == ['9'] and
|
||||
e == [] and
|
||||
f == ['[ab', 'cd][ef]'] and
|
||||
g == ['ab', '-11', '22']
|
||||
)
|
||||
|
||||
a = %w{abc#{1+2}def \}g}
|
||||
b = %w(abc #{2+3} def \(g)
|
||||
c = %w[#{3+4}]
|
||||
d = %w< #{4+5} >
|
||||
e = %w//
|
||||
f = %w[[ab cd][ef]]
|
||||
g = %w{
|
||||
ab
|
||||
#{-1}1
|
||||
2#{2}
|
||||
}
|
||||
|
||||
test2 = (a == ['abc#{1+2}def', '}g'] and
|
||||
b == ['abc', '#{2+3}', 'def', '(g'] and
|
||||
c == ['#{3+4}'] and
|
||||
d == ['#{4+5}'] and
|
||||
e == [] and
|
||||
f == ['[ab', 'cd][ef]'] and
|
||||
g == ['ab', '#{-1}1', '2#{2}']
|
||||
)
|
||||
|
||||
test1 and test2
|
||||
end
|
||||
|
||||
assert('Literals Symbol', '8.7.6.6') do
|
||||
/* do not compile error */
|
||||
:$asd
|
||||
:@asd
|
||||
:@@asd
|
||||
:asd=
|
||||
:asd!
|
||||
:asd?
|
||||
:+
|
||||
:+@
|
||||
:if
|
||||
:BEGIN
|
||||
|
||||
a = :"asd qwe"
|
||||
b = :'foo bar'
|
||||
c = :"a#{1+2}b"
|
||||
d = %s(asd)
|
||||
e = %s( foo \))
|
||||
f = %s[asd \[
|
||||
qwe]
|
||||
g = %s/foo#{1+2}bar/
|
||||
|
||||
a == :'asd qwe' and b == :"foo bar" and c == :a3b and d == :asd and
|
||||
e == :' foo )' and f == :"asd [\nqwe" and g == :'foo#{1+2}bar'
|
||||
end
|
||||
|
||||
# Not Implemented ATM assert('Literals Regular expression', '8.7.6.5') do
|
||||
|
||||
# Not Implemented ATM assert('Literals Symbol', '8.7.6.6') do
|
||||
|
||||
+1
-1
@@ -39,7 +39,7 @@ is_code_block_open(struct mrb_parser_state *parser)
|
||||
int code_block_open = FALSE;
|
||||
|
||||
/* check for unterminated string */
|
||||
if (parser->sterm) return TRUE;
|
||||
if (parser->lex_strterm) return TRUE;
|
||||
|
||||
/* check for heredoc */
|
||||
if (parser->heredoc_starts_nextline) return TRUE;
|
||||
|
||||
Reference in New Issue
Block a user