Как реализовать семантическую проверку для данного языка
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, однако реализация грамматики атрибутов отсутствует.
Parser:
%{
#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];
%%
1 ответ
В следующей грамматике tIDENT
а также tFUNCTION
являются жетонамиFoo()
это знак Вы должны держать
Таблица символов
для того, чтобы хранить tIDENT
или же tFUNCTION
tokens.To проверить, если 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);
}
}
Вам нужно будет реализовать свою собственную таблицу символов и ее функции, такие как добавление и поиск в ней на языке Си. Здесь 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
в другом производстве вам придется искать таблицу символов и возвращать error
если это отсутствует.