1

i have to design an original programming language and provide a syntactic analyzer for it. Now i'm at the point where i should check if a variable was already declared and if it was i shouldn't be able to declare it again. How can i do this?with an array?(how)

This is what I've done so far.

lex:


%{
#include <stdio.h>
#include <string.h>
#include "y.tab.h"

%}
%option noyywrap
%%

"/*"(.|\n)+"*/" ;
"float"|"char"|"string" {return TYPE;}
"int" {return INTTYPE;}
"for" {return FOR;}
"while" {return WHILE;}
"if" {return IF;}
"else" {return ELSE;}
"bool" {return BOOLTYPE;}
"true"|"false" {return BOOLVALUE;}
"++"|"--" {return INCRDECR;}
"/[^\"]+/" {return STRINGVALUE;}
"scat"|"scmp"|"scpy"|"slen" {return STRINGFUNCTION;}
"protected"|"private"|"public" { return CLASSTYPE;}
"class" {return CLASS;}
"eval" {return EVAL;}
[1-9][0-9]*|0 {yylval = atoi(yytext); return INTVALUE;}
[A-Za-z][A-Za-z0-9]* {yylval = strdup(yytext); return ID;}
"=" {return ASSIGN;}
"<="|"<"|">="|">"|"=="|"!=" {return COMP;}
"begin_prog" {return BGIN;}
"end_prog" {return END;}
[ \t] ;
\n {yylineno++;}
. {return yytext[0];}

yacc:

%{
#include <stdio.h>
extern FILE* yyin;
extern char* yytext;
extern int yylineno;
%}
%token TYPE INTTYPE FOR WHILE IF ELSE BOOLTYPE BOOLVALUE INCRDECR STRINGVALUE STRINGFUNCTION CLASSTYPE CLASS EVAL INTVALUE ID ASSIGN COMP BGIN END 

%start s
%left '.'
%left ','
%left ';'
%left '+' '-'
%left '*' '/' '%'

%%



s: declarations block {printf ("correct input \n ");}
;
declarations : declaration ';'
| declarations declaration ';'
;


declaration : TYPE ID 
|BOOLTYPE ID ASSIGN BOOLVALUE
|INTTYPE ID ASSIGN INTVALUE
|INTTYPE ID
|TYPE ID '(' list_param ')'
|TYPE ID '[' INTVALUE ']'
|INTTYPE ID '(' list_param ')'
|INTTYPE ID '[' INTVALUE ']'
|BOOLTYPE ID 
;


block: BGIN blockinstr END
;

blockinstr: blockinstr listfiw 
| blockinstr classs 
| blockinstr fdeclaration
| listfiw 
| listinstr 
| stringg 
| classs 
| fdeclaration

;

fdeclaration : TYPE EVAL '(' list_paramf ')' '{' listinstr '}' 
| INTTYPE EVAL '(' list_paramf ')' '{' listinstr '}'
| TYPE ID '(' list_param ')' '{' listinstr '}'
| INTTYPE ID '(' list_param ')' '{' listinstr '}'
;

list_param : parameter
| list_param ',' parameter
;

parameter : TYPE ID
| parameterf
;

list_paramf : parameterf
| list_paramf ',' parameterf
; 

parameterf : INTTYPE ID
;

listfiw : iff
|forr
|whilee
;

iff: IF '('  ID COMP INTVALUE ')' '{' listinstr '}'
| IF '(' ID COMP ID ')' '{' listinstr '}'
| IF '(' ID ')' '{' listinstr '}'
| IF '(' ID COMP INTVALUE ')' '{' listinstr '}' ELSE '{' listinstr '}'
| IF '(' ID COMP ID ')' '{' listinstr '}' ELSE '{' listinstr '}'
| IF '(' ID ')' '{' listinstr '}' ELSE '{' listinstr '}'
| IF '(' ID COMP BOOLVALUE ')' '{' listinstr '}'
| IF '(' ID COMP BOOLVALUE ')' '{' listinstr '}' ELSE '{' listinstr '}'
;

forr: FOR '(' ID ASSIGN INTVALUE ';' ID COMP INTVALUE ';' ID INCRDECR ')' '{' listinstr '}' 
| FOR '(' ID ASSIGN INTVALUE ';' ID COMP INTVALUE ';' ID INCRDECR ')' '{' FOR '(' ID ASSIGN INTVALUE ';' ID COMP INTVALUE ';' ID INCRDECR ')' '{' listinstr '}'  '}' 
    ;

whilee: WHILE '(' ID COMP INTVALUE ')' '{' listinstr '}'
| WHILE '(' INTVALUE ')' '{' listinstr '}'
 ;


listinstr : instruction ';'
| listinstr instruction ';'
;

instruction: ID ASSIGN BOOLVALUE
| ID ASSIGN operations
| ID '(' operations ')' 
;

operations: operations '+' operations
| operations '*' operations
|operations '-' operations
|operations '/' operations 
|operations '%' operations
|'(' operations ')'
|ID '[' INTVALUE ']'
|ID '(' operations ')'
|INTVALUE
|ID
;

stringg : stringg STRINGFUNCTION '(' ID ')' ';' 
        | stringg STRINGFUNCTION '(' ID ',' ID ')' ';'
    | STRINGFUNCTION '(' ID ')' ';'
        | STRINGFUNCTION '(' ID ',' ID ')' ';'
        ;

classs: CLASS ID '{' classlists '}'
      ;
classlists: classlist 
| classlists classlist
;
classlist: CLASSTYPE ':' declarations 
;


%%
int yyerror(char * s){
 printf("err: %s line:%d\n",s,yylineno);
}

int main(int argc, char** argv[]){
 yyin=fopen(argv[1],"r");
 yyparse();
 fclose(f);
 fclose(yyin);


} 

This works for declarations of any type. I hope you can help me with my problem. Thanks!!

BiaGH24990
  • 11
  • 3
  • 1
    Do you have a symbol table? When you have a declaration, see if the symbol is already there. I don't think you can check for this at the scanner or grammar level, it has to be checked in your actions. – Fred Larson Jan 06 '20 at 20:46
  • I do not have a symbol table. This is also a task I have to do but I also don't know how.. – BiaGH24990 Jan 06 '20 at 20:56
  • 1
    A symbol table is just a lookup table of symbols for the program, usually in a form that is quick to search like a [hash table](https://en.wikipedia.org/wiki/Hash_table). But for starters you could use just a linked list or array that you linear search. Each symbol table entry would contain the symbol name and other data, such as the type. – Fred Larson Jan 06 '20 at 21:04
  • You cannot check duplicate variables just using the grammar because the language is not context free. You need at least a symbol table. – Ajay Brahmakshatriya Jan 06 '20 at 21:37
  • 1
    Does your language have variable scope? That affects how you check duplicates – stark Jan 06 '20 at 21:40
  • OT: bison doesn't have any concept of reserved words. If you want to call a non-terminal `for` or `while` or `string`, go for it. There's no need to use strange words. (Although there are people who prefer `forStatement` or `for-stmt`, it's not required.) – rici Jan 07 '20 at 01:48
  • Also: you don't have to quote letters or numbers in flex patterns. So you can write `true|false` instead of `"true"|"false"`. Your pattern for strings (`"/[^\"]+/"`) is totally incorrect, since it is just a simple string match, not a regular expression. And your pattern for comments (`"/*"(.|\n)+"*/"`) will match the entire text from the start of the first comment to the end of the last one, which is definitely not what you want. That's not a complete list; it's just what struck my eye. – rici Jan 07 '20 at 01:55
  • Thank you for your answers. You really helped me. – BiaGH24990 Jan 07 '20 at 06:19

0 Answers0