CS143 PA3 语法分析器

PA3 Parser

PA3要求我们实现语法分析器。

所需要的文法已经在cool-manual中第10节下面的图片中给出了,我们只需要根据这个写出相应的代码即可,了解一下bison语法以及如何在代码中创建节点就可以开始了。

得分:

下面是一些我在做的过程中遇到的需要注意的地方:

  • 这个bison了解一下基本的语法就可以了,不用面面俱到,bison文档很长,在读bison文档时应该把握主要的脉络,不用太在意细节,读2、3章,再学习一下LR文法和第5章就够了。
  • debug的时候程序尽量简短,因为它展示出来的过程会很长。

符号优先级

符号优先级可以在cool-manual的第11节中找到,在代码中实现如下:

%right ASSIGN 
%left NOT
%nonassoc LE '<' '='
%left '+' '-'
%left '*' '/'
%left ISVOID
%left '~'
%left '@'
%left '.'

注意优先级越高要写到越下面。

非终结符声明

要使用上下文无关文法,首先要定义非终结符,如下:

%type <program> program
%type <classes> class_list
%type <class_> class
    
/* You will want to change the following line. */
%type <features> feature_list
%type <feature> feature

%type <formals> formal_list
%type <formal> formal

%type <expressions> blocks
%type <expressions> expression_list

%type <expression> let_expr
%type <expression> expression

%type <cases> case_list
%type <case_> case

文法

开始写文法,根据老师提供的文法规则,按顺序实现如下。

program和class

这块老师已经写了一部分,补充完整如下:

program	:
class_list	{ 
    @$ = @1; 
    ast_root = program($1);
  } 
;

class_list: 
  class {
    $$ = single_Classes($1);
    parse_results = $$; 
  }
| class_list class  { 
    $$ = append_Classes($1,single_Classes($2)); 
    parse_results = $$; 
  }
;
/*补充class的表达式*/
class: 
  CLASS TYPEID '{' feature_list '}' ';' { 
    $$ = class_($2,idtable.add_string("Object"),$4,
    stringtable.add_string(curr_filename)); 
  }
| CLASS TYPEID INHERITS TYPEID '{' feature_list '}' ';' { 
    $$ = class_($2,$4,$6,
    stringtable.add_string(curr_filename)); 
  }
| CLASS error ';' class {
    $$ = $4;
}
;

上面的报错是简单版本的,直接跳过当前错误的类并到下一个类,但这就产生了一个问题,如果出错的类是最后一个,该规则就不匹配了(虽然也没什么问题)。为此,可以将报错规则修改为对当前类各个组成部分检查错误,如果有错,就忽略当前类,但不跳至下一个:

| error TYPEID INHERITS TYPEID '{' feature_list '}' ';' 
| CLASS error INHERITS TYPEID '{' feature_list '}' ';' 
| CLASS TYPEID error TYPEID '{' feature_list '}' ';' 
| CLASS TYPEID INHERITS error '{' feature_list '}' ';' 
| CLASS TYPEID INHERITS TYPEID error feature_list '}' ';' 
| CLASS TYPEID INHERITS TYPEID '{' feature_list error ';' 

这两种在测试中都得到了满分。

feature

feature表示的是类中的语句,featureclass报错写法不同的主要原因是一个允许为空而另一个不允许,。

feature_list: // [feature;]*
  { $$ = nil_Features(); }
| feature_list feature  {
    $$ = append_Features($1, single_Features($2));
  }
| feature_list error ';'  {
    $$ = $1;
}
;

feature:
  OBJECTID '(' ')' ':' TYPEID '{' expression '}' ';'  {
    $$ = method($1, nil_Formals(), $5, $7);
  }
| OBJECTID '(' formal_list ')' ':' TYPEID '{' expression '}' ';'  {
    $$ = method($1, $3, $6, $8);
  }
| OBJECTID ':' TYPEID ';' {
    $$ = attr($1, $3, no_expr());
  }
| OBJECTID ':' TYPEID ASSIGN expression ';' {
    $$ = attr($1, $3, $5);
  }
;

formal

formal表示函数的输入参数列表,formal_list不为空。

formal_list:
  formal                  { 
    $$ = single_Formals($1); 
  }
| formal_list ',' formal  {
    $$ = append_Formals($1, single_Formals($3));
  }
;

formal: 
  OBJECTID ':' TYPEID {
    $$ = formal($1, $3);
}

blocks

expression即表达式,在下面说明。

blocks为表达式列表的一种形式。

blocks: // [expression;]+
  expression ';'  { 
    $$ = single_Expressions($1); 
  }
| blocks expression ';' {
    $$ = append_Expressions($1, single_Expressions($2));
  }
| blocks error ';'  {
    $$ = $1;
}
;

expression_list

表达式列表的另一种形式。

expression_list: // expression(,expression)*
  expression  {
    $$ = single_Expressions($1);
  }
| expression_list ',' expression  {
    $$ = append_Expressions($1, single_Expressions($3));
  }
;

let_expr

let_expr表示上面画红线的那部分。

let_expr:
  OBJECTID ':' TYPEID IN expression {
    $$ = let($1, $3, no_expr(), $5);
  }
| OBJECTID ':' TYPEID ASSIGN expression IN expression {
    $$ = let($1, $3, $5, $7);
  }
| OBJECTID ':' TYPEID ',' let_expr  {
    $$ = let($1, $3, no_expr(), $5);
  }  
 | OBJECTID ':' TYPEID ASSIGN expression ',' let_expr {
    $$ = let($1, $3, $5, $7);
  } 
 | error ',' let_expr  {
    $$ = $3;
}
;

case

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DdpH7VYy-1665105094824)(image/image-20221006203942217-16650599858581.png)]

case_list:
  case  { 
    $$ = single_Cases($1); 
  }
| case_list case  { 
    $$ = append_Cases($1, single_Cases($2)); 
  }
;
case: 
  OBJECTID ':' TYPEID DARROW expression ';' { 
    $$ = branch($1, $3, $5); 
  }
;

expression

按照给定的规则写就可以了,这里不用报错:

expression:
  OBJECTID ASSIGN expression  { 
    $$ = assign($1, $3); 
  }
| expression '.' OBJECTID '(' ')' { 
    $$ = dispatch($1, $3, nil_Expressions()); 
  }
| expression '.' OBJECTID '(' expression_list ')' { 
    $$ = dispatch($1, $3, $5); 
  }
| expression '@' TYPEID '.' OBJECTID '(' ')'  { 
    $$ = static_dispatch($1, $3, $5, nil_Expressions());
  }
| expression '@' TYPEID '.' OBJECTID '(' expression_list ')'  { 
    $$ = static_dispatch($1, $3, $5, $7);
  }
| OBJECTID '(' ')'  { 
    $$ = dispatch(object(idtable.add_string("self")), $1, nil_Expressions()); 
  }
| OBJECTID '(' expression_list ')'  { 
    $$ = dispatch(object(idtable.add_string("self")), $1, $3); 
  }
| IF expression THEN expression ELSE expression FI  { 
    $$ = cond($2, $4, $6); 
  }
| WHILE expression LOOP expression POOL { 
    $$ = loop($2, $4); 
  }
| '{' blocks '}' { 
    $$ = block($2); 
  }
| LET let_expr  {
    $$ = $2;
  }
| CASE expression OF case_list ESAC { 
    $$ = typcase($2, $4); 
  }
| NEW TYPEID  { 
    $$ = new_($2); 
  }
| ISVOID expression { 
    $$ = isvoid($2); 
  }
| expression '+' expression { 
    $$ = plus($1, $3); 
  }
| expression '-' expression { 
    $$ = sub($1, $3); 
  }
| expression '*' expression { 
    $$ = mul($1, $3); 
  }
| expression '/' expression { 
    $$ = divide($1, $3); 
  }
| '~' expression  { 
    $$ = neg($2); 
  }
| expression '<' expression { 
    $$ = lt($1, $3); 
  }
| expression LE expression  { 
    $$ = leq($1, $3); 
  }
| expression '=' expression { 
    $$ = eq($1, $3); 
  }
| NOT expression  { 
    $$ = comp($2); 
  }
| '(' expression ')'  { 
    $$ = $2; 
  }
| OBJECTID    { 
    $$ = object($1); 
  }
  
| INT_CONST   { 
    $$ = int_const($1); 
  }
| STR_CONST   { 
    $$ = string_const($1); 
  }
| BOOL_CONST  { 
    $$ = bool_const($1); 
  }
;
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值