Skip to content
Browse files

Implements rational number literal in syntax level

  • Loading branch information...
1 parent 2e01144 commit b16f4da893c1cb68058098612b7d38fa44182151 Kenta Murata committed May 21, 2013
Showing with 39 additions and 2 deletions.
  1. +6 −0 bootstraptest/test_literal.rb
  2. +31 −1 parse.y
  3. +2 −1 template/id.h.tmpl
View
6 bootstraptest/test_literal.rb
@@ -28,6 +28,12 @@
assert_equal 'Bignum', '123456789012345678901234567890.class'
assert_equal '2.0', '2.0'
assert_equal 'Float', '1.3.class'
+assert_equal 'Rational', '(0 // 1).class'
+assert_equal 'Rational', '(1 // 1).class'
+assert_equal 'Rational', '(0 // 2).class'
+assert_equal 'Rational', '(1 // 2).class'
+assert_equal 'Rational', '(2 // 2).class'
+assert_equal 'divide by 0', %q{begin eval('0 // 0', nil, '', 0); rescue SyntaxError => e; e.message[/\A:(?:\d+:)? (.*)/, 1] end}
# self
assert_equal 'main', 'self'
View
32 parse.y
@@ -759,7 +759,7 @@ static void token_info_pop(struct parser_params*, const char *token);
%type <node> singleton strings string string1 xstring regexp
%type <node> string_contents xstring_contents regexp_contents string_content
%type <node> words symbols symbol_list qwords qsymbols word_list qword_list qsym_list word
-%type <node> literal numeric dsym cpath
+%type <node> literal numeric rational dsym cpath
%type <node> top_compstmt top_stmts top_stmt
%type <node> bodystmt compstmt stmts stmt_or_begin stmt expr arg primary command command_call method_call
%type <node> expr_value arg_value primary_value fcall
@@ -788,6 +788,7 @@ static void token_info_pop(struct parser_params*, const char *token);
%token tUPLUS RUBY_TOKEN(UPLUS) "unary+"
%token tUMINUS RUBY_TOKEN(UMINUS) "unary-"
%token tPOW RUBY_TOKEN(POW) "**"
+%token tDIV2 RUBY_TOKEN(DIV2) "//"
%token tCMP RUBY_TOKEN(CMP) "<=>"
%token tEQ RUBY_TOKEN(EQ) "=="
%token tEQQ RUBY_TOKEN(EQQ) "==="
@@ -4292,6 +4293,7 @@ dsym : tSYMBEG xstring_contents tSTRING_END
numeric : tINTEGER
| tFLOAT
+ | rational
| tUMINUS_NUM tINTEGER %prec tLOWEST
{
/*%%%*/
@@ -4308,6 +4310,30 @@ numeric : tINTEGER
$$ = dispatch2(unary, ripper_intern("-@"), $2);
%*/
}
+ | tUMINUS_NUM rational %prec tLOWEST
+ {
+ /*%%%*/
+ $$ = negate_lit($2);
+ /*%
+ $$ = dispatch2(unary, ripper_intern("-@"), $2);
+ %*/
+ }
+ ;
+
+rational : tINTEGER tDIV2 tINTEGER
+ {
+ /*%%%*/
+ if (FIXNUM_P($<node>3->nd_lit) && $<node>3->nd_lit == INT2FIX(0)) {
+ yyerror("divide by 0");
+ $$ = 0;
+ }
+ else {
+ $$->nd_lit = rb_rational_new($<node>1->nd_lit, $<node>3->nd_lit);
+ }
+ /*%
+ $$ = rb_rational_new($1, $3);
+ %*/
+ }
;
user_variable : tIDENTIFIER
@@ -7642,6 +7668,9 @@ parser_yylex(struct parser_params *parser)
lex_state = EXPR_BEG;
return tOP_ASGN;
}
+ if (c == '/') {
+ return tDIV2;
+ }
pushback(c);
if (IS_SPCARG(c)) {
(void)arg_ambiguous();
@@ -9297,6 +9326,7 @@ negate_lit(NODE *node)
node->nd_lit = LONG2FIX(-FIX2LONG(node->nd_lit));
break;
case T_BIGNUM:
+ case T_RATIONAL:
node->nd_lit = rb_funcall(node->nd_lit,tUMINUS,0,0);
break;
case T_FLOAT:
View
3 template/id.h.tmpl
@@ -16,7 +16,7 @@ require 'optparse'
op_id_offset = 128
token_op_ids = %w[
- tDOT2 tDOT3 tUPLUS tUMINUS tPOW tDSTAR tCMP tLSHFT tRSHFT
+ tDOT2 tDOT3 tUPLUS tUMINUS tPOW tDIV2 tDSTAR tCMP tLSHFT tRSHFT
tLEQ tGEQ tEQ tEQQ tNEQ tMATCH tNMATCH tAREF tASET
tCOLON2 tCOLON3
]
@@ -55,6 +55,7 @@ enum ruby_method_ids {
idUPlus = RUBY_TOKEN(UPLUS),
idUMinus = RUBY_TOKEN(UMINUS),
idPow = RUBY_TOKEN(POW),
+ idDiv2 = RUBY_TOKEN(DIV2),
idCmp = RUBY_TOKEN(CMP),
idPLUS = '+',
idMINUS = '-',

0 comments on commit b16f4da

Please sign in to comment.
Something went wrong with that request. Please try again.