-
今天我们来继续上次的话题,聊一聊C语言词法中的constant:
constant:
floating-point-constant
integer-constant
enumeration-constant
character-constant我们看到C语言中有四种constant,分别是浮点数常量,整数常量,枚举常量和字符常量。我们今天先来讲浮点数常量:
floating-point-constant:
fractional-constant exponent-part opt floating-suffix opt
digit-sequence exponent-part floating-suffix opt
fractional-constant:
digit-sequence opt . digit-sequence
digit-sequence .
exponent-part:
e sign opt digit-sequence
E sign opt digit-sequence
sign: one of
+ -
floating-suffix: one of
f l F L
digit-sequence:
digit
digit-sequence digitflex里面我们可以用下面的正则表达式来描述这些词法:
floating-point-constant ({fractional-constant}{exponent-part}?{floating-suffix}?) |
({digit-sequence}{exponent-part}{floating-suffix}?)
fractional-constant ({digit-sequence}?"."{digit-sequence})|({digit-sequence}".")
exponent-part [eE]{sign}?{digit-sequence}
sign [+-]
floating-suffix [flFL]
digit-sequence {digit}+看上去很复杂,其实很简单,和上面的词法是一一对应的。
注:
1、词法中的opt意思是optional,指前面的元素允许出现0次或1次,在正则表达式中等同于?的含义。
2、浮点数常量可以没有整数部分,只有小数点和小数部分;也可以只有整数部分和小数点,没有小数部分。
3、为了便于阅读,我把floating-point-constant的正则表达式拆成了两行。
4、不知道什么是digit,请看上篇:C语言词法分析 二。 -
上一篇我们讲了keyword,在词法分析中,keyword是比较简单的部分,copy & paste就可以了。这一篇我们来讲identifier(标识符):
identifier:
nondigit
identifier nondigit
identifier digitnondigit: one of
_ a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Zdigit: one of
0 1 2 3 4 5 6 7 8 9换言之,标识符是以字符或下划线开头,后跟字符,数字或下划线的标记。在flex中这样定义:
identifier {nondigit}({nondigit}|{digit})*
nondigit [_a-zA-Z]
digit [0-9]%%
{identifier} return IDENTIFIER;
%%在flex中,我们用正则表达式来表示词法。
======================================
由于typedef的存在,有时我们可能需要从identifier中派生出typename来。GNU C就是这么实现的。
-
俗话说,有梦想谁都了不起,我的梦想是写一个编译器。这一篇来讲C语言词法分析。
词法分析器的任务,就是给语法分析器提供token。在编译原理中,token是指:
Any nonreducible textual element in data that is being parsed. For example, the use in a program of a variable name, a reserved word, or an operator. Storing tokens as short codes shortens program files and speeds execution.
中文翻译为:标记。参见 微软术语
C语言词法如下:
token:
keyword
identifier
constant
string-literal
operator
punctuator什么是keyword呢?
keyword: one of
auto break case char const continue default do double else enum extern float for goto if int long register return short signed sizeof static struct switch typedef union unsigned void volatile while对于每一个C语言的keyword,我们都需要返回一个唯一的token。这点和其他的元素不同。
我用lex (flex)开发,所以实际代码应该是:%%
auto return AUTO;
break return BREAK;
case return CASE;
char return CHAR;
const return CONST;
continue return CONTINUE;
default return DEFAULT;
do return DO;
double return DOUBLE;
else return ELSE;
enum return ENUM;
extern return EXTERN;
float return FLOAT;
for return FOR;
goto return GOTO;
if return IF;
int return INT;
long return LONG;
register return REGISTER;
return return RETURN;
short return SHORT;
signed return SIGNED;
sizeof return SIZEOF;
static return STATIC;
struct return STRUCT;
switch return SWITCH;
typedef return TYPEDEF;
union return UNION;
unsigned return UNSIGNED;
void return VOID;
volatile return VOLATILE;
while return WHILE;
%%限于篇幅,就先写到这里,后面几篇中我会介绍其他的一些token。
-
2008-12-21
打造Linux下的跨平台集成开发环境 - [IT科技]
在我用过的所有集成开发环境中,我个人认为:Visual Studio不一定是最好的,但是是最好用的。哎~~叹息一下Borland之塔的倒掉。
在Linux环境下,就不同了。Visual Studio不用想了,地球人都知道是不可能的事。好用的只有Anjuta,KDevelop和Code::Blocks。本人偏爱Gnome,所以KDevelop排除。Anjuta很久很久以前用过,很好用,但是搭配的是GTK。要跨平台开发,非Code::Blocks+wxWidgets莫属。
今天我们就来看看怎样用Code::Blocks和wxWidgets打造Linux下的跨平台集成开发环境。
硬件环境:联想T61,英特尔酷睿2双核64位CPU T7300,4GB内存
软件环境:Ubuntu 8.04.1 LTS安装步骤:
1、俗话说兵马未动,粮草先行,我们先把编译环境,C库,C++库和传说中巨牛逼的Boost库装好,如下:sudo apt-get install build-essential libc6 libc6-dbg libc6-dev glibc-doc libstdc++6 libstdc++6-4.2-dbg libstdc++6-4.2-dev libstdc++6-4.2-doc libboost*
2、最新版的Code::Blocks包括一个调试组件Valgrind,用来探测内存泄露的:
sudo apt-get install valgrind
3、然后我们来添加Code::Blocks最新版和wxWidgets的安装源:
安装公钥:
wget -q http://apt.wxwidgets.org/key.asc -O- | sudo apt-key add -
wget -q http://lgp203.free.fr/public.key -O- | sudo apt-key add -修改软件源配置文件:
sudo gedit /etc/apt/sources.list
在末尾加上软件源:
deb http://apt.wxwidgets.org/ hardy-wx main
deb-src http://apt.wxwidgets.org/ hardy-wx main
deb http://lgp203.free.fr/ubuntu/ hardy universe
deb-src http://lgp203.free.fr/ubuntu/ hardy universe然后存盘,退出gedit。
4、更新软件源:
sudo apt-get update
5、安装Code::Blocks最新版和wxWidgets:
sudo apt-get install libwxbase2.8-0 libwxbase2.8-dbg libwxbase2.8-dev libwxgtk2.8-0 libwxgtk2.8-dbg libwxgtk2.8-dev wx2.8-doc wx2.8-examples wx2.8-headers wx2.8-i18n wx-common
sudo apt-get install codeblocks codeblocks-contrib libcodeblocks0 libwxsmithlib06、如果你有心研究wxWidgets架构,可以下载wxWidgets的源代码,各种平台都有哦:
sudo apt-get source wxwidgets2.8
然后我们就可以开始使用Code::Blocks了,应用程序->编程->Code::Blocks IDE。
Code::Blocks和wxWidgets整合非常好,几乎不用做任何额外的配置。 -
2008-12-20
Blogbus导出日志的XML文件格式分析 - [IT科技]
Blogbus有一个很不错的功能“导出日志”,该功能可以将你所有的博客文章导出为XML格式以便备份和编辑。今天我们就来讲一讲导出日志的XML文件格式。
首先我们把自己的博客导出,步骤如下:
1、登录blogbus
2、选择博客->博客设置->导入导出->点这里导出日志
3、保存XML文件然后我们就可以分析XML文件格式了,用IE,Firefox或Visual Studio将备份文件打开,便可以看到它的结构:
<BlogBusCom dtype="BlogData" SchemaVersion="1.1" Creator="BlogBus.Com BlogSystem V4.0">
// 导出文件的数据类型,版本和出处
<Description> // 博客描述
<BlogName>博客名称,例如:孙楠的技术讲堂</BlogName>
<DomainName>博客地址,例如:sunnantechnology.blogbus.com</DomainName>
<ExportTime>导出的时间,格式为:2008-12-20 15:43:26</ExportTime>
</Description> // 描述结束
<Log> // 博客日志
<Title>日志标题,例如:Blogbus导出日志的XML文件格式分析</Title>
<Status>日志状态,控制隐藏和置顶,隐藏为0,正常为1,置顶为2</Status>
<AllowComment>评论,Y为允许,N为不允许</AllowComment>
<AllowPing>引用,Y为允许,N为不允许</AllowPing>
<AllowLinks>自动链接,Y为允许,N为不允许</AllowLinks>
<Writer>作者姓名,可以为空</Writer>
<Sort>分类,为什么用Sort,Catalog不是更好?</Sort>
<Content>日志内容,包括html格式</Content>
<Excerpt>日志摘要,包括html格式</Excerpt>
<Tags>关键词,关键词之间用空格分隔</Tags>
<LogDate>日志时间,格式为:2008-04-17 13:40:00</LogDate>
<Comments> // 这个标记做什么用?可以省略吗?
<Comment> // 博客评论
<Email>评论者的邮件地址</Email>
<HomePage>评论者的主页地址</HomePage>
<CreateTime>评论时间,格式为:2008-12-19 21:45:48</CreateTime>
<NiceName>评论者的姓名</NiceName>
<CommentText>评论的内容和回复,无html格式</CommentText>
</Comment> // 评论结束
<Comment>...</Comment> // 更多评论
</Comments> // 这个标记做什么用?可以省略吗?
</Log> // 日志结束
<Log>...</Log> // 更多日志
</BlogBusCom> // 导出文件结束
Blogbus的XML导出文件结构简单清晰,易读易维护,设计得不错。但是关于<Comments></Comments>这个标记,真的需要吗?1、首先不可能是排序用,日志和评论都以时间排序,而时间都已经有了相应的标记
2、如果是要把评论按照每篇日志分开,似乎也没有必要,毕竟每个<Comment></Comment>都在<Log></Log>里面思来想去,我感觉比较可能的作用是,在批量处理评论的操作中,可以节省时间。操作数可以从评论条数,减少到日志条数。但是从算法来说,都是O(n),真正效果如何,就要实测了。
另外:
1、日志的顺序可能与博客上看到的顺序不同,但是不会影响导入后的结果。这是由XML的特性决定的。
2、有了XML可以批量删除不必要的html标记,比如将> <批量替换为><,也可以把搬家时丢失的评论加进去,当然最重要的功能还是存档啦。







