2016-06-11 2 views
1

간체화 된 Java 언어로 자체 제작 된 컴파일러를 실행하려고하는데, 항상 세그먼트 화 오류로 끝납니다. 목표는 추상 구문 트리를 작성하는 것입니다. 또한 valgrind를 사용하여 디버깅을 시도했지만 tool이 내 PC에서 bison과 flex에 문제가있는 것 같습니다. 도와주세요.Flex, Bison 및 Segmentation 폴트 정보

Lexfile :

%{ 
#include <stdio.h> 
#include "abst.h" 
#include "yacc.tab.h" 
int yylineno; 
int column = 0; 
int nesting_comments = 0; 
int max_comment_level = 0; 
int total_comments_number = 0; 

void count() { 
    int i; 
    for(i = 0; yytext[i] != '\0'; i++){ 
     if(yytext[i] == '\n') 
     column = 0; 
     else if(yytext[i] == '\t') 
     column += 8 - (column % 8); 
     else 
     column++; 
    } 
    //printf("%s", yytext);  Uncomment this Line for printing the input stream 
} 

void yyerror(char const *s); 

%} 

DIGIT  [0-9] 
LETTER  [a-zA-Z] 
WHITESPACE [ \t\r] 

VINT   {DIGIT}+ 
VFLOAT  {VINT}+"."{DIGIT}* 
VDOUBLE  {VFLOAT}E{VINT} 
VSTRING  \".*\" 

COMMENT1 "//".* 
%x   COMMENT2 
COMMENT3 "/""*"([^{"*""/"}])*"*""/" 

REL_OP  "<"|"<="|"=="|"=>"|">"|"&&"|"||"|"&"|"|"|"!=" 
ADD_OP  "+"|"-"|"%" 
MUL_OP  "*"|"/" 
UNARY_OP  "++"|"--" 
ASSIGN_OP "+="|"-="|"*="|"/="|"%=" 
TYPE  "boolean"|"int"|"float"|"double" 

ID {LETTER}({LETTER}|{DIGIT})* 

%% 
"if"       { count(); return IF; } 
"else"       { count(); return ELSE; } 
"while"       { count(); return WHILE; } 
"for"       { count(); return FOR; } 
"read"       { count(); return READ; } 
"write"       { count(); return WRITE; } 
"final"       { count(); return FINAL; } 

{VINT}       { count(); yylval.ival = atoi(yytext); return IVALUE; } 
{VFLOAT}|{VDOUBLE}    { count(); yylval.fval = atof(yytext); return FVALUE; } 
{VSTRING}      { count(); yylval.identifier = strdup(yytext); return STRING; } 
"true"       { count(); return TRUE; } 
"false"       { count(); return FALSE; } 
"boolean"      { count(); return BOOLEAN; } 
"int"       { count(); return INT; } 
"float"       { count(); return FLOAT; } 
"double"      { count(); return DOUBLE; } 


{ID}       { count(); yylval.identifier = strdup(yytext); return IDENT; } 
{REL_OP}      { count(); yylval.ival = getEnum(yytext); return RELOP; } 
{ADD_OP}      { count(); yylval.ival = getEnum(yytext); return ADDOP; } 
{MUL_OP}      { count(); yylval.ival = getEnum(yytext); return MULOP; } 
{UNARY_OP}      { count(); yylval.ival = getEnum(yytext); return UNARYOP; } 

"="        { count(); return '='; } 
"!"        { count(); return '!'; } 
"("        { count(); return '('; } 
")"        { count(); return ')'; } 
"["        { count(); return '['; } 
"]"        { count(); return ']'; } 
"{"        { count(); return '{'; } 
"}"        { count(); return '}'; } 
","        { count(); return ','; } 
";"        { count(); return ';'; } 

{COMMENT1} { 
    total_comments_number++; 
    count(); 
} 

"(*" { 
    total_comments_number++; 
    BEGIN(COMMENT2); 
    printf("(* [BEGIN NESTED %d]\n", nesting_comments++); 
    count(); 
} 

<COMMENT2>[^*()]* { 
    printf("%s", yytext); /* Eat other characters */ 
    count(); 
} 
<COMMENT2>"(*" { 
    printf("(* [BEGIN NESTED %d]\n", nesting_comments); 
    if(++nesting_comments > max_comment_level) { 
     max_comment_level = nesting_comments; 
    } 
    count(); 
} 
<COMMENT2>"*)" { 
    printf("\n*) [END NESTED %d]", --nesting_comments); 
    if (nesting_comments == 0){ 
     BEGIN(INITIAL); 
    } 
    count(); 
} 
<COMMENT2>[*()] { 
    printf("%s", yytext); /* Eat the other characters if it is not a comment delimiter */ 
    count(); 
} 

{COMMENT3} { 
    total_comments_number++; 
    count(); 
} 
{WHITESPACE}+      { count(); } 
\n        { count(); yylineno++; } 
.         { yyerror("Lex"); } 

%% 

Yaccfile :

%{ 
    #include <stdio.h> 
    #include <stdlib.h> 
    #include <stdarg.h> 
    #include "abst.h" 

    extern char *yytext; 
    extern int yylineno; 
    extern FILE *yyin; 
    extern int column; 

    extern int nesting_comments; 
    extern int max_comment_level; 
    extern int total_comments_number; 

    int yylex(void); 
    //int yydebug=1; 

    node *root; 

    void yyerror (char const *s){ 
     fprintf (stderr, "%s Error at line %d:%d\n", s, yylineno, column); 
     fprintf (stderr, "Text was: %s\n", yytext); 
     exit(EXIT_FAILURE); 
    } 
%} 

%union { 
    char *identifier; 
    int ival; 
    float fval; 

    struct _node *node; 
} 

%type <identifier> IDENT STRING 
%type <ival> IVALUE MULOP RELOP ADDOP UNARYOP 
%type <fval> FVALUE 
%type <node> program compStmt varDecList varListType type varList ident identArray stmtList 
%type <node> statement assignStmt ifStmt elsePart whileStmt forStmt ioStmt ioCall paramList 
%type <node> expr simpleExpr term factor mulop addop relop 

%token IF ELSE WHILE FOR WRITE READ FINAL 
%token IVALUE FVALUE TRUE FALSE STRING 
%token BOOLEAN INT FLOAT DOUBLE 
%token IDENT 

%right UNARYOP '!' '=' 
%left MULOP ADDOP RELOP 
%left '[' ']' '(' ')' 

%start program 

%% 
program 
: compStmt      { $$ = $1; root = $1;} 
; 

compStmt 
: '{' varDecList stmtList '}'  { $$ = new_node(COMP_STMT, (node*[]){ $2, $3, NULL });} 
; 


varDecList 
: varListType varDecList   { $$ = new_node(DECLARATION, (node*[]){ $1, $2, NULL }); } 
| 
; 

varListType 
: type varList     { $$ = new_node(VAR_LIST_TYPE, (node*[]){ $1, $2, NULL }); } 
| FINAL type varList    { $$ = new_node(VAR_LIST_TYPE, (node*[]){ new_string_node(TYPE, "final") , $2, $3, NULL }); } 
; 

type 
: BOOLEAN       { $$ = new_string_node(TYPE, "boolean"); } 
| INT        { $$ = new_string_node(TYPE, "int"); } 
| FLOAT       { $$ = new_string_node(TYPE, "float"); } 
| DOUBLE       { $$ = new_string_node(TYPE, "double"); } 
; 

varList 
: ident ',' varList    { $$ = new_node(VAR_LIST, (node*[]){ $1, $3, NULL }); } 
| ident ';'      { $$ = new_node(VAR_LIST, (node*[]){ $1, NULL }); } 
| ident '=' expr ';'    { $$ = new_node(VAR_LIST, (node*[]){ $1, $3, NULL }); } 
; 

ident 
: IDENT       { $$ = new_string_node(VAR, $1); } 
| identArray '[' simpleExpr ']' { $$ = new_node(ARRAY, (node*[]){ $1, $3, NULL }); } 
; 

identArray 
: IDENT       { $$ = new_string_node(VAR, $1); } 
; 

stmtList 
: statement stmtList    { $$ = new_node(STATEMENT_LIST, (node*[]){ $1, $2, NULL }); } 
| statement      { $$ = new_node(STATEMENT_LIST, (node*[]){ $1, NULL }); } 
; 

statement 
: assignStmt ';'     { $$ = $1; } 
| compStmt      { $$ = $1; } 
| ifStmt       { $$ = $1; } 
| whileStmt      { $$ = $1; } 
| forStmt       { $$ = $1; } 
| ioStmt       { $$ = $1; } 
; 

assignStmt 
: ident '=' expr     { $$ = new_node(ASSIGN_STMT, (node*[]){ $1, $3, NULL }); } 
| ident UNARYOP     { $$ = new_node(ASSIGN_STMT, (node*[]){ $1, new_int_node(OP, $2), NULL }); } 
; 

ifStmt 
: IF '(' expr ')' statement elsePart { 
     if($6->type != NONE){ 
      $$ = new_node(IF_STMT, (node*[]){ $3, $5, $6, NULL }); 
     } 
     else { 
      $$ = new_node(IF_STMT, (node*[]){ $3, $5, NULL }); 
     } 
    } 
; 

elsePart 
: ELSE statement     { $$ = $2; } 
|         { $$ = new_none(); } 
; 

whileStmt 
: WHILE '(' expr ')' statement { $$ = new_node(WHILE_STMT, (node*[]){ $3, $5, NULL }); } 
; 

forStmt 
: FOR '(' assignStmt ';' expr ';' assignStmt ')' statement { 
             $$ = new_node(FOR_STMT, (node*[]){ $3, $5, $7, $9, NULL }); 
    } 
; 

ioStmt 
: ioCall '(' paramList ')' ';' { $$ = new_node(IOFUNC, (node*[]){ $1, $3, NULL }); } 
; 

ioCall 
: READ       { $$ = new_int_node(IOFUNCCALL, 0); } 
| WRITE       { $$ = new_int_node(IOFUNCCALL, 1); } 
; 

paramList 
: ident ',' paramList    { $$ = new_node(PARAM_LIST, (node*[]){ $1, $3, NULL }); } 
| STRING ',' paramList   { $$ = new_node(PARAM_LIST, (node*[]){ new_string_node(STRING_CONST, $1), $3, NULL }); } 
| ident       { $$ = new_node(PARAM_LIST, (node*[]){ $1, NULL }); } 
| STRING       { $$ = new_string_node(STRING_CONST, $1); } 
; 

expr 
: simpleExpr relop simpleExpr  { $$ = new_node(EXPR, (node*[]){ $1, $2, $3, NULL }); } 
| simpleExpr      { $$ = new_node(EXPR, (node*[]){ $1, NULL }); } 
; 

simpleExpr 
: term addop simpleExpr   { $$ = new_node(EXPR, (node*[]){ $1, $2 ,$3, NULL }); } 
| term       { $$ = new_node(EXPR, (node*[]){ $1, NULL }); } 
; 

term 
: factor mulop term    { $$ = new_node(EXPR, (node*[]){ $1, $2, $3, NULL }); } 
| factor       { $$ = new_node(EXPR, (node*[]){ $1, NULL }); } 
; 

factor 
: IVALUE       { $$ = new_int_node(INT_CONST, $1); } 
| FVALUE       { $$ = new_float_node(REAL_CONST, $1); } 
| TRUE       { $$ = new_int_node(BOOL_CONST, 1); } 
| FALSE       { $$ = new_int_node(BOOL_CONST, 0); } 
| ident       { $$ = $1; } 
| '!' factor      { $$ = new_node(EXPR, (node*[]){ $2, NULL }); } 
| '-' factor      { $$ = new_node(EXPR, (node*[]){ $2, NULL }); } 
| '(' expr ')'     { $$ = new_node(EXPR, (node*[]){ $2, NULL }); } 
; 

mulop 
: MULOP       { $$ = new_int_node(OP, $1); } 
; 

addop 
: ADDOP       { $$ = new_int_node(OP, $1); } 
; 

relop 
: RELOP       { $$ = new_int_node(OP, $1); } 
; 

%% 

int main(int argc, char **argv) {  
    if (argc > 1) 
     yyin = fopen(argv[1], "r"); 
    else 
     yyin = stdin; 
    yyparse(); 
    printf("\nCOMMENT-ANALYSIS:\n"); 
    printf("Total number of comments: %d\n", total_comments_number); 
    printf("Maximum nested comment level: %d\n", max_comment_level); 
    printf("\n"); 

    printNode(root); 

    return 0; 
} 

좀 구조체와 열거 형을 decleared하는 헤더 :

#ifndef AST_TYPES_H 
#define AST_TYPES_H 

typedef enum { 
    COMP_STMT = 0, 
    ASSIGN, 
    ASSIGN_STMT, 
    IF_STMT, 
    FOR_STMT, 
    WHILE_STMT, 
    STATEMENT, 
    STATEMENT_LIST, 
    CONST, 
    VAR, 
    ARRAY, 
    VAR_LIST, 
    TYPE, 
    EXPR, 
    SIMPLE_EXPR, 
    INT_CONST, 
    REAL_CONST, 
    BOOL_CONST, 
    STRING_CONST, 
    IDENTIFIER, 
    OP, 
    IOFUNC, 
    IOFUNCCALL, 
    PARAM_LIST, 
    DECLARATION, 
    VAR_LIST_TYPE, 
    NONE, 
} node_type; 

typedef enum { 
    PLUS = 0, 
    MINUS, 
    MUL, 
    DIV, 
    MOD, 
    LT, 
    LE, 
    GT, 
    GE, 
    EQ, 
    NE, 
    AND, 
    OR, 
    PLUSPLUS, 
    MINUSMINUS, 
    NOT, 
} operator; 

typedef union _node_value{ 
    int iValue; /*integer, true, false, compOp, addOp, mulOp */ 
    float fValue; /*number*/ 
    char* identifier; /*identifier*/ 
    /* list of BNF right-hand side symbols of nonterminal type */ 
    struct _node **body; 
} node_value; 

typedef struct _node { 
    node_type type; 
    int size; 
    node_value value; 
} node; 

void printNode(node *the_node); 
operator getEnum(char *value); 
char *printEnum(node_type type); 
node* new_none(); 
node* new_int_node(node_type type, int value); 
node* new_float_node(node_type type, float value); 
node* new_string_node(node_type type, char *value); 
node* new_node(node_type type, node **nodes); 

#endif //AST_TYPES_H 

headerfunctions을 구현하는 C-파일 :

나는이 같은 프로그램을 컴파일 : 너무 많은

/* This program that implements a few well-known algorithms */ 

{ int x, y, z; 
    final int n = 10; 
    int a[n]; 

    // greatest common divisor 
    { read(x, y); 
    while(x * y != 0) 
     if(x > y) 
     x = x - y; 
     else y = y - x; 
    if(x == 0) 
     write("gcd = ", y); 
    else write("gcd = ", x); 
    } 

    // factorial calculation 
    { read(x); 
    y = 1; 
    for(z = 2; z <= x; z++) 
     y = y * z; 
    write(x, " != ", y); 
    } 


    // prime number verification 
    { int k; 
    boolean prime; 
    read(x); 
    k = 2; 
    prime = true; 
    while((k < x/2) && prime) { 
     if(x % k == 0) 
     prime = false; 
     k++; 
    } 
    write(x, " is prime is ", prime); 
    } 

    // maximum array element 
    { int i, max; 
    for(i = 0; i < n; i++) 
     read(a[i]); 
    max = a[0]; 
    for(i = 0; i < n; i++) 
     if(max > a[i]) 
     max = a[i]; 
    write("max = ", max); 
    } 


    // bubble sort 
    { boolean k; 
    float r; 
    int i; 
    k = true; 
    while(k) { 
     k = false; 
     for(i = 0; i < n-1; i++) 
     if(a[i] > a[i+1]) { 
      b = a[i]; 
      a[i] = a[i+1]; 
      a[i+1] = b; 
      k = true; 
     } 
    } 
    write("sorted array: "); 
    for(i = 0; i < n; i++) 
     write(a[i]); 
    } 
} 
+1

주의 시도 line :'if (argc> 0)'가 올바르지 않습니다. argv는 argv []의 첫 번째 엔트리가 프로그램을 호출하는 데 사용 된 경로/이름이 될 것이므로 항상 0보다 커야합니다. 제안 :'if (argc> 1)' – user3629249

+0

내 코드를 살펴 보는 Thx. 그리고 실제로 이것은 잘못된 오류입니다. 그러나 여전히 세분화 오류로 인해 문제가 변경되지는 않습니다. bison이나 flex에 대해 많이 알 필요는 없기 때문에이 오류는 malloc의 잘못된 사용 일 수도 있습니다 ... Java 프로그램은 내 프로그램에 의해 컴파일되어야하는 예제 코드 일뿐입니다. – Harald

+1

: GCD 코드에는'{'braces'}'가 필요합니다. 알고리즘은'-' 연산자로 구현 된 분할 알고리즘처럼 매우 비효율적입니다. 예를 들어, 여러분의 알고리즘은'gcd (2000, 15)'를 계산하기 위해 132 개의 루프를 사용합니다. 반면에 모듈러스 연산자'%'를 사용하는 알고리즘은 1 루프 (2 회 연산은'while' 루프입니다)를 사용합니다. –

답변

3

는 수행

gdb run 

는 다음 (gdb) 프롬프트에서 같은 끝나는 출력을 생성

run < sample.java 

을 수행

Program received signal SIGSEGV, Segmentation fault. 
0x00007ffff7a66c36 in vfprintf() from /lib/x86_64-linux-gnu/libc.so.6 
(gdb) 

은 문제가 printf에게 전달되었음을 알려줍니다. 여기에서, 스택 백 트레이스를 얻기 위해 bt 명령을 사용하여이 상태로 있었는지

#0 0x00007ffff7a66c36 in vfprintf() from /lib/x86_64-linux-gnu/libc.so.6 
#1 0x00007ffff7a6f299 in printf() from /lib/x86_64-linux-gnu/libc.so.6 
#2 0x0000000000404b14 in printNode (the_node=0x60c870) at abst.c:178 
#3 0x0000000000404b94 in printNode (the_node=0x60c930) at abst.c:186 
#4 0x0000000000404b94 in printNode (the_node=0x60c970) at abst.c:186 
#5 0x0000000000404b94 in printNode (the_node=0x60ca70) at abst.c:186 
#6 0x0000000000404b94 in printNode (the_node=0x60d190) at abst.c:186 
#7 0x0000000000404b94 in printNode (the_node=0x60d6d0) at abst.c:186 
#8 0x0000000000404b94 in printNode (the_node=0x60d710) at abst.c:186 
#9 0x0000000000404b94 in printNode (the_node=0x60d750) at abst.c:186 
#10 0x0000000000404b94 in printNode (the_node=0x613500) at abst.c:186 
#11 0x0000000000404b94 in printNode (the_node=0x613540) at abst.c:186 
#12 0x00000000004024a7 in main (argc=1, argv=0x7fffffffe0a8) at yacc.y:208 

볼 수 있습니다. 당신이 사물의 값을 인쇄 할 수 있습니다 여기에서

#2 0x0000000000404b14 in printNode (the_node=0x60c870) at abst.c:178 
178    printf("%s with Identifier: %s\n", printEnum(the_node->type), the_node->value.identifier); 

: 당신은에있어 - 지금 (위의 목록에서 아래로 스택 추적에서 "최대"두 개의 프레임을 이동) 두 번 up 명령을 사용하여 p 명령 : (즉시) 문제가 무엇인지를 알려줍니다

(gdb) p the_node->value 
$1 = { 
    iValue = 2, 
    fValue = 2.80259693e-45, 
    identifier = 0x2 <error: Cannot access memory at address 0x2>, 
    body = 0x2 
} 

- 당신이 쓰레기 포인터를 전달하는, 그래서 당신은 실제로 아마 iValue 무엇 보유하고있는 노동 조합에서 identifier를 액세스하는 printf으로 인해 충돌이 발생합니다. 이 말했다 : 나는 렉스 및 yacc를 모르는, 그리고 내가 자바와 함께 일 이후 수십 년 수 있습니다

GDB 명령에 대한 자세한 내용

help 명령 ...

+0

오랫동안 내 코드에서 검색 한 결과, 들소가 yylval에서 작동하지 않는다는 것을 알았습니다. 대신 나는 $ -Symbols를 사용하고 올바른 유형을 설정해야합니다. 당신의 대답은 제가이 실수를 찾도록 도왔습니다. 이제 모든 것이 효과가 있다고 생각합니다. 나는 내일 다시보고 할 것이다. – Harald

+0

내 코드에서 모든 오류가 발견되었습니다. 컴퓨터에서 코드를 실행하고 모르는 일부 gdb 명령으로 모든 오류를 찾는 데 도움이 되었기 때문에 대답을 수락합니다. 나중에 돌아와서 내가 작성한 모든 실수를 요약해서 써 보겠습니다. – Harald

3

정말 많은 코드입니다 :

bison -d --debug --verbose yacc.y 
flex lex.l 
gcc yacc.tab.c lex.yy.c abst.c -std=c11 -Wall -o run -ll -g 
./run < sample.java 

이 컴파일해야 자바 문법에 대한 샘플 파일입니다 간단한 육안 검사. 아마도 디버거를 사용하여 프로그램을 실행하고 bison 추적을 활성화하거나 노드 구축 기능이 예상대로 작동하는지 확인하기위한 테스트 코드를 작성해야합니다. (필자는 세 가지로 가고 싶어.)

밖으로 뛰어 않는 것은 당신이이 같은 규칙의 수를 가지고있다

: 터미널과 관련된 몇 가지 의미 값이 있다고 가정

BOOLEAN     { $$ = new_node(TYPE, (node*[]){ $1, NULL }); } 

을 간단한 키워드를 나타내는 토큰. 그러나, 키워드 토큰 유형을

"boolean"     { count(); return BOOLEAN; } 

를 반환 플렉스 규칙은 yylval를 설정하지 않습니다. 사실, 플렉스 규칙은 항상 yylval을 설정하지 않으므로 항상 NULL입니다. (글로벌 변수이므로 0으로 초기화 될 것입니다.) 위의 들소 규칙에서 type 노드를 새로 만들 때 사용 된 node*이 참조 해제 된 경우 세그먼트가 생깁니다. 코드를 통해 참조 해제되었는지 여부를 추적하지 않았으므로 문제를 설명하지 못할 수도 있습니다.

+0

신에게 대답 해줘서 고맙다 : D 나는 내일이 시험을 치러야한다 :) 나는 다시보고 할 것이다. – Harald

+0

코드를 편집하여 yylval을 포함 시켰습니다. 그러나 세분화 오류가 남아 있습니다. 나는 아직 초기화되지 않은 노드가있는 porblem이 있는지 확인합니다. @rici, 다시 내 코드를보고 응답 해 주시겠습니까? 나는 내가 무엇을 향상시킬 수 있는지 모른다. – Harald

3
  1. .y 파일의 어느 곳에서나 yytext을 신뢰할 수 없습니다. yacc은 LALR (1) 파서이므로 이미 사라졌습니다. 당신은 yylval 노동 조합의 멤버로 렉서에서 동적 메모리의 조각에 복사하고, 할당해야합니다

    yylval.text = strdup(yytext); 
    
  2. 당신이 C++를 작성하는 것처럼, 당신은 노드 형 변수를 사용할 수 없습니다. 노드 클래스의 패밀리을 작성하고 node에서 상속받으며 각 특정 경우에 수행해야하는 작업을 수행하는 생성자 및 가상 메소드가있는 장비를 작성해야합니다.대신 명령 줄에서 직접 프로그램을 실행

+0

나는 당신과 rici와 같은 코드를 업데이트했다. 코드는 C 스타일로 유지되므로 gcc를 계속 사용하여 파일을 컴파일 할 수 있습니다. 몇 가지 큰 오류가 남아 있어야합니다. 또한 코드를 다시 볼 수 있으면 행복 할 것입니다. – Harald

+0

* yacc *이 이미 수행 한 작업을 다시하지 않으면 훨씬 간단 해집니다. 자신 만의 토큰 Enum을 정의 할 필요는 없습니다. 이미 y.tab.h에 있습니다. 운영자 중 하나도 필요하지 않습니다. 단일 문자 연산자에 대한 모든 논문 규칙은'. 'yytext [0];'을 반환하고, 문법에서 직접''+ ','- '' 등으로 사용합니다.모든 것을 훨씬 더 읽기 쉽도록하고, 코드가 훨씬 적습니다. 디버거에서이 코드를 실행하고 오류가 발생한 위치를 알려야합니다. – EJP

+0

이것은 정말 좋은 개선입니다! 나는 내 코드를 바꿀 것이다. – Harald