Stanford CS1 Compilers PA2J notes

【题记·碎碎念】html

斯坦福这门Compilers本来放在Coursera上,当年错过档期非常惋惜,后来发现他们本身的MOOC站放了一个self paced版本,真是普大喜奔,趁着放假有空学学。java

这门课的份量能够很轻,亦可很重。self-paced版本若是你只是看看视频,作作quiz,那么很简单,根据课程介绍,一个星期3小时就够了;而若是你要作programming assignments,老师给“有经验的”程序员预估6-10个小时/周的工做量。其实Coursera版写的是8-10 hours/week, 10-20 hours/week with PA,我的认为Coursera估得更准确。程序员

前两周学完,个人感觉是这门课若是不作编程做业,倒不如不学。作做业的过程既痛苦又兴奋,self-pace的一个最大问题是几乎没有进度差很少的同窗来一块儿讨论,论坛上的信息也是零零散散,并且Edx平台的论坛比Coursera的论坛体验差太多了,所以查资料时新建浏览器标签开到电脑接近崩溃是常有的事情。web

花了大把时间查的资料作完此次做业对我来讲就没什么用了,想一想很惋惜,那么仍是记下来给将来同窗一个参考,我相信会有必定帮助。我在作做业的时候,也许是刚开始不适应的关系,一会儿接触太多新概念有点overwhelming,花了两天时间看handout和Other Project Resources里的资料,我仍是不明白第一次PA要作什么、怎么作,简直无从下手。正则表达式

 

【上面都是废话,正题此处开始】:编程

我直接用老师提供的虚拟机,因此没有搭环境的环节。浏览器

第一周没有PA要提交,虚拟机下的PA1目录里有些示例程序,就让你走一走一下课程所使用的Cool语言的编译、运行流程。app

从第二周开始有做业,须要提交的PA1实际在~/cool/assignments/PA2或PA2J目录里,其中PA2是C++版本,PA2J是Java版。ide

第一次做业是作一个词法分析器,lexical analyzer, also called a scanner。这实际上是一件很琐碎的工做,而核心工做很单一:定义规则把源代码tokenize掉,因此大牛们作了一些工具来方便帮助你处理杂事,你能够专心写规则。函数

lexical analyzer generator的元总是lex,后来在其基础上发展出flex/jlex,分别对应C++和Java,(后来貌似又来了个jflex - -,这帮大佬起名字感受是存心要绕死你)。

我选择了Java路线,官方资料能够在这里找到,这份文档必读

Jlex是一个辅助工具,你按照必定格式定义好规则,而后Jlex将你定义的规则转换为程序,这个自动生成的程序就是你的词法分析器,你把源代码喂给它,它就吐出一个一个的token,告诉你这个是关键字那个是标识符。

规则写在一个叫cool.lex的文本文件里,乍看上去格式很复杂,由于它竟然还分四个区域,还带有各类稀奇古怪的形如%line的参数,细看其实不难,由于你的主要工做所有在"Rules"区完成,而后根据你的实现方式差别,你有可能须要在"Declarations"加上你的类/函数定义,能够在"Rules"区调用,而后在"Definitions"定义几个状态/正则别名。

 

所谓规则,其实就是正则表达式了,这东西若是以前历来没用过也不用怕,由于Jlex的正则语法很简单。PA2要作的事就是用正则匹配Cool程序源码里各个不一样的元素,而后处理成下一阶段须要的格式。在开始作做业以前,能够看看这个例子,你未来要实现的东西差很少就长这样。

任务不难,难的是熟悉这个操做环境,还有老师给你写好的一大堆辅助类(暂时用不上几个),再加上handout有些地方实在写得语焉不详:看了两遍,只输了一条命令

make -f /usr/class/cs143/assignments/PA2J/Makefile

而后就抓瞎了,大脑直接idle了;cool.lex里的例子有注释等于没有,看不懂,一开始根本不知道怎么下手,连看资料都不知道从哪里看起。

好在有Google和Github两个神器,我直接找到了别人写好的答案……说实话,当时我有点想偷懒直接抄,反正此次PA的核心就是写一写正则表达式,原理懂了差很少得了,代码一粘一贴,分数到手,多好,可是……

嗯……满分63分只拿了9分……

好吧,仍是得本身动手。

 

不过既然有了分数,说明它的输入输出确定是好的,这其实才是咱们新手最棘手的问题啊,ok,仔细看来:

1 <YYINITIAL>";"          { return new Symbol(TokenConstants.SEMI);  }

这是其中的一条规则,意思是在"YYINITIAL"这个状态下,若是遇到";"这个符号输入,那么就输出一个Symbol对象,{}保存你的处理策略。目测这个对象的constructor接受一个SEMI常量,跑到TokenConstants.java里面看了一下,这些常量都是int,形如

public static final int MULT = 27;

知道这个就很好办了,其余的规则都照葫芦画瓢,无非正则表达式复杂一点,有些状况换个类,加个参数。

在给Jlex的特别说明里(handout page 6)他写了,(编号是我加的):

1) The value returned by the
method CoolLexer.next token is an object of class java cup.runtime.Symbol. This object has
a field representing the syntactic category of a token. The syntactic codes for all tokens are defined in the file TokenConstants.java.

2) The component,
the semantic value or lexeme (if any), is also placed in a java cup.runtime.Symbol object

3) class identifiers, object identifiers, integers, and strings, the semantic value should be of type AbstractSymbol

(注意AbstractSymbol是个抽象类,你未来要用它的子类:IdSymbolIntSymbolStringSymbol,class identifiers, object identifiers要用IdSymbol,integer用IntSymbol,string用StringSymbol。文档在这里

其实就是告诉你,像上面那个例子同样,你的规则匹配中以后,要return一个Symbol对象,这个Symbol包含一个field表明你匹配中的token的分类或名字id,都在TokenConstants.java里定义好了,去找就是;另一个field是semantic value,也要用Symbol来表示,可是对于3)里的这些token,semantic value要用AbstractSymbol类。注意Symbol和AbstractSymbol没有关系,甚至不在同一个包里,看文档就知道了。如今这些东西的关系不是很清楚无所谓,但再日后PA3等可能就要用到。

 

这一大段估计能够把人绕晕。反正我在搜到那个9分答案以前彻底不理解它想说什么,代码其实很简单,若是token类型是identifier,那么就这样:

IdSymbol dummy = new IdSymbol(yytext(), yytext().length(), 0);
return new Symbol(TokenConstants.TYPEID, dummy);

也有这样作的(换一种Symbol类型,相似的套路)

IntTable table = new IntTable();
return new Symbol(TokenConstants.INT_CONST, table.addString(yytext()));

理由是IntTable.addString返回值就是一个IntSymbol。这些table在lexical analysis阶段暂时不用,因此能够弄些dummy值,constructor缺什么就给它喂什么,简单粗暴。

 

对了,状态有必要多说一句。在"directives"区域,你能够定义状态。语法如

%state COMMENT

进入注释之后,你就使用yybegin(COMMENT)进行状态转换,转换完以后能够用

<COMMENT>... {...}

这样的方式使用状态,表示在这种状态下才匹配这条规则,出注释切记要用yybegin(YYINITIAL)把状态转回来。另外在一条规则里,状态不是必须的,能够忽略,至关于任意状态都适用此规则。

YYINITIAL是Jlex隐含定义的常量,若是在lexer的整个运行过程当中你没有进行过状态转换,那么全程都处于YYINITIAL状态下,详见Jlex文档第2.2.5节

对了还有,yytext()表示被当前规则匹配中的、预处理过的文本,能够用简单粗暴的方式查看...

System.err.println("processing: "+yytext());

 

这些例子举出来,这个做业能够被视为完成一半了,剩下的就是对照Cool_manual一个一个写规则。哪一个TokenConstants对应哪一个符号,我没有找到文档,你要是找到了请告诉我,不过从名字看并不难对应,查查字典多试一试吧。

固然有一些正则仍是得花点时间动点脑筋的,必要的时候还须要写辅助类来处理字符串。

我在backslash上花费了较多时间,最后才经过的测试是"weirdcharcomment.cool",corner case无穷尽呐,更多的时候是按住葫芦起了瓢。

另外这个PDF可能会给一些启发。

最后晒一下分

相关文章
相关标签/搜索