2009年8月30日星期日

关于zflap.com

Hello World!

http://zflap.com/
这是前些天买的域名&空间,还没什么内容啊。
先建了一个本博的入口
http://blog.zflap.com/
另提供如下订阅入口
http://feeds.feedburner.com/ZsYard

写在http://blog.zflap.com/的代码暂就不贴了,
给下面的参考链接:
http://phpjs.org/
http://php.chinaunix.net/manual/zh/

备用域名myblog.zflap.com
感觉不好看,不用了。

再强调一下ee.zsy就是我,Z's Yard[中文]的博主。
你可通过下列方式联络
Z's Yard[中文]
Z's Yard[中文] - zflap.com入口
恩,感觉还是缺少一些方便的互动的东西啊,
而且至少目前访问确实也不方便,
此外就是在自己的空间里加强一下自身的存在感。

博客这里的内容是些自己杂乱的东西了,
开来还是需要有特别的项目来开展。
这不是关于关注度的话题,而是我能够创造的价值。
好吧,私人空间就依旧如平静的夜晚吧。

2009年8月28日星期五

伪春菜 - 简述

[茶兔&茶鹿]


伪春菜的说明请转移维基百科
http://zh.wikipedia.org/wiki/%E5%81%BD%E6%98%A5%E8%8F%9C
简单的说就是一个拟人化的桌面玩物,除了所安装的特定的人格(Ghost)机能外,也提供报时收取订阅等系统功能。

目前通过搜索可以找到打包好的伪春菜,不过在这里要自己组装一回。

核心程式:SSP
下载地址:http://cers.cuc2.idv.tw/
解包后运行主程序

先在已经可以开见最基础的平台,之后下载的模块只需要拖动到程序运行的窗口上(或者解包到程序所在目录,对应好路径)。
下面去下载 "人格(Ghost)":这是中文偽春菜後援會Wiki,http://cuc2.idv.tw/wiki/index.php?FrontPage,选择其中的"资源"的"人格"项目。仔细找可以发现下载链接。
其中最知名的人格是"橘花",目前有两个版本。
"落鳥" 以及 "茶兔&茶鹿" 具有很高完成度,推荐使用。
采用拖放方式安装后,右键选择切换或呼叫人格即可。

同时请仔细寻找额外的 "外表(Shell)" "对话框(Balloon)"哦(汗,其实我自己就很不擅长找)。主要是找橘花的,因为另两个有配套的提供。

最新的(从我写贴时间) 小绿
http://220.170.79.48/html/art/20090826/44568.html
来自 acfun.cn

觉得开此贴是在无聊了(没写到什么特别的),下面说玩法:
系统功能,详见右键菜单。
推到抚摸等动作,会与好感度相关。
人格提供的功能,双击出菜单。
调教,自己给人格添加脚本实现功能(算重点吧),涉及辞书文件和伪AI(Shiori),相关资料参见"中文偽春菜後援會Wiki"。

[橘花]图转自官网

好就先这么些,其他更多的可以去Google或百度贴吧看看。

2009年8月23日星期日

关于神的一二[第二篇小说的构想]

Part.1
090823
暂不打算成文,这次目的是完成内容的基础设定。本文标题是原先引开整个构思的话题。

对于神是否存在,有看法认为有,有反对的认为是没有。也有觉得神或许存在,但是在对外界的认识不断构建的过程中,神是会被简化去的事物。这里仅在把话题划分为三种存在形态。
信仰的一种可以的对象,是神。宗教是这种信仰的形式,体现在日常的认知和行为上。
在生命体认识(包括对外界事物和对心理道德等两方面的)有限的时期下,有太多空白需要以神做填补。
原始状况下无知的故事,对于一个隔开的观者,可以表现出满满的悲伤,也同时能体会到些许纯真。
某神说,它是世间的解救者。这与一群人内心想法共鸣,比如不满,愿望,内疚。他们发现,神是可以被认为存在的,并也同时利用他人信仰获得了收益。
于是他们更广泛的传播神的福音,扮演者解救众人的使者。不断歌颂着神的伟大,并描绘着需要齐力对付的黑暗敌人。
面对其他信仰,他们告诫信者,这是恶魔的诱惑,源于对神的不诚。面对神的怀疑者,他们将展示给信者自身的功劳和这类人面临的极大不幸。
信者在成长,对神的认知已不再是原本的共鸣。也没有转向怀疑,因为知道了所保持的信仰代表了自己拥有的,和能够再获得的。
神的影响在壮大,不论是何种缘由,直到有一刻发展成为区域内的共同取向。从此,神由名义的存在,变为了对社会推进的指引。

由此得到一个故事设定,是一个有现代感的封闭村落,保留着有血缘遗传的神的绝对信仰。出于安全考虑(表明其实有反对者活动),神的继承者要送往远方完全隔绝的地方教育成长,并在成年时接回告知神的血统。此时只有接受神的名号才能保障自身(包括父辈)的安全,同时出于传统需要否认之前的一切经历。哪怕是最好的伙伴也只能视为陌生,忍受着孤独。其实在村落里,能成为神是被向往的事情,是希望自己的出身是荣耀的血统。
关于故事的年代设定,是架空的久远的感觉,会调动起人情绪的幻想,而不是无知落后。是面对了合适但又伤感的东西。

成文方式,再等形式确定按需要和预计来。这次风格是打算保持有完整的情节和人物线,也按习惯考虑再在形态上体现些非常态的要素。注重个人体会和神的视角。

人物。主角,男,神的继承者,情节的主线。其他待确认或添加。
这里的内容本身,就在于构想的积累。

Part.2
090824-5
续写和预想总担心会有难调和的地方啊,现在是开始一个新的部分了。

教堂是宗教仪式的场所,具有神圣之感。信者在此洗礼祈愿,希望获得神的庇护。
即使不见神的形体,也能体会到它对未来的影响。以预言的方式,让信者内心感受力量,来支持自身最认为的情况。
或许存在击穿了现实和其他次元的视感,掩饰了悲伤的自虐感。或者既可是源于生命的力量信念向往,亦可是无形沉重的束缚。
仰望教堂汇聚的屋顶,寻找灵魂引导者的光芒。那是被渺小身影寄予希望能存在的神,它的作用在仪式场所里,被实现。
以神的名义而被广知的意志,是众信者依靠的引导。结合在一起的力量,掩去了争端隔阂。不论是出于对此力量的满足或恐惧。
一代代的信者,化身为神躯壳的部件,于发展之路上开拓出新的脚印,光芒闪烁在无尽长河中。
教会的领导者,同时是与神的媒介。也共同意志的个人存在,引导职责的现实担当。他获得着信者对神的依赖,可能出于愿望的共鸣,或也可能是象征体的延续(扮演与希望担当引导者不同的理想)。
古老的预言曾讲述,神把众生从恶魔的拉扯中解救。在延续下的信者对神敬仰的幸福目光的暗影中,有囚禁着的恶魔和发生的对将新诞生的神的杀戮。
神的意志,是生命对不可知的境地的依赖。同时渐渐,个体也把神视作等同满足感的存在,以忍受个体的压抑作为代价,共同填充着神的躯体。
约定,神不会说,因为它没有亲自实现愿望的力量。

以上构造背景是想想的,估计不合实际。教堂是古典欧洲的味道,故事里也想有石墙外神社状神灵和大自然的感觉。设定时间组成,主体是主角成人仪式时段,发生来有隔绝感到村落。还有就是很分明的成长时段,是现代文化的空间,有校园伙伴和成长,是被认为最真实不可丢弃的(有点读者生活的空间的情感)。预言传说,是模糊的,和现实有重影的,被相信而不会摆脱的。好友的亲近和对族人的距离感是对于,也和血缘关系反差。神的存在感,以典故氛围,特别是迫使主角的力量的形式存在。行文对神的重点在存在感,不涉及评价的。完整的故事由线索和场景的发展构成。

人物:主角的父亲,考虑是会有爷爷辈,该角色是发生了双重的身份,这里以长辈的为首要体现。抗议团体,根据上次设定有一个暴力团体,作为力量迫使主角的家族出于安危不可放弃地位(这里可划分出不同立场的)。主角同学,女生,可爱,有相对特别的性格。被祭祀和祈愿的对象,在传说和历史上分别存在的神,自身是认为到幸福的,不过被主角体会到悲剧感(有母亲爱子女感),这个不做故事线索。村民路人,被需要的角色,会提拔其中的任故事要素的。人物间有立场和身份的关系。

直线型情节要交织感有困难啊,情节的波动仍按习惯转移到叙述上(情节本身平稳化)。故事这次打算基于场景和情绪来组织。部分人物有纯真和距离近的感觉。

简单设定点场景(感觉上的,不一定使用):坐在倒下的树干上,夜晚,有虫鸣,星空和月光,独自或和来自外界的人一起,唤起现代回忆下美好和真实的感受。主角的不同时段愿望(理想)的冲突(就仅设定过两个存在的时段吧)。不同身份的人,亲切和敬意的同时存在的对话。注,村落也是现代感的,只是味道不同而已。

Part.3
090830
又过了些天了,构想没多少推进。话说这种依靠累积的项目,是需要安排好集中而平缓的进度的。

在背景中设定的各立场:主体是神,一个抽象的存在。故事中其他视角对它是模糊的认识,神圣无上的感觉。神使和信者,他们共同受神的牵制(这是故事的切入,展现悲伤的情绪,方向是意识的发掘)。两者的自身利益和与相互关系推动出了神的存在形态(也看作人的组成部分,区别在转为了人的制衡)。信者有对神使的不满,但仍有此方向的利益取向(价值的认可和收益)。不同神使有巩固自身利益和立场的动机,这也会造成另一方的情绪。整体是被压制的感觉。

这是补充内容,本篇构想篇第一篇就此结束。这里设定(这贴里的)的要点是故事的主题,也会再补些。此外填充场景(发展中的片段)人物和故事线(展现形态方面的,或情绪关系发展)。

2009年8月20日星期四

开始加AdSense试试

如题,刚填了申请。
加Ad不是本人最初对本Blog建设的设想了,虽然曾有过觉得对不住服务商的想法。
不过为了写本贴,来尝试一下申请和投放喽。
话说其实都没人路过这里啊。
就先这么,样式也不调整了,等下一步怎么做。
Ok,在自家挖个试验田。其他文章属性不受影响。
====
回信说 不符合。
参考这篇
http://www.google.com/support/forum/p/adsense/thread?tid=7ddbed7081a813d0&hl=zh-CN
中文blogspot的站点目前不接受。
注册网站的要求和其他说明看这里
http://www.google.com/support/forum/p/adsense/thread?tid=5b6daaad0a89ba6d&hl=zh-CN
先放一会公益广告吧。
====
090824
准备买空间,有考虑HG的,现在看中HM。
====
090828
前天晚上买好,域名是zflap.com,已尝试Drupal并建立博客入口,SSH也以开通。

2009年8月19日星期三

pdftotext

pdftotext is an open source command-line utility for converting PDF files to plain text files.
http://www.foolabs.com/xpdf/download.html
If your machine is x86,Win32,
you can download the Precompiled binaries for Win32,and use pdftotext.exe following pdftotext.txt.
If the PDF you converted contains Simplified Chinese characters,extra Language Support Packages for Chinese/simplified is needed.The URL where you will get the fonts can be founded in file README,which also shows you how to use this pac.

EN写着不顺啊,而且内容还是提及中文问题的。

2009年8月16日星期日

cgi&c,jQuery&CMS与OO

CGI 通用网关接口

The Common Gateway Interface
http://hoohoo.ncsa.illinois.edu/cgi/
CGI Programming FAQ
http://www.htmlhelp.org/faq/cgifaq.html

文档,参照和参考

最简单的示例

#!/bin/sh
echo Content-type: text/plain
echo /bin/date

出自 - 学习CGI脚本
http://www.jdon.com/idea/cgi.htm
老文了,用实例介绍了cgi

cgi是一种标准协议,与可执行的文件是何种语言编写无关。
通过URI的调用,服务器建立cgi进程。
cgi程序的标准输出的内容被发回客户端浏览器,
输入通过表单的GET和POST是以环境变量和标准输入的方式,
比如"/cgi-bin/test.cgi?inputstr"。
被建立的cgi进程随后销毁
c语言的实验代码

#include
int main(int argc,char** argv,char** envp)
{
puts("content-type:text/html\r\n\r\n");
while (envp++,*envp!=NULL){
puts(*envp);
puts("
");
}
}

解析FROM提交的QUERY-STRING的c实现
参见 用c写CGI 程序
http://www.programfan.com/article/2858.html

QUERY-STRING的格式及代码 略
theName=Ichabod+Crane&gender=male&status=missing&headless=yes
URL编码遵循下列规则:
每对name/value由&符分开.
每对来自表单的name/value由=符分开. 如果用户没有输入值给这个name,那么这个name还是出现,只是无值(象这样 "name=").
任何特殊的字符(就是那些不是简单的七位ASCII,如汉字) 将以百分符%用十六进制编码. 当然也包括象 =, &, 和 % 这些特殊的字符.
在输入区中的空格将以加号+显示.




用perl会比用c方便些,而php则更加专用了。
c/cpp库有 cgic Cgicc
封装了函数提供如表单检查或文件上传等功能
协议大体分别是BSD-Like和LGPL
能找到示例代码

使用FastCGI技术,可以建立长期的cgi进程。
http://www.fastcgi.com

#include

void main(void)
{
int count = 0;
while(FCGI_Accept() >= 0) {
printf("Content-type: text/html\r\n");
printf("\r\n");
printf("Hello world!
\r\n");
printf("Request number %d.", count++);
}
exit(0);
}


想简单实验cgi可以用
(Win32)EasyWebServer V1.9
(Linux)mini-httpd
Linux下注意权限和是否开启cgi功能

c语言下锁住文件用sys/file.h的flock()
例如编写计数器类似程序,会同时对同一个共享的文件读写的。

编写包含同时处理多用户的各自状态的程序,
通过session和cookie来实现
cookie的获取和设定功能,有cgi协议提供
session则对登录的用户分配ID,分别由服务器和浏览器的cookie匹配保存和传递状态。
如果用c编写,session需要自行实现。

CMS
内容管理系统 - Content Management System

比如 drupal,Joomla(个人乱猜前者侧重平台,后者是信息展示)
博客类wordpress也可以算,不过CMS管理个内容不限于博主及Post,且可结合更多样的形式。
对CMS我是刚去了解,之前仅有所耳闻。
我看了各自DEMO,感觉到的基础的组成有:前端后端(用于展示和管理),用户管理,模块管理(安装),文本(基本的)的发布及管理,站点栏目及页面的管理,展示的视图组件(首页的部件,也和使用theme相关),二次开发的API。

jQuery是用于客户端的JavaScript代码库,以实现
DOM操作 选择器及操作
AJAX 用于创建与服务器通信的交互式网页
动态效果
用户界面 jQuery UI
使用已有众多组件

见到有jQuery与drupal结合操作的教程。

如果想复杂,可以自己架一个eyeos试试?
一个基于php的WebOS,
提供GUI创建工具,和供服务端自行编写PHP使用的API。
感觉把一个Linux(界面很像)搬到了浏览器中。
记得它已经有好几年历史了,不过目前看来,过多把数据和处理逻辑全放在服务器,而客户端运行的部分不足,确实不方便。
其他WebOS也有形式如远程终端,FireFox的附加组件类似,FLASH类似先接受一个小心客户端再与服务端交互,AJAX与CGI的处理逻辑分别由和客户端服务端承担。

上面一段是借题想到,就写上去了。话说最近指南类文贴的较多,都仅泛泛说说,而求内容由不集中啊。呵呵。
我给本博想了一个主题,叫 IT技术(与 文艺)提升人的生产与生活。单篇贴仍保持之前“资源与引导”的思路来。恩,这里仅仅是这么想过而已。
有购域名和空间的打算,目前思路还不明了啊。

其实本来开本贴就只打算简单扯几句想法的,介绍部分一写就占内容了。
话说建立站点与信息发布,
较原始和简单的办法,就是手工编辑网页文件。
发布信息,只需要建立新网页或在网页中添加相应内容,修改也是同样的方式。
如果考虑主页的部分内容是可以自动生成的,也可编写简单的脚本来辅助。
评论部分用CGI的GuestBook即可。
单纯的信息发布,也可用已有的博客系统。但相比而言,一个博客系统会比前一种方式要庞大,且机制更为复杂。是否算违背“简单”的原则呢?
恩,这里会考虑分离和重用。就像DIV+CSS可以分离网页的内容和布局,运用博客系统则是分离了对内容的控制和对系统功能的控制。在对系统使用的功能中,使得用户能够更好的专注内容。同时也降低了技术上的要求。而同一份高质量的博客系统可以被不同的人使用,既节约了成本也保障了代码的质量。也有自定义主题和扩展模块的部件。

对于命令式语言,块结构是对GOTO的封装,而函数功能则提供了更高层次的封装。在C风格的API的设计中,可以划分出获取值,设置值,执行命令(初始化和释放是成对出现,有点特别)三类。而以对象形式封装的接口由包,属性,事件,方法组成。接口的信息可以通过文档或对象浏览器提供。GUI组件倾向于后者的形式封装,符合人的观点且可节约代码。(比如,不用调用一个长名称的函数,再加一个指向结构的指针为参数。也增强安全性。)
接口的形式仅是一个方面,这里更多是涉及设计方式的变化。从单一的变量,到包含不同数据的结构体,在演化为对象在包含数据的同时也可以能对自身处理的函数。这是在出于封装需求(安全,重用)的同时,也出于对模拟系统的开发与设计之中的探索(比如生命之类?)。参考Win32API在GUI部分的设计(我记不太清楚了,大体如此吧)是物件导向的思路加函数形式的接口。先填充包含属性和用于处理的消息的回调函数的结构体,由此从窗口类注册并创建窗口对象(也包含按钮文本框之类的,先是一个容器窗口了)。同时存在一个消息循环,就是一个while/loop循环了。接受到来自消息列队的消息并对消息代表的事件判断,就是switch或ifelseif(这两者有区别,因为前者可以优化为跳转表)的形式。事件比如按钮按下更,包括了两个基本的,是创建时和销毁时。如果不是通过资源文件里编写好的对话框样式,窗口就需要在创建是建立如按钮等控件,同时告诉子窗口发回不处理的消息(可能是)。对于窗口可以子类化(先自行处理消息在调用父类处理)和超类化(用来批量创建子类),实现方式体现在对消息的处理流程上。对比smalltalk和c++风格处理消息/方法的办法,前者是动态查找,后者是转化为函数并建立虚函数表处理子类的继承关系(可当接口用)。但至少不用自己进行消息判断的代码,在运用物件导向的同时,既节约了代码,也分离了实现消息处理的方法和设计中消息要处理的实际内容(即实际的处理逻辑)。
先承认一下,我一直认为物件导向给编码带来麻烦,同时又认同设计模式和重构中(才仅听说而已)分离出设计的步骤,且VB和GWBASIC都是方便的东西,所以想来上面一些内容。不过我目前看那些CMS都很痛苦的感觉,不过要用时又确实去会使用他们。

下面的话题是用代码创建一个虚拟的世界,其实就是游戏啦。通常的游戏脚本使用简单的GOTO语句就可以实现逻辑了。也或许有更快捷的方式。
参照是类RPG形式的冒险类游戏。
来伪代码:
while !quitgame
界面绘制()
处理按键()
触发及事件的游戏逻辑()
wend
func 子界面
或者有文本数据
或role npc1=new role("路人甲");sense1.add(npc1);
或...(?)
ok,不早了,先烂尾在这里吧。
4hours累计,闲话啊

======
找来RPGMARKER PC版的试玩,它把项目分为事件和数据(可单独划分出map)两类。其实它事件也是当作数据的,因为游戏本身的系统是固定的。后来的的版本由增加脚本模块,并预置了系统本身使用的脚本,按作用木桶分为:模块,游戏对象,精灵,窗口,场景,自定义插件,主程序。这些脚本可以看作是由原本固定的系统转化而成。在数据部分,系统是极有FF+DQ的风格。道具的效果或敌人的行为等设定并不直接提供脚本形式,而是选择预设的条件事件或加成效果等。事件编辑是条件加事件List(界面就是List加单独的属性框的设计)。RM的gba版和3d版也蛮有趣的样子啊。
看一些Galgame的引擎就是纯文本的脚本了,系统最基本的部分是提供了图像声音等一些功能调用。仅限定了游戏的形式,而对游戏的系统设计需自行完成(这样才被玩得有意思嘛)。不过这里通常就不用考虑OO了。状态以变量形式保存,用脚本展现游戏流程,再单独制作如存档等功能模块(包括场景)。
====
090819
关于WebApp的平台或框架,看了GAE和web.py的文档比较简明,虽然它们不是被通常使用。<-病句
AVG游戏的常见引擎有几个,这里略过。N,K,R.
有的CMS就可当框架用了,不过当然不是一回事情。
====
091029
只想着设计上的接口和抽象了,忘说cpp设计的一个初始目的是便于组织代码结构。<-当然前者仍是这贴里考虑的重点,貌似我当初是在这么写的。

2009年8月12日星期三

[回收贴]编写简单的语言解释器

说明:注意哦,是回收贴,把这段时间的一些实验的想法和代码贴过来。
都仍只是不成熟的内容,问题会比较多,而且缺少很多东西,如错误处理之类。
贴过来是觉得这些东西还是有点实用价值的。
因为代码中"<"和">"没有处理,所以#include部分在显示上有问题。
恩...我K&R风格的缩进也没显示出来。

Part1
编写简单的语言解释器
09-7-19

是想只记录构想要点的,不过仍是多了些无用的词句。不想在文字而非内容上耗时间。嗯,想到自己写文字为邮件是纯笔记的时候,是快快完成内容为先的啦。或者就把记事本里留的直接贴上,那个没有是专门去写的感觉。

语言用C,目地是纯实验,仅此很个人的。之前有试写了片段,不过若要完整的开始,还是先有份文档为好。
有三个方向,一个是GWBASIC兼容的,再适当扩展简单的代码风格。一个是基于lisp式表达式处理的,是处理type,value car,cdr式结构的,因为需要对list进行处理,不过如果从纯函数的角度说也不一定有必要。前面的那个就直接基于文本解析了,不按照编译原理先对完整的代码做词法和句法的分析,虽然有效率和编译时错误的缺陷,但我想会是仍能满足简单的运行要求。还有一个方向就是基于命令的如bat,sh,是语言本身就十分简单实用的实现。

BAS
由行构成,以换行或":"分割,行第一项为行号(纯数字只在换行后的行首,这次按Label处理,增加L语句)可省略,接着为语句名称,写为变量名的形式,对后续参数的处理由语句名称决定
变量简单地用链表储存,不hash或btree了。每项是字符串到值,值有类型和数据两部分。(之前第三类是全视为字符串,这里不是,有至少整数实数二进制字符串三类。)
先来流程控制部分。
LISP,先解析填充为树状结构,然后执行。两者之间可适当封装一下。
简单是原则哦。


lisp5.c

前缀表达式计算实验
ee.zsy按照BSD协议发布
缺陷
缺少错误处理
使用方法参见bat文件
lisp5.exe用TCC默认参数编译
09.07.12

BG
PLAN
简单的LISP解释器
//BAS解释器
TODO
逐步实现更多特性
从直接处理文本改为先转换为语法树
NEXT
改进getnum为getitem+isnum


#include
#include
#include
#include

char *exp;

int main(int argc, char** argv){
double eval();
//~ printf("argc %d\n",argc);
char ins[255];
gets(ins);
exp=ins;
printf("%s\n",exp);
//exp="(/ (+ 32 12) (* 1 4))";
printf("RST %g\n",eval());
return 0;
}

double getitem(){
double eval(),getnum();
if(*exp=='('){
printf("eval %s\n",exp);
return eval();
}else{
//printf("num %s\n",exp);
return getnum();
}
}

double getnum(){
int i=0;
char ts[10]={0,0,0,0,0,0,0,0,0,0};
printf("getnum %s\n",exp);
//~ for(i=0;isdigit(exp[i]);i++);
while(isdigit(exp[i]) || exp[i]=='.'){
i++;
}

printf("LEN %d\n",i);
strncpy(ts,exp,i);
printf("STR %s\n",ts);
printf("NUM %g\n",atof(ts));
exp+=i;
return atof(ts);
}

double eval(){
double p[5];
double result;
exp++;
switch(*exp){
case '+':
exp+=2;
p[0]=getitem();
exp+=1;
p[1]=getitem();
exp+=1;
printf("=%g+%g\n",p[0],p[1]);
result=p[0]+p[1];
break;
case '-':
exp+=2;
p[0]=getitem();
exp+=1;
p[1]=getitem();
exp+=1;
printf("=%g-%g\n",p[0],p[1]);
result=p[0]-p[1];
break;
case '*':
exp+=2;
p[0]=getitem();
exp+=1;
p[1]=getitem();
exp+=1;
printf("=%g*%g\n",p[0],p[1]);
result=p[0]*p[1];
break;
case '/':
exp+=2;
p[0]=getitem();
exp+=1;
p[1]=getitem();
exp+=1;
printf("=%g/%g\n",p[0],p[1]);
result=p[0]/p[1];
break;
default:
exit(1);
break;
}
return result;
}

getput.bat

getput.exe

后来随即尝试添加了cond语句(有嵌套的问题),并加入lisp中atom/list的处理,还没法编译。

3bas1.c

#include
#include
#include
#include
#define DebugPrint(SS) printf("%d:%s\n",__LINE__,SS);
int main(int argc, char** argv){
int LoadFile();
DebugPrint("main");
LoadFile();
return 0;
}

int LoadFile(){
DebugPrint("loadfile");
FILE *fp;
char *ss;
int fl;
fp = fopen("do2.c","r");
fseek(fp,0l,SEEK_END);
fl=ftell(fp);
fseek(fp,0l,SEEK_SET);
DebugPrint("as");
printf("LEN %2db\n",fl);
ss=(char*)malloc(fl+1);
int i;
for(i=0;i<=fl;i++) ss[i]='\0'; //~ ss[5]='\0'; //~ ss[0]='s'; //~ ss[1]='\0'; printf("%s\n",ss); //printf("%d",i); //~ int i; char ts[256]; for(i=0;i<=255;i++) ts[i]='\0'; //~ strcpy(ts,"bbbbbb"); //~ puts(fgets(ts,255,fp)); strcat(ss,ts); while(fgets(ts,256,fp) != NULL){ strcat(ss,ts); //~ puts("aa"); } //~ for(i=0;fgets(s,256,fp)!=NULL;i++){ //~ DebugPrint("cs"); //~ printf("%2d]",i+1); //~ puts(s); //~ strcat(ss,s); //~ puts(ss); //~ } fclose(fp); DebugPrint("bs"); printf("%s\n",ss); return 0; }

之后添加了

int main(int argc, char** argv)
int LoadSource(char* sn)
int NextStatement()//获取行并执行
int GetItemValue()
int GetItemLen(int start)
struct VarNode {
char *name;
char *value;
struct VarNode *next=NULL;
} VarNode0;//链表,可用代码在下面会有
char* GetVar(const char *name)
int SetVar(const char *name,const char *value)
char* NewStr(const char *Str)//malloc一个字符串的副本


Part2
BAS.txt

语句
[行号] 语句 参数
流程
label
goto
if then [else ]
//on goto
块
do
end
break,continue
for to stepnext
while:wend

命令
let =
表达式
运算符
数 +-*/
关系运算
字符串
]支持运算符和函数

变量储存
变量名,字符串
数组 支持数组语法 d(i,j)
转为字符串名处理 如 d_2_1
$运算符如 $abc
取字符串变量abc对应值为变量名的对应值
或单独建立类型名为引用
变量名是[a-zA-Z._0-9],凡是分隔符前不能被识别为数字的

def <>=<> 是扫描时定义,label


BAS表达式解析.txt

bas
目标 轻便

表达式计算 部分

记号
整数 digit
实数 digit|.|eE
//strtod能识别的部分,double
//能转换为整数就转换,运算都作实数
//或strtol
字符串 ""之间的
变量名 取得类型和值 alnum |$|%
之后有()则可能是
内置函数 运算
数组 查找
用户函数(或FN 开头) 查找并运算


操作符 长度>=1 可以前后有空格,或省略
优先级

针对double类型的
类型不符合则出错 类型错误
表达式(由高到低,优先处理):

括号表达式
数(leading 0 for octal, 0x for hex, else decimal),变量
一元 -
* /
+ -
= <>
> < <= >=
(* and + are also used for boolean AND and boolean OR)
Boolean expressions evaluate to 0 for false and 1 for true

对字符串类
& 合并
其他函数 返回值为数或字符串

解析函数为递归函数
被提供待解析的表达式
单独的片段
一个起始位
解析返回一个变量结构

流程
记号->变量->函数->常量
操作符

变量结构由链表储存
{
char *name
value
*}
*next
}

value emum type %{int
double
char

基本的常数运算

basexpr2.c
数值表达式

#include
#include
#include
#include
//~ #include
float expr();
float expr0();
float expr1();
float expr2();
float expr3();
float expr4();
float expr5();
float expr6();
char *e;
float expro=0;

double sin(double i){
return i+1;
}

float expr(){
char* o;
int i=expro,j;
expro=0;
do{
o=e;
expro=expr4();
}while(o!=e);
j=expro;
expro=i;
return j;
//~ return expr4();
}

float expr4(){
float o=expr3();
while(isspace(*e))e++;
if(!strncmp(e,"<=",2)){ e+=2; return o<=expr3(); }else if(!strncmp(e,">=",2)){
e+=2;
return o>=expr3();
}else
if(*e=='<'){ e++; return or,4:r->l
}else
if(*e=='>'){
e++;
return o>expr3();
}else{
return o;
}
}

float expr3(){
float o=expr2();
while(isspace(*e))e++;
if(*e=='='){
e++;
return o==expr2();
}else
if(!strncmp(e,"<>",2)){
e+=2;
return o!=expr2();
}else{
return o;
}
}

float expr2(){

float o=expr1();
while(isspace(*e))e++;
if(*e=='+'){
e++;
return o+expr1();//strtod(e,&endp);
}else
if(*e=='-'){
e++;
return o-expr1();//strtod(e,&endp);
}else{
return o;
}
}

float expr1(){
float o=expr0();
while(isspace(*e))e++;
if(*e=='*'){
e++;
return o*expr0();
}else
if(*e=='/'){
e++;
return o/expr0();
}else{
return o;
}
}

float expr0(void){
//~ char *endp;
//~ float o=strtod(e,&e);
while(isspace(*e))e++;
if(*e=='('){
e++;
float o=expr();
e++;
return o;
}else
if(isalpha(*e)){
if(!strncmp(e,"sin(",4)){
e+=4;
//~ return sin(expr());
//~ e++;
float o=expr();
e++;
return sin(o);
}
}else{
/* o=strtod(e,&e);//printf("%d\n",o);
* //~ e=endp;
* //~ else
*
* if(*e==')'){
* e++;printf("%d\n",o);
* return expr2(e);
* }else{
*
* return o;
* }
*/ if(expro!=0){float o=expro;expro=0;return o;}
else{return strtod(e,&e);}

//~ return strtod(e,&e);
}
}

int main(int argc, char** argv){
e="4+<5"; i="expr();">

basstrexpr.c
字符串表达式

#include
#include
#include
#include

char *e;
char* getstr();
char* strexpr1();

char* strexpr1(){
char* o=getstr();
while(isspace(*e))e++;
if(*e=='&'){
e++;
while(isspace(*e))e++;
char* p=strexpr1();
char* q=strcat(strcpy(malloc(strlen(o)+strlen(p)+1),o),p);
free(o);free(p);
return q;
}else{
return o;
}
}

char* getstr(){
while(isspace(*e))e++;
//not necessary
//~ if(*e=='('){
//~ e++;
//~ char* o=strexpr1();
//~ e++;
//~ return o;
//~ }else
if(*e=='\"'){
int i;
e++;
i=strchr(e,'\"')-e;
//~ printf("%d\n",i);
char* p;
p=strncpy(malloc(i+1),e,i);
p[i]='\0';
e+=i+1;
//~ if(p[i-2]!="\0"){
//~ p[i-2]="\0";
//~ }
//~ printf("%d\n%d\n%s\n",i,strlen(p),p);
return p;
}else
if(!strncmp(e,"left(",5)){
e+=5;
char* o=strexpr1();
e++; // ,
int i=strtod(e,&e);
e++; // )
char *p=strncpy(malloc(i+1),o,i);
p[i]='\0';
free(o);
return p;
}
}

int main(int argc, char** argv){
e="left(\"ABcdefg\"&\"CD\",9)&\"EF\"";
printf("e]%s\n",e);
char* i=strexpr1();
printf("]%s\n",i);
printf("]%s\n",e);
free(i);
return 0;
}


basvarnum.c
变量-数字部分

#include
#include
#include
#include
struct num* findnum(char*name);
float getnum(char *name);
int putnum(char *name,float value);

struct num{
char*n;
float v;
struct num *next;
} lne;//list num start
struct num* lns=⪇
//~ struct num ;
//~ lns.v=0.0;
//~ lns.next=NULL;
struct num* findnum(char*name){
struct num* i;
for(i=lns;(i->next)!=NULL;i=i->next){
if(strcmp(i->n,name)==0){
return i;
}
}
printf("not found %s\n",name);
return NULL;
}

float getnum(char *name){
struct num* o=findnum(name);
if(o!=NULL){
return o->v;
}
return 0;
}
int putnum(char *name,float value){
struct num* o;
o=findnum(name);
if(o!=NULL){//exist
o->v=value;
return 0;
}else{//new
o=malloc(sizeof(struct num));
o->n=name;
o->v=value;
o->next=lns;
lns=o;}
return 0;
}

int main(int argc, char** argv){
lne.n="test";
lne.v=123456;
lne.next=NULL;
putnum("a",1);
putnum("b",2);
putnum("c",3);
putnum("b",980);
//~ printf("%g\n",lns->v);
//~ lns=lns->next;
//~ printf("%g\n",lns->v);
//~ lns=lns->next;
//~ printf("%g\n",lns->v);
//~ lns=lns->next;
//~ printf("%g\n",lns->v);
//~ lns=lns->next;
//~ printf("%g\n",lns->v);
//~ findnum("b");
struct num* o=findnum("a");
if(o!=NULL){
printf("%g\n",o->v);
}

printf("%g\n",getnum("b"));
return 0;
}



Part3
变量存放.txt

以链表为基础name->value
局部变量用局部链
或加前缀
或允许同名并针对块语句处理

isitem(",")
=" "*," "*
e++

设计文档与草图
和编码过程

内置函数
数学函数num->num
字符串str->str
str->num
len
val
num->str
str/str$

合并为函数,也可match ,用
if(!strncmp(e,"while",5)){
e+=5;
}
while(isspace(*e))e++;

或建立单独的词法分析函数


对于模块先理,有规划和散开简单的尝试,再补充技术要点,使能初步运行,再补完和修改
有步骤和完成效率,补完类似代码时,目标相对非模糊

往专业化的痕迹

bas转c
添加如字符串库


块语句
设置execline标志判断块内是否执行(或passline)
某变量为记录块的嵌套层数
如果要层可嵌套,则块的首尾语句都要处理,不受标志影响
上层块设定不执行块内语句(不包含结构语句),内层则不做判断,直到上层的结束时恢复标志
块内可有局部变量

对解释while/wend块,若在执行状态则wend处跳回while之前,否则继续执行之后的语句

label table建立(常量)

basexpr3.c
上部分的代码合并并添加新特性

#include
#include
#include
#include
//~ #include

char* getstr();
char* strexpr1();


//================================================================================================
struct num* findnum(char*name);
float getnum(char *name);
int putnum(char *name,float value);

struct num{
char*n;
float v;
struct num *next;
} lne;//list num start
struct num* lns=⪇
//~ struct num ;
//~ lns.v=0.0;
//~ lns.next=NULL;
struct num* findnum(char*name){
struct num* i;
for(i=lns;(i->next)!=NULL;i=i->next){
if(strcmp(i->n,name)==0){
return i;
}
}
printf("not found %s\n",name);
return NULL;
}

float getnum(char *name){
struct num* o=findnum(name);
if(o!=NULL){
return o->v;
}
return 0;
}
int putnum(char *name,float value){
struct num* o;
o=findnum(name);
if(o!=NULL){//exist
o->v=value;
return 0;
}else{//new
o=malloc(sizeof(struct num));
o->n=name;
o->v=value;
o->next=lns;
lns=o;}
return 0;
}

//~ int main(int argc, char** argv){
//~ lne.n="test";
//~ lne.v=123456;
//~ lne.next=NULL;
//~ putnum("a",1);
//~ putnum("b",2);
//~ putnum("c",3);
//~ putnum("b",980);

//~ struct num* o=findnum("a");
//~ if(o!=NULL){
//~ printf("%g\n",o->v);
//~ }

//~ printf("%g\n",getnum("b"));
//~ return 0;
//~ }
//============================================================================

float expr();
float expr0();
float expr1();
float expr2();
float expr3();
float expr4();
float expr5();
float expr6();
char *e;
float expro=0;

double sin(double i){
return i+1;
}

float expr(){
char* o;
int i=expro,j;
expro=0;
do{
o=e;
expro=expr4();
}while(o!=e);
j=expro;
expro=i;
return j;
//~ return expr4();
}

float expr4(){
float o=expr3();
while(isspace(*e))e++;
if(!strncmp(e,"<=",2)){ e+=2; return o<=expr3(); }else if(!strncmp(e,">=",2)){
e+=2;
return o>=expr3();
}else
if(*e=='<'){ e++; return or,4:r->l
}else
if(*e=='>'){
e++;
return o>expr3();
}else{
return o;
}
}

float expr3(){
float o=expr2();
while(isspace(*e))e++;
if(*e=='='){
e++;
return o==expr2();
}else
if(!strncmp(e,"<>",2)){
e+=2;
return o!=expr2();
}else{
return o;
}
}

float expr2(){

float o=expr1();
while(isspace(*e))e++;
if(*e=='+'){
e++;
return o+expr1();//strtod(e,&endp);
}else
if(*e=='-'){
e++;
return o-expr1();//strtod(e,&endp);
}else{
return o;
}
}

float expr1(){
float o=expr0();
while(isspace(*e))e++;
if(*e=='*'){
e++;
return o*expr0();
}else
if(*e=='/'){
e++;
return o/expr0();
}else{
return o;
}
}

float expr0(void){
//~ char *endp;
//~ float o=strtod(e,&e);
while(isspace(*e))e++;
if(*e=='('){
e++;
float o=expr();
e++;
return o;
}else
if(isalpha(*e)){
if(!strncmp(e,"sin(",4)){
e+=4;
//~ return sin(expr());
//~ e++;
float o=expr();
e++;
return sin(o);
}else
if(!strncmp(e,"len(",4)){
e+=4;
//~ return sin(expr());
//~ e++;
char* o=strexpr1();
e++;
int i=strlen(o);
free(o);
return i;
}else{//getvar
char* p=e;
while(isalnum(*e)){
e++;
}
//~ puts(e);
//~ printf("%d\n",e-p);
int i=e-p;
p=strncpy(malloc(i+1),p,i);
p[i]='\0';
puts(p);
float l=getnum(p);
free(p);
return l;
}
}else{
/* o=strtod(e,&e);//printf("%d\n",o);
* //~ e=endp;
* //~ else
*
* if(*e==')'){
* e++;printf("%d\n",o);
* return expr2(e);
* }else{
*
* return o;
* }
*/ if(expro!=0){float o=expro;expro=0;return o;}
else{return strtod(e,&e);}

//~ return strtod(e,&e);
}
}

//=====================================================================================
//~ char *e;
//~ char* getstr();
//~ char* strexpr1();

char* strexpr1(){
char* o=getstr();
while(isspace(*e))e++;
if(*e=='&'){
e++;
while(isspace(*e))e++;
char* p=strexpr1();
char* q=strcat(strcpy(malloc(strlen(o)+strlen(p)+1),o),p);
free(o);free(p);
return q;
}else{
return o;
}
}

char* getstr(){
while(isspace(*e))e++;
//not necessary
//~ if(*e=='('){
//~ e++;
//~ char* o=strexpr1();
//~ e++;
//~ return o;
//~ }else
if(*e=='\"'){
int i;
e++;
i=strchr(e,'\"')-e;
//~ printf("%d\n",i);
char* p;
p=strncpy(malloc(i+1),e,i);
p[i]='\0';
e+=i+1;
//~ if(p[i-2]!="\0"){
//~ p[i-2]="\0";
//~ }
//~ printf("%d\n%d\n%s\n",i,strlen(p),p);
return p;
}else
if(!strncmp(e,"left(",5)){
e+=5;
char* o=strexpr1();
e++; // ,
int i=strtod(e,&e);
e++; // )
char *p=strncpy(malloc(i+1),o,i);
p[i]='\0';
free(o);
return p;
}
}

//~ int main(int argc, char** argv){
//~ e="left(\"ABcdefg\"&\"CD\",9)&\"EF\"";
//~ printf("e]%s\n",e);
//~ char* i=strexpr1();
//~ printf("]%s\n",i);
//~ printf("]%s\n",e);
//~ free(i);
//~ return 0;
//~ }
//========================================================================================

int main(int argc, char** argv){
putnum("a",1);
putnum("b",2);
putnum("cde",3);
e="len(\"asf\")+1";
float i=expr();
printf("%g",i);
return 0;
}


baslineexper.c
按行解析

#include
#include
#include
#include

char *e=
//"0 goto 30 \n"
//"5 print a\n"
"10 while 1\n"
"pause\n"
"while 1\n"
"print in\n"
"pause f\n"
"wend\n"
"wend\n"
//"20 goto 25\n"
"25 end\n"
"30 print 3\n";

char* pe;
char *s[256];//存放指针的数组,不用存行号了
char **ps;//指针 指向 指,数组(类型为指针)的元素

int main(int argc, char** argv){
pe=e;
ps=s;
int ln;
e--;
int passline=0;//跳过执行块内语句,非零为块的条件不成立时
do{
e++;
ln=strtol(e,&e,10);//pass line num
printf("e>\n===\n%s===\n",e);

while(isspace(*e))e++;
if(!strncmp(e,"while",5)){
//e+=5;
puts("[while]");
*ps++=e;
e+=5;
int i=strtod(e,&e);
if(passline==0){
passline=(i==0);
}else passline++;
printf("i='%d'\t%d\n",i,passline);
//~ push(ln);
if(ps==s+10)exit(5);
}else
if(!strncmp(e,"wend",4)){
e+=4;
puts("[wend]");
//~ int i=strtod(e,&e);
//~ printf("i='%d'\n",i);
printf("i\t%d\n",passline);
//~ pop(ln);
//~ //goto ln
if(passline==0){e=*--ps;}
else {--ps;passline--;}

printf("i\t%d\n",passline);
}else

if(passline)continue;
else

if(!strncmp(e,"print",5)){
e+=5;
puts("[print]");
while(isspace(*e))e++;
//

}else

if(!strncmp(e,"pause",5)){
e+=5;
puts("[pause]");


}else

if(!strncmp(e,"goto",4)){
e+=4;
puts("goto");
int i=strtod(e,&e);
printf("i='%d'\n",i);
e=pe-1;
do{
e++;
if(i==strtol(e,&e,10))break;
}while(e=strchr(e,'\n'));



//~ push(ln)
}else

if(!strncmp(e,"for",3)){
e+=3;
puts("[for]");
//~ int i=strtod(e,&e);
//~ printf("i='%d'\n",i);
//~ push(ln)
}else
if(!strncmp(e,"next",4)){
e+=4;
puts("[next]");
//~ int i=strtod(e,&e);
//~ printf("i='%d'\n",i);
//~ pop(ln);
//goto ln
}else
if(!strncmp(e,"end",3)){
e+=3;
puts("[end]");
exit(0);
}
//block,gosub,let,def,data,dim
//else
//if//to
//nextline
}while(e=strchr(e,'\n'));

puts("prog end");

return 0;
}


这个,我编辑器的框好小啊,纯写文字还好,一贴代码自己已经晕了。强调一下,我没考虑错误处理,贴的都是能编译的代码。自己这样一行行写的也是好耗时间的,自己还是不熟练啊。特别是把构想的细处实现的时候,还只有找个安静的地方一人想想才有些进展啊。

补充一下,目前的代码是把数,字符串,数组,变量分开处理的,包括解析和变量存放,比较简单的。另一种是变量是引用一个值,而值是有类型的,可以被处理函数获取。而不同于上面的觉得遇到的应该是什么类型。
表达式解析,除了用专用的词法与句法分析工具,可以递归解析。或从左到右,用两个stack存放元素和操作符。根据操作符的优先级,来进行运算。需要注意stack的长度,避免溢出或动态管理。目前觉得这样可能比递归会更好处理元素类型(?)。
现在是按照纯文本,没有编译加虚拟机,为跨平台考虑。可以解释器与虚拟机分离,使客户端轻便,但不要影响描述性脚本数据的易编辑。

Part4
上面实验代码就这样吧,不行再修改,以后重写时会用到。bas的解释器没写完,暂时停工了,在等打算好下一步的规划。
再贴一点上面已包含的小片段吧。还有一些参考资料。小片段的内容还思路很明了的感觉啊。

K&R
http://cis.csuohio.edu/~somos/ddsbasic.c
http://www.personal.leeds.ac.uk/~bgy1mm/Minibasic/MiniBasicHome.html
WxBasic PDF
FreeBasic chm
http://www.nicholson.com/rhn/basic/
编译原理
编程语言概念/原理

注意需要引用的库,K&R关于库的部分相当粗略。

int GetFileLen(){
FILE *fp;
int fl;
//FILE *fopen(char *name, char *mode);
fp = fopen("do2.c","r");
fseek(fp,0l,SEEK_END);
fl=ftell(fp);
//printf("%d",i);
fclose(fp);
return fl;
}


#include
#include
#include
#include

int main(int argc, char** argv){
char* e="assd+sdfdf";
char* p=e;
while(isalnum(*e)){
e++;
}
puts(e);
printf("%d\n",e-p);
int i=e-p;
p=strncpy(malloc(i+1),p,i);
p[i]='\0';
puts(p);
//free(p);
return 0;
}


...


回收贴了,东西杂乱了一点。
已经成了我不喜欢的形态了。
而且没语法高亮好不习惯,不如直接备份文件了,不过这里好自己附些评论。
对于耗时的事情,定计划长期行为,还是会有效过些。
当然也要预定好目的和结果。

补一下有关日期(会发现是纯粹在写着娱乐啊,日期是最后修改日期)

开贴 090812
today 090813
exp.exe 090709
lisp.c 090712
lisp7.c 0907113
3bas2.c 090720
复件 basexpr.c 090723
复件 basvarnum.c 090731
basexpr2.c 090729
basexpr3.c 090801
BAS.txt 090720
BAS表达式解析.txt 090723
basexpr.c 090727
basexpr2.c 090729
basstrexpr.c 090731
basvarnum.c 090731
basexpr3.c 090801
复件 baslineexper.c 090807
baslineexper.c 090811
变量存放.txt 090811

对这些日期,我承认,我只是想证明一下自己的存在感。
我这段期间里上cnbeta和acfun(我也是东方爱好者哦,还没狂热)也比较多,估计会有同好者看见啊。

====顺便写点,也回收了
说一下前面那贴翻译,目前没计划推动说要就翻译全文,仅凭喜好一点点做了。看来没翻译全部完成的可能,不过不至于是看自己无聊时间到什么地步才做的翻译。

我在自聊?

====
091029
The C++ Programming Language,Special Edition 里把简单的表达式计算作为示例,有很好的代码(相比我的那些就...),即使用C改写也是很容易的。