??xml version="1.0" encoding="utf-8" standalone="yes"?>精品午夜久久福利大片,伊人久久大香线蕉成人,久久综合亚洲欧美成人http://www.shnenglu.com/kevinlynx/category/9735.html低调做技术__ C/C++\MMORPG服务器\模块架构__ TODOQ编译原理\linux env __Kevin Lynxzh-cnMon, 15 Mar 2010 04:11:09 GMTMon, 15 Mar 2010 04:11:09 GMT60kl中的错误处理http://www.shnenglu.com/kevinlynx/archive/2009/03/26/77963.htmlKevin LynxKevin LynxThu, 26 Mar 2009 09:17:00 GMThttp://www.shnenglu.com/kevinlynx/archive/2009/03/26/77963.htmlhttp://www.shnenglu.com/kevinlynx/comments/77963.htmlhttp://www.shnenglu.com/kevinlynx/archive/2009/03/26/77963.html#Feedback0http://www.shnenglu.com/kevinlynx/comments/commentRss/77963.htmlhttp://www.shnenglu.com/kevinlynx/services/trackbacks/77963.htmlkl中的错误处理

    之前我一直说错误处理是kl里的软肋Q由于一直在x一些具体功能的改进Q也没有?br>q方面进行改善?

    我这里所说的错误处理Q包括语a本n和作为库本n两方面?br>    语言本n指的是对于脚本代码里的各U语法错误、运行时错误{的处理。好的处理应?br>不仅仅可以报告错误,而且q能忽视错误让处理过El?br>    而把kl解释器作Z个库使用Ӟ库本w也应该对一些错误情况进行报告?

    整体上,kl单地通过回调函数指针来把错误信息传给库的应用层。而因为我希望整个
kl实现的几层(词法分析、语法分析、符可、解释器{)(j)可以可能地独立。例如虽然语
法分析依赖于词法分析Q依赖于词法分析提供的接口)(j)Q但是因法分析ƈ不对语法分析
依赖Q所以完全可以把词法分析模块拿出来单独用。所以,在日志方面,我几乎ؓ(f)每一?br>都附加了个error_log函数指针?br>    而用户层在通过kllib层用整个库Ӟ传入的回调函C(x)被间接地传到词法分析层?br>实际上,当kl作ؓ(f)一个库Ӟkllib正是用于桥接库本w和用户层的bridge?

    另一斚wQ语a本n在处理错误的脚本代码Ӟ错误分ؓ(f)几大cd层次Q?br>    1.词法错误 lex errorQ如扫描字符串出?br>    2.语法错误 syntax errorQ整理语法树(wi)时出?br>    3.q行旉?runtime errorQ在解释执行代码时出?br>    4.库错?lib errorQ发生在kllibq个bridge层的错误
    kl在报告错误信息时Q会(x)首先附加该错误是什么类型的错误?

    q里最ȝ(ch)的是语法错误的处理。因法分析时发生错误的可能性最大,错误cd?br>有很多。例如你写了分P写了括P都会(x)D错误。这个阶D发生错误不仅要求能?br>报告错误,q需要忽略错误让整个q程量正确C厅R?

    语法分析阶段最Ҏ(gu)的就是符h|单就kl的实现而言Q,所谓的W号推导是这样一
个过E,例如有赋D句:(x)a = 1;语法分析Ӟ语法分析器希望(所谓的推导Q等号后面会(x)
是一个表辑ּQ当分析完了表达式后Q又希望接下来的W号(token)是分号作语句的结
束?br>    所以,klparser.c中的syn_match正是完成q个q程。每ơ你传入你希望的W号Q例?br>分号Q该函数检查词法分析中当前W号(token)是否是分受当?dng)对于正确的脚本代码?br>它是一个分P但是如果是错误的代码Qsyn_match׃(x)打印诸如Q?br>    >>syntax error->unexpected token-> ....
    卛_前的W号是不被期望的?

    上面完成了错误的(g)。对于错误的忽略Q或者更高点地寚w误的校正Qkl中处理得
比较单,卻I(x)直接消耗掉q个不是期望中的W号。例如:(x)
    a = 1 /* 忘加了分?*/
    b = 1;
    上面两句代码被处理时Q在处理完a=1后,发现当前的符?token)b(是一个ID token)?br>是期?expect)中的分号Q首先报告b不是期望的符P然后kl直接掠过bQ获取下个符??br>然后处理a=1q个q程l束。当?dng)下次处理其他语句Ӟ发?W号Q又?x)l发生错误?

    错误信息中比较重要的q有行号信息。之前klq方面一直存在BUGQ我在写贪食蛇例?br>的时候每ơ新加代码都不敢加太多。因释器报告的错误行hL错误的,我只能靠有没
有错误来N误,而不能通过错误信息N误?br>    行号信息被保存在词法分析状态中(lexState:lineno)Q语法分析中获取tokenӞ?x)?br>出当前的行号Q保存到语法?wi)?wi)节点中。因为包括解释模块都是基于树(wi)节点的,所以词法分
析语法分析解释器三层都可以准报告行受?

    但是之前解释器报告的行号始终很诡异。症l在于我在蝲入脚本代码文件时Q以rb方式
载入Q即二进制Ş式。于是,在windows下,每行文本N?x)有\r\n两个字符。而在词法?br>析阶D对于行L(fng)增加是:(x)
    case '\n':
    case '\r':
        ls->lineno ++;
    不同OS对于文本文g的换行所d的字W都不一P例如windows用\r\nQunixpȝ\n
Q貌似Mac用\r。所以,词法分析q里写应该可以准地处理行号?

    但是对于windowsQ这里就直接行号增加了两次Q所以也导致了行号出错的问题。查
了下文档Q发C文本方式打开文g("r")Q调用fread函数d文g内容Ӟ׃(x)自动?br>\r\n替换为\n?

    代码改后Q又出问题。这个时候,通过fseek和ftell获取到的文g寸Q貌似包括了
\r\nQ而fread出来的内容却因ؓ(f)替换\r\n为\n而没有这么多?br>    不过文g载入不属于kl库本w,kl只接收以字符串Ş式表C的脚本代码Q所以也不?br>核心问题?

    同样Q最C码可以从google SVN获取。当?dng)我也在考虑是否换一个新的项目地址?



Kevin Lynx 2009-03-26 17:17 发表评论
]]>
kl sample:贪食?/title><link>http://www.shnenglu.com/kevinlynx/archive/2009/03/25/77872.html</link><dc:creator>Kevin Lynx</dc:creator><author>Kevin Lynx</author><pubDate>Wed, 25 Mar 2009 13:17:00 GMT</pubDate><guid>http://www.shnenglu.com/kevinlynx/archive/2009/03/25/77872.html</guid><wfw:comment>http://www.shnenglu.com/kevinlynx/comments/77872.html</wfw:comment><comments>http://www.shnenglu.com/kevinlynx/archive/2009/03/25/77872.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/kevinlynx/comments/commentRss/77872.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/kevinlynx/services/trackbacks/77872.html</trackback:ping><description><![CDATA[<p><font size=2></font>  <p><font size=2>    貌似最qCPPBLOG写一门脚本语a比较行Q连我这U山寨程序员都搞Z个像C又像<br>BASIC的所谓脚本语aQ可见其行E度?/font></p> <p><font size=2><br>    q个kl脚本例子Q是一个具有基本功能的贪食蛇游戏。这个例子中使用了两个插Ӟ(x)<br><a target=_blank>HGE引擎</a>、以?qing)一个撇脚的二维数组插g。因为kl对于数组的实C是那么漂亮,而我实在<br>不想因ؓ(f)加入二维数组的支持而让代码看v来更乱,所以直接不支持q个Ҏ(gu)。考虑Cl?br>数组的应用在一些小游戏中还是比较重要(例如q个贪食蛇,总需要个容器M存游戏区?br>的属性)(j)Q所以撇脚地加了个支持number的二l数l插件?</font></p> <p><font size=2>    HGE插g我只port了部分接口,也就是注册了一部分函数到脚本里Q提供基本的贴图?br>能。(port--我实在找不到一个合适的词语来Ş容这U行?--HGEC门脚本语a里,我似<br>乎做q几ơ)(j) </font> <p><font size=2>    不知道有没必要提供贪食蛇的实现算法,q似乎说出来有点弱智? - 不过Z方便?br>人阅读kl脚本代码Q我q是E微讲一下。游戏中使用一个二l数l保存整个游戏区域,所?br>的游戏区域就是蛇可以zd到的地方。每一个二l数l元素对应游戏区域中的一个格子,?br>且称为tile。每个tile有一个整数DC其属性,如BODY、WALL、FOOD、NONE。蛇体的Ud<br>归根l底是蛇头和蛇Ud。蛇头和蛇尾属性一P但是蛇头负责把所l过的tile讄<br>为BODYQ而蛇ֈ把经q的tile讄为NONE。蛇头的Ud方向靠玩家控Ӟ每次蛇头转弯?br>Q都?x)记录一个{弯点C个队列。{弯点包括转弯XY坐标以及(qing)转向的方向。蛇每ơ移?br>旉?x)检查是否到达了一个{弯点Q是的话p|自qUd方向转弯点记录的方向?</font> <p><font size=2>    虽然我写了klq个脚本语言Q但是语aҎ(gu)ƈ不是我设计的。我只是取了C语言的一?br>Ҏ(gu)。所以在写这个sample的时候,我对于klq个脚本语言的感觉,是一个像basic的C?br>因ؓ(f)它太单一Q就像BASIC一样只拥有语言的一些基本功能,不能定义复杂的结构,没有?br>生的对各U数据结构的支持Q例如某些语a直接有list, tuple之类Q?</font> <p><font size=2>    以前中学的时候在?sh)子词典上用GVBASIC写小游戏Q当旉了BASIC什么也不知道。今?br>写这个贪食蛇例子Q感觉就像以前用BASIC?</font> <p><font size=2>    回头说说一些kl脚本里的Ҏ(gu)。从q个例子里(见下载包里的snake.klQ,诸如whileQ?br>forQif...else if...被支持(之前发布的版本里q不支持for和else ifQ。全局变量支持<br>赋初|上个版本不支持)(j)。当?dng)q演CZ如何使用插g函数?</font> <p><font size=2>    但是Q仍有一些特性在我的懒惰之下被置之不理。例如return后必跟一个表辑ּQ这<br>意味着单纯的return;被视ؓ(f)语法错误。对于if( a && b )Qkl?x)计所有的表达式,?br>别的语言也许?x)在a?x)false后不计算bQ这也许不算个问题,但v码我q没修正。还有,kl<br>内部对于错误的报告依然没被修复,打一个分号你?x)得Cpd错误的报告,但是却没?br>准确的行受甚臻I你会(x)看到解释器崩掉。不要紧Q在我心里,它作为当q电(sh)子词怸那个<br>GVBASIC而言Q已l很强大的了?DD</font> <p><font size=2>    最q接触了很多UNIX和GNU之类的东西,发觉没有提供版权说明?#8216;开?#8217;Q原来都是伪<br>开源。虽然我也想按照<a target=_blank>GNU~码标准</a>里所说ؓ(f)kl的发布包里附加Changelog之类的说明,但是<br>Z懒惰Q还是以后再说吧。同Pq次提供的下载里包含了一些编译好的东西,所以我?br>保证它在你的机器上依然可以运行。我使用了MingW来编译这些,q且提供有点丑陋的Makefile?br>HGE使用?.81版本?br>    贴张囄懒得下蝲的hQ?</font></p> <p><a href="http://www.shnenglu.com/images/cppblog_com/kevinlynx/WindowsLiveWriter/klsample_12B5E/snake_screenshot.jpg"><img style="BORDER-RIGHT-WIDTH: 0px; BORDER-TOP-WIDTH: 0px; BORDER-BOTTOM-WIDTH: 0px; BORDER-LEFT-WIDTH: 0px" border=0 alt=snake_screenshot src="http://www.shnenglu.com/images/cppblog_com/kevinlynx/WindowsLiveWriter/klsample_12B5E/snake_screenshot_thumb.jpg" width=670 height=433></a> </p> <p><font size=2>    <a href="http://www.shnenglu.com/Files/kevinlynx/snake_sample.zip" target=_blank>下蝲例子</a>Q包含脚本代码?</font> <p><font size=2>    如果要获取kl实现代码Q徏议从我在google的SVN获取Q?br></font><a ><font size=2>http://code.google.com/p/klcommon/</font></a></p> <img src ="http://www.shnenglu.com/kevinlynx/aggbug/77872.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/kevinlynx/" target="_blank">Kevin Lynx</a> 2009-03-25 21:17 <a href="http://www.shnenglu.com/kevinlynx/archive/2009/03/25/77872.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>实现一U解释性脚本语aQ七Q?/title><link>http://www.shnenglu.com/kevinlynx/archive/2009/03/12/76302.html</link><dc:creator>Kevin Lynx</dc:creator><author>Kevin Lynx</author><pubDate>Thu, 12 Mar 2009 01:35:00 GMT</pubDate><guid>http://www.shnenglu.com/kevinlynx/archive/2009/03/12/76302.html</guid><wfw:comment>http://www.shnenglu.com/kevinlynx/comments/76302.html</wfw:comment><comments>http://www.shnenglu.com/kevinlynx/archive/2009/03/12/76302.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.shnenglu.com/kevinlynx/comments/commentRss/76302.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/kevinlynx/services/trackbacks/76302.html</trackback:ping><description><![CDATA[<p><font size=2>author: Kevin Lynx email: zmhn320#163.com date: 3.12.2009 </font> <p><font size=2><strong>脚本与C语言交互</strong> </font> <p><font size=2>    q其实是q一pd的最后一,因ؓ(f)我觉得没什么其他需要写的了?br>    一般而言Q脚本语a同C语言交互Q包括在C语言中注册C函数到脚本,从而扩展脚本的<br>功能Q以?qing)在C语言中调用脚本函数?br>    Z扩展脚本的功能,q里引入插g的概c(din)kl在这斚w大致上实现得和lua怼。kl<br>支持静态插件和动态插件?br>    在C语言中调用脚本函敎ͼkl中提供了一些简单的接口用于满需求?</font> <p><font size=2><strong>静态插?/strong> </font> <p><font size=2>    静态插件其意思是在C代码中注册函数到脚本中,q脚本库一L(fng)译链接成最l执?br>E序。因为其l定是在开发一个程序的q程中,所以被UCؓ(f)静态的?br>    一个插件函敎ͼ指的是可以被注册q脚本的C函数。这U函数必d型一P在kl中这<br>个函数的原型为:(x)typedef struct TValue (*kl_func)( ArgType arg_list );    <br>    当你定义了一个这L(fng)原型的函数时Q可以通过kl库提供的:<br>    int kl_register( struct klState *kl, kl_func f, const char *name )来注册该<br>函数到kl脚本中。该函数参数很简单,W三个参数指定注册进脚本中时的名字?</font> <p><font size=2>    原理比较单:(x)在解释器中保存着一个插件符可Q该W号表的W号名就是这个函数提<br>供的名字Q符号对应的值就是第二个参数Q也是插g函数的函数地址?br>    解释器解释到函数调用Ӟ先从插gW号表中查找Q如果找到符P将W号的D{?br>为插件函敎ͼq调用之?</font> <p><font size=2>    插g函数的参数其实是一个参数链表。脚本里调用插g函数Ӟ所传递的参数被解释<br>器整理成参数链表q传递给插g函数。kl库中(集中在kllib.h?提供了一些方便的接口?br>于获取每个参数?br>    插g函数的返回g被解释器{换ؓ(f)脚本内部识别的格式,q在必要的时候参与运?br>?</font> <p><font size=2><strong>动态插?/strong> </font> <p><font size=2>    动态插件同静态插件的q作方式相同Q所不同的是动态插件的插g函数被放在动态运?br>时库里,例如windows下的dll?br>    kl插g~写标准里要求每个动态插件必L供一个lib_open函数。kl解释器(或者kl?br>--当被用作库时Q蝲入一个动态插件时Q会(x)直接调用lib_open函数。lib_open函数的主要目<br>的就是把该插件中的所有函数都注册q脚本里?</font> <p><font size=2>    因ؓ(f)动态插件在设计之初没有被考虑Q所以我q没有ؓ(f)kl加入一些原生的关键字用于导<br>入动态插Ӟ例如import、require之类。我在静态插件层ơ提供了q个功能。即我提供了<br>一个libloader静态插Ӟ链接qkl解释器程序。该静态插件提供脚本一个名为import的函<br>数。该函数负责动态蝲入dll之类的动态库Qƈ调用里面的lib_open函数完成动态插件的?br>册?</font> <p><font size=2><strong>CE序里调用脚本函?/strong> </font> <p><font size=2>    q个比较单,通常C语言惌用一个脚本函数时Q会(x)传入脚本函数名。因本函数名<br>都保存在全局W号表里Qkl库从全局W号表找到该函数W号Qƈ转换其gؓ(f)语法?wi)节?gu)?br>Q然后传入解释器模块解释执行?br>    kl库提供struct TValue kl_call( struct klState *kl, const char *name, ArgType args );<br>用于在C里调用脚本函数?</font> <p><font size=2><strong>代码D</strong> </font> <p><font size=2>    kllib.h/kllib.c作ؓ(f)一个桥接层Q用于封装其他模块可以提供给外部模块使用的接口,<br>如果kl作ؓ(f)一个库使用Q用户代码大部分时候只需要用kllib.h中提供出来的接口?br>    源码目录plugin下的kllibbase.c中提供了静态插件的例子Qkllibloader.c提供了装?br>动态插件的功能?br>    源码目录plugin/hge目录下是一个封?D游戏引擎HGE部分接口到kl脚本中的动态插?br>例子?br>    源码目录test/kl.c是一个简单的kl解释E序Q它用于执行一Dkl代码。这个程序同之前<br>说的解释器不是同一回事。当我说到解释器Ӟ它通常指的是klinterpret.c中实现的解释<br>模块Q而解释器E序则指的是一个用了kl库的独立解释器可执行E序?/font> <p><font size=2></font></p> <img src ="http://www.shnenglu.com/kevinlynx/aggbug/76302.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/kevinlynx/" target="_blank">Kevin Lynx</a> 2009-03-12 09:35 <a href="http://www.shnenglu.com/kevinlynx/archive/2009/03/12/76302.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>实现一U解释性脚本语aQ六Q?/title><link>http://www.shnenglu.com/kevinlynx/archive/2009/03/11/76176.html</link><dc:creator>Kevin Lynx</dc:creator><author>Kevin Lynx</author><pubDate>Wed, 11 Mar 2009 01:12:00 GMT</pubDate><guid>http://www.shnenglu.com/kevinlynx/archive/2009/03/11/76176.html</guid><wfw:comment>http://www.shnenglu.com/kevinlynx/comments/76176.html</wfw:comment><comments>http://www.shnenglu.com/kevinlynx/archive/2009/03/11/76176.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/kevinlynx/comments/commentRss/76176.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/kevinlynx/services/trackbacks/76176.html</trackback:ping><description><![CDATA[<p><font size=2>author: Kevin Lynx email: zmhn320#163.com date: 3.11.2009 </font> <p><font size=2><strong>解释?/strong> </font> <p><font size=2>    整理法树(wi)后,我们可以根据语法树(wi)Qƈ配合W号表开始解释执行脚本代码。这?br>是接下来要涉?qing)到的解释器?</font> <p><font size=2><strong>工作原理</strong> </font> <p><font size=2>    在第四节中讲语法?wi)时Q其实就已经提到解释器的大致工作原理?br>    一个kl的hello world例子代码大致为:(x)<br>    function main()<br>    {<br>        print( "hello world\n" );<br>    }<br>    在第二节中我描述了kl代码整体上的l构Q是以函Cؓ(f)单位的。因此,对于一个完整的<br>kl脚本代码Q其l过语法处理后,徏立一大的语法树(wi)Q该语法?wi)大致结构?f)Q?br>    fn1_node<br>        stmt_node1<br>        stmt_node2<br>        ...<br>    fn2_node<br>        stmt_node1<br>        stmt_node2<br>        ... </font> <p><font size=2>    fn1_node和fn2_node同属于同一个作用域Qfn1_node的sibling指针指向fn2_nodeQ即?br>整个?wi)结构中Q每一个node通过child[3]成员q接其子节点Q通过sibling指针q接其相?br>的节炏V?nbsp;   <br>    解释器解释执行时Q就是从main函数所对应的节点开始递归执行的。对于每个节点,?br>可以知道该节点对应了哪种E序逻辑Q是加法q算、比较运、还是一些控制语句等{?br>    以这L(fng)控制语句举例Q?br>    if( 1 ) print( "true" );<br>    对if语句而言Q其语法?wi)结构?f)Q?br>          if_node<br>         /   |    \<br>        /    |     \ <br>    con_exp    then_stmt else_stmt </font> <p><font size=2>    卻Iif语句有最多有三个子节?child[3])Qchild[0]指向if的条件表辑ּQchild[1]<br>指向条g表达式ؓ(f)真时执行的语句序列,如果if有else部分Q那么child[2]指向else部分<br>的语句序列?br>    那么Q在发现某个节点是if节点Ӟ首先计其条g表达式节炏V这个节点的计算?br>式同脚本中其他所有表辑ּ的计方式相同,当然Q它也是一个递归操作。计完后判断该<br>表达式的值是否ؓ(f)真,为真则递归执行if节点的child[1]节点Q否则检查是否有else节点Q?br>有的话就执行child[2]节点?</font> <p><font size=2>    其他所有节点的解释方式都是相同的?/font></p> <p><font size=2><br><strong>解释器环?/strong> </font></p> <p><font size=2>    解释器环境指的是解释器在解释执行脚本代码Ӟ所需要的q行时环境。kl中主要是W?br>可信息。一个解释器环境?x)有三个W号表:(x)全局W号表,主要保存全局变量以及(qing)脚本函数<br>W号Q函数局部符可Q在解释调用一个脚本函数时Q会(x)建立临时的符可Q插件符可Q?br>用于保存插g注册的函数?</font> <p><font size=2><strong>如何解释执行函数</strong> </font> <p><font size=2>    函数主要有两大类型:(x)脚本内定义的函数以及(qing)插g注册q符可的函数。无论是哪种?br>敎ͼ都会(x)在符可中徏立对应的W号。对于前者,W号被保存于全局W号表,其保存的内容<br>是该函数节点的节Ҏ(gu)针;而对于后者,则保存的插g函数的函数地址倹{?</font> <p><font size=2>    每一ơ解释器解释C个函数调用节Ҏ(gu)Q会(x)优先在插件符可中查找该函数W号。如<br>果找刎ͼ将其D{换ؓ(f)U定的插件函数类型(如同lua里注册的C函数一P(j)Q然后整理参<br>数调用之。这个时候代码执行权转接到插件函数里。如果没扑ֈQ就在全局W号表里查找Q?br>扑ֈ后就{法树(wi)节点指针Qƈ解释执行该节点下的语句?</font> <p><font size=2><strong>代码D</strong> </font> <p><font size=2>    解释器的代码位于klinterpret.h/klinterpret.c中。整体上而言没什么特别的地方Q?br>主要是利用语法树(wi)的特炏V?br>    完成了这一节后Qkl已l可以解释执行所有的脚本语句。当?dng)因?f)没有输出功能Q?br>只能在调试器里看看计结果。下一节里?x)讲到将脚本l合qC语言Q从而可以让C语言注册<br>所谓的插g函数到脚本里Q也可以让脚本hprintq样的输出函数?</font> <p><font size=2></font></p> <img src ="http://www.shnenglu.com/kevinlynx/aggbug/76176.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/kevinlynx/" target="_blank">Kevin Lynx</a> 2009-03-11 09:12 <a href="http://www.shnenglu.com/kevinlynx/archive/2009/03/11/76176.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>实现一U解释性脚本语aQ五Q?/title><link>http://www.shnenglu.com/kevinlynx/archive/2009/03/10/76078.html</link><dc:creator>Kevin Lynx</dc:creator><author>Kevin Lynx</author><pubDate>Tue, 10 Mar 2009 00:58:00 GMT</pubDate><guid>http://www.shnenglu.com/kevinlynx/archive/2009/03/10/76078.html</guid><wfw:comment>http://www.shnenglu.com/kevinlynx/comments/76078.html</wfw:comment><comments>http://www.shnenglu.com/kevinlynx/archive/2009/03/10/76078.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/kevinlynx/comments/commentRss/76078.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/kevinlynx/services/trackbacks/76078.html</trackback:ping><description><![CDATA[<p><font size=2>author: Kevin Lynx email: zmhn320#163.com date: 3.10.2009 </font> <p><font size=2><strong>W号?/strong> </font> <p><font size=2>    在上一节中Q当我们的解释器解释执行age=age+1q个语法?wi)时Q会(x)涉及(qing)到变量age的?br>。实际上我们q需要个保存脚本中相兛_量的模块Q当我们的解释器获取C个ID?wi)节?gu)<br>Q需要从q个模块中获取出该变量的|q参与运?br>    q个我称之ؓ(f)W号表。我惛_q里Q我所说的概念很可能和教科书有点不一样了?</font> <p><font size=2><strong>什么是W号表?</strong> </font> <p><font size=2>    W号?symbol table)如同其字面意思一P是一个表Q更宽泛地说是一个保存符?br>的容器?br>    脚本中诸如变量函Ccȝ东西都算作符P例如age。符可是保存q些W号的容<br>器?br>    在kl中,W号表保存着某一个作用域里的变量。其全局W号表还保存着函数W号Q对?br>函数W号而言Q其gؓ(f)语法?wi)?wi)节点的指针倹{当调用一个函数时Q将该D{换ؓ(f)?wi)节点?br>然后执行。当?dng)q应该算做解释执行一节的l节Q不多说?</font> <p><font size=2>    再明下W号表的作用QD例,在上一节中Q涉?qing)到q么一个例子函敎ͼ(x)<br>    value factor( TreeNode *node )<br>    {<br>        switch( node->type )<br>        {<br>            case ID:<br>                /* 在这里,发现一个树(wi)节点cd为IDQ就需要根据ID对应的名字,也就<br>                 是ageQ在W号表中查找age的?*/<br>                return ageQ?nbsp;   <br>        /* ... */<br>        }<br>    }<br>    以上注释阐述了符可的作用?</font> <p><font size=2><strong>W号表的实现</strong> </font> <p><font size=2>    其实不管W号表如何实玎ͼ对于其他模块而言Q对W号表的唯一要求是提供几个cM<br>q样的接口:(x)<br>    value sym_lookup( const char *name );<br>    void sym_insert( const char *name, value val ); <br>    也就是说Q提供查扄号|以及(qing)插入新符L(fng)接口?</font> <p><font size=2>    在kl中,使用?lt;~译原理与实?gt;中相同的W号表数据结构实现。即使用了hash表,<br>hash数组中每个元素保存的是一个链表头节点。每一个符号字W串通过散列函数得到hash?br>l烦(ch)引,然后在该索引里进行一ơ线性查找。很典型的hashl构?</font> <p><font size=2>    另一斚wQ因为kl支持全局和函数局部两个作用域。所以kl中有一个全局W号表,用于<br>保存全局变量以及(qing)所有的函数W号Q同时每一ơ进入一个函数时Q就?x)创Z个(f)时的局?br>W号表,用于存储局部变量;后来Qؓ(f)了支持插Ӟ插g函数被特定地保存在另一个全局W?br>可里?</font> <p><font size=2><strong>代码D</strong> </font> <p><font size=2>    kl中的W号表实C码在klsymtab.h/klsymtab.c中,实现比较单,无需多言?</font></p> <img src ="http://www.shnenglu.com/kevinlynx/aggbug/76078.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/kevinlynx/" target="_blank">Kevin Lynx</a> 2009-03-10 08:58 <a href="http://www.shnenglu.com/kevinlynx/archive/2009/03/10/76078.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>实现一U解释性脚本语aQ四Q?/title><link>http://www.shnenglu.com/kevinlynx/archive/2009/03/09/75962.html</link><dc:creator>Kevin Lynx</dc:creator><author>Kevin Lynx</author><pubDate>Mon, 09 Mar 2009 03:12:00 GMT</pubDate><guid>http://www.shnenglu.com/kevinlynx/archive/2009/03/09/75962.html</guid><wfw:comment>http://www.shnenglu.com/kevinlynx/comments/75962.html</wfw:comment><comments>http://www.shnenglu.com/kevinlynx/archive/2009/03/09/75962.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.shnenglu.com/kevinlynx/comments/commentRss/75962.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/kevinlynx/services/trackbacks/75962.html</trackback:ping><description><![CDATA[<p><font size=2>author: Kevin Lynx email: zmhn320#163.com date: 3.9.2009 </font> <p><font size=2><strong>语法分析</strong> </font> <p><font size=2>    语法分析接收词法分析阶段的token集合入,这些没有关pȝtokens整理为相?br>之间有关pȝl构。书面点的说法叫语法?wi)?br>    每一ơ让我写q些文绉l的概念真让我受不了:D?</font> <p><font size=2><strong>语法?/strong> </font> <p><font size=2>    语法?wi)简单来说就是一个以token作ؓ(f)每个节点的树(wi)型结构。例如我们有表达式age =<br>age + 1;Q在词法阶段它被整理为token集合Qage, =, age, +, 1。那么在l过语法分析?br>Q这些tokens被整理为大致如下的?wi)Şl构Q?br>        =<br>      /   \<br>    age    +<br>         /   \<br>       age     1 </font> <p><font size=2>    整理成这L(fng)l构有什么好处?kl解释器而言Q最直接的好处就是我可以递归地解?br>q棵?wi)执行。例如:(x) </font> <p><font size=2>    value compute( TreeNode *root )<br>    {<br>        /* child[0]保存l果值ageQchild[1]是那?表达?*/<br>        return op_exp( root->child[1] ); <br>    } </font> <p><font size=2>    value op_exp( TreeNode *node )<br>    {<br>        switch( node->op )<br>        {<br>            case '+':<br>            {<br>                /* + 表达式必然有左右操作?*/<br>                value left = factor( node->child[0] );<br>                value right = factor( node->child[1] );<br>                return left + right;<br>            }<br>        }<br>    }<br>    value factor( TreeNode *node )<br>    {<br>        switch( node->type )<br>        {<br>            case ID:<br>                /* 查找age的?*/<br>                return age; </font> <p><font size=2>            case CONST:<br>                /* 1 是常?*/<br>                return node->cvalue;<br>        }<br>    } </font> <p><font size=2>    如你所见,当我们完成了语法分析阶段Q我们就可以完成我们的解释器了。后面我?x)?br>独讲解下整个解释q程Q包括每个模块是如何协作的。我不知道其他解释器是怎么做的Q但<br>是我q样做,L(fng)l果是对的?</font> <p><font size=2><strong>如何整理法树(wi)Q?/strong> </font> <p><font size=2>    q里不得不提到所谓的BNF文法Q很明显你还是无法从我这里获取编译原理里某个概念<br>的讲解。我q里提这个概念完全是方便我提到这个东ѝ?br>    每一U语a都有其自qBNF文法Q因Z恶的先知告诉我们Q每一门语a都需要徏?br>其语法树(wi)? -!<br>    像词法分析一P因ؓ(f)大部分语a的结构都差不多,所以我觉得词法分析和语法分?br>基本上都没有M特别之处。也是_(d)别的语言的BNF你可以直接拿来改改用?br>    抄个BNF如下Q?br>    exp -> exp adop term | term<br>    addop -> + | -<br>    term -> term mulop factor | factor<br>    mulop -> *<br>    factor -> (exp) | number<br>    q个BNF用来描述一般的数表达?+-*/)。简单来_(d)一门语a的BNF是用于描述?br>语言所有语句的东西Q包括if、while、函数定义之cR徏议你google一下C语言的BNFQƈ<br>攚w之用于你自q语言?</font> <p><font size=2>    那么有了BNF之后Q该如何整理法树(wi)呢?<br>    通常Q我们的代码里都?x)直接有对应exp、term、addop之类的函数。按照我q句话的?br>思,上面抄的BNF被翻译ؓ(f)E序代码后,可能ؓ(f)Q?br>    exp()<br>    {<br>        if( ... ) left = exp()<br>        right = term();<br>        left addop right;<br>    }<br>    term()<br>    {<br>        if( ... ) left = term()<br>        right = factor();<br>        left mulop right;<br>    }<br>    factor()<br>    {<br>        if( ... ) return exp();<br>        else return number;<br>    } </font> <p><font size=2>    (可能q会(x)涉及(qing)到EBNFQ用于处理重复和选择的一些情?--不用这句话) </font> <p><font size=2>    每一个函数基本上都会(x)q回一个树(wi)节点Q当?dng)该节点下可能会(x)有很多子节炏V?nbsp;   </font> <p><font size=2><strong>ȝ</strong> </font> <p><font size=2>    语法分析基本上就是以上信息。它?yu)词法分析输出的token集合整理成一颗语法树(wi)。ؓ(f)<br>了整理出q棵语法?wi),你需要找一份用于描qC语言的BNFQ然后根据BNF译成处理代码?</font> <p><font size=2><strong>代码D</strong> </font> <p><font size=2>    kl中的整个语法分析代码位于klparser.c/klparser.h中,其BNF基本上取?lt;~译原理?br>实践>附录中的C_语言?/font> <p><font size=2></font></p> <img src ="http://www.shnenglu.com/kevinlynx/aggbug/75962.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/kevinlynx/" target="_blank">Kevin Lynx</a> 2009-03-09 11:12 <a href="http://www.shnenglu.com/kevinlynx/archive/2009/03/09/75962.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>实现一U解释性脚本语aQ三Q?/title><link>http://www.shnenglu.com/kevinlynx/archive/2009/03/07/75816.html</link><dc:creator>Kevin Lynx</dc:creator><author>Kevin Lynx</author><pubDate>Sat, 07 Mar 2009 05:43:00 GMT</pubDate><guid>http://www.shnenglu.com/kevinlynx/archive/2009/03/07/75816.html</guid><wfw:comment>http://www.shnenglu.com/kevinlynx/comments/75816.html</wfw:comment><comments>http://www.shnenglu.com/kevinlynx/archive/2009/03/07/75816.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.shnenglu.com/kevinlynx/comments/commentRss/75816.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/kevinlynx/services/trackbacks/75816.html</trackback:ping><description><![CDATA[<p><font size=2>author: Kevin Lynx email: zmhn320#163.com date: 3.7.2009</font> <p><font size=2><strong>词法分析</strong> </font> <p><font size=2>    词法分析属于整个~译程中的W一个阶Dc(din)ؓ(f)什么要把编译过E分为多个阶D,q就<br>如同软g分层一P个h觉得是出于降低复杂性的考虑?br>    再次声明我不?x)告诉你M~译原理的理论知识,因ؓ(f)坦率地说我也不会(x):D。所以我?br>力将我们需要了解的概念可能简单地告诉你。当?dng)可能会(x)与教科书不d?</font> <p><font size=2><strong>什么是词法分析?</strong> </font> <p><font size=2>    词法分析是把一D话整理成单词集合。D个简单的例子Q例如有代码:age = age + 1;Q?br>l过词法分析后,得刎ͼ(x)age?、age???几个W号。ؓ(f)了方便,我称每个单词Z<br>个token?</font> <p><font size=2><strong>词法分析的作?/strong> </font> <p><font size=2>    词法分析分析出来的单词集合,直接作ؓ(f)~译程中接下来的语法分析的输入。那么语<br>法分析阶D面对的是一个一个的tokenQ而不是单个的字符?br>    例如Q在处理age = age + 1;q种语句Ӟ当我们获取到token "="Ӟ我们直接期望?br>下来的token应该是个表达式。以单词为单位地处理Q比直接处理单个字符单很多?</font> <p><font size=2><strong>词法分析的过E?/strong> </font> <p><font size=2>    词法分析的输入是单个字符,一般我们fopen一个源代码文gQ保存在一个char~存<br>里,q就是词法分析的输入。而词法分析的最l输出结果就是一个一个的token?br>    Z处理方便Qtokenq不是单U的单词。通常我们?x)将源代码中的所有单词分c,?br>如变量名其实都属于一ctoken。简单的token可定义ؓ(f)Q?br>    struct Token<br>    {<br>        int type;<br>        char value[256];<br>    };<br>    type用于表示token的类型,例如一个变量名token的类型是一个标识符。value可以?br>来具体地保存q个变量的名字?</font> <p><font size=2>    对于type的处理,通常?x)事先定义一l枚丑ր|例如Q?br>    enum    {    ID, NUM, STRING, IF, ELSE, WHILE, RETURN, FUNCTION }{等用于标示<br>在一个源代码中可能出现的所有token?</font> <p><font size=2>    虽然说词法分析的l果是一个token集合Q但事实上我们ƈ不是一ơ做完词法分析。通常<br>词法分析模块提供一个get_token函数。每ơ调用该函数Ӟ都返回源代码中下一个token?br>例如Q有源代码:(x)age = age + 1;<br>    W一ơ调用get_token获?{ ID, "age" }Q第二次获得 { ASSIGN, "=" }Q第三次<br>获得{ ID, "age" }Q等{?</font> <p><font size=2>    那么Q词法分析该如何实现Q也是struct Token get_token()函数如何实现Q其实很<br>单,你告诉我Q给你一个字W串Q你如何判断q个字符串全部是数字Q?br>    int is_num( const char *str )<br>    {<br>        while( *str != 0 ) <br>        {<br>            if( !isdigit( *str++ ) ) return 0;<br>        }<br>        return 1;<br>    }<br>    所以,基本上,词法分析的过E也是q个q程。就拿标识符举例Q典型的标识W一?br>以字W开_(d)然后接着是数字或字符或_Q当遇到非法字符Ӟq个标识W的扫描即结束?br>    词法分析一般是个while+switchQ?br>    struct Token get_token()<br>    {<br>        while( current_char != 0 )<br>        {<br>            switch( current_char )<br>            {<br>                case CHARACTER:<br>                    /* 扫描一个标识符 token */<br>                    break; </font> <p><font size=2>                case '=':<br>                    /* 获得一?ASSIGN token */<br>                    break; </font> <p><font size=2>                    ...<br>            }<br>        }<br>    } </font> <p><font size=2>    现在Q试着Lȝ一门语a里的每一个token的规则,然后自己d写看?</font> <p><font size=2><strong>代码D</strong> </font> <p><font size=2>    在本节我提供kl在googlecode的SVN上的代码Q先不要ȝ代码包中的其他东ѝ关?br>词法的代码可以在kllex.c kllex.h中找到。lex_token是提供给其他模块的接口,用于获取<br>当前扫描的token。扫描结果可以通过lexStatel构体获取?br>    再次提下版权问题Q代码文件以?qing)代码包中我q没有加入Q何版权说明,哪怕是GPL?br>但是如同我之前说的一P我不介意你传播、改动此代码Q但是请保留原作者信息。当?dng)?br>我ƈ不介意你加上@modified by xxx:)?</font> <p><font size=2>    下蝲kl源代码:(x)</font><a ><font size=2>http://klcommon.googlecode.com/files/kllan_0.1.0.zip</font></a></p> <img src ="http://www.shnenglu.com/kevinlynx/aggbug/75816.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/kevinlynx/" target="_blank">Kevin Lynx</a> 2009-03-07 13:43 <a href="http://www.shnenglu.com/kevinlynx/archive/2009/03/07/75816.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>实现一U解释性脚本语aQ二Q?/title><link>http://www.shnenglu.com/kevinlynx/archive/2009/03/06/75751.html</link><dc:creator>Kevin Lynx</dc:creator><author>Kevin Lynx</author><pubDate>Fri, 06 Mar 2009 08:01:00 GMT</pubDate><guid>http://www.shnenglu.com/kevinlynx/archive/2009/03/06/75751.html</guid><wfw:comment>http://www.shnenglu.com/kevinlynx/comments/75751.html</wfw:comment><comments>http://www.shnenglu.com/kevinlynx/archive/2009/03/06/75751.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.shnenglu.com/kevinlynx/comments/commentRss/75751.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/kevinlynx/services/trackbacks/75751.html</trackback:ping><description><![CDATA[<p><font size=2>author: Kevin Lynx email: zmhn320#163.com date: 3.6.2009 </font> <p><font size=2><strong>语言Ҏ(gu)?/strong> </font> <p><font size=2>    在正式讨论实现细节前明确下这个脚本语a的一些语aҎ(gu),基本上可以让我们预见?br>来会(x)遇到哪些N。ȝ来说Q它Q脚本)(j)同我们qx接触的如lua一L(fng)脚本语言Q拥<br>有一般的~程语言Ҏ(gu),如变量、各U控制流E、也许还有函敎ͼ另一斚w它还应该和它?br>宿主语言l合Q如作ؓ(f)一个库被用qCQ这q涉?qing)到l这门语a设计一U插件方式,最好能<br>通过独立的解释程序让脚本载入一些插件运行?</font> <p><font size=2>    以下在描q我写的q个脚本语言Ӟ以kl表示它的名字Q以方便描述?</font> <p><font size=2><strong>代码块:(x)</strong> </font> <p><font size=2>    首先从整体风gQkl如同C语言一栯划分为函数块Q如Q?br>    function func1()<br>    {<br>    }<br>    function func2()<br>    {<br>    }<br>    ...<br>    kl支持以{}隔离代码块,但是qƈ不意味着kl有多个独立的局部堆栈,如同C语言一栗?br>q些l节暂不讨论。本节描q的所有内容你都不必深IӞ因ؓ(f)我只要求你对kl有个感性上?br>认识?br>    函数块之外没有可执行的语?statement)。那么你可能?x)想到程序的入口点也怼(x)?br>main。事实上从kl提供的库来看Qƈ没有q种性要求。但是,kl的独立解释程序是q样?br>求的?nbsp;   </font> <p><font size=2><strong>变量Q?/strong> </font> <p><font size=2>    kl允许你在M地方使用一个变量。变量不需要事先定义,M地方出现一个合<br>法的标识W时Q就意味着kl内部?x)增加这个变量,q给予初倹{变量也没有静态类型,也不<br>?x)固定?f)某一cd。就一门最单的语言来看Q我觉得数据cd无非是字符串和数字cd<br>?br>    所以,kl的变量在某一时刻必然是数字,或者字W串。在脚本里,你无法获知一个变?br>的类型,事实上也没这个必要。说变量拥有一个类型属性,倒不如说?value)有一U类?br>属性?br>    当字W串g数字值参与运时Q如1+"a"Q其q算l果自动{换ؓ(f)字符Ԍ也就?br>"1a"?br>    一个只有标识符的语?statement)通常意味着你想定义一个变量。这U无聊的手段?br>常被用于定义全局变量?</font> <p><font size=2><strong>q算W:(x)</strong> </font> <p><font size=2>    kl支持一般的C语言风格的算术、比较、逻辑q算W。例如加减乘除、大于小于、逻辑<br>与逻辑或?</font> <p><font size=2><strong>作用域:(x)</strong> </font> <p><font size=2>    kl脚本里只有两个作用域Q全局的和局部的?br>    位于所有函数块外的变量处于全局作用域;位于函数内的变量处于局部作用域Q位于函<br>数块内的代码块变量,q是处于局部作用域?br>    当局部作用域内出C个全局里的同名变量Ӟ优先取局部作用域里的变量。这同C?br>a一栗?</font> <p><font size=2><strong>控制语句ifQ?br></strong>    if的语法同C语言一P如:(x)<br>    if( a > 10 )<br>    {<br>    }<br>    else<br>    {<br>    }<br>    if( a > 10 )中的a>10被我成ؓ(f)条g语句Q所有条件语句,包括下面的whileQ都不能<br>为字W串。例如if( "a" )被视ؓ(f)非法语句。(我ؓ(f)什么要q样考虑Q? -!Q?</font> <p><font size=2><strong>控制语句while:</strong> </font> <p><font size=2>    c-like while:<br>    while( a > 10 )<br>    {<br>    }<br>    很遗憾,我暂时没有加入对for的支持。因为我觉得既然有了whileQ有了@环控Ӟ?br>没有更多无聊旉的前提下Q我没有必要加入for?</font> <p><font size=2><strong>函数Q?/strong> </font> <p><font size=2>    很遗憾,函数的定义和调用和C语言有点不一栗这是因为kl没有变量cdQ那意?br>着函数定义如果和C语言一P׃(x)出现语法歧义Q如Q?br>    func( a )<br>    {<br>    }<br>    ׃(x)和函数调用func(a)出现h。所以,我加入了function关键字。定义函数的语法<br>为:(x)<br>    function func( a, b )<br>    {<br>    }<br>    如你所见,函数支持参数传递,当然也支持return a;q回倹{kl是简陋的Q因为它?br>有指针之cȝ概念Q所以你无法为函C递一块数据。当?dng)kl也不能像lua一栯函数?br>以返回多个倹{?br>    函数调用的语法相对熟(zhn):(x)<br>    func( 1, 3 ); </font> <p><font size=2><strong>数组Q?/strong> </font> <p><font size=2>    从一开始我没考虑为kl加入数组。事实证明加入数l是一个不明智的做法。数l的?br>持让代码在很多地方变得脏乱。无论如何,kl后来支持一l数l了。ؓ(f)了让代码保持那么一<br>点点的干净Q我甚至为定义数l加入dim的关键字。这意味着Q在kl里,数组和一般的变量<br>L点不一P(x)变量无需定义Q数l却必须事先定义?br>    数组的长度不支持动态扩充。如果支持,我得让kl内部更好地去理内存?br>    数组元素的类型没有硬性的规定Q这意味着a[0] = 1; a[1] = "a";是允许的?</font> <p><font size=2>    语言Ҏ(gu)上描q这些,在本节末我军_贴一Dkl计算阶乘的代码:(x) </font> <p><font size=2>/* fac.kl */<br>function main()<br>{<br>    n = input( "%d" );<br>    print( "fac(" + n + ") = " + fac( n ) );<br>} </font> <p><font size=2>function fac( n )<br>{<br>    if( n == 1 )<br>    {<br>        return 1;<br>    }<br>    else<br>    {<br>        return fac( n - 1 ) * n;<br>    }<br>} </font></p> <img src ="http://www.shnenglu.com/kevinlynx/aggbug/75751.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/kevinlynx/" target="_blank">Kevin Lynx</a> 2009-03-06 16:01 <a href="http://www.shnenglu.com/kevinlynx/archive/2009/03/06/75751.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>实现一U解释性脚本语aQ一Q?/title><link>http://www.shnenglu.com/kevinlynx/archive/2009/03/06/75749.html</link><dc:creator>Kevin Lynx</dc:creator><author>Kevin Lynx</author><pubDate>Fri, 06 Mar 2009 07:58:00 GMT</pubDate><guid>http://www.shnenglu.com/kevinlynx/archive/2009/03/06/75749.html</guid><wfw:comment>http://www.shnenglu.com/kevinlynx/comments/75749.html</wfw:comment><comments>http://www.shnenglu.com/kevinlynx/archive/2009/03/06/75749.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.shnenglu.com/kevinlynx/comments/commentRss/75749.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/kevinlynx/services/trackbacks/75749.html</trackback:ping><description><![CDATA[<p><font size=2>author: Kevin Lynx email: zmhn320#163.com date: 3.6.2009 </font> <p><font size=2>    Q相信我Q这一节全是废话。)(j)<br>    我不是标题党Q但是有必要解释下这个标题。综合来说我是想与你分享我所学到的?br>我会(x)我实现的这个简单的脚本语言的实现细节展C给你。它?yu)涵盖?x)词法分析、语法分?br>、符可理、语法树(wi)解释执行、插件管理等内容?br>    我ƈ不擅长传授编译原理知识。我没有听过~译原理课,所以我也不?x)编译原理(也?br>即我听了也不会(x):DQ。所以对于这斚w的能手而言Q我口中?#8216;DFA‘可能?x)贻W大斏V?br>    昄QCPPBLOG上有~译原理上的大牛。如果你惛_?fn)更深入的知识,可以去请教他们?br>vczh(http://www.shnenglu.com/vczh/) 看v来是我所说的q个人。在致谢名单里我真诚地<br>写上他的名字。他?#8217;手把手xxx脚本‘pd多多少q是l了我一些有用的信息?br>    其次是FOXQ在词法分析的DFA和NFA那里我请教了他一些问题。虽然我现在又忘了。如<br>你们所知,理论和实C间M(x)隔着鸿沟?</font> <p><font size=2>    推荐《编译原理与实践?<Compiler Construction:Principles and Practice><br>Kenneth C. Louden)q本书。在你将来阅L的脚本语a的实C码时Q你?x)发现有很一些地<br>方同q本书里的TINY语言实现代码有相g处。徏议你阅读TINY的代码?br>    感谢VIM、GCC、GDB、MingWQ我用这些Y件在工作之余写出了这个东西的几千行C代码?br>很明显我是个开源文化的爱好者。但是我不会(x)告诉你unix有多么多么好Q因为我也是个初?br>者,我还不懂unix。开源在我看来更是一U分享知识的_。让q种_如同GPL一L(fng)?br>式地传染下去?br>    q有版权问题。但也许它不是个问题。我不会(x)dM版权信息。我允许你Q意传播?br>改动我所散播的东西,但是唯一的基本条件是Q保留作者的信息---不要告诉别hQ这东西<br>是你做的?</font> <p><font size=2>    在所有的文章发布后,我都可能?x)再ơ修攏V也?dng)R过RSS或者日志日期之cM可以?br>得修Ҏ(gu)醒?</font> <p><font size=2></font></p> <img src ="http://www.shnenglu.com/kevinlynx/aggbug/75749.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/kevinlynx/" target="_blank">Kevin Lynx</a> 2009-03-06 15:58 <a href="http://www.shnenglu.com/kevinlynx/archive/2009/03/06/75749.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <p>лǵվܻԴȤ</p> <a href="http://www.shnenglu.com/" title="精品视频久久久久">精品视频久久久久</a> <div class="friend-links"> </div> </div> </footer> <a href="http://www.xuwonline.cn" target="_blank">ҹƷþþþþӰ777</a>| <a href="http://www.lenovophone.com.cn" target="_blank">þۺϹ׾Ʒ</a>| <a href="http://www.vulm.cn" target="_blank">þۺϾþþ</a>| <a href="http://www.foundxy.cn" target="_blank">˾Ʒһþþ</a>| <a href="http://www.pic789.cn" target="_blank">þ99þóѲ</a>| <a href="http://www.usgold.cn" target="_blank">޾Ʒ97þĻ</a>| <a href="http://www.gxysbl.cn" target="_blank">޾ƷþþþþͼƬ </a>| <a href="http://www.zjhongfeng.cn" target="_blank">þܳ</a>| <a href="http://www.iview-inc.com.cn" target="_blank">һþƵ</a>| <a href="http://www.xiazb.cn" target="_blank">˾þü91</a>| <a href="http://www.68admin.cn" target="_blank">ɫۺϾžþ</a>| <a href="http://www.softplat.cn" target="_blank">þþþþùƷ볬</a>| <a href="http://www.3djeans.cn" target="_blank">þþùҺ</a>| <a href="http://www.ddmir.cn" target="_blank">þþþĻƷ</a>| <a href="http://www.rz2.com.cn" target="_blank">ۺϾþþƷ</a>| <a href="http://www.jacctv.cn" target="_blank">޺ݺۺϾþ</a>| <a href="http://www.wthangjia.cn" target="_blank">˾þվ</a>| <a href="http://www.sbznw.cn" target="_blank">һAëƬѹۿþþƷ</a>| <a href="http://www.yczu.cn" target="_blank">þAëƬѹۿ</a>| <a href="http://www.16pk8.cn" target="_blank">þþþĻɫ </a>| <a href="http://www.woaisheying.cn" target="_blank">ձ޿һþ</a>| <a href="http://www.zhaoziping.cn" target="_blank">þ޾ƷĻ</a>| <a href="http://www.fcsyx.cn" target="_blank">ŷþþþþ</a>| <a href="http://www.todouba.cn" target="_blank">޹˾Ʒ91þþ </a>| <a href="http://www.0553fc.cn" target="_blank">þþþƷձһ</a>| <a href="http://www.1rizu.cn" target="_blank">2021ƷۺϾþ</a>| <a href="http://www.jianzhuhr.net.cn" target="_blank">þˬˬƬAV</a>| <a href="http://www.tianit.cn" target="_blank">þ99þóѲ</a>| <a href="http://www.hetiandai.cn" target="_blank">ƷþþþӰԺ۲</a>| <a href="http://www.hzskc.cn" target="_blank">Ʒþҹҹ³³</a>| <a href="http://www.iido.org.cn" target="_blank">þˬˬƬAV</a>| <a href="http://www.uyfw.cn" target="_blank">ȾþùŷһƷ</a>| <a href="http://www.swd5.cn" target="_blank">þù˾Ʒ</a>| <a href="http://www.kukuoo.cn" target="_blank">þСƵ</a>| <a href="http://www.cnwowshell.cn" target="_blank">99þۺϹƷ</a>| <a href="http://www.jusunglabel.com.cn" target="_blank">þ91˳ɵӰվ</a>| <a href="http://www.mljy168.cn" target="_blank">þ99Ʒ99þ</a>| <a href="http://www.officene.com.cn" target="_blank">þþƷҹһ</a>| <a href="http://www.xibu520.cn" target="_blank">ƷþþþþӰԺ</a>| <a href="http://www.iningyu.cn" target="_blank">ŷƷһƷþ</a>| <a href="http://www.yonganwl.cn" target="_blank">99þþƷѿ</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>