I succeeded in adding a lisp like symbol literal to ruby by fixing parse.y
.
diff --git a/parse.y b/parse.y
index e2e92ce..c9fbb03 100644
--- a/parse.y
+++ b/parse.y
@@ -6319,6 +6319,9 @@ static int
parser_yylex(struct parser_params *parser)
{
register int c;
+ int cs[1024];
+ int i;
+ char flag; // 't': sTring, 'y': sYmbol
int space_seen = 0;
int cmd_state;
enum lex_state_e last_state;
@@ -6631,8 +6634,26 @@ parser_yylex(struct parser_params *parser)
return tXSTRING_BEG;
case '\'':
- lex_strterm = NEW_STRTERM(str_squote, '\'', 0);
- return tSTRING_BEG;
+ flag = 'y'; // sYmbol by default
+ for (i=0; i<sizeof(cs); i++) {
+ cs[i] = nextc();
+ if (cs[i] == '\'') {
+ flag = 't'; // sTring
+ break;
+ }
+ if (cs[i] == '\n' || cs[i] == -1) {
+ break; // sYmbol
+ }
+ }
+ while (i >= 0)
+ pushback(cs[i--]);
+ if (flag == 't') {
+ lex_strterm = NEW_STRTERM(str_squote, '\'', 0);
+ return tSTRING_BEG;
+ } else {
+ lex_state = EXPR_FNAME;
+ return tSYMBEG;
+ }
case '?':
if (lex_state == EXPR_END || lex_state == EXPR_ENDARG) {
After applying this patch, we can write such like:
p 'aaa' #=> "aaa"
p 'bbb #=> :bbb
p 'ccc, true #=> :ccc
# true
p :ddd #=> :ddd
The followings are the methodology how it works:
- If the ruby parser finds single quote, the parser peeks the next characters from the next character
- The parser stocks each characters into a stack which maximum size is 1024
- If the parser finds another single quote, the parser does back tracking with the stack and then considers the following characters as a string.
- Otherwise if the parser does not find another single quote within the line, the parser does back tracking with the stack and then considers the following characters as a symbol.
Obviously, there are some known bugs:
- It cannot handle a line which has 1024+ characters after a quote
-
It confuses in
p 'aaa, 'bbb
- It cannot handle a multi line string
e.g.
p 'aaa
bbb'
To tell the truth, I wrote this patch just for my curiousity. I don't believe this syntax will harmonize well with Ruby.
No comments:
Post a Comment