implement literal %W %w %s

refactor string parsing
This commit is contained in:
FUKUZAWA-Tadashi
2013-03-12 21:54:17 +09:00
parent 7872bee700
commit 44fbfc5184
6 changed files with 921 additions and 820 deletions
+21 -7
View File
@@ -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
View File
@@ -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;
+2
View File
@@ -106,6 +106,8 @@ enum node_type {
NODE_DSYM,
NODE_ATTRASGN,
NODE_HEREDOC,
NODE_LITERAL_DELIM,
NODE_WORDS,
NODE_LAST
};
+753 -805
View File
File diff suppressed because it is too large Load Diff
+71 -2
View File
@@ -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
View File
@@ -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;