友情支持草泥马语官方网站:[url=http://code.google.com/p/grass-mud-horse/]>>= 猛击这里 =<<[/url]
草泥马语是一种脱胎自[url=http://compsoc.dur.ac.uk/whitespace/]Whitespace[/url]的[b]全新[/b]语言。它是如此的新,我们可以放心的把Whitespace程序[b]升级[/b]为草泥马版。官网提供的发行版里就有ws2gmh工具帮我们完成升级。
在[url=http://grass-mud-horse.googlecode.com/svn/trunk/src/cn/icybear/GrassMudHorse/WS2GMH.java]WS2GMH.java[/url]中,升级的核心逻辑如下:
(注意该程序保留了\n;另外Java I/O的默认处理是读文件的时候把\r\n变成\n)
这是一个while-switch结构。不考虑运行效率,有没有办法写得更精悍一点呢?
先来看JavaScript版本甲:
可以在浏览器里测试:
如果从外部文本编辑器复制过来的话要注意了,有些编辑器会自动转换掉了单个的\n或\r,或\r\n,总之复制进来前注意一下……
然后,JavaScript版本乙:
当然mapping直接写在ws2gmh()里也行,只不过要重复求值有点不太爽。要实验的话照样放到前面的HTML里换掉版本甲即可。
用JavaScript能行,用Ruby当然也能。版本甲:
版本乙:
版本乙变种:
这个变种对mapping的变化敏感度更低些,但运行时开销更大些
于是官方版WS2GMH的完整逻辑就可以用以下脚本实现:
当然用Java也能实现正则版,只是写起来麻烦……懒得写了。
草泥马语是一种脱胎自[url=http://compsoc.dur.ac.uk/whitespace/]Whitespace[/url]的[b]全新[/b]语言。它是如此的新,我们可以放心的把Whitespace程序[b]升级[/b]为草泥马版。官网提供的发行版里就有ws2gmh工具帮我们完成升级。
在[url=http://grass-mud-horse.googlecode.com/svn/trunk/src/cn/icybear/GrassMudHorse/WS2GMH.java]WS2GMH.java[/url]中,升级的核心逻辑如下:
int ch;
while ((ch = reader.read()) != -1) {
switch (ch) {
case ' ':
// writer.append("[Space]");
ch = '草';
break;
case '\t':
// writer.append("[Tab]");
ch = '泥';
break;
case '\n':
// writer.append("[LF]\n");
writer.append('马');
break;
}
writer.append((char) ch);
}(注意该程序保留了\n;另外Java I/O的默认处理是读文件的时候把\r\n变成\n)
这是一个while-switch结构。不考虑运行效率,有没有办法写得更精悍一点呢?
先来看JavaScript版本甲:
function ws2gmh(wsSrc) {
return wsSrc.replace(/( )|(\t)|(\n)/mg, function (_, p1, p2, p3) {
return p1 && '草' || p2 && '泥' || p3 && '马\n'
})
}可以在浏览器里测试:
<html>
<meta http-equiv="Content-Type" content="text/html;charset=GBK" />
<head>
<script type="text/javascript">
function ws2gmh(wsSrc) {
return wsSrc.replace(/( )|(\t)|(\n)/mg, function (_, p1, p2, p3) {
return p1 && '草' || p2 && '泥' || p3 && '马\n'
})
}
function sync() {
var ws_textarea = document.getElementById('ws_textarea')
var gmh_textarea = document.getElementById('gmh_textarea')
// strip the CRs, mimic Java's file I/O behavior
var ws_src = ws_textarea.value.replace(/\r/mg, '')
gmh_textarea.value = ws2gmh(ws_src)
}
</script>
</head>
<body>
<div>
<p>Whitespace:<br />
<textarea id="ws_textarea" cols="80" rows="10" width="100%" onkeyup="sync()"></textarea>
</p>
</div>
<div>
<p>草泥马语:<br />
<textarea id="gmh_textarea" cols="80" rows="10" width="100%" readonly="true" disabled="true"></textarea>
</p>
</div>
</body>
</html>如果从外部文本编辑器复制过来的话要注意了,有些编辑器会自动转换掉了单个的\n或\r,或\r\n,总之复制进来前注意一下……
然后,JavaScript版本乙:
var mapping = {
' ' : '草',
'\t': '泥',
'\n': '马\n'
}
function ws2gmh(wsSrc) {
return wsSrc.replace(/[ \t\n]/mg, function (s) {
return mapping[s]
})
}当然mapping直接写在ws2gmh()里也行,只不过要重复求值有点不太爽。要实验的话照样放到前面的HTML里换掉版本甲即可。
用JavaScript能行,用Ruby当然也能。版本甲:
def ws2gmh(ws_src)
ws_src.gsub(/( )|(\t)|(\n)/m) { $1 && '草' || $2 && '泥' || $3 && "马\n" }
end版本乙:
def ws2gmh(ws_src)
mapping = { ' ' => '草', "\t" => '泥', "\n" => "马\n" }
ws_src.gsub(/[ \t\n]/m) {|s| mapping[s] }
end版本乙变种:
def ws2gmh(ws_src)
mapping = { ' ' => '草', "\t" => '泥', "\n" => "马\n" }
ws_src.gsub(/[#{Regexp.escape mapping.keys.join}]/m) {|s| mapping[s] }
end这个变种对mapping的变化敏感度更低些,但运行时开销更大些
于是官方版WS2GMH的完整逻辑就可以用以下脚本实现:
#!/usr/bin/env ruby
# -*- coding: gbk -*-
def ws2gmh(ws_src)
mapping = { ' ' => '草', "\t" => '泥', "\n" => "马\n" }
ws_src.gsub(/[ \t\n]/m) {|s| mapping[s] }
end
if __FILE__ == $0
begin
ws_file, gmh_file = ARGV
raise unless ws_file && File.extname(ws_file) =~ /\.ws/i
gmh_file ||= ws_file[0..-3] + 'gmh'
open(gmh_file, 'wb') {|f| f << ws2gmh(File.read(ws_file)) }
rescue
puts 'Usage: ws2gmh <ws_file> [gmh_file]'
end
end当然用Java也能实现正则版,只是写起来麻烦……懒得写了。
本文介绍了一种从Whitespace编程语言升级到草泥马语的编译器实现方法,并提供了Java和Ruby两种语言的具体实现示例。
6793

被折叠的 条评论
为什么被折叠?



