# Lexical Analysis(Scanner) Report

* 주하진, 2024062806

## Compilation Environment and Method

주어진 `Makefile`을 이용하여 C파일을 컴파일함.
C파일은 `gcc`를 이용해서 컴파일한다.
`Makefile`에서 산출되는 실행파일은 `cminus_cimpl`과 `cminus_lex`가 있으며 각각 `main.c util.c scan.c`, `main.c util.c lex.yy.c`를 컴파일한 오브젝트 파일을 필요로 한다.

`lex.yy.c`는 `flex -o lex.yy.c cminus.l`을 통해 생성된다.

## C-Minus Language

C-Minus에서 필요한 토큰타입변수와 그에 대한 설명은 다음과 같다.

**특수 토큰**

* `ENDFILE`: 파일끝
* `ERROR`: 에러

**키워드 토큰**

* `IF`: `if`
* `THEN`: `then`
* `ELSE`: `else`
* `WHILE`: `while`
* `RETURN`: `return`
* `INT`: `int`
* `VOID`: `void`

**가변길이 토큰**

* `ID`: 식별자
* `NUM`: 숫자

**기호 토큰**

* `ASSIGN`: `=`
* `EQ`: `==`
* `NE`: `!=`
* `LT`: `<`
* `LE`: `<=`
* `GT`: `>`
* `GE`: `>=`
* `PLUS`: `+`
* `MINUS`: `-`
* `TIMES`: `*`
* `OVER`: `/`
* `LPAREN`: `(`
* `RPAREN`: `)`
* `LBRACE`: `[`
* `RBRACE`: `]`
* `LCURLY`: `{`
* `RCURLY`: `}`
* `SEMI`: `;`
* `COMMA`: `,`

**토큰에 포함되지 않는 스펙**

* `/*` - `*/`: 주석 (토큰에 포함하지 않음)

위와 같은 토큰 타입을 기반으로 토크나이징하는 것이 목적이다.

### Using `scan.c`

`scan.c`에서는 올바른 `getToken`을 작성해야 한다.

`getToken`을 작성하기에 앞서 전이가능한 `STATE`를 작성한다. 특히 `<`, `>`, `!`, `=`, `/`의 경우에는 단 한 글자만 받는게 아니라 그 다음 문자에 따라 산출할 토큰이 달라질 수 있으므로 그에 따른 `STATE`를 만든다.

결과적으로 필요한 STATE는 다음과 같다.

```
START, INOVER, INCOMMENT, ASTERCOMMENT, INASSIGN, INLT, INGT, INNE, INNUM, INID, DONE
```

이를 이용해 `getToken`의 DFA를 작성할 수 있다.

```mermaid
stateDiagram-v2
    START
    state comment {
        INOVER
        INCOMMENT
        ASTERCOMMENT
    }
    
    
    INASSIGN
    INLT
    INGT
    INNE
    state multichar {
    INNUM
    INID
    }
    

    state done {
        DONE
    }
    
    

    START --> INNUM: isdigit
    INNUM --> INNUM: isdigit
    INNUM --> DONE: else with unget

    START --> INID: isalpha
    INID --> INID: isalnum
    INID --> DONE: else with unget

    START --> INASSIGN: =
    INASSIGN --> DONE: =
    INASSIGN --> DONE: else with unget

    START --> INLT: \<
    INLT --> DONE: =
    INLT --> DONE: else with unget

    START --> INGT: \>
    INGT --> DONE: =
    INGT --> DONE: else with unget

    START --> INNE: !
    INNE --> DONE: =
    INNE --> DONE: else with unget and</br> return ERROR


    START --> INOVER: /
    INOVER --> INCOMMENT: \*
    INCOMMENT --> ASTERCOMMENT: \*
    ASTERCOMMENT --> INCOMMENT: else
    ASTERCOMMENT --> START: /

```

이를 통해 `scan.c`를 작성하면 된다.

이때 `tokenString`은 항상 넣되 (하지만 NUM, ID 토큰에서만 필요함) comment때만 안 넣으면 된다. `unget`할때도 안넣어야 한다.

### Using Lex (cminus.l)

tiny의 lex파일처럼 간단하게 넣고 컴파일하면 된다.

하나 중요한 점은 comment를 구현할 때, `prev`와 `now`를 각 과정에서 계속 업데이트 해가면서 `now == '/' && prev == '*'` 일때까지 계속 `input()`을 받아주면 된다.

## Examples & Result


<table>
<tr>
<th>cminus file</th>
<th>result text file</th>
</tr>
<tr>
<td>

```c { .line-numbers }
/* A program to perform Euclid's
   Algorithm to computer gcd */

int gcd (int u, int v)
{
	if (v == 0) return u;
	else return gcd(v,u-u/v*v);
	/* u-u/v*v == u mod v */
}

void main(void)
{
	int x; int y;
	x = input(); y = input();
	output(gcd(x,y));
}

```

</td>
<td>

```scanres

C-MINUS COMPILATION: ./test1.cm
	4: reserved word: int
	4: ID, name= gcd
	4: (
	4: reserved word: int
	4: ID, name= u
	4: ,
	4: reserved word: int
	4: ID, name= v
	4: )
	5: {
	6: reserved word: if
	6: (
	6: ID, name= v
	6: ==
	6: NUM, val= 0
	6: )
	6: reserved word: return
	6: ID, name= u
	6: ;
	7: reserved word: else
	7: reserved word: return
	7: ID, name= gcd
	7: (
	7: ID, name= v
	7: ,
	7: ID, name= u
	7: -
	7: ID, name= u
	7: /
	7: ID, name= v
	7: *
	7: ID, name= v
	7: )
	7: ;
	9: }
	11: reserved word: void
	11: ID, name= main
	11: (
	11: reserved word: void
	11: )
	12: {
	13: reserved word: int
	13: ID, name= x
	13: ;
	13: reserved word: int
	13: ID, name= y
	13: ;
	14: ID, name= x
	14: =
	14: ID, name= input
	14: (
	14: )
	14: ;
	14: ID, name= y
	14: =
	14: ID, name= input
	14: (
	14: )
	14: ;
	15: ID, name= output
	15: (
	15: ID, name= gcd
	15: (
	15: ID, name= x
	15: ,
	15: ID, name= y
	15: )
	15: )
	15: ;
	16: }
	17: EOF
```


</td>
</tr>


<tr>
<td>

```c {.line-numbers}
void main(void)
{
	int i; int x[5];
	
	i = 0;
	while( i < 5 )
	{
		x[i] = input();

		i = i + 1;
	}

	i = 0;
	while( i <= 4 )
	{
		if( x[i] != 0 )
		{
			output(x[i]);
		}
	}
}

```

</td>

<td>

```scanres

C-MINUS COMPILATION: ./test2.cm
	1: reserved word: void
	1: ID, name= main
	1: (
	1: reserved word: void
	1: )
	2: {
	3: reserved word: int
	3: ID, name= i
	3: ;
	3: reserved word: int
	3: ID, name= x
	3: [
	3: NUM, val= 5
	3: ]
	3: ;
	5: ID, name= i
	5: =
	5: NUM, val= 0
	5: ;
	6: reserved word: while
	6: (
	6: ID, name= i
	6: <
	6: NUM, val= 5
	6: )
	7: {
	8: ID, name= x
	8: [
	8: ID, name= i
	8: ]
	8: =
	8: ID, name= input
	8: (
	8: )
	8: ;
	10: ID, name= i
	10: =
	10: ID, name= i
	10: +
	10: NUM, val= 1
	10: ;
	11: }
	13: ID, name= i
	13: =
	13: NUM, val= 0
	13: ;
	14: reserved word: while
	14: (
	14: ID, name= i
	14: <=
	14: NUM, val= 4
	14: )
	15: {
	16: reserved word: if
	16: (
	16: ID, name= x
	16: [
	16: ID, name= i
	16: ]
	16: !=
	16: NUM, val= 0
	16: )
	17: {
	18: ID, name= output
	18: (
	18: ID, name= x
	18: [
	18: ID, name= i
	18: ]
	18: )
	18: ;
	19: }
	20: }
	21: }
	22: EOF

```

</td>
</tr>

</table>