1-1.tokenization
관련 PR : #33
token.c arr.c libft/lst*.c
토큰화 (tokenization)는 입력으로 받아온 문자열 형태의 데이터를 해석할 수 있는 token으로 만드는 과정이다.
아래의 구조체 struct s_token을 사용하여 토큰화를 진행하였다.
token 구조체는 생성될 때 libft
에 구현된 연결리스트 node
의 content
에 저장된다.
구조체 정보
typedef struct s_token
{
t_ttype type;
char *str;
} t_token;
enum e_token_type
( t_ttype
) 정보
typedef enum e_token_type
{
T_WORD, // space 문자와 아래 문자들을 제외한 모든 문자
T_PIPE, // |
T_IO, // <<, <, >>, >
T_PAREN, // (, )
T_OPER // &&, ||
T_QUOTE, // ", '
T_SPACE,
T_DOLLER, // $
T_ENVP
} t_ttype;
처음에는 enum e_token_type
에서 실제로 사용될 수 있는 token
에 대한 정보만 남겨두려고 했는데
코드를 작성하다 보니 이후에 쓰이는 경우가 생겨 필요한 모든 token type
을 추가해서 총 9개가 되었다.
구조체를 활용하는 부분은 이곳에 자세히 작성해두었다.
구현 과정
토큰화를 진행할 때 구조체 리스트를 어떤 방법으로 생성할 지에 대해 굉장히 고민이 많았다.
팀원과 함께 같이 상의하면서 배열을 활용하기로 했다.
입력 문자열 str
과 동일한 크기의 int
배열 arr
을 사용하여 각 문자에 해당하는 token type
을 매기는 방식이다.
token type을 매길 때 사용하는 함수는 이후에 재사용하기 때문에 함수 포인터를 활용했다.
검사하는 token에 대한 정보들은 다음과 같이 Norm을 고려하여 const 배열로 선언해주었다.
symbol에서 작성된 순서대로 우선순위가 높다. 여기서는 “
이 우선순위가 가장 높게 되어있다.
cust_idx에서 십의 자리는 enum e_token_type
에 정의된 type을 의미하고, 일의 자리는 symbol의 길이 확인용으로 아래와 같이 사용하였다.
const char symbol[12][3] = {"\"", "\'", "&&", "||", "(", ")", \
"<<", "<", ">>", ">", "|", " "};
const int cust_idx[] = {50, 52, 41, 43, 30, 32, \
21, 22, 23, 24, 10, 60};
// len = cust_idx % 10 % 2 + 1;
배열을 cust_idx에 맞게 다 채우고 나면 따옴표 처리를 진행했다.
따옴표로 감싸는 문자열에 대해서는 해석되지 않도록 모두 T_WORD
type으로 채워주었다.
그리고 나서 만들어진 int
배열을 바탕으로 단방향 연결리스트를 만들어준다.
만들 때 단방향 연결리스트의 head
를 생성해두어서 head
는 있고 tail
은 없는 구조로 되어있다.
단방향 연결리스트의 각 node
의 token
정보는 앞에서 본 구조체 형태처럼 type
과 그에 해당하는 문자열(str
)이 동적할당되어 들어있게 된다.
1-2.check syntax error
관련 PR: #44
check_syntax.c, check_type.c
token으로 이루어진 단방향 연결리스트는 이후 이진 트리 형태로 변경한다.
이진 트리 형태로 변경하기 전에 syntax error를 검사한다.
검사 기준
- 괄호가 올바른 짝을 이루고 있는가?
)(
,(()
,)()
,))
와 같은 경우는 올바르지 않음- error message:
minishell: syntax error: invalid parenthesis pair
- redirection(
T_IO
) 뒤에 file명(T_WORD
)이 입력되었는가?- error message:
minishell: syntax error: redirection file does not exist
- error message:
- 괄호 chunk가
&&
,||
의 앞 또는 뒤에 위치하는가?- 괄호 앞 뒤는 괄호를 하나의 chunk로 보고 검사를 진행한다.
(( cmd ))
,()
,(())
와 같은 경우는 올바르지 않음- error message :
minishell: syntax error: invalid parenthesis position
- dsv(
&&
,||
,|
)라면 dsv 기준 왼쪽 오른쪽에 cmd가 입력되었는가?- error message
minishell: syntax error: &&
minishell: syntax error: ||
minishell: syntax error: |
- error message
- cmd가 하나 이상 들어왔는가?
- 스페이스만 들어왔을 경우, 또는 redirection만 입력될 경우는 올바르지 않음
- error message :
minishell: syntax error: command not found
각 기준은 번호 순서대로 우선순위를 가진다.
따라서 먼저 검사되는 기준에 부합하지 않을 경우, 그에 해당하는 에러 메시지를 출력하고 새로운 입력을 받게 된다.
subject에서 요구하는 괄호는 &&, || 의 우선순위를 표현하는 것에 의의가 있다고 생각해서 3번에 대한 검사 기준을 설정해두었다.
그리고 bash에서는 cmd가 존재하지 않는 redirection만 들어온 입력의 경우에도 실행되지만, 우리의 minishell에서는 syntax error로 처리했다.
'study > 42Seoul' 카테고리의 다른 글
[C] stat / lstat / fstat 함수 (0) | 2023.01.06 |
---|