\documentclass[12pt,a4paper]{article} \usepackage{fontspec, xunicode, xltxtra} \usepackage{xeCJK} \usepackage{amsmath} \usepackage{listings} \usepackage{multirow} \newfontfamily\courier{Courier} \lstset{ numbers=left, % where to put the line-numbers numberstyle=\tiny \courier, % the style that is used for the line-numbers basicstyle=\courier, numbersep=2em, % how far the line-numbers are from the code breaklines=true, % sets automatic line breaking breakatwhitespace=false, % sets if automatic breaks should only happen at whitespace } \setCJKmainfont[BoldFont={Adobe Heiti Std R}, ItalicFont={Adobe Kaiti Std}]{Adobe Song Std L} \setCJKmonofont{Courier} \title{编译原理PA1作业报告} \author{黄家晖 2014011330} \date{} \begin{document} \maketitle PA1的要求是修改原有编译器的框架,为编译器增加新的语法特性,最终输出正确的抽象语法分析树。 本次的作业涉及到了框架代码的阅读和JFlex/byacc工具的使用,整体较为简单。 \section{新增加的数据结构和函数} \begin{enumerate} \item 在Tree中增加Ternary语法节点,代表三元运算符,实现condition expression的功能,包含三个子节点:left、middle和right。 \item 在Tree中修改Binary语法节点,加入\texttt{<<}二元运算符,与其他二元运算符并列。 \item 在Tree中增加Case语法节点,代表\texttt{switch}语法块中的一个\texttt{case}语句,其中包含了一个Expr节点(代表\texttt{case}之后的常量)以及一些Tree节点(代表目标命中之后执行的语句列表)。 \item 在Tree中增加Switch语法节点,代表整个\texttt{switch}语句块,其中包含了一些Case语法节点以及一些Tree节点(代表\texttt{default}情况下需要执行的语句列表)。 \item 在Tree中增加Repeat语法节点,代表\texttt{repeat...until}语句块,其子节点包括了一个Expr节点(代表\texttt{until}之后的逻辑语句)和一些Tree节点(代表repeat之后需要执行的语句列表)。这里需要注意repeat的规则与C和JAVA的风格不太一致,根据PA1给出的参考语法,reapeat之后可以是不加大括号的连续语句,这与if是不同的。 \item 在Tree中增加Continue语法节点,实现同Break语法节点,是叶子节点。 \item 修改了SemValue语义值类,添加了成员变量\texttt{caselist}和\texttt{casedef},为了实现Lexer和Parser的交互添加了一些临时变量,用于存储case语句。 \item 为Tree和SemValue增加相应的\texttt{visit()}和\texttt{toString()}函数,使得程序风格统一,使用diagnose调试时更方便。 \end{enumerate} \section{遇到的问题和解决方法} 实现三元操作符\texttt{?:}的时候,在简单添加了parser生成式之后,byacc报告Shift/Reduce冲突,同时程序不能够正确识别形如\texttt{a?b:c?d:e}的表达式。为此,需要告知byacc三元表达式的右结合性,具体来说需要在适当位置加入\texttt{\%right ':' '?'}语句。 为了更清楚地了解byacc解决Shift(入栈)/Reduce(规约)冲突的办法,我在网上进行了相关搜索: http://stackoverflow.com/questions/17904706/why-does-my-ternary-operator-cause-a-shift-reduce-conflict 上述网站中清楚地阐明了解决冲突的办法: 即当找到符合条件的产生式之后,为了确定是否进行规约,需要比较产生式和下一个符号的优先级,而产生式的优先级与产生式右端的最后一个终结符相同,当定义\%left或是\%right之后(部分情况针对特定表达式需要加入\%prec),实际上就能根据结合性和定义位置确定每个产生式和终结符的优先级,冲突得以解决。 \end{document}