20 posts tagged “rubyex” (page 2)
celtic@sohma:~/code/linux/rubyex/translator$ make
g++ -enable-rtti -I. -c -o out/tests.o tests.cpp
g++ -o ruby out/ruby.tab.o out/lex.yy.o out/expr.o out/global.o out/main.o out/pretty.o out/tests.o
8 test(s) run, 8 test(s) succeeded.
234 assertion(s), 234 assertion(s) succeeded.
celtic@sohma:~/code/linux/rubyex/translator$
There's almost full test coverage for what's parseable so far. Blocks are also included.
celtic@sohma:~/code/linux/rubyex/translator$ ./test
test: "identifier": failure: Assertion failed on line 53: p.expressions.size() == 0
1 test(s) run, 0 test(s) succeeded.
celtic@sohma:~/code/linux/rubyex/translator$
これでテストコードがある:
And here we have the test code:
void _identifier()
{
Program p = parse_code("abc");
ASSERT(p.expressions.size() == 0);
}
The next question, of course, is of the best way to test parsers written in bison. I could just put all the parsing code in a separate library and have it compile two programs instead of the one big thing (i.e. one the parser, one the testing parser which just asserts all the output). I have no idea about test frameworks for C or C++, so I'll have a look now, I think.
celtic@sohma:~/code/linux/rubyex/translator$ ./ruby
a{
b{
c{}
d{e{f{g
}}}
h{j{};m{};c{q;b{}}}
}}
parse success. Program object 0xbfdd1480.
Program: 1 expression(s).
FuncCallExpr: a(arguments) { BlockExpr }
BlockExpr: 1 expression(s).
FuncCallExpr: b(arguments) { BlockExpr }
BlockExpr: 3 expression(s).
FuncCallExpr: c(arguments) { BlockExpr }
BlockExpr: 0 expression(s).
FuncCallExpr: d(arguments) { BlockExpr }
BlockExpr: 1 expression(s).
FuncCallExpr: e(arguments) { BlockExpr }
BlockExpr: 1 expression(s).
FuncCallExpr: f(arguments) { BlockExpr }
BlockExpr: 1 expression(s).
IdentifierExpr: g
FuncCallExpr: h(arguments) { BlockExpr }
BlockExpr: 3 expression(s).
FuncCallExpr: j(arguments) { BlockExpr }
BlockExpr: 0 expression(s).
FuncCallExpr: m(arguments) { BlockExpr }
BlockExpr: 0 expression(s).
FuncCallExpr: c(arguments) { BlockExpr }
BlockExpr: 2 expression(s).
IdentifierExpr: q
FuncCallExpr: b(arguments) { BlockExpr }
BlockExpr: 0 expression(s).
This took a lot of hacking and testing, and `lexical tie-ins'. I should start making this process test-driven to avoid some nasty-to-fix regressions in this.
今ね、パーサのアウトプットはoperatorが全然ありません。見てね:
The parser no longer has any operators! Have a look:
ここでは、"a - b"のパースアウトプット本当は"a.-(b)"です。それに、"a + (-b)"は"a.+(b.-@)"になる。celtic@sohma:~/code/linux/rubyex/translator$ ./ruby
a - b
a + (-b)
parse success. Program object 0xbfb6ea10.
Program has 2 statement(s).
ExprStatement: Expr
FuncCallExpr: Expr.-(arguments)
IdentifierExpr: a
IdentifierExpr: b
ExprStatement: Expr
FuncCallExpr: Expr.+(arguments)
IdentifierExpr: a
FuncCallExpr: Expr.-@(arguments)
IdentifierExpr: b
celtic@sohma:~/code/linux/rubyex/translator$
From here, we can see that "a - b" is actually parsed as "a.-(b)". In addition, "a + (-b)" becomes "a.+(b.-@)".
よかった!
Awesome!
celtic@sohma:~/code/linux/rubyex/translator$ ./ruby
p a(b), c - d, -e
p - 3
p(-3)
p -3
parse success. Program object 0xbffc0e70.
Program has 4 statement(s).
ExprStatement: Expr
FuncCallExpr: p(arguments)
FuncCallExpr: a(arguments)
IdentifierExpr: b
BinaryOpExpr: Expr SUBTRACT Expr
IdentifierExpr: c
IdentifierExpr: d
UnaryOpExpr: NEGATE Expr
IdentifierExpr: e
ExprStatement: Expr
BinaryOpExpr: Expr SUBTRACT Expr
IdentifierExpr: p
LiteralTypedExpr<i>: 3
ExprStatement: Expr
FuncCallExpr: p(arguments)
UnaryOpExpr: NEGATE Expr
LiteralTypedExpr<i>: 3
ExprStatement: Expr
BinaryOpExpr: Expr SUBTRACT Expr
IdentifierExpr: p
LiteralTypedExpr<i>: 3
celtic@sohma:~/code/linux/rubyex/translator$
これではRubyExのパーサのアウトプットがあります。"p a(b), c - d, -e"は正しくパースします。
Here we have RubyEx's output. "p a(b), c - d, -e" is parsed correctly.
次に、このホワイトスペースな問題が来ました。"p - 3"は、RubyExとMRIは同じくパースします、"p"はオブジェクトですから、本当には"p.-(3)"です。"p(-3)"の意味は明らかで、RubyExは正しくパースします。でも、RubyExはホワイトスペースが無視しますからで、"p -3"と"p - 3"のパースは同じだ!結果は意外です。この問題のためにパーサのトリックがあるかな。
Next is the problem of whitespace. RubyEx and MRI parse "p - 3" in the same manner - since "p" is an object, it's actually "p.-(3)". "p(-3)"'s meaning is clear, RubyEx parses it correctly. However, because RubyEx ignores whitespace, "p -3" and "p - 3" parse the same! The result is not what you'd expect. I wonder if I'll have to use some parser tricks to solve this.
>> 1*-5
=> -5
>> 1-5
=> -4
>> 1--5
=> 6
>> 5 - - 3
=> 8
>> 5* - 3
=> -15
>>
Yeah, I hate it. Trying to work it out now.
これで、MRIはホワイトスペースを無視しそうです。‘1-5’と`1--5’の違いはparseした後でresolveしそうです。
This shows us that MRI appears to be ignoring whitespace. The difference between "1-5" and "1--5" appears to be the way it resolves after parsing.
>> puts -3
-3
=> nil
>> puts (-3)
-3
=> nil
>> puts (- 3)
-3
=> nil
>> puts(- 3)
-3
=> nil
>> puts - 3
NoMethodError: undefined method `-' for nil:NilClass
from (irb):15
>>
MRIはRubyExのレファレンスインプリメンテーションです。この場合といえば、Rubyのパーサは明々白々ホワイトスペースを無視できません。。これから、パーサはもっともっと複雑になっている。。
MRI is RubyEx's reference implementation. In this case, a Ruby parser obviously can't ignore whitespace.. because of this, the parser is becoming more and more complicated...
今、Lexerでホワイトスペースをうっちゃりますから、parserはスペースをぜんぜんわかりません。でも、パーサはホワイトスペースがわからせられるのはたぶん難しい!!!
At the moment, the lexer is ignoring all whitespace, and the parser hence can't use it in its results. However, introducing whitespace recognition will likely make the parser's job very difficult!!!
celtic@vm:~/rubyex$ echo hi > m0
Connection to vm closed.
celtic@chikai:~/Code/linux$
