【问题标题】:How do i implement a semantic checker for given language我如何为给定语言实现语义检查器
【发布时间】:2018-09-25 05:57:33
【问题描述】:
for(var x in z) {
 a = x + 1 + 2;
 foo();
 }
 function bar() {}
 for(t in []){
 function hello(a) {
 a = t + 'hello' + 'world';
 }
 bar();
 hello();
 }
 hello();
 function hello() {}
 15 * 30;
 1 + 2 + 3;
 a = 3 - 2 - 1;
 a + 10;

假设我们有一个语义规则,即在调用函数时,该函数应在当前作用域或父作用域之前声明。

所以自从 foo();在上面的程序(第 3 行)中没有声明,我们需要打印一条错误消息。

对于第 13 行 hello() 没有声明,所以我们需要打印一条错误消息。

我们有 bison/flex 实现,但是缺少属性语法实现。

解析器:

%{
#include <stdio.h> 
void yyerror(const char * msg){
        printf("%s\n",msg);
}
%} 
%token tFOR tIN tSEMICOLON tLPAR tLBRKT tLT tSTAR tPLUS tPERCENT tINT tREAL tSTRING tWHILE tVAR tCOMMA tRPAR tRBRKT tRBRACE tGT tEQ tMINUS tNOT tIDENT tIF tCOLON tLBRACE tELSE tEQCHECK tFUNCTION
%left tMINUS tPLUS
%left tSTAR
%left tPERCENT
%left tLT tGT tEQCHECK
%left tNOT

%%
prog: statementList
;

statementList: statementList statement
             | statementList tSEMICOLON
             |
;

statement: assign
         | if
         | expr
         | while
         | for
         | functionCall
         | functionDeclaration
;

assign: tIDENT tEQ expr
      | tVAR tIDENT tEQ expr
;

if: ifPart elsePart
;

ifPart: tIF tLPAR expr tRPAR statementBlock
;

elsePart: tELSE statementBlock 
        | 
;

while: tWHILE tLPAR expr tRPAR statementBlock
;

for: tFOR tLPAR tIDENT tIN expr tRPAR statementBlock
   | tFOR tLPAR tVAR tIDENT tIN expr tRPAR statementBlock
;

functionDeclaration: tFUNCTION tIDENT tLPAR exprList tRPAR statementBlock
                   | tFUNCTION tIDENT tLPAR tRPAR statementBlock
;

statementBlock: tLBRACE statementList tRBRACE
;

functionCall: tIDENT tLPAR exprList tRPAR
            | tIDENT tLPAR tRPAR
;

expr: tIDENT
    | tREAL
    | tINT
    | tSTRING
    | tLBRKT tRBRKT
    | tLBRKT exprList tRBRKT
    | tLBRACE tRBRACE 
    | tLBRACE propertyList tRBRACE
    | tNOT expr
    | expr tPLUS expr
    | expr tMINUS expr
    | expr tSTAR expr
    | expr tEQCHECK expr
    | expr tLT expr
    | expr tGT expr
;

exprList: expr
        | exprList tCOMMA expr
;

propertyList: tIDENT tCOLON expr
            | propertyList tCOMMA tIDENT tCOLON expr
;

%%
int main() {
  return yyparse();
}

扫描仪:

%{
#include "parser.tab.h"
%}
%%
in      return tIN;
function      return tFUNCTION;
for      return tFOR;
while    return tWHILE;
var      return tVAR;
";"      return tSEMICOLON;
"("      return tLPAR;
")"      return tRPAR;
"["      return tLBRKT;
"]"      return tRBRKT;
"<"      return tLT;
">"      return tGT;
"*"      return tSTAR;
"+"      return tPLUS;
"%"      return tPERCENT;
","      return tCOMMA;
"{"      return tRBRACE;
"}"      return tLBRACE;
"=="      return tEQCHECK;
"="      return tEQ;
"-"      return tMINUS;
"!"      return tNOT;
"-"?[0-9]+  return tINT;
("-"[0-9]+"."[0-9]+)|([0-9]*"."[0-9]+)   return tREAL;
('[^']*')|(["][^"]*["]) return tSTRING;
[a-zA-Z_][a-zA-Z_0-9]*  return tIDENT;
[ \t\n] 
.      return yytext[0];
%%

【问题讨论】:

  • 不清楚这是一般问题还是特定于您对 bison/flex 的使用?如果是前者,这是一个非常广泛的问题。也许缩小到具体范围会有所帮助。
  • >> "我们有 bison/flex 实现,但是缺少属性语法实现。"是的。实施其中之一来进行语义检查。

标签: parsing compiler-construction bison semantics lex


【解决方案1】:

在以下语法中,tIDENTtFUNCTION 是标记。Foo() 是标记。 你必须保留一个

符号表

为了存储tIDENTtFUNCTION 标记。要检查foo 之前是否已声明,您必须遍历符号表并查看它是否已在其中。您还必须使用变量来执行此操作。

例如:

assign: tFUNCTION   {   
                        SYMBOL *s= NULL
                        if((s=symlook_function($1,depth,yylineno,param_count,symbol_list)) == NULL ){
                            strcat(errstr, "Found a function which is not decalared");
                            yyerror(errstr);
                        }
                }

您将必须实现自己的符号表及其功能,例如用 C 语言在其中添加和搜索。这里 symlook 在符号表中搜索,如果在里面找不到标记 tFUNCTION ($1)将产生错误消息。您还必须在里面包含不同的语法。一个函数或变量第一次是declaring,一个当你在an expression.中找到它时 检查这个 C Yacc 语法。这些是 C 语言的产生: https://www.lysator.liu.se/c/ANSI-C-grammar-y.html

看到这个:

external_declaration
    : function_definition
    | declaration

当产生式为function_definition 时,令牌foo 第一次进入符号表中。但是,如果您在不同的产生式中再次找到foo,则必须搜索符号表并返回@ 987654338@如果丢失。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-09-19
    • 2016-02-04
    • 1970-01-01
    • 2011-01-20
    • 2011-02-08
    • 1970-01-01
    • 2012-03-11
    • 2016-03-03
    相关资源
    最近更新 更多