2014-12-17 5 views
-1

구문 분석기를 만들려고했는데 LEX와 YACC를 사용하여 C++과 매우 유사합니다 ... 이 부분은 LEX 부분입니다. 이 부분은 YACC 부분이지만여전히 YACC에서 발견 할 수는 없지만 구문 오류가 발생했습니다

%{ 
#include <stdio.h> 
#include "y.tab.h" 
%} 
%x comment 
%x comment_line 
%% 

"//" {BEGIN comment_line;} 
<comment_line>\n {BEGIN 0;} 
<comment_line>. ; 
"/*" {BEGIN comment;} 
<comment>"*/" {BEGIN 0;} 
<comment>. ; 

"bool"|"const"|"int"|"float"|"char"|"string" {return TIP;} 
"void" {return TIP_VOID;} 
"class" {return TIP_CLASS;} 
\'.\' {return VAL_CHAR;} 
\".*\" {return VAL_STRING;} 
"start_program" {return BGIN;} 
"end_program" {return END;} 
"start_func" {return START_FUNC;} 
"end_func" {return END_FUNC;} 
"start_class" {return START_CLASS;} 
"end_class" {return END_CLASS;} 
"if" {return IF;} 
"then" {return THEN;} 
"end_then" {return END_THEN;} 
"else" {return ELSE;} 
"end_else" {return END_ELSE;} 
"while" {return WHILE;} 
"do" {return DO;}; 
"end_while" {return END_WHILE;} 
"for" {return FOR;} 
"end_for" {return END_FOR;} 
"return" {return RETURN;} 
"true"|"false" {return VAL_BOOL;} 
"and"|"or" {return OPERATOR_BOOL;} 
"<"|">"|"<="|"=>" {return OPERATOR_COMPARISON;} 
"=="|"!=" {return OPERATOR_INEQUALITY;} 
"<-" {return ASSIGN;} 
[_a-zA-Z][_a-zA-Z0-9]* {return ID;} 
0|[1-9][0-9]* {return NR_INT_U;} 
-?0|([1-9][0-9]*) {return NR_INT;} 
-?(0|[1-9][0-9]*)","[0-9]* {return NR_FLOAT;} 
[ \t] ; 
\n {yylineno++;} 
. { return yytext[0];} 

:

%{ 
#include <stdio.h> 
extern FILE* yyin; 
extern char* yytext; 
extern int yylineno; 
%} 
%token ID TIP BGIN END ASSIGN NR NR_FLOAT NR_INT NR_INT_U TIP_VOID START_FUNC END_FUNC RETURN TIP_CLASS START_CLASS END_CLASS OPERATOR_COMPARISON OPERATOR_INEQUALITY VAL_BOOL IF THEN END_THEN ELSE END_ELSE DO WHILE END_WHILE FOR END_FOR VAL_CHAR VAL_STRING OPERATOR_BOOL 
%start progr 
%% 
progr: declarations bloc {printf("Syntacticaly correct program\n");} 
    ; 
declarations : declaration ';' 
     | declarations declaration ';' 
     ; 
declaration : variable_declaration 
     | function body_function 
     | class_declaration 
     ; 

class_declaration : TIP_CLASS ID START_CLASS declarations END_CLASS 
      ; 

variable_declaration : TIP ID 
      | TIP ID ASSIGN value_asign 
      | TIP ID vector_declaration 
      | TIP_CLASS ID ID 
      ; 
value_asign: NR_INT_U 
     | VAL_BOOL 
     | NR_INT 
     | NR_FLOAT 
     | VAL_CHAR 
     | VAL_STRING 
     | ID '(' list_call ')' 
     | ID '.' ID '(' list_call ')' 
     ; 
/*functions declaration */ 
function : TIP ID '(' parameter_list ')' 
     | TIP ID '(' ')' 
     | TIP_VOID ID '(' parameter_list ')' 
     | TIP_VOID ID '(' ')' 
     ; 

body_function: START_FUNC list_function END_FUNC 
     ; 
list_function : RETURN expression ';' 
     | list_function RETURN expression ';' 
     | statement ';' 
     | list_function statement ';' 
     | bloc_logic_function 
     | list bloc_logic_function 
     ; 
bloc_logic_function: IF expression_logic 
      THEN list_function END_THEN 
      ELSE list_function END_ELSE 
      | WHILE expression_logic 
      list_function 
      END_WHILE 
      | FOR statement WHILE expression_logic DO statement 
      list_function 
      END_FOR 
      ; 


/*declaration of multidimensional arrays*/ 
vector_declaration : '[' NR_INT_U ']' 
       | vector_declaration '[' NR_INT_U ']' 
       ; 
vector : '[' expression ']' 
     | vector '[' expression ']' 
     ; 

parameter_list : param 
      | parameter_list ',' param 
      ; 

param : TIP ID  
     ; 

/* bloc */ 
bloc : BGIN list END 
    ; 

/* list of instructions */ 
list : bloc_logic 
    | list bloc_logic 
    | statement ';' 
    | list statement ';' 
    ; 
bloc_logic: IF expression_logic 
     THEN list END_THEN 
     ELSE list END_ELSE 
     | WHILE expression_logic 
     list 
     END_WHILE 
     | FOR statement WHILE expression_logic DO statement 
     list 
     END_FOR 
     ; 

/* instruction */ 
statement: variable_declaration 
    | ID ASSIGN ID 
    | ID ASSIGN NR_INT_U 
    | ID ASSIGN NR_INT 
    | ID ASSIGN NR_FLOAT 
    | ID ASSIGN VAL_BOOL 
    | ID ASSIGN expression 
    | ID vector ASSIGN expression 
    | ID '(' list_call ')' 
    | ID '.' ID '(' list_call ')' 
    ; 

expression: simbol 
    | expression '+' expression 
    | '('expression '+' expression ')' 
    | expression '-' expression 
    | '('expression '-' expression ')' 
    | expression '*' expression 
    | '('expression '*' expression ')' 
    | expression ':' expression 
    | '('expression ':' expression ')' 
    ; 
simbol: ID 
     | '-' ID 
     | '-' ID vector 
     | ID vector 
     | NR_INT_U 
     | NR_INT 
     | NR_FLOAT 
     | ID '(' list_call ')' 
     | ID '.' ID '(' list_call ')' 
     ; 
expression_logic : logical_condition 
     | '(' logical_condition ')' 
     | expression_logic OPERATOR_BOOL expression_logic 
     | '(' expression_logic OPERATOR_BOOL expression_logic ')' 
     ; 
logical_condition : VAL_BOOL OPERATOR_INEQUALITY VAL_BOOL 
     | VAL_BOOL OPERATOR_INEQUALITY expression 
     | expression OPERATOR_COMPARISON expression 
     | expression OPERATOR_INEQUALITY expression 
     | expression OPERATOR_INEQUALITY VAL_BOOL 
     ; 
list_call : expression 
     | list_call ',' expression 
     | VAL_STRING 
     | list_call ',' VAL_STRING 
     | VAL_CHAR 
     | list_call ',' VAL_CHAR 
     | VAL_BOOL 
     | list_call ',' VAL_BOOL 
     | /*empty*/ 
     ; 
%% 
int yyerror(char * s){ 
printf("Error: %s at line:%d\n",s,yylineno); 
} 

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

그리고 이것은 내 예입니다 나는 그것을 실행하려고 :

int factorial(int n) 
    start_func 
    if n==0 
     then 
     return 1; 
     end_then 
    else 
     return n*factorial(n-1); 
    end_else 
    end_func; 

class book 
    start_class 
    int code; 
    string name; 
    float price; 
    void setPrice(float x) 
     start_func 
     price <- x; 
     end_func; 

    string getNume() 
     start_func 
     return name; 
     end_func; 
    end_class; 

start_program 

    class book python; 
    float y<-1,37; 
    string auxiliar; 

    python.setPrice(y); 
    auxiliar<-getNume(); 

    int v[50]; 
    int j<-0; 
    for i<-0 while i<5 do i<-i+1 
    v[i]<-j+1; 
    end_for 

end_program 

나는 이러한 지침을 사용하여 퍼티에서이 작업을 실행하려고 해요 :

lex tema.l 
yacc -d tema.y 2>/dev/null 
gcc y.tab.c lex.yy.c -ll 
./a.out <prog2.txt 
내 화면이 있다는 것입니다에 내가 문제를 찾을 수 없습니다

... 나는 그것을 보여줍니다 모든 코드의 라인을 제외한 모든 검색 한 첫 번째 줄에는 오류가 있습니다. 어떤 실수도 볼 수 없기 때문에 이해가되지 않습니다. 아마도 내가 여기에서 눈이 멀어 졌을 것입니다. 어떻게 생각하십니까?

+2

실제 오류 메시지를 게시하고 네 개의 명령 중 어떤 명령을 생성했는지 나타냅니다. 그리고 퍼티는이 지구와 어떤 관계가 있습니까? – EJP

+0

@EJP 오류 : 행의 구문 오류 : 1 –

+0

@EJP './a.out

답변

0

분명히 첫 줄에는 캐리지 리턴이나 formfeed 또는 다른 이상한 문자가 있습니다. 공백과 줄 끝 규칙은 지나치게 제한적입니다.

[ \t\f]+ ; 
"\r\n"|"\n" { yylineno++; } 

첫 번째 줄은 공백으로 폼 피드, 그리고 +를 추가하는 것이 훨씬 더 효율적 핸들을보십시오. 두 번째 줄은 줄 종결 자로 \r\n\n을 모두 처리합니다.

은 또한 당신은이 모든 문제를 해결해야합니다

"bool"|"const"|"int"|"float"|"char"|"string" {return TIP;} 
"true"|"false" {return VAL_BOOL;} 
"and"|"or" {return OPERATOR_BOOL;} 
"<"|">"|"<="|"=>" {return OPERATOR_COMPARISON;} 
"=="|"!=" {return OPERATOR_INEQUALITY;} 

은 다음과 같이하지 '최적화'를 마십시오. 여기서 정보를 잃어 버렸고 정확한 코드를 생성하는 것이 불가능할 것입니다. 또한 andor을 섞으면 자신 사이에 우선권을 부여 할 수있는 기회가 주어지지 않습니다. 파서가 파서의 작업을하도록하십시오.

"bool" {return TIP_BOOL;} 
"const" {return TIP_CONST;} 
"int" {return TIP_INT;} 
"float" {return TIP_FLOAT;} 
"char" {return TIP_CHAR;} 
"string" {return TIP_STRING;} 
"true" {return VAL_TRUE;} 
"false" {return VAL_FALSE;} 
"and" { return OPERATOR_AND; } 
"or" {return OPERATOR_OR;} 
"<=" { return OPERATOR_LE; } 
"=>" {return OPERATOR_GE;} 
"==" {return OPERATOR_EQUALITY;} 
"!=" {return OPERATOR_INEQUALITY;} 

당신이 특별히 모든 <, >, =, + 등을 처리 할 필요가 없습니다주의 : 적절한 문법에 대한 조정 및 %token 선언으로,이 작업을 수행 그들은

에 의해 처리됩니다
. { return yytext[0];} 

그래서 '<', '>', '=' 등을 직접 문법에 사용할 수 있습니다.