파싱 - 2

김현우·2025년 2월 8일
0
post-thumbnail

해야할것

1. expression statement 정의
2. go에서 String 역할을 할 함수포인터 구현
3. 메모리 free 시킬 방법

1번

ast.h

typedef struct _expressionStatement {
    Expression expression;
    Token* token;
    int is_valid;
}ExpressionStatement;


ast.c

ExpressionStatement* newExpressionStatement()
{
    ExpressionStatement* es = (ExpressionStatement*)malloc(sizeof(ExpressionStatement));
    es->expression.node.TokenLiteral = expressionTokenLiteral;
    es->expression.node.statementType = EXPRESSIONSTMT;
    es->is_valid = 1;
    es->expression.node.PrintString = printExpressionStmt;
    return es;
}

이미 코드가 나와있었기에 만들기 쉬웠음

다만 expression이 포인터가아닌 그냥 구조체로 일단 사용했음
따라서 NULL 비교가 불가하기에 is_valid 추가시킴

2번

const char* printProgram(void* self)
{
    Program* p = (Program*)self;

    int len = p->statementsNum;
    char* str = NULL;
    for (int i = 0; i < len; i++) {
        append_string(&str, p->statements[i]->node.PrintString(p->statements[i]));
    }
    return str;
}

const char* printLetStmt(void* self)
{
    LetStatement* ls = (LetStatement*)self;

    char* str = NULL;
    append_string(&str, ls->statement.node.TokenLiteral(ls));
    append_string(&str, " ");
    append_string(&str, ls->name->node.TokenLiteral(ls->name));
    append_string(&str, " = ");

    if (ls->value != NULL) {
        append_string(&str,ls->value->node.TokenLiteral(ls->value));
    }

    append_string(&str, ";");

    return str;
}

const char* printReturnStmt(void* self)
{
    ReturnStatement* rs = (ReturnStatement*)self;
    char* str = NULL;

    append_string(&str, rs->statement.node.TokenLiteral(rs));
    append_string(&str, " ");

    if (rs->returnValue != NULL) {
        append_string(&str, rs->returnValue->node.TokenLiteral(rs->returnValue));
    }

    append_string(&str, ";");
    return str;
}

const char* printExpressionStmt(void* self)
{
    ExpressionStatement* es = (ExpressionStatement*)self;

    if (es->is_valid == 1) {
        return es->expression.node.TokenLiteral(es);
    }
    return "";
}

const char* printIdentifier(void* self)
{
    Identifier* i = (Identifier*)self;

    return i->value;
}

void append_string(char** dest, const char* src) {
    if (!src || !dest) return;  // src 또는 dest가 NULL인지 확인

    size_t old_len = (*dest ? strlen(*dest) : 0);
    size_t src_len = strlen(src);
    size_t new_len = old_len + src_len + 1;  // 널 종료 문자 포함

    char* new_str = (char*)realloc(*dest, new_len);
    if (!new_str) {
        perror("Memory allocation failed");
        exit(1);
    }

    if (old_len == 0) {
        // 기존 문자열이 없을 경우 strcpy_s 사용
        if (strcpy_s(new_str, new_len, src) != 0) {
            perror("strcpy_s failed");
            exit(1);
        }
    }
    else {
        // 기존 문자열이 있을 경우 strcat_s 사용
        if (strcat_s(new_str, new_len, src) != 0) {
            perror("strcat_s failed");
            exit(1);
        }
    }

    *dest = new_str;
}
문자열을 동적으로 추가해서 리턴하게 끔 만들어줌
책 내용 그대로 따라친거라 딱히 말할 내용없는듯

다만 문자열을 동적으로 추가하는 함수는 하나 추가해줌
String 관련 함수들이 없는게 참 불편한듯

3번

처음에 동적할당을 막 시켜놓으니 메모리를 해제 시키는 것에 좀 애를 먹었음

트리 구조이니 타고타고 들어가서 후위순회 방식으로 해야한다고 생각

일단 구조부터 파악을 하자 싶어서 코드를 다시 살펴봄

1. parser에는 errors와 lexer가 붙어있다.
2. lexer에는 input이 동적할당 되어있음

이 둘은 이렇게 따로 처리를 하고

program을 루트 노드로 Let, Return 등이 붙어있음
이를 비교해서 Let일때 name,token,expressionStmt를 free해줘야함

void freeToken(Token* token)
{
	if (token->literal != NULL)
		free(token->literal);

	free(token);
}

void freeLexer(Lexer* l)
{
    if (l->input != NULL)
        free(l->input);

    free(l);
}

void freeParser(Parser* p)
{
    if(p->l!=NULL)
        freeLexer(p->l);

    for (int i = 0; i < p->errorsNum; i++) {
        free(p->errors[i]);
    }

    free(p->errors);
}

void freeProgram(Program* p)
{
    for (int i = 0; i < p->statementsNum; i++) {
        int type = p->statements[i]->node.statementType;
        switch (type)
        {
        case LET:
            freeLetStmt((LetStatement*)p->statements[i]);
            break;
        case RETURN:
            break;
        case IDENTIFIER:
            break;
        case EXPRESSIONSTMT:
            break;

        }
    }

    free(p->statements);
    free(p);
}
void freeLetStmt(LetStatement* ls)
{
    freeToken(ls->token);

    if (ls->name != NULL)
        freeIdentifier(ls->name);

    if (ls->value != NULL)
        freeExpressionStmt(ls->value);

    free(ls);
}
void freeIdentifier(Identifier* i)
{
    freeToken(i->token);
    free(i);
}
void freeExpressionStmt(ExpressionStatement* es)
{
    free(es->token);
    free(es);
}
profile
학생

0개의 댓글

관련 채용 정보