add syntax
This commit is contained in:
@@ -8,13 +8,14 @@
|
|||||||
background-color: white;
|
background-color: white;
|
||||||
font-family: NanumGothic;
|
font-family: NanumGothic;
|
||||||
}
|
}
|
||||||
font-size: 11pt;
|
font-size: 10pt;
|
||||||
font-family: NanumMyeongjo;
|
font-family: NanumMyeongjo;
|
||||||
.language-scanres {
|
.language-scanres {
|
||||||
font-size: 6pt;
|
font-size: 6pt;
|
||||||
}
|
}
|
||||||
ol, ul {
|
ol, ul {
|
||||||
margin-top: 0.0pt;
|
margin-top: 0.0pt;
|
||||||
|
margin-bottom: 0.2rem;
|
||||||
}
|
}
|
||||||
p {
|
p {
|
||||||
margin-bottom: 0.4rem;
|
margin-bottom: 0.4rem;
|
||||||
|
|||||||
74
notes/4.md
74
notes/4.md
@@ -68,3 +68,77 @@ Language usually have basic types aka primitive types. Using these types to buil
|
|||||||
There are two options:
|
There are two options:
|
||||||
1. Implement a method `Equals(T1, T2)`.
|
1. Implement a method `Equals(T1, T2)`.
|
||||||
It must compare type trees of T1 and T2. For OOP languages also need sub-types
|
It must compare type trees of T1 and T2. For OOP languages also need sub-types
|
||||||
|
|
||||||
|
|
||||||
|
### Type Checking Methodology
|
||||||
|
Type checking means verifying whether expressions are given proper types
|
||||||
|
1. Implement using Syntax-Directed Definitions(SDD)
|
||||||
|
2. First build the AST, then implement type checking by recursive traversal of the AST nodes
|
||||||
|
|
||||||
|
#### SDD
|
||||||
|
|
||||||
|
SDD associates semantic rules for the productions in the CFG. It checks types based on the semantic rules associated with the production rules.
|
||||||
|
|
||||||
|
#### AST Traversal
|
||||||
|
|
||||||
|
Type Checking During AST Traversal.
|
||||||
|
|
||||||
|
중간에 새로운 타입이 생길 수 있음.
|
||||||
|
|
||||||
|
By Recursive Traversal of the AST nodes, inferencing types of AST nodes.
|
||||||
|
|
||||||
|
### Inference
|
||||||
|
|
||||||
|
$$\frac{\vdash H_1 \vdash H_2 \vdash H_3}{\vdash \text{conclusion}}[\text{rule name}]$$
|
||||||
|
|
||||||
|
#### Soundness
|
||||||
|
|
||||||
|
항상 참이 되는 타입
|
||||||
|
|
||||||
|
$e : T$ means that $e$ is a sound expression of type $T$, that is $e$ is always the type $T$.
|
||||||
|
|
||||||
|
for non expression statements use special unit type (like void or empty type)
|
||||||
|
|
||||||
|
$S: \text{void}$
|
||||||
|
|
||||||
|
#### Proof Tree
|
||||||
|
|
||||||
|
$$\frac{
|
||||||
|
\frac{1 \text{ is a integer literal}}{\vdash 1: \text{int}} [\text{int}] \;
|
||||||
|
\frac{2 \text{ is an integer literal}}{\vdash 2: \text{int}} [\text{int}]
|
||||||
|
}{\vdash 1 + 2 : \text{int}} [\text{int add}]
|
||||||
|
$$
|
||||||
|
|
||||||
|
Proof Tree는 AST를 뒤집은 모양.
|
||||||
|
|
||||||
|
If-then-else는 가질 수 있는데, If-then은 타입을 가질 수 없음.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#### Type Environment
|
||||||
|
|
||||||
|
어떻게 $x$가 variable이라고 할때 어떤 타입을 가지는지 알 수가 없음.
|
||||||
|
|
||||||
|
Type Environment gives types for **free variables**.
|
||||||
|
|
||||||
|
$$O \vdash e: T$$
|
||||||
|
* $O$ is essentially **symbol table**.
|
||||||
|
|
||||||
|
Complex Example of Declaration:
|
||||||
|
```c
|
||||||
|
for (T1 i = 0;;) {
|
||||||
|
exp
|
||||||
|
}
|
||||||
|
```
|
||||||
|
$$\frac{O[T1/i] \vdash \text{exp}: T2}{O\vdash \texttt{for}(i: T1) \set{\text{exp}: T2}}$$
|
||||||
|
|
||||||
|
Complex Example of Class Attrs
|
||||||
|
|
||||||
|
$$O_C(x) = T$$
|
||||||
|
* forall attrs $x: T$ in class C
|
||||||
|
$$O_C$$
|
||||||
|
|
||||||
|
Complex Example of Class Methods
|
||||||
|
|
||||||
|
### Subtyping
|
||||||
|
|
||||||
|
|||||||
379
out/lex.md
Normal file
379
out/lex.md
Normal file
@@ -0,0 +1,379 @@
|
|||||||
|
# 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>
|
||||||
BIN
out/lex.pdf
Normal file
BIN
out/lex.pdf
Normal file
Binary file not shown.
@@ -1,269 +1,135 @@
|
|||||||
# Lexical Analysis(Scanner) Report
|
# Syntax Analysis (Parser) Report
|
||||||
|
|
||||||
* 주하진, 2024062806
|
* 주하진, 2024062806
|
||||||
|
|
||||||
## Compilation Environment and Method
|
## Compilation Environment and Method
|
||||||
|
|
||||||
주어진 `Makefile`을 이용하여 C파일을 컴파일함.
|
주어진 `Makefile`을 이용해 C파일과 `cminus.l`, `cminus.y`를 변환함.
|
||||||
C파일은 `gcc`를 이용해서 컴파일한다.
|
C파일은 `gcc`를 이용하고 `*.l`은 `flex`, `*.y`는 `yacc`을 이용함.
|
||||||
`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`을 통해 생성된다.
|
`Makefile`의 빌드 결과물 `cminus_parser`를 만들기 위해서 `main.c`, `util.c`, `lex.yy.o`, `y.tab.o`를 필요로 한다.
|
||||||
|
|
||||||
## C-Minus Language
|
## C-Minus Parser Implementation
|
||||||
|
|
||||||
C-Minus에서 필요한 토큰타입변수와 그에 대한 설명은 다음과 같다.
|
C-Minus Parser 구현을 위해 다음 세 파일의 큰 수정이 필요했다.
|
||||||
|
|
||||||
**특수 토큰**
|
* `globals.h`
|
||||||
|
* `util.c`, `util.h`
|
||||||
|
* `cminus.y` (Important)
|
||||||
|
|
||||||
* `ENDFILE`: 파일끝
|
### `globals.h`
|
||||||
* `ERROR`: 에러
|
|
||||||
|
|
||||||
**키워드 토큰**
|
여러개의 Kind Enum을 추가하였다.
|
||||||
|
* NodeKind(큰 분류)
|
||||||
|
* StmtKind(Statement의 종류)
|
||||||
|
* ExpKind(Expression의 종류)
|
||||||
|
* DeclKind(Declaration의 종류)
|
||||||
|
* TypeKind(Declaration에서 Type을 구분하기 위해 사용, 실제로 파스트리에 들어가진 않음, var_declaration에서 참조하기 위한 목적.)
|
||||||
|
|
||||||
* `IF`: `if`
|
**StmtKind**
|
||||||
* `THEN`: `then`
|
* IfK: if문
|
||||||
* `ELSE`: `else`
|
* IterK: while문
|
||||||
* `WHILE`: `while`
|
* ReturnK: return문
|
||||||
* `RETURN`: `return`
|
* CompK: 여러개 있는 중괄호(복합) 문
|
||||||
* `INT`: `int`
|
|
||||||
* `VOID`: `void`
|
|
||||||
|
|
||||||
**가변길이 토큰**
|
**ExpKind**
|
||||||
|
* AssignK: 할당문
|
||||||
|
* OpK: 연산자가 포함된 표현식
|
||||||
|
* ConstK: 상수
|
||||||
|
* IdK: 식별자
|
||||||
|
* ArrIdK: 배열 식별자
|
||||||
|
* CallK: 함수 호출
|
||||||
|
|
||||||
* `ID`: 식별자
|
**DeclKind**
|
||||||
* `NUM`: 숫자
|
* FuncK: 함수 선언
|
||||||
|
* VarK: 변수 선언
|
||||||
|
* ArrVarK: 배열 변수 선언
|
||||||
|
* ArrParamK: 배열 매개변수
|
||||||
|
* NonArrParamK: 매개변수
|
||||||
|
|
||||||
**기호 토큰**
|
**TypeKind**
|
||||||
|
* TypeNameK: 선언의 타입
|
||||||
|
|
||||||
* `ASSIGN`: `=`
|
-----
|
||||||
* `EQ`: `==`
|
`TreeNode`를 추가하였다.
|
||||||
* `NE`: `!=`
|
|
||||||
* `LT`: `<`
|
|
||||||
* `LE`: `<=`
|
|
||||||
* `GT`: `>`
|
|
||||||
* `GE`: `>=`
|
|
||||||
* `PLUS`: `+`
|
|
||||||
* `MINUS`: `-`
|
|
||||||
* `TIMES`: `*`
|
|
||||||
* `OVER`: `/`
|
|
||||||
* `LPAREN`: `(`
|
|
||||||
* `RPAREN`: `)`
|
|
||||||
* `LBRACE`: `[`
|
|
||||||
* `RBRACE`: `]`
|
|
||||||
* `LCURLY`: `{`
|
|
||||||
* `RCURLY`: `}`
|
|
||||||
* `SEMI`: `;`
|
|
||||||
* `COMMA`: `,`
|
|
||||||
|
|
||||||
**토큰에 포함되지 않는 스펙**
|
```c
|
||||||
|
typedef struct treeNode {
|
||||||
* `/*` - `*/`: 주석 (토큰에 포함하지 않음)
|
struct treeNode *child[MAXCHILDREN];
|
||||||
|
struct treeNode *sibling;
|
||||||
위와 같은 토큰 타입을 기반으로 토크나이징하는 것이 목적이다.
|
int lineno;
|
||||||
|
NodeKind nodekind;
|
||||||
### Using `scan.c`
|
union {
|
||||||
|
StmtKind stmt;
|
||||||
`scan.c`에서는 올바른 `getToken`을 작성해야 한다.
|
ExpKind exp;
|
||||||
|
DeclKind decl;
|
||||||
`getToken`을 작성하기에 앞서 전이가능한 `STATE`를 작성한다. 특히 `<`, `>`, `!`, `=`, `/`의 경우에는 단 한 글자만 받는게 아니라 그 다음 문자에 따라 산출할 토큰이 달라질 수 있으므로 그에 따른 `STATE`를 만든다.
|
TypeKind type;
|
||||||
|
} kind;
|
||||||
결과적으로 필요한 STATE는 다음과 같다.
|
union {
|
||||||
|
TokenType op;
|
||||||
```
|
int val;
|
||||||
START, INOVER, INCOMMENT, ASTERCOMMENT, INASSIGN, INLT, INGT, INNE, INNUM, INID, DONE
|
char *name;
|
||||||
|
} attr;
|
||||||
|
ExpType type; /* for type checking of exps */
|
||||||
|
} TreeNode;
|
||||||
```
|
```
|
||||||
|
|
||||||
이를 이용해 `getToken`의 DFA를 작성할 수 있다.
|
TreeNode 타입은 ParseTree의 노드를 나타내며, 자식 노드와 형제 노드를 가리키는 포인터 그리고 노드의 kind와 attr, type을 가진다.
|
||||||
|
|
||||||
```mermaid
|
### `util.c`, `util.h`
|
||||||
stateDiagram-v2
|
|
||||||
START
|
`newStmtNode`, `newExpNode`, `newDeclNode`, `newTypeNode` 함수를 추가 및 수정했다. 각각 Statement, Expression, Declaration, Type 노드를 생성하는 함수이다.
|
||||||
state comment {
|
|
||||||
INOVER
|
Type을 출력하기 위해 `printType` 함수를 추가하였다.
|
||||||
INCOMMENT
|
|
||||||
ASTERCOMMENT
|
printTree는 TreeNode를 출력하는 함수이다. nodeKind에 따라 구분하여 출력한다. 이때 type이 필요한 node이면 type도 같이 출력한다.
|
||||||
}
|
|
||||||
|
### `cminus.y`(Important)
|
||||||
|
|
||||||
|
cminus.y에서 토큰의 선언은 다음과 같이 했다.
|
||||||
|
|
||||||
|
```yacc
|
||||||
|
%token IF ELSE WHILE RETURN INT VOID
|
||||||
|
%token EQ NE LT LE GT GE LPAREN RPAREN LBRACE LCURLY RBRACE RCURLY SEMI
|
||||||
|
%token ID NUM
|
||||||
|
|
||||||
|
|
||||||
INASSIGN
|
%left PLUS MINUS
|
||||||
INLT
|
%left TIMES OVER
|
||||||
INGT
|
%right ASSIGN
|
||||||
INNE
|
|
||||||
state multichar {
|
|
||||||
INNUM
|
|
||||||
INID
|
|
||||||
}
|
|
||||||
|
|
||||||
|
%nonassoc THEN
|
||||||
|
%nonassoc ELSE
|
||||||
|
|
||||||
state done {
|
%token ERROR
|
||||||
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`를 작성하면 된다.
|
나머지 부분은 제공된 grammar와 tiny.y의 많은 부분을 참고하여 작성했다.
|
||||||
|
|
||||||
이때 `tokenString`은 항상 넣되 (하지만 NUM, ID 토큰에서만 필요함) comment때만 안 넣으면 된다. `unget`할때도 안넣어야 한다.
|
이때 중요한 부분은 **dangling-else** 부분이다.
|
||||||
|
|
||||||
### Using Lex (cminus.l)
|
```yacc
|
||||||
|
selection_stmt : IF LPAREN expression RPAREN statement %prec THEN {
|
||||||
|
...
|
||||||
|
} | IF LPAREN expression RPAREN statement ELSE statement {
|
||||||
|
...
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
tiny의 lex파일처럼 간단하게 넣고 컴파일하면 된다.
|
`single-if`문의 우선순위를 `ELSE`보다 낮은 `THEN`으로 지정하여 Shift/Reduce Conflict를 해결했다.
|
||||||
|
|
||||||
하나 중요한 점은 comment를 구현할 때, `prev`와 `now`를 각 과정에서 계속 업데이트 해가면서 `now == '/' && prev == '*'` 일때까지 계속 `input()`을 받아주면 된다.
|
## Results
|
||||||
|
|
||||||
## Examples & Result
|
|
||||||
|
|
||||||
|
다음은 테스트 C-Minus 프로그램과 그에 대한 파스트리 출력 결과이다.
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<th>cminus file</th>
|
<th>C-Minus Test Program</th>
|
||||||
<th>result text file</th>
|
<th>Parse Tree Output</th>
|
||||||
</tr>
|
</tr><tr>
|
||||||
<tr>
|
|
||||||
<td>
|
<td>
|
||||||
|
|
||||||
```c { .line-numbers }
|
```c
|
||||||
/* 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)
|
void main(void)
|
||||||
{
|
{
|
||||||
int i; int x[5];
|
int i; int x[5];
|
||||||
@@ -285,95 +151,117 @@ void main(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
```
|
||||||
|
</td><td>
|
||||||
|
|
||||||
|
```txt
|
||||||
|
|
||||||
|
C-MINUS COMPILATION: test.2.txt
|
||||||
|
|
||||||
|
Syntax tree:
|
||||||
|
Function Declaration: name = main, return type = void
|
||||||
|
Void Parameter
|
||||||
|
Compound Statement:
|
||||||
|
Variable Declaration: name = i, type = int
|
||||||
|
Variable Declaration: name = x, type = int[]
|
||||||
|
Const: 5
|
||||||
|
Assign:
|
||||||
|
Variable: name = i
|
||||||
|
Const: 0
|
||||||
|
While Statement:
|
||||||
|
Op: <
|
||||||
|
Variable: name = i
|
||||||
|
Const: 5
|
||||||
|
Compound Statement:
|
||||||
|
Assign:
|
||||||
|
Variable: name = x
|
||||||
|
Variable: name = i
|
||||||
|
Call: function name = input
|
||||||
|
Assign:
|
||||||
|
Variable: name = i
|
||||||
|
Op: +
|
||||||
|
Variable: name = i
|
||||||
|
Const: 1
|
||||||
|
Assign:
|
||||||
|
Variable: name = i
|
||||||
|
Const: 0
|
||||||
|
While Statement:
|
||||||
|
Op: <=
|
||||||
|
Variable: name = i
|
||||||
|
Const: 4
|
||||||
|
Compound Statement:
|
||||||
|
If Statement:
|
||||||
|
Op: !=
|
||||||
|
Variable: name = x
|
||||||
|
Variable: name = i
|
||||||
|
Const: 0
|
||||||
|
Compound Statement:
|
||||||
|
Call: function name = output
|
||||||
|
Variable: name = x
|
||||||
|
Variable: name = i
|
||||||
```
|
```
|
||||||
|
|
||||||
</td>
|
</td></tr>
|
||||||
|
<td><tr>
|
||||||
<td>
|
<td>
|
||||||
|
|
||||||
```scanres
|
```c
|
||||||
|
int main(void){
|
||||||
C-MINUS COMPILATION: ./test2.cm
|
int a;
|
||||||
1: reserved word: void
|
int b;
|
||||||
1: ID, name= main
|
a = (b = 4) + 3;
|
||||||
1: (
|
if(a==b+(c*b+d))
|
||||||
1: reserved word: void
|
while(1)
|
||||||
1: )
|
if(1)
|
||||||
2: {
|
a=2;
|
||||||
3: reserved word: int
|
else a=3;
|
||||||
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><td>
|
||||||
|
|
||||||
|
```txt
|
||||||
|
|
||||||
|
C-MINUS COMPILATION: test.cm
|
||||||
|
|
||||||
|
Syntax tree:
|
||||||
|
Function Declaration: name = main, return type = int
|
||||||
|
Void Parameter
|
||||||
|
Compound Statement:
|
||||||
|
Variable Declaration: name = a, type = int
|
||||||
|
Variable Declaration: name = b, type = int
|
||||||
|
Assign:
|
||||||
|
Variable: name = a
|
||||||
|
Op: +
|
||||||
|
Assign:
|
||||||
|
Variable: name = b
|
||||||
|
Const: 4
|
||||||
|
Const: 3
|
||||||
|
If Statement:
|
||||||
|
Op: ==
|
||||||
|
Variable: name = a
|
||||||
|
Op: +
|
||||||
|
Variable: name = b
|
||||||
|
Op: +
|
||||||
|
Op: *
|
||||||
|
Variable: name = c
|
||||||
|
Variable: name = b
|
||||||
|
Variable: name = d
|
||||||
|
While Statement:
|
||||||
|
Const: 1
|
||||||
|
If-Else Statement:
|
||||||
|
Const: 1
|
||||||
|
Assign:
|
||||||
|
Variable: name = a
|
||||||
|
Const: 2
|
||||||
|
Assign:
|
||||||
|
Variable: name = a
|
||||||
|
Const: 3
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
|
||||||
</table>
|
</table>
|
||||||
Binary file not shown.
46
src/Makefile
46
src/Makefile
@@ -1,37 +1,43 @@
|
|||||||
# Makefile for C-Minus Scanner
|
# Makefile for C-Minus
|
||||||
# ./lex/tiny.l --> ./cminus.l
|
#
|
||||||
|
# ./lex/tiny.l --> ./cminus.l (from Project 1)
|
||||||
|
# ./yacc/tiny.y --> ./cminus.y
|
||||||
|
# ./yacc/globals.h --> ./globals.h
|
||||||
|
|
||||||
CC = gcc
|
CC = gcc
|
||||||
|
|
||||||
CFLAGS = -W -Wall
|
CFLAGS = -W -Wall
|
||||||
|
|
||||||
OBJS = main.o util.o scan.o
|
OBJS = main.o util.o lex.yy.o y.tab.o
|
||||||
OBJS_LEX = main.o util.o lex.yy.o
|
|
||||||
|
|
||||||
.PHONY: all clean
|
.PHONY: all clean
|
||||||
all: cminus_cimpl cminus_lex
|
all: cminus_parser
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
-rm -vf cminus_cimpl cminus_lex *.o lex.yy.c
|
rm -vf cminus_parser *.o lex.yy.c y.tab.c y.tab.h y.output
|
||||||
|
|
||||||
cminus_cimpl: $(OBJS)
|
cminus_parser: $(OBJS)
|
||||||
$(CC) $(CFLAGS) -o $@ $(OBJS)
|
$(CC) $(CFLAGS) $(OBJS) -o $@ -lfl
|
||||||
|
|
||||||
cminus_lex: $(OBJS_LEX)
|
main.o: main.c globals.h util.h scan.h parse.h y.tab.h
|
||||||
$(CC) $(CFLAGS) -o $@ $(OBJS_LEX) -lfl
|
$(CC) $(CFLAGS) -c main.c
|
||||||
|
|
||||||
main.o: main.c globals.h util.h scan.h
|
util.o: util.c util.h globals.h y.tab.h
|
||||||
$(CC) $(CFLAGS) -c -o $@ $<
|
$(CC) $(CFLAGS) -c util.c
|
||||||
|
|
||||||
scan.o: scan.c globals.h util.h scan.h
|
scan.o: scan.c scan.h util.h globals.h y.tab.h
|
||||||
$(CC) $(CFLAGS) -c -o $@ $<
|
$(CC) $(CFLAGS) -c scan.c
|
||||||
|
|
||||||
util.o: util.c globals.h util.h
|
lex.yy.o: lex.yy.c scan.h util.h globals.h y.tab.h
|
||||||
$(CC) $(CFLAGS) -c -o $@ $<
|
$(CC) $(CFLAGS) -c lex.yy.c
|
||||||
|
|
||||||
lex.yy.o: lex.yy.c globals.h util.h scan.h
|
|
||||||
$(CC) $(CFLAGS) -c -o $@ $<
|
|
||||||
|
|
||||||
lex.yy.c: cminus.l
|
lex.yy.c: cminus.l
|
||||||
flex -o $@ $<
|
flex cminus.l
|
||||||
|
|
||||||
|
y.tab.h: y.tab.c
|
||||||
|
|
||||||
|
y.tab.o: y.tab.c parse.h
|
||||||
|
$(CC) $(CFLAGS) -c y.tab.c
|
||||||
|
|
||||||
|
y.tab.c: cminus.y
|
||||||
|
yacc -d -Wcounterexamples -v cminus.y
|
||||||
|
|||||||
328
src/cminus.y
Normal file
328
src/cminus.y
Normal file
@@ -0,0 +1,328 @@
|
|||||||
|
/****************************************************/
|
||||||
|
/* File: tiny.y */
|
||||||
|
/* The TINY Yacc/Bison specification file */
|
||||||
|
/* Compiler Construction: Principles and Practice */
|
||||||
|
/* Kenneth C. Louden */
|
||||||
|
/****************************************************/
|
||||||
|
%{
|
||||||
|
#define YYPARSER /* distinguishes Yacc output from other code files */
|
||||||
|
|
||||||
|
#include "globals.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "scan.h"
|
||||||
|
#include "parse.h"
|
||||||
|
|
||||||
|
#define YYSTYPE TreeNode *
|
||||||
|
static char * savedName; /* for use in assignments */
|
||||||
|
static int savedNumber;
|
||||||
|
static int savedLineNo; /* ditto */
|
||||||
|
static TreeNode * savedTree; /* stores syntax tree for later return */
|
||||||
|
static int yylex(void); // added 11/2/11 to ensure no conflict with lex
|
||||||
|
|
||||||
|
%}
|
||||||
|
|
||||||
|
%token IF ELSE WHILE RETURN INT VOID
|
||||||
|
%token EQ NE LT LE GT GE LPAREN RPAREN LBRACE LCURLY RBRACE RCURLY SEMI COMMA
|
||||||
|
%token ID NUM
|
||||||
|
|
||||||
|
%left PLUS MINUS
|
||||||
|
%left TIMES OVER
|
||||||
|
%right ASSIGN
|
||||||
|
|
||||||
|
%nonassoc THEN
|
||||||
|
%nonassoc ELSE
|
||||||
|
|
||||||
|
%token ERROR
|
||||||
|
|
||||||
|
%% /* Grammar for C-MINUS */
|
||||||
|
|
||||||
|
program : declaration_list
|
||||||
|
{savedTree = $1;};
|
||||||
|
|
||||||
|
declaration_list : declaration_list declaration {
|
||||||
|
YYSTYPE t = $1;
|
||||||
|
if (t != NULL) {
|
||||||
|
while (t->sibling != NULL) {
|
||||||
|
t = t->sibling;
|
||||||
|
}
|
||||||
|
t->sibling = $2;
|
||||||
|
$$ = $1;
|
||||||
|
} else { $$ = $2; };
|
||||||
|
}
|
||||||
|
| declaration { $$ = $1; }
|
||||||
|
;
|
||||||
|
|
||||||
|
declaration : var_declaration {$$ = $1; } | func_declaration { $$ = $1; };
|
||||||
|
|
||||||
|
name_specifier : ID {
|
||||||
|
savedName = copyString(tokenString);
|
||||||
|
savedLineNo = lineno;
|
||||||
|
};
|
||||||
|
|
||||||
|
number_specifier : NUM {
|
||||||
|
savedNumber = atoi(tokenString);
|
||||||
|
savedLineNo = lineno;
|
||||||
|
};
|
||||||
|
|
||||||
|
var_declaration : type_specifier name_specifier SEMI {
|
||||||
|
$$ = newDeclNode(VarK);
|
||||||
|
$$->lineno = savedLineNo;
|
||||||
|
$$->attr.name = savedName;
|
||||||
|
$$->type = $1->type;
|
||||||
|
free($1);
|
||||||
|
} | type_specifier name_specifier LBRACE number_specifier RBRACE SEMI {
|
||||||
|
$$ = newDeclNode(ArrVarK);
|
||||||
|
$$->lineno = savedLineNo;
|
||||||
|
$$->type = IntegerArray;
|
||||||
|
$$->attr.name = savedName;
|
||||||
|
free($1);
|
||||||
|
$$->child[0] = newExpNode(ConstK);
|
||||||
|
$$->child[0]->type = Integer;
|
||||||
|
$$->child[0]->attr.val = savedNumber;
|
||||||
|
};
|
||||||
|
|
||||||
|
type_specifier : INT {
|
||||||
|
$$ = newTypeNode(TypeNameK);
|
||||||
|
$$->type = Integer;
|
||||||
|
}
|
||||||
|
| VOID {
|
||||||
|
$$ = newTypeNode(TypeNameK);
|
||||||
|
$$->type = Void;
|
||||||
|
};
|
||||||
|
|
||||||
|
func_declaration : type_specifier name_specifier {
|
||||||
|
$$ = newDeclNode(FuncK);
|
||||||
|
$$->lineno = savedLineNo;
|
||||||
|
$$->attr.name = savedName;
|
||||||
|
$$->type = $1->type; /* 타입 바로 복사 */
|
||||||
|
} LPAREN params RPAREN compound_stmt {
|
||||||
|
$$ = $3;
|
||||||
|
$$->child[0] = $5; /* params */
|
||||||
|
$$->child[1] = $7; /* compound_stmt */
|
||||||
|
};
|
||||||
|
|
||||||
|
params : param_list { $$ = $1; } | VOID {
|
||||||
|
$$ = newDeclNode(NonArrParamK);
|
||||||
|
$$->type = Void;
|
||||||
|
};
|
||||||
|
|
||||||
|
param_list : param_list COMMA param {
|
||||||
|
YYSTYPE t = $1;
|
||||||
|
if (t != NULL) {
|
||||||
|
while (t->sibling != NULL) {
|
||||||
|
t = t->sibling;
|
||||||
|
}
|
||||||
|
t->sibling = $3;
|
||||||
|
$$ = $1;
|
||||||
|
} else {
|
||||||
|
$$ = $3;
|
||||||
|
};
|
||||||
|
} | param {$$ = $1; };
|
||||||
|
|
||||||
|
param : type_specifier name_specifier {
|
||||||
|
$$ = newDeclNode(NonArrParamK );
|
||||||
|
$$->attr.name = savedName;
|
||||||
|
$$->type = $1->type;
|
||||||
|
} | type_specifier name_specifier LBRACE RBRACE {
|
||||||
|
$$ = newDeclNode(ArrParamK);
|
||||||
|
$$->type = $1->type;
|
||||||
|
$$->attr.name = savedName;
|
||||||
|
};
|
||||||
|
|
||||||
|
compound_stmt : LCURLY local_declarations statement_list RCURLY {
|
||||||
|
$$ = newStmtNode(CompK);
|
||||||
|
$$->lineno = lineno;
|
||||||
|
$$->child[0] = $2;
|
||||||
|
$$->child[1] = $3;
|
||||||
|
};
|
||||||
|
|
||||||
|
local_declarations : local_declarations var_declaration {
|
||||||
|
YYSTYPE t = $1;
|
||||||
|
if (t != NULL) {
|
||||||
|
while (t->sibling != NULL)
|
||||||
|
t = t->sibling;
|
||||||
|
t->sibling = $2;
|
||||||
|
$$ = $1;
|
||||||
|
} else $$ = $2;
|
||||||
|
} | { $$ = NULL; };
|
||||||
|
|
||||||
|
statement_list : statement_list statement {
|
||||||
|
YYSTYPE t = $1;
|
||||||
|
if (t != NULL) {
|
||||||
|
while (t->sibling != NULL)
|
||||||
|
t = t->sibling;
|
||||||
|
t->sibling = $2;
|
||||||
|
$$ = $1;
|
||||||
|
} else $$ = $2;
|
||||||
|
} | { $$ = NULL; };
|
||||||
|
|
||||||
|
statement : expression_stmt { $$ = $1; }
|
||||||
|
| compound_stmt { $$ = $1; }
|
||||||
|
| selection_stmt { $$ = $1; }
|
||||||
|
| iteration_stmt { $$ = $1; }
|
||||||
|
| return_stmt { $$ = $1; }
|
||||||
|
;
|
||||||
|
|
||||||
|
expression_stmt : expression SEMI { $$ = $1; }
|
||||||
|
| SEMI { $$ = NULL; }
|
||||||
|
;
|
||||||
|
selection_stmt : IF LPAREN expression RPAREN statement %prec THEN {
|
||||||
|
$$ = newStmtNode(IfK);
|
||||||
|
$$->lineno = lineno;
|
||||||
|
$$->child[0] = $3;
|
||||||
|
$$->child[1] = $5;
|
||||||
|
} | IF LPAREN expression RPAREN statement ELSE statement {
|
||||||
|
$$ = newStmtNode(IfK);
|
||||||
|
$$->lineno = lineno;
|
||||||
|
$$->child[0] = $3;
|
||||||
|
$$->child[1] = $5;
|
||||||
|
$$->child[2] = $7;
|
||||||
|
};
|
||||||
|
|
||||||
|
iteration_stmt : WHILE LPAREN expression RPAREN statement {
|
||||||
|
$$ = newStmtNode(IterK);
|
||||||
|
$$->lineno = lineno;
|
||||||
|
$$->child[0] = $3;
|
||||||
|
$$->child[1] = $5;
|
||||||
|
};
|
||||||
|
|
||||||
|
return_stmt : RETURN SEMI {
|
||||||
|
$$ = newStmtNode(ReturnK);
|
||||||
|
$$->lineno = lineno;
|
||||||
|
} | RETURN expression SEMI {
|
||||||
|
$$ = newStmtNode(ReturnK);
|
||||||
|
$$->lineno = lineno;
|
||||||
|
$$->child[0] = $2;
|
||||||
|
};
|
||||||
|
|
||||||
|
expression : var ASSIGN expression {
|
||||||
|
$$ = newExpNode(AssignK);
|
||||||
|
$$->lineno = lineno;
|
||||||
|
$$->type = $3->type;
|
||||||
|
$$->child[0] = $1;
|
||||||
|
$$->child[1] = $3;
|
||||||
|
} | simple_expression { $$ = $1; };
|
||||||
|
|
||||||
|
var : name_specifier {
|
||||||
|
$$ = newExpNode(IdK);
|
||||||
|
$$->attr.name = savedName;
|
||||||
|
} | name_specifier {
|
||||||
|
$$ = newExpNode(ArrIdK);
|
||||||
|
$$->attr.name = savedName;
|
||||||
|
} LBRACE expression RBRACE {
|
||||||
|
$$ = $2;
|
||||||
|
$$->child[0] = $4;
|
||||||
|
};
|
||||||
|
|
||||||
|
simple_expression : additive_expression relop additive_expression {
|
||||||
|
$$ = $2;
|
||||||
|
$$->lineno = lineno;
|
||||||
|
$$->child[0] = $1;
|
||||||
|
$$->child[1] = $3;
|
||||||
|
$$->type = Integer;
|
||||||
|
} | additive_expression { $$ = $1; };
|
||||||
|
|
||||||
|
relop : LE {
|
||||||
|
$$ = newExpNode(OpK);
|
||||||
|
$$->attr.op = LE;
|
||||||
|
} | LT {
|
||||||
|
$$ = newExpNode(OpK);
|
||||||
|
$$->attr.op = LT;
|
||||||
|
} | GT {
|
||||||
|
$$ = newExpNode(OpK);
|
||||||
|
$$->attr.op = GT;
|
||||||
|
} | GE {
|
||||||
|
$$ = newExpNode(OpK);
|
||||||
|
$$->attr.op = GE;
|
||||||
|
} | EQ {
|
||||||
|
$$ = newExpNode(OpK);
|
||||||
|
$$->attr.op = EQ;
|
||||||
|
} | NE {
|
||||||
|
$$ = newExpNode(OpK);
|
||||||
|
$$->attr.op = NE;
|
||||||
|
};
|
||||||
|
|
||||||
|
additive_expression : additive_expression addop term {
|
||||||
|
$$ = $2;
|
||||||
|
$$->lineno = lineno;
|
||||||
|
$$->child[0] = $1;
|
||||||
|
$$->child[1] = $3;
|
||||||
|
} | term { $$ = $1; };
|
||||||
|
|
||||||
|
addop : PLUS {
|
||||||
|
$$ = newExpNode(OpK);
|
||||||
|
$$->attr.op = PLUS;
|
||||||
|
} | MINUS {
|
||||||
|
$$ = newExpNode(OpK);
|
||||||
|
$$->attr.op = MINUS;
|
||||||
|
};
|
||||||
|
|
||||||
|
term : term mulop factor {
|
||||||
|
$$ = $2;
|
||||||
|
$$->lineno = lineno;
|
||||||
|
$$->child[0] = $1;
|
||||||
|
$$->child[1] = $3;
|
||||||
|
} | factor { $$ = $1; };
|
||||||
|
|
||||||
|
mulop : TIMES {
|
||||||
|
$$ = newExpNode(OpK);
|
||||||
|
$$->attr.op = TIMES;
|
||||||
|
} | OVER {
|
||||||
|
$$ = newExpNode(OpK);
|
||||||
|
$$->attr.op = OVER;
|
||||||
|
};
|
||||||
|
|
||||||
|
factor : LPAREN expression RPAREN { $$ = $2; }
|
||||||
|
| var { $$ = $1; }
|
||||||
|
| call { $$ = $1; }
|
||||||
|
| NUM {
|
||||||
|
$$ = newExpNode(ConstK);
|
||||||
|
$$->lineno = lineno;
|
||||||
|
$$->type = Integer;
|
||||||
|
$$->attr.val = atoi(tokenString);
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
call : name_specifier {
|
||||||
|
$$ = newExpNode(CallK);
|
||||||
|
$$->lineno = lineno;
|
||||||
|
$$->attr.name = savedName;
|
||||||
|
} LPAREN args RPAREN {
|
||||||
|
$$ = $2;
|
||||||
|
$$->child[0] = $4;
|
||||||
|
};
|
||||||
|
|
||||||
|
args : arg_list { $$ = $1; } | { $$ = NULL; } ;
|
||||||
|
|
||||||
|
arg_list : arg_list COMMA expression {
|
||||||
|
YYSTYPE t = $1;
|
||||||
|
if (t != NULL) {
|
||||||
|
while (t->sibling != NULL)
|
||||||
|
t = t->sibling;
|
||||||
|
t->sibling = $3;
|
||||||
|
$$ = $1;
|
||||||
|
} else $$ = $3;
|
||||||
|
} | expression { $$ = $1; } ;
|
||||||
|
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
||||||
|
int yyerror(char * message)
|
||||||
|
{ fprintf(listing,"Syntax error at line %d: %s\n",lineno,message);
|
||||||
|
fprintf(listing,"Current token: ");
|
||||||
|
printToken(yychar,tokenString);
|
||||||
|
Error = TRUE;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* yylex calls getToken to make Yacc/Bison output
|
||||||
|
* compatible with ealier versions of the TINY scanner
|
||||||
|
*/
|
||||||
|
static int yylex(void)
|
||||||
|
{ return getToken(); }
|
||||||
|
|
||||||
|
TreeNode * parse(void)
|
||||||
|
{ yyparse();
|
||||||
|
return savedTree;
|
||||||
|
}
|
||||||
|
|
||||||
115
src/globals.h
115
src/globals.h
@@ -9,9 +9,9 @@
|
|||||||
#ifndef _GLOBALS_H_
|
#ifndef _GLOBALS_H_
|
||||||
#define _GLOBALS_H_
|
#define _GLOBALS_H_
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <ctype.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#ifndef FALSE
|
#ifndef FALSE
|
||||||
@@ -22,23 +22,56 @@
|
|||||||
#define TRUE 1
|
#define TRUE 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef YYPARSER
|
||||||
|
#include "y.tab.h"
|
||||||
|
#define ENDFILE 0
|
||||||
|
#endif
|
||||||
/* MAXRESERVED = the number of reserved words */
|
/* MAXRESERVED = the number of reserved words */
|
||||||
#define MAXRESERVED 6
|
#define MAXRESERVED 6
|
||||||
|
|
||||||
|
#if 0
|
||||||
typedef enum
|
typedef enum
|
||||||
/* book-keeping tokens */
|
/* book-keeping tokens */
|
||||||
{ENDFILE,ERROR,
|
{ ENDFILE,
|
||||||
/* reserved words */
|
ERROR,
|
||||||
IF,ELSE,WHILE,RETURN,INT,VOID,
|
/* reserved words */
|
||||||
/* multicharacter tokens */
|
IF,
|
||||||
ID,NUM,
|
ELSE,
|
||||||
/* special symbols */
|
WHILE,
|
||||||
ASSIGN,EQ,NE,LT,LE,GT,GE,PLUS,MINUS,TIMES,OVER,LPAREN,RPAREN,LBRACE,RBRACE,LCURLY,RCURLY,SEMI,COMMA
|
RETURN,
|
||||||
} TokenType;
|
INT,
|
||||||
|
VOID,
|
||||||
|
/* multicharacter tokens */
|
||||||
|
ID,
|
||||||
|
NUM,
|
||||||
|
/* special symbols */
|
||||||
|
ASSIGN,
|
||||||
|
EQ,
|
||||||
|
NE,
|
||||||
|
LT,
|
||||||
|
LE,
|
||||||
|
GT,
|
||||||
|
GE,
|
||||||
|
PLUS,
|
||||||
|
MINUS,
|
||||||
|
TIMES,
|
||||||
|
OVER,
|
||||||
|
LPAREN,
|
||||||
|
RPAREN,
|
||||||
|
LBRACE,
|
||||||
|
RBRACE,
|
||||||
|
LCURLY,
|
||||||
|
RCURLY,
|
||||||
|
SEMI,
|
||||||
|
COMMA
|
||||||
|
} TokenType;
|
||||||
|
#endif
|
||||||
|
|
||||||
extern FILE* source; /* source code text file */
|
typedef int TokenType;
|
||||||
extern FILE* listing; /* listing output text file */
|
|
||||||
extern FILE* code; /* code text file for TM simulator */
|
extern FILE *source; /* source code text file */
|
||||||
|
extern FILE *listing; /* listing output text file */
|
||||||
|
extern FILE *code; /* code text file for TM simulator */
|
||||||
|
|
||||||
extern int lineno; /* source line number for listing */
|
extern int lineno; /* source line number for listing */
|
||||||
|
|
||||||
@@ -46,26 +79,52 @@ extern int lineno; /* source line number for listing */
|
|||||||
/*********** Syntax tree for parsing ************/
|
/*********** Syntax tree for parsing ************/
|
||||||
/**************************************************/
|
/**************************************************/
|
||||||
|
|
||||||
typedef enum {StmtK,ExpK} NodeKind;
|
typedef enum { StmtK,
|
||||||
typedef enum {IfK,RepeatK,AssignK,ReadK,WriteK} StmtKind;
|
ExpK,
|
||||||
typedef enum {OpK,ConstK,IdK} ExpKind;
|
DeclK,
|
||||||
|
TypeK } NodeKind;
|
||||||
|
typedef enum { CompK,
|
||||||
|
IfK,
|
||||||
|
IterK, /* WhileK*/
|
||||||
|
ReturnK } StmtKind;
|
||||||
|
typedef enum { AssignK,
|
||||||
|
OpK,
|
||||||
|
ConstK,
|
||||||
|
IdK,
|
||||||
|
ArrIdK,
|
||||||
|
CallK } ExpKind;
|
||||||
|
typedef enum { FuncK,
|
||||||
|
VarK,
|
||||||
|
ArrVarK,
|
||||||
|
ArrParamK,
|
||||||
|
NonArrParamK } DeclKind;
|
||||||
|
typedef enum { TypeNameK } TypeKind;
|
||||||
|
|
||||||
/* ExpType is used for type checking */
|
/* ExpType is used for type checking */
|
||||||
typedef enum {Void,Integer,Boolean} ExpType;
|
typedef enum { Void,
|
||||||
|
Integer,
|
||||||
|
IntegerArray } ExpType;
|
||||||
|
|
||||||
#define MAXCHILDREN 3
|
#define MAXCHILDREN 3
|
||||||
|
|
||||||
typedef struct treeNode
|
typedef struct treeNode {
|
||||||
{ struct treeNode * child[MAXCHILDREN];
|
struct treeNode *child[MAXCHILDREN];
|
||||||
struct treeNode * sibling;
|
struct treeNode *sibling;
|
||||||
int lineno;
|
int lineno;
|
||||||
NodeKind nodekind;
|
NodeKind nodekind;
|
||||||
union { StmtKind stmt; ExpKind exp;} kind;
|
union {
|
||||||
union { TokenType op;
|
StmtKind stmt;
|
||||||
int val;
|
ExpKind exp;
|
||||||
char * name; } attr;
|
DeclKind decl;
|
||||||
ExpType type; /* for type checking of exps */
|
TypeKind type;
|
||||||
} TreeNode;
|
} kind;
|
||||||
|
union {
|
||||||
|
TokenType op;
|
||||||
|
int val;
|
||||||
|
char *name;
|
||||||
|
} attr;
|
||||||
|
ExpType type; /* for type checking of exps */
|
||||||
|
} TreeNode;
|
||||||
|
|
||||||
/**************************************************/
|
/**************************************************/
|
||||||
/*********** Flags for tracing ************/
|
/*********** Flags for tracing ************/
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
|
|
||||||
/* set NO_PARSE to TRUE to get a scanner-only compiler */
|
/* set NO_PARSE to TRUE to get a scanner-only compiler */
|
||||||
#define NO_PARSE TRUE
|
#define NO_PARSE FALSE
|
||||||
/* set NO_ANALYZE to TRUE to get a parser-only compiler */
|
/* set NO_ANALYZE to TRUE to get a parser-only compiler */
|
||||||
#define NO_ANALYZE TRUE
|
#define NO_ANALYZE TRUE
|
||||||
|
|
||||||
@@ -38,8 +38,8 @@ FILE *code;
|
|||||||
|
|
||||||
/* allocate and set tracing flags */
|
/* allocate and set tracing flags */
|
||||||
int EchoSource = FALSE;
|
int EchoSource = FALSE;
|
||||||
int TraceScan = TRUE;
|
int TraceScan = FALSE;
|
||||||
int TraceParse = FALSE;
|
int TraceParse = TRUE;
|
||||||
int TraceAnalyze = FALSE;
|
int TraceAnalyze = FALSE;
|
||||||
int TraceCode = FALSE;
|
int TraceCode = FALSE;
|
||||||
|
|
||||||
|
|||||||
@@ -1,73 +0,0 @@
|
|||||||
|
|
||||||
C-MINUS COMPILATION: ./test.1.txt
|
|
||||||
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
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
|
|
||||||
C-MINUS COMPILATION: ./test.2.txt
|
|
||||||
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
|
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
|
|
||||||
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
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
|
|
||||||
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
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
/*
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
dddd
|
|
||||||
16
src/test1.cm
16
src/test1.cm
@@ -1,16 +0,0 @@
|
|||||||
/* 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));
|
|
||||||
}
|
|
||||||
21
src/test2.cm
21
src/test2.cm
@@ -1,21 +0,0 @@
|
|||||||
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]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
116
src/util.c
116
src/util.c
@@ -137,6 +137,36 @@ TreeNode *newExpNode(ExpKind kind) {
|
|||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TreeNode *newDeclNode(DeclKind kind) {
|
||||||
|
TreeNode *t = (TreeNode *) malloc(sizeof(TreeNode));
|
||||||
|
int i;
|
||||||
|
if (t == NULL)
|
||||||
|
fprintf(listing, "Out of memory error at line %d\n", lineno);
|
||||||
|
else {
|
||||||
|
for (i = 0; i < MAXCHILDREN; i++) t->child[i] = NULL;
|
||||||
|
t->sibling = NULL;
|
||||||
|
t->nodekind = DeclK;
|
||||||
|
t->kind.decl = kind;
|
||||||
|
t->lineno = lineno;
|
||||||
|
}
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
TreeNode *newTypeNode(TypeKind kind) {
|
||||||
|
TreeNode *t = (TreeNode *) malloc(sizeof(TreeNode));
|
||||||
|
int i;
|
||||||
|
if (t == NULL)
|
||||||
|
fprintf(listing, "Out of memory error at line %d\n", lineno);
|
||||||
|
else {
|
||||||
|
for (i = 0; i < MAXCHILDREN; i++) t->child[i] = NULL;
|
||||||
|
t->sibling = NULL;
|
||||||
|
t->nodekind = TypeK;
|
||||||
|
t->kind.type = kind;
|
||||||
|
t->lineno = lineno;
|
||||||
|
}
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
/* Function copyString allocates and makes a new
|
/* Function copyString allocates and makes a new
|
||||||
* copy of an existing string
|
* copy of an existing string
|
||||||
*/
|
*/
|
||||||
@@ -169,6 +199,22 @@ static void printSpaces(void) {
|
|||||||
fprintf(listing, " ");
|
fprintf(listing, " ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void printType(TreeNode *tree) {
|
||||||
|
switch (tree->type) {
|
||||||
|
case Void:
|
||||||
|
fprintf(listing, "void");
|
||||||
|
break;
|
||||||
|
case Integer:
|
||||||
|
fprintf(listing, "int");
|
||||||
|
break;
|
||||||
|
case IntegerArray:
|
||||||
|
fprintf(listing, "int[]");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* procedure printTree prints a syntax tree to the
|
/* procedure printTree prints a syntax tree to the
|
||||||
* listing file using indentation to indicate subtrees
|
* listing file using indentation to indicate subtrees
|
||||||
*/
|
*/
|
||||||
@@ -179,27 +225,28 @@ void printTree(TreeNode *tree) {
|
|||||||
printSpaces();
|
printSpaces();
|
||||||
if (tree->nodekind == StmtK) {
|
if (tree->nodekind == StmtK) {
|
||||||
switch (tree->kind.stmt) {
|
switch (tree->kind.stmt) {
|
||||||
|
case CompK:
|
||||||
|
fprintf(listing, "Compound Statement:\n");
|
||||||
|
break;
|
||||||
case IfK:
|
case IfK:
|
||||||
fprintf(listing, "If\n");
|
fprintf(listing, "%s:\n",
|
||||||
|
(tree->child[2] != NULL) ? "If-Else Statement" : "If Statement");
|
||||||
break;
|
break;
|
||||||
case RepeatK:
|
case IterK:
|
||||||
fprintf(listing, "Repeat\n");
|
fprintf(listing, "While Statement:\n");
|
||||||
break;
|
break;
|
||||||
case AssignK:
|
case ReturnK:
|
||||||
fprintf(listing, "Assign to: %s\n", tree->attr.name);
|
fprintf(listing, "Return Statement:\n");
|
||||||
break;
|
|
||||||
case ReadK:
|
|
||||||
fprintf(listing, "Read: %s\n", tree->attr.name);
|
|
||||||
break;
|
|
||||||
case WriteK:
|
|
||||||
fprintf(listing, "Write\n");
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(listing, "Unknown ExpNode kind\n");
|
fprintf(listing, "Unknown StmtNode kind\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (tree->nodekind == ExpK) {
|
} else if (tree->nodekind == ExpK) {
|
||||||
switch (tree->kind.exp) {
|
switch (tree->kind.exp) {
|
||||||
|
case AssignK:
|
||||||
|
fprintf(listing, "Assign:\n");
|
||||||
|
break;
|
||||||
case OpK:
|
case OpK:
|
||||||
fprintf(listing, "Op: ");
|
fprintf(listing, "Op: ");
|
||||||
printToken(tree->attr.op, "\0");
|
printToken(tree->attr.op, "\0");
|
||||||
@@ -208,12 +255,55 @@ void printTree(TreeNode *tree) {
|
|||||||
fprintf(listing, "Const: %d\n", tree->attr.val);
|
fprintf(listing, "Const: %d\n", tree->attr.val);
|
||||||
break;
|
break;
|
||||||
case IdK:
|
case IdK:
|
||||||
fprintf(listing, "Id: %s\n", tree->attr.name);
|
fprintf(listing, "Variable: name = %s\n", tree->attr.name);
|
||||||
|
break;
|
||||||
|
case ArrIdK:
|
||||||
|
fprintf(listing, "Variable: name = %s\n", tree->attr.name);
|
||||||
|
break;
|
||||||
|
case CallK:
|
||||||
|
fprintf(listing, "Call: function name = %s\n", tree->attr.name);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(listing, "Unknown ExpNode kind\n");
|
fprintf(listing, "Unknown ExpNode kind\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
} else if (tree->nodekind == DeclK) {
|
||||||
|
switch (tree->kind.decl) {
|
||||||
|
case FuncK:
|
||||||
|
fprintf(listing, "Function Declaration: name = %s, return type = ", tree->attr.name);
|
||||||
|
printType(tree);
|
||||||
|
fprintf(listing, "\n");
|
||||||
|
break;
|
||||||
|
case VarK:
|
||||||
|
fprintf(listing, "Variable Declaration: name = %s, type = ", tree->attr.name);
|
||||||
|
printType(tree);
|
||||||
|
fprintf(listing, "\n");
|
||||||
|
break;
|
||||||
|
case ArrVarK:
|
||||||
|
fprintf(listing, "Variable Declaration: name = %s, type = ", tree->attr.name);
|
||||||
|
printType(tree);
|
||||||
|
fprintf(listing, "\n");
|
||||||
|
break;
|
||||||
|
case NonArrParamK:
|
||||||
|
if (tree->type == Void)
|
||||||
|
fprintf(listing, "Void Parameter\n");
|
||||||
|
else {
|
||||||
|
fprintf(listing, "Parameter: name = %s, type = ", tree->attr.name);
|
||||||
|
printType(tree);
|
||||||
|
fprintf(listing, "\n");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ArrParamK:
|
||||||
|
fprintf(listing, "Parameter: name = %s, type = ", tree->attr.name);
|
||||||
|
printType(tree);
|
||||||
|
fprintf(listing, "\n");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(listing, "Unknown DeclNode kind\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (tree->nodekind == TypeK) {
|
||||||
|
|
||||||
} else
|
} else
|
||||||
fprintf(listing, "Unknown node kind\n");
|
fprintf(listing, "Unknown node kind\n");
|
||||||
for (i = 0; i < MAXCHILDREN; i++)
|
for (i = 0; i < MAXCHILDREN; i++)
|
||||||
|
|||||||
@@ -25,6 +25,10 @@ TreeNode * newStmtNode(StmtKind);
|
|||||||
*/
|
*/
|
||||||
TreeNode * newExpNode(ExpKind);
|
TreeNode * newExpNode(ExpKind);
|
||||||
|
|
||||||
|
TreeNode* newDeclNode(DeclKind);
|
||||||
|
|
||||||
|
TreeNode* newTypeNode(TypeKind);
|
||||||
|
|
||||||
/* Function copyString allocates and makes a new
|
/* Function copyString allocates and makes a new
|
||||||
* copy of an existing string
|
* copy of an existing string
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user